pax_global_header00006660000000000000000000000064134033517510014514gustar00rootroot0000000000000052 comment=2e8d03015ac5f2c0467d42e55891ba7711159eca dpkt-1.9.2/000077500000000000000000000000001340335175100124675ustar00rootroot00000000000000dpkt-1.9.2/.coveralls.yml000066400000000000000000000000561340335175100152630ustar00rootroot00000000000000repo_token: D8kiOhp6QNkHx6D0A54t89ER98XWTTgT8 dpkt-1.9.2/.gitignore000066400000000000000000000004731340335175100144630ustar00rootroot00000000000000# Compiled/intermediate Python files *.py[cod] # C extensions *.so # Packages *.egg *.egg-info dist build sdist __pycache__ # Installer logs pip-log.txt # Unit test / coverage reports .coverage .tox .cache # iPython temp files .ipynb_checkpoints # Mac DS files .DS_Store # ReadTheDocs build directory _build dpkt-1.9.2/.landscape.yml000066400000000000000000000002251340335175100152210ustar00rootroot00000000000000doc-warnings: yes test-warnings: yes strictness: low max-line-length: 140 autodetect: yes ignore-paths: - docs pep8: disable: - E704 dpkt-1.9.2/.prospector.yaml000066400000000000000000000001261340335175100156300ustar00rootroot00000000000000pep8: disable: - E1101 - E1103 pylint: disable: - E1101 - E1103 dpkt-1.9.2/.travis.yml000066400000000000000000000010701340335175100145760ustar00rootroot00000000000000language: python matrix: global: LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so include: - python: "2.6" env: TOXENV=py26 - python: "2.7" env: TOXENV=py27 - python: "3.5" env: TOXENV=py35 - python: "3.6" env: TOXENV=py36,coveralls, docs - python: "pypy" env: TOXENV=pypy before_install: - python --version - virtualenv --version - pip --version - uname -a - lsb_release -a install: - pip install tox script: - tox -e $TOXENV notifications: email: on_success: never on_failure: always dpkt-1.9.2/AUTHORS000066400000000000000000000024251340335175100135420ustar00rootroot00000000000000 Original author --------------- Dug Song Contributors ------------ Timur Alperovich radiotap module Nic Bellamy HTTP header parsing fix the grugq better RTP module David Helder bug fixes Przemyslaw Karwasiecki TABLE_DUMP in MRT module Reza Lotun MetaPacket cleanup Jeff Nathan bug fixes Tim Newsham IPv6 bugfixing and improvements keisuke.nishimoto@gmail.com Snoop file parser Jon Oberheide STUN, H.225, TPKT, NTP, RIP, Diameter, SCTP, BGP, MRT, RX modules plotnikoff@gmail.com handle dynamic imports from py2exe/freeze.py/zipped egg packages simdream@gmail.com handle multiple cookie values in HTTP Owen Stephens IP6 extension header support Robert Stone Netflow and QQ modules Thomas Taranowski dnet IP checksum bug on i386 Jirka Vejrazka bug fixes Tim Yardley DHCP definitions obormot pcapng module, Packet repr improvements Kyle Keppler Python 3 port Hao Sun Python 3 port dpkt-1.9.2/CHANGES000066400000000000000000000044761340335175100134750ustar00rootroot00000000000000dpkt-1.9.0: - add support for Python 3.4, 3.5. Python 2.6 and 2.7 are still supported. dpkt-1.8: - fix a typo in vrrp.py - fix IPv4 and IPv6 packet to correctly handle zero payload length - store cipher_suite as int in TLSServerHello to allow app-specific messages - improve SSL parsing dpkt-1.7: - handle dynamic imports from py2exe/freeze.py/zipped egg packages, from plotnikoff - decode Ethernet MPLS labels, Cisco ISL VLAN tags, 802.2 LLC fields - handle multiply-defined HTTP headers from simdream - add IPv6 extension header support (minus ESP) from Owen Stephens - add radiotap module from Timur Alperovich - add IEEE80211 module from Jon Oberheide - add RFB module from Jon Oberheide - fix IP6 checksum to include options - rename 'as' to 'asn' field in BGP header - fix transport-layer checksum in IP6 - handle improper TCP header offset - fix SSL typo - handle malformed ICMP headers - added RX module from Jon Oberheide - fixed loopback module IP/IP6 decoding - set transport-layer (TCP, UDP) checksum in IP - MRT module fixes - fix pcap.Writer timestamp calculation dpkt-1.6: - DNS RR packing fixed - added STUN, H.225, TPKT, NTP, RIP, Diameter, SCTP, BGP, and MRT modules from Jon Oberheide - new dpkt.NeedData exception dpkt-1.5: - IP6 checksum fix - __getitem__() interface to Packet (e.g. ip['src'] == ip.src) - faster Ethernet, IP, PPP module loading - support any endianness capture file in pcap module, and export a pypcap-compatible Reader - additional CDP definitions - replaced rtp module with the grugq's version - added QQ module from Robert Stone - added gzip module - added PPPoE module - added RADIUS module dpkt-1.4: - fix IP checksum bug on i386, caught by Thomas Taranowski dpkt-1.3: - autoload IP, Ethernet dispatch tables - IP6 bugfixes from Tim Newsham - additional DHCP definitions from Tim Yardley - HTTP bugfixes and abstraction (see SIP) - RPC bugfixes - added pypcap-compatible PcapReader - added Linux libpcap "cooked" capture module - added preliminary SSL module - added SIP module - added SCCP module - added RTP module - added Portmap module dpkt-1.2: - changed license from GPL to BSD - added DTP module - added HTTP module - added DNS RR decodes - added enough PPP to decode PPTP GRE encapsulation # $Id: CHANGES 379 2006-07-27 05:23:19Z dugsong $ dpkt-1.9.2/LICENSE000066400000000000000000000027251340335175100135020ustar00rootroot00000000000000 Copyright (c) 2004 Dug Song All rights reserved, all wrongs reversed. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The names of the authors and copyright holders may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. dpkt-1.9.2/MANIFEST.in000066400000000000000000000001661340335175100142300ustar00rootroot00000000000000 include AUTHORS CHANGES README.rst LICENSE recursive-include docs * prune docs/_build global-exclude __pycache__/* dpkt-1.9.2/Makefile000066400000000000000000000007221340335175100141300ustar00rootroot00000000000000 help: @echo "clean - remove all build/python artifacts" @echo "clean-build - remove build artifacts" @echo "clean-pyc - remove Python file artifacts" clean: clean-build clean-pyc clean-build: rm -fr build/ rm -fr dist/ rm -fr deb_dist/ rm -fr *.egg-info rm -fr *.tar.gz rm -fr .tox find . -name '__pycache__' -exec rm -fr {} + clean-pyc: find . -name '*.pyc' -exec rm -f {} + find . -name '*.pyo' -exec rm -f {} + find . -name '*~' -exec rm -f {} + dpkt-1.9.2/README.rst000066400000000000000000000042071340335175100141610ustar00rootroot00000000000000 ==== dpkt ==== | |travis| |coveralls| |landscape| |version| | |wheel| |supported-versions| |supported-implementations| .. |travis| image:: http://img.shields.io/travis/kbandla/dpkt.svg :alt: Travis-CI Build Status :target: https://travis-ci.org/kbandla/dpkt .. |coveralls| image:: http://img.shields.io/coveralls/kbandla/dpkt.svg :alt: Coverage Status :target: https://coveralls.io/r/kbandla/dpkt .. |landscape| image:: https://landscape.io/github/kbandla/dpkt/master/landscape.svg :target: https://landscape.io/github/kbandla/dpkt/master :alt: Code Quality Status .. |version| image:: http://img.shields.io/pypi/v/dpkt.svg :alt: PyPI Package latest release :target: https://pypi.python.org/pypi/dpkt .. |wheel| image:: https://img.shields.io/pypi/wheel/dpkt.svg :alt: PyPI Wheel :target: https://pypi.python.org/pypi/dpkt .. |supported-versions| image:: https://img.shields.io/pypi/pyversions/dpkt.svg :alt: Supported versions :target: https://pypi.python.org/pypi/dpkt .. |supported-implementations| image:: https://img.shields.io/pypi/implementation/dpkt.svg :alt: Supported implementations :target: https://pypi.python.org/pypi/dpkt Installation ============ :: pip install dpkt Documentation ============= https://dpkt.readthedocs.org/ Recent News =========== The DPKT code base now supports both Python2 and Python3 thanks to the efforts of @kylekeppler @jonathanslenders @sunhao2014 and many `more `__. Given the large amount of work that went into the Python3 support there's bound to be a few wrinkles that crop up. - Please submit an Issue if you find a problem - The legacy/stable release is dpkt==1.8.8 (https://github.com/kbandla/dpkt/releases), please use this release if you have any troubles. About ===== This code is based on `dpkt code `__ lead by Dug Song and is now being maintained and improved by an extended set of `contributors `__ and `developers `__. LICENSE ------- BSD 3-Clause dpkt-1.9.2/docs/000077500000000000000000000000001340335175100134175ustar00rootroot00000000000000dpkt-1.9.2/docs/Makefile000066400000000000000000000127101340335175100150600ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pyspotify.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pyspotify.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/pyspotify" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pyspotify" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." dpkt-1.9.2/docs/admin_notes.rst000066400000000000000000000046401340335175100164550ustar00rootroot00000000000000 Notes ====== PyPI Release How-To ------------------- Notes and information on how to do the PyPI release for the dpkt project. For full details on packaging you can reference this page Packaging_ .. _Packaging: https://packaging.python.org/tutorials/packaging-projects/#packaging-your-project The following instructions should work, but things change :) Package Requirements ~~~~~~~~~~~~~~~~~~~~ - pip install tox - pip install --upgrade setuptools wheel - pip install twine Setup pypirc ~~~~~~~~~~~~ The easiest thing to do is setup a ~/.pypirc file with the following contents .. code-block:: bash [distutils] index-servers = pypi testpypi [pypi] repository=https://upload.pypi.org/legacy/ username= password= [testpypi] repository=https://test.pypi.org/legacy/ username= password= Tox Background ~~~~~~~~~~~~~~ Tox will install the dpkt package into a blank virtualenv and then execute all the tests against the newly installed package. So if everything goes okay, you know the pypi package installed fine and the tests (which pull from the installed dpkt package) also ran okay. Make sure ALL tests pass ~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash $ cd dpkt $ tox If ALL the test above pass... Create the TEST PyPI Release ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash $ vi dpkt/__init__.py and bump the version $ python setup.py sdist bdist_wheel $ twine upload dist/* -r testpypi Install the TEST PyPI Release ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash $ pip install --index-url https://test.pypi.org/simple dpkt Create the REAL PyPI Release ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash $ twine upload dist/* -r pypi Push changes to Github ~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash $ git add dpkt/__init__.py $ get commit -m "dpkt version 1.8.7 (or whatever)" $ git tag v1.8.7 (or whatever) $ git push --tags $ git push Git Releases (discussion) ~~~~~~~~~~~~~~~~~~~~~~~~~ Note: This is an opinion, we/I could certainly be convinced otherwise. You can also do a 'release' on GitHub (the tags above are perfect for that). In general this is discouraged, people should always do a $pip install dpkt. If people want older releases they can do a $pip install dpkt==. Providing tarballs/zip file on GitHub will just confuse new users and they'll have a 'bad experience' when trying to deal with a tarball. dpkt-1.9.2/docs/api/000077500000000000000000000000001340335175100141705ustar00rootroot00000000000000dpkt-1.9.2/docs/api/api_auto.rst000066400000000000000000000177421340335175100165360ustar00rootroot00000000000000 dpkt.ah module -------------- .. automodule:: dpkt.ah :members: :undoc-members: :show-inheritance: dpkt.aim module --------------- .. automodule:: dpkt.aim :members: :undoc-members: :show-inheritance: dpkt.aoe module --------------- .. automodule:: dpkt.aoe :members: :undoc-members: :show-inheritance: dpkt.aoeata module ------------------ .. automodule:: dpkt.aoeata :members: :undoc-members: :show-inheritance: dpkt.aoecfg module ------------------ .. automodule:: dpkt.aoecfg :members: :undoc-members: :show-inheritance: dpkt.arp module --------------- .. automodule:: dpkt.arp :members: :undoc-members: :show-inheritance: dpkt.asn1 module ---------------- .. automodule:: dpkt.asn1 :members: :undoc-members: :show-inheritance: dpkt.bgp module --------------- .. automodule:: dpkt.bgp :members: :undoc-members: :show-inheritance: dpkt.cdp module --------------- .. automodule:: dpkt.cdp :members: :undoc-members: :show-inheritance: dpkt.crc32c module ------------------ .. automodule:: dpkt.crc32c :members: :undoc-members: :show-inheritance: dpkt.decorators module ---------------------- .. automodule:: dpkt.decorators :members: :undoc-members: :show-inheritance: dpkt.dhcp module ---------------- .. automodule:: dpkt.dhcp :members: :undoc-members: :show-inheritance: dpkt.diameter module -------------------- .. automodule:: dpkt.diameter :members: :undoc-members: :show-inheritance: dpkt.dns module --------------- .. automodule:: dpkt.dns :members: :undoc-members: :show-inheritance: dpkt.dpkt module ---------------- .. automodule:: dpkt.dpkt :members: :undoc-members: :show-inheritance: dpkt.dtp module --------------- .. automodule:: dpkt.dtp :members: :undoc-members: :show-inheritance: dpkt.esp module --------------- .. automodule:: dpkt.esp :members: :undoc-members: :show-inheritance: dpkt.ethernet module -------------------- .. automodule:: dpkt.ethernet :members: :undoc-members: :show-inheritance: dpkt.gre module --------------- .. automodule:: dpkt.gre :members: :undoc-members: :show-inheritance: dpkt.gzip module ---------------- .. automodule:: dpkt.gzip :members: :undoc-members: :show-inheritance: dpkt.h225 module ---------------- .. automodule:: dpkt.h225 :members: :undoc-members: :show-inheritance: dpkt.hsrp module ---------------- .. automodule:: dpkt.hsrp :members: :undoc-members: :show-inheritance: dpkt.http module ---------------- .. automodule:: dpkt.http :members: :undoc-members: :show-inheritance: dpkt.icmp module ---------------- .. automodule:: dpkt.icmp :members: :undoc-members: :show-inheritance: dpkt.icmp6 module ----------------- .. automodule:: dpkt.icmp6 :members: :undoc-members: :show-inheritance: dpkt.ieee80211 module --------------------- .. automodule:: dpkt.ieee80211 :members: :undoc-members: :show-inheritance: dpkt.igmp module ---------------- .. automodule:: dpkt.igmp :members: :undoc-members: :show-inheritance: dpkt.ip module -------------- .. automodule:: dpkt.ip :members: :undoc-members: :show-inheritance: dpkt.ip6 module --------------- .. automodule:: dpkt.ip6 :members: :undoc-members: :show-inheritance: dpkt.ipx module --------------- .. automodule:: dpkt.ipx :members: :undoc-members: :show-inheritance: dpkt.llc module --------------- .. automodule:: dpkt.llc :members: :undoc-members: :show-inheritance: dpkt.loopback module -------------------- .. automodule:: dpkt.loopback :members: :undoc-members: :show-inheritance: dpkt.mrt module --------------- .. automodule:: dpkt.mrt :members: :undoc-members: :show-inheritance: dpkt.netbios module ------------------- .. automodule:: dpkt.netbios :members: :undoc-members: :show-inheritance: dpkt.netflow module ------------------- .. automodule:: dpkt.netflow :members: :undoc-members: :show-inheritance: dpkt.ntp module --------------- .. automodule:: dpkt.ntp :members: :undoc-members: :show-inheritance: dpkt.ospf module ---------------- .. automodule:: dpkt.ospf :members: :undoc-members: :show-inheritance: dpkt.pcap module ---------------- .. automodule:: dpkt.pcap :members: :undoc-members: :show-inheritance: dpkt.pim module --------------- .. automodule:: dpkt.pim :members: :undoc-members: :show-inheritance: dpkt.pmap module ---------------- .. automodule:: dpkt.pmap :members: :undoc-members: :show-inheritance: dpkt.ppp module --------------- .. automodule:: dpkt.ppp :members: :undoc-members: :show-inheritance: dpkt.pppoe module ----------------- .. automodule:: dpkt.pppoe :members: :undoc-members: :show-inheritance: dpkt.qq module -------------- .. automodule:: dpkt.qq :members: :undoc-members: :show-inheritance: dpkt.radiotap module -------------------- .. automodule:: dpkt.radiotap :members: :undoc-members: :show-inheritance: dpkt.radius module ------------------ .. automodule:: dpkt.radius :members: :undoc-members: :show-inheritance: dpkt.rfb module --------------- .. automodule:: dpkt.rfb :members: :undoc-members: :show-inheritance: dpkt.rip module --------------- .. automodule:: dpkt.rip :members: :undoc-members: :show-inheritance: dpkt.rpc module --------------- .. automodule:: dpkt.rpc :members: :undoc-members: :show-inheritance: dpkt.rtp module --------------- .. automodule:: dpkt.rtp :members: :undoc-members: :show-inheritance: dpkt.rx module -------------- .. automodule:: dpkt.rx :members: :undoc-members: :show-inheritance: dpkt.sccp module ---------------- .. automodule:: dpkt.sccp :members: :undoc-members: :show-inheritance: dpkt.sctp module ---------------- .. automodule:: dpkt.sctp :members: :undoc-members: :show-inheritance: dpkt.sip module --------------- .. automodule:: dpkt.sip :members: :undoc-members: :show-inheritance: dpkt.sll module --------------- .. automodule:: dpkt.sll :members: :undoc-members: :show-inheritance: dpkt.smb module --------------- .. automodule:: dpkt.smb :members: :undoc-members: :show-inheritance: dpkt.snoop module ----------------- .. automodule:: dpkt.snoop :members: :undoc-members: :show-inheritance: dpkt.ssl module --------------- .. automodule:: dpkt.ssl :members: :undoc-members: :show-inheritance: dpkt.ssl_ciphersuites module ---------------------------- .. automodule:: dpkt.ssl_ciphersuites :members: :undoc-members: :show-inheritance: dpkt.stp module --------------- .. automodule:: dpkt.stp :members: :undoc-members: :show-inheritance: dpkt.stun module ---------------- .. automodule:: dpkt.stun :members: :undoc-members: :show-inheritance: dpkt.tcp module --------------- .. automodule:: dpkt.tcp :members: :undoc-members: :show-inheritance: dpkt.telnet module ------------------ .. automodule:: dpkt.telnet :members: :undoc-members: :show-inheritance: dpkt.tftp module ---------------- .. automodule:: dpkt.tftp :members: :undoc-members: :show-inheritance: dpkt.tns module --------------- .. automodule:: dpkt.tns :members: :undoc-members: :show-inheritance: dpkt.tpkt module ---------------- .. automodule:: dpkt.tpkt :members: :undoc-members: :show-inheritance: dpkt.udp module --------------- .. automodule:: dpkt.udp :members: :undoc-members: :show-inheritance: dpkt.vrrp module ---------------- .. automodule:: dpkt.vrrp :members: :undoc-members: :show-inheritance: dpkt.yahoo module ----------------- .. automodule:: dpkt.yahoo :members: :undoc-members: :show-inheritance: dpkt-1.9.2/docs/api/index.rst000066400000000000000000000003361340335175100160330ustar00rootroot00000000000000 API Reference ============= The dpkt API reference section is currently a work in progress, please have patience as we fill in and improve the documentation. **dpkt Modules** .. toctree:: :maxdepth: 4 api_auto dpkt-1.9.2/docs/authors.rst000066400000000000000000000001561340335175100156400ustar00rootroot00000000000000******* Authors ******* .. include:: ../AUTHORS If you want to contribute to dpkt, see :doc:`contributing`. dpkt-1.9.2/docs/badges.rst000066400000000000000000000025061340335175100154010ustar00rootroot00000000000000| |travis| |coveralls| |landscape| |downloads| | |version| |wheel| |supported-versions| |supported-implementations| .. |travis| image:: http://img.shields.io/travis/kbandla/dpkt.svg :alt: Travis-CI Build Status :target: https://travis-ci.org/kbandla/dpkt .. |coveralls| image:: http://img.shields.io/coveralls/kbandla/dpkt.svg :alt: Coverage Status :target: https://coveralls.io/r/kbandla/dpkt .. |landscape| image:: https://landscape.io/github/kbandla/dpkt/master/landscape.svg :target: https://landscape.io/github/kbandla/dpkt/master :alt: Code Quality Status .. |version| image:: http://img.shields.io/pypi/v/dpkt.svg :alt: PyPI Package latest release :target: https://pypi.python.org/pypi/dpkt .. |downloads| image:: http://img.shields.io/pypi/dm/dpkt.svg :alt: PyPI Package monthly downloads :target: https://pypi.python.org/pypi/dpkt .. |wheel| image:: https://img.shields.io/pypi/wheel/dpkt.svg :alt: PyPI Wheel :target: https://pypi.python.org/pypi/dpkt .. |supported-versions| image:: https://img.shields.io/pypi/pyversions/dpkt.svg :alt: Supported versions :target: https://pypi.python.org/pypi/dpkt .. |supported-implementations| image:: https://img.shields.io/pypi/implementation/dpkt.svg :alt: Supported implementations :target: https://pypi.python.org/pypi/dpktdpkt-1.9.2/docs/changelog.rst000066400000000000000000000000371340335175100161000ustar00rootroot00000000000000********* Changelog ********* dpkt-1.9.2/docs/conf.py000066400000000000000000000032701340335175100147200ustar00rootroot00000000000000# encoding: utf-8 """dpkt documentation build configuration file""" from __future__ import unicode_literals import os import re import sys import types import mock def get_version(filename): init_py = open(filename).read() metadata = dict(re.findall("__([a-z]+)__ = '([^']+)'", init_py)) return metadata['version'] # -- Workarounds to have autodoc generate API docs ---------------------------- sys.path.insert(0, os.path.abspath('..')) # Mock any objects that we might need to foo = mock.Mock() foo.__version__ = '0.1.1' sys.modules['foo'] = foo # -- General configuration ---------------------------------------------------- needs_sphinx = '1.0' extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.extlinks', 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode', 'sphinx.ext.autosummary', 'sphinxcontrib.napoleon' ] templates_path = ['_templates'] source_suffix = '.rst' master_doc = 'index' project = 'dpkt' copyright = '2009-2015 Dug Song and contributors' release = get_version('../dpkt/__init__.py') version = '.'.join(release.split('.')[:2]) exclude_patterns = ['_build'] pygments_style = 'sphinx' modindex_common_prefix = ['dpkt.'] autodoc_default_flags = ['members', 'undoc-members', 'show-inheritance'] autodoc_member_order = 'bysource' # -- Options for HTML output -------------------------------------------------- html_theme = 'default' html_static_path = ['_static'] html_use_modindex = True html_use_index = True html_split_index = False html_show_sourcelink = True htmlhelp_basename = 'dpkt' # -- Options for extlink extension -------------------------------------------- extlinks = { 'issue': ('https://github.com/kbandla/dpkt/issues/%s', '#'), } dpkt-1.9.2/docs/contributing.rst000066400000000000000000000022411340335175100166570ustar00rootroot00000000000000============ Contributing ============ Report a Bug or Make a Feature Request -------------------------------------- Please go to the GitHub Issues page: https://github.com/kbandla/dpkt/issues. Checkout the Code ----------------- :: git clone https://github.com/kblandla/dpkt.git Become a Developer ------------------ dpkt uses the 'GitHub Flow' model: `GitHub Flow `_ - To work on something new, create a descriptively named branch off of master (ie: my-awesome) - Commit to that branch locally and regularly push your work to the same named branch on the server - When you need feedback or help, or you think the branch is ready for merging, open a pull request - After someone else has reviewed and signed off on the feature, they or you can merge it into master New Feature or Bug ~~~~~~~~~~~~~~~~~~ :: $ git checkout -b my-awesome $ git push -u origin my-awesome $ ; git push $ ; git push $ tox (this will run all the tests) - Go to github and hit 'New pull request' - Someone reviews it and says 'AOK' - Merge the pull request (green button) dpkt-1.9.2/docs/examples.rst000066400000000000000000000017621340335175100157750ustar00rootroot00000000000000 Examples ======== Examples in dpkt/examples ------------------------- .. toctree:: :maxdepth: 2 print_packets print_icmp print_http_requests Jon Oberheide's Examples ------------------------- [@jonoberheide's](https://twitter.com/jonoberheide) old examples still apply: - `dpkt Tutorial #1: ICMP Echo `__ - `dpkt Tutorial #2: Parsing a PCAP File `__ - `dpkt Tutorial #3: dns spoofing `__ - `dpkt Tutorial #4: AS Paths from MRT/BGP `__ Jeff Silverman Docs/Code ------------------------ `Jeff Silverman `__ has some `code `__ and `documentation `__. dpkt-1.9.2/docs/index.rst000066400000000000000000000010061340335175100152550ustar00rootroot00000000000000dpkt ==== .. include:: badges.rst dpkt is a python module for fast, simple packet creation / parsing, with definitions for the basic TCP/IP protocols Getting Started =============== .. toctree:: :maxdepth: 2 installation examples API Reference ============= .. toctree:: :maxdepth: 1 api/index About dpkt ========== .. toctree:: :maxdepth: 2 authors changelog plans contributing license Administration =============== .. toctree:: :maxdepth: 2 admin_notes dpkt-1.9.2/docs/installation.rst000066400000000000000000000003571340335175100166570ustar00rootroot00000000000000============ Installation ============ DKPT is now available directly from pypi :) Install the Code ---------------- :: pip install dpkt Checkout the Code ----------------- :: git clone https://github.com/kbandla/dpkt.git dpkt-1.9.2/docs/license.rst000066400000000000000000000000771340335175100155770ustar00rootroot00000000000000 License ======= BSD 3-Clause License, as the upstream project dpkt-1.9.2/docs/plans.rst000066400000000000000000000002241340335175100152640ustar00rootroot00000000000000***************** Development plans ***************** Current plans ============= - Be Awesome Future plans ============ - Maintain the Awesome dpkt-1.9.2/docs/print_http_requests.rst000066400000000000000000000101251340335175100202760ustar00rootroot00000000000000 Print HTTP Requests Example =========================== This example expands on the print_packets example. It checks for HTTP request headers and displays their contents. **NOTE:** We are not reconstructing 'flows' so the request (and response if you tried to parse it) will only parse correctly if they fit within a single packet. Requests can often fit in a single packet but Responses almost never will. For proper reconstruction of flows you may want to look at other projects that use DPKT (http://chains.readthedocs.io and others) **Code Excerpt** .. code-block:: python # For each packet in the pcap process the contents for timestamp, buf in pcap: # Unpack the Ethernet frame (mac src/dst, ethertype) eth = dpkt.ethernet.Ethernet(buf) # Make sure the Ethernet data contains an IP packet if not isinstance(eth.data, dpkt.ip.IP): print 'Non IP Packet type not supported %s\n' % eth.data.__class__.__name__ continue # Now grab the data within the Ethernet frame (the IP packet) ip = eth.data # Check for TCP in the transport layer if isinstance(ip.data, dpkt.tcp.TCP): # Set the TCP data tcp = ip.data # Now see if we can parse the contents as a HTTP request try: request = dpkt.http.Request(tcp.data) except (dpkt.dpkt.NeedData, dpkt.dpkt.UnpackError): continue # Pull out fragment information (flags and offset all packed into off field, so use bitmasks) do_not_fragment = bool(ip.off & dpkt.ip.IP_DF) more_fragments = bool(ip.off & dpkt.ip.IP_MF) fragment_offset = ip.off & dpkt.ip.IP_OFFMASK # Print out the info print 'Timestamp: ', str(datetime.datetime.utcfromtimestamp(timestamp)) print 'Ethernet Frame: ', mac_addr(eth.src), mac_addr(eth.dst), eth.type print 'IP: %s -> %s (len=%d ttl=%d DF=%d MF=%d offset=%d)' % \ (inet_to_str(ip.src), inet_to_str(ip.dst), ip.len, ip.ttl, do_not_fragment, more_fragments, fragment_offset) print 'HTTP request: %s\n' % repr(request) **Example Output** .. code-block:: json Timestamp: 2004-05-13 10:17:08.222534 Ethernet Frame: 00:00:01:00:00:00 fe:ff:20:00:01:00 2048 IP: 145.254.160.237 -> 65.208.228.223 (len=519 ttl=128 DF=1 MF=0 offset=0) HTTP request: Request(body='', uri='/download.html', headers={'accept-language': 'en-us,en;q=0.5', 'accept-encoding': 'gzip,deflate', 'connection': 'keep-alive', 'keep-alive': '300', 'accept': 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1', 'user-agent': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113', 'accept-charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'host': 'www.ethereal.com', 'referer': 'http://www.ethereal.com/development.html'}, version='1.1', data='', method='GET') Timestamp: 2004-05-13 10:17:10.295515 Ethernet Frame: 00:00:01:00:00:00 fe:ff:20:00:01:00 2048 IP: 145.254.160.237 -> 216.239.59.99 (len=761 ttl=128 DF=1 MF=0 offset=0) HTTP request: Request(body='', uri='/pagead/ads?client=ca-pub-2309191948673629&random=1084443430285&lmt=1082467020&format=468x60_as&output=html&url=http%3A%2F%2Fwww.ethereal.com%2Fdownload.html&color_bg=FFFFFF&color_text=333333&color_link=000000&color_url=666633&color_border=666633', headers={'accept-language': 'en-us,en;q=0.5', 'accept-encoding': 'gzip,deflate', 'connection': 'keep-alive', 'keep-alive': '300', 'accept': 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1', 'user-agent': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113', 'accept-charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'host': 'pagead2.googlesyndication.com', 'referer': 'http://www.ethereal.com/download.html'}, version='1.1', data='', method='GET') ... **dpkt/examples/print_http_requests.py** .. automodule:: examples.print_http_requests dpkt-1.9.2/docs/print_icmp.rst000066400000000000000000000047371340335175100163300ustar00rootroot00000000000000 Print ICMP Example ================== This example expands on the print_packets example. It checks for ICMP packets and displays the ICMP contents. **Code Excerpt** .. code-block:: python # For each packet in the pcap process the contents for timestamp, buf in pcap: # Unpack the Ethernet frame (mac src/dst, ethertype) eth = dpkt.ethernet.Ethernet(buf) # Make sure the Ethernet data contains an IP packet if not isinstance(eth.data, dpkt.ip.IP): print 'Non IP Packet type not supported %s\n' % eth.data.__class__.__name__ continue # Now grab the data within the Ethernet frame (the IP packet) ip = eth.data # Now check if this is an ICMP packet if isinstance(ip.data, dpkt.icmp.ICMP): icmp = ip.data # Pull out fragment information (flags and offset all packed into off field, so use bitmasks) do_not_fragment = bool(ip.off & dpkt.ip.IP_DF) more_fragments = bool(ip.off & dpkt.ip.IP_MF) fragment_offset = ip.off & dpkt.ip.IP_OFFMASK # Print out the info print 'Timestamp: ', str(datetime.datetime.utcfromtimestamp(timestamp)) print 'Ethernet Frame: ', mac_addr(eth.src), mac_addr(eth.dst), eth.type print 'IP: %s -> %s (len=%d ttl=%d DF=%d MF=%d offset=%d)' % \ (inet_to_str(ip.src), inet_to_str(ip.dst), ip.len, ip.ttl, do_not_fragment, more_fragments, fragment_offset) print 'ICMP: type:%d code:%d checksum:%d data: %s\n' % (icmp.type, icmp.code, icmp.sum, repr(icmp.data)) **Example Output** .. code-block:: json Timestamp: 2013-05-30 22:45:17.283187 Ethernet Frame: 60:33:4b:13:c5:58 02:1a:11:f0:c8:3b 2048 IP: 192.168.43.9 -> 8.8.8.8 (len=84 ttl=64 DF=0 MF=0 offset=0) ICMP: type:8 code:0 checksum:48051 data: Echo(id=55099, data='Q\xa7\xd6}\x00\x04Q\xe4\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567') Timestamp: 2013-05-30 22:45:17.775391 Ethernet Frame: 02:1a:11:f0:c8:3b 60:33:4b:13:c5:58 2048 IP: 8.8.8.8 -> 192.168.43.9 (len=84 ttl=40 DF=0 MF=0 offset=0) ICMP: type:0 code:0 checksum:50099 data: Echo(id=55099, data='Q\xa7\xd6}\x00\x04Q\xe4\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567') ... **dpkt/examples/print_icmp.py** .. automodule:: examples.print_icmp dpkt-1.9.2/docs/print_packets.rst000066400000000000000000000040041340335175100170150ustar00rootroot00000000000000 Print Packets Example ===================== This example uses DPKT to read in a pcap file and print out the contents of the packets This example is focused on the fields in the Ethernet Frame and IP packet **Code Excerpt** .. code-block:: python # For each packet in the pcap process the contents for timestamp, buf in pcap: # Print out the timestamp in UTC print 'Timestamp: ', str(datetime.datetime.utcfromtimestamp(timestamp)) # Unpack the Ethernet frame (mac src/dst, ethertype) eth = dpkt.ethernet.Ethernet(buf) print 'Ethernet Frame: ', mac_addr(eth.src), mac_addr(eth.dst), eth.type # Make sure the Ethernet frame contains an IP packet if not isinstance(eth.data, dpkt.ip.IP): print 'Non IP Packet type not supported %s\n' % eth.data.__class__.__name__ continue # Now unpack the data within the Ethernet frame (the IP packet) # Pulling out src, dst, length, fragment info, TTL, and Protocol ip = eth.data # Pull out fragment information (flags and offset all packed into off field, so use bitmasks) do_not_fragment = bool(ip.off & dpkt.ip.IP_DF) more_fragments = bool(ip.off & dpkt.ip.IP_MF) fragment_offset = ip.off & dpkt.ip.IP_OFFMASK # Print out the info print 'IP: %s -> %s (len=%d ttl=%d DF=%d MF=%d offset=%d)\n' % \ (inet_to_str(ip.src), inet_to_str(ip.dst), ip.len, ip.ttl, do_not_fragment, more_fragments, fragment_offset) **Example Output** .. code-block:: json Timestamp: 2004-05-13 10:17:07.311224 Ethernet Frame: 00:00:01:00:00:00 fe:ff:20:00:01:00 2048 IP: 145.254.160.237 -> 65.208.228.223 (len=48 ttl=128 DF=1 MF=0 offset=0) Timestamp: 2004-05-13 10:17:08.222534 Ethernet Frame: fe:ff:20:00:01:00 00:00:01:00:00:00 2048 IP: 65.208.228.223 -> 145.254.160.237 (len=48 ttl=47 DF=1 MF=0 offset=0) ... **dpkt/examples/print_packets.py** .. automodule:: examples.print_packets dpkt-1.9.2/docs/requirements.txt000066400000000000000000000000611340335175100167000ustar00rootroot00000000000000mock >= 1.0 Sphinx >= 1.0 sphinxcontrib-napoleon dpkt-1.9.2/dpkt/000077500000000000000000000000001340335175100134315ustar00rootroot00000000000000dpkt-1.9.2/dpkt/__init__.py000066400000000000000000000034531340335175100155470ustar00rootroot00000000000000"""fast, simple packet creation and parsing.""" from __future__ import absolute_import from __future__ import division import sys __author__ = 'Dug Song' __author_email__ = 'dugsong@monkey.org' __license__ = 'BSD' __url__ = 'http://dpkt.googlecode.com/' __version__ = '1.9.2' from .dpkt import * from . import ah from . import aoe from . import aim from . import arp from . import asn1 from . import bgp from . import cdp from . import dhcp from . import diameter from . import dns from . import dtp from . import esp from . import ethernet from . import gre from . import gzip from . import h225 from . import hsrp from . import http from . import http2 from . import icmp from . import icmp6 from . import ieee80211 from . import igmp from . import ip from . import ip6 from . import ipx from . import llc from . import loopback from . import mrt from . import netbios from . import netflow from . import ntp from . import ospf from . import pcap from . import pcapng from . import pim from . import pmap from . import ppp from . import pppoe from . import qq from . import radiotap from . import radius from . import rfb from . import rip from . import rpc from . import rtp from . import rx from . import sccp from . import sctp from . import sip from . import sll from . import smb from . import ssl from . import stp from . import stun from . import tcp from . import telnet from . import tftp from . import tns from . import tpkt from . import udp from . import vrrp from . import yahoo # Note: list() is used to get a copy of the dict in order to avoid # "RuntimeError: dictionary changed size during iteration" # exception in Python 3 caused by _mod_init() funcs that load another modules for name, mod in list(sys.modules.items()): if name.startswith('dpkt.') and hasattr(mod, '_mod_init'): mod._mod_init() dpkt-1.9.2/dpkt/ah.py000066400000000000000000000021531340335175100143740ustar00rootroot00000000000000# $Id: ah.py 34 2007-01-28 07:54:20Z dugsong $ # -*- coding: utf-8 -*- """Authentication Header.""" from __future__ import absolute_import from . import dpkt class AH(dpkt.Packet): """Authentication Header. TODO: Longer class information.... Attributes: __hdr__: Header fields of AH. auth: Authentication body. data: Message data. """ __hdr__ = ( ('nxt', 'B', 0), ('len', 'B', 0), # payload length ('rsvd', 'H', 0), ('spi', 'I', 0), ('seq', 'I', 0) ) auth = b'' def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.auth = self.data[:self.len] buf = self.data[self.len:] from . import ip try: self.data = ip.IP.get_proto(self.nxt)(buf) setattr(self, self.data.__class__.__name__.lower(), self.data) except (KeyError, dpkt.UnpackError): self.data = buf def __len__(self): return self.__hdr_len__ + len(self.auth) + len(self.data) def __bytes__(self): return self.pack_hdr() + bytes(self.auth) + bytes(self.data) dpkt-1.9.2/dpkt/aim.py000066400000000000000000000110641340335175100145530ustar00rootroot00000000000000# $Id: aim.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """AOL Instant Messenger.""" from __future__ import absolute_import import struct from . import dpkt # OSCAR: http://iserverd1.khstu.ru/oscar/ class FLAP(dpkt.Packet): """Frame Layer Protocol. See more about the FLAP on \ https://en.wikipedia.org/wiki/OSCAR_protocol#FLAP_header Attributes: __hdr__: Header fields of FLAP. data: Message data. """ __hdr__ = ( ('ast', 'B', 0x2a), # '*' ('type', 'B', 0), ('seq', 'H', 0), ('len', 'H', 0) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.ast != 0x2a: raise dpkt.UnpackError('invalid FLAP header') if len(self.data) < self.len: raise dpkt.NeedData('%d left, %d needed' % (len(self.data), self.len)) class SNAC(dpkt.Packet): """Simple Network Atomic Communication. See more about the SNAC on \ https://en.wikipedia.org/wiki/OSCAR_protocol#SNAC_data Attributes: __hdr__: Header fields of SNAC. """ __hdr__ = ( ('family', 'H', 0), ('subtype', 'H', 0), ('flags', 'H', 0), ('reqid', 'I', 0) ) def tlv(buf): n = 4 try: t, l = struct.unpack('>HH', buf[:n]) except struct.error: raise dpkt.UnpackError('invalid type, length fields') v = buf[n:n + l] if len(v) < l: raise dpkt.NeedData('%d left, %d needed' % (len(v), l)) buf = buf[n + l:] return t, l, v, buf # TOC 1.0: http://jamwt.com/Py-TOC/PROTOCOL # TOC 2.0: http://www.firestuff.org/projects/firetalk/doc/toc2.txt def testAIM(): testdata = b'*\x02\xac\xf3\x00\x81\x00\x03\x00\x0b\x00\x00\xfaEUd\x0eusrnameremoved\x00\x00\x00\n\x00\x01\x00\x02\x12\x90\x00D\x00\x01\x00\x00\x03\x00\x04X\x90T6\x00E\x00\x04\x00\x00\x0f\x93\x00!\x00\x08\x00\x85\x00}\x00}\x00\x00\x00A\x00\x01\x00\x007\x00\x04\x00\x00\x00\x00\x00\r\x00\x00\x00\x19\x00\x00\x00\x1d\x00$\x00\x00\x00\x05\x02\x01\xd2\x04r\x00\x01\x00\x05\x02\x01\xd2\x04r\x00\x03\x00\x05+\x00\x00*\xcc\x00\x81\x00\x05+\x00\x00\x13\xf1' flap = FLAP(testdata) assert flap.ast == 0x2a assert flap.type == 0x02 assert flap.seq == 44275 assert flap.len == 129 assert flap.data == b'\x00\x03\x00\x0b\x00\x00\xfaEUd\x0eusrnameremoved\x00\x00\x00\n\x00\x01\x00\x02\x12\x90\x00D\x00\x01\x00\x00\x03\x00\x04X\x90T6\x00E\x00\x04\x00\x00\x0f\x93\x00!\x00\x08\x00\x85\x00}\x00}\x00\x00\x00A\x00\x01\x00\x007\x00\x04\x00\x00\x00\x00\x00\r\x00\x00\x00\x19\x00\x00\x00\x1d\x00$\x00\x00\x00\x05\x02\x01\xd2\x04r\x00\x01\x00\x05\x02\x01\xd2\x04r\x00\x03\x00\x05+\x00\x00*\xcc\x00\x81\x00\x05+\x00\x00\x13\xf1' snac = SNAC(flap.data) assert snac.family == 3 assert snac.subtype == 11 assert snac.flags == 0 assert snac.reqid == 0xfa455564 assert snac.data == b'\x0eusrnameremoved\x00\x00\x00\n\x00\x01\x00\x02\x12\x90\x00D\x00\x01\x00\x00\x03\x00\x04X\x90T6\x00E\x00\x04\x00\x00\x0f\x93\x00!\x00\x08\x00\x85\x00}\x00}\x00\x00\x00A\x00\x01\x00\x007\x00\x04\x00\x00\x00\x00\x00\r\x00\x00\x00\x19\x00\x00\x00\x1d\x00$\x00\x00\x00\x05\x02\x01\xd2\x04r\x00\x01\x00\x05\x02\x01\xd2\x04r\x00\x03\x00\x05+\x00\x00*\xcc\x00\x81\x00\x05+\x00\x00\x13\xf1' #skip over the buddyname and TLV count in Oncoming Buddy message tlvdata = snac.data[19:] tlvCount = 0 while tlvdata: t, l, v, tlvdata = tlv(tlvdata) tlvCount += 1 if tlvCount == 1: # just check function return for first TLV assert t == 0x01 assert l == 2 assert v == b'\x12\x90' assert tlvdata == b'\x00D\x00\x01\x00\x00\x03\x00\x04X\x90T6\x00E\x00\x04\x00\x00\x0f\x93\x00!\x00\x08\x00\x85\x00}\x00}\x00\x00\x00A\x00\x01\x00\x007\x00\x04\x00\x00\x00\x00\x00\r\x00\x00\x00\x19\x00\x00\x00\x1d\x00$\x00\x00\x00\x05\x02\x01\xd2\x04r\x00\x01\x00\x05\x02\x01\xd2\x04r\x00\x03\x00\x05+\x00\x00*\xcc\x00\x81\x00\x05+\x00\x00\x13\xf1' # make sure we extracted 10 TLVs assert tlvCount == 10 def testExceptions(): testdata = b'xxxxxx' try: flap = FLAP(testdata) except dpkt.UnpackError as e: assert str(e) == 'invalid FLAP header' testdata = b'*\x02\x12\x34\x00\xff' try: flap = FLAP(testdata) except dpkt.NeedData as e: assert str(e) == '0 left, 255 needed' try: t, l, v, _ = tlv(b'x') except dpkt.UnpackError as e: assert str(e) == 'invalid type, length fields' try: t, l, v, _ = tlv(b'\x00\x01\x00\xff') except dpkt.NeedData as e: assert str(e) == '0 left, 255 needed' dpkt-1.9.2/dpkt/aoe.py000066400000000000000000000040631340335175100145520ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ATA over Ethernet Protocol.""" from __future__ import absolute_import import struct from . import dpkt from .decorators import deprecated from .compat import iteritems class AOE(dpkt.Packet): """ATA over Ethernet Protocol. See more about the AOE on \ https://en.wikipedia.org/wiki/ATA_over_Ethernet Attributes: __hdr__: Header fields of AOE. data: Message data. """ __hdr__ = ( ('ver_fl', 'B', 0x10), ('err', 'B', 0), ('maj', 'H', 0), ('min', 'B', 0), ('cmd', 'B', 0), ('tag', 'I', 0), ) _cmdsw = {} @property def ver(self): return self.ver_fl >> 4 @ver.setter def ver(self, ver): self.ver_fl = (ver << 4) | (self.ver_fl & 0xf) @property def fl(self): return self.ver_fl & 0xf @fl.setter def fl(self, fl): self.ver_fl = (self.ver_fl & 0xf0) | fl @classmethod def set_cmd(cls, cmd, pktclass): cls._cmdsw[cmd] = pktclass @classmethod def get_cmd(cls, cmd): return cls._cmdsw[cmd] def unpack(self, buf): dpkt.Packet.unpack(self, buf) try: self.data = self._cmdsw[self.cmd](self.data) setattr(self, self.data.__class__.__name__.lower(), self.data) except (KeyError, struct.error, dpkt.UnpackError): pass def pack_hdr(self): try: return dpkt.Packet.pack_hdr(self) except struct.error as e: raise dpkt.PackError(str(e)) AOE_CMD_ATA = 0 AOE_CMD_CFG = 1 AOE_FLAG_RSP = 1 << 3 def __load_cmds(): prefix = 'AOE_CMD_' g = globals() for k, v in iteritems(g): if k.startswith(prefix): name = 'aoe' + k[len(prefix):].lower() try: mod = __import__(name, g, level=1) AOE.set_cmd(v, getattr(mod, name.upper())) except (ImportError, AttributeError): continue def _mod_init(): """Post-initialization called when all dpkt modules are fully loaded""" if not AOE._cmdsw: __load_cmds() dpkt-1.9.2/dpkt/aoeata.py000066400000000000000000000022611340335175100152360ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ATA over Ethernet ATA command""" from __future__ import print_function from __future__ import absolute_import from . import dpkt ATA_DEVICE_IDENTIFY = 0xec class AOEATA(dpkt.Packet): """ATA over Ethernet ATA command. See more about the AOEATA on \ https://en.wikipedia.org/wiki/ATA_over_Ethernet Attributes: __hdr__: Header fields of AOEATA. data: Message data. """ __hdr__ = ( ('aflags', 'B', 0), ('errfeat', 'B', 0), ('scnt', 'B', 0), ('cmdstat', 'B', ATA_DEVICE_IDENTIFY), ('lba0', 'B', 0), ('lba1', 'B', 0), ('lba2', 'B', 0), ('lba3', 'B', 0), ('lba4', 'B', 0), ('lba5', 'B', 0), ('res', 'H', 0), ) # XXX: in unpack, switch on ATA command like icmp does on type def test_aoeata(): s = b'\x03\x0a\x6b\x19\x00\x00\x00\x00\x45\x00\x00\x28\x94\x1f\x00\x00\xe3\x06\x99\xb4\x23\x2b\x24\x00\xde\x8e\x84\x42\xab\xd1\x00\x50\x00\x35\xe1\x29\x20\xd9\x00\x00\x00\x22\x9b\xf0\xe2\x04\x65\x6b' aoeata = AOEATA(s) assert (bytes(aoeata) == s) if __name__ == '__main__': test_aoeata() print('Tests Successful...') dpkt-1.9.2/dpkt/aoecfg.py000066400000000000000000000016011340335175100152250ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ATA over Ethernet ATA command""" from __future__ import print_function from __future__ import absolute_import from . import dpkt class AOECFG(dpkt.Packet): """ATA over Ethernet ATA command. See more about the AOE on \ https://en.wikipedia.org/wiki/ATA_over_Ethernet Attributes: __hdr__: Header fields of AOECFG. data: Message data. """ __hdr__ = ( ('bufcnt', 'H', 0), ('fwver', 'H', 0), ('scnt', 'B', 0), ('aoeccmd', 'B', 0), ('cslen', 'H', 0), ) def test_aoecfg(): s = b'\x01\x02\x03\x04\x05\x06\x11\x12\x13\x14\x15\x16\x88\xa2\x10\x00\x00\x01\x02\x01\x80\x00\x00\x00\x12\x34\x00\x00\x00\x00\x04\x00' + b'\0xed' * 1024 aoecfg = AOECFG(s[14 + 10:]) assert (aoecfg.bufcnt == 0x1234) if __name__ == '__main__': test_aoecfg() print('Tests Successful...') dpkt-1.9.2/dpkt/arp.py000066400000000000000000000021671340335175100145730ustar00rootroot00000000000000# $Id: arp.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Address Resolution Protocol.""" from __future__ import absolute_import from . import dpkt # Hardware address format ARP_HRD_ETH = 0x0001 # ethernet hardware ARP_HRD_IEEE802 = 0x0006 # IEEE 802 hardware # Protocol address format ARP_PRO_IP = 0x0800 # IP protocol # ARP operation ARP_OP_REQUEST = 1 # request to resolve ha given pa ARP_OP_REPLY = 2 # response giving hardware address ARP_OP_REVREQUEST = 3 # request to resolve pa given ha ARP_OP_REVREPLY = 4 # response giving protocol address class ARP(dpkt.Packet): """Address Resolution Protocol. See more about the ARP on \ https://en.wikipedia.org/wiki/Address_Resolution_Protocol Attributes: __hdr__: Header fields of ARP. """ __hdr__ = ( ('hrd', 'H', ARP_HRD_ETH), ('pro', 'H', ARP_PRO_IP), ('hln', 'B', 6), # hardware address length ('pln', 'B', 4), # protocol address length ('op', 'H', ARP_OP_REQUEST), ('sha', '6s', ''), ('spa', '4s', ''), ('tha', '6s', ''), ('tpa', '4s', '') ) dpkt-1.9.2/dpkt/asn1.py000066400000000000000000000124721340335175100146530ustar00rootroot00000000000000# $Id: asn1.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Abstract Syntax Notation #1.""" from __future__ import absolute_import from __future__ import print_function import struct import time from . import dpkt from .compat import compat_ord # Type class CLASSMASK = 0xc0 UNIVERSAL = 0x00 APPLICATION = 0x40 CONTEXT = 0x80 PRIVATE = 0xc0 # Constructed (vs. primitive) CONSTRUCTED = 0x20 # Universal-class tags TAGMASK = 0x1f INTEGER = 2 BIT_STRING = 3 # arbitrary bit string OCTET_STRING = 4 # arbitrary octet string NULL = 5 OID = 6 # object identifier SEQUENCE = 16 # ordered collection of types SET = 17 # unordered collection of types PRINT_STRING = 19 # printable string T61_STRING = 20 # T.61 (8-bit) character string IA5_STRING = 22 # ASCII UTC_TIME = 23 def utctime(buf): """Convert ASN.1 UTCTime string to UTC float. TODO: Long description here. Args: buf: A buffer with format "yymnddhhmm" Returns: A floating point number, indicates seconds since the Epoch. """ yy = int(buf[:2]) mn = int(buf[2:4]) dd = int(buf[4:6]) hh = int(buf[6:8]) mm = int(buf[8:10]) try: ss = int(buf[10:12]) buf = buf[12:] except TypeError: ss = 0 buf = buf[10:] if buf[0] == '+': hh -= int(buf[1:3]) mm -= int(buf[3:5]) elif buf[0] == '-': hh += int(buf[1:3]) mm += int(buf[3:5]) return time.mktime((2000 + yy, mn, dd, hh, mm, ss, 0, 0, 0)) def decode(buf): """Sleazy ASN.1 decoder. TODO: Long description here. Args: buf: A buffer with Sleazy ASN.1 data. Returns: A list of (id, value) tuples from ASN.1 BER/DER encoded buffer. Raises: UnpackError: An error occurred the ASN.1 length exceed. """ msg = [] while buf: t = compat_ord(buf[0]) constructed = t & CONSTRUCTED tag = t & TAGMASK l = compat_ord(buf[1]) c = 0 if constructed and l == 128: # XXX - constructed, indefinite length msg.append((t, decode(buf[2:]))) elif l >= 128: c = l & 127 if c == 1: l = compat_ord(buf[2]) elif c == 2: l = struct.unpack('>H', buf[2:4])[0] elif c == 3: l = struct.unpack('>I', buf[1:5])[0] & 0xfff c = 2 elif c == 4: l = struct.unpack('>I', buf[2:6])[0] else: # XXX - can be up to 127 bytes, but... raise dpkt.UnpackError('excessive long-form ASN.1 length %d' % l) # Skip type, length buf = buf[2 + c:] # Parse content if constructed: msg.append((t, decode(buf))) elif tag == INTEGER: if l == 0: n = 0 elif l == 1: n = compat_ord(buf[0]) elif l == 2: n = struct.unpack('>H', buf[:2])[0] elif l == 3: n = struct.unpack('>I', buf[:4])[0] >> 8 elif l == 4: n = struct.unpack('>I', buf[:4])[0] else: raise dpkt.UnpackError('excessive integer length > %d bytes' % l) msg.append((t, n)) elif tag == UTC_TIME: msg.append((t, utctime(buf[:l]))) else: msg.append((t, buf[:l])) # Skip content buf = buf[l:] return msg def test_asn1(): s = b'0\x82\x02Q\x02\x01\x0bc\x82\x02J\x04xcn=Douglas J Song 1, ou=Information Technology Division, ou=Faculty and Staff, ou=People, o=University of Michigan, c=US\n\x01\x00\n\x01\x03\x02\x01\x00\x02\x01\x00\x01\x01\x00\x87\x0bobjectclass0\x82\x01\xb0\x04\rmemberOfGroup\x04\x03acl\x04\x02cn\x04\x05title\x04\rpostalAddress\x04\x0ftelephoneNumber\x04\x04mail\x04\x06member\x04\thomePhone\x04\x11homePostalAddress\x04\x0bobjectClass\x04\x0bdescription\x04\x18facsimileTelephoneNumber\x04\x05pager\x04\x03uid\x04\x0cuserPassword\x04\x08joinable\x04\x10associatedDomain\x04\x05owner\x04\x0erfc822ErrorsTo\x04\x08ErrorsTo\x04\x10rfc822RequestsTo\x04\nRequestsTo\x04\tmoderator\x04\nlabeledURL\x04\nonVacation\x04\x0fvacationMessage\x04\x05drink\x04\x0elastModifiedBy\x04\x10lastModifiedTime\x04\rmodifiersname\x04\x0fmodifytimestamp\x04\x0ccreatorsname\x04\x0fcreatetimestamp' assert (decode(s) == [(48, [(2, 11), (99, [(4, b'cn=Douglas J Song 1, ou=Information Technology Division, ou=Faculty and Staff, ou=People, o=University of Michigan, c=US'), (10, b'\x00'), (10, b'\x03'), (2, 0), (2, 0), (1, b'\x00'), (135, b'objectclass'), (48, [(4, b'memberOfGroup'), (4, b'acl'), (4, b'cn'), (4, b'title'), (4, b'postalAddress'), (4, b'telephoneNumber'), (4, b'mail'), (4, b'member'), (4, b'homePhone'), (4, b'homePostalAddress'), (4, b'objectClass'), (4, b'description'), (4, b'facsimileTelephoneNumber'), (4, b'pager'), (4, b'uid'), (4, b'userPassword'), (4, b'joinable'), (4, b'associatedDomain'), (4, b'owner'), (4, b'rfc822ErrorsTo'), (4, b'ErrorsTo'), (4, b'rfc822RequestsTo'), (4, b'RequestsTo'), (4, b'moderator'), (4, b'labeledURL'), (4, b'onVacation'), (4, b'vacationMessage'), (4, b'drink'), (4, b'lastModifiedBy'), (4, b'lastModifiedTime'), (4, b'modifiersname'), (4, b'modifytimestamp'), (4, b'creatorsname'), (4, b'createtimestamp')])])])]) if __name__ == '__main__': test_asn1() print('Tests Successful...') dpkt-1.9.2/dpkt/bgp.py000077500000000000000000000765351340335175100145760ustar00rootroot00000000000000# $Id: bgp.py 76 2011-01-06 15:51:30Z dugsong $ # -*- coding: utf-8 -*- """Border Gateway Protocol.""" from __future__ import print_function from __future__ import absolute_import import struct import socket from . import dpkt from .decorators import deprecated from .compat import compat_ord # Border Gateway Protocol 4 - RFC 4271 # Communities Attribute - RFC 1997 # Capabilities - RFC 3392 # Route Refresh - RFC 2918 # Route Reflection - RFC 4456 # Confederations - RFC 3065 # Cease Subcodes - RFC 4486 # NOPEER Community - RFC 3765 # Multiprotocol Extensions - 2858 # Message Types OPEN = 1 UPDATE = 2 NOTIFICATION = 3 KEEPALIVE = 4 ROUTE_REFRESH = 5 # Attribute Types ORIGIN = 1 AS_PATH = 2 NEXT_HOP = 3 MULTI_EXIT_DISC = 4 LOCAL_PREF = 5 ATOMIC_AGGREGATE = 6 AGGREGATOR = 7 COMMUNITIES = 8 ORIGINATOR_ID = 9 CLUSTER_LIST = 10 MP_REACH_NLRI = 14 MP_UNREACH_NLRI = 15 # Origin Types ORIGIN_IGP = 0 ORIGIN_EGP = 1 INCOMPLETE = 2 # AS Path Types AS_SET = 1 AS_SEQUENCE = 2 AS_CONFED_SEQUENCE = 3 AS_CONFED_SET = 4 # Reserved Communities Types NO_EXPORT = 0xffffff01 NO_ADVERTISE = 0xffffff02 NO_EXPORT_SUBCONFED = 0xffffff03 NO_PEER = 0xffffff04 # Common AFI types AFI_IPV4 = 1 AFI_IPV6 = 2 AFI_L2VPN = 25 # Multiprotocol SAFI types SAFI_UNICAST = 1 SAFI_MULTICAST = 2 SAFI_UNICAST_MULTICAST = 3 SAFI_EVPN = 70 # OPEN Message Optional Parameters AUTHENTICATION = 1 CAPABILITY = 2 # Capability Types CAP_MULTIPROTOCOL = 1 CAP_ROUTE_REFRESH = 2 # NOTIFICATION Error Codes MESSAGE_HEADER_ERROR = 1 OPEN_MESSAGE_ERROR = 2 UPDATE_MESSAGE_ERROR = 3 HOLD_TIMER_EXPIRED = 4 FSM_ERROR = 5 CEASE = 6 # Message Header Error Subcodes CONNECTION_NOT_SYNCHRONIZED = 1 BAD_MESSAGE_LENGTH = 2 BAD_MESSAGE_TYPE = 3 # OPEN Message Error Subcodes UNSUPPORTED_VERSION_NUMBER = 1 BAD_PEER_AS = 2 BAD_BGP_IDENTIFIER = 3 UNSUPPORTED_OPTIONAL_PARAMETER = 4 AUTHENTICATION_FAILURE = 5 UNACCEPTABLE_HOLD_TIME = 6 UNSUPPORTED_CAPABILITY = 7 # UPDATE Message Error Subcodes MALFORMED_ATTRIBUTE_LIST = 1 UNRECOGNIZED_ATTRIBUTE = 2 MISSING_ATTRIBUTE = 3 ATTRIBUTE_FLAGS_ERROR = 4 ATTRIBUTE_LENGTH_ERROR = 5 INVALID_ORIGIN_ATTRIBUTE = 6 AS_ROUTING_LOOP = 7 INVALID_NEXT_HOP_ATTRIBUTE = 8 OPTIONAL_ATTRIBUTE_ERROR = 9 INVALID_NETWORK_FIELD = 10 MALFORMED_AS_PATH = 11 # Cease Error Subcodes MAX_NUMBER_OF_PREFIXES_REACHED = 1 ADMINISTRATIVE_SHUTDOWN = 2 PEER_DECONFIGURED = 3 ADMINISTRATIVE_RESET = 4 CONNECTION_REJECTED = 5 OTHER_CONFIGURATION_CHANGE = 6 CONNECTION_COLLISION_RESOLUTION = 7 OUT_OF_RESOURCES = 8 class BGP(dpkt.Packet): """Border Gateway Protocol. BGP is an inter-AS routing protocol. See more about the BGP on \ https://en.wikipedia.org/wiki/Border_Gateway_Protocol Attributes: __hdr__: Header fields of BGP. #TODO """ __hdr__ = ( ('marker', '16s', '\xff' * 16), ('len', 'H', 0), ('type', 'B', OPEN) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.data = self.data[:self.len - self.__hdr_len__] if self.type == OPEN: self.data = self.open = self.Open(self.data) elif self.type == UPDATE: self.data = self.update = self.Update(self.data) elif self.type == NOTIFICATION: self.data = self.notifiation = self.Notification(self.data) elif self.type == KEEPALIVE: self.data = self.keepalive = self.Keepalive(self.data) elif self.type == ROUTE_REFRESH: self.data = self.route_refresh = self.RouteRefresh(self.data) class Open(dpkt.Packet): __hdr__ = ( ('v', 'B', 4), ('asn', 'H', 0), ('holdtime', 'H', 0), ('identifier', 'I', 0), ('param_len', 'B', 0) ) __hdr_defaults__ = { 'parameters': [] } def unpack(self, buf): dpkt.Packet.unpack(self, buf) l = [] plen = self.param_len while plen > 0: param = self.Parameter(self.data) self.data = self.data[len(param):] plen -= len(param) l.append(param) self.data = self.parameters = l def __len__(self): return self.__hdr_len__ + sum(map(len, self.parameters)) def __bytes__(self): params = b''.join(map(bytes, self.parameters)) self.param_len = len(params) return self.pack_hdr() + params class Parameter(dpkt.Packet): __hdr__ = ( ('type', 'B', 0), ('len', 'B', 0) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.data = self.data[:self.len] if self.type == AUTHENTICATION: self.data = self.authentication = self.Authentication(self.data) elif self.type == CAPABILITY: self.data = self.capability = self.Capability(self.data) class Authentication(dpkt.Packet): __hdr__ = ( ('code', 'B', 0), ) class Capability(dpkt.Packet): __hdr__ = ( ('code', 'B', 0), ('len', 'B', 0) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.data = self.data[:self.len] class Update(dpkt.Packet): __hdr_defaults__ = { 'withdrawn': [], 'attributes': [], 'announced': [] } def unpack(self, buf): self.data = buf # Withdrawn Routes wlen = struct.unpack('>H', self.data[:2])[0] self.data = self.data[2:] l = [] while wlen > 0: route = RouteIPV4(self.data) self.data = self.data[len(route):] wlen -= len(route) l.append(route) self.withdrawn = l # Path Attributes plen = struct.unpack('>H', self.data[:2])[0] self.data = self.data[2:] l = [] while plen > 0: attr = self.Attribute(self.data) self.data = self.data[len(attr):] plen -= len(attr) l.append(attr) self.attributes = l # Announced Routes l = [] while self.data: route = RouteIPV4(self.data) self.data = self.data[len(route):] l.append(route) self.announced = l def __len__(self): return 2 + sum(map(len, self.withdrawn)) + \ 2 + sum(map(len, self.attributes)) + \ sum(map(len, self.announced)) def __bytes__(self): return struct.pack('>H', sum(map(len, self.withdrawn))) + \ b''.join(map(bytes, self.withdrawn)) + \ struct.pack('>H', sum(map(len, self.attributes))) + \ b''.join(map(bytes, self.attributes)) + \ b''.join(map(bytes, self.announced)) class Attribute(dpkt.Packet): __hdr__ = ( ('flags', 'B', 0), ('type', 'B', 0) ) @property def optional(self): return (self.flags >> 7) & 0x1 @optional.setter def optional(self, o): self.flags = (self.flags & ~0x80) | ((o & 0x1) << 7) @property def transitive(self): return (self.flags >> 6) & 0x1 @transitive.setter def transitive(self, t): self.flags = (self.flags & ~0x40) | ((t & 0x1) << 6) @property def partial(self): return (self.flags >> 5) & 0x1 @partial.setter def partial(self, p): self.flags = (self.flags & ~0x20) | ((p & 0x1) << 5) @property def extended_length(self): return (self.flags >> 4) & 0x1 @extended_length.setter def extended_length(self, e): self.flags = (self.flags & ~0x10) | ((e & 0x1) << 4) def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.extended_length: self.len = struct.unpack('>H', self.data[:2])[0] self.data = self.data[2:] else: self.len = struct.unpack('B', self.data[:1])[0] self.data = self.data[1:] self.data = self.data[:self.len] if self.type == ORIGIN: self.data = self.origin = self.Origin(self.data) elif self.type == AS_PATH: self.data = self.as_path = self.ASPath(self.data) elif self.type == NEXT_HOP: self.data = self.next_hop = self.NextHop(self.data) elif self.type == MULTI_EXIT_DISC: self.data = self.multi_exit_disc = self.MultiExitDisc(self.data) elif self.type == LOCAL_PREF: self.data = self.local_pref = self.LocalPref(self.data) elif self.type == ATOMIC_AGGREGATE: self.data = self.atomic_aggregate = self.AtomicAggregate(self.data) elif self.type == AGGREGATOR: self.data = self.aggregator = self.Aggregator(self.data) elif self.type == COMMUNITIES: self.data = self.communities = self.Communities(self.data) elif self.type == ORIGINATOR_ID: self.data = self.originator_id = self.OriginatorID(self.data) elif self.type == CLUSTER_LIST: self.data = self.cluster_list = self.ClusterList(self.data) elif self.type == MP_REACH_NLRI: self.data = self.mp_reach_nlri = self.MPReachNLRI(self.data) elif self.type == MP_UNREACH_NLRI: self.data = self.mp_unreach_nlri = self.MPUnreachNLRI(self.data) def __len__(self): if self.extended_length: attr_len = 2 else: attr_len = 1 return self.__hdr_len__ + attr_len + len(self.data) def __bytes__(self): if self.extended_length: attr_len_str = struct.pack('>H', self.len) else: attr_len_str = struct.pack('B', self.len) return self.pack_hdr() + attr_len_str + bytes(self.data) class Origin(dpkt.Packet): __hdr__ = ( ('type', 'B', ORIGIN_IGP), ) class ASPath(dpkt.Packet): __hdr_defaults__ = { 'segments': [] } def unpack(self, buf): self.data = buf l = [] while self.data: seg = self.ASPathSegment(self.data) self.data = self.data[len(seg):] l.append(seg) self.data = self.segments = l def __len__(self): return sum(map(len, self.data)) def __bytes__(self): return b''.join(map(bytes, self.data)) class ASPathSegment(dpkt.Packet): __hdr__ = ( ('type', 'B', 0), ('len', 'B', 0) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) l = [] for i in range(self.len): AS = struct.unpack('>H', self.data[:2])[0] self.data = self.data[2:] l.append(AS) self.data = self.path = l def __len__(self): return self.__hdr_len__ + 2 * len(self.path) def __bytes__(self): as_str = b'' for AS in self.path: as_str += struct.pack('>H', AS) return self.pack_hdr() + as_str class NextHop(dpkt.Packet): __hdr__ = ( ('ip', 'I', 0), ) class MultiExitDisc(dpkt.Packet): __hdr__ = ( ('value', 'I', 0), ) class LocalPref(dpkt.Packet): __hdr__ = ( ('value', 'I', 0), ) class AtomicAggregate(dpkt.Packet): def unpack(self, buf): pass def __len__(self): return 0 def __bytes__(self): return b'' class Aggregator(dpkt.Packet): __hdr__ = ( ('asn', 'H', 0), ('ip', 'I', 0) ) class Communities(dpkt.Packet): __hdr_defaults__ = { 'list': [] } def unpack(self, buf): self.data = buf l = [] while self.data: val = struct.unpack('>I', self.data[:4])[0] if (0x00000000 <= val <= 0x0000ffff) or (0xffff0000 <= val <= 0xffffffff): comm = self.ReservedCommunity(self.data[:4]) else: comm = self.Community(self.data[:4]) self.data = self.data[len(comm):] l.append(comm) self.data = self.list = l def __len__(self): return sum(map(len, self.data)) def __bytes__(self): return b''.join(map(bytes, self.data)) class Community(dpkt.Packet): __hdr__ = ( ('asn', 'H', 0), ('value', 'H', 0) ) class ReservedCommunity(dpkt.Packet): __hdr__ = ( ('value', 'I', 0), ) class OriginatorID(dpkt.Packet): __hdr__ = ( ('value', 'I', 0), ) class ClusterList(dpkt.Packet): __hdr_defaults__ = { 'list': [] } def unpack(self, buf): self.data = buf l = [] while self.data: id = struct.unpack('>I', self.data[:4])[0] self.data = self.data[4:] l.append(id) self.data = self.list = l def __len__(self): return 4 * len(self.list) def __bytes__(self): cluster_str = b'' for val in self.list: cluster_str += struct.pack('>I', val) return cluster_str class MPReachNLRI(dpkt.Packet): __hdr__ = ( ('afi', 'H', AFI_IPV4), ('safi', 'B', SAFI_UNICAST), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) # Next Hop nlen = struct.unpack('B', self.data[:1])[0] self.data = self.data[1:] self.next_hop = self.data[:nlen] self.data = self.data[nlen:] # SNPAs l = [] num_snpas = struct.unpack('B', self.data[:1])[0] self.data = self.data[1:] for i in range(num_snpas): snpa = self.SNPA(self.data) self.data = self.data[len(snpa):] l.append(snpa) self.snpas = l if self.afi == AFI_IPV4: Route = RouteIPV4 elif self.afi == AFI_IPV6: Route = RouteIPV6 elif self.afi == AFI_L2VPN: Route = RouteEVPN else: Route = RouteGeneric # Announced Routes l = [] while self.data: route = Route(self.data) self.data = self.data[len(route):] l.append(route) self.data = self.announced = l def __len__(self): return self.__hdr_len__ + \ 1 + len(self.next_hop) + \ 1 + sum(map(len, self.snpas)) + \ sum(map(len, self.announced)) def __bytes__(self): return self.pack_hdr() + \ struct.pack('B', len(self.next_hop)) + \ bytes(self.next_hop) + \ struct.pack('B', len(self.snpas)) + \ b''.join(map(bytes, self.snpas)) + \ b''.join(map(bytes, self.announced)) class SNPA(object): __hdr__ = ( ('len', 'B', 0), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.data = self.data[:(self.len + 1) // 2] class MPUnreachNLRI(dpkt.Packet): __hdr__ = ( ('afi', 'H', AFI_IPV4), ('safi', 'B', SAFI_UNICAST), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.afi == AFI_IPV4: Route = RouteIPV4 elif self.afi == AFI_IPV6: Route = RouteIPV6 elif self.afi == AFI_L2VPN: Route = RouteEVPN else: Route = RouteGeneric # Withdrawn Routes l = [] while self.data: route = Route(self.data) self.data = self.data[len(route):] l.append(route) self.data = self.withdrawn = l def __len__(self): return self.__hdr_len__ + sum(map(len, self.data)) def __bytes__(self): return self.pack_hdr() + b''.join(map(bytes, self.data)) class Notification(dpkt.Packet): __hdr__ = ( ('code', 'B', 0), ('subcode', 'B', 0), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.error = self.data class Keepalive(dpkt.Packet): def unpack(self, buf): pass def __len__(self): return 0 def __bytes__(self): return b'' class RouteRefresh(dpkt.Packet): __hdr__ = ( ('afi', 'H', AFI_IPV4), ('rsvd', 'B', 0), ('safi', 'B', SAFI_UNICAST) ) class RouteGeneric(dpkt.Packet): __hdr__ = ( ('len', 'B', 0), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.data = self.prefix = self.data[:(self.len + 7) // 8] class RouteIPV4(dpkt.Packet): __hdr__ = ( ('len', 'B', 0), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) tmp = self.data[:(self.len + 7) // 8] tmp += (4 - len(tmp)) * b'\x00' self.data = self.prefix = tmp def __repr__(self): cidr = '%s/%d' % (socket.inet_ntoa(self.prefix), self.len) return '%s(%s)' % (self.__class__.__name__, cidr) def __len__(self): return self.__hdr_len__ + (self.len + 7) // 8 def __bytes__(self): return self.pack_hdr() + self.prefix[:(self.len + 7) // 8] class RouteIPV6(dpkt.Packet): __hdr__ = ( ('len', 'B', 0), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) tmp = self.data[:(self.len + 7) // 8] tmp += (16 - len(tmp)) * b'\x00' self.data = self.prefix = tmp def __len__(self): return self.__hdr_len__ + (self.len + 7) // 8 def __bytes__(self): return self.pack_hdr() + self.prefix[:(self.len + 7) // 8] class RouteEVPN(dpkt.Packet): __hdr__ = ( ('type', 'B', 0), ('len', 'B', 0) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.route_data = buf = self.data[:self.len] self.data = self.data[self.len:] # Get route distinguisher. self.rd = buf[:8] buf = buf[8:] # Get route information. Not all fields are present on all route types. if self.type != 0x3: self.esi = buf[:10] buf = buf[10:] if self.type != 0x4: self.eth_id = buf[:4] buf = buf[4:] if self.type == 0x2: self.mac_address_length = compat_ord(buf[0]) if self.mac_address_length == 48: self.mac_address = buf[1:7] buf = buf[7:] else: self.mac_address = None buf = buf[1:] if self.type != 0x1: self.ip_address_length = compat_ord(buf[0]) if self.ip_address_length == 128: self.ip_address = buf[1:17] buf = buf[17:] elif self.ip_address_length == 32: self.ip_address = buf[1:5] buf = buf[5:] else: self.ip_address = None buf = buf[1:] if self.type in [0x1, 0x2]: self.mpls_label_stack = buf[:3] buf = buf[3:] if self.len > len(buf): self.mpls_label_stack += buf[:3] def __len__(self): return self.__hdr_len__ + self.len def __bytes__(self): return self.pack_hdr() + self.route_data __bgp1 = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x13\x04' __bgp2 = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x63\x02\x00\x00\x00\x48\x40\x01\x01\x00\x40\x02\x0a\x01\x02\x01\xf4\x01\xf4\x02\x01\xfe\xbb\x40\x03\x04\xc0\xa8\x00\x0f\x40\x05\x04\x00\x00\x00\x64\x40\x06\x00\xc0\x07\x06\xfe\xba\xc0\xa8\x00\x0a\xc0\x08\x0c\xfe\xbf\x00\x01\x03\x16\x00\x04\x01\x54\x00\xfa\x80\x09\x04\xc0\xa8\x00\x0f\x80\x0a\x04\xc0\xa8\x00\xfa\x16\xc0\xa8\x04' __bgp3 = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x79\x02\x00\x00\x00\x62\x40\x01\x01\x00\x40\x02\x00\x40\x05\x04\x00\x00\x00\x64\xc0\x10\x08\x00\x02\x01\x2c\x00\x00\x01\x2c\xc0\x80\x24\x00\x00\xfd\xe9\x40\x01\x01\x00\x40\x02\x04\x02\x01\x15\xb3\x40\x05\x04\x00\x00\x00\x2c\x80\x09\x04\x16\x05\x05\x05\x80\x0a\x04\x16\x05\x05\x05\x90\x0e\x00\x1e\x00\x01\x80\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x04\x04\x04\x00\x60\x18\x77\x01\x00\x00\x01\xf4\x00\x00\x01\xf4\x85' __bgp4 = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x2d\x01\x04\x00\xed\x00\x5a\xc6\x6e\x83\x7d\x10\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80\x00\x02\x02\x02\x00' # BGP-EVPN type 1-4 packets for testing. __bgp5 = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x60\x02\x00\x00\x00\x49\x40\x01\x01\x00\x40\x02\x00\x40\x05\x04\x00\x00\x00\x64\xc0\x10\x10\x03\x0c\x00\x00\x00\x00\x00\x08\x00\x02\x03\xe8\x00\x00\x00\x02\x90\x0e\x00\x24\x00\x19\x46\x04\x01\x01\x01\x02\x00\x01\x19\x00\x01\x01\x01\x01\x02\x00\x02\x05\x00\x00\x03\xe8\x00\x00\x04\x00\x00\x00\x00\x00\x02\x00\x00\x02' __bgp6 = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x6f\x02\x00\x00\x00\x58\x40\x01\x01\x00\x40\x02\x00\x40\x05\x04\x00\x00\x00\x64\xc0\x10\x10\x03\x0c\x00\x00\x00\x00\x00\x08\x00\x02\x03\xe8\x00\x00\x00\x02\x90\x0e\x00\x33\x00\x19\x46\x04\x01\x01\x01\x02\x00\x02\x28\x00\x01\x01\x01\x01\x02\x00\x02\x05\x00\x00\x03\xe8\x00\x00\x04\x00\x00\x00\x00\x00\x02\x30\xcc\xaa\x02\x9c\xd8\x29\x20\xc0\xb4\x01\x02\x00\x00\x02\x00\x00\x00' __bgp7 = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x58\x02\x00\x00\x00\x41\x40\x01\x01\x00\x40\x02\x00\x40\x05\x04\x00\x00\x00\x64\xc0\x10\x10\x03\x0c\x00\x00\x00\x00\x00\x08\x00\x02\x03\xe8\x00\x00\x00\x02\x90\x0e\x00\x1c\x00\x19\x46\x04\x01\x01\x01\x02\x00\x03\x11\x00\x01\x01\x01\x01\x02\x00\x02\x00\x00\x00\x02\x20\xc0\xb4\x01\x02' __bgp8 = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x5f\x02\x00\x00\x00\x48\x40\x01\x01\x00\x40\x02\x00\x40\x05\x04\x00\x00\x00\x64\xc0\x10\x10\x03\x0c\x00\x00\x00\x00\x00\x08\x00\x02\x03\xe8\x00\x00\x00\x02\x90\x0e\x00\x23\x00\x19\x46\x04\x01\x01\x01\x02\x00\x04\x18\x00\x01\x01\x01\x01\x02\x00\x02\x05\x00\x00\x03\xe8\x00\x00\x04\x00\x00\x20\xc0\xb4\x01\x02' __bgp9 = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x7b\x02\x00\x00\x00\x64\x40\x01\x01\x00\x40\x02\x00\x40\x05\x04\x00\x00\x00\x64\xc0\x10\x10\x03\x0c\x00\x00\x00\x00\x00\x08\x00\x02\x03\xe8\x00\x00\x00\x02\x90\x0e\x00\x3f\x00\x19\x46\x04\x01\x01\x01\x02\x00\x02\x34\x00\x01\x01\x01\x01\x02\x00\x02\x05\x00\x00\x03\xe8\x00\x00\x04\x00\x00\x00\x00\x00\x02\x30\xcc\xaa\x02\x9c\xd8\x29\x80\xc0\xb4\x01\x02\xc0\xb4\x01\x02\xc0\xb4\x01\x02\xc0\xb4\x01\x02\x00\x00\x02\x00\x00\x00' def test_pack(): assert (__bgp1 == bytes(BGP(__bgp1))) assert (__bgp2 == bytes(BGP(__bgp2))) assert (__bgp3 == bytes(BGP(__bgp3))) assert (__bgp4 == bytes(BGP(__bgp4))) assert (__bgp5 == bytes(BGP(__bgp5))) assert (__bgp6 == bytes(BGP(__bgp6))) assert (__bgp7 == bytes(BGP(__bgp7))) assert (__bgp8 == bytes(BGP(__bgp8))) assert (__bgp9 == bytes(BGP(__bgp9))) def test_unpack(): b1 = BGP(__bgp1) assert (b1.len == 19) assert (b1.type == KEEPALIVE) assert (b1.keepalive is not None) b2 = BGP(__bgp2) assert (b2.type == UPDATE) assert (len(b2.update.withdrawn) == 0) assert (len(b2.update.announced) == 1) assert (len(b2.update.attributes) == 9) a = b2.update.attributes[1] assert (a.type == AS_PATH) assert (a.len == 10) assert (len(a.as_path.segments) == 2) s = a.as_path.segments[0] assert (s.type == AS_SET) assert (s.len == 2) assert (len(s.path) == 2) assert (s.path[0] == 500) a = b2.update.attributes[6] assert (a.type == COMMUNITIES) assert (a.len == 12) assert (len(a.communities.list) == 3) c = a.communities.list[0] assert (c.asn == 65215) assert (c.value == 1) r = b2.update.announced[0] assert (r.len == 22) assert (r.prefix == b'\xc0\xa8\x04\x00') b3 = BGP(__bgp3) assert (b3.type == UPDATE) assert (len(b3.update.withdrawn) == 0) assert (len(b3.update.announced) == 0) assert (len(b3.update.attributes) == 6) a = b3.update.attributes[0] assert (a.optional == False) assert (a.transitive == True) assert (a.partial == False) assert (a.extended_length == False) assert (a.type == ORIGIN) assert (a.len == 1) o = a.origin assert (o.type == ORIGIN_IGP) a = b3.update.attributes[5] assert (a.optional == True) assert (a.transitive == False) assert (a.partial == False) assert (a.extended_length == True) assert (a.type == MP_REACH_NLRI) assert (a.len == 30) m = a.mp_reach_nlri assert (m.afi == AFI_IPV4) assert (len(m.snpas) == 0) assert (len(m.announced) == 1) p = m.announced[0] assert (p.len == 96) b4 = BGP(__bgp4) assert (b4.len == 45) assert (b4.type == OPEN) assert (b4.open.asn == 237) assert (b4.open.param_len == 16) assert (len(b4.open.parameters) == 3) p = b4.open.parameters[0] assert (p.type == CAPABILITY) assert (p.len == 6) c = p.capability assert (c.code == CAP_MULTIPROTOCOL) assert (c.len == 4) assert (c.data == b'\x00\x01\x00\x01') c = b4.open.parameters[2].capability assert (c.code == CAP_ROUTE_REFRESH) assert (c.len == 0) b5 = BGP(__bgp5) assert (b5.len == 96) assert (b5.type == UPDATE) assert (len(b5.update.withdrawn) == 0) a = b5.update.attributes[-1] assert (a.type == MP_REACH_NLRI) assert (a.len == 36) m = a.mp_reach_nlri assert (m.afi == AFI_L2VPN) assert (m.safi == SAFI_EVPN) r = m.announced[0] assert (r.type == 1) assert (r.len == 25) assert (r.rd == b'\x00\x01\x01\x01\x01\x02\x00\x02') assert (r.esi == b'\x05\x00\x00\x03\xe8\x00\x00\x04\x00\x00') assert (r.eth_id == b'\x00\x00\x00\x02') assert (r.mpls_label_stack == b'\x00\x00\x02') b6 = BGP(__bgp6) assert (b6.len == 111) assert (b6.type == UPDATE) assert (len(b6.update.withdrawn) == 0) a = b6.update.attributes[-1] assert (a.type == MP_REACH_NLRI) assert (a.len == 51) m = a.mp_reach_nlri assert (m.afi == AFI_L2VPN) assert (m.safi == SAFI_EVPN) r = m.announced[0] assert (r.type == 2) assert (r.len == 40) assert (r.rd == b'\x00\x01\x01\x01\x01\x02\x00\x02') assert (r.esi == b'\x05\x00\x00\x03\xe8\x00\x00\x04\x00\x00') assert (r.eth_id == b'\x00\x00\x00\x02') assert (r.mac_address_length == 48) assert (r.mac_address == b'\xcc\xaa\x02\x9c\xd8\x29') assert (r.ip_address_length == 32) assert (r.ip_address == b'\xc0\xb4\x01\x02') assert (r.mpls_label_stack == b'\x00\x00\x02\x00\x00\x00') b7 = BGP(__bgp7) assert (b7.len == 88) assert (b7.type == UPDATE) assert (len(b7.update.withdrawn) == 0) a = b7.update.attributes[-1] assert (a.type == MP_REACH_NLRI) assert (a.len == 28) m = a.mp_reach_nlri assert (m.afi == AFI_L2VPN) assert (m.safi == SAFI_EVPN) r = m.announced[0] assert (r.type == 3) assert (r.len == 17) assert (r.rd == b'\x00\x01\x01\x01\x01\x02\x00\x02') assert (r.eth_id == b'\x00\x00\x00\x02') assert (r.ip_address_length == 32) assert (r.ip_address == b'\xc0\xb4\x01\x02') b8 = BGP(__bgp8) assert (b8.len == 95) assert (b8.type == UPDATE) assert (len(b8.update.withdrawn) == 0) a = b8.update.attributes[-1] assert (a.type == MP_REACH_NLRI) assert (a.len == 35) m = a.mp_reach_nlri assert (m.afi == AFI_L2VPN) assert (m.safi == SAFI_EVPN) r = m.announced[0] assert (r.type == 4) assert (r.len == 24) assert (r.rd == b'\x00\x01\x01\x01\x01\x02\x00\x02') assert (r.esi == b'\x05\x00\x00\x03\xe8\x00\x00\x04\x00\x00') assert (r.ip_address_length == 32) assert (r.ip_address == b'\xc0\xb4\x01\x02') b9 = BGP(__bgp9) assert (b9.len == 123) assert (b9.type == UPDATE) assert (len(b9.update.withdrawn) == 0) a = b9.update.attributes[-1] assert (a.type == MP_REACH_NLRI) assert (a.len == 63) m = a.mp_reach_nlri assert (m.afi == AFI_L2VPN) assert (m.safi == SAFI_EVPN) r = m.announced[0] assert (r.type == 2) assert (r.len == 52) assert (r.rd == b'\x00\x01\x01\x01\x01\x02\x00\x02') assert (r.esi == b'\x05\x00\x00\x03\xe8\x00\x00\x04\x00\x00') assert (r.eth_id == b'\x00\x00\x00\x02') assert (r.mac_address_length == 48) assert (r.mac_address == b'\xcc\xaa\x02\x9c\xd8\x29') assert (r.ip_address_length == 128) assert (r.ip_address == b'\xc0\xb4\x01\x02\xc0\xb4\x01\x02\xc0\xb4\x01\x02\xc0\xb4\x01\x02') assert (r.mpls_label_stack == b'\x00\x00\x02\x00\x00\x00') if __name__ == '__main__': test_pack() test_unpack() print('Tests Successful...') dpkt-1.9.2/dpkt/cdp.py000066400000000000000000000057551340335175100145650ustar00rootroot00000000000000# $Id: cdp.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Cisco Discovery Protocol.""" from __future__ import absolute_import import struct from . import dpkt CDP_DEVID = 1 # string CDP_ADDRESS = 2 CDP_PORTID = 3 # string CDP_CAPABILITIES = 4 # 32-bit bitmask CDP_VERSION = 5 # string CDP_PLATFORM = 6 # string CDP_IPPREFIX = 7 CDP_VTP_MGMT_DOMAIN = 9 # string CDP_NATIVE_VLAN = 10 # 16-bit integer CDP_DUPLEX = 11 # 8-bit boolean CDP_TRUST_BITMAP = 18 # 8-bit bitmask0x13 CDP_UNTRUST_COS = 19 # 8-bit port CDP_SYSTEM_NAME = 20 # string CDP_SYSTEM_OID = 21 # 10-byte binary string CDP_MGMT_ADDRESS = 22 # 32-bit number of addrs, Addresses CDP_LOCATION = 23 # string class CDP(dpkt.Packet): """Cisco Discovery Protocol. See more about the BGP on \ https://en.wikipedia.org/wiki/Cisco_Discovery_Protocol Attributes: __hdr__: Header fields of CDP. #TODO """ __hdr__ = ( ('version', 'B', 2), ('ttl', 'B', 180), ('sum', 'H', 0) ) class Address(dpkt.Packet): # XXX - only handle NLPID/IP for now __hdr__ = ( ('ptype', 'B', 1), # protocol type (NLPID) ('plen', 'B', 1), # protocol length ('p', 'B', 0xcc), # IP ('alen', 'H', 4) # address length ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.data = self.data[:self.alen] class TLV(dpkt.Packet): __hdr__ = ( ('type', 'H', 0), ('len', 'H', 4) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.data = self.data[:self.len - 4] if self.type == CDP_ADDRESS: n = struct.unpack('>I', self.data[:4])[0] buf = self.data[4:] l = [] for i in range(n): a = CDP.Address(buf) l.append(a) buf = buf[len(a):] self.data = l def __len__(self): if self.type == CDP_ADDRESS: n = 4 + sum(map(len, self.data)) else: n = len(self.data) return self.__hdr_len__ + n def __bytes__(self): self.len = len(self) if self.type == CDP_ADDRESS: s = struct.pack('>I', len(self.data)) + \ b''.join(map(bytes, self.data)) else: s = self.data return self.pack_hdr() + s def unpack(self, buf): dpkt.Packet.unpack(self, buf) buf = self.data l = [] while buf: tlv = self.TLV(buf) l.append(tlv) buf = buf[len(tlv):] self.data = l def __len__(self): return self.__hdr_len__ + sum(map(len, self.data)) def __bytes__(self): data = b''.join(map(bytes, self.data)) if not self.sum: self.sum = dpkt.in_cksum(self.pack_hdr() + data) return self.pack_hdr() + data dpkt-1.9.2/dpkt/compat.py000066400000000000000000000011261340335175100152660ustar00rootroot00000000000000from __future__ import absolute_import import sys if sys.version_info < (3,): compat_ord = ord else: def compat_ord(char): return char try: from itertools import izip compat_izip = izip except ImportError: compat_izip = zip try: from cStringIO import StringIO except ImportError: from io import StringIO try: from BytesIO import BytesIO except ImportError: from io import BytesIO if sys.version_info < (3,): def iteritems(d, **kw): return d.iteritems(**kw) else: def iteritems(d, **kw): return iter(d.items(**kw)) dpkt-1.9.2/dpkt/crc32c.py000066400000000000000000000105341340335175100150650ustar00rootroot00000000000000# $Id: crc32c.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- from __future__ import absolute_import import array # CRC-32C Checksum for SCTP # http://tools.ietf.org/html/rfc3309 crc32c_table = ( 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 ) def add(crc, buf): byte_buf = array.array('B', buf) for b in byte_buf: crc = (crc >> 8) ^ crc32c_table[(crc ^ b) & 0xff] return crc def done(crc): tmp = ~crc & 0xffffffff b0 = tmp & 0xff b1 = (tmp >> 8) & 0xff b2 = (tmp >> 16) & 0xff b3 = (tmp >> 24) & 0xff crc = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3 return crc def cksum(buf): """Return computed CRC-32c checksum.""" return done(add(0xffffffff, buf)) def test_crc32c(): def bswap32(x): from struct import pack, unpack return unpack('I', x))[0] # reference test value from CRC catalogue # http://reveng.sourceforge.net/crc-catalogue/17plus.htm#crc.cat.crc-32c # SCTP uses tranport-level mirrored byte ordering, so we bswap32 assert cksum(b'') == 0 assert cksum(b'123456789') == bswap32(0xe3069283) if __name__ == '__main__': test_crc32c() print('Tests Successful...') dpkt-1.9.2/dpkt/decorators.py000066400000000000000000000051201340335175100161460ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import print_function from __future__ import absolute_import import warnings def decorator_with_args(decorator_to_enhance): """ This is decorator for decorator. It allows any decorator to get additional arguments """ def decorator_maker(*args, **kwargs): def decorator_wrapper(func): return decorator_to_enhance(func, *args, **kwargs) return decorator_wrapper return decorator_maker @decorator_with_args def deprecated(deprecated_method, func_name=None): def _deprecated(*args, **kwargs): # Print only the first occurrence of the DeprecationWarning, regardless of location warnings.simplefilter('once', DeprecationWarning) # Display the deprecation warning message if func_name: # If the function, should be used instead, is received warnings.warn("Call to deprecated method %s; use %s instead" % (deprecated_method.__name__, func_name), category=DeprecationWarning, stacklevel=2) else: warnings.warn("Call to deprecated method %s" % deprecated_method.__name__, category=DeprecationWarning, stacklevel=2) return deprecated_method(*args, **kwargs) # actually call the method return _deprecated class TestDeprecatedDecorator(object): def new_method(self): return @deprecated('new_method') def old_method(self): return @deprecated() def deprecated_decorator(self): return def test_deprecated_decorator(self): import sys from .compat import StringIO saved_stderr = sys.stderr try: out = StringIO() sys.stderr = out self.deprecated_decorator() try: # This isn't working under newest version of pytest assert ('DeprecationWarning: Call to deprecated method deprecated_decorator' in out.getvalue()) out.truncate(0) # clean the buffer self.old_method() assert ('DeprecationWarning: Call to deprecated method old_method; use new_method instead' in out.getvalue()) out.truncate(0) # clean the buffer self.new_method() assert ('DeprecationWarning' not in out.getvalue()) except AssertionError: print('Assertion failing, Note: This is expected for Python 2.6') finally: sys.stderr = saved_stderr if __name__ == '__main__': a = TestDeprecatedDecorator() a.test_deprecated_decorator() print('Tests Successful...') dpkt-1.9.2/dpkt/dhcp.py000066400000000000000000000141131340335175100147210ustar00rootroot00000000000000# $Id: dhcp.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Dynamic Host Configuration Protocol.""" from __future__ import print_function from __future__ import absolute_import import struct from . import arp from . import dpkt from .compat import compat_ord DHCP_OP_REQUEST = 1 DHCP_OP_REPLY = 2 DHCP_MAGIC = 0x63825363 # DHCP option codes DHCP_OPT_NETMASK = 1 # I: subnet mask DHCP_OPT_TIMEOFFSET = 2 DHCP_OPT_ROUTER = 3 # s: list of router ips DHCP_OPT_TIMESERVER = 4 DHCP_OPT_NAMESERVER = 5 DHCP_OPT_DNS_SVRS = 6 # s: list of DNS servers DHCP_OPT_LOGSERV = 7 DHCP_OPT_COOKIESERV = 8 DHCP_OPT_LPRSERV = 9 DHCP_OPT_IMPSERV = 10 DHCP_OPT_RESSERV = 11 DHCP_OPT_HOSTNAME = 12 # s: client hostname DHCP_OPT_BOOTFILESIZE = 13 DHCP_OPT_DUMPFILE = 14 DHCP_OPT_DOMAIN = 15 # s: domain name DHCP_OPT_SWAPSERV = 16 DHCP_OPT_ROOTPATH = 17 DHCP_OPT_EXTENPATH = 18 DHCP_OPT_IPFORWARD = 19 DHCP_OPT_SRCROUTE = 20 DHCP_OPT_POLICYFILTER = 21 DHCP_OPT_MAXASMSIZE = 22 DHCP_OPT_IPTTL = 23 DHCP_OPT_MTUTIMEOUT = 24 DHCP_OPT_MTUTABLE = 25 DHCP_OPT_MTUSIZE = 26 DHCP_OPT_LOCALSUBNETS = 27 DHCP_OPT_BROADCASTADDR = 28 DHCP_OPT_DOMASKDISCOV = 29 DHCP_OPT_MASKSUPPLY = 30 DHCP_OPT_DOROUTEDISC = 31 DHCP_OPT_ROUTERSOLICIT = 32 DHCP_OPT_STATICROUTE = 33 DHCP_OPT_TRAILERENCAP = 34 DHCP_OPT_ARPTIMEOUT = 35 DHCP_OPT_ETHERENCAP = 36 DHCP_OPT_TCPTTL = 37 DHCP_OPT_TCPKEEPALIVE = 38 DHCP_OPT_TCPALIVEGARBAGE = 39 DHCP_OPT_NISDOMAIN = 40 DHCP_OPT_NISSERVERS = 41 DHCP_OPT_NISTIMESERV = 42 DHCP_OPT_VENDSPECIFIC = 43 DHCP_OPT_NBNS = 44 DHCP_OPT_NBDD = 45 DHCP_OPT_NBTCPIP = 46 DHCP_OPT_NBTCPSCOPE = 47 DHCP_OPT_XFONT = 48 DHCP_OPT_XDISPLAYMGR = 49 DHCP_OPT_REQ_IP = 50 # I: IP address DHCP_OPT_LEASE_SEC = 51 # I: lease seconds DHCP_OPT_OPTIONOVERLOAD = 52 DHCP_OPT_MSGTYPE = 53 # B: message type DHCP_OPT_SERVER_ID = 54 # I: server IP address DHCP_OPT_PARAM_REQ = 55 # s: list of option codes DHCP_OPT_MESSAGE = 56 DHCP_OPT_MAXMSGSIZE = 57 DHCP_OPT_RENEWTIME = 58 DHCP_OPT_REBINDTIME = 59 DHCP_OPT_VENDOR_ID = 60 # s: vendor class id DHCP_OPT_CLIENT_ID = 61 # Bs: idtype, id (idtype 0: FQDN, idtype 1: MAC) DHCP_OPT_NISPLUSDOMAIN = 64 DHCP_OPT_NISPLUSSERVERS = 65 DHCP_OPT_MOBILEIPAGENT = 68 DHCP_OPT_SMTPSERVER = 69 DHCP_OPT_POP3SERVER = 70 DHCP_OPT_NNTPSERVER = 71 DHCP_OPT_WWWSERVER = 72 DHCP_OPT_FINGERSERVER = 73 DHCP_OPT_IRCSERVER = 74 DHCP_OPT_STSERVER = 75 DHCP_OPT_STDASERVER = 76 # DHCP message type values DHCPDISCOVER = 1 DHCPOFFER = 2 DHCPREQUEST = 3 DHCPDECLINE = 4 DHCPACK = 5 DHCPNAK = 6 DHCPRELEASE = 7 DHCPINFORM = 8 class DHCP(dpkt.Packet): """Dynamic Host Configuration Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of DHCP. TODO. """ __hdr__ = ( ('op', 'B', DHCP_OP_REQUEST), ('hrd', 'B', arp.ARP_HRD_ETH), # just like ARP.hrd ('hln', 'B', 6), # and ARP.hln ('hops', 'B', 0), ('xid', 'I', 0xdeadbeef), ('secs', 'H', 0), ('flags', 'H', 0), ('ciaddr', 'I', 0), ('yiaddr', 'I', 0), ('siaddr', 'I', 0), ('giaddr', 'I', 0), ('chaddr', '16s', 16 * b'\x00'), ('sname', '64s', 64 * b'\x00'), ('file', '128s', 128 * b'\x00'), ('magic', 'I', DHCP_MAGIC), ) opts = ( (DHCP_OPT_MSGTYPE, chr(DHCPDISCOVER)), (DHCP_OPT_PARAM_REQ, ''.join(map(chr, (DHCP_OPT_REQ_IP, DHCP_OPT_ROUTER, DHCP_OPT_NETMASK, DHCP_OPT_DNS_SVRS)))) ) # list of (type, data) tuples def __len__(self): return self.__hdr_len__ + \ sum([2 + len(o[1]) for o in self.opts]) + 1 + len(self.data) def __bytes__(self): return self.pack_hdr() + self.pack_opts() + bytes(self.data) def pack_opts(self): """Return packed options string.""" if not self.opts: return b'' l = [] for t, data in self.opts: l.append(struct.pack("BB%is"%len(data), t, len(data), data)) l.append(b'\xff') return b''.join(l) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.chaddr = self.chaddr[:self.hln] buf = self.data l = [] while buf: t = compat_ord(buf[0]) if t == 0xff: buf = buf[1:] break elif t == 0: buf = buf[1:] else: n = compat_ord(buf[1]) l.append((t, buf[2:2 + n])) buf = buf[2 + n:] self.opts = l self.data = buf def test_dhcp(): s = b'\x01\x01\x06\x00\xadS\xc8c\xb8\x87\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02U\x82\xf3\xa6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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\xfb\x01\x01=\x07\x01\x00\x02U\x82\xf3\xa62\x04\n\x00\x01e\x0c\tGuinevere<\x08MSFT 5.07\n\x01\x0f\x03\x06,./\x1f!+\xff\x00\x00\x00\x00\x00' dhcp = DHCP(s) assert (s == bytes(dhcp)) assert isinstance(dhcp.chaddr, bytes) assert isinstance(dhcp.sname, bytes) assert isinstance(dhcp.file, bytes) # Test default construction dhcp = DHCP() assert isinstance(dhcp.chaddr, bytes) assert isinstance(dhcp.sname, bytes) assert isinstance(dhcp.file, bytes) if __name__ == '__main__': test_dhcp() print('Tests Successful...') dpkt-1.9.2/dpkt/diameter.py000066400000000000000000000131011340335175100155710ustar00rootroot00000000000000# $Id: diameter.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Diameter.""" from __future__ import print_function from __future__ import absolute_import import struct from . import dpkt from .decorators import deprecated from .compat import compat_ord # Diameter Base Protocol - RFC 3588 # http://tools.ietf.org/html/rfc3588 # Request/Answer Command Codes ABORT_SESSION = 274 ACCOUTING = 271 CAPABILITIES_EXCHANGE = 257 DEVICE_WATCHDOG = 280 DISCONNECT_PEER = 282 RE_AUTH = 258 SESSION_TERMINATION = 275 class Diameter(dpkt.Packet): """Diameter. TODO: Longer class information.... Attributes: __hdr__: Header fields of Diameter. TODO. """ __hdr__ = ( ('v', 'B', 1), ('len', '3s', 0), ('flags', 'B', 0), ('cmd', '3s', 0), ('app_id', 'I', 0), ('hop_id', 'I', 0), ('end_id', 'I', 0) ) @property def request_flag(self): return (self.flags >> 7) & 0x1 @request_flag.setter def request_flag(self, r): self.flags = (self.flags & ~0x80) | ((r & 0x1) << 7) @property def proxiable_flag(self): return (self.flags >> 6) & 0x1 @proxiable_flag.setter def proxiable_flag(self, p): self.flags = (self.flags & ~0x40) | ((p & 0x1) << 6) @property def error_flag(self): return (self.flags >> 5) & 0x1 @error_flag.setter def error_flag(self, e): self.flags = (self.flags & ~0x20) | ((e & 0x1) << 5) @property def retransmit_flag(self): return (self.flags >> 4) & 0x1 @retransmit_flag.setter def retransmit_flag(self, t): self.flags = (self.flags & ~0x10) | ((t & 0x1) << 4) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.cmd = (compat_ord(self.cmd[0]) << 16) | \ (compat_ord(self.cmd[1]) << 8) | \ (compat_ord(self.cmd[2])) self.len = (compat_ord(self.len[0]) << 16) | \ (compat_ord(self.len[1]) << 8) | \ (compat_ord(self.len[2])) self.data = self.data[:self.len - self.__hdr_len__] l = [] while self.data: avp = AVP(self.data) l.append(avp) self.data = self.data[len(avp):] self.data = self.avps = l def pack_hdr(self): self.len = struct.pack("BBB", (self.len >> 16) & 0xff, (self.len >> 8) & 0xff, self.len & 0xff) self.cmd = struct.pack("BBB", (self.cmd >> 16) & 0xff, (self.cmd >> 8) & 0xff, self.cmd & 0xff) return dpkt.Packet.pack_hdr(self) def __len__(self): return self.__hdr_len__ + sum(map(len, self.data)) def __bytes__(self): return self.pack_hdr() + b''.join(map(bytes, self.data)) class AVP(dpkt.Packet): __hdr__ = ( ('code', 'I', 0), ('flags', 'B', 0), ('len', '3s', 0), ) @property def vendor_flag(self): return (self.flags >> 7) & 0x1 @vendor_flag.setter def vendor_flag(self, v): self.flags = (self.flags & ~0x80) | ((v & 0x1) << 7) @property def mandatory_flag(self): return (self.flags >> 6) & 0x1 @mandatory_flag.setter def mandatory_flag(self, m): self.flags = (self.flags & ~0x40) | ((m & 0x1) << 6) @property def protected_flag(self): return (self.flags >> 5) & 0x1 @protected_flag.setter def protected_flag(self, p): self.flags = (self.flags & ~0x20) | ((p & 0x1) << 5) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.len = (compat_ord(self.len[0]) << 16) | \ (compat_ord(self.len[1]) << 8) | \ (compat_ord(self.len[2])) if self.vendor_flag: self.vendor = struct.unpack('>I', self.data[:4])[0] self.data = self.data[4:self.len - self.__hdr_len__] else: self.data = self.data[:self.len - self.__hdr_len__] def pack_hdr(self): self.len = struct.pack("BBB", (self.len >> 16) & 0xff, (self.len >> 8) & 0xff, self.len & 0xff) data = dpkt.Packet.pack_hdr(self) if self.vendor_flag: data += struct.pack('>I', self.vendor) return data def __len__(self): length = self.__hdr_len__ + len(self.data) if self.vendor_flag: length += 4 return length __s = b'\x01\x00\x00\x28\x80\x00\x01\x18\x00\x00\x00\x00\x00\x00\x41\xc8\x00\x00\x00\x0c\x00\x00\x01\x08\x40\x00\x00\x0c\x68\x30\x30\x32\x00\x00\x01\x28\x40\x00\x00\x08' __t = b'\x01\x00\x00\x2c\x80\x00\x01\x18\x00\x00\x00\x00\x00\x00\x41\xc8\x00\x00\x00\x0c\x00\x00\x01\x08\xc0\x00\x00\x10\xde\xad\xbe\xef\x68\x30\x30\x32\x00\x00\x01\x28\x40\x00\x00\x08' def test_pack(): d = Diameter(__s) assert (__s == bytes(d)) d = Diameter(__t) assert (__t == bytes(d)) def test_unpack(): d = Diameter(__s) assert (d.len == 40) # assert (d.cmd == DEVICE_WATCHDOG_REQUEST) assert (d.request_flag == 1) assert (d.error_flag == 0) assert (len(d.avps) == 2) avp = d.avps[0] # assert (avp.code == ORIGIN_HOST) assert (avp.mandatory_flag == 1) assert (avp.vendor_flag == 0) assert (avp.len == 12) assert (len(avp) == 12) assert (avp.data == b'\x68\x30\x30\x32') # also test the optional vendor id support d = Diameter(__t) assert (d.len == 44) avp = d.avps[0] assert (avp.vendor_flag == 1) assert (avp.len == 16) assert (len(avp) == 16) assert (avp.vendor == 3735928559) assert (avp.data == b'\x68\x30\x30\x32') if __name__ == '__main__': test_pack() test_unpack() print('Tests Successful...') dpkt-1.9.2/dpkt/dns.py000066400000000000000000000412571340335175100146000ustar00rootroot00000000000000# $Id: dns.py 27 2006-11-21 01:22:52Z dahelder $ # -*- coding: utf-8 -*- """Domain Name System.""" from __future__ import print_function from __future__ import absolute_import import struct import codecs from . import dpkt from .decorators import deprecated from .compat import compat_ord DNS_Q = 0 DNS_R = 1 # Opcodes DNS_QUERY = 0 DNS_IQUERY = 1 DNS_STATUS = 2 DNS_NOTIFY = 4 DNS_UPDATE = 5 # Flags DNS_CD = 0x0010 # checking disabled DNS_AD = 0x0020 # authenticated data DNS_Z = 0x0040 # unused DNS_RA = 0x0080 # recursion available DNS_RD = 0x0100 # recursion desired DNS_TC = 0x0200 # truncated DNS_AA = 0x0400 # authoritative answer DNS_QR = 0x8000 # response ( query / response ) # Response codes DNS_RCODE_NOERR = 0 DNS_RCODE_FORMERR = 1 DNS_RCODE_SERVFAIL = 2 DNS_RCODE_NXDOMAIN = 3 DNS_RCODE_NOTIMP = 4 DNS_RCODE_REFUSED = 5 DNS_RCODE_YXDOMAIN = 6 DNS_RCODE_YXRRSET = 7 DNS_RCODE_NXRRSET = 8 DNS_RCODE_NOTAUTH = 9 DNS_RCODE_NOTZONE = 10 # RR types DNS_A = 1 DNS_NS = 2 DNS_CNAME = 5 DNS_SOA = 6 DNS_NULL = 10 DNS_PTR = 12 DNS_HINFO = 13 DNS_MX = 15 DNS_TXT = 16 DNS_AAAA = 28 DNS_SRV = 33 DNS_OPT = 41 # RR classes DNS_IN = 1 DNS_CHAOS = 3 DNS_HESIOD = 4 DNS_ANY = 255 def pack_name(name, off, label_ptrs): name = codecs.encode(name, 'utf-8') if name: labels = name.split(b'.') else: labels = [] labels.append(b'') buf = b'' for i, label in enumerate(labels): key = b'.'.join(labels[i:]).upper() ptr = label_ptrs.get(key) if not ptr: if len(key) > 1: ptr = off + len(buf) if ptr < 0xc000: label_ptrs[key] = ptr i = len(label) buf += struct.pack("B", i) + label else: buf += struct.pack('>H', (0xc000 | ptr)) break return buf def unpack_name(buf, off): name = [] saved_off = 0 start_off = off name_length = 0 while True: if off >= len(buf): raise dpkt.NeedData() n = compat_ord(buf[off]) if n == 0: off += 1 break elif (n & 0xc0) == 0xc0: ptr = struct.unpack('>H', buf[off:off + 2])[0] & 0x3fff if ptr >= start_off: raise dpkt.UnpackError('Invalid label compression pointer') off += 2 if not saved_off: saved_off = off start_off = off = ptr elif (n & 0xc0) == 0x00: off += 1 name.append(buf[off:off + n]) name_length += n + 1 if name_length > 255: raise dpkt.UnpackError('name longer than 255 bytes') off += n else: raise dpkt.UnpackError('Invalid label length %02x' % n) if not saved_off: saved_off = off return codecs.decode(b'.'.join(name), 'utf-8'), saved_off class DNS(dpkt.Packet): """Domain Name System. TODO: Longer class information.... Attributes: __hdr__: Header fields of DNS. TODO. """ __hdr__ = ( ('id', 'H', 0), ('op', 'H', DNS_RD), # recursive query # XXX - lists of query, RR objects ('qd', 'H', []), ('an', 'H', []), ('ns', 'H', []), ('ar', 'H', []) ) @property def qr(self): return int((self.op & DNS_QR) == DNS_QR) @qr.setter def qr(self, v): if v: self.op |= DNS_QR else: self.op &= ~DNS_QR @property def opcode(self): return (self.op >> 11) & 0xf @opcode.setter def opcode(self, v): self.op = (self.op & ~0x7800) | ((v & 0xf) << 11) @property def aa(self): return int((self.op & DNS_AA) == DNS_AA) @aa.setter def aa(self, v): if v: self.op |= DNS_AA else: self.op &= ~DNS_AA @property def tc(self): return int((self.op & DNS_TC) == DNS_TC) @tc.setter def tc(self, v): if v: self.op |= DNS_TC else: self.op &= ~DNS_TC @property def rd(self): return int((self.op & DNS_RD) == DNS_RD) @rd.setter def rd(self, v): if v: self.op |= DNS_RD else: self.op &= ~DNS_RD @property def ra(self): return int((self.op & DNS_RA) == DNS_RA) @ra.setter def ra(self, v): if v: self.op |= DNS_RA else: self.op &= ~DNS_RA @property def zero(self): return int((self.op & DNS_Z) == DNS_Z) @zero.setter def zero(self, v): if v: self.op |= DNS_Z else: self.op &= ~DNS_Z @property def rcode(self): return self.op & 0xf @rcode.setter def rcode(self, v): self.op = (self.op & ~0xf) | (v & 0xf) class Q(dpkt.Packet): """DNS question.""" __hdr__ = ( ('name', '1025s', b''), ('type', 'H', DNS_A), ('cls', 'H', DNS_IN) ) # XXX - suk def __len__(self): raise NotImplementedError __str__ = __len__ def unpack(self, buf): raise NotImplementedError class RR(Q): """DNS resource record.""" __hdr__ = ( ('name', '1025s', b''), ('type', 'H', DNS_A), ('cls', 'H', DNS_IN), ('ttl', 'I', 0), ('rlen', 'H', 4), ('rdata', 's', b'') ) def pack_rdata(self, off, label_ptrs): # XXX - yeah, this sux if self.rdata: return self.rdata if self.type == DNS_A: return self.ip elif self.type == DNS_NS: return pack_name(self.nsname, off, label_ptrs) elif self.type == DNS_CNAME: return pack_name(self.cname, off, label_ptrs) elif self.type == DNS_PTR: return pack_name(self.ptrname, off, label_ptrs) elif self.type == DNS_SOA: l = [] l.append(pack_name(self.mname, off, label_ptrs)) l.append(pack_name(self.rname, off + len(l[0]), label_ptrs)) l.append(struct.pack('>IIIII', self.serial, self.refresh, self.retry, self.expire, self.minimum)) return b''.join(l) elif self.type == DNS_MX: return struct.pack('>H', self.preference) + \ pack_name(self.mxname, off + 2, label_ptrs) elif self.type == DNS_TXT or self.type == DNS_HINFO: return b''.join(struct.pack('B', len(x)) + x for x in self.text) elif self.type == DNS_AAAA: return self.ip6 elif self.type == DNS_SRV: return struct.pack('>HHH', self.priority, self.weight, self.port) + \ pack_name(self.srvname, off + 6, label_ptrs) elif self.type == DNS_OPT: return b'' # self.rdata else: raise dpkt.PackError('RR type %s is not supported' % self.type) def unpack_rdata(self, buf, off): if self.type == DNS_A: self.ip = self.rdata elif self.type == DNS_NS: self.nsname, off = unpack_name(buf, off) elif self.type == DNS_CNAME: self.cname, off = unpack_name(buf, off) elif self.type == DNS_PTR: self.ptrname, off = unpack_name(buf, off) elif self.type == DNS_SOA: self.mname, off = unpack_name(buf, off) self.rname, off = unpack_name(buf, off) self.serial, self.refresh, self.retry, self.expire, \ self.minimum = struct.unpack('>IIIII', buf[off:off + 20]) elif self.type == DNS_MX: self.preference = struct.unpack('>H', self.rdata[:2]) self.mxname, off = unpack_name(buf, off + 2) elif self.type == DNS_TXT or self.type == DNS_HINFO: self.text = [] buf = self.rdata while buf: n = compat_ord(buf[0]) self.text.append(codecs.decode(buf[1:1 + n], 'utf-8')) buf = buf[1 + n:] elif self.type == DNS_AAAA: self.ip6 = self.rdata elif self.type == DNS_NULL: self.null = codecs.encode(self.rdata, 'hex') elif self.type == DNS_SRV: self.priority, self.weight, self.port = struct.unpack('>HHH', self.rdata[:6]) self.srvname, off = unpack_name(buf, off + 6) elif self.type == DNS_OPT: pass # RFC-6891: OPT is a pseudo-RR not carrying any DNS data else: raise dpkt.UnpackError('RR type %s is not supported' % self.type) def pack_q(self, buf, q): """Append packed DNS question and return buf.""" return buf + pack_name(q.name, len(buf), self.label_ptrs) + struct.pack('>HH', q.type, q.cls) def unpack_q(self, buf, off): """Return DNS question and new offset.""" q = self.Q() q.name, off = unpack_name(buf, off) q.type, q.cls = struct.unpack('>HH', buf[off:off + 4]) off += 4 return q, off def pack_rr(self, buf, rr): """Append packed DNS RR and return buf.""" name = pack_name(rr.name, len(buf), self.label_ptrs) rdata = rr.pack_rdata(len(buf) + len(name) + 10, self.label_ptrs) return buf + name + struct.pack('>HHIH', rr.type, rr.cls, rr.ttl, len(rdata)) + rdata def unpack_rr(self, buf, off): """Return DNS RR and new offset.""" rr = self.RR() rr.name, off = unpack_name(buf, off) rr.type, rr.cls, rr.ttl, rdlen = struct.unpack('>HHIH', buf[off:off + 10]) off += 10 rr.rdata = buf[off:off + rdlen] rr.rlen = rdlen rr.unpack_rdata(buf, off) off += rdlen return rr, off def unpack(self, buf): dpkt.Packet.unpack(self, buf) off = self.__hdr_len__ cnt = self.qd # FIXME: This relies on this being properly set somewhere else self.qd = [] for _ in range(cnt): q, off = self.unpack_q(buf, off) self.qd.append(q) for x in ('an', 'ns', 'ar'): cnt = getattr(self, x, 0) setattr(self, x, []) for _ in range(cnt): rr, off = self.unpack_rr(buf, off) getattr(self, x).append(rr) self.data = b'' def __len__(self): # XXX - cop out return len(bytes(self)) def __bytes__(self): # XXX - compress names on the fly self.label_ptrs = {} buf = struct.pack(self.__hdr_fmt__, self.id, self.op, len(self.qd), len(self.an), len(self.ns), len(self.ar)) for q in self.qd: buf = self.pack_q(buf, q) for x in ('an', 'ns', 'ar'): for rr in getattr(self, x): buf = self.pack_rr(buf, rr) del self.label_ptrs return buf def test_basic(): from . import ip s = b'E\x00\x02\x08\xc15\x00\x00\x80\x11\x92aBk0\x01Bk0w\x005\xc07\x01\xf4\xda\xc2d\xd2\x81\x80\x00\x01\x00\x03\x00\x0b\x00\x0b\x03www\x06google\x03com\x00\x00\x01\x00\x01\xc0\x0c\x00\x05\x00\x01\x00\x00\x03V\x00\x17\x03www\x06google\x06akadns\x03net\x00\xc0,\x00\x01\x00\x01\x00\x00\x01\xa3\x00\x04@\xe9\xabh\xc0,\x00\x01\x00\x01\x00\x00\x01\xa3\x00\x04@\xe9\xabc\xc07\x00\x02\x00\x01\x00\x00KG\x00\x0c\x04usw5\x04akam\xc0>\xc07\x00\x02\x00\x01\x00\x00KG\x00\x07\x04usw6\xc0t\xc07\x00\x02\x00\x01\x00\x00KG\x00\x07\x04usw7\xc0t\xc07\x00\x02\x00\x01\x00\x00KG\x00\x08\x05asia3\xc0t\xc07\x00\x02\x00\x01\x00\x00KG\x00\x05\x02za\xc07\xc07\x00\x02\x00\x01\x00\x00KG\x00\x0f\x02zc\x06akadns\x03org\x00\xc07\x00\x02\x00\x01\x00\x00KG\x00\x05\x02zf\xc07\xc07\x00\x02\x00\x01\x00\x00KG\x00\x05\x02zh\xc0\xd5\xc07\x00\x02\x00\x01\x00\x00KG\x00\x07\x04eur3\xc0t\xc07\x00\x02\x00\x01\x00\x00KG\x00\x07\x04use2\xc0t\xc07\x00\x02\x00\x01\x00\x00KG\x00\x07\x04use4\xc0t\xc0\xc1\x00\x01\x00\x01\x00\x00\xfb4\x00\x04\xd0\xb9\x84\xb0\xc0\xd2\x00\x01\x00\x01\x00\x001\x0c\x00\x04?\xf1\xc76\xc0\xed\x00\x01\x00\x01\x00\x00\xfb4\x00\x04?\xd7\xc6S\xc0\xfe\x00\x01\x00\x01\x00\x001\x0c\x00\x04?\xd00.\xc1\x0f\x00\x01\x00\x01\x00\x00\n\xdf\x00\x04\xc1-\x01g\xc1"\x00\x01\x00\x01\x00\x00\x101\x00\x04?\xd1\xaa\x88\xc15\x00\x01\x00\x01\x00\x00\r\x1a\x00\x04PCC\xb6\xc0o\x00\x01\x00\x01\x00\x00\x10\x7f\x00\x04?\xf1I\xd6\xc0\x87\x00\x01\x00\x01\x00\x00\n\xdf\x00\x04\xce\x84dl\xc0\x9a\x00\x01\x00\x01\x00\x00\n\xdf\x00\x04A\xcb\xea\x1b\xc0\xad\x00\x01\x00\x01\x00\x00\x0b)\x00\x04\xc1l\x9a\t' ip = ip.IP(s) my_dns = DNS(ip.udp.data) assert my_dns.qd[0].name == 'www.google.com' and my_dns.an[1].name == 'www.google.akadns.net' s = b'\x05\xf5\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x03cnn\x03com\x00\x00\x01\x00\x01' my_dns = DNS(s) assert s == bytes(my_dns) def test_PTR(): s = b'g\x02\x81\x80\x00\x01\x00\x01\x00\x03\x00\x00\x011\x011\x03211\x03141\x07in-addr\x04arpa\x00\x00\x0c\x00\x01\xc0\x0c\x00\x0c\x00\x01\x00\x00\r6\x00$\x07default\nv-umce-ifs\x05umnet\x05umich\x03edu\x00\xc0\x0e\x00\x02\x00\x01\x00\x00\r6\x00\r\x06shabby\x03ifs\xc0O\xc0\x0e\x00\x02\x00\x01\x00\x00\r6\x00\x0f\x0cfish-license\xc0m\xc0\x0e\x00\x02\x00\x01\x00\x00\r6\x00\x0b\x04dns2\x03itd\xc0O' my_dns = DNS(s) assert my_dns.qd[0].name == '1.1.211.141.in-addr.arpa' and \ my_dns.an[0].ptrname == 'default.v-umce-ifs.umnet.umich.edu' and \ my_dns.ns[0].nsname == 'shabby.ifs.umich.edu' and \ my_dns.ns[1].ttl == 3382 and \ my_dns.ns[2].nsname == 'dns2.itd.umich.edu' assert s == bytes(my_dns) def test_OPT(): s = b'\x8dn\x01\x10\x00\x01\x00\x00\x00\x00\x00\x01\x04x111\x06xxxx11\x06akamai\x03net\x00\x00\x01\x00\x01\x00\x00)\x0f\xa0\x00\x00\x80\x00\x00\x00' my_dns = DNS(s) my_rr = my_dns.ar[0] assert my_rr.type == DNS_OPT assert my_rr.rlen == 0 and my_rr.rdata == b'' assert bytes(my_dns) == s my_rr.rdata = b'\x00\x00\x00\x02\x00\x00' # add 1 attribute tlv my_dns2 = DNS(bytes(my_dns)) my_rr2 = my_dns2.ar[0] assert my_rr2.rlen == 6 and my_rr2.rdata == b'\x00\x00\x00\x02\x00\x00' def test_pack_name(): # Empty name is \0 x = pack_name('', 0, {}) assert x == b'\0' def test_random_data(): try: DNS(b'\x83z0\xd2\x9a\xec\x94_7\xf3\xb7+\x85"?\xf0\xfb') except dpkt.UnpackError: pass except: assert False else: assert False def test_circular_pointers(): try: DNS(b'\xc0\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\x03com\xc0\x00') except dpkt.UnpackError: pass except: assert False else: assert False def test_very_long_name(): try: DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00' + (b'\x10abcdef0123456789' * 16) + b'\x00') except dpkt.UnpackError: pass except: assert False else: assert False def test_null_response(): s = b'\x12\xb0\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x0bblahblah666\x06pirate\x03sea\x00\x00\n\x00\x01\xc0\x0c\x00\n\x00\x01\x00\x00\x00\x00\x00\tVACKD\x03\xc5\xe9\x01' my_dns = DNS(s) assert my_dns.qd[0].name == 'blahblah666.pirate.sea' and \ my_dns.an[0].null == b'5641434b4403c5e901' assert str(s) == str(my_dns) def test_txt_response(): buf = ( b'\x10\x32\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00\x06\x67\x6f\x6f\x67\x6c\x65\x03\x63\x6f' b'\x6d\x00\x00\x10\x00\x01\xc0\x0c\x00\x10\x00\x01\x00\x00\x01\x0e\x00\x10\x0f\x76\x3d\x73' b'\x70\x66\x31\x20\x70\x74\x72\x20\x3f\x61\x6c\x6c') my_dns = DNS(buf) my_rr = my_dns.an[0] assert my_rr.type == DNS_TXT assert my_rr.name == 'google.com' assert my_rr.text == ['v=spf1 ptr ?all'] assert str(my_dns) == str(buf) assert bytes(my_dns) == buf def test_rdata_TXT(): rr = DNS.RR( type=DNS_TXT, text=[b'v=spf1 ptr ?all', b'a=something'] ) packdata = rr.pack_rdata(0, {}) correct = b'\x0fv=spf1 ptr ?all\x0ba=something' assert packdata == correct def test_rdata_HINFO(): rr = DNS.RR( type=DNS_HINFO, text=[b'v=spf1 ptr ?all', b'a=something'] ) packdata = rr.pack_rdata(0, {}) correct = b'\x0fv=spf1 ptr ?all\x0ba=something' assert packdata == correct def test_dns_len(): my_dns = DNS() assert len(my_dns) == 12 if __name__ == '__main__': # Runs all the test associated with this class/file test_basic() test_PTR() test_OPT() test_pack_name() test_random_data() test_circular_pointers() test_very_long_name() test_null_response() test_txt_response() test_deprecated_methods() test_deprecated_method_performance() print('Tests Successful...') dpkt-1.9.2/dpkt/dpkt.py000066400000000000000000000160701340335175100147510ustar00rootroot00000000000000# $Id: dpkt.py 43 2007-08-02 22:42:59Z jon.oberheide $ # -*- coding: utf-8 -*- """Simple packet creation and parsing.""" from __future__ import absolute_import import copy import itertools import socket import struct import array from .compat import compat_ord, compat_izip, iteritems class Error(Exception): pass class UnpackError(Error): pass class NeedData(UnpackError): pass class PackError(Error): pass class _MetaPacket(type): def __new__(cls, clsname, clsbases, clsdict): t = type.__new__(cls, clsname, clsbases, clsdict) st = getattr(t, '__hdr__', None) if st is not None: # XXX - __slots__ only created in __new__() clsdict['__slots__'] = [x[0] for x in st] + ['data'] t = type.__new__(cls, clsname, clsbases, clsdict) t.__hdr_fields__ = [x[0] for x in st] t.__hdr_fmt__ = getattr(t, '__byte_order__', '>') + ''.join([x[1] for x in st]) t.__hdr_len__ = struct.calcsize(t.__hdr_fmt__) t.__hdr_defaults__ = dict(compat_izip( t.__hdr_fields__, [x[2] for x in st])) return t class Packet(_MetaPacket("Temp", (object,), {})): """Base packet class, with metaclass magic to generate members from self.__hdr__. Attributes: __hdr__: Packet header should be defined as a list of (name, structfmt, default) tuples. __byte_order__: Byte order, can be set to override the default ('>') Example: >>> class Foo(Packet): ... __hdr__ = (('foo', 'I', 1), ('bar', 'H', 2), ('baz', '4s', 'quux')) ... >>> foo = Foo(bar=3) >>> foo Foo(bar=3) >>> str(foo) '\x00\x00\x00\x01\x00\x03quux' >>> foo.bar 3 >>> foo.baz 'quux' >>> foo.foo = 7 >>> foo.baz = 'whee' >>> foo Foo(baz='whee', foo=7, bar=3) >>> Foo('hello, world!') Foo(baz=' wor', foo=1751477356L, bar=28460, data='ld!') """ def __init__(self, *args, **kwargs): """Packet constructor with ([buf], [field=val,...]) prototype. Arguments: buf -- optional packet buffer to unpack Optional keyword arguments correspond to members to set (matching fields in self.__hdr__, or 'data'). """ self.data = b'' if args: try: self.unpack(args[0]) except struct.error: if len(args[0]) < self.__hdr_len__: raise NeedData raise UnpackError('invalid %s: %r' % (self.__class__.__name__, args[0])) else: for k in self.__hdr_fields__: setattr(self, k, copy.copy(self.__hdr_defaults__[k])) for k, v in iteritems(kwargs): setattr(self, k, v) def __len__(self): return self.__hdr_len__ + len(self.data) def __getitem__(self, k): try: return getattr(self, k) except AttributeError: raise KeyError def __repr__(self): # Collect and display protocol fields in order: # 1. public fields defined in __hdr__, unless their value is default # 2. properties derived from _private fields defined in __hdr__ # 3. dynamically added fields from self.__dict__, unless they are _private # 4. self.data when it's present l = [] # maintain order of fields as defined in __hdr__ for field_name, _, _ in getattr(self, '__hdr__', []): field_value = getattr(self, field_name) if field_value != self.__hdr_defaults__[field_name]: if field_name[0] != '_': l.append('%s=%r' % (field_name, field_value)) # (1) else: # interpret _private fields as name of properties joined by underscores for prop_name in field_name.split('_'): # (2) if isinstance(getattr(self.__class__, prop_name, None), property): l.append('%s=%r' % (prop_name, getattr(self, prop_name))) # (3) l.extend( ['%s=%r' % (attr_name, attr_value) for attr_name, attr_value in iteritems(self.__dict__) if attr_name[0] != '_' # exclude _private attributes and attr_name != self.data.__class__.__name__.lower()]) # exclude fields like ip.udp # (4) if self.data: l.append('data=%r' % self.data) return '%s(%s)' % (self.__class__.__name__, ', '.join(l)) def __str__(self): return str(self.__bytes__()) def __bytes__(self): return self.pack_hdr() + bytes(self.data) def pack_hdr(self): """Return packed header string.""" try: return struct.pack(self.__hdr_fmt__, *[getattr(self, k) for k in self.__hdr_fields__]) except struct.error: vals = [] for k in self.__hdr_fields__: v = getattr(self, k) if isinstance(v, tuple): vals.extend(v) else: vals.append(v) try: return struct.pack(self.__hdr_fmt__, *vals) except struct.error as e: raise PackError(str(e)) def pack(self): """Return packed header + self.data string.""" return bytes(self) def unpack(self, buf): """Unpack packet header fields from buf, and set self.data.""" for k, v in compat_izip(self.__hdr_fields__, struct.unpack(self.__hdr_fmt__, buf[:self.__hdr_len__])): setattr(self, k, v) self.data = buf[self.__hdr_len__:] # XXX - ''.join([(len(`chr(x)`)==3) and chr(x) or '.' for x in range(256)]) __vis_filter = b'................................ !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[.]^_`abcdefghijklmnopqrstuvwxyz{|}~.................................................................................................................................' def hexdump(buf, length=16): """Return a hexdump output string of the given buffer.""" n = 0 res = [] while buf: line, buf = buf[:length], buf[length:] hexa = ' '.join(['%02x' % compat_ord(x) for x in line]) line = line.translate(__vis_filter).decode('utf-8') res.append(' %04d: %-*s %s' % (n, length * 3, hexa, line)) n += length return '\n'.join(res) def in_cksum_add(s, buf): n = len(buf) cnt = (n // 2) * 2 a = array.array('H', buf[:cnt]) if cnt != n: a.append(compat_ord(buf[-1])) return s + sum(a) def in_cksum_done(s): s = (s >> 16) + (s & 0xffff) s += (s >> 16) return socket.ntohs(~s & 0xffff) def in_cksum(buf): """Return computed Internet checksum.""" return in_cksum_done(in_cksum_add(0, buf)) def test_utils(): __buf = b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e' __hd = ' 0000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e ...............' h = hexdump(__buf) assert (h == __hd) c = in_cksum(__buf) assert (c == 51150) dpkt-1.9.2/dpkt/dtp.py000066400000000000000000000013401340335175100145700ustar00rootroot00000000000000# $Id: dtp.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Dynamic Trunking Protocol.""" from __future__ import absolute_import import struct from . import dpkt class DTP(dpkt.Packet): """Dynamic Trunking Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of DTP. TODO. """ __hdr__ = ( ('v', 'B', 0), ) # rest is TLVs def unpack(self, buf): dpkt.Packet.unpack(self, buf) buf = self.data tvs = [] while buf: t, l = struct.unpack('>HH', buf[:4]) v, buf = buf[4:4 + l], buf[4 + l:] tvs.append((t, v)) self.data = tvs TRUNK_NAME = 0x01 MAC_ADDR = 0x04 dpkt-1.9.2/dpkt/edp.py000066400000000000000000000044321340335175100145560ustar00rootroot00000000000000"""Extreme Discovery Protocol.""" from __future__ import absolute_import import dpkt import sys class EDP(dpkt.Packet): __hdr__ = ( ('version', 'B', 1), ('reserved', 'B', 0), ('hlen', 'H', 0), ('sum', 'H', 0), ('seq', 'H', 0), ('mid', 'H', 0), ('mac', '6s', '') ) def __str__(self): if not self.sum: self.sum = dpkt.in_cksum(dpkt.Packet.__str__(self)) return dpkt.Packet.__str__(self) class TestEDP(object): """ Test basic EDP functionality. """ @classmethod def setup_class(cls): cls.p = EDP(b'\x01\x00\x01\x3c\x9e\x76\x00\x1b\x00\x00\x08\x00\x27-\x90\xed\x99\x02\x00$\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x02\x02\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99\x01\x01\x04EXOS-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\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99\x00\x00\x04') def test_version(self): assert (self.p.version == 1) def test_reserved(self): assert (self.p.reserved == 0) def test_hlen(self): assert (self.p.hlen == 316) def test_sum(self): assert (self.p.sum == 40566) def test_seq(self): assert (self.p.seq == 27) def test_mid(self): assert (self.p.mid == 0) def test_mac(self): assert (self.p.mac == b"\x08\x00'-\x90\xed") dpkt-1.9.2/dpkt/esp.py000066400000000000000000000006541340335175100145770ustar00rootroot00000000000000# $Id: esp.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Encapsulated Security Protocol.""" from __future__ import absolute_import from . import dpkt class ESP(dpkt.Packet): """Encapsulated Security Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of ESP. TODO. """ __hdr__ = ( ('spi', 'I', 0), ('seq', 'I', 0) ) dpkt-1.9.2/dpkt/ethernet.py000066400000000000000000000643211340335175100156270ustar00rootroot00000000000000# $Id: ethernet.py 65 2010-03-26 02:53:51Z dugsong $ # -*- coding: utf-8 -*- """Ethernet II, LLC (802.3+802.2), LLC/SNAP, and Novell raw 802.3, with automatic 802.1q, MPLS, PPPoE, and Cisco ISL decapsulation.""" from __future__ import print_function from __future__ import absolute_import import struct from zlib import crc32 from . import dpkt from . import llc from .compat import compat_ord, iteritems try: isinstance("", basestring) def isstr(s): return isinstance(s, basestring) except NameError: def isstr(s): return isinstance(s, str) ETH_CRC_LEN = 4 ETH_HDR_LEN = 14 ETH_LEN_MIN = 64 # minimum frame length with CRC ETH_LEN_MAX = 1518 # maximum frame length with CRC ETH_MTU = (ETH_LEN_MAX - ETH_HDR_LEN - ETH_CRC_LEN) ETH_MIN = (ETH_LEN_MIN - ETH_HDR_LEN - ETH_CRC_LEN) # Ethernet payload types - http://standards.ieee.org/regauth/ethertype ETH_TYPE_EDP = 0x00bb # Extreme Networks Discovery Protocol ETH_TYPE_PUP = 0x0200 # PUP protocol ETH_TYPE_IP = 0x0800 # IP protocol ETH_TYPE_ARP = 0x0806 # address resolution protocol ETH_TYPE_AOE = 0x88a2 # AoE protocol ETH_TYPE_CDP = 0x2000 # Cisco Discovery Protocol ETH_TYPE_DTP = 0x2004 # Cisco Dynamic Trunking Protocol ETH_TYPE_REVARP = 0x8035 # reverse addr resolution protocol ETH_TYPE_8021Q = 0x8100 # IEEE 802.1Q VLAN tagging ETH_TYPE_8021AD = 0x88a8 # IEEE 802.1ad ETH_TYPE_QINQ1 = 0x9100 # Legacy QinQ ETH_TYPE_QINQ2 = 0x9200 # Legacy QinQ ETH_TYPE_IPX = 0x8137 # Internetwork Packet Exchange ETH_TYPE_IP6 = 0x86DD # IPv6 protocol ETH_TYPE_PPP = 0x880B # PPP ETH_TYPE_MPLS = 0x8847 # MPLS ETH_TYPE_MPLS_MCAST = 0x8848 # MPLS Multicast ETH_TYPE_PPPoE_DISC = 0x8863 # PPP Over Ethernet Discovery Stage ETH_TYPE_PPPoE = 0x8864 # PPP Over Ethernet Session Stage ETH_TYPE_LLDP = 0x88CC # Link Layer Discovery Protocol ETH_TYPE_TEB = 0x6558 # Transparent Ethernet Bridging # all QinQ types for fast checking _ETH_TYPES_QINQ = frozenset([ETH_TYPE_8021Q, ETH_TYPE_8021AD, ETH_TYPE_QINQ1, ETH_TYPE_QINQ2]) class Ethernet(dpkt.Packet): """Ethernet. Ethernet II, LLC (802.3+802.2), LLC/SNAP, and Novell raw 802.3, with automatic 802.1q, MPLS, PPPoE, and Cisco ISL decapsulation. Attributes: __hdr__: Header fields of Ethernet. TODO. """ __hdr__ = ( ('dst', '6s', ''), ('src', '6s', ''), ('type', 'H', ETH_TYPE_IP) ) _typesw = {} _typesw_rev = {} # reverse mapping def __init__(self, *args, **kwargs): dpkt.Packet.__init__(self, *args, **kwargs) # if data was given in kwargs, try to unpack it if self.data: if isstr(self.data) or isinstance(self.data, bytes): self._unpack_data(self.data) def _unpack_data(self, buf): next_type = self.type # unpack vlan tag and mpls label stacks if next_type in _ETH_TYPES_QINQ: self.vlan_tags = [] # support up to 2 tags (double tagging aka QinQ) for _ in range(2): tag = VLANtag8021Q(buf) buf = buf[tag.__hdr_len__:] self.vlan_tags.append(tag) next_type = tag.type if next_type != ETH_TYPE_8021Q: break # backward compatibility, use the 1st tag self.vlanid, self.priority, self.cfi = self.vlan_tags[0].as_tuple() elif next_type == ETH_TYPE_MPLS or next_type == ETH_TYPE_MPLS_MCAST: self.labels = [] # old list containing labels as tuples self.mpls_labels = [] # new list containing labels as instances of MPLSlabel # XXX - max # of labels is undefined, just use 24 for i in range(24): lbl = MPLSlabel(buf) buf = buf[lbl.__hdr_len__:] self.mpls_labels.append(lbl) self.labels.append(lbl.as_tuple()) if lbl.s: # bottom of stack break # poor man's heuristics to guessing the next type if compat_ord(buf[0]) == 0x45: # IP version 4 + header len 20 bytes next_type = ETH_TYPE_IP # pseudowire Ethernet elif len(buf) >= self.__hdr_len__: if buf[:2] == b'\x00\x00': # looks like the control word (ECW) buf = buf[4:] # skip the ECW next_type = ETH_TYPE_TEB # re-use TEB class mapping to decode Ethernet try: self.data = self._typesw[next_type](buf) setattr(self, self.data.__class__.__name__.lower(), self.data) except (KeyError, dpkt.UnpackError): self.data = buf def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.type > 1500: # Ethernet II self._unpack_data(self.data) elif (self.dst.startswith(b'\x01\x00\x0c\x00\x00') or self.dst.startswith(b'\x03\x00\x0c\x00\x00')): # Cisco ISL tag = VLANtagISL(buf) buf = buf[tag.__hdr_len__:] self.vlan_tags = [tag] self.vlan = tag.id # backward compatibility self.unpack(buf) elif self.data.startswith(b'\xff\xff'): # Novell "raw" 802.3 self.type = ETH_TYPE_IPX self.data = self.ipx = self._typesw[ETH_TYPE_IPX](self.data[2:]) else: # IEEE 802.3 Ethernet - LLC # try to unpack FCS here; we follow the same heuristic approach as Wireshark: # if the upper layer len(self.data) can be fully decoded and returns its size, # and there's a difference with size in the Eth header, then assume the last # 4 bytes is the FCS and remaining bytes are a trailer. eth_len = self.len = self.type if len(self.data) > eth_len: tail_len = len(self.data) - eth_len if tail_len >= 4: # if the last 4 bytes are zeroes that's unlikely a FCS if self.data[-4:] == b'\x00\x00\x00\x00': self.trailer = self.data[eth_len:] else: self.fcs = struct.unpack('>I', self.data[-4:])[0] self.trailer = self.data[eth_len:-4] self.data = self.llc = llc.LLC(self.data[:eth_len]) def pack_hdr(self): tags_buf = b'' new_type = self.type is_isl = False # ISL wraps Ethernet, this determines order of packing if getattr(self, 'mpls_labels', None): # mark all labels with s=0, last one with s=1 for lbl in self.mpls_labels: lbl.s = 0 lbl.s = 1 # set encapsulation type if new_type not in (ETH_TYPE_MPLS, ETH_TYPE_MPLS_MCAST): new_type = ETH_TYPE_MPLS tags_buf = b''.join(lbl.pack_hdr() for lbl in self.mpls_labels) elif getattr(self, 'vlan_tags', None): # set encapsulation types t1 = self.vlan_tags[0] if len(self.vlan_tags) == 1: if isinstance(t1, VLANtag8021Q): if new_type not in _ETH_TYPES_QINQ: # preserve the type if already set new_type = ETH_TYPE_8021Q elif isinstance(t1, VLANtagISL): t1.type = 0 # 0 means Ethernet is_isl = True elif len(self.vlan_tags) == 2: t2 = self.vlan_tags[1] if isinstance(t1, VLANtag8021Q) and isinstance(t2, VLANtag8021Q): t1.type = ETH_TYPE_8021Q if new_type not in _ETH_TYPES_QINQ: new_type = ETH_TYPE_8021AD else: raise dpkt.PackError('maximum is 2 VLAN tags per Ethernet frame') tags_buf = b''.join(tag.pack_hdr() for tag in self.vlan_tags) # initial type is based on next layer, pointed by self.data; # try to find an ETH_TYPE matching the data class elif isinstance(self.data, dpkt.Packet): new_type = self._typesw_rev.get(self.data.__class__, new_type) # if self.data is LLC then this is IEEE 802.3 Ethernet and self.type # then actually encodes the length of data if isinstance(self.data, llc.LLC): new_type = len(self.data) hdr_buf = dpkt.Packet.pack_hdr(self)[:-2] + struct.pack('>H', new_type) if not is_isl: return hdr_buf + tags_buf else: return tags_buf + hdr_buf def __str__(self): tail = b'' if isinstance(self.data, llc.LLC): if hasattr(self, 'fcs'): if self.fcs: fcs = self.fcs else: # if fcs field is present but 0/None, then compute it and add to the tail fcs_buf = self.pack_hdr() + bytes(self.data) + getattr(self, 'trailer', '') # if ISL header is present, exclude it from the calculation if getattr(self, 'vlan_tags', None): if isinstance(self.vlan_tags[0], VLANtagISL): fcs_buf = fcs_buf[VLANtagISL.__hdr_len__:] revcrc = crc32(fcs_buf) & 0xffffffff fcs = struct.unpack('I', revcrc))[0] # bswap32 tail = getattr(self, 'trailer', b'') + struct.pack('>I', fcs) return str(dpkt.Packet.__bytes__(self) + tail) def __len__(self): tags = getattr(self, 'mpls_labels', []) + getattr(self, 'vlan_tags', []) _len = dpkt.Packet.__len__(self) + sum(t.__hdr_len__ for t in tags) if isinstance(self.data, llc.LLC) and hasattr(self, 'fcs'): _len += len(getattr(self, 'trailer', '')) + 4 return _len @classmethod def set_type(cls, t, pktclass): cls._typesw[t] = pktclass cls._typesw_rev[pktclass] = t @classmethod def get_type(cls, t): return cls._typesw[t] @classmethod def get_type_rev(cls, k): return cls._typesw_rev[k] # XXX - auto-load Ethernet dispatch table from ETH_TYPE_* definitions def __load_types(): g = globals() for k, v in iteritems(g): if k.startswith('ETH_TYPE_'): name = k[9:] modname = name.lower() try: mod = __import__(modname, g, level=1) Ethernet.set_type(v, getattr(mod, name)) except (ImportError, AttributeError): continue # add any special cases below Ethernet.set_type(ETH_TYPE_TEB, Ethernet) def _mod_init(): """Post-initialization called when all dpkt modules are fully loaded""" if not Ethernet._typesw: __load_types() # Misc protocols class MPLSlabel(dpkt.Packet): """A single entry in MPLS label stack""" __hdr__ = ( ('_val_exp_s_ttl', 'I', 0), ) # field names are according to RFC3032 def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.val = (self._val_exp_s_ttl & 0xfffff000) >> 12 # label value, 20 bits self.exp = (self._val_exp_s_ttl & 0x00000e00) >> 9 # experimental use, 3 bits self.s = (self._val_exp_s_ttl & 0x00000100) >> 8 # bottom of stack flag, 1 bit self.ttl = self._val_exp_s_ttl & 0x000000ff # time to live, 8 bits self.data = b'' def pack_hdr(self): self._val_exp_s_ttl = ( ((self.val & 0xfffff) << 12) | ((self.exp & 7) << 9) | ((self.s & 1) << 8) | ((self.ttl & 0xff)) ) return dpkt.Packet.pack_hdr(self) def as_tuple(self): # backward-compatible representation return (self.val, self.exp, self.ttl) class VLANtag8021Q(dpkt.Packet): """IEEE 802.1q VLAN tag""" __hdr__ = ( ('_pri_cfi_id', 'H', 0), ('type', 'H', ETH_TYPE_IP) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.pri = (self._pri_cfi_id & 0xe000) >> 13 # priority, 3 bits self.cfi = (self._pri_cfi_id & 0x1000) >> 12 # canonical format indicator, 1 bit self.id = self._pri_cfi_id & 0x0fff # VLAN id, 12 bits self.data = b'' def pack_hdr(self): self._pri_cfi_id = ( ((self.pri & 7) << 13) | ((self.cfi & 1) << 12) | ((self.id & 0xfff)) ) return dpkt.Packet.pack_hdr(self) def as_tuple(self): return (self.id, self.pri, self.cfi) class VLANtagISL(dpkt.Packet): """Cisco Inter-Switch Link VLAN tag""" __hdr__ = ( ('da', '5s', b'\x01\x00\x0c\x00\x00'), ('_type_pri', 'B', 3), ('sa', '6s', ''), ('len', 'H', 0), ('snap', '3s', b'\xaa\xaa\x03'), ('hsa', '3s', b'\x00\x00\x0c'), ('_id_bpdu', 'H', 0), ('indx', 'H', 0), ('res', 'H', 0) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.type = (self._type_pri & 0xf0) >> 4 # encapsulation type, 4 bits; 0 means Ethernet self.pri = self._type_pri & 0x03 # user defined bits, 2 bits are used; means priority self.id = self._id_bpdu >> 1 # VLAN id self.bpdu = self._id_bpdu & 1 self.data = b'' def pack_hdr(self): self._type_pri = ((self.type & 0xf) << 4) | (self.pri & 0x3) self._id_bpdu = ((self.id & 0x7fff) << 1) | (self.bpdu & 1) return dpkt.Packet.pack_hdr(self) # Unit tests def test_eth(): from . import ip # IPv6 needs this to build its protocol stack from . import ip6 from . import tcp s = (b'\x00\xb0\xd0\xe1\x80\x72\x00\x11\x24\x8c\x11\xde\x86\xdd\x60\x00\x00\x00' b'\x00\x28\x06\x40\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x11\x24\xff\xfe\x8c' b'\x11\xde\xfe\x80\x00\x00\x00\x00\x00\x00\x02\xb0\xd0\xff\xfe\xe1\x80\x72' b'\xcd\xd3\x00\x16\xff\x50\xd7\x13\x00\x00\x00\x00\xa0\x02\xff\xff\x67\xd3' b'\x00\x00\x02\x04\x05\xa0\x01\x03\x03\x00\x01\x01\x08\x0a\x7d\x18\x3a\x61' b'\x00\x00\x00\x00') eth = Ethernet(s) assert eth assert isinstance(eth.data, ip6.IP6) assert isinstance(eth.data.data, tcp.TCP) assert str(eth) == str(s) assert len(eth) == len(s) def test_eth_init_with_data(): # initialize with a data string, test that it gets unpacked from . import arp eth1 = Ethernet( dst=b'PQRSTU', src=b'ABCDEF', type=ETH_TYPE_ARP, data=b'\x00\x01\x08\x00\x06\x04\x00\x01123456abcd7890abwxyz') assert isinstance(eth1.data, arp.ARP) # now initialize with a class, test packing eth2 = Ethernet( dst=b'PQRSTU', src=b'ABCDEF', data=arp.ARP(sha=b'123456', spa=b'abcd', tha=b'7890ab', tpa=b'wxyz')) assert str(eth1) == str(eth2) assert len(eth1) == len(eth2) def test_mpls_label(): s = b'\x00\x01\x0b\xff' m = MPLSlabel(s) assert m.val == 16 assert m.exp == 5 assert m.s == 1 assert m.ttl == 255 assert str(m) == str(s) assert len(m) == len(s) def test_802dot1q_tag(): s = b'\xa0\x76\x01\x65' t = VLANtag8021Q(s) assert t.pri == 5 assert t.cfi == 0 assert t.id == 118 assert str(t) == str(s) t.cfi = 1 assert str(t) == str(b'\xb0\x76\x01\x65') assert len(t) == len(s) def test_isl_tag(): s = (b'\x01\x00\x0c\x00\x00\x03\x00\x02\xfd\x2c\xb8\x97\x00\x00\xaa\xaa\x03\x00\x00\x00\x04\x57' b'\x00\x00\x00\x00') t = VLANtagISL(s) assert t.pri == 3 assert t.id == 555 assert t.bpdu == 1 assert str(t) == str(s) assert len(t) == len(s) def test_eth_802dot1q(): from . import ip s = (b'\x00\x60\x08\x9f\xb1\xf3\x00\x40\x05\x40\xef\x24\x81\x00\x90\x20\x08' b'\x00\x45\x00\x00\x34\x3b\x64\x40\x00\x40\x06\xb7\x9b\x83\x97\x20\x81' b'\x83\x97\x20\x15\x04\x95\x17\x70\x51\xd4\xee\x9c\x51\xa5\x5b\x36\x80' b'\x10\x7c\x70\x12\xc7\x00\x00\x01\x01\x08\x0a\x00\x04\xf0\xd4\x01\x99' b'\xa3\xfd') eth = Ethernet(s) assert eth.cfi == 1 assert eth.vlanid == 32 assert eth.priority == 4 assert len(eth.vlan_tags) == 1 assert eth.vlan_tags[0].type == ETH_TYPE_IP assert isinstance(eth.data, ip.IP) # construction assert str(eth) == str(s), 'pack 1' assert str(eth) == str(s), 'pack 2' assert len(eth) == len(s) # construction with kwargs eth2 = Ethernet(src=eth.src, dst=eth.dst, vlan_tags=eth.vlan_tags, data=eth.data) assert str(eth2) == str(s) # construction w/o the tag del eth.vlan_tags, eth.cfi, eth.vlanid, eth.priority assert str(eth) == str(s[:12] + b'\x08\x00' + s[18:]) def test_eth_802dot1q_stacked(): # 2 VLAN tags from . import arp from . import ip s = (b'\x00\x1b\xd4\x1b\xa4\xd8\x00\x13\xc3\xdf\xae\x18\x81\x00\x00\x76\x81\x00\x00\x0a\x08\x00' b'\x45\x00\x00\x64\x00\x0f\x00\x00\xff\x01\x92\x9b\x0a\x76\x0a\x01\x0a\x76\x0a\x02\x08\x00' b'\xce\xb7\x00\x03\x00\x00\x00\x00\x00\x00\x00\x1f\xaf\x70\xab\xcd\xab\xcd\xab\xcd\xab\xcd' b'\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd' b'\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd' b'\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd') eth = Ethernet(s) assert eth.type == ETH_TYPE_8021Q assert len(eth.vlan_tags) == 2 assert eth.vlan_tags[0].id == 118 assert eth.vlan_tags[1].id == 10 assert eth.vlan_tags[0].type == ETH_TYPE_8021Q assert eth.vlan_tags[1].type == ETH_TYPE_IP assert [t.as_tuple() for t in eth.vlan_tags] == [(118, 0, 0), (10, 0, 0)] assert isinstance(eth.data, ip.IP) # construction assert str(eth) == str(s), 'pack 1' assert str(eth) == str(s), 'pack 2' assert len(eth) == len(s) # construction with kwargs eth2 = Ethernet(src=eth.src, dst=eth.dst, vlan_tags=eth.vlan_tags, data=eth.data) # construction sets ip.type to 802.1ad instead of 802.1q so account for it assert str(eth2) == str(s[:12] + b'\x88\xa8' + s[14:]) # construction w/o the tags del eth.vlan_tags, eth.cfi, eth.vlanid, eth.priority assert str(eth) == str(s[:12] + b'\x08\x00' + s[22:]) # 2 VLAN tags + ARP s = (b'\xff\xff\xff\xff\xff\xff\xca\x03\x0d\xb4\x00\x1c\x81\x00\x00\x64\x81\x00\x00\xc8\x08\x06' b'\x00\x01\x08\x00\x06\x04\x00\x01\xca\x03\x0d\xb4\x00\x1c\xc0\xa8\x02\xc8\x00\x00\x00\x00' b'\x00\x00\xc0\xa8\x02\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') eth = Ethernet(s) assert len(eth.vlan_tags) == 2 assert eth.vlan_tags[0].type == ETH_TYPE_8021Q assert eth.vlan_tags[1].type == ETH_TYPE_ARP assert isinstance(eth.data, arp.ARP) def test_eth_mpls_stacked(): # Eth - MPLS - MPLS - IP - ICMP from . import ip from . import icmp s = (b'\x00\x30\x96\xe6\xfc\x39\x00\x30\x96\x05\x28\x38\x88\x47\x00\x01\x20\xff\x00\x01\x01\xff' b'\x45\x00\x00\x64\x00\x50\x00\x00\xff\x01\xa7\x06\x0a\x1f\x00\x01\x0a\x22\x00\x01\x08\x00' b'\xbd\x11\x0f\x65\x12\xa0\x00\x00\x00\x00\x00\x53\x9e\xe0' + b'\xab\xcd' * 32) eth = Ethernet(s) assert len(eth.mpls_labels) == 2 assert eth.mpls_labels[0].val == 18 assert eth.mpls_labels[1].val == 16 assert eth.labels == [(18, 0, 255), (16, 0, 255)] assert isinstance(eth.data, ip.IP) assert isinstance(eth.data.data, icmp.ICMP) # construction assert str(eth) == str(s), 'pack 1' assert str(eth) == str(s), 'pack 2' assert len(eth) == len(s) # construction with kwargs eth2 = Ethernet(src=eth.src, dst=eth.dst, mpls_labels=eth.mpls_labels, data=eth.data) assert str(eth2) == str(s) # construction w/o labels del eth.labels, eth.mpls_labels assert str(eth) == str(s[:12] + b'\x08\x00' + s[22:]) def test_isl_eth_llc_stp(): # ISL - 802.3 Ethernet(w/FCS) - LLC - STP from . import stp s = (b'\x01\x00\x0c\x00\x00\x03\x00\x02\xfd\x2c\xb8\x97\x00\x00\xaa\xaa\x03\x00\x00\x00\x02\x9b' b'\x00\x00\x00\x00\x01\x80\xc2\x00\x00\x00\x00\x02\xfd\x2c\xb8\x98\x00\x26\x42\x42\x03\x00' b'\x00\x00\x00\x00\x80\x00\x00\x02\xfd\x2c\xb8\x83\x00\x00\x00\x00\x80\x00\x00\x02\xfd\x2c' b'\xb8\x83\x80\x26\x00\x00\x14\x00\x02\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x41\xc6' b'\x75\xd6') eth = Ethernet(s) assert eth.vlan == 333 assert len(eth.vlan_tags) == 1 assert eth.vlan_tags[0].id == 333 assert eth.vlan_tags[0].pri == 3 # check that FCS was decoded assert eth.fcs == 0x41c675d6 assert eth.trailer == b'\x00' * 8 # stack assert isinstance(eth.data, llc.LLC) assert isinstance(eth.data.data, stp.STP) # construction assert str(eth) == str(s), 'pack 1' assert str(eth) == str(s), 'pack 2' assert len(eth) == len(s) # construction with kwargs eth2 = Ethernet(src=eth.src, dst=eth.dst, vlan_tags=eth.vlan_tags, data=eth.data) eth2.trailer = eth.trailer eth2.fcs = None # test FCS computation assert str(eth2) == str(s) # construction w/o the ISL tag del eth.vlan_tags, eth.vlan assert str(eth) == str(s[26:]) def test_eth_llc_snap_cdp(): # 802.3 Ethernet - LLC/SNAP - CDP from . import cdp s = (b'\x01\x00\x0c\xcc\xcc\xcc\xc4\x022k\x00\x00\x01T\xaa\xaa\x03\x00\x00\x0c \x00\x02\xb4,B' b'\x00\x01\x00\x06R2\x00\x05\x00\xffCisco IOS Software, 3700 Software (C3745-ADVENTERPRI' b'SEK9_SNA-M), Version 12.4(25d), RELEASE SOFTWARE (fc1)\nTechnical Support: http://www.' b'cisco.com/techsupport\nCopyright (c) 1986-2010 by Cisco Systems, Inc.\nCompiled Wed 18' b'-Aug-10 08:18 by prod_rel_team\x00\x06\x00\x0eCisco 3745\x00\x02\x00\x11\x00\x00\x00\x01' b'\x01\x01\xcc\x00\x04\n\x00\x00\x02\x00\x03\x00\x13FastEthernet0/0\x00\x04\x00\x08\x00' b'\x00\x00)\x00\t\x00\x04\x00\x0b\x00\x05\x00') eth = Ethernet(s) # stack assert isinstance(eth.data, llc.LLC) assert isinstance(eth.data.data, cdp.CDP) assert len(eth.data.data.data) == 8 # number of CDP TLVs; ensures they are decoded assert str(eth) == str(s), 'pack 1' assert str(eth) == str(s), 'pack 2' assert len(eth) == len(s) def test_eth_llc_ipx(): # 802.3 Ethernet - LLC - IPX from . import ipx s = (b'\xff\xff\xff\xff\xff\xff\x00\xb0\xd0\x22\xf7\xf3\x00\x54\xe0\xe0\x03\xff\xff\x00\x50\x00' b'\x14\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\x04\x55\x00\x00\x00\x00\x00\xb0\xd0\x22\xf7' b'\xf3\x04\x55\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x02\x5f\x5f\x4d\x53\x42' b'\x52\x4f\x57\x53\x45\x5f\x5f\x02\x01\x00') eth = Ethernet(s) # stack assert isinstance(eth.data, llc.LLC) assert isinstance(eth.data.data, ipx.IPX) assert eth.data.data.pt == 0x14 assert str(eth) == str(s), 'pack 1' assert str(eth) == str(s), 'pack 2' assert len(eth) == len(s) def test_eth_pppoe(): # Eth - PPPoE - IPv6 - UDP - DHCP6 from . import ip # IPv6 needs this to build its protocol stack from . import ip6 from . import ppp from . import pppoe from . import udp s = (b'\xca\x01\x0e\x88\x00\x06\xcc\x05\x0e\x88\x00\x00\x88\x64\x11\x00\x00\x11\x00\x64\x57\x6e' b'\x00\x00\x00\x00\x3a\x11\xff\xfe\x80\x00\x00\x00\x00\x00\x00\xce\x05\x0e\xff\xfe\x88\x00' b'\x00\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x02\x22\x02\x23\x00' b'\x3a\x1a\x67\x01\xfc\x24\xab\x00\x08\x00\x02\x05\xe9\x00\x01\x00\x0a\x00\x03\x00\x01\xcc' b'\x05\x0e\x88\x00\x00\x00\x06\x00\x06\x00\x19\x00\x17\x00\x18\x00\x19\x00\x0c\x00\x09\x00' b'\x01\x00\x00\x00\x00\x00\x00\x00\x00') eth = Ethernet(s) # stack assert isinstance(eth.data, pppoe.PPPoE) assert isinstance(eth.data.data, ppp.PPP) assert isinstance(eth.data.data.data, ip6.IP6) assert isinstance(eth.data.data.data.data, udp.UDP) # construction assert str(eth) == str(s) assert len(eth) == len(s) def test_eth_2mpls_ecw_eth_llc_stp(): # Eth - MPLS - MPLS - PW ECW - 802.3 Eth(no FCS) - LLC - STP from . import stp s = (b'\xcc\x01\x0d\x5c\x00\x10\xcc\x00\x0d\x5c\x00\x10\x88\x47\x00\x01\x20\xfe\x00\x01\x01\xff' b'\x00\x00\x00\x00\x01\x80\xc2\x00\x00\x00\xcc\x04\x0d\x5c\xf0\x00\x00\x26\x42\x42\x03\x00' b'\x00\x00\x00\x00\x80\x00\xcc\x04\x0d\x5c\x00\x00\x00\x00\x00\x00\x80\x00\xcc\x04\x0d\x5c' b'\x00\x00\x80\x01\x00\x00\x14\x00\x02\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00') eth = Ethernet(s) assert len(eth.mpls_labels) == 2 assert eth.mpls_labels[0].val == 18 assert eth.mpls_labels[1].val == 16 # stack eth2 = eth.data assert isinstance(eth2, Ethernet) assert eth2.len == 38 # 802.3 Ethernet # no FCS, all trailer assert not hasattr(eth2, 'fcs') assert eth2.trailer == b'\x00' * 8 assert isinstance(eth2.data, llc.LLC) assert isinstance(eth2.data.data, stp.STP) assert eth2.data.data.port_id == 0x8001 # construction # XXX - FIXME: make packing account for the ECW # assert str(eth) == str(s) # QinQ: Eth - 802.1ad - 802.1Q - IP def test_eth_802dot1ad_802dot1q_ip(): from . import ip s = (b'\x00\x10\x94\x00\x00\x0c\x00\x10\x94\x00\x00\x14\x88\xa8\x00\x1e\x81\x00\x00\x64\x08\x00' b'\x45\x00\x05\xc2\x54\xb0\x00\x00\xff\xfd\xdd\xbf\xc0\x55\x01\x16\xc0\x55\x01\x0e' + 1434 * b'\x00' + b'\x4f\xdc\xcd\x64\x20\x8d\xb6\x4e\xa8\x45\xf8\x80\xdd\x0c\xf9\x72\xc4' b'\xd0\xcf\xcb\x46\x6d\x62\x7a') eth = Ethernet(s) assert eth.type == ETH_TYPE_8021AD assert eth.vlan_tags[0].id == 30 assert eth.vlan_tags[1].id == 100 assert isinstance(eth.data, ip.IP) e1 = Ethernet(s[:-1458]) # strip IP data # construction e2 = Ethernet( dst=b'\x00\x10\x94\x00\x00\x0c', src=b'\x00\x10\x94\x00\x00\x14', type=ETH_TYPE_8021AD, vlan_tags=[ VLANtag8021Q(pri=0, id=30, cfi=0), VLANtag8021Q(pri=0, id=100, cfi=0) ], data=ip.IP( len=1474, id=21680, ttl=255, p=253, sum=56767, src=b'\xc0U\x01\x16', dst=b'\xc0U\x01\x0e', opts=b'' ) ) assert str(e1) == str(e2) if __name__ == '__main__': test_eth() test_eth_init_with_data() test_mpls_label() test_802dot1q_tag() test_isl_tag() test_eth_802dot1q() test_eth_802dot1q_stacked() test_eth_mpls_stacked() test_isl_eth_llc_stp() test_eth_llc_snap_cdp() test_eth_llc_ipx() test_eth_pppoe() test_eth_2mpls_ecw_eth_llc_stp() test_eth_802dot1ad_802dot1q_ip() print('Tests Successful...') dpkt-1.9.2/dpkt/gre.py000066400000000000000000000101751340335175100145640ustar00rootroot00000000000000# $Id: gre.py 75 2010-08-03 14:42:19Z jon.oberheide $ # -*- coding: utf-8 -*- """Generic Routing Encapsulation.""" from __future__ import absolute_import import struct import codecs from . import dpkt from . import ethernet from .decorators import deprecated from .compat import compat_izip GRE_CP = 0x8000 # Checksum Present GRE_RP = 0x4000 # Routing Present GRE_KP = 0x2000 # Key Present GRE_SP = 0x1000 # Sequence Present GRE_SS = 0x0800 # Strict Source Route GRE_AP = 0x0080 # Acknowledgment Present GRE_opt_fields = ( (GRE_CP | GRE_RP, 'sum', 'H'), (GRE_CP | GRE_RP, 'off', 'H'), (GRE_KP, 'key', 'I'), (GRE_SP, 'seq', 'I'), (GRE_AP, 'ack', 'I') ) class GRE(dpkt.Packet): """Generic Routing Encapsulation. TODO: Longer class information.... Attributes: __hdr__: Header fields of GRE. TODO. """ __hdr__ = ( ('flags', 'H', 0), ('p', 'H', 0x0800), # ETH_TYPE_IP ) sre = () @property def v(self): return self.flags & 0x7 @v.setter def v(self, v): self.flags = (self.flags & ~0x7) | (v & 0x7) @property def recur(self): return (self.flags >> 5) & 0x7 @recur.setter def recur(self, v): self.flags = (self.flags & ~0xe0) | ((v & 0x7) << 5) class SRE(dpkt.Packet): __hdr__ = [ ('family', 'H', 0), ('off', 'B', 0), ('len', 'B', 0) ] def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.data = self.data[:self.len] def opt_fields_fmts(self): if self.v == 0: fields, fmts = [], [] opt_fields = GRE_opt_fields else: fields, fmts = ['len', 'callid'], ['H', 'H'] opt_fields = GRE_opt_fields[-2:] for flags, field, fmt in opt_fields: if self.flags & flags: fields.append(field) fmts.append(fmt) return fields, fmts def unpack(self, buf): dpkt.Packet.unpack(self, buf) fields, fmts = self.opt_fields_fmts() if fields: fmt = ''.join(fmts) fmtlen = struct.calcsize(fmt) vals = struct.unpack("!" + fmt, self.data[:fmtlen]) self.data = self.data[fmtlen:] self.__dict__.update(dict(compat_izip(fields, vals))) if self.flags & GRE_RP: l = [] while True: sre = self.SRE(self.data) self.data = self.data[len(sre):] l.append(sre) if not sre.len: break self.sre = l try: self.data = ethernet.Ethernet._typesw[self.p](self.data) setattr(self, self.data.__class__.__name__.lower(), self.data) except (KeyError, dpkt.UnpackError): # data alrady set pass def __len__(self): opt_fmtlen = struct.calcsize(''.join(self.opt_fields_fmts()[1])) return self.__hdr_len__ + opt_fmtlen + sum(map(len, self.sre)) + len(self.data) def __bytes__(self): fields, fmts = self.opt_fields_fmts() if fields: vals = [] for f in fields: vals.append(getattr(self, f)) opt_s = struct.pack(b''.join(fmts), *vals) else: opt_s = b'' return self.pack_hdr() + opt_s + b''.join(map(bytes, self.sre)) + bytes(self.data) def test_gre_v1(): # Runs all the test associated with this class/file s = codecs.decode("3081880a0067178000068fb100083a76", 'hex') + b"A" * 103 g = GRE(s) assert g.v == 1 assert g.p == 0x880a assert g.seq == 430001 assert g.ack == 539254 assert g.callid == 6016 assert g.len == 103 assert g.data == b"A" * 103 assert len(g) == len(s) s = codecs.decode("3001880a00b2001100083ab8", 'hex') + b"A" * 178 g = GRE(s) assert g.v == 1 assert g.p == 0x880a assert g.seq == 539320 assert g.callid == 17 assert g.len == 178 assert g.data == b"A" * 178 assert len(g) == len(s) def test_gre_len(): gre = GRE() assert len(gre) == 4 if __name__ == '__main__': test_gre_v1() test_gre_len() dpkt-1.9.2/dpkt/gzip.py000066400000000000000000000113631340335175100147600ustar00rootroot00000000000000# $Id: gzip.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """GNU zip.""" from __future__ import print_function from __future__ import absolute_import import struct import zlib import binascii from . import dpkt # RFC 1952 GZIP_MAGIC = b'\x1f\x8b' # Compression methods GZIP_MSTORED = 0 GZIP_MCOMPRESS = 1 GZIP_MPACKED = 2 GZIP_MLZHED = 3 GZIP_MDEFLATE = 8 # Flags GZIP_FTEXT = 0x01 GZIP_FHCRC = 0x02 GZIP_FEXTRA = 0x04 GZIP_FNAME = 0x08 GZIP_FCOMMENT = 0x10 GZIP_FENCRYPT = 0x20 GZIP_FRESERVED = 0xC0 # OS GZIP_OS_MSDOS = 0 GZIP_OS_AMIGA = 1 GZIP_OS_VMS = 2 GZIP_OS_UNIX = 3 GZIP_OS_VMCMS = 4 GZIP_OS_ATARI = 5 GZIP_OS_OS2 = 6 GZIP_OS_MACOS = 7 GZIP_OS_ZSYSTEM = 8 GZIP_OS_CPM = 9 GZIP_OS_TOPS20 = 10 GZIP_OS_WIN32 = 11 GZIP_OS_QDOS = 12 GZIP_OS_RISCOS = 13 GZIP_OS_UNKNOWN = 255 GZIP_FENCRYPT_LEN = 12 class GzipExtra(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('id', '2s', ''), ('len', 'H', 0) ) class Gzip(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('magic', '2s', GZIP_MAGIC), ('method', 'B', GZIP_MDEFLATE), ('flags', 'B', 0), ('mtime', 'I', 0), ('xflags', 'B', 0), ('os', 'B', GZIP_OS_UNIX), ('extra', '0s', ''), # XXX - GZIP_FEXTRA ('filename', '0s', ''), # XXX - GZIP_FNAME ('comment', '0s', '') # XXX - GZIP_FCOMMENT ) def unpack(self, buf): super(Gzip, self).unpack(buf) if self.flags & GZIP_FEXTRA: if len(self.data) < 2: raise dpkt.NeedData('Gzip extra') n = struct.unpack(' len(self.tpkt.data): raise dpkt.UnpackError('invalid TPKT length') buf = self.tpkt.data # Q.931 payload dpkt.Packet.unpack(self, buf) buf = buf[self.__hdr_len__:] self.ref_val = buf[:self.ref_len] buf = buf[self.ref_len:] self.type = struct.unpack('B', buf[:1])[0] buf = buf[1:] # Information Elements l = [] while buf: ie = self.IE(buf) l.append(ie) buf = buf[len(ie):] self.data = l def __len__(self): return self.tpkt.__hdr_len__ + self.__hdr_len__ + sum(map(len, self.data)) def __bytes__(self): return self.tpkt.pack_hdr() + self.pack_hdr() + self.ref_val + \ struct.pack('B', self.type) + b''.join(map(bytes, self.data)) class IE(dpkt.Packet): __hdr__ = ( ('type', 'B', 0), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) buf = buf[self.__hdr_len__:] # single-byte IE if self.type & 0x80: self.len = 0 self.data = None # multi-byte IE else: # special PER-encoded UUIE if self.type == USER_TO_USER: self.len = struct.unpack('>H', buf[:2])[0] buf = buf[2:] # normal TLV-like IE else: self.len = struct.unpack('B', buf[:1])[0] buf = buf[1:] self.data = buf[:self.len] def __len__(self): if self.type & 0x80: n = 0 else: if self.type == USER_TO_USER: n = 2 else: n = 1 return self.__hdr_len__ + self.len + n def __bytes__(self): if self.type & 0x80: length_str = None else: if self.type == USER_TO_USER: length_str = struct.pack('>H', self.len) else: length_str = struct.pack('B', self.len) return struct.pack('B', self.type) + length_str + self.data __s = b'\x03\x00\x04\x11\x08\x02\x54\x2b\x05\x04\x03\x88\x93\xa5\x28\x0e\x4a\x6f\x6e\x20\x4f\x62\x65\x72\x68\x65\x69\x64\x65\x00\x7e\x03\xf0\x05\x20\xb8\x06\x00\x08\x91\x4a\x00\x04\x01\x40\x0c\x00\x4a\x00\x6f\x00\x6e\x00\x20\x00\x4f\x00\x62\x00\x65\x00\x72\x00\x68\x00\x65\x00\x69\x00\x64\x00\x65\x22\xc0\x09\x00\x00\x3d\x06\x65\x6b\x69\x67\x61\x00\x00\x14\x32\x2e\x30\x2e\x32\x20\x28\x4f\x50\x41\x4c\x20\x76\x32\x2e\x32\x2e\x32\x29\x00\x00\x00\x01\x40\x15\x00\x74\x00\x63\x00\x70\x00\x24\x00\x68\x00\x33\x00\x32\x00\x33\x00\x2e\x00\x76\x00\x6f\x00\x78\x00\x67\x00\x72\x00\x61\x00\x74\x00\x69\x00\x61\x00\x2e\x00\x6f\x00\x72\x00\x67\x00\x42\x87\x23\x2c\x06\xb8\x00\x6a\x8b\x1d\x0c\xb7\x06\xdb\x11\x9e\xca\x00\x10\xa4\x89\x6d\x6a\x00\xc5\x1d\x80\x04\x07\x00\x0a\x00\x01\x7a\x75\x30\x11\x00\x5e\x88\x1d\x0c\xb7\x06\xdb\x11\x9e\xca\x00\x10\xa4\x89\x6d\x6a\x82\x2b\x0e\x30\x40\x00\x00\x06\x04\x01\x00\x4c\x10\x09\x00\x00\x3d\x0f\x53\x70\x65\x65\x78\x20\x62\x73\x34\x20\x57\x69\x64\x65\x36\x80\x11\x1c\x00\x01\x00\x98\xa0\x26\x41\x13\x8a\x00\x98\xa0\x26\x41\x13\x8b\x26\x00\x00\x64\x0c\x10\x09\x00\x00\x3d\x0f\x53\x70\x65\x65\x78\x20\x62\x73\x34\x20\x57\x69\x64\x65\x36\x80\x0b\x0d\x00\x01\x00\x98\xa0\x26\x41\x13\x8b\x00\x2a\x40\x00\x00\x06\x04\x01\x00\x4c\x10\x09\x00\x00\x3d\x09\x69\x4c\x42\x43\x2d\x31\x33\x6b\x33\x80\x11\x1c\x00\x01\x00\x98\xa0\x26\x41\x13\x8a\x00\x98\xa0\x26\x41\x13\x8b\x20\x00\x00\x65\x0c\x10\x09\x00\x00\x3d\x09\x69\x4c\x42\x43\x2d\x31\x33\x6b\x33\x80\x0b\x0d\x00\x01\x00\x98\xa0\x26\x41\x13\x8b\x00\x20\x40\x00\x00\x06\x04\x01\x00\x4e\x0c\x03\x00\x83\x00\x80\x11\x1c\x00\x01\x00\x98\xa0\x26\x41\x13\x8a\x00\x98\xa0\x26\x41\x13\x8b\x16\x00\x00\x66\x0e\x0c\x03\x00\x83\x00\x80\x0b\x0d\x00\x01\x00\x98\xa0\x26\x41\x13\x8b\x00\x4b\x40\x00\x00\x06\x04\x01\x00\x4c\x10\xb5\x00\x53\x4c\x2a\x02\x00\x00\x00\x00\x00\x40\x01\x00\x00\x40\x01\x02\x00\x08\x00\x00\x00\x00\x00\x31\x00\x01\x00\x40\x1f\x00\x00\x59\x06\x00\x00\x41\x00\x00\x00\x02\x00\x40\x01\x00\x00\x80\x11\x1c\x00\x01\x00\x98\xa0\x26\x41\x13\x8a\x00\x98\xa0\x26\x41\x13\x8b\x41\x00\x00\x67\x0c\x10\xb5\x00\x53\x4c\x2a\x02\x00\x00\x00\x00\x00\x40\x01\x00\x00\x40\x01\x02\x00\x08\x00\x00\x00\x00\x00\x31\x00\x01\x00\x40\x1f\x00\x00\x59\x06\x00\x00\x41\x00\x00\x00\x02\x00\x40\x01\x00\x00\x80\x0b\x0d\x00\x01\x00\x98\xa0\x26\x41\x13\x8b\x00\x32\x40\x00\x00\x06\x04\x01\x00\x4c\x10\x09\x00\x00\x3d\x11\x53\x70\x65\x65\x78\x20\x62\x73\x34\x20\x4e\x61\x72\x72\x6f\x77\x33\x80\x11\x1c\x00\x01\x00\x98\xa0\x26\x41\x13\x8a\x00\x98\xa0\x26\x41\x13\x8b\x28\x00\x00\x68\x0c\x10\x09\x00\x00\x3d\x11\x53\x70\x65\x65\x78\x20\x62\x73\x34\x20\x4e\x61\x72\x72\x6f\x77\x33\x80\x0b\x0d\x00\x01\x00\x98\xa0\x26\x41\x13\x8b\x00\x1d\x40\x00\x00\x06\x04\x01\x00\x4c\x60\x1d\x80\x11\x1c\x00\x01\x00\x98\xa0\x26\x41\x13\x8a\x00\x98\xa0\x26\x41\x13\x8b\x13\x00\x00\x69\x0c\x60\x1d\x80\x0b\x0d\x00\x01\x00\x98\xa0\x26\x41\x13\x8b\x00\x1d\x40\x00\x00\x06\x04\x01\x00\x4c\x20\x1d\x80\x11\x1c\x00\x01\x00\x98\xa0\x26\x41\x13\x8a\x00\x98\xa0\x26\x41\x13\x8b\x13\x00\x00\x6a\x0c\x20\x1d\x80\x0b\x0d\x00\x01\x00\x98\xa0\x26\x41\x13\x8b\x00\x01\x00\x01\x00\x01\x00\x01\x00\x81\x03\x02\x80\xf8\x02\x70\x01\x06\x00\x08\x81\x75\x00\x0b\x80\x13\x80\x01\xf4\x00\x01\x00\x00\x01\x00\x00\x01\x00\x00\x0c\xc0\x01\x00\x01\x80\x0b\x80\x00\x00\x20\x20\x09\x00\x00\x3d\x0f\x53\x70\x65\x65\x78\x20\x62\x73\x34\x20\x57\x69\x64\x65\x36\x80\x00\x01\x20\x20\x09\x00\x00\x3d\x09\x69\x4c\x42\x43\x2d\x31\x33\x6b\x33\x80\x00\x02\x24\x18\x03\x00\xe6\x00\x80\x00\x03\x20\x20\xb5\x00\x53\x4c\x2a\x02\x00\x00\x00\x00\x00\x40\x01\x00\x00\x40\x01\x02\x00\x08\x00\x00\x00\x00\x00\x31\x00\x01\x00\x40\x1f\x00\x00\x59\x06\x00\x00\x41\x00\x00\x00\x02\x00\x40\x01\x00\x00\x80\x00\x04\x20\x20\x09\x00\x00\x3d\x11\x53\x70\x65\x65\x78\x20\x62\x73\x34\x20\x4e\x61\x72\x72\x6f\x77\x33\x80\x00\x05\x20\xc0\xef\x80\x00\x06\x20\x40\xef\x80\x00\x07\x08\xe0\x03\x51\x00\x80\x01\x00\x80\x00\x08\x08\xd0\x03\x51\x00\x80\x01\x00\x80\x00\x09\x83\x01\x50\x80\x00\x0a\x83\x01\x10\x80\x00\x0b\x83\x01\x40\x00\x80\x01\x03\x06\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x01\x00\x07\x00\x08\x00\x00\x09\x01\x00\x0a\x00\x0b\x07\x01\x00\x32\x80\xa6\xff\x4c\x02\x80\x01\x80' def test_pack(): h = H225(__s) assert (__s == bytes(h)) def test_unpack(): h = H225(__s) assert (h.tpkt.v == 3) assert (h.tpkt.rsvd == 0) assert (h.tpkt.len == 1041) assert (h.proto == 8) assert (h.type == SETUP) assert (len(h.data) == 3) ie = h.data[0] assert (ie.type == BEARER_CAPABILITY) assert (ie.len == 3) ie = h.data[1] assert (ie.type == DISPLAY) assert (ie.len == 14) ie = h.data[2] assert (ie.type == USER_TO_USER) assert (ie.len == 1008) if __name__ == '__main__': test_pack() test_unpack() print('Tests Successful...') dpkt-1.9.2/dpkt/hsrp.py000066400000000000000000000014421340335175100147600ustar00rootroot00000000000000# $Id: hsrp.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Cisco Hot Standby Router Protocol.""" from __future__ import absolute_import from . import dpkt # Opcodes HELLO = 0 COUP = 1 RESIGN = 2 # States INITIAL = 0x00 LEARN = 0x01 LISTEN = 0x02 SPEAK = 0x04 STANDBY = 0x08 ACTIVE = 0x10 class HSRP(dpkt.Packet): """Cisco Hot Standby Router Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of HSRP. TODO. """ __hdr__ = ( ('version', 'B', 0), ('opcode', 'B', 0), ('state', 'B', 0), ('hello', 'B', 0), ('hold', 'B', 0), ('priority', 'B', 0), ('group', 'B', 0), ('rsvd', 'B', 0), ('auth', '8s', 'cisco'), ('vip', '4s', '') ) dpkt-1.9.2/dpkt/http.py000066400000000000000000000412041340335175100147630ustar00rootroot00000000000000# $Id: http.py 86 2013-03-05 19:25:19Z andrewflnr@gmail.com $ # -*- coding: utf-8 -*- """Hypertext Transfer Protocol.""" from __future__ import print_function from __future__ import absolute_import try: from collections import OrderedDict except ImportError: # Python 2.6 OrderedDict = dict from . import dpkt from .compat import BytesIO, iteritems def parse_headers(f): """Return dict of HTTP headers parsed from a file object.""" d = OrderedDict() while 1: # The following logic covers two kinds of loop exit criteria. # 1) If the header is valid, when we reached the end of the header, # f.readline() would return with '\r\n', then after strip(), # we can break the loop. # 2) If this is a weird header, which do not ends with '\r\n', # f.readline() would return with '', then after strip(), # we still get an empty string, also break the loop. line = f.readline().strip().decode("ascii", "ignore") if not line: break l = line.split(':', 1) if len(l[0].split()) != 1: raise dpkt.UnpackError('invalid header: %r' % line) k = l[0].lower() v = len(l) != 1 and l[1].lstrip() or '' if k in d: if not type(d[k]) is list: d[k] = [d[k]] d[k].append(v) else: d[k] = v return d def parse_body(f, headers): """Return HTTP body parsed from a file object, given HTTP header dict.""" if headers.get('transfer-encoding', '').lower() == 'chunked': l = [] found_end = False while 1: try: sz = f.readline().split(None, 1)[0] except IndexError: raise dpkt.UnpackError('missing chunk size') n = int(sz, 16) if n == 0: found_end = True buf = f.read(n) if f.readline().strip(): break if n and len(buf) == n: l.append(buf) else: break if not found_end: raise dpkt.NeedData('premature end of chunked body') body = b''.join(l) elif 'content-length' in headers: n = int(headers['content-length']) body = f.read(n) if len(body) != n: raise dpkt.NeedData('short body (missing %d bytes)' % (n - len(body))) elif 'content-type' in headers: body = f.read() else: # XXX - need to handle HTTP/0.9 body = b'' return body class Message(dpkt.Packet): """Hypertext Transfer Protocol headers + body. TODO: Longer class information.... Attributes: __hdr__: Header fields of HTTP. TODO. """ __metaclass__ = type __hdr_defaults__ = {} headers = None body = None def __init__(self, *args, **kwargs): if args: self.unpack(args[0]) else: self.headers = OrderedDict() self.body = b'' self.data = b'' # NOTE: changing this to iteritems breaks py3 compatibility for k, v in self.__hdr_defaults__.items(): setattr(self, k, v) for k, v in iteritems(kwargs): setattr(self, k, v) def unpack(self, buf, is_body_allowed=True): f = BytesIO(buf) # Parse headers self.headers = parse_headers(f) # Parse body if is_body_allowed: self.body = parse_body(f, self.headers) else: self.body = b'' # Save the rest self.data = f.read() def pack_hdr(self): return ''.join(['%s: %s\r\n' % t for t in iteritems(self.headers)]) def __len__(self): return len(str(self)) def __str__(self): return '%s\r\n%s' % (self.pack_hdr(), self.body.decode("utf8", "ignore")) def __bytes__(self): return self.pack_hdr().encode("ascii", "ignore") + b'\r\n' + (self.body or b'') class Request(Message): """Hypertext Transfer Protocol Request. TODO: Longer class information.... Attributes: __hdr__: Header fields of HTTP request. TODO. """ __hdr_defaults__ = { 'method': 'GET', 'uri': '/', 'version': '1.0', } __methods = dict.fromkeys(( 'GET', 'PUT', 'ICY', 'COPY', 'HEAD', 'LOCK', 'MOVE', 'POLL', 'POST', 'BCOPY', 'BMOVE', 'MKCOL', 'TRACE', 'LABEL', 'MERGE', 'DELETE', 'SEARCH', 'UNLOCK', 'REPORT', 'UPDATE', 'NOTIFY', 'BDELETE', 'CONNECT', 'OPTIONS', 'CHECKIN', 'PROPFIND', 'CHECKOUT', 'CCM_POST', 'SUBSCRIBE', 'PROPPATCH', 'BPROPFIND', 'BPROPPATCH', 'UNCHECKOUT', 'MKACTIVITY', 'MKWORKSPACE', 'UNSUBSCRIBE', 'RPC_CONNECT', 'VERSION-CONTROL', 'BASELINE-CONTROL' )) __proto = 'HTTP' def unpack(self, buf): f = BytesIO(buf) line = f.readline().decode("ascii", "ignore") l = line.strip().split() if len(l) < 2: raise dpkt.UnpackError('invalid request: %r' % line) if l[0] not in self.__methods: raise dpkt.UnpackError('invalid http method: %r' % l[0]) if len(l) == 2: # HTTP/0.9 does not specify a version in the request line self.version = '0.9' else: if not l[2].startswith(self.__proto): raise dpkt.UnpackError('invalid http version: %r' % l[2]) self.version = l[2][len(self.__proto) + 1:] self.method = l[0] self.uri = l[1] Message.unpack(self, f.read()) def __str__(self): return '%s %s %s/%s\r\n' % (self.method, self.uri, self.__proto, self.version) + Message.__str__(self) def __bytes__(self): str_out = '%s %s %s/%s\r\n' % (self.method, self.uri, self.__proto, self.version) return str_out.encode("ascii", "ignore") + Message.__bytes__(self) class Response(Message): """Hypertext Transfer Protocol Response. TODO: Longer class information.... Attributes: __hdr__: Header fields of HTTP Response. TODO. """ __hdr_defaults__ = { 'version': '1.0', 'status': '200', 'reason': 'OK' } __proto = 'HTTP' def unpack(self, buf): f = BytesIO(buf) line = f.readline() l = line.strip().decode("ascii", "ignore").split(None, 2) if len(l) < 2 or not l[0].startswith(self.__proto) or not l[1].isdigit(): raise dpkt.UnpackError('invalid response: %r' % line) self.version = l[0][len(self.__proto) + 1:] self.status = l[1] self.reason = l[2] if len(l) > 2 else '' # RFC Sec 4.3. # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3. # For response messages, whether or not a message-body is included with # a message is dependent on both the request method and the response # status code (section 6.1.1). All responses to the HEAD request method # MUST NOT include a message-body, even though the presence of entity- # header fields might lead one to believe they do. All 1xx # (informational), 204 (no content), and 304 (not modified) responses # MUST NOT include a message-body. All other responses do include a # message-body, although it MAY be of zero length. is_body_allowed = int(self.status) >= 200 and 204 != int(self.status) != 304 Message.unpack(self, f.read(), is_body_allowed) def __str__(self): return '%s/%s %s %s\r\n' % (self.__proto, self.version, self.status, self.reason) + Message.__str__(self) def __bytes__(self): str_out = '%s/%s %s %s\r\n' % (self.__proto, self.version, self.status, self.reason) return str_out.encode("ascii", "ignore") + Message.__bytes__(self) def test_parse_request(): s = b"""POST /main/redirect/ab/1,295,,00.html HTTP/1.0\r\nReferer: http://www.email.com/login/snap/login.jhtml\r\nConnection: Keep-Alive\r\nUser-Agent: Mozilla/4.75 [en] (X11; U; OpenBSD 2.8 i386; Nav)\r\nHost: ltd.snap.com\r\nAccept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*\r\nAccept-Encoding: gzip\r\nAccept-Language: en\r\nAccept-Charset: iso-8859-1,*,utf-8\r\nContent-type: application/x-www-form-urlencoded\r\nContent-length: 61\r\n\r\nsn=em&mn=dtest4&pw=this+is+atest&fr=true&login=Sign+in&od=www""" r = Request(s) assert r.method == 'POST' assert r.uri == '/main/redirect/ab/1,295,,00.html' assert r.body == b'sn=em&mn=dtest4&pw=this+is+atest&fr=true&login=Sign+in&od=www' assert r.headers['content-type'] == 'application/x-www-form-urlencoded' try: Request(s[:60]) assert 'invalid headers parsed!' except dpkt.UnpackError: pass def test_format_request(): r = Request() assert str(r) == 'GET / HTTP/1.0\r\n\r\n' r.method = 'POST' r.uri = '/foo/bar/baz.html' r.headers['content-type'] = 'text/plain' r.headers['content-length'] = '5' r.body = b'hello' s = str(r) assert s.startswith('POST /foo/bar/baz.html HTTP/1.0\r\n') assert s.endswith('\r\n\r\nhello') assert '\r\ncontent-length: 5\r\n' in s assert '\r\ncontent-type: text/plain\r\n' in s s = bytes(r) assert s.startswith(b'POST /foo/bar/baz.html HTTP/1.0\r\n') assert s.endswith(b'\r\n\r\nhello') assert b'\r\ncontent-length: 5\r\n' in s assert b'\r\ncontent-type: text/plain\r\n' in s r = Request(bytes(r)) assert bytes(r) == s def test_chunked_response(): s = b"""HTTP/1.1 200 OK\r\nCache-control: no-cache\r\nPragma: no-cache\r\nContent-Type: text/javascript; charset=utf-8\r\nContent-Encoding: gzip\r\nTransfer-Encoding: chunked\r\nSet-Cookie: S=gmail=agg:gmail_yj=v2s:gmproxy=JkU; Domain=.google.com; Path=/\r\nServer: GFE/1.3\r\nDate: Mon, 12 Dec 2005 22:33:23 GMT\r\n\r\na\r\n\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00\r\n152\r\nm\x91MO\xc4 \x10\x86\xef\xfe\n\x82\xc9\x9eXJK\xe9\xb6\xee\xc1\xe8\x1e6\x9e4\xf1\xe0a5\x86R\xda\x12Yh\x80\xba\xfa\xef\x85\xee\x1a/\xf21\x99\x0c\xef0<\xc3\x81\xa0\xc3\x01\xe6\x10\xc1<\xa7eYT5\xa1\xa4\xac\xe1\xdb\x15:\xa4\x9d\x0c\xfa5K\x00\xf6.\xaa\xeb\x86\xd5y\xcdHY\x954\x8e\xbc*h\x8c\x8e!L7Y\xe6\'\xeb\x82WZ\xcf>8\x1ed\x87\x851X\xd8c\xe6\xbc\x17Z\x89\x8f\xac \x84e\xde\n!]\x96\x17i\xb5\x02{{\xc2z0\x1e\x0f#7\x9cw3v\x992\x9d\xfc\xc2c8\xea[/EP\xd6\xbc\xce\x84\xd0\xce\xab\xf7`\'\x1f\xacS\xd2\xc7\xd2\xfb\x94\x02N\xdc\x04\x0f\xee\xba\x19X\x03TtW\xd7\xb4\xd9\x92\n\xbcX\xa7;\xb0\x9b\'\x10$?F\xfd\xf3CzPt\x8aU\xef\xb8\xc8\x8b-\x18\xed\xec<\xe0\x83\x85\x08!\xf8"[\xb0\xd3j\x82h\x93\xb8\xcf\xd8\x9b\xba\xda\xd0\x92\x14\xa4a\rc\reM\xfd\x87=X;h\xd9j;\xe0db\x17\xc2\x02\xbd\xb0F\xc2in#\xfb:\xb6\xc4x\x15\xd6\x9f\x8a\xaf\xcf)\x0b^\xbc\xe7i\x11\x80\x8b\x00D\x01\xd8/\x82x\xf6\xd8\xf7J(\xae/\x11p\x1f+\xc4p\t:\xfe\xfd\xdf\xa3Y\xfa\xae4\x7f\x00\xc5\xa5\x95\xa1\xe2\x01\x00\x00\r\n0\r\n\r\n""" r = Response(s) assert r.version == '1.1' assert r.status == '200' assert r.reason == 'OK' def test_multicookie_response(): s = b"""HTTP/1.x 200 OK\r\nSet-Cookie: first_cookie=cookie1; path=/; domain=.example.com\r\nSet-Cookie: second_cookie=cookie2; path=/; domain=.example.com\r\nContent-Length: 0\r\n\r\n""" r = Response(s) assert type(r.headers['set-cookie']) is list assert len(r.headers['set-cookie']) == 2 def test_noreason_response(): s = b"""HTTP/1.1 200 \r\n\r\n""" r = Response(s) assert r.reason == '' assert bytes(r) == s def test_response_with_body(): r = Response() r.body = b'foo' assert str(r) == 'HTTP/1.0 200 OK\r\n\r\nfoo' assert bytes(r) == b'HTTP/1.0 200 OK\r\n\r\nfoo' def test_body_forbidden_response(): s = b'HTTP/1.1 304 Not Modified\r\n'\ b'Content-Type: text/css\r\n'\ b'Last-Modified: Wed, 14 Jan 2009 16:42:11 GMT\r\n'\ b'ETag: "3a7-496e15e3"\r\n'\ b'Cache-Control: private, max-age=414295\r\n'\ b'Date: Wed, 22 Sep 2010 17:55:54 GMT\r\n'\ b'Connection: keep-alive\r\n'\ b'Vary: Accept-Encoding\r\n\r\n'\ b'HTTP/1.1 200 OK\r\n'\ b'Server: Sun-ONE-Web-Server/6.1\r\n'\ b'ntCoent-length: 257\r\n'\ b'Content-Type: application/x-javascript\r\n'\ b'Last-Modified: Wed, 06 Jan 2010 19:34:06 GMT\r\n'\ b'ETag: "101-4b44e5ae"\r\n'\ b'Accept-Ranges: bytes\r\n'\ b'Content-Encoding: gzip\r\n'\ b'Cache-Control: private, max-age=439726\r\n'\ b'Date: Wed, 22 Sep 2010 17:55:54 GMT\r\n'\ b'Connection: keep-alive\r\n'\ b'Vary: Accept-Encoding\r\n' result = [] while s: msg = Response(s) s = msg.data result.append(msg) # the second HTTP response should be an standalone message assert len(result) == 2 def test_request_version(): s = b"""GET / HTTP/1.0\r\n\r\n""" r = Request(s) assert r.method == 'GET' assert r.uri == '/' assert r.version == '1.0' s = b"""GET /\r\n\r\n""" r = Request(s) assert r.method == 'GET' assert r.uri == '/' assert r.version == '0.9' s = b"""GET / CHEESE/1.0\r\n\r\n""" try: Request(s) assert "invalid protocol version parsed!" except: pass def test_invalid_header(): # valid header. s = b'POST /main/redirect/ab/1,295,,00.html HTTP/1.0\r\n' \ b'Referer: http://www.email.com/login/snap/login.jhtml\r\n' \ b'Connection: Keep-Alive\r\n' \ b'User-Agent: Mozilla/4.75 [en] (X11; U; OpenBSD 2.8 i386; Nav)\r\n' \ b'Host: ltd.snap.com\r\n' \ b'Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*\r\n' \ b'Accept-Encoding: gzip\r\n' \ b'Accept-Language: en\r\n' \ b'Accept-Charset: iso-8859-1,*,utf-8\r\n' \ b'Content-type: application/x-www-form-urlencoded\r\n' \ b'Content-length: 61\r\n\r\n' \ b'sn=em&mn=dtest4&pw=this+is+atest&fr=true&login=Sign+in&od=www' r = Request(s) assert r.method == 'POST' assert r.uri == '/main/redirect/ab/1,295,,00.html' assert r.body == b'sn=em&mn=dtest4&pw=this+is+atest&fr=true&login=Sign+in&od=www' assert r.headers['content-type'] == 'application/x-www-form-urlencoded' # invalid header. s_weird_end = b'POST /main/redirect/ab/1,295,,00.html HTTP/1.0\r\n' \ b'Referer: http://www.email.com/login/snap/login.jhtml\r\n' \ b'Connection: Keep-Alive\r\n' \ b'User-Agent: Mozilla/4.75 [en] (X11; U; OpenBSD 2.8 i386; Nav)\r\n' \ b'Host: ltd.snap.com\r\n' \ b'Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*\r\n' \ b'Accept-Encoding: gzip\r\n' \ b'Accept-Language: en\r\n' \ b'Accept-Charset: iso-8859-1,*,utf-8\r\n' \ b'Content-type: application/x-www-form-urlencoded\r\n' \ b'Cookie: TrackID=1PWdcr3MO_C611BGW' r = Request(s_weird_end) assert r.method == 'POST' assert r.uri == '/main/redirect/ab/1,295,,00.html' assert r.headers['content-type'] == 'application/x-www-form-urlencoded' # messy header. s_messy_header = b'aaaaaaaaa\r\nbbbbbbbbb' try: r = Request(s_messy_header) except dpkt.UnpackError: assert True # If the http request is built successfully or raised exceptions # other than UnpackError, then return a false assertion. except: assert False else: assert False def test_gzip_response(): import zlib # valid response, compressed using gzip s = b'HTTP/1.0 200 OK\r\n' \ b'Server: SimpleHTTP/0.6 Python/2.7.12\r\n' \ b'Date: Fri, 10 Mar 2017 20:43:08 GMT\r\n' \ b'Content-type: text/plain\r\n' \ b'Content-Encoding: gzip\r\n' \ b'Content-Length: 68\r\n' \ b'Last-Modified: Fri, 10 Mar 2017 20:40:43 GMT\r\n\r\n' \ b'\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\x03\x0b\xc9\xc8,V\x00\xa2D' \ b'\x85\xb2\xd4\xa2J\x85\xe2\xdc\xc4\x9c\x1c\x85\xb4\xcc\x9cT\x85\x92' \ b'|\x85\x92\xd4\xe2\x12\x85\xf4\xaa\xcc\x02\x85\xa2\xd4\xe2\x82\xfc' \ b'\xbc\xe2\xd4b=.\x00\x01(m\xad2\x00\x00\x00' r = Response(s) assert r.version == '1.0' assert r.status == '200' assert r.reason == 'OK' # Make a zlib compressor with the appropriate gzip options decompressor = zlib.decompressobj(16 + zlib.MAX_WBITS) body = decompressor.decompress(r.body) assert body.startswith(b'This is a very small file') if __name__ == '__main__': # Runs all the test associated with this class/file test_parse_request() test_format_request() test_chunked_response() test_multicookie_response() test_noreason_response() test_response_with_body() test_request_version() test_invalid_header() test_body_forbidden_response() print('Tests Successful...') dpkt-1.9.2/dpkt/http2.py000066400000000000000000000713041340335175100150510ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Hypertext Transfer Protocol Version 2.""" import struct import codecs from . import dpkt HTTP2_PREFACE = b'\x50\x52\x49\x20\x2a\x20\x48\x54\x54\x50\x2f\x32\x2e\x30\x0d\x0a\x0d\x0a\x53\x4d\x0d\x0a\x0d\x0a' # Frame types HTTP2_FRAME_DATA = 0 HTTP2_FRAME_HEADERS = 1 HTTP2_FRAME_PRIORITY = 2 HTTP2_FRAME_RST_STREAM = 3 HTTP2_FRAME_SETTINGS = 4 HTTP2_FRAME_PUSH_PROMISE = 5 HTTP2_FRAME_PING = 6 HTTP2_FRAME_GOAWAY = 7 HTTP2_FRAME_WINDOW_UPDATE = 8 HTTP2_FRAME_CONTINUATION = 9 # Flags HTTP2_FLAG_END_STREAM = 0x01 # for DATA and HEADERS frames HTTP2_FLAG_ACK = 0x01 # for SETTINGS and PING frames HTTP2_FLAG_END_HEADERS = 0x04 HTTP2_FLAG_PADDED = 0x08 HTTP2_FLAG_PRIORITY = 0x20 # Settings HTTP2_SETTINGS_HEADER_TABLE_SIZE = 0x1 HTTP2_SETTINGS_ENABLE_PUSH = 0x2 HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 0x3 HTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 0x4 HTTP2_SETTINGS_MAX_FRAME_SIZE = 0x5 HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 0x6 # Error codes HTTP2_NO_ERROR = 0x0 HTTP2_PROTOCOL_ERROR = 0x1 HTTP2_INTERNAL_ERROR = 0x2 HTTP2_FLOW_CONTROL_ERROR = 0x3 HTTP2_SETTINGS_TIMEOUT = 0x4 HTTP2_STREAM_CLOSED = 0x5 HTTP2_FRAME_SIZE_ERROR = 0x6 HTTP2_REFUSED_STREAM = 0x7 HTTP2_CANCEL = 0x8 HTTP2_COMPRESSION_ERROR = 0x9 HTTP2_CONNECT_ERROR = 0xa HTTP2_ENHANCE_YOUR_CALM = 0xb HTTP2_INADEQUATE_SECURITY = 0xc HTTP2_HTTP_1_1_REQUIRED = 0xd error_code_str = { HTTP2_NO_ERROR: 'NO_ERROR', HTTP2_PROTOCOL_ERROR: 'PROTOCOL_ERROR', HTTP2_INTERNAL_ERROR: 'INTERNAL_ERROR', HTTP2_FLOW_CONTROL_ERROR: 'FLOW_CONTROL_ERROR', HTTP2_SETTINGS_TIMEOUT: 'SETTINGS_TIMEOUT', HTTP2_STREAM_CLOSED: 'STREAM_CLOSED', HTTP2_FRAME_SIZE_ERROR: 'FRAME_SIZE_ERROR', HTTP2_REFUSED_STREAM: 'REFUSED_STREAM', HTTP2_CANCEL: 'CANCEL', HTTP2_COMPRESSION_ERROR: 'COMPRESSION_ERROR', HTTP2_CONNECT_ERROR: 'CONNECT_ERROR', HTTP2_ENHANCE_YOUR_CALM: 'ENHANCE_YOUR_CALM', HTTP2_INADEQUATE_SECURITY: 'INADEQUATE_SECURITY', HTTP2_HTTP_1_1_REQUIRED: 'HTTP_1_1_REQUIRED', } class HTTP2Exception(Exception): pass class Preface(dpkt.Packet): __hdr__ = ( ('preface', '24s', HTTP2_PREFACE), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.preface != HTTP2_PREFACE: raise HTTP2Exception('Invalid HTTP/2 preface') self.data = '' class Frame(dpkt.Packet): """ An HTTP/2 frame as defined in RFC 7540 """ # struct.unpack can't handle the 3-byte int, so we parse it as bytes # (and store it as bytes so dpkt doesn't get confused), and turn it into # an int in a user-facing property __hdr__ = ( ('length_bytes', '3s', 0), ('type', 'B', 0), ('flags', 'B', 0), ('stream_id', 'I', 0), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) # only take the right number of bytes self.data = self.data[:self.length] if len(self.data) != self.length: raise dpkt.NeedData @property def length(self): return struct.unpack('!I', b'\x00' + self.length_bytes)[0] class Priority(dpkt.Packet): """ Payload of a PRIORITY frame, also used in HEADERS frame with FLAG_PRIORITY. Also used in the HEADERS frame if the PRIORITY flag is set. """ __hdr__ = ( ('stream_dep', 'I', 0), ('weight', 'B', 0), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) if len(self.data) != 0: raise HTTP2Exception('Invalid number of bytes in PRIORITY frame') self.exclusive = (self.stream_dep & 0x80000000) != 0 self.stream_dep &= 0x7fffffff self.weight += 1 class Setting(dpkt.Packet): """ A key-value pair used in the SETTINGS frame. """ __hdr__ = ( ('identifier', 'H', 0), ('value', 'I', 0), ) class PaddedFrame(Frame): """ Abstract class for frame types that support the FLAG_PADDED flag: DATA, HEADERS and PUSH_PROMISE. """ def unpack(self, buf): Frame.unpack(self, buf) if self.flags & HTTP2_FLAG_PADDED: if self.length == 0: raise HTTP2Exception('Missing padding length in PADDED frame') self.pad_length = struct.unpack('B', self.data[0:1])[0] if self.length <= self.pad_length: raise HTTP2Exception('Missing padding bytes in PADDED frame') self.unpadded_data = self.data[1:-self.pad_length] else: self.unpadded_data = self.data class DataFrame(PaddedFrame): """ Frame of type DATA. """ @property def payload(self): return self.unpadded_data class HeadersFrame(PaddedFrame): """ Frame of type HEADERS. """ def unpack(self, buf): PaddedFrame.unpack(self, buf) if self.flags & HTTP2_FLAG_PRIORITY: if len(self.unpadded_data) < 5: raise HTTP2Exception('Missing stream dependency in HEADERS frame with PRIORITY flag') self.priority = Priority(self.unpadded_data[:5]) self.block_fragment = self.unpadded_data[5:] else: self.block_fragment = self.unpadded_data class PriorityFrame(Frame): """ Frame of type PRIORITY. """ def unpack(self, buf): Frame.unpack(self, buf) self.priority = Priority(self.data) class RSTStreamFrame(Frame): """ Frame of type RST_STREAM. """ def unpack(self, buf): Frame.unpack(self, buf) if self.length != 4: raise HTTP2Exception('Invalid number of bytes in RST_STREAM frame (must be 4)') self.error_code = struct.unpack('!I', self.data)[0] class SettingsFrame(Frame): """ Frame of type SETTINGS. """ def unpack(self, buf): Frame.unpack(self, buf) if self.length % 6 != 0: raise HTTP2Exception('Invalid number of bytes in SETTINGS frame (must be multiple of 6)') self.settings = [] i = 0 while i < self.length: self.settings.append(Setting(self.data[i:i+6])) i += 6 class PushPromiseFrame(PaddedFrame): """ Frame of type PUSH_PROMISE. """ def unpack(self, buf): PaddedFrame.unpack(self, buf) if len(self.unpadded_data) < 4: raise HTTP2Exception('Missing promised stream ID in PUSH_PROMISE frame') self.promised_id = struct.unpack('!I', self.data[:4])[0] self.block_fragment = self.unpadded_data[4:] class PingFrame(Frame): """ Frame of type PING. """ def unpack(self, buf): Frame.unpack(self, buf) if self.length != 8: raise HTTP2Exception('Invalid number of bytes in PING frame (must be 8)') class GoAwayFrame(Frame): """ Frame of type GO_AWAY. """ def unpack(self, buf): Frame.unpack(self, buf) if self.length < 8: raise HTTP2Exception('Invalid number of bytes in GO_AWAY frame') self.last_stream_id = struct.unpack('!I', self.data[:4])[0] self.error_code = struct.unpack('!I', self.data[4:8])[0] self.debug_data = self.data[8:] class WindowUpdateFrame(Frame): """ Frame of type WINDOW_UPDATE. """ def unpack(self, buf): Frame.unpack(self, buf) if self.length != 4: raise HTTP2Exception('Invalid number of bytes in WINDOW_UPDATE frame (must be 4)') self.window_increment = struct.unpack('!I', self.data)[0] class ContinuationFrame(Frame): """ Frame of type CONTINUATION. """ def unpack(self, buf): Frame.unpack(self, buf) self.block_fragment = self.data FRAME_TYPES = { HTTP2_FRAME_DATA: ('DATA', DataFrame), HTTP2_FRAME_HEADERS: ('HEADERS', HeadersFrame), HTTP2_FRAME_PRIORITY: ('PRIORITY', PriorityFrame), HTTP2_FRAME_RST_STREAM: ('RST_STREAM', RSTStreamFrame), HTTP2_FRAME_SETTINGS: ('SETTINGS', SettingsFrame), HTTP2_FRAME_PUSH_PROMISE: ('PUSH_PROMISE', PushPromiseFrame), HTTP2_FRAME_PING: ('PING', PingFrame), HTTP2_FRAME_GOAWAY: ('GOAWAY', GoAwayFrame), HTTP2_FRAME_WINDOW_UPDATE: ('WINDOW_UPDATE', WindowUpdateFrame), HTTP2_FRAME_CONTINUATION: ('CONTINUATION', ContinuationFrame), } class FrameFactory(object): def __new__(cls, buf): if len(buf) < 4: raise dpkt.NeedData t = struct.unpack('B', buf[3:4])[0] frame_type = FRAME_TYPES.get(t, None) if frame_type is None: raise HTTP2Exception('Invalid frame type: ' + hex(t)) return frame_type[1](buf) def frame_multi_factory(buf, preface=False): """ Attempt to parse one or more Frame's out of buf Args: buf: string containing HTTP/2 frames. May have an incomplete frame at the end. preface: expect an HTTP/2 preface at the beginning of the buffer. Returns: [Frame] int, total bytes consumed, != len(buf) if an incomplete frame was left at the end. """ i = 0 n = len(buf) frames = [] if preface: try: p = Preface(buf) i += len(p) except dpkt.NeedData: return [], 0 while i < n: try: frame = FrameFactory(buf[i:]) frames.append(frame) i += len(frame) except dpkt.NeedData: break return frames, i class TestFrame(object): """Some data found in real traffic""" @classmethod def setup_class(cls): # First TLS AppData record sent by Firefox (decrypted) record = codecs.decode(b'505249202a20485454502f322e300d0a' b'0d0a534d0d0a0d0a00000c0400000000' b'00000400020000000500004000000004' b'08000000000000bf0001000005020000' b'00000300000000c80000050200000000' b'05000000006400000502000000000700' b'00000000000005020000000009000000' b'070000000502000000000b0000000300', 'hex') cls.frames, cls.i = frame_multi_factory(record, preface=True) def test_frame(self): import pytest # Too short pytest.raises(dpkt.NeedData, Frame, codecs.decode(b'000001' # length b'0000' # type, flags b'deadbeef' # stream id , 'hex')) def test_data(self): # Padded DATA frame frame_data_padded = FrameFactory(codecs.decode(b'000008' #length b'0008' # type, flags b'12345678' # stream id b'05' # pad length b'abcd' # data b'1122334455' # padding , 'hex')) assert (frame_data_padded.length == 8) assert (frame_data_padded.type == HTTP2_FRAME_DATA) assert (frame_data_padded.flags == HTTP2_FLAG_PADDED) assert (frame_data_padded.stream_id == 0x12345678) assert (frame_data_padded.data == b'\x05\xAB\xCD\x11\x22\x33\x44\x55') assert (frame_data_padded.pad_length == 5) assert (frame_data_padded.unpadded_data == b'\xAB\xCD') assert (frame_data_padded.payload == b'\xAB\xCD') # empty DATA frame frame_data_empty_end = FrameFactory(codecs.decode(b'000000' #length b'0001' # type, flags b'deadbeef' # stream id , 'hex')) assert (frame_data_empty_end.length == 0) assert (frame_data_empty_end.type == HTTP2_FRAME_DATA) assert (frame_data_empty_end.flags == HTTP2_FLAG_END_STREAM) assert (frame_data_empty_end.stream_id == 0xdeadbeef) assert (frame_data_empty_end.data == b'') assert (frame_data_empty_end.unpadded_data == b'') assert (frame_data_empty_end.payload == b'') import pytest # Invalid padding with pytest.raises(HTTP2Exception) as e: x = DataFrame(codecs.decode(b'000000' # length b'0008' # type, flags b'12345678' # stream id b'' # missing padding , 'hex')) assert (str(e.value) == 'Missing padding length in PADDED frame') with pytest.raises(HTTP2Exception) as e: x = DataFrame(codecs.decode(b'000001' # length b'0008' # type, flags b'12345678' # stream id b'01' b'' # missing padding bytes , 'hex')) assert (str(e.value) == 'Missing padding bytes in PADDED frame') def test_headers(self): frame_headers = FrameFactory(codecs.decode(b'000003' # length b'0100' # type, flags b'deadbeef' # stream id b'f00baa' # block fragment , 'hex')) assert (frame_headers.length == 3) assert (frame_headers.type == HTTP2_FRAME_HEADERS) assert (frame_headers.flags == 0) assert (frame_headers.stream_id == 0xdeadbeef) assert (frame_headers.data == b'\xF0\x0B\xAA') assert (frame_headers.unpadded_data == b'\xF0\x0B\xAA') assert (frame_headers.block_fragment == b'\xF0\x0B\xAA') frame_headers_prio = FrameFactory(codecs.decode(b'000008' # length b'0120' # type, flags b'deadbeef' # stream id b'cafebabe10' # priority b'f00baa' # block fragment , 'hex')) assert (frame_headers_prio.length == 8) assert (frame_headers_prio.type == HTTP2_FRAME_HEADERS) assert (frame_headers_prio.flags == HTTP2_FLAG_PRIORITY) assert (frame_headers_prio.stream_id == 0xdeadbeef) assert (frame_headers_prio.data == b'\xCA\xFE\xBA\xBE\x10\xF0\x0B\xAA') assert (frame_headers_prio.unpadded_data == b'\xCA\xFE\xBA\xBE\x10\xF0\x0B\xAA') assert (frame_headers_prio.priority.exclusive == True) assert (frame_headers_prio.priority.stream_dep == 0x4afebabe) assert (frame_headers_prio.priority.weight == 0x11) assert (frame_headers_prio.block_fragment == b'\xF0\x0B\xAA') import pytest # Invalid priority with pytest.raises(HTTP2Exception) as e: x = HeadersFrame(codecs.decode(b'000002' # length b'0120' # type, flags b'deadbeef' # stream id b'1234' # invalid priority , 'hex')) assert (str(e.value) == 'Missing stream dependency in HEADERS frame with PRIORITY flag') def test_priority(self): frame_priority = FrameFactory(codecs.decode(b'000005' # length b'0200' # type, flags b'deadbeef' # stream id b'cafebabe' # stream dep b'12' # weight , 'hex')) assert (frame_priority.length == 5) assert (frame_priority.type == HTTP2_FRAME_PRIORITY) assert (frame_priority.flags == 0) assert (frame_priority.stream_id == 0xdeadbeef) assert (frame_priority.data == b'\xCA\xFE\xBA\xBE\x12') assert (frame_priority.priority.data == b'') assert (frame_priority.priority.exclusive == True) assert (frame_priority.priority.stream_dep == 0x4afebabe) assert (frame_priority.priority.weight == 0x13) import pytest # Invalid length with pytest.raises(HTTP2Exception) as e: x = PriorityFrame(codecs.decode(b'000006' # length b'0200' # type, flags b'deadbeef' # stream id b'cafebabe' # stream dep b'12' # weight b'00' # unexpected additional payload , 'hex')) assert (str(e.value) == 'Invalid number of bytes in PRIORITY frame') def test_rst_stream(self): frame_rst = FrameFactory(codecs.decode(b'000004' # length b'0300' # type, flags b'deadbeef' # stream id b'0000000c' # error code , 'hex')) assert (frame_rst.length == 4) assert (frame_rst.type == HTTP2_FRAME_RST_STREAM) assert (frame_rst.flags == 0) assert (frame_rst.stream_id == 0xdeadbeef) assert (frame_rst.data == b'\x00\x00\x00\x0c') assert (frame_rst.error_code == HTTP2_INADEQUATE_SECURITY) import pytest # Invalid length with pytest.raises(HTTP2Exception) as e: x = RSTStreamFrame(codecs.decode(b'000005' # length b'0300' # type, flags b'deadbeef' # stream id b'0000000c' # error code b'00' # unexpected additional payload , 'hex')) assert (str(e.value) == 'Invalid number of bytes in RST_STREAM frame (must be 4)') def test_settings(self): frame_settings = FrameFactory(codecs.decode(b'00000c' # length b'0400' # type, flags b'00000000' # stream id # settings b'0004' # setting id b'00020000' # setting value b'0005' # setting id b'00004000' # setting value , 'hex')) assert (frame_settings.length == 12) assert (frame_settings.type == HTTP2_FRAME_SETTINGS) assert (frame_settings.flags == 0) assert (frame_settings.stream_id == 0) assert (len(frame_settings.settings) == 2) assert (frame_settings.settings[0].identifier == HTTP2_SETTINGS_INITIAL_WINDOW_SIZE) assert (frame_settings.settings[0].value == 0x20000) assert (frame_settings.settings[1].identifier == HTTP2_SETTINGS_MAX_FRAME_SIZE) assert (frame_settings.settings[1].value == 0x4000) # Settings ack, with empty payload frame_settings_ack = FrameFactory(codecs.decode(b'000000' # length b'0401' # type, flags b'00000000' # stream id , 'hex')) assert (frame_settings_ack.length == 0) assert (frame_settings_ack.type == HTTP2_FRAME_SETTINGS) assert (frame_settings_ack.flags == HTTP2_FLAG_ACK) assert (frame_settings_ack.stream_id == 0) assert (len(frame_settings_ack.settings) == 0) import pytest # Invalid length with pytest.raises(HTTP2Exception) as e: x = SettingsFrame(codecs.decode(b'000005' # length b'0400' # type, flags b'deadbeef' # stream id b'1234567890' # invalid length , 'hex')) assert (str(e.value) == 'Invalid number of bytes in SETTINGS frame (must be multiple of 6)') def test_push_promise(self): frame_pp = FrameFactory(codecs.decode(b'000007' # length b'0500' # type, flags b'deadbeef' # stream id b'cafebabe' # promised id b'123456' # some block fragment , 'hex')) assert (frame_pp.length == 7) assert (frame_pp.type == HTTP2_FRAME_PUSH_PROMISE) assert (frame_pp.flags == 0) assert (frame_pp.stream_id == 0xdeadbeef) assert (frame_pp.promised_id == 0xcafebabe) assert (frame_pp.block_fragment == b'\x12\x34\x56') import pytest # Invalid length with pytest.raises(HTTP2Exception) as e: x = PushPromiseFrame(codecs.decode(b'000003' # length b'0500' # type, flags b'deadbeef' # stream id b'cafeba' # missing promised id , 'hex')) assert (str(e.value) == 'Missing promised stream ID in PUSH_PROMISE frame') def test_ping(self): frame_ping = FrameFactory(codecs.decode(b'000008' # length b'0600' # type, flags b'deadbeef' # stream id b'cafebabe12345678' # user data , 'hex')) assert (frame_ping.length == 8) assert (frame_ping.type == HTTP2_FRAME_PING) assert (frame_ping.flags == 0) assert (frame_ping.stream_id == 0xdeadbeef) assert (frame_ping.data == b'\xCA\xFE\xBA\xBE\x12\x34\x56\x78') import pytest # Invalid length with pytest.raises(HTTP2Exception) as e: x = PingFrame(codecs.decode(b'000005' # length b'0600' # type, flags b'deadbeef' # stream id b'1234567890' # invalid length , 'hex')) assert (str(e.value) == 'Invalid number of bytes in PING frame (must be 8)') def test_goaway(self): frame_goaway = FrameFactory(codecs.decode(b'00000a' # length b'0700' # type, flags b'deadbeef' # stream id b'00000000' # last stream id b'00000000' # error code b'cafe' # debug data , 'hex')) assert (frame_goaway.length == 10) assert (frame_goaway.type == HTTP2_FRAME_GOAWAY) assert (frame_goaway.flags == 0) assert (frame_goaway.stream_id == 0xdeadbeef) assert (frame_goaway.last_stream_id == 0) assert (frame_goaway.error_code == HTTP2_NO_ERROR) assert (frame_goaway.debug_data == b'\xCA\xFE') import pytest # Invalid length with pytest.raises(HTTP2Exception) as e: x = GoAwayFrame(codecs.decode(b'000005' # length b'0700' # type, flags b'deadbeef' # stream id b'1234567890' # invalid length , 'hex')) assert (str(e.value) == 'Invalid number of bytes in GO_AWAY frame') def test_window_update(self): frame_wu = FrameFactory(codecs.decode(b'000004' # length b'0800' # type, flags b'deadbeef' # stream id b'12345678' # window increment , 'hex')) assert (frame_wu.length == 4) assert (frame_wu.type == HTTP2_FRAME_WINDOW_UPDATE) assert (frame_wu.flags == 0) assert (frame_wu.stream_id == 0xdeadbeef) assert (frame_wu.window_increment == 0x12345678) import pytest # Invalid length with pytest.raises(HTTP2Exception) as e: x = WindowUpdateFrame(codecs.decode(b'000005' # length b'0800' # type, flags b'deadbeef' # stream id b'1234567890' # invalid length , 'hex')) assert (str(e.value) == 'Invalid number of bytes in WINDOW_UPDATE frame (must be 4)') def test_continuation(self): frame_cont = FrameFactory(codecs.decode(b'000003' # length b'0900' # type, flags b'deadbeef' # stream id b'f00baa' # block fragment , 'hex')) assert (frame_cont.length == 3) assert (frame_cont.type == HTTP2_FRAME_CONTINUATION) assert (frame_cont.flags == 0) assert (frame_cont.stream_id == 0xdeadbeef) assert (frame_cont.block_fragment == b'\xF0\x0B\xAA') def test_factory(self): import pytest # Too short pytest.raises(dpkt.NeedData, FrameFactory, codecs.decode(b'000000', 'hex')) # Invalid type with pytest.raises(HTTP2Exception) as e: x = FrameFactory(codecs.decode(b'000000' # length b'abcd' # type, flags b'deadbeef' # stream id , 'hex')) assert (str(e.value) == 'Invalid frame type: 0xab') def test_preface(self): import pytest # Preface pytest.raises(dpkt.NeedData, Preface, codecs.decode(b'505249202a20485454502f322e300d0a', 'hex')) pytest.raises(dpkt.NeedData, Preface, b'\x00' * 23) with pytest.raises(HTTP2Exception) as e: x = Preface(b'\x00' * 24) assert (str(e.value) == 'Invalid HTTP/2 preface') def test_multi(self): assert (self.i == 128) assert (len(self.frames) == 7) assert (self.frames[0].length == 12) assert (self.frames[1].length == 4) assert (self.frames[2].length == 5) assert (self.frames[3].length == 5) assert (self.frames[4].length == 5) assert (self.frames[5].length == 5) assert (self.frames[6].length == 5) assert (self.frames[0].type == HTTP2_FRAME_SETTINGS) assert (self.frames[1].type == HTTP2_FRAME_WINDOW_UPDATE) assert (self.frames[2].type == HTTP2_FRAME_PRIORITY) assert (self.frames[3].type == HTTP2_FRAME_PRIORITY) assert (self.frames[4].type == HTTP2_FRAME_PRIORITY) assert (self.frames[5].type == HTTP2_FRAME_PRIORITY) assert (self.frames[6].type == HTTP2_FRAME_PRIORITY) assert (self.frames[0].flags == 0) assert (self.frames[1].flags == 0) assert (self.frames[2].flags == 0) assert (self.frames[3].flags == 0) assert (self.frames[4].flags == 0) assert (self.frames[5].flags == 0) assert (self.frames[6].flags == 0) assert (self.frames[0].stream_id == 0) assert (self.frames[1].stream_id == 0) assert (self.frames[2].stream_id == 3) assert (self.frames[3].stream_id == 5) assert (self.frames[4].stream_id == 7) assert (self.frames[5].stream_id == 9) assert (self.frames[6].stream_id == 11) frames, i = frame_multi_factory( codecs.decode(b'505249202a20485454502f322e300d0a', 'hex'), preface=True) assert (len(frames) == 0) assert (i == 0) # Only preface was parsed frames, i = frame_multi_factory( codecs.decode(b'505249202a20485454502f322e300d0a' b'0d0a534d0d0a0d0a00000c0400000000', 'hex'), preface=True) assert (len(frames) == 0) assert (i == 24) dpkt-1.9.2/dpkt/icmp.py000066400000000000000000000125401340335175100147350ustar00rootroot00000000000000# $Id: icmp.py 45 2007-08-03 00:05:22Z jon.oberheide $ # -*- coding: utf-8 -*- """Internet Control Message Protocol.""" from __future__ import print_function from __future__ import absolute_import from . import dpkt # Types (icmp_type) and codes (icmp_code) - # http://www.iana.org/assignments/icmp-parameters ICMP_CODE_NONE = 0 # for types without codes ICMP_ECHOREPLY = 0 # echo reply ICMP_UNREACH = 3 # dest unreachable, codes: ICMP_UNREACH_NET = 0 # bad net ICMP_UNREACH_HOST = 1 # bad host ICMP_UNREACH_PROTO = 2 # bad protocol ICMP_UNREACH_PORT = 3 # bad port ICMP_UNREACH_NEEDFRAG = 4 # IP_DF caused drop ICMP_UNREACH_SRCFAIL = 5 # src route failed ICMP_UNREACH_NET_UNKNOWN = 6 # unknown net ICMP_UNREACH_HOST_UNKNOWN = 7 # unknown host ICMP_UNREACH_ISOLATED = 8 # src host isolated ICMP_UNREACH_NET_PROHIB = 9 # for crypto devs ICMP_UNREACH_HOST_PROHIB = 10 # ditto ICMP_UNREACH_TOSNET = 11 # bad tos for net ICMP_UNREACH_TOSHOST = 12 # bad tos for host ICMP_UNREACH_FILTER_PROHIB = 13 # prohibited access ICMP_UNREACH_HOST_PRECEDENCE = 14 # precedence error ICMP_UNREACH_PRECEDENCE_CUTOFF = 15 # precedence cutoff ICMP_SRCQUENCH = 4 # packet lost, slow down ICMP_REDIRECT = 5 # shorter route, codes: ICMP_REDIRECT_NET = 0 # for network ICMP_REDIRECT_HOST = 1 # for host ICMP_REDIRECT_TOSNET = 2 # for tos and net ICMP_REDIRECT_TOSHOST = 3 # for tos and host ICMP_ALTHOSTADDR = 6 # alternate host address ICMP_ECHO = 8 # echo service ICMP_RTRADVERT = 9 # router advertise, codes: ICMP_RTRADVERT_NORMAL = 0 # normal ICMP_RTRADVERT_NOROUTE_COMMON = 16 # selective routing ICMP_RTRSOLICIT = 10 # router solicitation ICMP_TIMEXCEED = 11 # time exceeded, code: ICMP_TIMEXCEED_INTRANS = 0 # ttl==0 in transit ICMP_TIMEXCEED_REASS = 1 # ttl==0 in reass ICMP_PARAMPROB = 12 # ip header bad ICMP_PARAMPROB_ERRATPTR = 0 # req. opt. absent ICMP_PARAMPROB_OPTABSENT = 1 # req. opt. absent ICMP_PARAMPROB_LENGTH = 2 # bad length ICMP_TSTAMP = 13 # timestamp request ICMP_TSTAMPREPLY = 14 # timestamp reply ICMP_INFO = 15 # information request ICMP_INFOREPLY = 16 # information reply ICMP_MASK = 17 # address mask request ICMP_MASKREPLY = 18 # address mask reply ICMP_TRACEROUTE = 30 # traceroute ICMP_DATACONVERR = 31 # data conversion error ICMP_MOBILE_REDIRECT = 32 # mobile host redirect ICMP_IP6_WHEREAREYOU = 33 # IPv6 where-are-you ICMP_IP6_IAMHERE = 34 # IPv6 i-am-here ICMP_MOBILE_REG = 35 # mobile registration req ICMP_MOBILE_REGREPLY = 36 # mobile registration reply ICMP_DNS = 37 # domain name request ICMP_DNSREPLY = 38 # domain name reply ICMP_SKIP = 39 # SKIP ICMP_PHOTURIS = 40 # Photuris ICMP_PHOTURIS_UNKNOWN_INDEX = 0 # unknown sec index ICMP_PHOTURIS_AUTH_FAILED = 1 # auth failed ICMP_PHOTURIS_DECOMPRESS_FAILED = 2 # decompress failed ICMP_PHOTURIS_DECRYPT_FAILED = 3 # decrypt failed ICMP_PHOTURIS_NEED_AUTHN = 4 # no authentication ICMP_PHOTURIS_NEED_AUTHZ = 5 # no authorization ICMP_TYPE_MAX = 40 class ICMP(dpkt.Packet): """Internet Control Message Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of ICMP. TODO. """ __hdr__ = ( ('type', 'B', 8), ('code', 'B', 0), ('sum', 'H', 0) ) class Echo(dpkt.Packet): __hdr__ = (('id', 'H', 0), ('seq', 'H', 0)) class Quote(dpkt.Packet): __hdr__ = (('pad', 'I', 0),) def unpack(self, buf): dpkt.Packet.unpack(self, buf) from . import ip self.data = self.ip = ip.IP(self.data) class Unreach(Quote): __hdr__ = (('pad', 'H', 0), ('mtu', 'H', 0)) class Quench(Quote): pass class Redirect(Quote): __hdr__ = (('gw', 'I', 0),) class ParamProbe(Quote): __hdr__ = (('ptr', 'B', 0), ('pad1', 'B', 0), ('pad2', 'H', 0)) class TimeExceed(Quote): pass _typesw = {0: Echo, 3: Unreach, 4: Quench, 5: Redirect, 8: Echo, 11: TimeExceed} def unpack(self, buf): dpkt.Packet.unpack(self, buf) try: self.data = self._typesw[self.type](self.data) setattr(self, self.data.__class__.__name__.lower(), self.data) except (KeyError, dpkt.UnpackError): pass def __bytes__(self): if not self.sum: self.sum = dpkt.in_cksum(dpkt.Packet.__bytes__(self)) return dpkt.Packet.__bytes__(self) def test_icmp(): s = ( b'\x03\x0a\x6b\x19\x00\x00\x00\x00\x45\x00\x00\x28\x94\x1f\x00\x00\xe3\x06\x99\xb4\x23\x2b' b'\x24\x00\xde\x8e\x84\x42\xab\xd1\x00\x50\x00\x35\xe1\x29\x20\xd9\x00\x00\x00\x22\x9b\xf0' b'\xe2\x04\x65\x6b' ) r = ICMP(s) assert bytes(r) == s # construction s = ( b'\x00\x00\x53\x87\x00\x01\x03\xd6\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e' b'\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x41\x42\x43\x44\x45\x46\x47\x48\x49' ) p = ICMP( type=0, sum=0x5387, data=ICMP.Echo( id=1, seq=0x03d6, data=b'ABCDEFGHIJKLMNOPQRSTUVWABCDEFGHI' ) ) assert bytes(p) == s # test checksum p = ICMP( type=0, data=ICMP.Echo( id=1, seq=0x03d6, data=b'ABCDEFGHIJKLMNOPQRSTUVWABCDEFGHI' ) ) assert bytes(p) == s assert p.sum == 0x5387 if __name__ == '__main__': test_icmp() print('Tests Successful...') dpkt-1.9.2/dpkt/icmp6.py000066400000000000000000000047451340335175100150330ustar00rootroot00000000000000# $Id: icmp6.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Internet Control Message Protocol for IPv6.""" from __future__ import absolute_import from . import dpkt ICMP6_DST_UNREACH = 1 # dest unreachable, codes: ICMP6_PACKET_TOO_BIG = 2 # packet too big ICMP6_TIME_EXCEEDED = 3 # time exceeded, code: ICMP6_PARAM_PROB = 4 # ip6 header bad ICMP6_ECHO_REQUEST = 128 # echo service ICMP6_ECHO_REPLY = 129 # echo reply MLD_LISTENER_QUERY = 130 # multicast listener query MLD_LISTENER_REPORT = 131 # multicast listener report MLD_LISTENER_DONE = 132 # multicast listener done # RFC2292 decls ICMP6_MEMBERSHIP_QUERY = 130 # group membership query ICMP6_MEMBERSHIP_REPORT = 131 # group membership report ICMP6_MEMBERSHIP_REDUCTION = 132 # group membership termination ND_ROUTER_SOLICIT = 133 # router solicitation ND_ROUTER_ADVERT = 134 # router advertisment ND_NEIGHBOR_SOLICIT = 135 # neighbor solicitation ND_NEIGHBOR_ADVERT = 136 # neighbor advertisment ND_REDIRECT = 137 # redirect ICMP6_ROUTER_RENUMBERING = 138 # router renumbering ICMP6_WRUREQUEST = 139 # who are you request ICMP6_WRUREPLY = 140 # who are you reply ICMP6_FQDN_QUERY = 139 # FQDN query ICMP6_FQDN_REPLY = 140 # FQDN reply ICMP6_NI_QUERY = 139 # node information request ICMP6_NI_REPLY = 140 # node information reply ICMP6_MAXTYPE = 201 class ICMP6(dpkt.Packet): """Internet Control Message Protocol for IPv6. TODO: Longer class information.... Attributes: __hdr__: Header fields of ICMPv6. TODO. """ __hdr__ = ( ('type', 'B', 0), ('code', 'B', 0), ('sum', 'H', 0) ) class Error(dpkt.Packet): __hdr__ = (('pad', 'I', 0), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) from . import ip6 self.data = self.ip6 = ip6.IP6(self.data) class Unreach(Error): pass class TooBig(Error): __hdr__ = (('mtu', 'I', 1232), ) class TimeExceed(Error): pass class ParamProb(Error): __hdr__ = (('ptr', 'I', 0), ) class Echo(dpkt.Packet): __hdr__ = (('id', 'H', 0), ('seq', 'H', 0)) _typesw = {1: Unreach, 2: TooBig, 3: TimeExceed, 4: ParamProb, 128: Echo, 129: Echo} def unpack(self, buf): dpkt.Packet.unpack(self, buf) try: self.data = self._typesw[self.type](self.data) setattr(self, self.data.__class__.__name__.lower(), self.data) except (KeyError, dpkt.UnpackError): pass dpkt-1.9.2/dpkt/ieee80211.py000066400000000000000000000625721340335175100153220ustar00rootroot00000000000000# $Id: 80211.py 53 2008-12-18 01:22:57Z jon.oberheide $ # -*- coding: utf-8 -*- """IEEE 802.11.""" from __future__ import print_function from __future__ import absolute_import import socket import struct from . import dpkt from .decorators import deprecated # Frame Types MGMT_TYPE = 0 CTL_TYPE = 1 DATA_TYPE = 2 # Frame Sub-Types M_ASSOC_REQ = 0 M_ASSOC_RESP = 1 M_REASSOC_REQ = 2 M_REASSOC_RESP = 3 M_PROBE_REQ = 4 M_PROBE_RESP = 5 M_BEACON = 8 M_ATIM = 9 M_DISASSOC = 10 M_AUTH = 11 M_DEAUTH = 12 M_ACTION = 13 C_BLOCK_ACK_REQ = 8 C_BLOCK_ACK = 9 C_PS_POLL = 10 C_RTS = 11 C_CTS = 12 C_ACK = 13 C_CF_END = 14 C_CF_END_ACK = 15 D_DATA = 0 D_DATA_CF_ACK = 1 D_DATA_CF_POLL = 2 D_DATA_CF_ACK_POLL = 3 D_NULL = 4 D_CF_ACK = 5 D_CF_POLL = 6 D_CF_ACK_POLL = 7 D_QOS_DATA = 8 D_QOS_CF_ACK = 9 D_QOS_CF_POLL = 10 D_QOS_CF_ACK_POLL = 11 D_QOS_NULL = 12 D_QOS_CF_POLL_EMPTY = 14 TO_DS_FLAG = 10 FROM_DS_FLAG = 1 INTER_DS_FLAG = 11 # Bitshifts for Frame Control _VERSION_MASK = 0x0300 _TYPE_MASK = 0x0c00 _SUBTYPE_MASK = 0xf000 _TO_DS_MASK = 0x0001 _FROM_DS_MASK = 0x0002 _MORE_FRAG_MASK = 0x0004 _RETRY_MASK = 0x0008 _PWR_MGT_MASK = 0x0010 _MORE_DATA_MASK = 0x0020 _WEP_MASK = 0x0040 _ORDER_MASK = 0x0080 _VERSION_SHIFT = 8 _TYPE_SHIFT = 10 _SUBTYPE_SHIFT = 12 _TO_DS_SHIFT = 0 _FROM_DS_SHIFT = 1 _MORE_FRAG_SHIFT = 2 _RETRY_SHIFT = 3 _PWR_MGT_SHIFT = 4 _MORE_DATA_SHIFT = 5 _WEP_SHIFT = 6 _ORDER_SHIFT = 7 # IEs IE_SSID = 0 IE_RATES = 1 IE_FH = 2 IE_DS = 3 IE_CF = 4 IE_TIM = 5 IE_IBSS = 6 IE_HT_CAPA = 45 IE_ESR = 50 IE_HT_INFO = 61 FCS_LENGTH = 4 FRAMES_WITH_CAPABILITY = [M_BEACON, M_ASSOC_RESP, M_ASSOC_REQ, M_REASSOC_REQ, ] # Block Ack control constants _ACK_POLICY_SHIFT = 0 _MULTI_TID_SHIFT = 1 _COMPRESSED_SHIFT = 2 _TID_SHIFT = 12 _ACK_POLICY_MASK = 0x0001 _MULTI_TID_MASK = 0x0002 _COMPRESSED_MASK = 0x0004 _TID_MASK = 0xf000 _COMPRESSED_BMP_LENGTH = 8 _BMP_LENGTH = 128 # Action frame categories BLOCK_ACK = 3 # Block ack category action codes BLOCK_ACK_CODE_REQUEST = 0 BLOCK_ACK_CODE_RESPONSE = 1 class IEEE80211(dpkt.Packet): """IEEE 802.11. TODO: Longer class information.... Attributes: __hdr__: Header fields of IEEE802.11. TODO. """ __hdr__ = ( ('framectl', 'H', 0), ('duration', 'H', 0) ) @property def version(self): return (self.framectl & _VERSION_MASK) >> _VERSION_SHIFT @version.setter def version(self, val): self.framectl = (val << _VERSION_SHIFT) | (self.framectl & ~_VERSION_MASK) @property def type(self): return (self.framectl & _TYPE_MASK) >> _TYPE_SHIFT @type.setter def type(self, val): self.framectl = (val << _TYPE_SHIFT) | (self.framectl & ~_TYPE_MASK) @property def subtype(self): return (self.framectl & _SUBTYPE_MASK) >> _SUBTYPE_SHIFT @subtype.setter def subtype(self, val): self.framectl = (val << _SUBTYPE_SHIFT) | (self.framectl & ~_SUBTYPE_MASK) @property def to_ds(self): return (self.framectl & _TO_DS_MASK) >> _TO_DS_SHIFT @to_ds.setter def to_ds(self, val): self.framectl = (val << _TO_DS_SHIFT) | (self.framectl & ~_TO_DS_MASK) @property def from_ds(self): return (self.framectl & _FROM_DS_MASK) >> _FROM_DS_SHIFT @from_ds.setter def from_ds(self, val): self.framectl = (val << _FROM_DS_SHIFT) | (self.framectl & ~_FROM_DS_MASK) @property def more_frag(self): return (self.framectl & _MORE_FRAG_MASK) >> _MORE_FRAG_SHIFT @more_frag.setter def more_frag(self, val): self.framectl = (val << _MORE_FRAG_SHIFT) | (self.framectl & ~_MORE_FRAG_MASK) @property def retry(self): return (self.framectl & _RETRY_MASK) >> _RETRY_SHIFT @retry.setter def retry(self, val): self.framectl = (val << _RETRY_SHIFT) | (self.framectl & ~_RETRY_MASK) @property def pwr_mgt(self): return (self.framectl & _PWR_MGT_MASK) >> _PWR_MGT_SHIFT @pwr_mgt.setter def pwr_mgt(self, val): self.framectl = (val << _PWR_MGT_SHIFT) | (self.framectl & ~_PWR_MGT_MASK) @property def more_data(self): return (self.framectl & _MORE_DATA_MASK) >> _MORE_DATA_SHIFT @more_data.setter def more_data(self, val): self.framectl = (val << _MORE_DATA_SHIFT) | (self.framectl & ~_MORE_DATA_MASK) @property def wep(self): return (self.framectl & _WEP_MASK) >> _WEP_SHIFT @wep.setter def wep(self, val): self.framectl = (val << _WEP_SHIFT) | (self.framectl & ~_WEP_MASK) @property def order(self): return (self.framectl & _ORDER_MASK) >> _ORDER_SHIFT @order.setter def order(self, val): self.framectl = (val << _ORDER_SHIFT) | (self.framectl & ~_ORDER_MASK) def unpack_ies(self, buf): self.ies = [] ie_decoder = { IE_SSID: ('ssid', self.IE), IE_RATES: ('rate', self.IE), IE_FH: ('fh', self.FH), IE_DS: ('ds', self.DS), IE_CF: ('cf', self.CF), IE_TIM: ('tim', self.TIM), IE_IBSS: ('ibss', self.IBSS), IE_HT_CAPA: ('ht_capa', self.IE), IE_ESR: ('esr', self.IE), IE_HT_INFO: ('ht_info', self.IE) } # each IE starts with an ID and a length while len(buf) > FCS_LENGTH: ie_id = struct.unpack('B', buf[:1])[0] try: parser = ie_decoder[ie_id][1] name = ie_decoder[ie_id][0] except KeyError: parser = self.IE name = 'ie_' + str(ie_id) ie = parser(buf) ie.data = buf[2:2 + ie.len] setattr(self, name, ie) self.ies.append(ie) buf = buf[2 + ie.len:] class Capability(object): def __init__(self, field): self.ess = field & 1 self.ibss = (field >> 1) & 1 self.cf_poll = (field >> 2) & 1 self.cf_poll_req = (field >> 3) & 1 self.privacy = (field >> 4) & 1 self.short_preamble = (field >> 5) & 1 self.pbcc = (field >> 6) & 1 self.hopping = (field >> 7) & 1 self.spec_mgmt = (field >> 8) & 1 self.qos = (field >> 9) & 1 self.short_slot = (field >> 10) & 1 self.apsd = (field >> 11) & 1 self.dsss = (field >> 13) & 1 self.delayed_blk_ack = (field >> 14) & 1 self.imm_blk_ack = (field >> 15) & 1 def __init__(self, *args, **kwargs): if kwargs and 'fcs' in kwargs: self.fcs_present = kwargs.pop('fcs') else: self.fcs_present = False super(IEEE80211, self).__init__(*args, **kwargs) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.data = buf[self.__hdr_len__:] m_decoder = { M_BEACON: ('beacon', self.Beacon), M_ASSOC_REQ: ('assoc_req', self.Assoc_Req), M_ASSOC_RESP: ('assoc_resp', self.Assoc_Resp), M_DISASSOC: ('diassoc', self.Disassoc), M_REASSOC_REQ: ('reassoc_req', self.Reassoc_Req), M_REASSOC_RESP: ('reassoc_resp', self.Assoc_Resp), M_AUTH: ('auth', self.Auth), M_PROBE_RESP: ('probe_resp', self.Beacon), M_DEAUTH: ('deauth', self.Deauth), M_ACTION: ('action', self.Action) } c_decoder = { C_RTS: ('rts', self.RTS), C_CTS: ('cts', self.CTS), C_ACK: ('ack', self.ACK), C_BLOCK_ACK_REQ: ('bar', self.BlockAckReq), C_BLOCK_ACK: ('back', self.BlockAck), C_CF_END: ('cf_end', self.CFEnd), } d_dsData = { 0: self.Data, FROM_DS_FLAG: self.DataFromDS, TO_DS_FLAG: self.DataToDS, INTER_DS_FLAG: self.DataInterDS } # For now decode everything with DATA. Haven't checked about other QoS # additions d_decoder = { # modified the decoder to consider the ToDS and FromDS flags # Omitting the 11 case for now D_DATA: ('data_frame', d_dsData), D_NULL: ('data_frame', d_dsData), D_QOS_DATA: ('data_frame', d_dsData), D_QOS_NULL: ('data_frame', d_dsData) } decoder = { MGMT_TYPE: m_decoder, CTL_TYPE: c_decoder, DATA_TYPE: d_decoder } # Strip off the FCS field if self.fcs_present: self.fcs = struct.unpack('I', self.data[-1 * FCS_LENGTH:])[0] self.data = self.data[0: -1 * FCS_LENGTH] if self.type == MGMT_TYPE: self.mgmt = self.MGMT_Frame(self.data) self.data = self.mgmt.data if self.subtype == M_PROBE_REQ: self.unpack_ies(self.data) return if self.subtype == M_ATIM: return try: parser = decoder[self.type][self.subtype][1] name = decoder[self.type][self.subtype][0] except KeyError: raise dpkt.UnpackError("KeyError: type=%s subtype=%s" % (self.type, self.subtype)) if self.type == DATA_TYPE: # need to grab the ToDS/FromDS info parser = parser[self.to_ds * 10 + self.from_ds] if self.type == MGMT_TYPE: field = parser(self.mgmt.data) else: field = parser(self.data) self.data = field setattr(self, name, field) if self.type == MGMT_TYPE: self.unpack_ies(field.data) if self.subtype in FRAMES_WITH_CAPABILITY: self.capability = self.Capability(socket.ntohs(field.capability)) if self.type == DATA_TYPE and self.subtype == D_QOS_DATA: self.qos_data = self.QoS_Data(field.data) field.data = self.qos_data.data self.data = field.data class BlockAckReq(dpkt.Packet): __hdr__ = ( ('dst', '6s', '\x00' * 6), ('src', '6s', '\x00' * 6), ('ctl', 'H', 0), ('seq', 'H', 0), ) class BlockAck(dpkt.Packet): __hdr__ = ( ('dst', '6s', '\x00' * 6), ('src', '6s', '\x00' * 6), ('ctl', 'H', 0), ('seq', 'H', 0), ) @property def compressed(self): return (self.ctl & _COMPRESSED_MASK) >> _COMPRESSED_SHIFT @compressed.setter def compressed(self, val): self.ctl = (val << _COMPRESSED_SHIFT) | (self.ctl & ~_COMPRESSED_MASK) @property def ack_policy(self): return (self.ctl & _ACK_POLICY_MASK) >> _ACK_POLICY_SHIFT @ack_policy.setter def ack_policy(self, val): self.ctl = (val << _ACK_POLICY_SHIFT) | (self.ctl & ~_ACK_POLICY_MASK) @property def multi_tid(self): return (self.ctl & _MULTI_TID_MASK) >> _MULTI_TID_SHIFT @multi_tid.setter def multi_tid(self, val): self.ctl = (val << _MULTI_TID_SHIFT) | (self.ctl & ~_MULTI_TID_MASK) @property def tid(self): return (self.ctl & _TID_MASK) >> _TID_SHIFT @tid.setter def tid(self, val): self.ctl = (val << _TID_SHIFT) | (self.ctl & ~_TID_MASK) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.data = buf[self.__hdr_len__:] self.ctl = socket.ntohs(self.ctl) if self.compressed: self.bmp = struct.unpack('8s', self.data[0:_COMPRESSED_BMP_LENGTH])[0] else: self.bmp = struct.unpack('128s', self.data[0:_BMP_LENGTH])[0] self.data = self.data[len(self.__hdr__) + len(self.bmp):] class RTS(dpkt.Packet): __hdr__ = ( ('dst', '6s', '\x00' * 6), ('src', '6s', '\x00' * 6) ) class CTS(dpkt.Packet): __hdr__ = ( ('dst', '6s', '\x00' * 6), ) class ACK(dpkt.Packet): __hdr__ = ( ('dst', '6s', '\x00' * 6), ) class CFEnd(dpkt.Packet): __hdr__ = ( ('dst', '6s', '\x00' * 6), ('src', '6s', '\x00' * 6), ) class MGMT_Frame(dpkt.Packet): __hdr__ = ( ('dst', '6s', '\x00' * 6), ('src', '6s', '\x00' * 6), ('bssid', '6s', '\x00' * 6), ('frag_seq', 'H', 0) ) class Beacon(dpkt.Packet): __hdr__ = ( ('timestamp', 'Q', 0), ('interval', 'H', 0), ('capability', 'H', 0) ) class Disassoc(dpkt.Packet): __hdr__ = ( ('reason', 'H', 0), ) class Assoc_Req(dpkt.Packet): __hdr__ = ( ('capability', 'H', 0), ('interval', 'H', 0) ) class Assoc_Resp(dpkt.Packet): __hdr__ = ( ('capability', 'H', 0), ('status', 'H', 0), ('aid', 'H', 0) ) class Reassoc_Req(dpkt.Packet): __hdr__ = ( ('capability', 'H', 0), ('interval', 'H', 0), ('current_ap', '6s', '\x00' * 6) ) # This obviously doesn't support any of AUTH frames that use encryption class Auth(dpkt.Packet): __hdr__ = ( ('algorithm', 'H', 0), ('auth_seq', 'H', 0), ) class Deauth(dpkt.Packet): __hdr__ = ( ('reason', 'H', 0), ) class Action(dpkt.Packet): __hdr__ = ( ('category', 'B', 0), ('code', 'B', 0), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) action_parser = { BLOCK_ACK: { BLOCK_ACK_CODE_REQUEST: ('block_ack_request', IEEE80211.BlockAckActionRequest), BLOCK_ACK_CODE_RESPONSE: ('block_ack_response', IEEE80211.BlockAckActionResponse), }, } try: decoder = action_parser[self.category][self.code][1] field_name = action_parser[self.category][self.code][0] except KeyError: raise dpkt.UnpackError("KeyError: category=%s code=%s" % (self.category, self.code)) field = decoder(self.data) setattr(self, field_name, field) self.data = field.data class BlockAckActionRequest(dpkt.Packet): __hdr__ = ( ('dialog', 'B', 0), ('parameters', 'H', 0), ('timeout', 'H', 0), ('starting_seq', 'H', 0), ) class BlockAckActionResponse(dpkt.Packet): __hdr__ = ( ('dialog', 'B', 0), ('status_code', 'H', 0), ('parameters', 'H', 0), ('timeout', 'H', 0), ) class Data(dpkt.Packet): __hdr__ = ( ('dst', '6s', '\x00' * 6), ('src', '6s', '\x00' * 6), ('bssid', '6s', '\x00' * 6), ('frag_seq', 'H', 0) ) class DataFromDS(dpkt.Packet): __hdr__ = ( ('dst', '6s', '\x00' * 6), ('bssid', '6s', '\x00' * 6), ('src', '6s', '\x00' * 6), ('frag_seq', 'H', 0) ) class DataToDS(dpkt.Packet): __hdr__ = ( ('bssid', '6s', '\x00' * 6), ('src', '6s', '\x00' * 6), ('dst', '6s', '\x00' * 6), ('frag_seq', 'H', 0) ) class DataInterDS(dpkt.Packet): __hdr__ = ( ('dst', '6s', '\x00' * 6), ('src', '6s', '\x00' * 6), ('da', '6s', '\x00' * 6), ('frag_seq', 'H', 0), ('sa', '6s', '\x00' * 6) ) class QoS_Data(dpkt.Packet): __hdr__ = ( ('control', 'H', 0), ) class IE(dpkt.Packet): __hdr__ = ( ('id', 'B', 0), ('len', 'B', 0) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.info = buf[2:self.len + 2] class FH(dpkt.Packet): __hdr__ = ( ('id', 'B', 0), ('len', 'B', 0), ('tu', 'H', 0), ('hopset', 'B', 0), ('hoppattern', 'B', 0), ('hopindex', 'B', 0) ) class DS(dpkt.Packet): __hdr__ = ( ('id', 'B', 0), ('len', 'B', 0), ('ch', 'B', 0) ) class CF(dpkt.Packet): __hdr__ = ( ('id', 'B', 0), ('len', 'B', 0), ('count', 'B', 0), ('period', 'B', 0), ('max', 'H', 0), ('dur', 'H', 0) ) class TIM(dpkt.Packet): __hdr__ = ( ('id', 'B', 0), ('len', 'B', 0), ('count', 'B', 0), ('period', 'B', 0), ('ctrl', 'H', 0) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.bitmap = buf[5:self.len + 2] class IBSS(dpkt.Packet): __hdr__ = ( ('id', 'B', 0), ('len', 'B', 0), ('atim', 'H', 0) ) def test_802211_ack(): s = b'\xd4\x00\x00\x00\x00\x12\xf0\xb6\x1c\xa4\xff\xff\xff\xff' ieee = IEEE80211(s, fcs=True) assert ieee.version == 0 assert ieee.type == CTL_TYPE assert ieee.subtype == C_ACK assert ieee.to_ds == 0 assert ieee.from_ds == 0 assert ieee.pwr_mgt == 0 assert ieee.more_data == 0 assert ieee.wep == 0 assert ieee.order == 0 assert ieee.ack.dst == b'\x00\x12\xf0\xb6\x1c\xa4' fcs = struct.unpack('I', s[-4:])[0] assert ieee.fcs == fcs def test_80211_beacon(): s = b'\x80\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x26\xcb\x18\x6a\x30\x00\x26\xcb\x18\x6a\x30\xa0\xd0\x77\x09\x32\x03\x8f\x00\x00\x00\x66\x00\x31\x04\x00\x04\x43\x41\x45\x4e\x01\x08\x82\x84\x8b\x0c\x12\x96\x18\x24\x03\x01\x01\x05\x04\x00\x01\x00\x00\x07\x06\x55\x53\x20\x01\x0b\x1a\x0b\x05\x00\x00\x6e\x00\x00\x2a\x01\x02\x2d\x1a\x6e\x18\x1b\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x30\x14\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x28\x00\x32\x04\x30\x48\x60\x6c\x36\x03\x51\x63\x03\x3d\x16\x01\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x85\x1e\x05\x00\x8f\x00\x0f\x00\xff\x03\x59\x00\x63\x73\x65\x2d\x33\x39\x31\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x36\x96\x06\x00\x40\x96\x00\x14\x00\xdd\x18\x00\x50\xf2\x02\x01\x01\x80\x00\x03\xa4\x00\x00\x27\xa4\x00\x00\x42\x43\x5e\x00\x62\x32\x2f\x00\xdd\x06\x00\x40\x96\x01\x01\x04\xdd\x05\x00\x40\x96\x03\x05\xdd\x05\x00\x40\x96\x0b\x09\xdd\x08\x00\x40\x96\x13\x01\x00\x34\x01\xdd\x05\x00\x40\x96\x14\x05' ieee = IEEE80211(s, fcs=True) assert ieee.version == 0 assert ieee.type == MGMT_TYPE assert ieee.subtype == M_BEACON assert ieee.to_ds == 0 assert ieee.from_ds == 0 assert ieee.pwr_mgt == 0 assert ieee.more_data == 0 assert ieee.wep == 0 assert ieee.order == 0 assert ieee.mgmt.dst == b'\xff\xff\xff\xff\xff\xff' assert ieee.mgmt.src == b'\x00\x26\xcb\x18\x6a\x30' assert ieee.beacon.capability == 0x3104 assert ieee.capability.privacy == 1 assert ieee.ssid.data == b'CAEN' assert ieee.rate.data == b'\x82\x84\x8b\x0c\x12\x96\x18\x24' assert ieee.ds.data == b'\x01' assert ieee.tim.data == b'\x00\x01\x00\x00' fcs = struct.unpack('I', s[-4:])[0] assert ieee.fcs == fcs def test_80211_data(): s = b'\x08\x09\x20\x00\x00\x26\xcb\x17\x3d\x91\x00\x16\x44\xb0\xae\xc6\x00\x02\xb3\xd6\x26\x3c\x80\x7e\xaa\xaa\x03\x00\x00\x00\x08\x00\x45\x00\x00\x28\x07\x27\x40\x00\x80\x06\x1d\x39\x8d\xd4\x37\x3d\x3f\xf5\xd1\x69\xc0\x5f\x01\xbb\xb2\xd6\xef\x23\x38\x2b\x4f\x08\x50\x10\x42\x04\xac\x17\x00\x00' ieee = IEEE80211(s, fcs=True) assert ieee.type == DATA_TYPE assert ieee.subtype == D_DATA assert ieee.data_frame.dst == b'\x00\x02\xb3\xd6\x26\x3c' assert ieee.data_frame.src == b'\x00\x16\x44\xb0\xae\xc6' assert ieee.data_frame.frag_seq == 0x807e assert ieee.data == b'\xaa\xaa\x03\x00\x00\x00\x08\x00\x45\x00\x00\x28\x07\x27\x40\x00\x80\x06\x1d\x39\x8d\xd4\x37\x3d\x3f\xf5\xd1\x69\xc0\x5f\x01\xbb\xb2\xd6\xef\x23\x38\x2b\x4f\x08\x50\x10\x42\x04' assert ieee.fcs == struct.unpack('I', b'\xac\x17\x00\x00')[0] from . import llc llc_pkt = llc.LLC(ieee.data_frame.data) ip_pkt = llc_pkt.data assert ip_pkt.dst == b'\x3f\xf5\xd1\x69' def test_80211_data_qos(): s = b'\x88\x01\x3a\x01\x00\x26\xcb\x17\x44\xf0\x00\x23\xdf\xc9\xc0\x93\x00\x26\xcb\x17\x44\xf0\x20\x7b\x00\x00\xaa\xaa\x03\x00\x00\x00\x88\x8e\x01\x00\x00\x74\x02\x02\x00\x74\x19\x80\x00\x00\x00\x6a\x16\x03\x01\x00\x65\x01\x00\x00\x61\x03\x01\x4b\x4c\xa7\x7e\x27\x61\x6f\x02\x7b\x3c\x72\x39\xe3\x7b\xd7\x43\x59\x91\x7f\xaa\x22\x47\x51\xb6\x88\x9f\x85\x90\x87\x5a\xd1\x13\x20\xe0\x07\x00\x00\x68\xbd\xa4\x13\xb0\xd5\x82\x7e\xc7\xfb\xe7\xcc\xab\x6e\x5d\x5a\x51\x50\xd4\x45\xc5\xa1\x65\x53\xad\xb5\x88\x5b\x00\x1a\x00\x2f\x00\x05\x00\x04\x00\x35\x00\x0a\x00\x09\x00\x03\x00\x08\x00\x33\x00\x39\x00\x16\x00\x15\x00\x14\x01\x00\xff\xff\xff\xff' ieee = IEEE80211(s, fcs=True) assert ieee.type == DATA_TYPE assert ieee.subtype == D_QOS_DATA assert ieee.data_frame.dst == b'\x00\x26\xcb\x17\x44\xf0' assert ieee.data_frame.src == b'\x00\x23\xdf\xc9\xc0\x93' assert ieee.data_frame.frag_seq == 0x207b assert ieee.data == b'\xaa\xaa\x03\x00\x00\x00\x88\x8e\x01\x00\x00\x74\x02\x02\x00\x74\x19\x80\x00\x00\x00\x6a\x16\x03\x01\x00\x65\x01\x00\x00\x61\x03\x01\x4b\x4c\xa7\x7e\x27\x61\x6f\x02\x7b\x3c\x72\x39\xe3\x7b\xd7\x43\x59\x91\x7f\xaa\x22\x47\x51\xb6\x88\x9f\x85\x90\x87\x5a\xd1\x13\x20\xe0\x07\x00\x00\x68\xbd\xa4\x13\xb0\xd5\x82\x7e\xc7\xfb\xe7\xcc\xab\x6e\x5d\x5a\x51\x50\xd4\x45\xc5\xa1\x65\x53\xad\xb5\x88\x5b\x00\x1a\x00\x2f\x00\x05\x00\x04\x00\x35\x00\x0a\x00\x09\x00\x03\x00\x08\x00\x33\x00\x39\x00\x16\x00\x15\x00\x14\x01\x00' assert ieee.qos_data.control == 0x0 assert ieee.fcs == struct.unpack('I', b'\xff\xff\xff\xff')[0] def test_bug(): s = b'\x88\x41\x2c\x00\x00\x26\xcb\x17\x44\xf0\x00\x1e\x52\x97\x14\x11\x00\x1f\x6d\xe8\x18\x00\xd0\x07\x00\x00\x6f\x00\x00\x20\x00\x00\x00\x00' ieee = IEEE80211(s) assert ieee.wep == 1 def test_data_ds(): # verifying the ToDS and FromDS fields and that we're getting the # correct values s = b'\x08\x03\x00\x00\x01\x0b\x85\x00\x00\x00\x00\x26\xcb\x18\x73\x50\x01\x0b\x85\x00\x00\x00\x00\x89\x00\x26\xcb\x18\x73\x50' ieee = IEEE80211(s) assert ieee.type == DATA_TYPE assert ieee.to_ds == 1 assert ieee.from_ds == 1 assert ieee.data_frame.sa == b'\x00\x26\xcb\x18\x73\x50' assert ieee.data_frame.src == b'\x00\x26\xcb\x18\x73\x50' assert ieee.data_frame.dst == b'\x01\x0b\x85\x00\x00\x00' assert ieee.data_frame.da == b'\x01\x0b\x85\x00\x00\x00' s = b'\x88\x41\x50\x01\x00\x26\xcb\x17\x48\xc1\x00\x24\x2c\xe7\xfe\x8a\xff\xff\xff\xff\xff\xff\x80\xa0\x00\x00\x09\x1a\x00\x20\x00\x00\x00\x00' ieee = IEEE80211(s) assert ieee.type == DATA_TYPE assert ieee.to_ds == 1 assert ieee.from_ds == 0 assert ieee.data_frame.bssid == b'\x00\x26\xcb\x17\x48\xc1' assert ieee.data_frame.src == b'\x00\x24\x2c\xe7\xfe\x8a' assert ieee.data_frame.dst == b'\xff\xff\xff\xff\xff\xff' s = b'\x08\x02\x02\x01\x00\x02\x44\xac\x27\x70\x00\x1f\x33\x39\x75\x44\x00\x1f\x33\x39\x75\x44\x90\xa4' ieee = IEEE80211(s) assert ieee.type == DATA_TYPE assert ieee.to_ds == 0 assert ieee.from_ds == 1 assert ieee.data_frame.bssid == b'\x00\x1f\x33\x39\x75\x44' assert ieee.data_frame.src == b'\x00\x1f\x33\x39\x75\x44' assert ieee.data_frame.dst == b'\x00\x02\x44\xac\x27\x70' def test_compressed_block_ack(): s = b'\x94\x00\x00\x00\x34\xc0\x59\xd6\x3f\x62\xb4\x75\x0e\x46\x83\xc1\x05\x50\x80\xee\x03\x00\x00\x00\x00\x00\x00\x00\xa2\xe4\x98\x45' ieee = IEEE80211(s, fcs=True) assert ieee.type == CTL_TYPE assert ieee.subtype == C_BLOCK_ACK assert ieee.back.dst == b'\x34\xc0\x59\xd6\x3f\x62' assert ieee.back.src == b'\xb4\x75\x0e\x46\x83\xc1' assert ieee.back.compressed == 1 assert len(ieee.back.bmp) == 8 assert ieee.back.ack_policy == 1 assert ieee.back.tid == 5 def test_action_block_ack_request(): s = b'\xd0\x00\x3a\x01\x00\x23\x14\x36\x52\x30\xb4\x75\x0e\x46\x83\xc1\xb4\x75\x0e\x46\x83\xc1\x70\x14\x03\x00\x0d\x02\x10\x00\x00\x40\x29\x06\x50\x33\x9e' ieee = IEEE80211(s, fcs=True) assert ieee.type == MGMT_TYPE assert ieee.subtype == M_ACTION assert ieee.action.category == BLOCK_ACK assert ieee.action.code == BLOCK_ACK_CODE_REQUEST assert ieee.action.block_ack_request.timeout == 0 parameters = struct.unpack('H', b'\x10\x02')[0] assert ieee.action.block_ack_request.parameters == parameters def test_action_block_ack_response(): s = b'\xd0\x00\x3c\x00\xb4\x75\x0e\x46\x83\xc1\x00\x23\x14\x36\x52\x30\xb4\x75\x0e\x46\x83\xc1\xd0\x68\x03\x01\x0d\x00\x00\x02\x10\x88\x13\x9f\xc0\x0b\x75' ieee = IEEE80211(s, fcs=True) assert ieee.type == MGMT_TYPE assert ieee.subtype == M_ACTION assert ieee.action.category == BLOCK_ACK assert ieee.action.code == BLOCK_ACK_CODE_RESPONSE timeout = struct.unpack('H', b'\x13\x88')[0] assert ieee.action.block_ack_response.timeout == timeout parameters = struct.unpack('H', b'\x10\x02')[0] assert ieee.action.block_ack_response.parameters == parameters if __name__ == '__main__': # Runs all the test associated with this class/file test_802211_ack() test_80211_beacon() test_80211_data() test_80211_data_qos() test_bug() test_data_ds() test_compressed_block_ack() test_action_block_ack_request() test_action_block_ack_response() print('Tests Successful...') dpkt-1.9.2/dpkt/igmp.py000066400000000000000000000012261340335175100147400ustar00rootroot00000000000000# $Id: igmp.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Internet Group Management Protocol.""" from __future__ import absolute_import from . import dpkt class IGMP(dpkt.Packet): """Internet Group Management Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of IGMP. TODO. """ __hdr__ = ( ('type', 'B', 0), ('maxresp', 'B', 0), ('sum', 'H', 0), ('group', '4s', '\x00' * 4) ) def __bytes__(self): if not self.sum: self.sum = dpkt.in_cksum(dpkt.Packet.__bytes__(self)) return dpkt.Packet.__bytes__(self) dpkt-1.9.2/dpkt/ip.py000066400000000000000000000341211340335175100144140ustar00rootroot00000000000000# $Id: ip.py 87 2013-03-05 19:41:04Z andrewflnr@gmail.com $ # -*- coding: utf-8 -*- """Internet Protocol.""" from __future__ import print_function from __future__ import absolute_import from . import dpkt from .decorators import deprecated from .compat import iteritems class IP(dpkt.Packet): """Internet Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of IP. TODO. """ __hdr__ = ( ('_v_hl', 'B', (4 << 4) | (20 >> 2)), ('tos', 'B', 0), ('len', 'H', 20), ('id', 'H', 0), ('off', 'H', 0), ('ttl', 'B', 64), ('p', 'B', 0), ('sum', 'H', 0), ('src', '4s', b'\x00' * 4), ('dst', '4s', b'\x00' * 4) ) _protosw = {} opts = b'' def __init__(self, *args, **kwargs): super(IP, self).__init__(*args, **kwargs) # If IP packet is not initialized by string and the len field has # been rewritten. if not args and 'len' not in kwargs: self.len = self.__len__() @property def v(self): return self._v_hl >> 4 @v.setter def v(self, v): self._v_hl = (v << 4) | (self._v_hl & 0xf) @property def hl(self): return self._v_hl & 0xf @hl.setter def hl(self, hl): self._v_hl = (self._v_hl & 0xf0) | hl @property def rf(self): return (self.off >> 15) & 0x1 @rf.setter def rf(self, rf): self.off = (self.off & ~IP_RF) | (rf << 15) @property def df(self): return (self.off >> 14) & 0x1 @df.setter def df(self, df): self.off = (self.off & ~IP_DF) | (df << 14) @property def mf(self): return (self.off >> 13) & 0x1 @mf.setter def mf(self, mf): self.off = (self.off & ~IP_MF) | (mf << 13) @property def offset(self): return (self.off & IP_OFFMASK) << 3 @offset.setter def offset(self, offset): self.off = (self.off & ~IP_OFFMASK) | (offset >> 3) def __len__(self): return self.__hdr_len__ + len(self.opts) + len(self.data) def __bytes__(self): self.len = self.__len__() if self.sum == 0: self.sum = dpkt.in_cksum(self.pack_hdr() + bytes(self.opts)) if (self.p == 6 or self.p == 17) and (self.off & (IP_MF | IP_OFFMASK)) == 0 and \ isinstance(self.data, dpkt.Packet) and self.data.sum == 0: # Set zeroed TCP and UDP checksums for non-fragments. p = bytes(self.data) s = dpkt.struct.pack('>4s4sxBH', self.src, self.dst, self.p, len(p)) s = dpkt.in_cksum_add(0, s) s = dpkt.in_cksum_add(s, p) self.data.sum = dpkt.in_cksum_done(s) if self.p == 17 and self.data.sum == 0: self.data.sum = 0xffff # RFC 768 # XXX - skip transports which don't need the pseudoheader return self.pack_hdr() + bytes(self.opts) + bytes(self.data) def unpack(self, buf): dpkt.Packet.unpack(self, buf) ol = ((self._v_hl & 0xf) << 2) - self.__hdr_len__ if ol < 0: raise dpkt.UnpackError('invalid header length') self.opts = buf[self.__hdr_len__:self.__hdr_len__ + ol] if self.len: buf = buf[self.__hdr_len__ + ol:self.len] else: # very likely due to TCP segmentation offload buf = buf[self.__hdr_len__ + ol:] try: self.data = self._protosw[self.p](buf) if self.offset == 0 else buf setattr(self, self.data.__class__.__name__.lower(), self.data) except (KeyError, dpkt.UnpackError): self.data = buf @classmethod def set_proto(cls, p, pktclass): cls._protosw[p] = pktclass @classmethod def get_proto(cls, p): return cls._protosw[p] # IP Headers IP_ADDR_LEN = 0x04 IP_ADDR_BITS = 0x20 IP_HDR_LEN = 0x14 IP_OPT_LEN = 0x02 IP_OPT_LEN_MAX = 0x28 IP_HDR_LEN_MAX = IP_HDR_LEN + IP_OPT_LEN_MAX IP_LEN_MAX = 0xffff IP_LEN_MIN = IP_HDR_LEN # Reserved Addresses IP_ADDR_ANY = "\x00\x00\x00\x00" # 0.0.0.0 IP_ADDR_BROADCAST = "\xff\xff\xff\xff" # 255.255.255.255 IP_ADDR_LOOPBACK = "\x7f\x00\x00\x01" # 127.0.0.1 IP_ADDR_MCAST_ALL = "\xe0\x00\x00\x01" # 224.0.0.1 IP_ADDR_MCAST_LOCAL = "\xe0\x00\x00\xff" # 224.0.0.255 # Type of service (ip_tos), RFC 1349 ("obsoleted by RFC 2474") IP_TOS_DEFAULT = 0x00 # default IP_TOS_LOWDELAY = 0x10 # low delay IP_TOS_THROUGHPUT = 0x08 # high throughput IP_TOS_RELIABILITY = 0x04 # high reliability IP_TOS_LOWCOST = 0x02 # low monetary cost - XXX IP_TOS_ECT = 0x02 # ECN-capable transport IP_TOS_CE = 0x01 # congestion experienced # IP precedence (high 3 bits of ip_tos), hopefully unused IP_TOS_PREC_ROUTINE = 0x00 IP_TOS_PREC_PRIORITY = 0x20 IP_TOS_PREC_IMMEDIATE = 0x40 IP_TOS_PREC_FLASH = 0x60 IP_TOS_PREC_FLASHOVERRIDE = 0x80 IP_TOS_PREC_CRITIC_ECP = 0xa0 IP_TOS_PREC_INTERNETCONTROL = 0xc0 IP_TOS_PREC_NETCONTROL = 0xe0 # Fragmentation flags (ip_off) IP_RF = 0x8000 # reserved IP_DF = 0x4000 # don't fragment IP_MF = 0x2000 # more fragments (not last frag) IP_OFFMASK = 0x1fff # mask for fragment offset # Time-to-live (ip_ttl), seconds IP_TTL_DEFAULT = 64 # default ttl, RFC 1122, RFC 1340 IP_TTL_MAX = 255 # maximum ttl # Protocol (ip_p) - http://www.iana.org/assignments/protocol-numbers IP_PROTO_IP = 0 # dummy for IP IP_PROTO_HOPOPTS = IP_PROTO_IP # IPv6 hop-by-hop options IP_PROTO_ICMP = 1 # ICMP IP_PROTO_IGMP = 2 # IGMP IP_PROTO_GGP = 3 # gateway-gateway protocol IP_PROTO_IPIP = 4 # IP in IP IP_PROTO_ST = 5 # ST datagram mode IP_PROTO_TCP = 6 # TCP IP_PROTO_CBT = 7 # CBT IP_PROTO_EGP = 8 # exterior gateway protocol IP_PROTO_IGP = 9 # interior gateway protocol IP_PROTO_BBNRCC = 10 # BBN RCC monitoring IP_PROTO_NVP = 11 # Network Voice Protocol IP_PROTO_PUP = 12 # PARC universal packet IP_PROTO_ARGUS = 13 # ARGUS IP_PROTO_EMCON = 14 # EMCON IP_PROTO_XNET = 15 # Cross Net Debugger IP_PROTO_CHAOS = 16 # Chaos IP_PROTO_UDP = 17 # UDP IP_PROTO_MUX = 18 # multiplexing IP_PROTO_DCNMEAS = 19 # DCN measurement IP_PROTO_HMP = 20 # Host Monitoring Protocol IP_PROTO_PRM = 21 # Packet Radio Measurement IP_PROTO_IDP = 22 # Xerox NS IDP IP_PROTO_TRUNK1 = 23 # Trunk-1 IP_PROTO_TRUNK2 = 24 # Trunk-2 IP_PROTO_LEAF1 = 25 # Leaf-1 IP_PROTO_LEAF2 = 26 # Leaf-2 IP_PROTO_RDP = 27 # "Reliable Datagram" proto IP_PROTO_IRTP = 28 # Inet Reliable Transaction IP_PROTO_TP = 29 # ISO TP class 4 IP_PROTO_NETBLT = 30 # Bulk Data Transfer IP_PROTO_MFPNSP = 31 # MFE Network Services IP_PROTO_MERITINP = 32 # Merit Internodal Protocol IP_PROTO_SEP = 33 # Sequential Exchange proto IP_PROTO_3PC = 34 # Third Party Connect proto IP_PROTO_IDPR = 35 # Interdomain Policy Route IP_PROTO_XTP = 36 # Xpress Transfer Protocol IP_PROTO_DDP = 37 # Datagram Delivery Proto IP_PROTO_CMTP = 38 # IDPR Ctrl Message Trans IP_PROTO_TPPP = 39 # TP++ Transport Protocol IP_PROTO_IL = 40 # IL Transport Protocol IP_PROTO_IP6 = 41 # IPv6 IP_PROTO_SDRP = 42 # Source Demand Routing IP_PROTO_ROUTING = 43 # IPv6 routing header IP_PROTO_FRAGMENT = 44 # IPv6 fragmentation header IP_PROTO_RSVP = 46 # Reservation protocol IP_PROTO_GRE = 47 # General Routing Encap IP_PROTO_MHRP = 48 # Mobile Host Routing IP_PROTO_ENA = 49 # ENA IP_PROTO_ESP = 50 # Encap Security Payload IP_PROTO_AH = 51 # Authentication Header IP_PROTO_INLSP = 52 # Integated Net Layer Sec IP_PROTO_SWIPE = 53 # SWIPE IP_PROTO_NARP = 54 # NBMA Address Resolution IP_PROTO_MOBILE = 55 # Mobile IP, RFC 2004 IP_PROTO_TLSP = 56 # Transport Layer Security IP_PROTO_SKIP = 57 # SKIP IP_PROTO_ICMP6 = 58 # ICMP for IPv6 IP_PROTO_NONE = 59 # IPv6 no next header IP_PROTO_DSTOPTS = 60 # IPv6 destination options IP_PROTO_ANYHOST = 61 # any host internal proto IP_PROTO_CFTP = 62 # CFTP IP_PROTO_ANYNET = 63 # any local network IP_PROTO_EXPAK = 64 # SATNET and Backroom EXPAK IP_PROTO_KRYPTOLAN = 65 # Kryptolan IP_PROTO_RVD = 66 # MIT Remote Virtual Disk IP_PROTO_IPPC = 67 # Inet Pluribus Packet Core IP_PROTO_DISTFS = 68 # any distributed fs IP_PROTO_SATMON = 69 # SATNET Monitoring IP_PROTO_VISA = 70 # VISA Protocol IP_PROTO_IPCV = 71 # Inet Packet Core Utility IP_PROTO_CPNX = 72 # Comp Proto Net Executive IP_PROTO_CPHB = 73 # Comp Protocol Heart Beat IP_PROTO_WSN = 74 # Wang Span Network IP_PROTO_PVP = 75 # Packet Video Protocol IP_PROTO_BRSATMON = 76 # Backroom SATNET Monitor IP_PROTO_SUNND = 77 # SUN ND Protocol IP_PROTO_WBMON = 78 # WIDEBAND Monitoring IP_PROTO_WBEXPAK = 79 # WIDEBAND EXPAK IP_PROTO_EON = 80 # ISO CNLP IP_PROTO_VMTP = 81 # Versatile Msg Transport IP_PROTO_SVMTP = 82 # Secure VMTP IP_PROTO_VINES = 83 # VINES IP_PROTO_TTP = 84 # TTP IP_PROTO_NSFIGP = 85 # NSFNET-IGP IP_PROTO_DGP = 86 # Dissimilar Gateway Proto IP_PROTO_TCF = 87 # TCF IP_PROTO_EIGRP = 88 # EIGRP IP_PROTO_OSPF = 89 # Open Shortest Path First IP_PROTO_SPRITERPC = 90 # Sprite RPC Protocol IP_PROTO_LARP = 91 # Locus Address Resolution IP_PROTO_MTP = 92 # Multicast Transport Proto IP_PROTO_AX25 = 93 # AX.25 Frames IP_PROTO_IPIPENCAP = 94 # yet-another IP encap IP_PROTO_MICP = 95 # Mobile Internet Ctrl IP_PROTO_SCCSP = 96 # Semaphore Comm Sec Proto IP_PROTO_ETHERIP = 97 # Ethernet in IPv4 IP_PROTO_ENCAP = 98 # encapsulation header IP_PROTO_ANYENC = 99 # private encryption scheme IP_PROTO_GMTP = 100 # GMTP IP_PROTO_IFMP = 101 # Ipsilon Flow Mgmt Proto IP_PROTO_PNNI = 102 # PNNI over IP IP_PROTO_PIM = 103 # Protocol Indep Multicast IP_PROTO_ARIS = 104 # ARIS IP_PROTO_SCPS = 105 # SCPS IP_PROTO_QNX = 106 # QNX IP_PROTO_AN = 107 # Active Networks IP_PROTO_IPCOMP = 108 # IP Payload Compression IP_PROTO_SNP = 109 # Sitara Networks Protocol IP_PROTO_COMPAQPEER = 110 # Compaq Peer Protocol IP_PROTO_IPXIP = 111 # IPX in IP IP_PROTO_VRRP = 112 # Virtual Router Redundancy IP_PROTO_PGM = 113 # PGM Reliable Transport IP_PROTO_ANY0HOP = 114 # 0-hop protocol IP_PROTO_L2TP = 115 # Layer 2 Tunneling Proto IP_PROTO_DDX = 116 # D-II Data Exchange (DDX) IP_PROTO_IATP = 117 # Interactive Agent Xfer IP_PROTO_STP = 118 # Schedule Transfer Proto IP_PROTO_SRP = 119 # SpectraLink Radio Proto IP_PROTO_UTI = 120 # UTI IP_PROTO_SMP = 121 # Simple Message Protocol IP_PROTO_SM = 122 # SM IP_PROTO_PTP = 123 # Performance Transparency IP_PROTO_ISIS = 124 # ISIS over IPv4 IP_PROTO_FIRE = 125 # FIRE IP_PROTO_CRTP = 126 # Combat Radio Transport IP_PROTO_CRUDP = 127 # Combat Radio UDP IP_PROTO_SSCOPMCE = 128 # SSCOPMCE IP_PROTO_IPLT = 129 # IPLT IP_PROTO_SPS = 130 # Secure Packet Shield IP_PROTO_PIPE = 131 # Private IP Encap in IP IP_PROTO_SCTP = 132 # Stream Ctrl Transmission IP_PROTO_FC = 133 # Fibre Channel IP_PROTO_RSVPIGN = 134 # RSVP-E2E-IGNORE IP_PROTO_RAW = 255 # Raw IP packets IP_PROTO_RESERVED = IP_PROTO_RAW # Reserved IP_PROTO_MAX = 255 # XXX - auto-load IP dispatch table from IP_PROTO_* definitions def __load_protos(): g = globals() for k, v in iteritems(g): if k.startswith('IP_PROTO_'): name = k[9:].lower() try: mod = __import__(name, g, level=1) IP.set_proto(v, getattr(mod, name.upper())) except (ImportError, AttributeError): continue def _mod_init(): """Post-initialization called when all dpkt modules are fully loaded""" if not IP._protosw: __load_protos() def test_ip(): from . import udp s = b'E\x00\x00"\x00\x00\x00\x00@\x11r\xc0\x01\x02\x03\x04\x01\x02\x03\x04\x00o\x00\xde\x00\x0e\xbf5foobar' ip = IP(id=0, src=b'\x01\x02\x03\x04', dst=b'\x01\x02\x03\x04', p=17) u = udp.UDP(sport=111, dport=222) u.data = b'foobar' u.ulen += len(u.data) ip.data = u ip.len += len(u) assert (bytes(ip) == s) assert (ip.v == 4) assert (ip.hl == 5) ip = IP(s) assert (bytes(ip) == s) assert (ip.udp.sport == 111) assert (ip.udp.data == b'foobar') def test_hl(): # Todo chack this test method s = b'BB\x03\x00\x00\x00\x00\x00\x00\x00\xd0\x00\xec\xbc\xa5\x00\x00\x00\x03\x80\x00\x00\xd0\x01\xf2\xac\xa5"0\x01\x00\x14\x00\x02\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00' try: IP(s) except dpkt.UnpackError: pass def test_opt(): s = b'\x4f\x00\x00\x3c\xae\x08\x00\x00\x40\x06\x18\x10\xc0\xa8\x0a\x26\xc0\xa8\x0a\x01\x07\x27\x08\x01\x02\x03\x04\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' ip = IP(s) ip.sum = 0 assert (bytes(ip) == s) def test_zerolen(): from . import tcp d = b'X' * 2048 s = b'E\x00\x00\x004\xce@\x00\x80\x06\x00\x00\x7f\x00\x00\x01\x7f\x00\x00\x01\xccN\x0c8`\xff\xc6N_\x8a\x12\x98P\x18@):\xa3\x00\x00' + d ip = IP(s) assert (isinstance(ip.data, tcp.TCP)) assert (ip.tcp.data == d) def test_constuctor(): ip1 = IP(data = b"Hello world!") ip2 = IP(data = b"Hello world!", len = 0) ip3 = IP(bytes(ip1)) ip4 = IP(bytes(ip2)) assert (bytes(ip1) == bytes(ip3)) assert (bytes(ip1) == b'E\x00\x00 \x00\x00\x00\x00@\x00z\xdf\x00\x00\x00\x00\x00\x00\x00\x00Hello world!') assert (bytes(ip2) == bytes(ip4)) assert (bytes(ip2) == b'E\x00\x00 \x00\x00\x00\x00@\x00z\xdf\x00\x00\x00\x00\x00\x00\x00\x00Hello world!') def test_frag(): from . import ethernet s = b"\x00\x23\x20\xd4\x2a\x8c\x00\x23\x20\xd4\x2a\x8c\x08\x00\x45\x00\x00\x54\x00\x00\x40\x00\x40\x01\x25\x8d\x0a\x00\x00\x8f\x0a\x00\x00\x8e\x08\x00\x2e\xa0\x01\xff\x23\x73\x20\x48\x4a\x4d\x00\x00\x00\x00\x78\x85\x02\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" ip = ethernet.Ethernet(s).ip assert (ip.rf == 0) assert (ip.df == 1) assert (ip.mf == 0) assert (ip.offset == 0) # test setters of fragmentation related attributes. ip.rf = 1 ip.df = 0 ip.mf = 1 ip.offset = 1480 assert (ip.rf == 1) assert (ip.df == 0) assert (ip.mf == 1) assert (ip.offset == 1480) if __name__ == '__main__': test_ip() test_hl() test_opt() test_zerolen() test_constuctor() test_frag() print('Tests Successful...') dpkt-1.9.2/dpkt/ip6.py000066400000000000000000000333511340335175100145060ustar00rootroot00000000000000# $Id: ip6.py 87 2013-03-05 19:41:04Z andrewflnr@gmail.com $ # -*- coding: utf-8 -*- """Internet Protocol, version 6.""" from __future__ import print_function from __future__ import absolute_import from . import dpkt from . import ip from .compat import compat_ord class IP6(dpkt.Packet): """Internet Protocol, version 6. TODO: Longer class information.... Attributes: __hdr__: Header fields of IPv6. TODO. """ __hdr__ = ( ('_v_fc_flow', 'I', 0x60000000), ('plen', 'H', 0), # payload length (not including header) ('nxt', 'B', 0), # next header protocol ('hlim', 'B', 0), # hop limit ('src', '16s', ''), ('dst', '16s', '') ) _protosw = ip.IP._protosw @property def v(self): return self._v_fc_flow >> 28 @v.setter def v(self, v): self._v_fc_flow = (self._v_fc_flow & ~0xf0000000) | (v << 28) @property def fc(self): return (self._v_fc_flow >> 20) & 0xff @fc.setter def fc(self, v): self._v_fc_flow = (self._v_fc_flow & ~0xff00000) | (v << 20) @property def flow(self): return self._v_fc_flow & 0xfffff @flow.setter def flow(self, v): self._v_fc_flow = (self._v_fc_flow & ~0xfffff) | (v & 0xfffff) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.extension_hdrs = {} # NOTE: self.extension_hdrs is not accurate, as it doesn't support duplicate header types. # According to RFC-1883 "Each extension header should occur at most once, except for the # Destination Options header which should occur at most twice". # Secondly, the .headers_str() method attempts to pack the extension headers in order as # defined in the RFC, however it doesn't adjust the next header (nxt) pointer accordingly. # Here we introduce the new field .all_extension_headers; it allows duplicate types and # keeps the original order. self.all_extension_headers = [] if self.plen: buf = self.data[:self.plen] else: # due to jumbo payload or TSO buf = self.data next_ext_hdr = self.nxt while next_ext_hdr in ext_hdrs: ext = ext_hdrs_cls[next_ext_hdr](buf) self.extension_hdrs[next_ext_hdr] = ext self.all_extension_headers.append(ext) buf = buf[ext.length:] next_ext_hdr = getattr(ext, 'nxt', None) # set the payload protocol id if next_ext_hdr is not None: self.p = next_ext_hdr try: self.data = self._protosw[next_ext_hdr](buf) setattr(self, self.data.__class__.__name__.lower(), self.data) except (KeyError, dpkt.UnpackError): self.data = buf def headers_str(self): # If all_extension_headers is available, return the headers as they originally appeared if self.all_extension_headers: return b''.join(bytes(ext) for ext in self.all_extension_headers) # Output extension headers in order defined in RFC1883 (except dest opts) header_str = b"" for hdr in ext_hdrs: if hdr in self.extension_hdrs: header_str += bytes(self.extension_hdrs[hdr]) return header_str def __bytes__(self): if (self.p == 6 or self.p == 17 or self.p == 58) and not self.data.sum: # XXX - set TCP, UDP, and ICMPv6 checksums p = bytes(self.data) s = dpkt.struct.pack('>16s16sxBH', self.src, self.dst, self.nxt, len(p)) s = dpkt.in_cksum_add(0, s) s = dpkt.in_cksum_add(s, p) try: self.data.sum = dpkt.in_cksum_done(s) except AttributeError: pass return self.pack_hdr() + self.headers_str() + bytes(self.data) @classmethod def set_proto(cls, p, pktclass): cls._protosw[p] = pktclass @classmethod def get_proto(cls, p): return cls._protosw[p] class IP6ExtensionHeader(dpkt.Packet): """ An extension header is very similar to a 'sub-packet'. We just want to re-use all the hdr unpacking etc. """ pass class IP6OptsHeader(IP6ExtensionHeader): __hdr__ = ( ('nxt', 'B', 0), # next extension header protocol ('len', 'B', 0) # option data length in 8 octect units (ignoring first 8 octets) so, len 0 == 64bit header ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.length = (self.len + 1) * 8 options = [] index = 0 while index < self.length - 2: opt_type = compat_ord(self.data[index]) # PAD1 option if opt_type == 0: index += 1 continue opt_length = compat_ord(self.data[index + 1]) if opt_type == 1: # PADN option # PADN uses opt_length bytes in total index += opt_length + 2 continue options.append( {'type': opt_type, 'opt_length': opt_length, 'data': self.data[index + 2:index + 2 + opt_length]}) # add the two chars and the option_length, to move to the next option index += opt_length + 2 self.options = options self.data = buf[2:self.length] # keep raw data with all pad options, but not the following data class IP6HopOptsHeader(IP6OptsHeader): pass class IP6DstOptsHeader(IP6OptsHeader): pass class IP6RoutingHeader(IP6ExtensionHeader): __hdr__ = ( ('nxt', 'B', 0), # next extension header protocol ('len', 'B', 0), # extension data length in 8 octect units (ignoring first 8 octets) (<= 46 for type 0) ('type', 'B', 0), # routing type (currently, only 0 is used) ('segs_left', 'B', 0), # remaining segments in route, until destination (<= 23) ('rsvd_sl_bits', 'I', 0), # reserved (1 byte), strict/loose bitmap for addresses ) @property def sl_bits(self): return self.rsvd_sl_bits & 0xffffff @sl_bits.setter def sl_bits(self, v): self.rsvd_sl_bits = (self.rsvd_sl_bits & ~0xfffff) | (v & 0xfffff) def unpack(self, buf): hdr_size = 8 addr_size = 16 dpkt.Packet.unpack(self, buf) addresses = [] num_addresses = self.len // 2 buf = buf[hdr_size:hdr_size + num_addresses * addr_size] for i in range(num_addresses): addresses.append(buf[i * addr_size: i * addr_size + addr_size]) self.data = buf self.addresses = addresses self.length = self.len * 8 + 8 class IP6FragmentHeader(IP6ExtensionHeader): __hdr__ = ( ('nxt', 'B', 0), # next extension header protocol ('resv', 'B', 0), # reserved, set to 0 ('frag_off_resv_m', 'H', 0), # frag offset (13 bits), reserved zero (2 bits), More frags flag ('id', 'I', 0) # fragments id ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.length = self.__hdr_len__ self.data = b'' @property def frag_off(self): return self.frag_off_resv_m >> 3 @frag_off.setter def frag_off(self, v): self.frag_off_resv_m = (self.frag_off_resv_m & ~0xfff8) | (v << 3) @property def m_flag(self): return self.frag_off_resv_m & 1 @m_flag.setter def m_flag(self, v): self.frag_off_resv_m = (self.frag_off_resv_m & ~0xfffe) | v class IP6AHHeader(IP6ExtensionHeader): __hdr__ = ( ('nxt', 'B', 0), # next extension header protocol ('len', 'B', 0), # length of header in 4 octet units (ignoring first 2 units) ('resv', 'H', 0), # reserved, 2 bytes of 0 ('spi', 'I', 0), # SPI security parameter index ('seq', 'I', 0) # sequence no. ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.length = (self.len + 2) * 4 self.auth_data = self.data[:(self.len - 1) * 4] class IP6ESPHeader(IP6ExtensionHeader): __hdr__ = ( ('spi', 'I', 0), ('seq', 'I', 0) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.length = self.__hdr_len__ + len(self.data) ext_hdrs = [ip.IP_PROTO_HOPOPTS, ip.IP_PROTO_ROUTING, ip.IP_PROTO_FRAGMENT, ip.IP_PROTO_AH, ip.IP_PROTO_ESP, ip.IP_PROTO_DSTOPTS] ext_hdrs_cls = {ip.IP_PROTO_HOPOPTS: IP6HopOptsHeader, ip.IP_PROTO_ROUTING: IP6RoutingHeader, ip.IP_PROTO_FRAGMENT: IP6FragmentHeader, ip.IP_PROTO_ESP: IP6ESPHeader, ip.IP_PROTO_AH: IP6AHHeader, ip.IP_PROTO_DSTOPTS: IP6DstOptsHeader} # Unit tests def test_ipg(): s = (b'\x60\x00\x00\x00\x00\x28\x06\x40\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x11\x24\xff\xfe\x8c' b'\x11\xde\xfe\x80\x00\x00\x00\x00\x00\x00\x02\xb0\xd0\xff\xfe\xe1\x80\x72\xcd\xca\x00\x16' b'\x04\x84\x46\xd5\x00\x00\x00\x00\xa0\x02\xff\xff\xf8\x09\x00\x00\x02\x04\x05\xa0\x01\x03' b'\x03\x00\x01\x01\x08\x0a\x7d\x18\x35\x3f\x00\x00\x00\x00') _ip = IP6(s) # basic properties assert _ip.v == 6 assert _ip.fc == 0 assert _ip.flow == 0 _ip.data.sum = 0 s2 = bytes(_ip) assert s == s2 def test_ip6_routing_header(): s = (b'\x60\x00\x00\x00\x00\x3c\x2b\x40\x20\x48\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\xde\xca\x20\x47\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xca\xfe\x06\x04\x00\x02' b'\x00\x00\x00\x00\x20\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xde\xca\x20\x22' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xde\xca\x00\x14\x00\x50\x00\x00\x00\x00' b'\x00\x00\x00\x00\x50\x02\x20\x00\x91\x7f\x00\x00') _ip = IP6(s) s2 = bytes(_ip) # 43 is Routing header id assert len(_ip.extension_hdrs[43].addresses) == 2 assert _ip.tcp assert s == s2 def test_ip6_fragment_header(): s = b'\x06\xee\xff\xfb\x00\x00\xff\xff' fh = IP6FragmentHeader(s) # s2 = str(fh) variable 's2' is not used assert fh.nxt == 6 assert fh.id == 65535 assert fh.frag_off == 8191 assert fh.m_flag == 1 assert bytes(fh) == s # IP6 with fragment header s = (b'\x60\x00\x00\x00\x00\x10\x2c\x00\x02\x22\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x02\x03\x33\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x29\x00\x00\x01' b'\x00\x00\x00\x00\x60\x00\x00\x00\x00\x10\x2c\x00') _ip = IP6(s) assert bytes(_ip) == s def test_ip6_options_header(): s = (b'\x3b\x04\x01\x02\x00\x00\xc9\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x01\x00\xc2\x04\x00\x00\x00\x00\x05\x02\x00\x00\x01\x02\x00\x00') options = IP6OptsHeader(s).options assert len(options) == 3 assert bytes(IP6OptsHeader(s)) == s def test_ip6_ah_header(): s = b'\x3b\x04\x00\x00\x02\x02\x02\x02\x01\x01\x01\x01\x78\x78\x78\x78\x78\x78\x78\x78' ah = IP6AHHeader(s) assert ah.length == 24 assert ah.auth_data == b'xxxxxxxx' assert ah.spi == 0x2020202 assert ah.seq == 0x1010101 assert bytes(ah) == s def test_ip6_esp_header(): s = (b'\x00\x00\x01\x00\x00\x00\x00\x44\xe2\x4f\x9e\x68\xf3\xcd\xb1\x5f\x61\x65\x42\x8b\x78\x0b' b'\x4a\xfd\x13\xf0\x15\x98\xf5\x55\x16\xa8\x12\xb3\xb8\x4d\xbc\x16\xb2\x14\xbe\x3d\xf9\x96' b'\xd4\xa0\x39\x1f\x85\x74\x25\x81\x83\xa6\x0d\x99\xb6\xba\xa3\xcc\xb6\xe0\x9a\x78\xee\xf2' b'\xaf\x9a') esp = IP6ESPHeader(s) assert esp.length == 68 assert esp.spi == 256 assert bytes(esp) == s def test_ip6_extension_headers(): p = (b'\x60\x00\x00\x00\x00\x3c\x2b\x40\x20\x48\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\xde\xca\x20\x47\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xca\xfe\x06\x04\x00\x02' b'\x00\x00\x00\x00\x20\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xde\xca\x20\x22' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xde\xca\x00\x14\x00\x50\x00\x00\x00\x00' b'\x00\x00\x00\x00\x50\x02\x20\x00\x91\x7f\x00\x00') _ip = IP6(p) o = (b'\x3b\x04\x01\x02\x00\x00\xc9\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x01\x00\xc2\x04\x00\x00\x00\x00\x05\x02\x00\x00\x01\x02\x00\x00') _ip.extension_hdrs[0] = IP6HopOptsHeader(o) fh = b'\x06\xee\xff\xfb\x00\x00\xff\xff' _ip.extension_hdrs[44] = IP6FragmentHeader(fh) ah = b'\x3b\x04\x00\x00\x02\x02\x02\x02\x01\x01\x01\x01\x78\x78\x78\x78\x78\x78\x78\x78' _ip.extension_hdrs[51] = IP6AHHeader(ah) do = b'\x3b\x02\x01\x02\x00\x00\xc9\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' _ip.extension_hdrs[60] = IP6DstOptsHeader(do) assert len(_ip.extension_hdrs) == 5 def test_ip6_all_extension_headers(): # https://github.com/kbandla/dpkt/pull/403 s = (b'\x60\x00\x00\x00\x00\x47\x3c\x40\xfe\xd0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' b'\x00\x02\xfe\xd0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x3c\x00\x01\x04' b'\x00\x00\x00\x00\x3c\x00\x01\x04\x00\x00\x00\x00\x2c\x00\x01\x04\x00\x00\x00\x00\x2c\x00' b'\x00\x00\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x2c\x00\x01\x04\x00\x00\x00\x00' b'\x3a\x00\x00\x00\x00\x00\x00\x00\x80\x00\xd8\xe5\x0c\x1a\x00\x00\x50\x61\x79\x4c\x6f\x61' b'\x64') _ip = IP6(s) assert _ip.p == 58 # ICMPv6 hdrs = _ip.all_extension_headers assert len(hdrs) == 7 assert isinstance(hdrs[0], IP6DstOptsHeader) assert isinstance(hdrs[3], IP6FragmentHeader) assert isinstance(hdrs[5], IP6DstOptsHeader) assert bytes(_ip) == s if __name__ == '__main__': test_ipg() test_ip6_routing_header() test_ip6_fragment_header() test_ip6_options_header() test_ip6_ah_header() test_ip6_esp_header() test_ip6_extension_headers() test_ip6_all_extension_headers() print('Tests Successful...') dpkt-1.9.2/dpkt/ipip.py000066400000000000000000000002531340335175100147440ustar00rootroot00000000000000# Defines a copy of the IP protocol as IPIP so the protocol parsing in ip.py # can decode IPIP packets. from __future__ import absolute_import from .ip import IP as IPIP dpkt-1.9.2/dpkt/ipx.py000066400000000000000000000010611340335175100146010ustar00rootroot00000000000000# $Id: ipx.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Internetwork Packet Exchange.""" from __future__ import absolute_import from . import dpkt IPX_HDR_LEN = 30 class IPX(dpkt.Packet): """Internetwork Packet Exchange. TODO: Longer class information.... Attributes: __hdr__: Header fields of IPX. TODO. """ __hdr__ = ( ('sum', 'H', 0xffff), ('len', 'H', IPX_HDR_LEN), ('tc', 'B', 0), ('pt', 'B', 0), ('dst', '12s', ''), ('src', '12s', '') ) dpkt-1.9.2/dpkt/llc.py000066400000000000000000000063351340335175100145640ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import print_function from __future__ import absolute_import import struct from . import dpkt from . import stp class LLC(dpkt.Packet): """802.2 Logical Link Control (LLC) data communication protocol. Attributes: __hdr__ = ( ('dsap', 'B', 0xaa), # Destination Service Access Point ('ssap', 'B', 0xaa), # Source Service Access Point ('ctl', 'B', 3) # Control Byte ) """ __hdr__ = ( ('dsap', 'B', 0xaa), # Destination Service Access Point ('ssap', 'B', 0xaa), # Source Service Access Point ('ctl', 'B', 3) # Control Byte ) @property def is_snap(self): return self.dsap == self.ssap == 0xaa def unpack(self, buf): from .ethernet import Ethernet, ETH_TYPE_IP, ETH_TYPE_IPX dpkt.Packet.unpack(self, buf) if self.is_snap: self.oui, self.type = struct.unpack('>IH', b'\x00' + self.data[:5]) self.data = self.data[5:] try: self.data = Ethernet.get_type(self.type)(self.data) setattr(self, self.data.__class__.__name__.lower(), self.data) except (KeyError, dpkt.UnpackError): pass else: # non-SNAP if self.dsap == 0x06: # SAP_IP self.data = self.ip = Ethernet.get_type(ETH_TYPE_IP)(self.data) elif self.dsap == 0x10 or self.dsap == 0xe0: # SAP_NETWARE{1,2} self.data = self.ipx = Ethernet.get_type(ETH_TYPE_IPX)(self.data) elif self.dsap == 0x42: # SAP_STP self.data = self.stp = stp.STP(self.data) def pack_hdr(self): buf = dpkt.Packet.pack_hdr(self) if self.is_snap: # add SNAP sublayer oui = getattr(self, 'oui', 0) _type = getattr(self, 'type', 0) if not _type and isinstance(self.data, dpkt.Packet): from .ethernet import Ethernet try: _type = Ethernet.get_type_rev(self.data.__class__) except KeyError: pass buf += struct.pack('>IH', oui, _type)[1:] return buf def __len__(self): # add 5 bytes of SNAP header if needed return self.__hdr_len__ + 5 * int(self.is_snap) + len(self.data) def test_llc(): from . import ip from . import ethernet s = (b'\xaa\xaa\x03\x00\x00\x00\x08\x00\x45\x00\x00\x28\x07\x27\x40\x00\x80\x06\x1d' b'\x39\x8d\xd4\x37\x3d\x3f\xf5\xd1\x69\xc0\x5f\x01\xbb\xb2\xd6\xef\x23\x38\x2b' b'\x4f\x08\x50\x10\x42\x04\xac\x17\x00\x00') llc_pkt = LLC(s) ip_pkt = llc_pkt.data assert isinstance(ip_pkt, ip.IP) assert llc_pkt.type == ethernet.ETH_TYPE_IP assert ip_pkt.dst == b'\x3f\xf5\xd1\x69' assert str(llc_pkt) == str(s) assert len(llc_pkt) == len(s) # construction with SNAP header llc_pkt = LLC(ssap=0xaa, dsap=0xaa, data=ip.IP(s[8:])) assert str(llc_pkt) == str(s) # no SNAP llc_pkt = LLC(ssap=6, dsap=6, data=ip.IP(s[8:])) assert isinstance(llc_pkt.data, ip.IP) assert str(llc_pkt) == str(b'\x06\x06\x03' + s[8:]) if __name__ == '__main__': test_llc() print('Tests Successful...') dpkt-1.9.2/dpkt/loopback.py000066400000000000000000000016241340335175100156000ustar00rootroot00000000000000# $Id: loopback.py 38 2007-03-17 03:33:16Z dugsong $ # -*- coding: utf-8 -*- """Platform-dependent loopback header.""" from __future__ import absolute_import from . import dpkt from . import ethernet from . import ip from . import ip6 class Loopback(dpkt.Packet): """Platform-dependent loopback header. TODO: Longer class information.... Attributes: __hdr__: Header fields of Loopback. TODO. """ __hdr__ = (('family', 'I', 0), ) __byte_order__ = '@' def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.family == 2: self.data = ip.IP(self.data) elif self.family == 0x02000000: self.family = 2 self.data = ip.IP(self.data) elif self.family in (24, 28, 30): self.data = ip6.IP6(self.data) elif self.family > 1500: self.data = ethernet.Ethernet(self.data) dpkt-1.9.2/dpkt/mrt.py000066400000000000000000000037421340335175100146130ustar00rootroot00000000000000# $Id: mrt.py 29 2007-01-26 02:29:07Z jon.oberheide $ # -*- coding: utf-8 -*- """Multi-threaded Routing Toolkit.""" from __future__ import absolute_import from . import dpkt from . import bgp # Multi-threaded Routing Toolkit # http://www.ietf.org/internet-drafts/draft-ietf-grow-mrt-03.txt # MRT Types NULL = 0 START = 1 DIE = 2 I_AM_DEAD = 3 PEER_DOWN = 4 BGP = 5 # Deprecated by BGP4MP RIP = 6 IDRP = 7 RIPNG = 8 BGP4PLUS = 9 # Deprecated by BGP4MP BGP4PLUS_01 = 10 # Deprecated by BGP4MP OSPF = 11 TABLE_DUMP = 12 BGP4MP = 16 BGP4MP_ET = 17 ISIS = 32 ISIS_ET = 33 OSPF_ET = 64 # BGP4MP Subtypes BGP4MP_STATE_CHANGE = 0 BGP4MP_MESSAGE = 1 BGP4MP_ENTRY = 2 BGP4MP_SNAPSHOT = 3 BGP4MP_MESSAGE_32BIT_AS = 4 # Address Family Types AFI_IPv4 = 1 AFI_IPv6 = 2 class MRTHeader(dpkt.Packet): __hdr__ = ( ('ts', 'I', 0), ('type', 'H', 0), ('subtype', 'H', 0), ('len', 'I', 0) ) class TableDump(dpkt.Packet): __hdr__ = ( ('view', 'H', 0), ('seq', 'H', 0), ('prefix', 'I', 0), ('prefix_len', 'B', 0), ('status', 'B', 1), ('originated_ts', 'I', 0), ('peer_ip', 'I', 0), ('peer_as', 'H', 0), ('attr_len', 'H', 0) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) plen = self.attr_len l = [] while plen > 0: attr = bgp.BGP.Update.Attribute(self.data) self.data = self.data[len(attr):] plen -= len(attr) l.append(attr) self.attributes = l class BGP4MPMessage(dpkt.Packet): __hdr__ = ( ('src_as', 'H', 0), ('dst_as', 'H', 0), ('intf', 'H', 0), ('family', 'H', AFI_IPv4), ('src_ip', 'I', 0), ('dst_ip', 'I', 0) ) class BGP4MPMessage_32(dpkt.Packet): __hdr__ = ( ('src_as', 'I', 0), ('dst_as', 'I', 0), ('intf', 'H', 0), ('family', 'H', AFI_IPv4), ('src_ip', 'I', 0), ('dst_ip', 'I', 0) ) dpkt-1.9.2/dpkt/netbios.py000066400000000000000000000117621340335175100154550ustar00rootroot00000000000000# $Id: netbios.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Network Basic Input/Output System.""" from __future__ import absolute_import import struct from . import dpkt from . import dns def encode_name(name): """Return the NetBIOS first-level encoded name.""" l = [] for c in struct.pack('16s', name): c = ord(c) l.append(chr((c >> 4) + 0x41)) l.append(chr((c & 0xf) + 0x41)) return ''.join(l) def decode_name(nbname): """Return the NetBIOS first-level decoded nbname.""" if len(nbname) != 32: return nbname l = [] for i in range(0, 32, 2): l.append(chr(((ord(nbname[i]) - 0x41) << 4) | ((ord(nbname[i + 1]) - 0x41) & 0xf))) return ''.join(l).split('\x00', 1)[0] # RR types NS_A = 0x01 # IP address NS_NS = 0x02 # Name Server NS_NULL = 0x0A # NULL NS_NB = 0x20 # NetBIOS general Name Service NS_NBSTAT = 0x21 # NetBIOS NODE STATUS # RR classes NS_IN = 1 # NBSTAT name flags NS_NAME_G = 0x8000 # group name (as opposed to unique) NS_NAME_DRG = 0x1000 # deregister NS_NAME_CNF = 0x0800 # conflict NS_NAME_ACT = 0x0400 # active NS_NAME_PRM = 0x0200 # permanent # NBSTAT service names nbstat_svcs = { # (service, unique): list of ordered (name prefix, service name) tuples (0x00, 0): [('', 'Domain Name')], (0x00, 1): [('IS~', 'IIS'), ('', 'Workstation Service')], (0x01, 0): [('__MSBROWSE__', 'Master Browser')], (0x01, 1): [('', 'Messenger Service')], (0x03, 1): [('', 'Messenger Service')], (0x06, 1): [('', 'RAS Server Service')], (0x1B, 1): [('', 'Domain Master Browser')], (0x1C, 0): [('INet~Services', 'IIS'), ('', 'Domain Controllers')], (0x1D, 1): [('', 'Master Browser')], (0x1E, 0): [('', 'Browser Service Elections')], (0x1F, 1): [('', 'NetDDE Service')], (0x20, 1): [('Forte_$ND800ZA', 'DCA IrmaLan Gateway Server Service'), ('', 'File Server Service')], (0x21, 1): [('', 'RAS Client Service')], (0x22, 1): [('', 'Microsoft Exchange Interchange(MSMail Connector)')], (0x23, 1): [('', 'Microsoft Exchange Store')], (0x24, 1): [('', 'Microsoft Exchange Directory')], (0x2B, 1): [('', 'Lotus Notes Server Service')], (0x2F, 0): [('IRISMULTICAST', 'Lotus Notes')], (0x30, 1): [('', 'Modem Sharing Server Service')], (0x31, 1): [('', 'Modem Sharing Client Service')], (0x33, 0): [('IRISNAMESERVER', 'Lotus Notes')], (0x43, 1): [('', 'SMS Clients Remote Control')], (0x44, 1): [('', 'SMS Administrators Remote Control Tool')], (0x45, 1): [('', 'SMS Clients Remote Chat')], (0x46, 1): [('', 'SMS Clients Remote Transfer')], (0x4C, 1): [('', 'DEC Pathworks TCPIP service on Windows NT')], (0x52, 1): [('', 'DEC Pathworks TCPIP service on Windows NT')], (0x87, 1): [('', 'Microsoft Exchange MTA')], (0x6A, 1): [('', 'Microsoft Exchange IMC')], (0xBE, 1): [('', 'Network Monitor Agent')], (0xBF, 1): [('', 'Network Monitor Application')] } def node_to_service_name(name_service_flags): name, service, flags = name_service_flags try: unique = int(flags & NS_NAME_G == 0) for namepfx, svcname in nbstat_svcs[(service, unique)]: if name.startswith(namepfx): return svcname except KeyError: pass return '' class NS(dns.DNS): """NetBIOS Name Service.""" class Q(dns.DNS.Q): pass class RR(dns.DNS.RR): """NetBIOS resource record.""" def unpack_rdata(self, buf, off): if self.type == NS_A: self.ip = self.rdata elif self.type == NS_NBSTAT: num = ord(self.rdata[0]) off = 1 l = [] for i in range(num): name = self.rdata[off:off + 15].split(None, 1)[0].split('\x00', 1)[0] service = ord(self.rdata[off + 15]) off += 16 flags = struct.unpack('>H', self.rdata[off:off + 2])[0] off += 2 l.append((name, service, flags)) self.nodenames = l # XXX - skip stats def pack_name(self, buf, name): return dns.DNS.pack_name(self, buf, encode_name(name)) def unpack_name(self, buf, off): name, off = dns.DNS.unpack_name(self, buf, off) return decode_name(name), off class Session(dpkt.Packet): """NetBIOS Session Service.""" __hdr__ = ( ('type', 'B', 0), ('flags', 'B', 0), ('len', 'H', 0) ) SSN_MESSAGE = 0 SSN_REQUEST = 1 SSN_POSITIVE = 2 SSN_NEGATIVE = 3 SSN_RETARGET = 4 SSN_KEEPALIVE = 5 class Datagram(dpkt.Packet): """NetBIOS Datagram Service.""" __hdr__ = ( ('type', 'B', 0), ('flags', 'B', 0), ('id', 'H', 0), ('src', 'I', 0), ('sport', 'H', 0), ('len', 'H', 0), ('off', 'H', 0) ) DGRAM_UNIQUE = 0x10 DGRAM_GROUP = 0x11 DGRAM_BROADCAST = 0x12 DGRAM_ERROR = 0x13 DGRAM_QUERY = 0x14 DGRAM_POSITIVE = 0x15 DGRAM_NEGATIVE = 0x16 dpkt-1.9.2/dpkt/netflow.py000066400000000000000000000377141340335175100154750ustar00rootroot00000000000000# $Id: netflow.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Cisco Netflow.""" from __future__ import print_function from __future__ import absolute_import import struct from . import dpkt from .compat import compat_izip class NetflowBase(dpkt.Packet): """Base class for Cisco Netflow packets. TODO: Longer class information.... Attributes: __hdr__: Header fields of NetflowBase. TODO. """ __hdr__ = ( ('version', 'H', 1), ('count', 'H', 0), ('sys_uptime', 'I', 0), ('unix_sec', 'I', 0), ('unix_nsec', 'I', 0) ) def __len__(self): return self.__hdr_len__ + (len(self.data[0]) * self.count) def __bytes__(self): # for now, don't try to enforce any size limits self.count = len(self.data) return self.pack_hdr() + b''.join(map(bytes, self.data)) def unpack(self, buf): dpkt.Packet.unpack(self, buf) buf = self.data l = [] while buf: flow = self.NetflowRecord(buf) l.append(flow) buf = buf[len(flow):] self.data = l class NetflowRecordBase(dpkt.Packet): """Base class for netflow v1-v7 netflow records. TODO: Longer class information.... Attributes: __hdr__: Header fields of NetflowRecordBase. TODO. """ # performance optimizations def __len__(self): # don't bother with data return self.__hdr_len__ def __bytes__(self): # don't bother with data return self.pack_hdr() def unpack(self, buf): # don't bother with data for k, v in compat_izip(self.__hdr_fields__, struct.unpack(self.__hdr_fmt__, buf[:self.__hdr_len__])): setattr(self, k, v) self.data = b"" class Netflow1(NetflowBase): """Netflow Version 1. TODO: Longer class information.... Attributes: __hdr__: Header fields of Netflow Version 1. TODO. """ class NetflowRecord(NetflowBase.NetflowRecordBase): """Netflow v1 flow record. TODO: Longer class information.... Attributes: __hdr__: Header fields of Netflow Version 1 flow record. TODO. """ __hdr__ = ( ('src_addr', 'I', 0), ('dst_addr', 'I', 0), ('next_hop', 'I', 0), ('input_iface', 'H', 0), ('output_iface', 'H', 0), ('pkts_sent', 'I', 0), ('bytes_sent', 'I', 0), ('start_time', 'I', 0), ('end_time', 'I', 0), ('src_port', 'H', 0), ('dst_port', 'H', 0), ('pad1', 'H', 0), ('ip_proto', 'B', 0), ('tos', 'B', 0), ('tcp_flags', 'B', 0), ('pad2', 'B', 0), ('pad3', 'H', 0), ('reserved', 'I', 0) ) # FYI, versions 2-4 don't appear to have ever seen the light of day. class Netflow5(NetflowBase): """Netflow Version 5. TODO: Longer class information.... Attributes: __hdr__: Header fields of Netflow Version 5. TODO. """ __hdr__ = NetflowBase.__hdr__ + ( ('flow_sequence', 'I', 0), ('engine_type', 'B', 0), ('engine_id', 'B', 0), ('reserved', 'H', 0), ) class NetflowRecord(NetflowBase.NetflowRecordBase): """Netflow v5 flow record. TODO: Longer class information.... Attributes: __hdr__: Header fields of Netflow Version 5 flow record. TODO. """ __hdr__ = ( ('src_addr', 'I', 0), ('dst_addr', 'I', 0), ('next_hop', 'I', 0), ('input_iface', 'H', 0), ('output_iface', 'H', 0), ('pkts_sent', 'I', 0), ('bytes_sent', 'I', 0), ('start_time', 'I', 0), ('end_time', 'I', 0), ('src_port', 'H', 0), ('dst_port', 'H', 0), ('pad1', 'B', 0), ('tcp_flags', 'B', 0), ('ip_proto', 'B', 0), ('tos', 'B', 0), ('src_as', 'H', 0), ('dst_as', 'H', 0), ('src_mask', 'B', 0), ('dst_mask', 'B', 0), ('pad2', 'H', 0), ) class Netflow6(NetflowBase): """Netflow Version 6. XXX - unsupported by Cisco, but may be found in the field. TODO: Longer class information.... Attributes: __hdr__: Header fields of Netflow Version 6. TODO. """ __hdr__ = Netflow5.__hdr__ class NetflowRecord(NetflowBase.NetflowRecordBase): """Netflow v6 flow record. TODO: Longer class information.... Attributes: __hdr__: Header fields of Netflow Version 6 flow record. TODO. """ __hdr__ = ( ('src_addr', 'I', 0), ('dst_addr', 'I', 0), ('next_hop', 'I', 0), ('input_iface', 'H', 0), ('output_iface', 'H', 0), ('pkts_sent', 'I', 0), ('bytes_sent', 'I', 0), ('start_time', 'I', 0), ('end_time', 'I', 0), ('src_port', 'H', 0), ('dst_port', 'H', 0), ('pad1', 'B', 0), ('tcp_flags', 'B', 0), ('ip_proto', 'B', 0), ('tos', 'B', 0), ('src_as', 'H', 0), ('dst_as', 'H', 0), ('src_mask', 'B', 0), ('dst_mask', 'B', 0), ('in_encaps', 'B', 0), ('out_encaps', 'B', 0), ('peer_nexthop', 'I', 0), ) class Netflow7(NetflowBase): """Netflow Version 7. TODO: Longer class information.... Attributes: __hdr__: Header fields of Netflow Version 7. TODO. """ __hdr__ = NetflowBase.__hdr__ + ( ('flow_sequence', 'I', 0), ('reserved', 'I', 0), ) class NetflowRecord(NetflowBase.NetflowRecordBase): """Netflow v6 flow record. TODO: Longer class information.... Attributes: __hdr__: Header fields of Netflow Version 6 flow record. TODO. """ __hdr__ = ( ('src_addr', 'I', 0), ('dst_addr', 'I', 0), ('next_hop', 'I', 0), ('input_iface', 'H', 0), ('output_iface', 'H', 0), ('pkts_sent', 'I', 0), ('bytes_sent', 'I', 0), ('start_time', 'I', 0), ('end_time', 'I', 0), ('src_port', 'H', 0), ('dst_port', 'H', 0), ('flags', 'B', 0), ('tcp_flags', 'B', 0), ('ip_proto', 'B', 0), ('tos', 'B', 0), ('src_as', 'H', 0), ('dst_as', 'H', 0), ('src_mask', 'B', 0), ('dst_mask', 'B', 0), ('pad2', 'H', 0), ('router_sc', 'I', 0), ) # No support for v8 or v9 yet. __sample_v1 = b"\x00\x01\x00\x18gza> 3) & 0x7 @v.setter def v(self, v): self.flags = (self.flags & ~0x38) | ((v & 0x7) << 3) @property def li(self): return (self.flags >> 6) & 0x3 @li.setter def li(self, li): self.flags = (self.flags & ~0xc0) | ((li & 0x3) << 6) @property def mode(self): return self.flags & 0x7 @mode.setter def mode(self, mode): self.flags = (self.flags & ~0x7) | (mode & 0x7) __s = b'\x24\x02\x04\xef\x00\x00\x00\x84\x00\x00\x33\x27\xc1\x02\x04\x02\xc8\x90\xec\x11\x22\xae\x07\xe5\xc8\x90\xf9\xd9\xc0\x7e\x8c\xcd\xc8\x90\xf9\xd9\xda\xc5\xb0\x78\xc8\x90\xf9\xd9\xda\xc6\x8a\x93' def test_ntp_pack(): n = NTP(__s) assert (__s == bytes(n)) def test_ntp_unpack(): n = NTP(__s) assert (n.li == NO_WARNING) assert (n.v == 4) assert (n.mode == SERVER) assert (n.stratum == 2) assert (n.id == b'\xc1\x02\x04\x02') # test get/set functions n.li = ALARM_CONDITION n.v = 3 n.mode = CLIENT assert (n.li == ALARM_CONDITION) assert (n.v == 3) assert (n.mode == CLIENT) if __name__ == '__main__': test_ntp_pack() test_ntp_unpack() print('Tests Successful...') dpkt-1.9.2/dpkt/ospf.py000066400000000000000000000014161340335175100147540ustar00rootroot00000000000000# $Id: ospf.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Open Shortest Path First.""" from __future__ import absolute_import from . import dpkt AUTH_NONE = 0 AUTH_PASSWORD = 1 AUTH_CRYPTO = 2 class OSPF(dpkt.Packet): """Open Shortest Path First. TODO: Longer class information.... Attributes: __hdr__: Header fields of OSPF. TODO. """ __hdr__ = ( ('v', 'B', 0), ('type', 'B', 0), ('len', 'H', 0), ('router', 'I', 0), ('area', 'I', 0), ('sum', 'H', 0), ('atype', 'H', 0), ('auth', '8s', '') ) def __bytes__(self): if not self.sum: self.sum = dpkt.in_cksum(dpkt.Packet.__bytes__(self)) return dpkt.Packet.__bytes__(self) dpkt-1.9.2/dpkt/pcap.py000066400000000000000000000235441340335175100147360ustar00rootroot00000000000000# $Id: pcap.py 77 2011-01-06 15:59:38Z dugsong $ # -*- coding: utf-8 -*- """Libpcap file format.""" from __future__ import print_function from __future__ import absolute_import import sys import time from decimal import Decimal from . import dpkt TCPDUMP_MAGIC = 0xa1b2c3d4 TCPDUMP_MAGIC_NANO = 0xa1b23c4d PMUDPCT_MAGIC = 0xd4c3b2a1 PMUDPCT_MAGIC_NANO = 0x4d3cb2a1 PCAP_VERSION_MAJOR = 2 PCAP_VERSION_MINOR = 4 # see http://www.tcpdump.org/linktypes.html for explanations DLT_NULL = 0 DLT_EN10MB = 1 DLT_EN3MB = 2 DLT_AX25 = 3 DLT_PRONET = 4 DLT_CHAOS = 5 DLT_IEEE802 = 6 DLT_ARCNET = 7 DLT_SLIP = 8 DLT_PPP = 9 DLT_FDDI = 10 DLT_PFSYNC = 18 DLT_PPP_SERIAL = 50 DLT_PPP_ETHER = 51 DLT_ATM_RFC1483 = 100 DLT_RAW = 101 DLT_C_HDLC = 104 DLT_IEEE802_11 = 105 DLT_FRELAY = 107 DLT_LOOP = 108 DLT_LINUX_SLL = 113 DLT_LTALK = 114 DLT_PFLOG = 117 DLT_PRISM_HEADER = 119 DLT_IP_OVER_FC = 122 DLT_SUNATM = 123 DLT_IEEE802_11_RADIO = 127 DLT_ARCNET_LINUX = 129 DLT_APPLE_IP_OVER_IEEE1394 = 138 DLT_MTP2_WITH_PHDR = 139 DLT_MTP2 = 140 DLT_MTP3 = 141 DLT_SCCP = 142 DLT_DOCSIS = 143 DLT_LINUX_IRDA = 144 DLT_USER0 = 147 DLT_USER1 = 148 DLT_USER2 = 149 DLT_USER3 = 150 DLT_USER4 = 151 DLT_USER5 = 152 DLT_USER6 = 153 DLT_USER7 = 154 DLT_USER8 = 155 DLT_USER9 = 156 DLT_USER10 = 157 DLT_USER11 = 158 DLT_USER12 = 159 DLT_USER13 = 160 DLT_USER14 = 161 DLT_USER15 = 162 DLT_IEEE802_11_RADIO_AVS = 163 DLT_BACNET_MS_TP = 165 DLT_PPP_PPPD = 166 DLT_GPRS_LLC = 169 DLT_GPF_T = 170 DLT_GPF_F = 171 DLT_LINUX_LAPD = 177 DLT_BLUETOOTH_HCI_H4 = 187 DLT_USB_LINUX = 189 DLT_PPI = 192 DLT_IEEE802_15_4 = 195 DLT_SITA = 196 DLT_ERF = 197 DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 201 DLT_AX25_KISS = 202 DLT_LAPD = 203 DLT_PPP_WITH_DIR = 204 DLT_C_HDLC_WITH_DIR = 205 DLT_FRELAY_WITH_DIR = 206 DLT_IPMB_LINUX = 209 DLT_IEEE802_15_4_NONASK_PHY = 215 DLT_USB_LINUX_MMAPPED = 220 DLT_FC_2 = 224 DLT_FC_2_WITH_FRAME_DELIMS = 225 DLT_IPNET = 226 DLT_CAN_SOCKETCAN = 227 DLT_IPV4 = 228 DLT_IPV6 = 229 DLT_IEEE802_15_4_NOFCS = 230 DLT_DBUS = 231 DLT_DVB_CI = 235 DLT_MUX27010 = 236 DLT_STANAG_5066_D_PDU = 237 DLT_NFLOG = 239 DLT_NETANALYZER = 240 DLT_NETANALYZER_TRANSPARENT = 241 DLT_IPOIB = 242 DLT_MPEG_2_TS = 243 DLT_NG40 = 244 DLT_NFC_LLCP = 245 DLT_INFINIBAND = 247 DLT_SCTP = 248 DLT_USBPCAP = 249 DLT_RTAC_SERIAL = 250 DLT_BLUETOOTH_LE_LL = 251 DLT_NETLINK = 253 DLT_BLUETOOTH_LINUX_MONITOR = 253 DLT_BLUETOOTH_BREDR_BB = 255 DLT_BLUETOOTH_LE_LL_WITH_PHDR = 256 DLT_PROFIBUS_DL = 257 DLT_PKTAP = 258 DLT_EPON = 259 DLT_IPMI_HPM_2 = 260 DLT_ZWAVE_R1_R2 = 261 DLT_ZWAVE_R3 = 262 DLT_WATTSTOPPER_DLM = 263 DLT_ISO_14443 = 264 if sys.platform.find('openbsd') != -1: DLT_LOOP = 12 DLT_RAW = 14 else: DLT_LOOP = 108 DLT_RAW = 12 dltoff = {DLT_NULL: 4, DLT_EN10MB: 14, DLT_IEEE802: 22, DLT_ARCNET: 6, DLT_SLIP: 16, DLT_PPP: 4, DLT_FDDI: 21, DLT_PFLOG: 48, DLT_PFSYNC: 4, DLT_LOOP: 4, DLT_LINUX_SLL: 16} class PktHdr(dpkt.Packet): """pcap packet header. TODO: Longer class information.... Attributes: __hdr__: Header fields of pcap header. TODO. """ __hdr__ = ( ('tv_sec', 'I', 0), ('tv_usec', 'I', 0), ('caplen', 'I', 0), ('len', 'I', 0), ) class LEPktHdr(PktHdr): __byte_order__ = '<' class FileHdr(dpkt.Packet): """pcap file header. TODO: Longer class information.... Attributes: __hdr__: Header fields of pcap file header. TODO. """ __hdr__ = ( ('magic', 'I', TCPDUMP_MAGIC), ('v_major', 'H', PCAP_VERSION_MAJOR), ('v_minor', 'H', PCAP_VERSION_MINOR), ('thiszone', 'I', 0), ('sigfigs', 'I', 0), ('snaplen', 'I', 1500), ('linktype', 'I', 1), ) class LEFileHdr(FileHdr): __byte_order__ = '<' class Writer(object): """Simple pcap dumpfile writer. TODO: Longer class information.... Attributes: __hdr__: Header fields of simple pcap dumpfile writer. TODO. """ def __init__(self, fileobj, snaplen=1500, linktype=DLT_EN10MB, nano=False): self.__f = fileobj self._precision = 9 if nano else 6 magic = TCPDUMP_MAGIC_NANO if nano else TCPDUMP_MAGIC if sys.byteorder == 'little': fh = LEFileHdr(snaplen=snaplen, linktype=linktype, magic=magic) else: fh = FileHdr(snaplen=snaplen, linktype=linktype, magic=magic) self.__f.write(bytes(fh)) def writepkt(self, pkt, ts=None): if ts is None: ts = time.time() s = bytes(pkt) n = len(s) sec = int(ts) usec = int(round(ts % 1 * 10 ** self._precision)) if sys.byteorder == 'little': ph = LEPktHdr(tv_sec=sec, tv_usec=usec, caplen=n, len=n) else: ph = PktHdr(tv_sec=sec, tv_usec=usec, caplen=n, len=n) self.__f.write(bytes(ph)) self.__f.write(s) def close(self): self.__f.close() class Reader(object): """Simple pypcap-compatible pcap file reader. TODO: Longer class information.... Attributes: __hdr__: Header fields of simple pypcap-compatible pcap file reader. TODO. """ def __init__(self, fileobj): self.name = getattr(fileobj, 'name', '<%s>' % fileobj.__class__.__name__) self.__f = fileobj buf = self.__f.read(FileHdr.__hdr_len__) self.__fh = FileHdr(buf) self.__ph = PktHdr if self.__fh.magic in (PMUDPCT_MAGIC, PMUDPCT_MAGIC_NANO): self.__fh = LEFileHdr(buf) self.__ph = LEPktHdr elif self.__fh.magic not in (TCPDUMP_MAGIC, TCPDUMP_MAGIC_NANO): raise ValueError('invalid tcpdump header') if self.__fh.linktype in dltoff: self.dloff = dltoff[self.__fh.linktype] else: self.dloff = 0 self._divisor = 1E6 if self.__fh.magic in (TCPDUMP_MAGIC, PMUDPCT_MAGIC) else Decimal('1E9') self.snaplen = self.__fh.snaplen self.filter = '' self.__iter = iter(self) @property def fd(self): return self.__f.fileno() def fileno(self): return self.fd def datalink(self): return self.__fh.linktype def setfilter(self, value, optimize=1): return NotImplementedError def readpkts(self): return list(self) def __next__(self): return next(self.__iter) def dispatch(self, cnt, callback, *args): """Collect and process packets with a user callback. Return the number of packets processed, or 0 for a savefile. Arguments: cnt -- number of packets to process; or 0 to process all packets until EOF callback -- function with (timestamp, pkt, *args) prototype *args -- optional arguments passed to callback on execution """ processed = 0 if cnt > 0: for _ in range(cnt): try: ts, pkt = next(iter(self)) except StopIteration: break callback(ts, pkt, *args) processed += 1 else: for ts, pkt in self: callback(ts, pkt, *args) processed += 1 return processed def loop(self, callback, *args): self.dispatch(0, callback, *args) def __iter__(self): while 1: buf = self.__f.read(PktHdr.__hdr_len__) if not buf: break hdr = self.__ph(buf) buf = self.__f.read(hdr.caplen) yield (hdr.tv_sec + (hdr.tv_usec / self._divisor), buf) def test_pcap_endian(): be = b'\xa1\xb2\xc3\xd4\x00\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x60\x00\x00\x00\x01' le = b'\xd4\xc3\xb2\xa1\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x60\x00\x00\x00\x01\x00\x00\x00' befh = FileHdr(be) lefh = LEFileHdr(le) assert (befh.linktype == lefh.linktype) def test_reader(): data = ( # full libpcap file with one packet 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' b'\xb2\x67\x4a\x42\xae\x91\x07\x00\x46\x00\x00\x00\x46\x00\x00\x00\x00\xc0\x9f\x32\x41\x8c\x00\xe0' b'\x18\xb1\x0c\xad\x08\x00\x45\x00\x00\x38\x00\x00\x40\x00\x40\x11\x65\x47\xc0\xa8\xaa\x08\xc0\xa8' b'\xaa\x14\x80\x1b\x00\x35\x00\x24\x85\xed' ) # --- BytesIO tests --- from .compat import BytesIO # BytesIO fobj = BytesIO(data) reader = Reader(fobj) assert reader.name == '' _, buf1 = next(iter(reader)) assert buf1 == data[FileHdr.__hdr_len__ + PktHdr.__hdr_len__:] # --- dispatch() tests --- # test count = 0 fobj.seek(0) reader = Reader(fobj) assert reader.dispatch(0, lambda ts, pkt: None) == 1 # test count > 0 fobj.seek(0) reader = Reader(fobj) assert reader.dispatch(4, lambda ts, pkt: None) == 1 # test iterative dispatch fobj.seek(0) reader = Reader(fobj) assert reader.dispatch(1, lambda ts, pkt: None) == 1 assert reader.dispatch(1, lambda ts, pkt: None) == 0 def test_writer_precision(): data = b'foo' from .compat import BytesIO # default precision fobj = BytesIO() writer = Writer(fobj) writer.writepkt(data, ts=1454725786.526401) fobj.flush() fobj.seek(0) reader = Reader(fobj) ts, buf1 = next(iter(reader)) assert ts == 1454725786.526401 assert buf1 == b'foo' # nano precision from decimal import Decimal fobj = BytesIO() writer = Writer(fobj, nano=True) writer.writepkt(data, ts=Decimal('1454725786.010203045')) fobj.flush() fobj.seek(0) reader = Reader(fobj) ts, buf1 = next(iter(reader)) assert ts == Decimal('1454725786.010203045') assert buf1 == b'foo' if __name__ == '__main__': test_pcap_endian() test_reader() test_writer_precision() print('Tests Successful...') dpkt-1.9.2/dpkt/pcapng.py000066400000000000000000000607611340335175100152650ustar00rootroot00000000000000"""pcap Next Generation file format""" # Spec: https://pcapng.github.io/pcapng/ # pylint: disable=no-member # pylint: disable=attribute-defined-outside-init from __future__ import print_function from __future__ import absolute_import from struct import pack as struct_pack, unpack as struct_unpack from time import time import sys from . import dpkt from .compat import BytesIO BYTE_ORDER_MAGIC = 0x1A2B3C4D BYTE_ORDER_MAGIC_LE = 0x4D3C2B1A PCAPNG_VERSION_MAJOR = 1 PCAPNG_VERSION_MINOR = 0 # Block types PCAPNG_BT_IDB = 0x00000001 # Interface Description Block PCAPNG_BT_PB = 0x00000002 # Packet Block (deprecated) PCAPNG_BT_SPB = 0x00000003 # Simple Packet Block PCAPNG_BT_EPB = 0x00000006 # Enhanced Packet Block PCAPNG_BT_SHB = 0x0A0D0D0A # Section Header Block # Options PCAPNG_OPT_ENDOFOPT = 0 # end of options PCAPNG_OPT_COMMENT = 1 # comment # SHB options PCAPNG_OPT_SHB_HARDWARE = 2 # description of the hardware PCAPNG_OPT_SHB_OS = 3 # name of the operating system PCAPNG_OPT_SHB_USERAPPL = 4 # name of the application # IDB options PCAPNG_OPT_IF_NAME = 2 # interface name PCAPNG_OPT_IF_DESCRIPTION = 3 # interface description PCAPNG_OPT_IF_IPV4ADDR = 4 # IPv4 network address and netmask for the interface PCAPNG_OPT_IF_IPV6ADDR = 5 # IPv6 network address and prefix length for the interface PCAPNG_OPT_IF_MACADDR = 6 # interface hardware MAC address PCAPNG_OPT_IF_EUIADDR = 7 # interface hardware EUI address PCAPNG_OPT_IF_SPEED = 8 # interface speed in bits/s PCAPNG_OPT_IF_TSRESOL = 9 # timestamp resolution PCAPNG_OPT_IF_TZONE = 10 # time zone PCAPNG_OPT_IF_FILTER = 11 # capture filter PCAPNG_OPT_IF_OS = 12 # operating system PCAPNG_OPT_IF_FCSLEN = 13 # length of the Frame Check Sequence in bits PCAPNG_OPT_IF_TSOFFSET = 14 # offset (in seconds) that must be added to packet timestamp # DLT_NULL = 0 DLT_EN10MB = 1 DLT_EN3MB = 2 DLT_AX25 = 3 DLT_PRONET = 4 DLT_CHAOS = 5 DLT_IEEE802 = 6 DLT_ARCNET = 7 DLT_SLIP = 8 DLT_PPP = 9 DLT_FDDI = 10 DLT_PFSYNC = 18 DLT_IEEE802_11 = 105 DLT_LINUX_SLL = 113 DLT_PFLOG = 117 DLT_IEEE802_11_RADIO = 127 if sys.platform.find('openbsd') != -1: DLT_LOOP = 12 DLT_RAW = 14 else: DLT_LOOP = 108 DLT_RAW = 12 dltoff = {DLT_NULL: 4, DLT_EN10MB: 14, DLT_IEEE802: 22, DLT_ARCNET: 6, DLT_SLIP: 16, DLT_PPP: 4, DLT_FDDI: 21, DLT_PFLOG: 48, DLT_PFSYNC: 4, DLT_LOOP: 4, DLT_LINUX_SLL: 16} # def _swap32b(i): """Swap endianness of an uint32""" return struct_unpack('I', i))[0] def _align32b(i): """Return int `i` aligned to the 32-bit boundary""" r = i % 4 return i if not r else i + 4 - r def _padded(s): """Return bytes `s` padded with zeroes to align to the 32-bit boundary""" return struct_pack('%ss' % _align32b(len(s)), s) def _padlen(s): """Return size of padding required to align str `s` to the 32-bit boundary""" return _align32b(len(s)) - len(s) class _PcapngBlock(dpkt.Packet): """Base class for a pcapng block with Options""" __hdr__ = ( ('type', 'I', 0), # block type ('len', 'I', 12), # block total length: total size of this block, in octets #( body, variable size ) ('_len', 'I', 12), # dup of len ) def unpack_hdr(self, buf): dpkt.Packet.unpack(self, buf) def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.len > len(buf): raise dpkt.NeedData self._do_unpack_options(buf) def _do_unpack_options(self, buf, oo=None): self.opts = [] self.data = '' oo = oo or self.__hdr_len__ - 4 # options offset ol = self.len - oo - 4 # length opts_buf = buf[oo:oo + ol] while opts_buf: opt = (PcapngOptionLE(opts_buf) if self.__hdr_fmt__[0] == '<' else PcapngOption(opts_buf)) self.opts.append(opt) opts_buf = opts_buf[len(opt):] if opt.code == PCAPNG_OPT_ENDOFOPT: break # duplicate total length field self._len = struct_unpack(self.__hdr_fmt__[0] + 'I', buf[-4:])[0] if self._len != self.len: raise dpkt.UnpackError('length fields do not match') def _do_pack_options(self): if not getattr(self, 'opts', None): return b'' if self.opts[-1].code != PCAPNG_OPT_ENDOFOPT: raise dpkt.PackError('options must end with opt_endofopt') return b''.join(bytes(o) for o in self.opts) def __bytes__(self): opts_buf = self._do_pack_options() self.len = self._len = self.__hdr_len__ + len(opts_buf) hdr_buf = dpkt.Packet.pack_hdr(self) return hdr_buf[:-4] + opts_buf + hdr_buf[-4:] def __len__(self): if not getattr(self, 'opts', None): return self.__hdr_len__ opts_len = sum(len(o) for o in self.opts) return self.__hdr_len__ + opts_len class PcapngBlockLE(_PcapngBlock): __byte_order__ = '<' class PcapngOption(dpkt.Packet): """A single Option""" __hdr__ = ( ('code', 'H', PCAPNG_OPT_ENDOFOPT), ('len', 'H', 0), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.data = buf[self.__hdr_len__:self.__hdr_len__ + self.len] # decode comment if self.code == PCAPNG_OPT_COMMENT: self.text = self.data.decode('utf-8') def __bytes__(self): #return dpkt.Packet.__bytes__(self) # encode comment if self.code == PCAPNG_OPT_COMMENT: text = getattr(self, 'text', self.data) self.data = text.encode('utf-8') if not isinstance(text, bytes) else text self.len = len(self.data) return dpkt.Packet.pack_hdr(self) + _padded(self.data) def __len__(self): return self.__hdr_len__ + len(self.data) + _padlen(self.data) def __repr__(self): if self.code == PCAPNG_OPT_ENDOFOPT: return '{0}(opt_endofopt)'.format(self.__class__.__name__) else: return dpkt.Packet.__repr__(self) class PcapngOptionLE(PcapngOption): __byte_order__ = '<' class SectionHeaderBlock(_PcapngBlock): """Section Header block""" __hdr__ = ( ('type', 'I', PCAPNG_BT_SHB), ('len', 'I', 28), ('bom', 'I', BYTE_ORDER_MAGIC), ('v_major', 'H', PCAPNG_VERSION_MAJOR), ('v_minor', 'H', PCAPNG_VERSION_MINOR), ('sec_len', 'q', -1), # section length, -1 = auto #( options, variable size ) ('_len', 'I', 28) ) class SectionHeaderBlockLE(SectionHeaderBlock): __byte_order__ = '<' class InterfaceDescriptionBlock(_PcapngBlock): """Interface Description block""" __hdr__ = ( ('type', 'I', PCAPNG_BT_IDB), ('len', 'I', 20), ('linktype', 'H', DLT_EN10MB), ('_reserved', 'H', 0), ('snaplen', 'I', 1500), #( options, variable size ) ('_len', 'I', 20) ) class InterfaceDescriptionBlockLE(InterfaceDescriptionBlock): __byte_order__ = '<' class EnhancedPacketBlock(_PcapngBlock): """Enhanced Packet block""" __hdr__ = ( ('type', 'I', PCAPNG_BT_EPB), ('len', 'I', 64), ('iface_id', 'I', 0), ('ts_high', 'I', 0), # timestamp high ('ts_low', 'I', 0), # timestamp low ('caplen', 'I', 0), # captured len, size of pkt_data ('pkt_len', 'I', 0), # actual packet len #( pkt_data, variable size ) #( options, variable size ) ('_len', 'I', 64) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.len > len(buf): raise dpkt.NeedData # packet data po = self.__hdr_len__ - 4 # offset of pkt_data self.pkt_data = buf[po:po + self.caplen] # skip padding between pkt_data and options opts_offset = po + _align32b(self.caplen) self._do_unpack_options(buf, opts_offset) def __bytes__(self): pkt_buf = self.pkt_data self.caplen = self.pkt_len = len(pkt_buf) opts_buf = self._do_pack_options() self.len = self._len = self.__hdr_len__ + _align32b(self.caplen) + len(opts_buf) hdr_buf = dpkt.Packet.pack_hdr(self) return hdr_buf[:-4] + _padded(pkt_buf) + opts_buf + hdr_buf[-4:] def __len__(self): opts_len = sum(len(o) for o in self.opts) return self.__hdr_len__ + _align32b(self.caplen) + opts_len class EnhancedPacketBlockLE(EnhancedPacketBlock): __byte_order__ = '<' class Writer(object): """Simple pcapng dumpfile writer.""" def __init__(self, fileobj, snaplen=1500, linktype=DLT_EN10MB, shb=None, idb=None): """ Create a pcapng dumpfile writer for the given fileobj. shb can be an instance of SectionHeaderBlock(LE) idb can be an instance of InterfaceDescriptionBlock(LE) """ self.__f = fileobj self.__le = sys.byteorder == 'little' if shb: self._validate_block('shb', shb, SectionHeaderBlock) if idb: self._validate_block('idb', idb, InterfaceDescriptionBlock) if self.__le: shb = shb or SectionHeaderBlockLE() idb = idb or InterfaceDescriptionBlockLE(snaplen=snaplen, linktype=linktype) else: shb = shb or SectionHeaderBlock() idb = idb or InterfaceDescriptionBlock(snaplen=snaplen, linktype=linktype) self.__f.write(bytes(shb)) self.__f.write(bytes(idb)) def _validate_block(self, arg_name, blk, expected_cls): """Check a user-defined block for correct type and endianness""" if not isinstance(blk, expected_cls): raise ValueError('{0}: expecting class {1}'.format( arg_name, expected_cls.__name__)) if self.__le and blk.__hdr_fmt__[0] == '>': raise ValueError('{0}: expecting class {1}LE on a little-endian system'.format( arg_name, expected_cls.__name__)) if not self.__le and blk.__hdr_fmt__[0] == '<': raise ValueError('{0}: expecting class {1} on a big-endian system'.format( arg_name, expected_cls.__name__.replace('LE', ''))) def writepkt(self, pkt, ts=None): """ Write a single packet with its timestamp. pkt can be a buffer or an instance of EnhancedPacketBlock(LE) ts is a Unix timestamp in seconds since Epoch (e.g. 1454725786.99) """ if isinstance(pkt, EnhancedPacketBlock): self._validate_block('pkt', pkt, EnhancedPacketBlock) if ts is not None: # ts as an argument gets precedence ts = int(round(ts * 1e6)) elif pkt.ts_high == pkt.ts_low == 0: ts = int(round(time() * 1e6)) if ts is not None: pkt.ts_high = ts >> 32 pkt.ts_low = ts & 0xffffffff self.__f.write(bytes(pkt)) return # pkt is a buffer - wrap it into an EPB if ts is None: ts = time() ts = int(round(ts * 1e6)) # to int microseconds s = bytes(pkt) n = len(s) kls = EnhancedPacketBlockLE if self.__le else EnhancedPacketBlock epb = kls(ts_high=ts >> 32, ts_low=ts & 0xffffffff, caplen=n, pkt_len=n, pkt_data=s) self.__f.write(bytes(epb)) def close(self): self.__f.close() class Reader(object): """Simple pypcap-compatible pcapng file reader.""" def __init__(self, fileobj): self.name = getattr(fileobj, 'name', '<{0}>'.format(fileobj.__class__.__name__)) self.__f = fileobj shb = SectionHeaderBlock() buf = self.__f.read(shb.__hdr_len__) if len(buf) < shb.__hdr_len__: raise ValueError('invalid pcapng header') # unpack just the header since endianness is not known shb.unpack_hdr(buf) if shb.type != PCAPNG_BT_SHB: raise ValueError('invalid pcapng header: not a SHB') # determine the correct byte order and reload full SHB if shb.bom == BYTE_ORDER_MAGIC_LE: self.__le = True buf += self.__f.read(_swap32b(shb.len) - shb.__hdr_len__) shb = SectionHeaderBlockLE(buf) elif shb.bom == BYTE_ORDER_MAGIC: self.__le = False buf += self.__f.read(shb.len - shb.__hdr_len__) shb = SectionHeaderBlock(buf) else: raise ValueError('unknown endianness') # check if this version is supported if shb.v_major != PCAPNG_VERSION_MAJOR: raise ValueError('unknown pcapng version {0}.{1}'.format(shb.v_major, shb.v_minor,)) # look for a mandatory IDB idb = None while 1: buf = self.__f.read(8) if len(buf) < 8: break blk_type, blk_len = struct_unpack('II', buf) buf += self.__f.read(blk_len - 8) if blk_type == PCAPNG_BT_IDB: idb = (InterfaceDescriptionBlockLE(buf) if self.__le else InterfaceDescriptionBlock(buf)) break # just skip other blocks if idb is None: raise ValueError('IDB not found') # set timestamp resolution and offset self._divisor = float(1e6) # defaults self._tsoffset = 0 for opt in idb.opts: if opt.code == PCAPNG_OPT_IF_TSRESOL: # if MSB=0, the remaining bits is a neg power of 10 (e.g. 6 means microsecs) # if MSB=1, the remaining bits is a neg power of 2 (e.g. 10 means 1/1024 of second) opt_val = struct_unpack('b', opt.data)[0] pow_num = 2 if opt_val & 0b10000000 else 10 self._divisor = float(pow_num ** (opt_val & 0b01111111)) elif opt.code == PCAPNG_OPT_IF_TSOFFSET: # 64-bit int that specifies an offset (in seconds) that must be added to the # timestamp of each packet self._tsoffset = struct_unpack('q', opt.data)[0] if idb.linktype in dltoff: self.dloff = dltoff[idb.linktype] else: self.dloff = 0 self.idb = idb self.snaplen = idb.snaplen self.filter = '' self.__iter = iter(self) @property def fd(self): return self.__f.fileno() def fileno(self): return self.fd def datalink(self): return self.idb.linktype def setfilter(self, value, optimize=1): return NotImplementedError def readpkts(self): return list(self) def next(self): return next(self.__iter) def dispatch(self, cnt, callback, *args): """Collect and process packets with a user callback. Return the number of packets processed, or 0 for a savefile. Arguments: cnt -- number of packets to process; or 0 to process all packets until EOF callback -- function with (timestamp, pkt, *args) prototype *args -- optional arguments passed to callback on execution """ processed = 0 if cnt > 0: for _ in range(cnt): try: ts, pkt = next(iter(self)) except StopIteration: break callback(ts, pkt, *args) processed += 1 else: for ts, pkt in self: callback(ts, pkt, *args) processed += 1 return processed def loop(self, callback, *args): self.dispatch(0, callback, *args) def __iter__(self): while 1: buf = self.__f.read(8) if len(buf) < 8: break blk_type, blk_len = struct_unpack('II', buf) buf += self.__f.read(blk_len - 8) if blk_type == PCAPNG_BT_EPB: epb = EnhancedPacketBlockLE(buf) if self.__le else EnhancedPacketBlock(buf) ts = self._tsoffset + (((epb.ts_high << 32) | epb.ts_low) / self._divisor) yield (ts, epb.pkt_data) # just ignore other blocks ######### # TESTS # ######### def test_shb(): """Test SHB with options""" buf = ( b'\x0a\x0d\x0d\x0a\x58\x00\x00\x00\x4d\x3c\x2b\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff' b'\xff\xff\x04\x00\x31\x00\x54\x53\x68\x61\x72\x6b\x20\x31\x2e\x31\x30\x2e\x30\x72\x63\x32' b'\x20\x28\x53\x56\x4e\x20\x52\x65\x76\x20\x34\x39\x35\x32\x36\x20\x66\x72\x6f\x6d\x20\x2f' b'\x74\x72\x75\x6e\x6b\x2d\x31\x2e\x31\x30\x29\x00\x00\x00\x00\x00\x00\x00\x58\x00\x00\x00') opt_buf = b'\x04\x00\x31\x00TShark 1.10.0rc2 (SVN Rev 49526 from /trunk-1.10)\x00\x00\x00' # block unpacking shb = SectionHeaderBlockLE(buf) assert shb.type == PCAPNG_BT_SHB assert shb.bom == BYTE_ORDER_MAGIC assert shb.v_major == 1 assert shb.v_minor == 0 assert shb.sec_len == -1 assert shb.data == '' # options unpacking assert len(shb.opts) == 2 assert shb.opts[0].code == PCAPNG_OPT_SHB_USERAPPL assert shb.opts[0].data == b'TShark 1.10.0rc2 (SVN Rev 49526 from /trunk-1.10)' assert shb.opts[0].len == len(shb.opts[0].data) assert shb.opts[1].code == PCAPNG_OPT_ENDOFOPT assert shb.opts[1].len == 0 # option packing assert str(shb.opts[0]) == str(opt_buf) assert len(shb.opts[0]) == len(opt_buf) assert bytes(shb.opts[1]) == b'\x00\x00\x00\x00' # block packing assert str(shb) == str(buf) assert len(shb) == len(buf) def test_idb(): """Test IDB with options""" buf = ( b'\x01\x00\x00\x00\x20\x00\x00\x00\x01\x00\x00\x00\xff\xff\x00\x00\x09\x00\x01\x00\x06\x00' b'\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00') # block unpacking idb = InterfaceDescriptionBlockLE(buf) assert idb.type == PCAPNG_BT_IDB assert idb.linktype == DLT_EN10MB assert idb.snaplen == 0xffff assert idb.data == '' # options unpacking assert len(idb.opts) == 2 assert idb.opts[0].code == PCAPNG_OPT_IF_TSRESOL assert idb.opts[0].len == 1 assert idb.opts[0].data == b'\x06' assert idb.opts[1].code == PCAPNG_OPT_ENDOFOPT assert idb.opts[1].len == 0 # option packing assert bytes(idb.opts[0]) == b'\x09\x00\x01\x00\x06\x00\x00\x00' assert len(idb.opts[0]) == 8 assert bytes(idb.opts[1]) == b'\x00\x00\x00\x00' # block packing assert str(idb) == str(buf) assert len(idb) == len(buf) def test_epb(): """Test EPB with a non-ascii comment option""" buf = ( b'\x06\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x73\xe6\x04\x00\xbe\x37\xe2\x19\x4a\x00' b'\x00\x00\x4a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x45\x00' b'\x00\x3c\x5d\xb3\x40\x00\x40\x06\xdf\x06\x7f\x00\x00\x01\x7f\x00\x00\x01\x98\x34\x11\x4e' b'\x95\xcb\x2d\x3a\x00\x00\x00\x00\xa0\x02\xaa\xaa\xfe\x30\x00\x00\x02\x04\xff\xd7\x04\x02' b'\x08\x0a\x05\x8f\x70\x89\x00\x00\x00\x00\x01\x03\x03\x07\x00\x00\x01\x00\x0a\x00\xd0\xbf' b'\xd0\xb0\xd0\xba\xd0\xb5\xd1\x82\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00') # block unpacking epb = EnhancedPacketBlockLE(buf) assert epb.type == PCAPNG_BT_EPB assert epb.caplen == len(epb.pkt_data) assert epb.pkt_len == len(epb.pkt_data) assert epb.caplen == 74 assert epb.ts_high == 321139 assert epb.ts_low == 434255806 assert epb.data == '' # options unpacking assert len(epb.opts) == 2 assert epb.opts[0].code == PCAPNG_OPT_COMMENT assert epb.opts[0].text == u'\u043f\u0430\u043a\u0435\u0442' assert epb.opts[1].code == PCAPNG_OPT_ENDOFOPT assert epb.opts[1].len == 0 # option packing assert bytes(epb.opts[0]) == b'\x01\x00\x0a\x00\xd0\xbf\xd0\xb0\xd0\xba\xd0\xb5\xd1\x82\x00\x00' assert len(epb.opts[0]) == 16 assert bytes(epb.opts[1]) == b'\x00\x00\x00\x00' # block packing assert str(epb) == str(buf) assert len(epb) == len(buf) def test_simple_write_read(): """Test writing a basic pcapng and then reading it""" fobj = BytesIO() writer = Writer(fobj, snaplen=0x2000, linktype=DLT_LINUX_SLL) writer.writepkt(b'foo', ts=1454725786.526401) fobj.flush() fobj.seek(0) reader = Reader(fobj) assert reader.snaplen == 0x2000 assert reader.datalink() == DLT_LINUX_SLL ts, buf1 = next(iter(reader)) assert ts == 1454725786.526401 assert buf1 == b'foo' # test dispatch() fobj.seek(0) reader = Reader(fobj) assert reader.dispatch(1, lambda ts, pkt: None) == 1 assert reader.dispatch(1, lambda ts, pkt: None) == 0 fobj.close() def test_custom_read_write(): """Test a full pcapng file with 1 ICMP packet""" buf = ( b'\x0a\x0d\x0d\x0a\x7c\x00\x00\x00\x4d\x3c\x2b\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff' b'\xff\xff\x03\x00\x1e\x00\x36\x34\x2d\x62\x69\x74\x20\x57\x69\x6e\x64\x6f\x77\x73\x20\x38' b'\x2e\x31\x2c\x20\x62\x75\x69\x6c\x64\x20\x39\x36\x30\x30\x00\x00\x04\x00\x34\x00\x44\x75' b'\x6d\x70\x63\x61\x70\x20\x31\x2e\x31\x32\x2e\x37\x20\x28\x76\x31\x2e\x31\x32\x2e\x37\x2d' b'\x30\x2d\x67\x37\x66\x63\x38\x39\x37\x38\x20\x66\x72\x6f\x6d\x20\x6d\x61\x73\x74\x65\x72' b'\x2d\x31\x2e\x31\x32\x29\x00\x00\x00\x00\x7c\x00\x00\x00\x01\x00\x00\x00\x7c\x00\x00\x00' b'\x01\x00\x00\x00\x00\x00\x04\x00\x02\x00\x32\x00\x5c\x44\x65\x76\x69\x63\x65\x5c\x4e\x50' b'\x46\x5f\x7b\x33\x42\x42\x46\x32\x31\x41\x37\x2d\x39\x31\x41\x45\x2d\x34\x44\x44\x42\x2d' b'\x41\x42\x32\x43\x2d\x43\x37\x38\x32\x39\x39\x39\x43\x32\x32\x44\x35\x7d\x00\x00\x09\x00' b'\x01\x00\x06\x00\x00\x00\x0c\x00\x1e\x00\x36\x34\x2d\x62\x69\x74\x20\x57\x69\x6e\x64\x6f' b'\x77\x73\x20\x38\x2e\x31\x2c\x20\x62\x75\x69\x6c\x64\x20\x39\x36\x30\x30\x00\x00\x00\x00' b'\x00\x00\x7c\x00\x00\x00\x06\x00\x00\x00\x84\x00\x00\x00\x00\x00\x00\x00\x63\x20\x05\x00' b'\xd6\xc4\xab\x0b\x4a\x00\x00\x00\x4a\x00\x00\x00\x08\x00\x27\x96\xcb\x7c\x52\x54\x00\x12' b'\x35\x02\x08\x00\x45\x00\x00\x3c\xa4\x40\x00\x00\x1f\x01\x27\xa2\xc0\xa8\x03\x28\x0a\x00' b'\x02\x0f\x00\x00\x56\xf0\x00\x01\x00\x6d\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c' b'\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x41\x42\x43\x44\x45\x46\x47\x48\x49\x00\x00' b'\x01\x00\x0f\x00\x64\x70\x6b\x74\x20\x69\x73\x20\x61\x77\x65\x73\x6f\x6d\x65\x00\x00\x00' b'\x00\x00\x84\x00\x00\x00') fobj = BytesIO(buf) # test reading reader = Reader(fobj) assert reader.snaplen == 0x40000 assert reader.datalink() == DLT_EN10MB assert reader.idb.opts[0].data.decode('utf-8') == '\\Device\\NPF_{3BBF21A7-91AE-4DDB-AB2C-C782999C22D5}' assert reader.idb.opts[2].data.decode('utf-8') == '64-bit Windows 8.1, build 9600' ts, buf1 = next(iter(reader)) assert ts == 1442984653.2108380 assert len(buf1) == 74 assert buf1.startswith(b'\x08\x00\x27\x96') assert buf1.endswith(b'FGHI') fobj.close() # test pcapng customized writing shb = SectionHeaderBlockLE(opts=[ PcapngOptionLE(code=3, data=b'64-bit Windows 8.1, build 9600'), PcapngOptionLE(code=4, data=b'Dumpcap 1.12.7 (v1.12.7-0-g7fc8978 from master-1.12)'), PcapngOptionLE() ]) idb = InterfaceDescriptionBlockLE(snaplen=0x40000, opts=[ PcapngOptionLE(code=2, data=b'\\Device\\NPF_{3BBF21A7-91AE-4DDB-AB2C-C782999C22D5}'), PcapngOptionLE(code=9, data=b'\x06'), PcapngOptionLE(code=12, data=b'64-bit Windows 8.1, build 9600'), PcapngOptionLE() ]) epb = EnhancedPacketBlockLE(opts=[ PcapngOptionLE(code=1, text=b'dpkt is awesome'), PcapngOptionLE() ], pkt_data=( b'\x08\x00\x27\x96\xcb\x7c\x52\x54\x00\x12\x35\x02\x08\x00\x45\x00\x00\x3c\xa4\x40\x00\x00' b'\x1f\x01\x27\xa2\xc0\xa8\x03\x28\x0a\x00\x02\x0f\x00\x00\x56\xf0\x00\x01\x00\x6d\x41\x42' b'\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x41' b'\x42\x43\x44\x45\x46\x47\x48\x49' )) fobj = BytesIO() writer = Writer(fobj, shb=shb, idb=idb) writer.writepkt(epb, ts=1442984653.210838) assert fobj.getvalue() == buf fobj.close() # same with timestamps defined inside EPB epb.ts_high = 335971 epb.ts_low = 195806422 fobj = BytesIO() writer = Writer(fobj, shb=shb, idb=idb) writer.writepkt(epb) assert fobj.getvalue() == buf fobj.close() if __name__ == '__main__': # TODO: big endian unit tests; could not find any examples.. test_shb() test_idb() test_epb() test_simple_write_read() test_custom_read_write() repr(PcapngOptionLE()) print('Tests Successful...') dpkt-1.9.2/dpkt/pim.py000066400000000000000000000023301340335175100145660ustar00rootroot00000000000000# $Id: pim.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Protocol Independent Multicast.""" from __future__ import absolute_import from . import dpkt from .decorators import deprecated class PIM(dpkt.Packet): """Protocol Independent Multicast. TODO: Longer class information.... Attributes: __hdr__: Header fields of PIM. TODO. """ __hdr__ = ( ('_v_type', 'B', 0x20), ('rsvd', 'B', 0), ('sum', 'H', 0) ) @property def v(self): return self._v_type >> 4 @v.setter def v(self, v): self._v_type = (v << 4) | (self._v_type & 0xf) @property def type(self): return self._v_type & 0xf @type.setter def type(self, type): self._v_type = (self._v_type & 0xf0) | type def __bytes__(self): if not self.sum: self.sum = dpkt.in_cksum(dpkt.Packet.__bytes__(self)) return dpkt.Packet.__bytes__(self) def test_pim(): pimdata = PIM(b'\x20\x00\x9f\xf4\x00\x01\x00\x02\x00\x69') assert pimdata.v == 2 assert pimdata.type == 0 # test setters pimdata.v = 3 pimdata.type = 1 assert bytes(pimdata) == b'\x31\x00\x9f\xf4\x00\x01\x00\x02\x00\x69' dpkt-1.9.2/dpkt/pmap.py000066400000000000000000000010001340335175100147270ustar00rootroot00000000000000# $Id: pmap.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Portmap / rpcbind.""" from __future__ import absolute_import from . import dpkt PMAP_PROG = 100000 PMAP_PROCDUMP = 4 PMAP_VERS = 2 class Pmap(dpkt.Packet): """Portmap / rpcbind. TODO: Longer class information.... Attributes: __hdr__: Header fields of Pmap. TODO. """ __hdr__ = ( ('prog', 'I', 0), ('vers', 'I', 0), ('prot', 'I', 0), ('port', 'I', 0), ) dpkt-1.9.2/dpkt/ppp.py000066400000000000000000000051621340335175100146060ustar00rootroot00000000000000# $Id: ppp.py 65 2010-03-26 02:53:51Z dugsong $ # -*- coding: utf-8 -*- """Point-to-Point Protocol.""" from __future__ import absolute_import import struct from . import dpkt # XXX - finish later # http://www.iana.org/assignments/ppp-numbers PPP_IP = 0x21 # Internet Protocol PPP_IP6 = 0x57 # Internet Protocol v6 # Protocol field compression PFC_BIT = 0x01 class PPP(dpkt.Packet): # Note: This class is subclassed in PPPoE """Point-to-Point Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of PPP. TODO. """ __hdr__ = ( ('addr', 'B', 0xff), ('cntrl', 'B', 3), ('p', 'B', PPP_IP), ) _protosw = {} @classmethod def set_p(cls, p, pktclass): cls._protosw[p] = pktclass @classmethod def get_p(cls, p): return cls._protosw[p] def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.p & PFC_BIT == 0: try: self.p = struct.unpack('>H', buf[2:4])[0] except struct.error: raise dpkt.NeedData self.data = self.data[1:] try: self.data = self._protosw[self.p](self.data) setattr(self, self.data.__class__.__name__.lower(), self.data) except (KeyError, struct.error, dpkt.UnpackError): pass def pack_hdr(self): try: if self.p > 0xff: return struct.pack('>BBH', self.addr, self.cntrl, self.p) return dpkt.Packet.pack_hdr(self) except struct.error as e: raise dpkt.PackError(str(e)) def __load_protos(): g = globals() for k, v in g.items(): if k.startswith('PPP_'): name = k[4:] modname = name.lower() try: mod = __import__(modname, g, level=1) PPP.set_p(v, getattr(mod, name)) except (ImportError, AttributeError): continue def _mod_init(): """Post-initialization called when all dpkt modules are fully loaded""" if not PPP._protosw: __load_protos() def test_ppp(): # Test protocol compression s = b"\xff\x03\x21" p = PPP(s) assert p.p == 0x21 s = b"\xff\x03\x00\x21" p = PPP(s) assert p.p == 0x21 def test_ppp_short(): s = b"\xff\x03\x00" import pytest pytest.raises(dpkt.NeedData, PPP, s) def test_packing(): p = PPP() assert p.pack_hdr() == b"\xff\x03\x21" p.p = 0xc021 # LCP assert p.pack_hdr() == b"\xff\x03\xc0\x21" if __name__ == '__main__': # Runs all the test associated with this class/file test_ppp() dpkt-1.9.2/dpkt/pppoe.py000066400000000000000000000076761340335175100151460ustar00rootroot00000000000000# $Id: pppoe.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """PPP-over-Ethernet.""" from __future__ import absolute_import import struct import codecs from . import dpkt from . import ppp from .decorators import deprecated # RFC 2516 codes PPPoE_PADI = 0x09 PPPoE_PADO = 0x07 PPPoE_PADR = 0x19 PPPoE_PADS = 0x65 PPPoE_PADT = 0xA7 PPPoE_SESSION = 0x00 class PPPoE(dpkt.Packet): """PPP-over-Ethernet. TODO: Longer class information.... Attributes: __hdr__: Header fields of PPPoE. TODO. """ __hdr__ = ( ('_v_type', 'B', 0x11), ('code', 'B', 0), ('session', 'H', 0), ('len', 'H', 0) # payload length ) @property def v(self): return self._v_type >> 4 @v.setter def v(self, v): self._v_type = (v << 4) | (self._v_type & 0xf) @property def type(self): return self._v_type & 0xf @type.setter def type(self, t): self._v_type = (self._v_type & 0xf0) | t def unpack(self, buf): dpkt.Packet.unpack(self, buf) try: if self.code == 0: # We need to use the pppoe.PPP header here, because PPPoE # doesn't do the normal encapsulation. self.data = self.ppp = PPP(self.data) except dpkt.UnpackError: pass class PPP(ppp.PPP): # Light version for protocols without the usual encapsulation, for PPPoE __hdr__ = ( # Usuaully two-bytes, but while protocol compression is not recommended, it is supported ('p', 'B', ppp.PPP_IP), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.p & ppp.PFC_BIT == 0: try: self.p = struct.unpack('>H', buf[:2])[0] except struct.error: raise dpkt.NeedData self.data = self.data[1:] try: self.data = self._protosw[self.p](self.data) setattr(self, self.data.__class__.__name__.lower(), self.data) except (KeyError, struct.error, dpkt.UnpackError): pass def pack_hdr(self): try: # Protocol compression is *not* recommended (RFC2516), but we do it anyway if self.p > 0xff: return struct.pack('>H', self.p) return dpkt.Packet.pack_hdr(self) except struct.error as e: raise dpkt.PackError(str(e)) def test_pppoe_discovery(): s = ("11070000002801010000010300046413" "85180102000442524153010400103d0f" "0587062484f2df32b9ddfd77bd5b") s = codecs.decode(s, 'hex') p = PPPoE(s) assert p.code == PPPoE_PADO assert p.v == 1 assert p.type == 1 s = ("11190000002801010000010300046413" "85180102000442524153010400103d0f" "0587062484f2df32b9ddfd77bd5b") s = codecs.decode(s, 'hex') p = PPPoE(s) assert p.code == PPPoE_PADR assert p.pack_hdr() == s[:6] def test_pppoe_session(): s = "11000011000cc0210101000a050605fcd459" s = codecs.decode(s, 'hex') p = PPPoE(s) assert p.code == PPPoE_SESSION assert isinstance(p.ppp, PPP) assert p.data.p == 0xc021 # LCP assert len(p.data.data) == 10 assert p.data.pack_hdr() == b"\xc0\x21" s = ("110000110066005760000000003c3a40fc000000000000000000000000000001" "fc0000000002010000000000000100018100bf291f9700010102030405060708" "090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728" "292a2b2c2d2e2f3031323334") s = codecs.decode(s, 'hex') p = PPPoE(s) assert p.code == PPPoE_SESSION assert isinstance(p.ppp, PPP) assert p.data.p == ppp.PPP_IP6 assert p.data.data.p == 58 # ICMPv6 assert p.ppp.pack_hdr() == b"\x57" def test_ppp_packing(): p = PPP() assert p.pack_hdr() == b"\x21" p.p = 0xc021 # LCP assert p.pack_hdr() == b"\xc0\x21" def test_ppp_short(): import pytest pytest.raises(dpkt.NeedData, PPP, b"\x00") # XXX - TODO TLVs, etc. dpkt-1.9.2/dpkt/qq.py000066400000000000000000000152051340335175100144270ustar00rootroot00000000000000# $Id: qq.py 48 2008-05-27 17:31:15Z yardley $ # -*- coding: utf-8 -*- from __future__ import absolute_import from .dpkt import Packet # header_type QQ_HEADER_BASIC_FAMILY = 0x02 QQ_HEADER_P2P_FAMILY = 0x00 QQ_HEADER_03_FAMILY = 0x03 QQ_HEADER_04_FAMILY = 0x04 QQ_HEADER_05_FAMILY = 0x05 header_type_str = [ "QQ_HEADER_P2P_FAMILY", "Unknown Type", "QQ_HEADER_03_FAMILY", "QQ_HEADER_04_FAMILY", "QQ_HEADER_05_FAMILY", ] # command QQ_CMD_LOGOUT = 0x0001 QQ_CMD_KEEP_ALIVE = 0x0002 QQ_CMD_MODIFY_INFO = 0x0004 QQ_CMD_SEARCH_USER = 0x0005 QQ_CMD_GET_USER_INFO = 0x0006 QQ_CMD_ADD_FRIEND = 0x0009 QQ_CMD_DELETE_FRIEND = 0x000A QQ_CMD_ADD_FRIEND_AUTH = 0x000B QQ_CMD_CHANGE_STATUS = 0x000D QQ_CMD_ACK_SYS_MSG = 0x0012 QQ_CMD_SEND_IM = 0x0016 QQ_CMD_RECV_IM = 0x0017 QQ_CMD_REMOVE_SELF = 0x001C QQ_CMD_REQUEST_KEY = 0x001D QQ_CMD_LOGIN = 0x0022 QQ_CMD_GET_FRIEND_LIST = 0x0026 QQ_CMD_GET_ONLINE_OP = 0x0027 QQ_CMD_SEND_SMS = 0x002D QQ_CMD_CLUSTER_CMD = 0x0030 QQ_CMD_TEST = 0x0031 QQ_CMD_GROUP_DATA_OP = 0x003C QQ_CMD_UPLOAD_GROUP_FRIEND = 0x003D QQ_CMD_FRIEND_DATA_OP = 0x003E QQ_CMD_DOWNLOAD_GROUP_FRIEND = 0x0058 QQ_CMD_FRIEND_LEVEL_OP = 0x005C QQ_CMD_PRIVACY_DATA_OP = 0x005E QQ_CMD_CLUSTER_DATA_OP = 0x005F QQ_CMD_ADVANCED_SEARCH = 0x0061 QQ_CMD_REQUEST_LOGIN_TOKEN = 0x0062 QQ_CMD_USER_PROPERTY_OP = 0x0065 QQ_CMD_TEMP_SESSION_OP = 0x0066 QQ_CMD_SIGNATURE_OP = 0x0067 QQ_CMD_RECV_MSG_SYS = 0x0080 QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS = 0x0081 QQ_CMD_WEATHER_OP = 0x00A6 QQ_CMD_ADD_FRIEND_EX = 0x00A7 QQ_CMD_AUTHORIZE = 0X00A8 QQ_CMD_UNKNOWN = 0xFFFF QQ_SUB_CMD_SEARCH_ME_BY_QQ_ONLY = 0x03 QQ_SUB_CMD_SHARE_GEOGRAPHY = 0x04 QQ_SUB_CMD_GET_FRIEND_LEVEL = 0x02 QQ_SUB_CMD_GET_CLUSTER_ONLINE_MEMBER = 0x01 QQ_05_CMD_REQUEST_AGENT = 0x0021 QQ_05_CMD_REQUEST_FACE = 0x0022 QQ_05_CMD_TRANSFER = 0x0023 QQ_05_CMD_REQUEST_BEGIN = 0x0026 QQ_CLUSTER_CMD_CREATE_CLUSTER = 0x01 QQ_CLUSTER_CMD_MODIFY_MEMBER = 0x02 QQ_CLUSTER_CMD_MODIFY_CLUSTER_INFO = 0x03 QQ_CLUSTER_CMD_GET_CLUSTER_INFO = 0x04 QQ_CLUSTER_CMD_ACTIVATE_CLUSTER = 0x05 QQ_CLUSTER_CMD_SEARCH_CLUSTER = 0x06 QQ_CLUSTER_CMD_JOIN_CLUSTER = 0x07 QQ_CLUSTER_CMD_JOIN_CLUSTER_AUTH = 0x08 QQ_CLUSTER_CMD_EXIT_CLUSTER = 0x09 QQ_CLUSTER_CMD_SEND_IM = 0x0A QQ_CLUSTER_CMD_GET_ONLINE_MEMBER = 0x0B QQ_CLUSTER_CMD_GET_MEMBER_INFO = 0x0C QQ_CLUSTER_CMD_MODIFY_CARD = 0x0E QQ_CLUSTER_CMD_GET_CARD_BATCH = 0x0F QQ_CLUSTER_CMD_GET_CARD = 0x10 QQ_CLUSTER_CMD_COMMIT_ORGANIZATION = 0x11 QQ_CLUSTER_CMD_UPDATE_ORGANIZATION = 0x12 QQ_CLUSTER_CMD_COMMIT_MEMBER_ORGANIZATION = 0x13 QQ_CLUSTER_CMD_GET_VERSION_ID = 0x19 QQ_CLUSTER_CMD_SEND_IM_EX = 0x1A QQ_CLUSTER_CMD_SET_ROLE = 0x1B QQ_CLUSTER_CMD_TRANSFER_ROLE = 0x1C QQ_CLUSTER_CMD_CREATE_TEMP = 0x30 QQ_CLUSTER_CMD_MODIFY_TEMP_MEMBER = 0x31 QQ_CLUSTER_CMD_EXIT_TEMP = 0x32 QQ_CLUSTER_CMD_GET_TEMP_INFO = 0x33 QQ_CLUSTER_CMD_MODIFY_TEMP_INFO = 0x34 QQ_CLUSTER_CMD_SEND_TEMP_IM = 0x35 QQ_CLUSTER_CMD_SUB_CLUSTER_OP = 0x36 QQ_CLUSTER_CMD_ACTIVATE_TEMP = 0x37 QQ_CLUSTER_SUB_CMD_ADD_MEMBER = 0x01 QQ_CLUSTER_SUB_CMD_REMOVE_MEMBER = 0x02 QQ_CLUSTER_SUB_CMD_GET_SUBJECT_LIST = 0x02 QQ_CLUSTER_SUB_CMD_GET_DIALOG_LIST = 0x01 QQ_SUB_CMD_GET_ONLINE_FRIEND = 0x2 QQ_SUB_CMD_GET_ONLINE_SERVICE = 0x3 QQ_SUB_CMD_UPLOAD_GROUP_NAME = 0x2 QQ_SUB_CMD_DOWNLOAD_GROUP_NAME = 0x1 QQ_SUB_CMD_SEND_TEMP_SESSION_IM = 0x01 QQ_SUB_CMD_BATCH_DOWNLOAD_FRIEND_REMARK = 0x0 QQ_SUB_CMD_UPLOAD_FRIEND_REMARK = 0x1 QQ_SUB_CMD_REMOVE_FRIEND_FROM_LIST = 0x2 QQ_SUB_CMD_DOWNLOAD_FRIEND_REMARK = 0x3 QQ_SUB_CMD_MODIFY_SIGNATURE = 0x01 QQ_SUB_CMD_DELETE_SIGNATURE = 0x02 QQ_SUB_CMD_GET_SIGNATURE = 0x03 QQ_SUB_CMD_GET_USER_PROPERTY = 0x01 QQ_SUB_CMD_GET_WEATHER = 0x01 QQ_FILE_CMD_HEART_BEAT = 0x0001 QQ_FILE_CMD_HEART_BEAT_ACK = 0x0002 QQ_FILE_CMD_TRANSFER_FINISHED = 0x0003 QQ_FILE_CMD_FILE_OP = 0x0007 QQ_FILE_CMD_FILE_OP_ACK = 0x0008 QQ_FILE_CMD_SENDER_SAY_HELLO = 0x0031 QQ_FILE_CMD_SENDER_SAY_HELLO_ACK = 0x0032 QQ_FILE_CMD_RECEIVER_SAY_HELLO = 0x0033 QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK = 0x0034 QQ_FILE_CMD_NOTIFY_IP_ACK = 0x003C QQ_FILE_CMD_PING = 0x003D QQ_FILE_CMD_PONG = 0x003E QQ_FILE_CMD_YES_I_AM_BEHIND_FIREWALL = 0x0040 QQ_FILE_CMD_REQUEST_AGENT = 0x0001 QQ_FILE_CMD_CHECK_IN = 0x0002 QQ_FILE_CMD_FORWARD = 0x0003 QQ_FILE_CMD_FORWARD_FINISHED = 0x0004 QQ_FILE_CMD_IT_IS_TIME = 0x0005 QQ_FILE_CMD_I_AM_READY = 0x0006 command_str = { 0x0001: "QQ_CMD_LOGOUT", 0x0002: "QQ_CMD_KEEP_ALIVE", 0x0004: "QQ_CMD_MODIFY_INFO", 0x0005: "QQ_CMD_SEARCH_USER", 0x0006: "QQ_CMD_GET_USER_INFO", 0x0009: "QQ_CMD_ADD_FRIEND", 0x000A: "QQ_CMD_DELETE_FRIEND", 0x000B: "QQ_CMD_ADD_FRIEND_AUTH", 0x000D: "QQ_CMD_CHANGE_STATUS", 0x0012: "QQ_CMD_ACK_SYS_MSG", 0x0016: "QQ_CMD_SEND_IM", 0x0017: "QQ_CMD_RECV_IM", 0x001C: "QQ_CMD_REMOVE_SELF", 0x001D: "QQ_CMD_REQUEST_KEY", 0x0022: "QQ_CMD_LOGIN", 0x0026: "QQ_CMD_GET_FRIEND_LIST", 0x0027: "QQ_CMD_GET_ONLINE_OP", 0x002D: "QQ_CMD_SEND_SMS", 0x0030: "QQ_CMD_CLUSTER_CMD", 0x0031: "QQ_CMD_TEST", 0x003C: "QQ_CMD_GROUP_DATA_OP", 0x003D: "QQ_CMD_UPLOAD_GROUP_FRIEND", 0x003E: "QQ_CMD_FRIEND_DATA_OP", 0x0058: "QQ_CMD_DOWNLOAD_GROUP_FRIEND", 0x005C: "QQ_CMD_FRIEND_LEVEL_OP", 0x005E: "QQ_CMD_PRIVACY_DATA_OP", 0x005F: "QQ_CMD_CLUSTER_DATA_OP", 0x0061: "QQ_CMD_ADVANCED_SEARCH", 0x0062: "QQ_CMD_REQUEST_LOGIN_TOKEN", 0x0065: "QQ_CMD_USER_PROPERTY_OP", 0x0066: "QQ_CMD_TEMP_SESSION_OP", 0x0067: "QQ_CMD_SIGNATURE_OP", 0x0080: "QQ_CMD_RECV_MSG_SYS", 0x0081: "QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS", 0x00A6: "QQ_CMD_WEATHER_OP", 0x00A7: "QQ_CMD_ADD_FRIEND_EX", 0x00A8: "QQ_CMD_AUTHORIZE", 0xFFFF: "QQ_CMD_UNKNOWN", 0x0021: "_CMD_REQUEST_AGENT", 0x0022: "_CMD_REQUEST_FACE", 0x0023: "_CMD_TRANSFER", 0x0026: "_CMD_REQUEST_BEGIN", } class QQBasicPacket(Packet): __hdr__ = ( ('header_type', 'B', 2), ('source', 'H', 0), ('command', 'H', 0), ('sequence', 'H', 0), ('qqNum', 'L', 0), ) class QQ3Packet(Packet): __hdr__ = ( ('header_type', 'B', 3), ('command', 'B', 0), ('sequence', 'H', 0), ('unknown1', 'L', 0), ('unknown2', 'L', 0), ('unknown3', 'L', 0), ('unknown4', 'L', 0), ('unknown5', 'L', 0), ('unknown6', 'L', 0), ('unknown7', 'L', 0), ('unknown8', 'L', 0), ('unknown9', 'L', 0), ('unknown10', 'B', 1), ('unknown11', 'B', 0), ('unknown12', 'B', 0), ('source', 'H', 0), ('unknown13', 'B', 0), ) class QQ5Packet(Packet): __hdr__ = ( ('header_type', 'B', 5), ('source', 'H', 0), ('unknown', 'H', 0), ('command', 'H', 0), ('sequence', 'H', 0), ('qqNum', 'L', 0), ) dpkt-1.9.2/dpkt/radiotap.py000066400000000000000000000245631340335175100156200ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Radiotap""" from __future__ import print_function from __future__ import absolute_import import socket from . import dpkt from . import ieee80211 from .decorators import deprecated # Ref: http://www.radiotap.org # Fields Ref: http://www.radiotap.org/defined-fields/all # Present flags _TSFT_MASK = 0x1000000 _FLAGS_MASK = 0x2000000 _RATE_MASK = 0x4000000 _CHANNEL_MASK = 0x8000000 _FHSS_MASK = 0x10000000 _ANT_SIG_MASK = 0x20000000 _ANT_NOISE_MASK = 0x40000000 _LOCK_QUAL_MASK = 0x80000000 _TX_ATTN_MASK = 0x10000 _DB_TX_ATTN_MASK = 0x20000 _DBM_TX_POWER_MASK = 0x40000 _ANTENNA_MASK = 0x80000 _DB_ANT_SIG_MASK = 0x100000 _DB_ANT_NOISE_MASK = 0x200000 _RX_FLAGS_MASK = 0x400000 _CHANNELPLUS_MASK = 0x200 _EXT_MASK = 0x1 _TSFT_SHIFT = 24 _FLAGS_SHIFT = 25 _RATE_SHIFT = 26 _CHANNEL_SHIFT = 27 _FHSS_SHIFT = 28 _ANT_SIG_SHIFT = 29 _ANT_NOISE_SHIFT = 30 _LOCK_QUAL_SHIFT = 31 _TX_ATTN_SHIFT = 16 _DB_TX_ATTN_SHIFT = 17 _DBM_TX_POWER_SHIFT = 18 _ANTENNA_SHIFT = 19 _DB_ANT_SIG_SHIFT = 20 _DB_ANT_NOISE_SHIFT = 21 _RX_FLAGS_SHIFT = 22 _CHANNELPLUS_SHIFT = 10 _EXT_SHIFT = 0 # Flags elements _FLAGS_SIZE = 2 _CFP_FLAG_SHIFT = 0 _PREAMBLE_SHIFT = 1 _WEP_SHIFT = 2 _FRAG_SHIFT = 3 _FCS_SHIFT = 4 _DATA_PAD_SHIFT = 5 _BAD_FCS_SHIFT = 6 _SHORT_GI_SHIFT = 7 # Channel type _CHAN_TYPE_SIZE = 4 _CHANNEL_TYPE_SHIFT = 4 _CCK_SHIFT = 5 _OFDM_SHIFT = 6 _TWO_GHZ_SHIFT = 7 _FIVE_GHZ_SHIFT = 8 _PASSIVE_SHIFT = 9 _DYN_CCK_OFDM_SHIFT = 10 _GFSK_SHIFT = 11 _GSM_SHIFT = 12 _STATIC_TURBO_SHIFT = 13 _HALF_RATE_SHIFT = 14 _QUARTER_RATE_SHIFT = 15 # Flags offsets and masks _FCS_SHIFT = 4 _FCS_MASK = 0x10 class Radiotap(dpkt.Packet): """Radiotap. TODO: Longer class information.... Attributes: __hdr__: Header fields of Radiotap. TODO. """ __hdr__ = ( ('version', 'B', 0), ('pad', 'B', 0), ('length', 'H', 0), ('present_flags', 'I', 0) ) @property def tsft_present(self): return (self.present_flags & _TSFT_MASK) >> _TSFT_SHIFT @tsft_present.setter def tsft_present(self, val): self.present_flags |= val << _TSFT_SHIFT @property def flags_present(self): return (self.present_flags & _FLAGS_MASK) >> _FLAGS_SHIFT @flags_present.setter def flags_present(self, val): self.present_flags |= val << _FLAGS_SHIFT @property def rate_present(self): return (self.present_flags & _RATE_MASK) >> _RATE_SHIFT @rate_present.setter def rate_present(self, val): self.present_flags |= val << _RATE_SHIFT @property def channel_present(self): return (self.present_flags & _CHANNEL_MASK) >> _CHANNEL_SHIFT @channel_present.setter def channel_present(self, val): self.present_flags |= val << _CHANNEL_SHIFT @property def fhss_present(self): return (self.present_flags & _FHSS_MASK) >> _FHSS_SHIFT @fhss_present.setter def fhss_present(self, val): self.present_flags |= val << _FHSS_SHIFT @property def ant_sig_present(self): return (self.present_flags & _ANT_SIG_MASK) >> _ANT_SIG_SHIFT @ant_sig_present.setter def ant_sig_present(self, val): self.present_flags |= val << _ANT_SIG_SHIFT @property def ant_noise_present(self): return (self.present_flags & _ANT_NOISE_MASK) >> _ANT_NOISE_SHIFT @ant_noise_present.setter def ant_noise_present(self, val): self.present_flags |= val << _ANT_NOISE_SHIFT @property def lock_qual_present(self): return (self.present_flags & _LOCK_QUAL_MASK) >> _LOCK_QUAL_SHIFT @lock_qual_present.setter def lock_qual_present(self, val): self.present_flags |= val << _LOCK_QUAL_SHIFT @property def tx_attn_present(self): return (self.present_flags & _TX_ATTN_MASK) >> _TX_ATTN_SHIFT @tx_attn_present.setter def tx_attn_present(self, val): self.present_flags |= val << _TX_ATTN_SHIFT @property def db_tx_attn_present(self): return (self.present_flags & _DB_TX_ATTN_MASK) >> _DB_TX_ATTN_SHIFT @db_tx_attn_present.setter def db_tx_attn_present(self, val): self.present_flags |= val << _DB_TX_ATTN_SHIFT @property def dbm_tx_power_present(self): return (self.present_flags & _DBM_TX_POWER_MASK) >> _DBM_TX_POWER_SHIFT @dbm_tx_power_present.setter def dbm_tx_power_present(self, val): self.present_flags |= val << _DBM_TX_POWER_SHIFT @property def ant_present(self): return (self.present_flags & _ANTENNA_MASK) >> _ANTENNA_SHIFT @ant_present.setter def ant_present(self, val): self.present_flags |= val << _ANTENNA_SHIFT @property def db_ant_sig_present(self): return (self.present_flags & _DB_ANT_SIG_MASK) >> _DB_ANT_SIG_SHIFT @db_ant_sig_present.setter def db_ant_sig_present(self, val): self.present_flags |= val << _DB_ANT_SIG_SHIFT @property def db_ant_noise_present(self): return (self.present_flags & _DB_ANT_NOISE_MASK) >> _DB_ANT_NOISE_SHIFT @db_ant_noise_present.setter def db_ant_noise_present(self, val): self.present_flags |= val << _DB_ANT_NOISE_SHIFT @property def rx_flags_present(self): return (self.present_flags & _RX_FLAGS_MASK) >> _RX_FLAGS_SHIFT @rx_flags_present.setter def rx_flags_present(self, val): self.present_flags |= val << _RX_FLAGS_SHIFT @property def chanplus_present(self): return (self.present_flags & _CHANNELPLUS_MASK) >> _CHANNELPLUS_SHIFT @chanplus_present.setter def chanplus_present(self, val): self.present_flags |= val << _CHANNELPLUS_SHIFT @property def ext_present(self): return (self.present_flags & _EXT_MASK) >> _EXT_SHIFT @ext_present.setter def ext_present(self, val): self.present_flags |= val << _EXT_SHIFT def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.data = buf[socket.ntohs(self.length):] self.fields = [] buf = buf[self.__hdr_len__:] # decode each field into self. (eg. self.tsft) as well as append it self.fields list field_decoder = [ ('tsft', self.tsft_present, self.TSFT), ('flags', self.flags_present, self.Flags), ('rate', self.rate_present, self.Rate), ('channel', self.channel_present, self.Channel), ('fhss', self.fhss_present, self.FHSS), ('ant_sig', self.ant_sig_present, self.AntennaSignal), ('ant_noise', self.ant_noise_present, self.AntennaNoise), ('lock_qual', self.lock_qual_present, self.LockQuality), ('tx_attn', self.tx_attn_present, self.TxAttenuation), ('db_tx_attn', self.db_tx_attn_present, self.DbTxAttenuation), ('dbm_tx_power', self.dbm_tx_power_present, self.DbmTxPower), ('ant', self.ant_present, self.Antenna), ('db_ant_sig', self.db_ant_sig_present, self.DbAntennaSignal), ('db_ant_noise', self.db_ant_noise_present, self.DbAntennaNoise), ('rx_flags', self.rx_flags_present, self.RxFlags) ] for name, present_bit, parser in field_decoder: if present_bit: field = parser(buf) field.data = b'' setattr(self, name, field) self.fields.append(field) buf = buf[len(field):] if len(self.data) > 0: if self.flags_present and self.flags.fcs: self.data = ieee80211.IEEE80211(self.data, fcs=self.flags.fcs) else: self.data = ieee80211.IEEE80211(self.data) class Antenna(dpkt.Packet): __hdr__ = ( ('index', 'B', 0), ) class AntennaNoise(dpkt.Packet): __hdr__ = ( ('db', 'B', 0), ) class AntennaSignal(dpkt.Packet): __hdr__ = ( ('db', 'B', 0), ) class Channel(dpkt.Packet): __hdr__ = ( ('freq', 'H', 0), ('flags', 'H', 0), ) class FHSS(dpkt.Packet): __hdr__ = ( ('set', 'B', 0), ('pattern', 'B', 0), ) class Flags(dpkt.Packet): __hdr__ = ( ('val', 'B', 0), ) @property def fcs(self): return (self.val & _FCS_MASK) >> _FCS_SHIFT # TODO statement seems to have no effect @fcs.setter def fcs(self, v): (v << _FCS_SHIFT) | (self.val & ~_FCS_MASK) class LockQuality(dpkt.Packet): __hdr__ = ( ('val', 'H', 0), ) class RxFlags(dpkt.Packet): __hdr__ = ( ('val', 'H', 0), ) class Rate(dpkt.Packet): __hdr__ = ( ('val', 'B', 0), ) class TSFT(dpkt.Packet): __hdr__ = ( ('usecs', 'Q', 0), ) class TxAttenuation(dpkt.Packet): __hdr__ = ( ('val', 'H', 0), ) class DbTxAttenuation(dpkt.Packet): __hdr__ = ( ('db', 'H', 0), ) class DbAntennaNoise(dpkt.Packet): __hdr__ = ( ('db', 'B', 0), ) class DbAntennaSignal(dpkt.Packet): __hdr__ = ( ('db', 'B', 0), ) class DbmTxPower(dpkt.Packet): __hdr__ = ( ('dbm', 'B', 0), ) def test_Radiotap(): s = b'\x00\x00\x00\x18\x6e\x48\x00\x00\x00\x02\x6c\x09\xa0\x00\xa8\x81\x02\x00\x00\x00\x00\x00\x00\x00' rad = Radiotap(s) assert(rad.version == 0) assert(rad.present_flags == 0x6e480000) assert(rad.tsft_present == 0) assert(rad.flags_present == 1) assert(rad.rate_present == 1) assert(rad.channel_present == 1) assert(rad.fhss_present == 0) assert(rad.ant_sig_present == 1) assert(rad.ant_noise_present == 1) assert(rad.lock_qual_present == 0) assert(rad.db_tx_attn_present == 0) assert(rad.dbm_tx_power_present == 0) assert(rad.ant_present == 1) assert(rad.db_ant_sig_present == 0) assert(rad.db_ant_noise_present == 0) assert(rad.rx_flags_present == 1) assert(rad.channel.freq == 0x6c09) assert(rad.channel.flags == 0xa000) assert(len(rad.fields) == 7) def test_fcs(): s = b'\x00\x00\x1a\x00\x2f\x48\x00\x00\x34\x8f\x71\x09\x00\x00\x00\x00\x10\x0c\x85\x09\xc0\x00\xcc\x01\x00\x00' rt = Radiotap(s) assert(rt.flags_present == 1) assert(rt.flags.fcs == 1) if __name__ == '__main__': test_Radiotap() test_fcs() print('Tests Successful...') dpkt-1.9.2/dpkt/radius.py000066400000000000000000000045431340335175100153000ustar00rootroot00000000000000# $Id: radius.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Remote Authentication Dial-In User Service.""" from __future__ import absolute_import from . import dpkt from .compat import compat_ord # http://www.untruth.org/~josh/security/radius/radius-auth.html # RFC 2865 class RADIUS(dpkt.Packet): """Remote Authentication Dial-In User Service. TODO: Longer class information.... Attributes: __hdr__: Header fields of RADIUS. TODO. """ __hdr__ = ( ('code', 'B', 0), ('id', 'B', 0), ('len', 'H', 4), ('auth', '16s', b'') ) attrs = b'' def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.attrs = parse_attrs(self.data) self.data = b'' def parse_attrs(buf): """Parse attributes buffer into a list of (type, data) tuples.""" attrs = [] while buf: t = compat_ord(buf[0]) l = compat_ord(buf[1]) if l < 2: break d, buf = buf[2:l], buf[l:] attrs.append((t, d)) return attrs # Codes RADIUS_ACCESS_REQUEST = 1 RADIUS_ACCESS_ACCEPT = 2 RADIUS_ACCESS_REJECT = 3 RADIUS_ACCT_REQUEST = 4 RADIUS_ACCT_RESPONSE = 5 RADIUS_ACCT_STATUS = 6 RADIUS_ACCESS_CHALLENGE = 11 # Attributes RADIUS_USER_NAME = 1 RADIUS_USER_PASSWORD = 2 RADIUS_CHAP_PASSWORD = 3 RADIUS_NAS_IP_ADDR = 4 RADIUS_NAS_PORT = 5 RADIUS_SERVICE_TYPE = 6 RADIUS_FRAMED_PROTOCOL = 7 RADIUS_FRAMED_IP_ADDR = 8 RADIUS_FRAMED_IP_NETMASK = 9 RADIUS_FRAMED_ROUTING = 10 RADIUS_FILTER_ID = 11 RADIUS_FRAMED_MTU = 12 RADIUS_FRAMED_COMPRESSION = 13 RADIUS_LOGIN_IP_HOST = 14 RADIUS_LOGIN_SERVICE = 15 RADIUS_LOGIN_TCP_PORT = 16 # unassigned RADIUS_REPLY_MESSAGE = 18 RADIUS_CALLBACK_NUMBER = 19 RADIUS_CALLBACK_ID = 20 # unassigned RADIUS_FRAMED_ROUTE = 22 RADIUS_FRAMED_IPX_NETWORK = 23 RADIUS_STATE = 24 RADIUS_CLASS = 25 RADIUS_VENDOR_SPECIFIC = 26 RADIUS_SESSION_TIMEOUT = 27 RADIUS_IDLE_TIMEOUT = 28 RADIUS_TERMINATION_ACTION = 29 RADIUS_CALLED_STATION_ID = 30 RADIUS_CALLING_STATION_ID = 31 RADIUS_NAS_ID = 32 RADIUS_PROXY_STATE = 33 RADIUS_LOGIN_LAT_SERVICE = 34 RADIUS_LOGIN_LAT_NODE = 35 RADIUS_LOGIN_LAT_GROUP = 36 RADIUS_FRAMED_ATALK_LINK = 37 RADIUS_FRAMED_ATALK_NETWORK = 38 RADIUS_FRAMED_ATALK_ZONE = 39 # 40-59 reserved for accounting RADIUS_CHAP_CHALLENGE = 60 RADIUS_NAS_PORT_TYPE = 61 RADIUS_PORT_LIMIT = 62 RADIUS_LOGIN_LAT_PORT = 63 dpkt-1.9.2/dpkt/rfb.py000066400000000000000000000036041340335175100145570ustar00rootroot00000000000000# $Id: rfb.py 47 2008-05-27 02:10:00Z jon.oberheide $ # -*- coding: utf-8 -*- """Remote Framebuffer Protocol.""" from __future__ import absolute_import from . import dpkt # Remote Framebuffer Protocol # http://www.realvnc.com/docs/rfbproto.pdf # Client to Server Messages CLIENT_SET_PIXEL_FORMAT = 0 CLIENT_SET_ENCODINGS = 2 CLIENT_FRAMEBUFFER_UPDATE_REQUEST = 3 CLIENT_KEY_EVENT = 4 CLIENT_POINTER_EVENT = 5 CLIENT_CUT_TEXT = 6 # Server to Client Messages SERVER_FRAMEBUFFER_UPDATE = 0 SERVER_SET_COLOUR_MAP_ENTRIES = 1 SERVER_BELL = 2 SERVER_CUT_TEXT = 3 class RFB(dpkt.Packet): """Remote Framebuffer Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of RADIUS. TODO. """ __hdr__ = ( ('type', 'B', 0), ) class SetPixelFormat(dpkt.Packet): __hdr__ = ( ('pad', '3s', ''), ('pixel_fmt', '16s', '') ) class SetEncodings(dpkt.Packet): __hdr__ = ( ('pad', '1s', ''), ('num_encodings', 'H', 0) ) class FramebufferUpdateRequest(dpkt.Packet): __hdr__ = ( ('incremental', 'B', 0), ('x_position', 'H', 0), ('y_position', 'H', 0), ('width', 'H', 0), ('height', 'H', 0) ) class KeyEvent(dpkt.Packet): __hdr__ = ( ('down_flag', 'B', 0), ('pad', '2s', ''), ('key', 'I', 0) ) class PointerEvent(dpkt.Packet): __hdr__ = ( ('button_mask', 'B', 0), ('x_position', 'H', 0), ('y_position', 'H', 0) ) class FramebufferUpdate(dpkt.Packet): __hdr__ = ( ('pad', '1s', ''), ('num_rects', 'H', 0) ) class SetColourMapEntries(dpkt.Packet): __hdr__ = ( ('pad', '1s', ''), ('first_colour', 'H', 0), ('num_colours', 'H', 0) ) class CutText(dpkt.Packet): __hdr__ = ( ('pad', '3s', ''), ('length', 'I', 0) ) dpkt-1.9.2/dpkt/rip.py000066400000000000000000000042401340335175100145750ustar00rootroot00000000000000# $Id: rip.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Routing Information Protocol.""" from __future__ import print_function from __future__ import absolute_import from . import dpkt # RIP v2 - RFC 2453 # http://tools.ietf.org/html/rfc2453 REQUEST = 1 RESPONSE = 2 class RIP(dpkt.Packet): """Routing Information Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of RIP. TODO. """ __hdr__ = ( ('cmd', 'B', REQUEST), ('v', 'B', 2), ('rsvd', 'H', 0) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) l = [] self.auth = None while self.data: rte = RTE(self.data[:20]) if rte.family == 0xFFFF: self.auth = Auth(self.data[:20]) else: l.append(rte) self.data = self.data[20:] self.data = self.rtes = l def __len__(self): n = self.__hdr_len__ if self.auth: n += len(self.auth) n += sum(map(len, self.rtes)) return n def __bytes__(self): auth = b'' if self.auth: auth = bytes(self.auth) return self.pack_hdr() + auth + b''.join(map(bytes, self.rtes)) class RTE(dpkt.Packet): __hdr__ = ( ('family', 'H', 2), ('route_tag', 'H', 0), ('addr', 'I', 0), ('subnet', 'I', 0), ('next_hop', 'I', 0), ('metric', 'I', 1) ) class Auth(dpkt.Packet): __hdr__ = ( ('rsvd', 'H', 0xFFFF), ('type', 'H', 2), ('auth', '16s', 0) ) __s = b'\x02\x02\x00\x00\x00\x02\x00\x00\x01\x02\x03\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\xc0\xa8\x01\x08\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x01' def test_rtp_pack(): r = RIP(__s) assert (__s == bytes(r)) def test_rtp_unpack(): r = RIP(__s) assert (r.auth is None) assert (len(r.rtes) == 2) rte = r.rtes[1] assert (rte.family == 2) assert (rte.route_tag == 0) assert (rte.metric == 1) if __name__ == '__main__': test_rtp_pack() test_rtp_unpack() print('Tests Successful...') dpkt-1.9.2/dpkt/rpc.py000066400000000000000000000117321340335175100145730ustar00rootroot00000000000000# $Id: rpc.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Remote Procedure Call.""" from __future__ import absolute_import import struct from . import dpkt # RPC.dir CALL = 0 REPLY = 1 # RPC.Auth.flavor AUTH_NONE = AUTH_NULL = 0 AUTH_UNIX = 1 AUTH_SHORT = 2 AUTH_DES = 3 # RPC.Reply.stat MSG_ACCEPTED = 0 MSG_DENIED = 1 # RPC.Reply.Accept.stat SUCCESS = 0 PROG_UNAVAIL = 1 PROG_MISMATCH = 2 PROC_UNAVAIL = 3 GARBAGE_ARGS = 4 SYSTEM_ERR = 5 # RPC.Reply.Reject.stat RPC_MISMATCH = 0 AUTH_ERROR = 1 class RPC(dpkt.Packet): """Remote Procedure Call. TODO: Longer class information.... Attributes: __hdr__: Header fields of RPC. TODO. """ __hdr__ = ( ('xid', 'I', 0), ('dir', 'I', CALL) ) class Auth(dpkt.Packet): __hdr__ = (('flavor', 'I', AUTH_NONE), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) n = struct.unpack('>I', self.data[:4])[0] self.data = self.data[4:4 + n] def __len__(self): return 8 + len(self.data) def __bytes__(self): return self.pack_hdr() + struct.pack('>I', len(self.data)) + \ bytes(self.data) class Call(dpkt.Packet): __hdr__ = ( ('rpcvers', 'I', 2), ('prog', 'I', 0), ('vers', 'I', 0), ('proc', 'I', 0) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.cred = RPC.Auth(self.data) self.verf = RPC.Auth(self.data[len(self.cred):]) self.data = self.data[len(self.cred) + len(self.verf):] def __len__(self): return len(str(self)) # XXX def __bytes__(self): return dpkt.Packet.__bytes__(self) + \ bytes(getattr(self, 'cred', RPC.Auth())) + \ bytes(getattr(self, 'verf', RPC.Auth())) + \ bytes(self.data) class Reply(dpkt.Packet): __hdr__ = (('stat', 'I', MSG_ACCEPTED), ) class Accept(dpkt.Packet): __hdr__ = (('stat', 'I', SUCCESS), ) def unpack(self, buf): self.verf = RPC.Auth(buf) buf = buf[len(self.verf):] self.stat = struct.unpack('>I', buf[:4])[0] if self.stat == SUCCESS: self.data = buf[4:] elif self.stat == PROG_MISMATCH: self.low, self.high = struct.unpack('>II', buf[4:12]) self.data = buf[12:] def __len__(self): if self.stat == PROG_MISMATCH: n = 8 else: n = 0 return len(self.verf) + 4 + n + len(self.data) def __bytes__(self): if self.stat == PROG_MISMATCH: return bytes(self.verf) + struct.pack('>III', self.stat, self.low, self.high) + self.data return bytes(self.verf) + dpkt.Packet.__bytes__(self) class Reject(dpkt.Packet): __hdr__ = (('stat', 'I', AUTH_ERROR), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.stat == RPC_MISMATCH: self.low, self.high = struct.unpack('>II', self.data[:8]) self.data = self.data[8:] elif self.stat == AUTH_ERROR: self.why = struct.unpack('>I', self.data[:4])[0] self.data = self.data[4:] def __len__(self): if self.stat == RPC_MISMATCH: n = 8 elif self.stat == AUTH_ERROR: n = 4 else: n = 0 return 4 + n + len(self.data) def __bytes__(self): if self.stat == RPC_MISMATCH: return struct.pack('>III', self.stat, self.low, self.high) + self.data elif self.stat == AUTH_ERROR: return struct.pack('>II', self.stat, self.why) + self.data return dpkt.Packet.__bytes__(self) def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.stat == MSG_ACCEPTED: self.data = self.accept = self.Accept(self.data) elif self.status == MSG_DENIED: self.data = self.reject = self.Reject(self.data) def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.dir == CALL: self.data = self.call = self.Call(self.data) elif self.dir == REPLY: self.data = self.reply = self.Reply(self.data) def unpack_xdrlist(cls, buf): l = [] while buf: if buf.startswith(b'\x00\x00\x00\x01'): p = cls(buf[4:]) l.append(p) buf = p.data elif buf.startswith(b'\x00\x00\x00\x00'): break else: raise dpkt.UnpackError('invalid XDR list') return l def pack_xdrlist(*args): return b'\x00\x00\x00\x01'.join(map(bytes, args)) + b'\x00\x00\x00\x00' dpkt-1.9.2/dpkt/rtp.py000066400000000000000000000105351340335175100146140ustar00rootroot00000000000000# $Id: rtp.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Real-Time Transport Protocol.""" from __future__ import absolute_import from .dpkt import Packet from .decorators import deprecated # version 1100 0000 0000 0000 ! 0xC000 14 # p 0010 0000 0000 0000 ! 0x2000 13 # x 0001 0000 0000 0000 ! 0x1000 12 # cc 0000 1111 0000 0000 ! 0x0F00 8 # m 0000 0000 1000 0000 ! 0x0080 7 # pt 0000 0000 0111 1111 ! 0x007F 0 # _VERSION_MASK = 0xC000 _P_MASK = 0x2000 _X_MASK = 0x1000 _CC_MASK = 0x0F00 _M_MASK = 0x0080 _PT_MASK = 0x007F _VERSION_SHIFT = 14 _P_SHIFT = 13 _X_SHIFT = 12 _CC_SHIFT = 8 _M_SHIFT = 7 _PT_SHIFT = 0 VERSION = 2 class RTP(Packet): """Real-Time Transport Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of RTP. TODO. """ __hdr__ = ( ('_type', 'H', 0x8000), ('seq', 'H', 0), ('ts', 'I', 0), ('ssrc', 'I', 0), ) csrc = b'' @property def version(self): return (self._type & _VERSION_MASK) >> _VERSION_SHIFT @version.setter def version(self, ver): self._type = (ver << _VERSION_SHIFT) | (self._type & ~_VERSION_MASK) @property def p(self): return (self._type & _P_MASK) >> _P_SHIFT @p.setter def p(self, p): self._type = (p << _P_SHIFT) | (self._type & ~_P_MASK) @property def x(self): return (self._type & _X_MASK) >> _X_SHIFT @x.setter def x(self, x): self._type = (x << _X_SHIFT) | (self._type & ~_X_MASK) @property def cc(self): return (self._type & _CC_MASK) >> _CC_SHIFT @cc.setter def cc(self, cc): self._type = (cc << _CC_SHIFT) | (self._type & ~_CC_MASK) @property def m(self): return (self._type & _M_MASK) >> _M_SHIFT @m.setter def m(self, m): self._type = (m << _M_SHIFT) | (self._type & ~_M_MASK) @property def pt(self): return (self._type & _PT_MASK) >> _PT_SHIFT @pt.setter def pt(self, m): self._type = (m << _PT_SHIFT) | (self._type & ~_PT_MASK) def __len__(self): return self.__hdr_len__ + len(self.csrc) + len(self.data) def __bytes__(self): return self.pack_hdr() + self.csrc + bytes(self.data) def unpack(self, buf): super(RTP, self).unpack(buf) self.csrc = buf[self.__hdr_len__:self.__hdr_len__ + self.cc * 4] self.data = buf[self.__hdr_len__ + self.cc * 4:] def test_rtp(): rtp = RTP(b"\x80\x08\x4d\x01\x00\x01\x00\xe0\x34\x3f\xfa\x34\x53\x53\x53\x56\x53\x5d\x56\x57\xd5\xd6\xd1\xde\xdf\xd3\xd9\xda\xdf\xdc\xdf\xd8\xdd\xd4\xdd\xd9\xd1\xd6\xdc\xda\xde\xdd\xc7\xc1\xdf\xdf\xda\xdb\xdd\xdd\xc4\xd9\x55\x57\xd4\x50\x44\x44\x5b\x44\x4f\x4c\x47\x40\x4c\x47\x59\x5b\x58\x5d\x56\x56\x53\x56\xd5\xd5\x54\x55\xd6\xd6\xd4\xd1\xd1\xd0\xd1\xd5\xdd\xd6\x55\xd4\xd6\xd1\xd4\xd6\xd7\xd7\xd5\xd4\xd0\xd7\xd1\xd4\xd2\xdc\xd6\xdc\xdf\xdc\xdd\xd2\xde\xdc\xd0\xdd\xdc\xd0\xd6\xd6\xd6\x55\x54\x55\x57\x57\x56\x50\x50\x5c\x5c\x52\x5d\x5d\x5f\x5e\x5d\x5e\x52\x50\x52\x56\x54\x57\x55\x55\xd4\xd7\x55\xd5\x55\x55\x55\x55\x55\x54\x57\x54\x55\x55\xd5\xd5\xd7\xd6\xd7\xd1\xd1\xd3\xd2\xd3\xd2\xd2\xd3\xd3") assert (rtp.version == 2) assert (rtp.p == 0) assert (rtp.x == 0) assert (rtp.cc == 0) assert (rtp.m == 0) assert (rtp.pt == 8) assert (rtp.seq == 19713) assert (rtp.ts == 65760) assert (rtp.ssrc == 0x343ffa34) assert (len(rtp) == 172) assert (bytes(rtp) == b"\x80\x08\x4d\x01\x00\x01\x00\xe0\x34\x3f\xfa\x34\x53\x53\x53\x56\x53\x5d\x56\x57\xd5\xd6\xd1\xde\xdf\xd3\xd9\xda\xdf\xdc\xdf\xd8\xdd\xd4\xdd\xd9\xd1\xd6\xdc\xda\xde\xdd\xc7\xc1\xdf\xdf\xda\xdb\xdd\xdd\xc4\xd9\x55\x57\xd4\x50\x44\x44\x5b\x44\x4f\x4c\x47\x40\x4c\x47\x59\x5b\x58\x5d\x56\x56\x53\x56\xd5\xd5\x54\x55\xd6\xd6\xd4\xd1\xd1\xd0\xd1\xd5\xdd\xd6\x55\xd4\xd6\xd1\xd4\xd6\xd7\xd7\xd5\xd4\xd0\xd7\xd1\xd4\xd2\xdc\xd6\xdc\xdf\xdc\xdd\xd2\xde\xdc\xd0\xdd\xdc\xd0\xd6\xd6\xd6\x55\x54\x55\x57\x57\x56\x50\x50\x5c\x5c\x52\x5d\x5d\x5f\x5e\x5d\x5e\x52\x50\x52\x56\x54\x57\x55\x55\xd4\xd7\x55\xd5\x55\x55\x55\x55\x55\x54\x57\x54\x55\x55\xd5\xd5\xd7\xd6\xd7\xd1\xd1\xd3\xd2\xd3\xd2\xd2\xd3\xd3") # the following tests RTP header setters rtp = RTP() rtp.m = 1 rtp.pt = 3 rtp.seq = 1234 rtp.ts = 5678 rtp.ssrc = 0xabcdef01 assert (rtp.m == 1) assert (rtp.pt == 3) assert (rtp.seq == 1234) assert (rtp.ts == 5678) assert (rtp.ssrc == 0xabcdef01) dpkt-1.9.2/dpkt/rx.py000066400000000000000000000017261340335175100144420ustar00rootroot00000000000000# $Id: rx.py 23 2006-11-08 15:45:33Z jonojono $ # -*- coding: utf-8 -*- """Rx Protocol.""" from __future__ import absolute_import from . import dpkt # Types DATA = 0x01 ACK = 0x02 BUSY = 0x03 ABORT = 0x04 ACKALL = 0x05 CHALLENGE = 0x06 RESPONSE = 0x07 DEBUG = 0x08 # Flags CLIENT_INITIATED = 0x01 REQUEST_ACK = 0x02 LAST_PACKET = 0x04 MORE_PACKETS = 0x08 SLOW_START_OK = 0x20 JUMBO_PACKET = 0x20 # Security SEC_NONE = 0x00 SEC_BCRYPT = 0x01 SEC_RXKAD = 0x02 SEC_RXKAD_ENC = 0x03 class Rx(dpkt.Packet): """Rx Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of Rx. TODO. """ __hdr__ = ( ('epoch', 'I', 0), ('cid', 'I', 0), ('call', 'I', 1), ('seq', 'I', 0), ('serial', 'I', 1), ('type', 'B', 0), ('flags', 'B', CLIENT_INITIATED), ('status', 'B', 0), ('security', 'B', 0), ('sum', 'H', 0), ('service', 'H', 0) ) dpkt-1.9.2/dpkt/sccp.py000066400000000000000000000126721340335175100147430ustar00rootroot00000000000000# $Id: sccp.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Cisco Skinny Client Control Protocol.""" from __future__ import absolute_import from . import dpkt KEYPAD_BUTTON = 0x00000003 OFF_HOOK = 0x00000006 ON_HOOK = 0x00000007 OPEN_RECEIVE_CHANNEL_ACK = 0x00000022 START_TONE = 0x00000082 STOP_TONE = 0x00000083 SET_LAMP = 0x00000086 SET_SPEAKER_MODE = 0x00000088 START_MEDIA_TRANSMIT = 0x0000008A STOP_MEDIA_TRANSMIT = 0x0000008B CALL_INFO = 0x0000008F DEFINE_TIME_DATE = 0x00000094 DISPLAY_TEXT = 0x00000099 OPEN_RECEIVE_CHANNEL = 0x00000105 CLOSE_RECEIVE_CHANNEL = 0x00000106 SELECT_SOFTKEYS = 0x00000110 CALL_STATE = 0x00000111 DISPLAY_PROMPT_STATUS = 0x00000112 CLEAR_PROMPT_STATUS = 0x00000113 ACTIVATE_CALL_PLANE = 0x00000116 class ActivateCallPlane(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('line_instance', 'I', 0), ) class CallInfo(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('calling_party_name', '40s', ''), ('calling_party', '24s', ''), ('called_party_name', '40s', ''), ('called_party', '24s', ''), ('line_instance', 'I', 0), ('call_id', 'I', 0), ('call_type', 'I', 0), ('orig_called_party_name', '40s', ''), ('orig_called_party', '24s', '') ) class CallState(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('call_state', 'I', 12), # 12: Proceed, 15: Connected ('line_instance', 'I', 1), ('call_id', 'I', 0) ) class ClearPromptStatus(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('line_instance', 'I', 1), ('call_id', 'I', 0) ) class CloseReceiveChannel(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('conference_id', 'I', 0), ('passthruparty_id', 'I', 0), ) class DisplayPromptStatus(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('msg_timeout', 'I', 0), ('display_msg', '32s', ''), ('line_instance', 'I', 1), ('call_id', 'I', 0) ) class DisplayText(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('display_msg', '36s', ''), ) class KeypadButton(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('button', 'I', 0), ) class OpenReceiveChannel(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('conference_id', 'I', 0), ('passthruparty_id', 'I', 0), ('ms_packet', 'I', 0), ('payload_capability', 'I', 4), # 4: G.711 u-law 64k ('echo_cancel_type', 'I', 4), ('g723_bitrate', 'I', 0), ) class OpenReceiveChannelAck(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('channel_status', 'I', 0), ('ip', '4s', ''), ('port', 'I', 0), ('passthruparty_id', 'I', 0), ) class SelectStartKeys(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('line_id', 'I', 1), ('call_id', 'I', 0), ('softkey_set', 'I', 8), ('softkey_map', 'I', 0xffffffff) ) class SetLamp(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('stimulus', 'I', 9), # 9: Line ('stimulus_instance', 'I', 1), ('lamp_mode', 'I', 1), ) class SetSpeakerMode(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('speaker', 'I', 2), # 2: SpeakerOff ) class StartMediaTransmission(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('conference_id', 'I', 0), ('passthruparty_id', 'I', 0), ('ipv4_or_ipv6', 'I', 0), ('remote_ip', '16s', ''), ('remote_port', 'I', 0), ('ms_packet', 'I', 0), ('payload_capability', 'I', 4), # 4: G.711 u-law 64k ('precedence', 'I', 0), ('silence_suppression', 'I', 0), ('max_frames_per_pkt', 'I', 1), ('g723_bitrate', 'I', 0), ('call_reference', 'I', 0) ) class StartTone(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('tone', 'I', 0x24), # 0x24: AlertingTone ) class StopMediaTransmission(dpkt.Packet): __byte_order__ = '<' __hdr__ = ( ('conference_id', 'I', 0), ('passthruparty_id', 'I', 0), ) class SCCP(dpkt.Packet): """Cisco Skinny Client Control Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of SCCP. TODO. """ __byte_order__ = '<' __hdr__ = ( ('len', 'I', 0), ('rsvd', 'I', 0), ('msgid', 'I', 0), ('msg', '0s', ''), ) _msgsw = { KEYPAD_BUTTON: KeypadButton, OPEN_RECEIVE_CHANNEL_ACK: OpenReceiveChannelAck, START_TONE: StartTone, SET_LAMP: SetLamp, START_MEDIA_TRANSMIT: StartMediaTransmission, STOP_MEDIA_TRANSMIT: StopMediaTransmission, CALL_INFO: CallInfo, DISPLAY_TEXT: DisplayText, OPEN_RECEIVE_CHANNEL: OpenReceiveChannel, CLOSE_RECEIVE_CHANNEL: CloseReceiveChannel, CALL_STATE: CallState, DISPLAY_PROMPT_STATUS: DisplayPromptStatus, CLEAR_PROMPT_STATUS: ClearPromptStatus, ACTIVATE_CALL_PLANE: ActivateCallPlane, } def unpack(self, buf): dpkt.Packet.unpack(self, buf) n = self.len - 4 if n > len(self.data): raise dpkt.NeedData('not enough data') self.msg, self.data = self.data[:n], self.data[n:] try: p = self._msgsw[self.msgid](self.msg) setattr(self, p.__class__.__name__.lower(), p) except (KeyError, dpkt.UnpackError): pass dpkt-1.9.2/dpkt/sctp.py000066400000000000000000000047331340335175100147630ustar00rootroot00000000000000# $Id: sctp.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Stream Control Transmission Protocol.""" from __future__ import print_function from __future__ import absolute_import from . import dpkt from . import crc32c # Stream Control Transmission Protocol # http://tools.ietf.org/html/rfc2960 # Chunk Types DATA = 0 INIT = 1 INIT_ACK = 2 SACK = 3 HEARTBEAT = 4 HEARTBEAT_ACK = 5 ABORT = 6 SHUTDOWN = 7 SHUTDOWN_ACK = 8 ERROR = 9 COOKIE_ECHO = 10 COOKIE_ACK = 11 ECNE = 12 CWR = 13 SHUTDOWN_COMPLETE = 14 class SCTP(dpkt.Packet): """Stream Control Transmission Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of SCTP. TODO. """ __hdr__ = ( ('sport', 'H', 0), ('dport', 'H', 0), ('vtag', 'I', 0), ('sum', 'I', 0) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) l = [] while self.data: chunk = Chunk(self.data) l.append(chunk) self.data = self.data[len(chunk):] self.data = self.chunks = l def __len__(self): return self.__hdr_len__ + sum(map(len, self.data)) def __bytes__(self): l = [bytes(x) for x in self.data] if self.sum == 0: s = crc32c.add(0xffffffff, self.pack_hdr()) for x in l: s = crc32c.add(s, x) self.sum = crc32c.done(s) return self.pack_hdr() + b''.join(l) class Chunk(dpkt.Packet): __hdr__ = ( ('type', 'B', INIT), ('flags', 'B', 0), ('len', 'H', 0) ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.data = self.data[:self.len - self.__hdr_len__] __s = b'\x80\x44\x00\x50\x00\x00\x00\x00\x30\xba\xef\x54\x01\x00\x00\x3c\x3b\xb9\x9c\x46\x00\x01\xa0\x00\x00\x0a\xff\xff\x2b\x2d\x7e\xb2\x00\x05\x00\x08\x9b\xe6\x18\x9b\x00\x05\x00\x08\x9b\xe6\x18\x9c\x00\x0c\x00\x06\x00\x05\x00\x00\x80\x00\x00\x04\xc0\x00\x00\x04\xc0\x06\x00\x08\x00\x00\x00\x00' def test_sctp_pack(): sctp = SCTP(__s) assert (__s == bytes(sctp)) sctp.sum = 0 assert (__s == bytes(sctp)) def test_sctp_unpack(): sctp = SCTP(__s) assert (sctp.sport == 32836) assert (sctp.dport == 80) assert (len(sctp.chunks) == 1) assert (len(sctp) == 72) chunk = sctp.chunks[0] assert (chunk.type == INIT) assert (chunk.len == 60) if __name__ == '__main__': test_sctp_pack() test_sctp_unpack() print('Tests Successful...') dpkt-1.9.2/dpkt/sip.py000066400000000000000000000022251340335175100145770ustar00rootroot00000000000000# $Id: sip.py 48 2008-05-27 17:31:15Z yardley $ # -*- coding: utf-8 -*- """Session Initiation Protocol.""" from __future__ import absolute_import from . import http class Request(http.Request): """SIP request. TODO: Longer class information.... Attributes: __hdr__: Header fields of SIP request. TODO. """ __hdr_defaults__ = { 'method': 'INVITE', 'uri': 'sip:user@example.com', 'version': '2.0', 'headers': {'To': '', 'From': '', 'Call-ID': '', 'CSeq': '', 'Contact': ''} } __methods = dict.fromkeys(( 'ACK', 'BYE', 'CANCEL', 'INFO', 'INVITE', 'MESSAGE', 'NOTIFY', 'OPTIONS', 'PRACK', 'PUBLISH', 'REFER', 'REGISTER', 'SUBSCRIBE', 'UPDATE' )) __proto = 'SIP' class Response(http.Response): """SIP response. TODO: Longer class information.... Attributes: __hdr__: Header fields of SIP response. TODO. """ __hdr_defaults__ = { 'version': '2.0', 'status': '200', 'reason': 'OK', 'headers': {'To': '', 'From': '', 'Call-ID': '', 'CSeq': '', 'Contact': ''} } __proto = 'SIP' dpkt-1.9.2/dpkt/sll.py000066400000000000000000000032441340335175100146000ustar00rootroot00000000000000# $Id: sll.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Linux libpcap "cooked" capture encapsulation.""" from __future__ import absolute_import from . import arp from . import dpkt from . import ethernet class SLL(dpkt.Packet): """Linux libpcap "cooked" capture encapsulation. TODO: Longer class information.... Attributes: __hdr__: Header fields of SLL. TODO. """ __hdr__ = ( ('type', 'H', 0), # 0: to us, 1: bcast, 2: mcast, 3: other, 4: from us ('hrd', 'H', arp.ARP_HRD_ETH), ('hlen', 'H', 6), # hardware address length ('hdr', '8s', ''), # first 8 bytes of link-layer header ('ethtype', 'H', ethernet.ETH_TYPE_IP), ) _typesw = ethernet.Ethernet._typesw def unpack(self, buf): dpkt.Packet.unpack(self, buf) try: self.data = self._typesw[self.ethtype](self.data) setattr(self, self.data.__class__.__name__.lower(), self.data) except (KeyError, dpkt.UnpackError): pass def test_sll(): slldata = b'\x00\x00\x00\x01\x00\x06\x00\x0b\xdb\x52\x0e\x08\xf6\x7f\x08\x00\x45\x00\x00\x34\xcc\x6c\x40\x00\x40\x06\x74\x08\x82\xd9\xfa\x8e\x82\xd9\xfa\x0d' slltest = SLL(slldata) assert slltest.type == 0 assert slltest.hrd == 1 assert slltest.hlen == 6 assert slltest.hdr == b'\x00\x0b\xdb\x52\x0e\x08\xf6\x7f' assert slltest.ethtype == 0x0800 # give invalid ethtype of 0x1234 to make sure error is caught slldata2 = b'\x00\x00\x00\x01\x00\x06\x00\x0b\xdb\x52\x0e\x08\xf6\x7f\x12\x34\x45\x00\x00\x34\xcc\x6c\x40\x00\x40\x06\x74\x08\x82\xd9\xfa\x8e\x82\xd9\xfa\x0d' slltest = SLL(slldata2) dpkt-1.9.2/dpkt/smb.py000066400000000000000000000053641340335175100145740ustar00rootroot00000000000000# $Id: smb.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Server Message Block.""" from __future__ import print_function from __future__ import absolute_import from . import dpkt # https://msdn.microsoft.com/en-us/library/ee441774.aspx SMB_FLAGS_LOCK_AND_READ_OK = 0x01 SMB_FLAGS_BUF_AVAIL = 0x02 SMB_FLAGS_CASE_INSENSITIVE = 0x08 SMB_FLAGS_CANONICALIZED_PATHS = 0x10 SMB_FLAGS_OPLOCK = 0x20 SMB_FLAGS_OPBATCH = 0x40 SMB_FLAGS_REPLY = 0x80 SMB_FLAGS2_LONG_NAMES = 0x0001 SMB_FLAGS2_EXTENDED_ATTRIBUTES = 0x0002 SMB_FLAGS2_SECURITY_SIGNATURES = 0x0004 SMB_FLAGS2_COMPRESSED = 0x0008 SMB_FLAGS2_SECURITY_SIGNATURES_REQUIRED = 0x0010 SMB_FLAGS2_IS_LONG_NAME = 0x0040 SMB_FLAGS2_REVERSE_PATH = 0x0400 SMB_FLAGS2_EXTENDED_SECURITY = 0x0800 SMB_FLAGS2_DFS = 0x1000 SMB_FLAGS2_PAGING_IO = 0x2000 SMB_FLAGS2_NT_STATUS = 0x4000 SMB_FLAGS2_UNICODE = 0x8000 SMB_STATUS_SUCCESS = 0x00000000 class SMB(dpkt.Packet): """Server Message Block. TODO: Longer class information.... Attributes: __hdr__ = [ ('proto', '4s', b'\xffSMB'), ('cmd', 'B', 0), ('status', 'I', SMB_STATUS_SUCCESS), ('flags', 'B', 0), ('flags2', 'H', 0), ('_pidhi', 'H', 0), ('security', '8s', b''), ('rsvd', 'H', 0), ('tid', 'H', 0), ('_pidlo', 'H', 0), ('uid', 'H', 0), ('mid', 'H', 0) ] """ __byte_order__ = '<' __hdr__ = [ ('proto', '4s', b'\xffSMB'), ('cmd', 'B', 0), ('status', 'I', SMB_STATUS_SUCCESS), ('flags', 'B', 0), ('flags2', 'H', 0), ('_pidhi', 'H', 0), ('security', '8s', b''), ('rsvd', 'H', 0), ('tid', 'H', 0), ('_pidlo', 'H', 0), ('uid', 'H', 0), ('mid', 'H', 0) ] @property def pid(self): return (self._pidhi << 16) | self._pidlo @pid.setter def pid(self, v): self._pidhi = v >> 16 self._pidlo = v & 0xffff def test_smb(): buf = b'\xffSMB\xa0\x00\x00\x00\x00\x08\x03\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xfa\x7a\x00\x08\x53\x02' smb = SMB(buf) assert smb.flags == SMB_FLAGS_CASE_INSENSITIVE assert smb.flags2 == SMB_FLAGS2_UNICODE | SMB_FLAGS2_NT_STATUS | SMB_FLAGS2_EXTENDED_SECURITY | SMB_FLAGS2_EXTENDED_ATTRIBUTES | SMB_FLAGS2_LONG_NAMES assert smb.pid == 31482 assert smb.uid == 2048 assert smb.mid == 595 print(repr(smb)) smb = SMB() smb.pid = 0x00081020 smb.uid = 0x800 assert str(smb) == str(b'\xffSMB\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x10\x00\x08\x00\x00') if __name__ == '__main__': test_smb() print('Tests Successful...') dpkt-1.9.2/dpkt/snoop.py000066400000000000000000000065151340335175100151500ustar00rootroot00000000000000# $Id$ # -*- coding: utf-8 -*- """Snoop file format.""" from __future__ import absolute_import import time from . import dpkt # RFC 1761 SNOOP_MAGIC = 0x736E6F6F70000000 SNOOP_VERSION = 2 SDL_8023 = 0 SDL_8024 = 1 SDL_8025 = 2 SDL_8026 = 3 SDL_ETHER = 4 SDL_HDLC = 5 SDL_CHSYNC = 6 SDL_IBMCC = 7 SDL_FDDI = 8 SDL_OTHER = 9 dltoff = {SDL_ETHER: 14} class PktHdr(dpkt.Packet): """snoop packet header. TODO: Longer class information.... Attributes: __hdr__: Header fields of snoop packet header. TODO. """ __byte_order__ = '!' __hdr__ = ( ('orig_len', 'I', 0), ('incl_len', 'I', 0), ('rec_len', 'I', 0), ('cum_drops', 'I', 0), ('ts_sec', 'I', 0), ('ts_usec', 'I', 0), ) class FileHdr(dpkt.Packet): """snoop file header. TODO: Longer class information.... Attributes: __hdr__: Header fields of snoop file header. TODO. """ __byte_order__ = '!' __hdr__ = ( ('magic', 'Q', SNOOP_MAGIC), ('v', 'I', SNOOP_VERSION), ('linktype', 'I', SDL_ETHER), ) class Writer(object): """Simple snoop dumpfile writer. TODO: Longer class information.... Attributes: TODO. """ def __init__(self, fileobj, linktype=SDL_ETHER): self.__f = fileobj fh = FileHdr(linktype=linktype) self.__f.write(str(fh)) def writepkt(self, pkt, ts=None): if ts is None: ts = time.time() s = str(pkt) n = len(s) pad_len = 4 - n % 4 if n % 4 else 0 ph = PktHdr(orig_len=n, incl_len=n, rec_len=PktHdr.__hdr_len__ + n + pad_len, ts_sec=int(ts), ts_usec=int((int(ts) - float(ts)) * 1000000.0)) self.__f.write(str(ph)) self.__f.write(s + '\0' * pad_len) def close(self): self.__f.close() class Reader(object): """Simple pypcap-compatible snoop file reader. TODO: Longer class information.... Attributes: TODO. """ def __init__(self, fileobj): self.name = fileobj.name self.fd = fileobj.fileno() self.__f = fileobj buf = self.__f.read(FileHdr.__hdr_len__) self.__fh = FileHdr(buf) self.__ph = PktHdr if self.__fh.magic != SNOOP_MAGIC: raise ValueError('invalid snoop header') self.dloff = dltoff[self.__fh.linktype] self.filter = '' def fileno(self): return self.fd def datalink(self): return self.__fh.linktype def setfilter(self, value, optimize=1): return NotImplementedError def readpkts(self): return list(self) def dispatch(self, cnt, callback, *args): if cnt > 0: for i in range(cnt): ts, pkt = next(self) callback(ts, pkt, *args) else: for ts, pkt in self: callback(ts, pkt, *args) def loop(self, callback, *args): self.dispatch(0, callback, *args) def __iter__(self): self.__f.seek(FileHdr.__hdr_len__) while 1: buf = self.__f.read(PktHdr.__hdr_len__) if not buf: break hdr = self.__ph(buf) buf = self.__f.read(hdr.rec_len - PktHdr.__hdr_len__) yield (hdr.ts_sec + (hdr.ts_usec / 1000000.0), buf[:hdr.incl_len]) dpkt-1.9.2/dpkt/ssl.py000066400000000000000000000715311340335175100146130ustar00rootroot00000000000000# $Id: ssl.py 90 2014-04-02 22:06:23Z andrewflnr@gmail.com $ # Portion Copyright 2012 Google Inc. All rights reserved. # -*- coding: utf-8 -*- """Secure Sockets Layer / Transport Layer Security.""" from __future__ import absolute_import import struct import binascii from . import dpkt from . import ssl_ciphersuites # # Note from April 2011: cde...@gmail.com added code that parses SSL3/TLS messages more in depth. # # Jul 2012: afleenor@google.com modified and extended SSL support further. # # SSL 2.0 is deprecated in RFC 6176 class SSL2(dpkt.Packet): __hdr__ = ( ('len', 'H', 0), ('msg', 's', ''), ('pad', 's', ''), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.len & 0x8000: n = self.len = self.len & 0x7FFF self.msg, self.data = self.data[:n], self.data[n:] else: n = self.len = self.len & 0x3FFF padlen = ord(self.data[0]) self.msg = self.data[1:1 + n] self.pad = self.data[1 + n:1 + n + padlen] self.data = self.data[1 + n + padlen:] # SSL 3.0 is deprecated in RFC 7568 # Use class TLS for >= SSL 3.0 class TLS(dpkt.Packet): __hdr__ = ( ('type', 'B', ''), ('version', 'H', ''), ('len', 'H', ''), ) def __init__(self, *args, **kwargs): self.records = [] dpkt.Packet.__init__(self, *args, **kwargs) def unpack(self, buf): dpkt.Packet.unpack(self, buf) pointer = 0 while len(self.data[pointer:]) > 0: end = pointer + 5 + struct.unpack("!H", buf[pointer+3:pointer+5])[0] self.records.append(TLSRecord(buf[pointer:end])) pointer = end self.data = self.data[pointer:] # SSLv3/TLS versions SSL3_V = 0x0300 TLS1_V = 0x0301 TLS11_V = 0x0302 TLS12_V = 0x0303 ssl3_versions_str = { SSL3_V: 'SSL3', TLS1_V: 'TLS 1.0', TLS11_V: 'TLS 1.1', TLS12_V: 'TLS 1.2' } SSL3_VERSION_BYTES = set((b'\x03\x00', b'\x03\x01', b'\x03\x02', b'\x03\x03')) # Alert levels SSL3_AD_WARNING = 1 SSL3_AD_FATAL = 2 alert_level_str = { SSL3_AD_WARNING: 'SSL3_AD_WARNING', SSL3_AD_FATAL: 'SSL3_AD_FATAL' } # SSL3 alert descriptions SSL3_AD_CLOSE_NOTIFY = 0 SSL3_AD_UNEXPECTED_MESSAGE = 10 # fatal SSL3_AD_BAD_RECORD_MAC = 20 # fatal SSL3_AD_DECOMPRESSION_FAILURE = 30 # fatal SSL3_AD_HANDSHAKE_FAILURE = 40 # fatal SSL3_AD_NO_CERTIFICATE = 41 SSL3_AD_BAD_CERTIFICATE = 42 SSL3_AD_UNSUPPORTED_CERTIFICATE = 43 SSL3_AD_CERTIFICATE_REVOKED = 44 SSL3_AD_CERTIFICATE_EXPIRED = 45 SSL3_AD_CERTIFICATE_UNKNOWN = 46 SSL3_AD_ILLEGAL_PARAMETER = 47 # fatal # TLS1 alert descriptions TLS1_AD_DECRYPTION_FAILED = 21 TLS1_AD_RECORD_OVERFLOW = 22 TLS1_AD_UNKNOWN_CA = 48 # fatal TLS1_AD_ACCESS_DENIED = 49 # fatal TLS1_AD_DECODE_ERROR = 50 # fatal TLS1_AD_DECRYPT_ERROR = 51 TLS1_AD_EXPORT_RESTRICTION = 60 # fatal TLS1_AD_PROTOCOL_VERSION = 70 # fatal TLS1_AD_INSUFFICIENT_SECURITY = 71 # fatal TLS1_AD_INTERNAL_ERROR = 80 # fatal TLS1_AD_USER_CANCELLED = 90 TLS1_AD_NO_RENEGOTIATION = 100 # /* codes 110-114 are from RFC3546 */ TLS1_AD_UNSUPPORTED_EXTENSION = 110 TLS1_AD_CERTIFICATE_UNOBTAINABLE = 111 TLS1_AD_UNRECOGNIZED_NAME = 112 TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE = 113 TLS1_AD_BAD_CERTIFICATE_HASH_VALUE = 114 TLS1_AD_UNKNOWN_PSK_IDENTITY = 115 # fatal # Mapping alert types to strings alert_description_str = { SSL3_AD_CLOSE_NOTIFY: 'SSL3_AD_CLOSE_NOTIFY', SSL3_AD_UNEXPECTED_MESSAGE: 'SSL3_AD_UNEXPECTED_MESSAGE', SSL3_AD_BAD_RECORD_MAC: 'SSL3_AD_BAD_RECORD_MAC', SSL3_AD_DECOMPRESSION_FAILURE: 'SSL3_AD_DECOMPRESSION_FAILURE', SSL3_AD_HANDSHAKE_FAILURE: 'SSL3_AD_HANDSHAKE_FAILURE', SSL3_AD_NO_CERTIFICATE: 'SSL3_AD_NO_CERTIFICATE', SSL3_AD_BAD_CERTIFICATE: 'SSL3_AD_BAD_CERTIFICATE', SSL3_AD_UNSUPPORTED_CERTIFICATE: 'SSL3_AD_UNSUPPORTED_CERTIFICATE', SSL3_AD_CERTIFICATE_REVOKED: 'SSL3_AD_CERTIFICATE_REVOKED', SSL3_AD_CERTIFICATE_EXPIRED: 'SSL3_AD_CERTIFICATE_EXPIRED', SSL3_AD_CERTIFICATE_UNKNOWN: 'SSL3_AD_CERTIFICATE_UNKNOWN', SSL3_AD_ILLEGAL_PARAMETER: 'SSL3_AD_ILLEGAL_PARAMETER', TLS1_AD_DECRYPTION_FAILED: 'TLS1_AD_DECRYPTION_FAILED', TLS1_AD_RECORD_OVERFLOW: 'TLS1_AD_RECORD_OVERFLOW', TLS1_AD_UNKNOWN_CA: 'TLS1_AD_UNKNOWN_CA', TLS1_AD_ACCESS_DENIED: 'TLS1_AD_ACCESS_DENIED', TLS1_AD_DECODE_ERROR: 'TLS1_AD_DECODE_ERROR', TLS1_AD_DECRYPT_ERROR: 'TLS1_AD_DECRYPT_ERROR', TLS1_AD_EXPORT_RESTRICTION: 'TLS1_AD_EXPORT_RESTRICTION', TLS1_AD_PROTOCOL_VERSION: 'TLS1_AD_PROTOCOL_VERSION', TLS1_AD_INSUFFICIENT_SECURITY: 'TLS1_AD_INSUFFICIENT_SECURITY', TLS1_AD_INTERNAL_ERROR: 'TLS1_AD_INTERNAL_ERROR', TLS1_AD_USER_CANCELLED: 'TLS1_AD_USER_CANCELLED', TLS1_AD_NO_RENEGOTIATION: 'TLS1_AD_NO_RENEGOTIATION', TLS1_AD_UNSUPPORTED_EXTENSION: 'TLS1_AD_UNSUPPORTED_EXTENSION', TLS1_AD_CERTIFICATE_UNOBTAINABLE: 'TLS1_AD_CERTIFICATE_UNOBTAINABLE', TLS1_AD_UNRECOGNIZED_NAME: 'TLS1_AD_UNRECOGNIZED_NAME', TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: 'TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE', TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: 'TLS1_AD_BAD_CERTIFICATE_HASH_VALUE', TLS1_AD_UNKNOWN_PSK_IDENTITY: 'TLS1_AD_UNKNOWN_PSK_IDENTITY' } # struct format strings for parsing buffer lengths # don't forget, you have to pad a 3-byte value with \x00 _SIZE_FORMATS = ['!B', '!H', '!I', '!I'] def parse_variable_array(buf, lenbytes): """ Parse an array described using the 'Type name' syntax from the spec Read a length at the start of buf, and returns that many bytes after, in a tuple with the TOTAL bytes consumed (including the size). This does not check that the array is the right length for any given datatype. """ # first have to figure out how to parse length assert lenbytes <= 4 # pretty sure 4 is impossible, too size_format = _SIZE_FORMATS[lenbytes - 1] padding = b'\x00' if lenbytes == 3 else b'' # read off the length size = struct.unpack(size_format, padding + buf[:lenbytes])[0] # read the actual data data = buf[lenbytes:lenbytes + size] # if len(data) != size: insufficient data return data, size + lenbytes def parse_extensions(buf): """ Parse TLS extensions in passed buf. Returns an ordered list of extension tuples with ordinal extension type as first value and extension data as second value. Passed buf must start with the 2-byte extensions length TLV. http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml """ extensions_length = struct.unpack('!H', buf[:2])[0] extensions = [] pointer = 2 while pointer < extensions_length: ext_type = struct.unpack('!H', buf[pointer:pointer+2])[0] pointer += 2 ext_data, parsed = parse_variable_array(buf[pointer:], 2) extensions.append((ext_type, ext_data)) pointer += parsed return extensions class SSL3Exception(Exception): pass class TLSRecord(dpkt.Packet): """ SSLv3 or TLSv1+ packet. In addition to the fields specified in the header, there are compressed and decrypted fields, indicating whether, in the language of the spec, this is a TLSPlaintext, TLSCompressed, or TLSCiphertext. The application will have to figure out when it's appropriate to change these values. """ __hdr__ = ( ('type', 'B', 0), ('version', 'H', 0), ('length', 'H', 0), ) def __init__(self, *args, **kwargs): # assume plaintext unless specified otherwise in arguments self.compressed = kwargs.pop('compressed', False) self.encrypted = kwargs.pop('encrypted', False) # parent constructor dpkt.Packet.__init__(self, *args, **kwargs) # make sure length and data are consistent self.length = len(self.data) def unpack(self, buf): dpkt.Packet.unpack(self, buf) header_length = self.__hdr_len__ self.data = buf[header_length:header_length + self.length] # make sure buffer was long enough if len(self.data) != self.length: raise dpkt.NeedData('TLSRecord data was too short.') # assume compressed and encrypted when it's been parsed from # raw data self.compressed = True self.encrypted = True class TLSChangeCipherSpec(dpkt.Packet): """ ChangeCipherSpec message is just a single byte with value 1 """ __hdr__ = (('type', 'B', 1),) class TLSAppData(str): """ As far as TLSRecord is concerned, AppData is just an opaque blob. """ pass class TLSAlert(dpkt.Packet): __hdr__ = ( ('level', 'B', 1), ('description', 'B', 0), ) class TLSHelloRequest(dpkt.Packet): __hdr__ = tuple() class TLSClientHello(dpkt.Packet): __hdr__ = ( ('version', 'H', 0x0301), ('random', '32s', '\x00' * 32), ) # the rest is variable-length and has to be done manually def unpack(self, buf): dpkt.Packet.unpack(self, buf) # now session, cipher suites, extensions are in self.data self.session_id, pointer = parse_variable_array(self.data, 1) # print 'pointer',pointer # handle ciphersuites ciphersuites, parsed = parse_variable_array(self.data[pointer:], 2) pointer += parsed self.num_ciphersuites = len(ciphersuites) / 2 # check len(ciphersuites) % 2 == 0 ? # compression methods compression_methods, parsed = parse_variable_array( self.data[pointer:], 1) pointer += parsed self.num_compression_methods = parsed - 1 self.compression_methods = map(ord, compression_methods) # Parse extensions if present if len(self.data[pointer:]) >= 6: self.extensions = parse_extensions(self.data[pointer:]) class TLSServerHello(dpkt.Packet): __hdr__ = ( ('version', 'H', '0x0301'), ('random', '32s', '\x00' * 32), ) # session is variable, forcing rest to be manual def unpack(self, buf): try: dpkt.Packet.unpack(self, buf) self.session_id, pointer = parse_variable_array(self.data, 1) # single cipher suite self.cipher_suite = struct.unpack('!H', self.data[pointer:pointer + 2])[0] pointer += 2 # single compression method self.compression = struct.unpack('!B', self.data[pointer:pointer + 1])[0] pointer += 1 # Parse extensions if present if len(self.data[pointer:]) >= 6: self.extensions = parse_extensions(self.data[pointer:]) except struct.error: # probably data too short raise dpkt.NeedData class TLSCertificate(dpkt.Packet): __hdr__ = tuple() def unpack(self, buf): try: dpkt.Packet.unpack(self, buf) all_certs, all_certs_len = parse_variable_array(self.data, 3) self.certificates = [] pointer = 3 while pointer < all_certs_len: cert, parsed = parse_variable_array(self.data[pointer:], 3) self.certificates.append((cert)) pointer += parsed except struct.error: raise dpkt.NeedData class TLSUnknownHandshake(dpkt.Packet): __hdr__ = tuple() TLSServerKeyExchange = TLSUnknownHandshake TLSCertificateRequest = TLSUnknownHandshake TLSServerHelloDone = TLSUnknownHandshake TLSCertificateVerify = TLSUnknownHandshake TLSClientKeyExchange = TLSUnknownHandshake TLSFinished = TLSUnknownHandshake # mapping of handshake type ids to their names # and the classes that implement them HANDSHAKE_TYPES = { 0: ('HelloRequest', TLSHelloRequest), 1: ('ClientHello', TLSClientHello), 2: ('ServerHello', TLSServerHello), 11: ('Certificate', TLSCertificate), 12: ('ServerKeyExchange', TLSServerKeyExchange), 13: ('CertificateRequest', TLSCertificateRequest), 14: ('ServerHelloDone', TLSServerHelloDone), 15: ('CertificateVerify', TLSCertificateVerify), 16: ('ClientKeyExchange', TLSClientKeyExchange), 20: ('Finished', TLSFinished), } class TLSHandshake(dpkt.Packet): """ A TLS Handshake message This goes for all messages encapsulated in the Record layer, but especially important for handshakes and app data: A message may be spread across a number of TLSRecords, in addition to the possibility of there being more than one in a given Record. You have to put together the contents of TLSRecord's yourself. """ # struct.unpack can't handle the 3-byte int, so we parse it as bytes # (and store it as bytes so dpkt doesn't get confused), and turn it into # an int in a user-facing property __hdr__ = ( ('type', 'B', 0), ('length_bytes', '3s', 0), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) # Wait, might there be more than one message of self.type? embedded_type = HANDSHAKE_TYPES.get(self.type, None) if embedded_type is None: raise SSL3Exception('Unknown or invalid handshake type %d' % self.type) # only take the right number of bytes self.data = self.data[:self.length] if len(self.data) != self.length: raise dpkt.NeedData # get class out of embedded_type tuple self.data = embedded_type[1](self.data) @property def length(self): return struct.unpack('!I', b'\x00' + self.length_bytes)[0] RECORD_TYPES = { 20: TLSChangeCipherSpec, 21: TLSAlert, 22: TLSHandshake, 23: TLSAppData, } class SSLFactory(object): def __new__(cls, buf): v = buf[1:3] if v in SSL3_VERSION_BYTES: return TLSRecord(buf) # SSL2 has no characteristic header or magic bytes, so we just assume # that the msg is an SSL2 msg if it is not detected as SSL3+ return SSL2(buf) def tls_multi_factory(buf): """ Attempt to parse one or more TLSRecord's out of buf Args: buf: string containing SSL/TLS messages. May have an incomplete record on the end Returns: [TLSRecord] int, total bytes consumed, != len(buf) if an incomplete record was left at the end. Raises SSL3Exception. """ i, n = 0, len(buf) msgs = [] while i + 5 <= n: v = buf[i + 1:i + 3] if v in SSL3_VERSION_BYTES: try: msg = TLSRecord(buf[i:]) msgs.append(msg) except dpkt.NeedData: break else: raise SSL3Exception('Bad TLS version in buf: %r' % buf[i:i + 5]) i += len(msg) return msgs, i _hexdecode = binascii.a2b_hex class TestTLS(object): """ Test basic TLS functionality. Test that each TLSRecord is correctly discovered and added to TLS.records """ @classmethod def setup_class(cls): cls.p = TLS(_hexdecode('1603000206010002020303585c2ff72a6599498771f59514f10af68c68f9ef30d0dadc9e1af64d1091476a000084c02bc02cc086c087c009c023c00ac024c072c073c008c007c02fc030c08ac08bc013c027c014c028c076c077c012c011009c009dc07ac07b002f003c0035003d004100ba008400c0000a00050004009e009fc07cc07d003300670039006b004500be008800c4001600a200a3c080c081003200400038006a004400bd008700c3001300660100015500050005010000000000000011000f00000c7777772e69616e612e6f7267ff0100010000230000000a000c000a00130015001700180019000b00020100000d001c001a0401040204030501050306010603030103020303020102020203001500f400f20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')) def test_records_length(self): assert (len(self.p.records) == 1) def test_record_type(self): assert (self.p.records[0].type == 22) def test_record_version(self): assert (self.p.records[0].version == 768) class TestTLSRecord(object): """ Test basic TLSRecord functionality For this test, the contents of the record doesn't matter, since we're not parsing the next layer. """ @classmethod def setup_class(cls): # add some extra data, to make sure length is parsed correctly cls.p = TLSRecord(b'\x17\x03\x01\x00\x08abcdefghzzzzzzzzzzz') def test_content_type(self): assert (self.p.type == 23) def test_version(self): assert (self.p.version == 0x0301) def test_length(self): assert (self.p.length == 8) def test_data(self): assert (self.p.data == b'abcdefgh') def test_initial_flags(self): assert (self.p.compressed == True) assert (self.p.encrypted == True) def test_repack(self): p2 = TLSRecord(type=23, version=0x0301, data=b'abcdefgh') assert (p2.type == 23) assert (p2.version == 0x0301) assert (p2.length == 8) assert (p2.data == b'abcdefgh') assert (p2.pack() == self.p.pack()) def test_total_length(self): # that len(p) includes header assert (len(self.p) == 13) def test_raises_need_data_when_buf_is_short(self): import pytest pytest.raises(dpkt.NeedData, TLSRecord, b'\x16\x03\x01\x00\x10abc') class TestTLSChangeCipherSpec(object): """It's just a byte. This will be quick, I promise""" @classmethod def setup_class(cls): cls.p = TLSChangeCipherSpec(b'\x01') def test_parses(self): assert (self.p.type == 1) def test_total_length(self): assert (len(self.p) == 1) class TestTLSAppData(object): """AppData is basically just a string""" def test_value(self): d = TLSAppData('abcdefgh') assert (d == 'abcdefgh') class TestTLSHandshake(object): @classmethod def setup_class(cls): cls.h = TLSHandshake(b'\x00\x00\x00\x01\xff') def test_created_inside_message(self): assert (isinstance(self.h.data, TLSHelloRequest) == True) def test_length(self): assert (self.h.length == 0x01) def test_raises_need_data(self): import pytest pytest.raises(dpkt.NeedData, TLSHandshake, b'\x00\x00\x01\x01') class TestClientHello(object): """This data is extracted from and verified by Wireshark""" @classmethod def setup_class(cls): cls.data = _hexdecode( b"01000199" # handshake header b"0301" # version b"5008220ce5e0e78b6891afe204498c9363feffbe03235a2d9e05b7d990eb708d" # rand b"2009bc0192e008e6fa8fe47998fca91311ba30ddde14a9587dc674b11c3d3e5ed1" # session id # cipher suites b"005400ffc00ac0140088008700390038c00fc00500840035c007c009c011c0130045004400330032c00cc00ec002c0040096004100050004002fc008c01200160013c00dc003feff000ac006c010c00bc00100020001" b"0100" # compresssion methods # extensions b"00fc0000000e000c0000096c6f63616c686f7374000a00080006001700180019000b00020100002300d0a50b2e9f618a9ea9bf493ef49b421835cd2f6b05bbe1179d8edf70d58c33d656e8696d36d7e7e0b9d3ecc0e4de339552fa06c64c0fcb550a334bc43944e2739ca342d15a9ebbe981ac87a0d38160507d47af09bdc16c5f0ee4cdceea551539382333226048a026d3a90a0535f4a64236467db8fee22b041af986ad0f253bc369137cd8d8cd061925461d7f4d7895ca9a4181ab554dad50360ac31860e971483877c9335ac1300c5e78f3e56f3b8e0fc16358fcaceefd5c8d8aaae7b35be116f8832856ca61144fcdd95e071b94d0cf7233740000" b"FFFFFFFFFFFFFFFF") # random garbage cls.p = TLSHandshake(cls.data) def test_client_hello_constructed(self): """Make sure the correct class was constructed""" # print self.p assert (isinstance(self.p.data, TLSClientHello) == True) # def testClientDateCorrect(self): # self.assertEqual(self.p.random_unixtime, 1342710284) def test_client_random_correct(self): assert (self.p.data.random == _hexdecode(b'5008220ce5e0e78b6891afe204498c9363feffbe03235a2d9e05b7d990eb708d')) def test_cipher_suite_length(self): # we won't bother testing the identity of each cipher suite in the list. assert (self.p.data.num_ciphersuites == 42) # self.assertEqual(len(self.p.ciphersuites), 42) def test_session_id(self): assert (self.p.data.session_id == _hexdecode(b'09bc0192e008e6fa8fe47998fca91311ba30ddde14a9587dc674b11c3d3e5ed1')) def test_compression_methods(self): assert (self.p.data.num_compression_methods == 1) def test_total_length(self): assert (len(self.p) == 413) class TestServerHello(object): """Again, from Wireshark""" @classmethod def setup_class(cls): cls.data = _hexdecode( b'0200004d03015008220c8ec43c5462315a7c99f5d5b6bff009ad285b51dc18485f352e9fdecd2009bc0192e008e6fa8fe47998fca91311ba30ddde14a9587dc674b11c3d3e5ed10002000005ff01000100') cls.p = TLSHandshake(cls.data) def test_constructed(self): assert (isinstance(self.p.data, TLSServerHello) == True) # def testDateCorrect(self): # self.assertEqual(self.p.random_unixtime, 1342710284) def test_random_correct(self): assert (self.p.data.random == _hexdecode(b'5008220c8ec43c5462315a7c99f5d5b6bff009ad285b51dc18485f352e9fdecd')) def test_cipher_suite(self): assert (ssl_ciphersuites.BY_CODE[self.p.data.cipher_suite].name == 'TLS_RSA_WITH_NULL_SHA') def test_total_length(self): assert (len(self.p) == 81) class TestTLSCertificate(object): """We use a 2016 certificate record from iana.org as test data.""" @classmethod def setup_class(cls): cls.p = TLSHandshake(_hexdecode('0b000b45000b42000687308206833082056ba003020102021009cabbe2191c8f569dd4b6dd250f21d8300d06092a864886f70d01010b05003070310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d312f302d06035504031326446967694365727420534841322048696768204173737572616e636520536572766572204341301e170d3134313032373030303030305a170d3138303130333132303030305a3081a3310b3009060355040613025553311330110603550408130a43616c69666f726e6961311430120603550407130b4c6f7320416e67656c6573313c303a060355040a1333496e7465726e657420436f72706f726174696f6e20666f722041737369676e6564204e616d657320616e64204e756d6265727331163014060355040b130d4954204f7065726174696f6e733113301106035504030c0a2a2e69616e612e6f726730820222300d06092a864886f70d01010105000382020f003082020a02820201009dbdfddeb5cae53a559747e2fda63728e4aba60f18b79a69f03310bf0164e5ee7db6b15bf56df23fddbae6a1bb38449b8c883f18102bbd8bb655ac0e2dac2ee3ed5cf4315868d2c598068284854b24894dcd4bd37811f0ad3a282cd4b4e599ffd07d8d2d3f2478554f81020b320ee12f44948e2ea1edbc990b830ca5cca6b4a839fb27b51850c9847eac74f26609eb24365b9751fb1c3208f56913bacbcae49201347c78b7e54a9d99979404c37f00fb65db849fd75e3a68770c30f2abe65b33256fb59b450050b00d8139d4d80d36f7bc46daf303e48f0f0791b2fdd72ec60b2cb3ad533c3f288c9c194e49337a69c496731f086d4f1f9825900713e2a551d05cb6057567850d91e6001c4ce27176f0957873a95b880acbec19e7bd9bcf1286d0452b73789c41905dd470971cd73aea52c77b080cd779af58234f337225c26f87a8c13e2a65e9dd4e03a5b41d7e06b3353f38129b2327a531ec9627a21dc423733aa029d4989448ba3322891c1a5690ddf2d25c8ec8aaa894b14aa92130c6b6d969a21ff671b60c4c923a94a93ea1dd0492c93393ca6edd61f33ca77e9208d01d6bd15107662ec088733df4c876a7e1608b82973a0f7592e84ed15579d181e79024ae8a7e4b9f0078eb2005b23f9d09a1df1bbc7de2a5a6085a3646d9fadb0e9da273a5f403cdd42831ce6f0ca46889585602bb8bc36bb3be861ff6d1a62e350203010001a38201e3308201df301f0603551d230418301680145168ff90af0207753cccd9656462a212b859723b301d0603551d0e04160414c7d0acef898b20e4b914668933032394f6bf3a61301f0603551d1104183016820a2a2e69616e612e6f7267820869616e612e6f7267300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b0601050507030230750603551d1f046e306c3034a032a030862e687474703a2f2f63726c332e64696769636572742e636f6d2f736861322d68612d7365727665722d67332e63726c3034a032a030862e687474703a2f2f63726c342e64696769636572742e636f6d2f736861322d68612d7365727665722d67332e63726c30420603551d20043b3039303706096086480186fd6c0101302a302806082b06010505070201161c68747470733a2f2f7777772e64696769636572742e636f6d2f43505330818306082b0601050507010104773075302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d304d06082b060105050730028641687474703a2f2f636163657274732e64696769636572742e636f6d2f446967694365727453484132486967684173737572616e636553657276657243412e637274300c0603551d130101ff04023000300d06092a864886f70d01010b0500038201010070314c38e7c02fd80810500b9df6dae85de9b23e29fbd68bfdb5f23411c89acfaf9ae05af9123a8aa6bce6954a4e68dc7cfc480a65d76f229c4bd5f5674b0c9ac6d06a37a1a1c145c3956120b8efe67c887ab4ff7d6aa950ff3698f27c4a19d59d93a39aca5a7b6d6c75e34974e50f5a590005b3cb665ddbd7074f9fcbcbf9c50228d5e25596b64ada160b48f77a93aaced22617bfe005e00fe20a532a0adcb818c878dc5d6649277777ca1a814e21d0b53308af4078be4554715e4ce4828b012f25ffa13a6ceb30d20a75deba8a344e41d627fa638feff38a3063a0187519b39b053f7134d9cd83e6091accf5d2e3a05edfa1dfbe181a87ad86ba24fe6b97fe0004b5308204b130820399a003020102021004e1e7a4dc5cf2f36dc02b42b85d159f300d06092a864886f70d01010b0500306c310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d312b30290603550403132244696769436572742048696768204173737572616e636520455620526f6f74204341301e170d3133313032323132303030305a170d3238313032323132303030305a3070310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d312f302d06035504031326446967694365727420534841322048696768204173737572616e63652053657276657220434130820122300d06092a864886f70d01010105000382010f003082010a0282010100b6e02fc22406c86d045fd7ef0a6406b27d22266516ae42409bcedc9f9f76073ec330558719b94f940e5a941f5556b4c2022aafd098ee0b40d7c4d03b72c8149eef90b111a9aed2c8b8433ad90b0bd5d595f540afc81ded4d9c5f57b786506899f58adad2c7051fa897c9dca4b182842dc6ada59cc71982a6850f5e44582a378ffd35f10b0827325af5bb8b9ea4bd51d027e2dd3b4233a30528c4bb28cc9aac2b230d78c67be65e71b74a3e08fb81b71616a19d23124de5d79208ac75a49cbacd17b21e4435657f532539d11c0a9a631b199274680a37c2c25248cb395aa2b6e15dc1dda020b821a293266f144a2141c7ed6d9bf2482ff303f5a26892532f5ee30203010001a38201493082014530120603551d130101ff040830060101ff020100300e0603551d0f0101ff040403020186301d0603551d250416301406082b0601050507030106082b06010505070302303406082b0601050507010104283026302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d304b0603551d1f044430423040a03ea03c863a687474703a2f2f63726c342e64696769636572742e636f6d2f4469676943657274486967684173737572616e63654556526f6f7443412e63726c303d0603551d200436303430320604551d2000302a302806082b06010505070201161c68747470733a2f2f7777772e64696769636572742e636f6d2f435053301d0603551d0e041604145168ff90af0207753cccd9656462a212b859723b301f0603551d23041830168014b13ec36903f8bf4701d498261a0802ef63642bc3300d06092a864886f70d01010b05000382010100188a958903e66ddf5cfc1d68ea4a8f83d6512f8d6b44169eac63f5d26e6c84998baa8171845bed344eb0b7799229cc2d806af08e20e179a4fe034713eaf586ca59717df404966bd359583dfed331255c183884a3e69f82fd8c5b98314ecd789e1afd85cb49aaf2278b9972fc3eaad5410bdad536a1bf1c6e47497f5ed9487c03d9fd8b49a098264240ebd69211a4640a5754c4f51dd6025e6baceec4809a1272fa5693d7ffbf30850630bf0b7f4eff57059d24ed85c32bfba675a8ac2d16ef7d7927b2ebc29d0b07eaaa85d301a3202841594328d281e3aaf6ec7b3b77b640628005414501ef17063edec0339b67d3612e7287e469fc120057401e70f51ec9b4')) def test_num_certs(self): assert (len(self.p.data.certificates) == 2) class TestTLSMultiFactory(object): """Made up test data""" @classmethod def setup_class(cls): cls.data = _hexdecode(b'1703010010' # header 1 b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' # data 1 b'1703010010' # header 2 b'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB' # data 2 b'1703010010' # header 3 b'CCCCCCCC') # data 3 (incomplete) cls.msgs, cls.bytes_parsed = tls_multi_factory(cls.data) def test_num_messages(self): # only complete messages should be parsed, incomplete ones left # in buffer assert (len(self.msgs) == 2) def test_bytes_parsed(self): assert (self.bytes_parsed == (5 + 16) * 2) def test_first_msg_data(self): assert (self.msgs[0].data == _hexdecode(b'AA' * 16)) def test_second_msg_data(self): assert (self.msgs[1].data == _hexdecode(b'BB' * 16)) def test_incomplete(self): msgs, n = tls_multi_factory(_hexdecode(b'17')) assert (len(msgs) == 0) assert (n == 0) msgs, n = tls_multi_factory(_hexdecode(b'1703')) assert (len(msgs) == 0) assert (n == 0) msgs, n = tls_multi_factory(_hexdecode(b'170301')) assert (len(msgs) == 0) assert (n == 0) msgs, n = tls_multi_factory(_hexdecode(b'17030100')) assert (len(msgs) == 0) assert (n == 0) msgs, n = tls_multi_factory(_hexdecode(b'1703010000')) assert (len(msgs) == 1) assert (n == 5) dpkt-1.9.2/dpkt/ssl_ciphersuites.py000066400000000000000000001042531340335175100174000ustar00rootroot00000000000000# Copyright 2012 Google Inc. All rights reserved. # -*- coding: utf-8 -*- """ Nicely formatted cipher suite definitions for TLS A list of cipher suites in the form of CipherSuite objects. These are supposed to be immutable; don't mess with them. """ class CipherSuite(object): """ Encapsulates a cipher suite. Members/args: * code: two-byte ID code, as int * kx: key exchange algorithm, e.g. 'RSA' or 'DHE' * auth: authentication algorithm, e.g. 'RSA' or 'DSS' * cipher: stream or block cipher algorithm, e.g. 'AES_128' * mode: mode of operation for block ciphers, e.g. 'CBC' or 'GCM' * mac: message authentication code algorithm, e.g. 'MD5' or 'SHA256' * name: cipher suite name as defined in the RFCs, e.g. 'TLS_RSA_WITH_RC4_40_MD5', can be generated by default from the other parameters * encoding: encoding algorithm, defaults to cipher+mode Additional members: * kx_auth: kx+auth algorithm, as 'KeyExchangeAlgorithm' in RFCs """ def __init__(self, code, kx, auth, cipher, mode, mac, name=None, encoding=None): self.code = code # We strip trailing whitespace here because we want to format the # global table nicely while making pylint happy. self._kx = kx.rstrip() self._auth = auth.rstrip() self.cipher = cipher.rstrip() self.mode = mode.rstrip() self.mac = mac.rstrip() self._name = name self._encoding = encoding @property def kx(self): if self._kx == '': # for PSK return self._auth else: return self._kx @property def auth(self): if self._auth == '': # for RSA return self._kx else: return self._auth @property def kx_auth(self): if self._auth == '': # for RSA return self._kx elif self._kx == '': # for PSK return self._auth else: return self._kx + '_' + self._auth @property def encoding(self): if self._encoding is None: if self.mode == '': return self.cipher else: return self.cipher + '_' + self.mode else: return self._encoding @property def name(self): if self._name is None: if self.mac == '': # for CCM and CCM_8 modes return 'TLS_' + self.kx_auth + '_WITH_' + self.encoding else: return 'TLS_' + self.kx_auth + '_WITH_' + self.encoding + '_' + self.mac else: return self._name def __repr__(self): return 'CipherSuite(%s)' % self.name MAC_SIZES = { 'MD5': 16, 'SHA': 20, 'SHA256': 32, 'SHA384': 48, } # TODO: add RC4_40, RC4_128, RC2_40, IDEA, DES40, DES, 3DES_EDE, # CAMELLIA_128, CAMELLIA_256, SEED, ARIA_128, ARIA_256, CHACHA20 BLOCK_SIZES = { 'AES_128': 16, 'AES_256': 16, } @property def mac_size(self): """In bytes. Default to 0.""" return self.MAC_SIZES.get(self.mac, 0) @property def block_size(self): """In bytes. Default to 1.""" return self.BLOCK_SIZES.get(self.cipher, 1) # master list of CipherSuite Objects # Full list from IANA: # https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml CIPHERSUITES = [ # not a real cipher suite, can be ignored, see RFC5746 CipherSuite(0x00ff, 'NULL', ' ', 'NULL ', ' ', 'NULL', 'TLS_EMPTY_RENEGOTIATION_INFO'), # RFC7507 CipherSuite(0x5600, '', ' ', '', '', '', 'TLS_FALLBACK'), CipherSuite(0xffff, '', ' ', '', '', '', 'UNKNOWN_CIPHER'), # RFC2246 : TLS 1.0 CipherSuite(0x0000, 'NULL', ' ', 'NULL ', ' ', 'NULL'), CipherSuite(0x0001, 'RSA', ' ', 'NULL ', ' ', 'MD5'), CipherSuite(0x0002, 'RSA', ' ', 'NULL ', ' ', 'SHA'), CipherSuite(0x0003, 'RSA_EXPORT', ' ', 'RC4_40 ', ' ', 'MD5'), CipherSuite(0x0004, 'RSA', ' ', 'RC4_128 ', ' ', 'MD5'), CipherSuite(0x0005, 'RSA', ' ', 'RC4_128 ', ' ', 'SHA'), CipherSuite(0x0006, 'RSA_EXPORT', ' ', 'RC2_40 ', 'CBC ', 'MD5', encoding='RC2_CBC_40'), CipherSuite(0x0007, 'RSA', ' ', 'IDEA ', 'CBC ', 'SHA'), CipherSuite(0x0008, 'RSA_EXPORT', ' ', 'DES40 ', 'CBC ', 'SHA'), CipherSuite(0x0009, 'RSA', ' ', 'DES ', 'CBC ', 'SHA'), CipherSuite(0x000a, 'RSA', ' ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0x000b, 'DH', 'DSS_EXPORT', 'DES40 ', 'CBC ', 'SHA'), CipherSuite(0x000c, 'DH', 'DSS ', 'DES ', 'CBC ', 'SHA'), CipherSuite(0x000d, 'DH', 'DSS ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0x000e, 'DH', 'RSA_EXPORT', 'DES40 ', 'CBC ', 'SHA'), CipherSuite(0x000f, 'DH', 'RSA ', 'DES ', 'CBC ', 'SHA'), CipherSuite(0x0010, 'DH', 'RSA ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0x0011, 'DHE', 'DSS_EXPORT', 'DES40 ', 'CBC ', 'SHA'), CipherSuite(0x0012, 'DHE', 'DSS ', 'DES ', 'CBC ', 'SHA'), CipherSuite(0x0013, 'DHE', 'DSS ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0x0014, 'DHE', 'RSA_EXPORT', 'DES40 ', 'CBC ', 'SHA'), CipherSuite(0x0015, 'DHE', 'RSA ', 'DES ', 'CBC ', 'SHA'), CipherSuite(0x0016, 'DHE', 'RSA ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0x0017, 'DH', 'anon_EXPORT', 'RC4_40 ', ' ', 'MD5'), CipherSuite(0x0018, 'DH', 'anon ', 'RC4_128 ', ' ', 'MD5'), CipherSuite(0x0019, 'DH', 'anon_EXPORT', 'DES40 ', 'CBC ', 'SHA'), CipherSuite(0x001a, 'DH', 'anon ', 'DES ', 'CBC ', 'SHA'), CipherSuite(0x001b, 'DH', 'anon ', '3DES_EDE', 'CBC ', 'SHA'), # Reserved: 0x1c-0x1d # RFC4346 : TLS 1.1 # RFC2712 CipherSuite(0x001e, 'KRB5', ' ', 'DES ', 'CBC ', 'SHA'), CipherSuite(0x001f, 'KRB5', ' ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0x0020, 'KRB5', ' ', 'RC4_128 ', ' ', 'SHA'), CipherSuite(0x0021, 'KRB5', ' ', 'IDEA ', 'CBC ', 'SHA'), CipherSuite(0x0022, 'KRB5', ' ', 'DES ', 'CBC ', 'MD5'), CipherSuite(0x0023, 'KRB5', ' ', '3DES_EDE', 'CBC ', 'MD5'), CipherSuite(0x0024, 'KRB5', ' ', 'RC4_128 ', ' ', 'MD5'), CipherSuite(0x0025, 'KRB5', ' ', 'IDEA ', 'CBC ', 'MD5'), CipherSuite(0x0026, 'KRB5_EXPORT', ' ', 'DES40 ', 'CBC ', 'SHA', encoding='DES_CBC_40'), CipherSuite(0x0027, 'KRB5_EXPORT', ' ', 'RC2_40 ', 'CBC ', 'SHA', encoding='RC2_CBC_40'), CipherSuite(0x0028, 'KRB5_EXPORT', ' ', 'RC4_40 ', ' ', 'SHA'), CipherSuite(0x0029, 'KRB5_EXPORT', ' ', 'DES40 ', 'CBC ', 'MD5', encoding='DES_CBC_40'), CipherSuite(0x002a, 'KRB5_EXPORT', ' ', 'RC2_40 ', 'CBC ', 'MD5', encoding='RC2_CBC_40'), CipherSuite(0x002b, 'KRB5_EXPORT', ' ', 'RC4_40 ', ' ', 'MD5'), # RFC4785 CipherSuite(0x002c, ' ', 'PSK ', 'NULL ', ' ', 'SHA'), CipherSuite(0x002d, 'DHE ', 'PSK ', 'NULL ', ' ', 'SHA'), CipherSuite(0x002e, 'RSA ', 'PSK ', 'NULL ', ' ', 'SHA'), # RFC3268 CipherSuite(0x002f, 'RSA ', ' ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0x0030, 'DH ', 'DSS ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0x0031, 'DH ', 'RSA ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0x0032, 'DHE ', 'DSS ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0x0033, 'DHE ', 'RSA ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0x0034, 'DH ', 'anon ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0x0035, 'RSA ', ' ', 'AES_256 ', 'CBC ', 'SHA'), CipherSuite(0x0036, 'DH ', 'DSS ', 'AES_256 ', 'CBC ', 'SHA'), CipherSuite(0x0037, 'DH ', 'RSA ', 'AES_256 ', 'CBC ', 'SHA'), CipherSuite(0x0038, 'DHE ', 'DSS ', 'AES_256 ', 'CBC ', 'SHA'), CipherSuite(0x0039, 'DHE ', 'RSA ', 'AES_256 ', 'CBC ', 'SHA'), CipherSuite(0x003a, 'DH ', 'anon ', 'AES_256 ', 'CBC ', 'SHA'), # RFC5246 : TLS 1.2 CipherSuite(0x003b, 'RSA ', ' ', 'NULL ', ' ', 'SHA256'), CipherSuite(0x003c, 'RSA ', ' ', 'AES_128 ', 'CBC ', 'SHA256'), CipherSuite(0x003d, 'RSA ', ' ', 'AES_256 ', 'CBC ', 'SHA256'), CipherSuite(0x003e, 'DH ', 'DSS ', 'AES_128 ', 'CBC ', 'SHA256'), CipherSuite(0x003f, 'DH ', 'RSA ', 'AES_128 ', 'CBC ', 'SHA256'), CipherSuite(0x0040, 'DHE ', 'DSS ', 'AES_128 ', 'CBC ', 'SHA256'), # RFC5932 CipherSuite(0x0041, 'RSA ', ' ', 'CAMELLIA_128', 'CBC', 'SHA'), CipherSuite(0x0042, 'DH ', 'DSS ', 'CAMELLIA_128', 'CBC', 'SHA'), CipherSuite(0x0043, 'DH ', 'RSA ', 'CAMELLIA_128', 'CBC', 'SHA'), CipherSuite(0x0044, 'DHE ', 'DSS ', 'CAMELLIA_128', 'CBC', 'SHA'), CipherSuite(0x0045, 'DHE ', 'RSA ', 'CAMELLIA_128', 'CBC', 'SHA'), CipherSuite(0x0046, 'DH ', 'anon ', 'CAMELLIA_128', 'CBC', 'SHA'), # Reserved: 0x47-5c # Unassigned: 0x5d-5f # Reserved: 0x60-66 # RFC5246 : TLS 1.2 CipherSuite(0x0067, 'DHE ', 'RSA ', 'AES_128 ', 'CBC ', 'SHA256'), CipherSuite(0x0068, 'DH ', 'DSS ', 'AES_256 ', 'CBC ', 'SHA256'), CipherSuite(0x0069, 'DH ', 'RSA ', 'AES_256 ', 'CBC ', 'SHA256'), CipherSuite(0x006a, 'DHE ', 'DSS ', 'AES_256 ', 'CBC ', 'SHA256'), CipherSuite(0x006b, 'DHE ', 'RSA ', 'AES_256 ', 'CBC ', 'SHA256'), CipherSuite(0x006c, 'DH ', 'anon ', 'AES_128 ', 'CBC ', 'SHA256'), CipherSuite(0x006d, 'DH ', 'anon ', 'AES_256 ', 'CBC ', 'SHA256'), # Unassigned: 0x6e-83 # RFC5932 CipherSuite(0x0084, 'RSA ', ' ', 'CAMELLIA_256', 'CBC', 'SHA'), CipherSuite(0x0085, 'DH ', 'DSS ', 'CAMELLIA_256', 'CBC', 'SHA'), CipherSuite(0x0086, 'DH ', 'RSA ', 'CAMELLIA_256', 'CBC', 'SHA'), CipherSuite(0x0087, 'DHE ', 'DSS ', 'CAMELLIA_256', 'CBC', 'SHA'), CipherSuite(0x0088, 'DHE ', 'RSA ', 'CAMELLIA_256', 'CBC', 'SHA'), CipherSuite(0x0089, 'DH ', 'anon ', 'CAMELLIA_256', 'CBC', 'SHA'), # RFC4279 CipherSuite(0x008a, ' ', 'PSK ', 'RC4_128 ', ' ', 'SHA'), CipherSuite(0x008b, ' ', 'PSK ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0x008c, ' ', 'PSK ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0x008d, ' ', 'PSK ', 'AES_256 ', 'CBC ', 'SHA'), CipherSuite(0x008e, 'DHE ', 'PSK ', 'RC4_128 ', ' ', 'SHA'), CipherSuite(0x008f, 'DHE ', 'PSK ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0x0090, 'DHE ', 'PSK ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0x0091, 'DHE ', 'PSK ', 'AES_256 ', 'CBC ', 'SHA'), CipherSuite(0x0092, 'RSA ', 'PSK ', 'RC4_128 ', ' ', 'SHA'), CipherSuite(0x0093, 'RSA ', 'PSK ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0x0094, 'RSA ', 'PSK ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0x0095, 'RSA ', 'PSK ', 'AES_256 ', 'CBC ', 'SHA'), # RFC4162 CipherSuite(0x0096, 'RSA ', ' ', 'SEED ', 'CBC ', 'SHA'), CipherSuite(0x0097, 'DH ', 'DSS ', 'SEED ', 'CBC ', 'SHA'), CipherSuite(0x0098, 'DH ', 'RSA ', 'SEED ', 'CBC ', 'SHA'), CipherSuite(0x0099, 'DHE ', 'DSS ', 'SEED ', 'CBC ', 'SHA'), CipherSuite(0x009a, 'DHE ', 'RSA ', 'SEED ', 'CBC ', 'SHA'), CipherSuite(0x009b, 'DH ', 'anon ', 'SEED ', 'CBC ', 'SHA'), # RFC5288 CipherSuite(0x009c, 'RSA ', ' ', 'AES_128 ', 'GCM ', 'SHA256'), CipherSuite(0x009d, 'RSA ', ' ', 'AES_256 ', 'GCM ', 'SHA384'), CipherSuite(0x009e, 'DHE ', 'RSA ', 'AES_128 ', 'GCM ', 'SHA256'), CipherSuite(0x009f, 'DHE ', 'RSA ', 'AES_256 ', 'GCM ', 'SHA384'), CipherSuite(0x00a0, 'DH ', 'RSA ', 'AES_128 ', 'GCM ', 'SHA256'), CipherSuite(0x00a1, 'DH ', 'RSA ', 'AES_256 ', 'GCM ', 'SHA384'), CipherSuite(0x00a2, 'DHE ', 'DSS ', 'AES_128 ', 'GCM ', 'SHA256'), CipherSuite(0x00a3, 'DHE ', 'DSS ', 'AES_256 ', 'GCM ', 'SHA384'), CipherSuite(0x00a4, 'DH ', 'DSS ', 'AES_128 ', 'GCM ', 'SHA256'), CipherSuite(0x00a5, 'DH ', 'DSS ', 'AES_256 ', 'GCM ', 'SHA384'), CipherSuite(0x00a6, 'DH ', 'anon ', 'AES_128 ', 'GCM ', 'SHA256'), CipherSuite(0x00a7, 'DH ', 'anon ', 'AES_256 ', 'GCM ', 'SHA384'), # RFC5487 CipherSuite(0x00a8, ' ', 'PSK ', 'AES_128 ', 'GCM ', 'SHA256'), CipherSuite(0x00a9, ' ', 'PSK ', 'AES_256 ', 'GCM ', 'SHA384'), CipherSuite(0x00aa, 'DHE ', 'PSK ', 'AES_128 ', 'GCM ', 'SHA256'), CipherSuite(0x00ab, 'DHE ', 'PSK ', 'AES_256 ', 'GCM ', 'SHA384'), CipherSuite(0x00ac, 'RSA ', 'PSK ', 'AES_128 ', 'GCM ', 'SHA256'), CipherSuite(0x00ad, 'RSA ', 'PSK ', 'AES_256 ', 'GCM ', 'SHA384'), CipherSuite(0x00ae, ' ', 'PSK ', 'AES_128 ', 'CBC ', 'SHA256'), CipherSuite(0x00af, ' ', 'PSK ', 'AES_256 ', 'CBC ', 'SHA384'), CipherSuite(0x00b0, ' ', 'PSK ', 'NULL ', ' ', 'SHA256'), CipherSuite(0x00b1, ' ', 'PSK ', 'NULL ', ' ', 'SHA384'), CipherSuite(0x00b2, 'DHE ', 'PSK ', 'AES_128 ', 'CBC ', 'SHA256'), CipherSuite(0x00b3, 'DHE ', 'PSK ', 'AES_256 ', 'CBC ', 'SHA384'), CipherSuite(0x00b4, 'DHE ', 'PSK ', 'NULL ', ' ', 'SHA256'), CipherSuite(0x00b5, 'DHE ', 'PSK ', 'NULL ', ' ', 'SHA384'), CipherSuite(0x00b6, 'RSA ', 'PSK ', 'AES_128 ', 'CBC ', 'SHA256'), CipherSuite(0x00b7, 'RSA ', 'PSK ', 'AES_256 ', 'CBC ', 'SHA384'), CipherSuite(0x00b8, 'RSA ', 'PSK ', 'NULL ', ' ', 'SHA256'), CipherSuite(0x00b9, 'RSA ', 'PSK ', 'NULL ', ' ', 'SHA384'), # RFC5932 CipherSuite(0x00ba, 'RSA ', ' ', 'CAMELLIA_128', 'CBC', 'SHA256'), CipherSuite(0x00bb, 'DH ', 'DSS ', 'CAMELLIA_128', 'CBC', 'SHA256'), CipherSuite(0x00bc, 'DH ', 'RSA ', 'CAMELLIA_128', 'CBC', 'SHA256'), CipherSuite(0x00bd, 'DHE ', 'DSS ', 'CAMELLIA_128', 'CBC', 'SHA256'), CipherSuite(0x00be, 'DHE ', 'RSA ', 'CAMELLIA_128', 'CBC', 'SHA256'), CipherSuite(0x00bf, 'DH ', 'anon ', 'CAMELLIA_128', 'CBC', 'SHA256'), CipherSuite(0x00c0, 'RSA ', ' ', 'CAMELLIA_256', 'CBC', 'SHA256'), CipherSuite(0x00c1, 'DH ', 'DSS ', 'CAMELLIA_256', 'CBC', 'SHA256'), CipherSuite(0x00c2, 'DH ', 'RSA ', 'CAMELLIA_256', 'CBC', 'SHA256'), CipherSuite(0x00c3, 'DHE ', 'DSS ', 'CAMELLIA_256', 'CBC', 'SHA256'), CipherSuite(0x00c4, 'DHE ', 'RSA ', 'CAMELLIA_256', 'CBC', 'SHA256'), CipherSuite(0x00c5, 'DH ', 'anon ', 'CAMELLIA_256', 'CBC', 'SHA256'), # RFC4492 CipherSuite(0xc001, 'ECDH ', 'ECDSA ', 'NULL ', ' ', 'SHA'), CipherSuite(0xc002, 'ECDH ', 'ECDSA ', 'RC4_128 ', ' ', 'SHA'), CipherSuite(0xc003, 'ECDH ', 'ECDSA ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0xc004, 'ECDH ', 'ECDSA ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0xc005, 'ECDH ', 'ECDSA ', 'AES_256 ', 'CBC ', 'SHA'), CipherSuite(0xc006, 'ECDHE', 'ECDSA ', 'NULL ', ' ', 'SHA'), CipherSuite(0xc007, 'ECDHE', 'ECDSA ', 'RC4_128 ', ' ', 'SHA'), CipherSuite(0xc008, 'ECDHE', 'ECDSA ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0xc009, 'ECDHE', 'ECDSA ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0xc00a, 'ECDHE', 'ECDSA ', 'AES_256 ', 'CBC ', 'SHA'), CipherSuite(0xc00b, 'ECDH ', 'RSA ', 'NULL ', ' ', 'SHA'), CipherSuite(0xc00c, 'ECDH ', 'RSA ', 'RC4_128 ', ' ', 'SHA'), CipherSuite(0xc00d, 'ECDH ', 'RSA ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0xc00e, 'ECDH ', 'RSA ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0xc00f, 'ECDH ', 'RSA ', 'AES_256 ', 'CBC ', 'SHA'), CipherSuite(0xc010, 'ECDHE', 'RSA ', 'NULL ', ' ', 'SHA'), CipherSuite(0xc011, 'ECDHE', 'RSA ', 'RC4_128 ', ' ', 'SHA'), CipherSuite(0xc012, 'ECDHE', 'RSA ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0xc013, 'ECDHE', 'RSA ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0xc014, 'ECDHE', 'RSA ', 'AES_256 ', 'CBC ', 'SHA'), CipherSuite(0xc015, 'ECDH ', 'anon ', 'NULL ', ' ', 'SHA'), CipherSuite(0xc016, 'ECDH ', 'anon ', 'RC4_128 ', ' ', 'SHA'), CipherSuite(0xc017, 'ECDH ', 'anon ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0xc018, 'ECDH ', 'anon ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0xc019, 'ECDH ', 'anon ', 'AES_256 ', 'CBC ', 'SHA'), # RFC5054 CipherSuite(0xc01a, 'SRP_SHA', ' ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0xc01b, 'SRP_SHA', 'RSA ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0xc01c, 'SRP_SHA', 'DSS ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0xc01d, 'SRP_SHA', ' ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0xc01e, 'SRP_SHA', 'RSA ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0xc01f, 'SRP_SHA', 'DSS ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0xc020, 'SRP_SHA', ' ', 'AES_256 ', 'CBC ', 'SHA'), CipherSuite(0xc021, 'SRP_SHA', 'RSA ', 'AES_256 ', 'CBC ', 'SHA'), CipherSuite(0xc022, 'SRP_SHA', 'DSS ', 'AES_256 ', 'CBC ', 'SHA'), # RFC5289 CipherSuite(0xc023, 'ECDHE', 'ECDSA ', 'AES_128 ', 'CBC ', 'SHA256'), CipherSuite(0xc024, 'ECDHE', 'ECDSA ', 'AES_256 ', 'CBC ', 'SHA384'), CipherSuite(0xc025, 'ECDH ', 'ECDSA ', 'AES_128 ', 'CBC ', 'SHA256'), CipherSuite(0xc026, 'ECDH ', 'ECDSA ', 'AES_256 ', 'CBC ', 'SHA384'), CipherSuite(0xc027, 'ECDHE', 'RSA ', 'AES_128 ', 'CBC ', 'SHA256'), CipherSuite(0xc028, 'ECDHE', 'RSA ', 'AES_256 ', 'CBC ', 'SHA384'), CipherSuite(0xc029, 'ECDH ', 'RSA ', 'AES_128 ', 'CBC ', 'SHA256'), CipherSuite(0xc02a, 'ECDH ', 'RSA ', 'AES_256 ', 'CBC ', 'SHA384'), CipherSuite(0xc02b, 'ECDHE', 'ECDSA ', 'AES_128 ', 'GCM ', 'SHA256'), CipherSuite(0xc02c, 'ECDHE', 'ECDSA ', 'AES_256 ', 'GCM ', 'SHA384'), CipherSuite(0xc02d, 'ECDH ', 'ECDSA ', 'AES_128 ', 'GCM ', 'SHA256'), CipherSuite(0xc02e, 'ECDH ', 'ECDSA ', 'AES_256 ', 'GCM ', 'SHA384'), CipherSuite(0xc02f, 'ECDHE', 'RSA ', 'AES_128 ', 'GCM ', 'SHA256'), CipherSuite(0xc030, 'ECDHE', 'RSA ', 'AES_256 ', 'GCM ', 'SHA384'), CipherSuite(0xc031, 'ECDH ', 'RSA ', 'AES_128 ', 'GCM ', 'SHA256'), CipherSuite(0xc032, 'ECDH ', 'RSA ', 'AES_256 ', 'GCM ', 'SHA384'), # RFC5489 CipherSuite(0xc033, 'ECDHE', 'PSK ', 'RC4_128 ', ' ', 'SHA'), CipherSuite(0xc034, 'ECDHE', 'PSK ', '3DES_EDE', 'CBC ', 'SHA'), CipherSuite(0xc035, 'ECDHE', 'PSK ', 'AES_128 ', 'CBC ', 'SHA'), CipherSuite(0xc036, 'ECDHE', 'PSK ', 'AES_256 ', 'CBC ', 'SHA'), CipherSuite(0xc037, 'ECDHE', 'PSK ', 'AES_128 ', 'CBC ', 'SHA256'), CipherSuite(0xc038, 'ECDHE', 'PSK ', 'AES_256 ', 'CBC ', 'SHA384'), CipherSuite(0xc039, 'ECDHE', 'PSK ', 'NULL ', ' ', 'SHA'), CipherSuite(0xc03a, 'ECDHE', 'PSK ', 'NULL ', ' ', 'SHA256'), CipherSuite(0xc03b, 'ECDHE', 'PSK ', 'NULL ', ' ', 'SHA384'), # RFC6209 CipherSuite(0xc03c, 'RSA ', ' ', 'ARIA_128', 'CBC ', 'SHA256'), CipherSuite(0xc03d, 'RSA ', ' ', 'ARIA_256', 'CBC ', 'SHA384'), CipherSuite(0xc03e, 'DH ', 'DSS ', 'ARIA_128', 'CBC ', 'SHA256'), CipherSuite(0xc03f, 'DH ', 'DSS ', 'ARIA_256', 'CBC ', 'SHA384'), CipherSuite(0xc040, 'DH ', 'RSA ', 'ARIA_128', 'CBC ', 'SHA256'), CipherSuite(0xc041, 'DH ', 'RSA ', 'ARIA_256', 'CBC ', 'SHA384'), CipherSuite(0xc042, 'DHE ', 'DSS ', 'ARIA_128', 'CBC ', 'SHA256'), CipherSuite(0xc043, 'DHE ', 'DSS ', 'ARIA_256', 'CBC ', 'SHA384'), CipherSuite(0xc044, 'DHE ', 'RSA ', 'ARIA_128', 'CBC ', 'SHA256'), CipherSuite(0xc045, 'DHE ', 'RSA ', 'ARIA_256', 'CBC ', 'SHA384'), CipherSuite(0xc046, 'DH ', 'anon ', 'ARIA_128', 'CBC ', 'SHA256'), CipherSuite(0xc047, 'DH ', 'anon ', 'ARIA_256', 'CBC ', 'SHA384'), CipherSuite(0xc048, 'ECDHE', 'ECDSA ', 'ARIA_128', 'CBC ', 'SHA256'), CipherSuite(0xc049, 'ECDHE', 'ECDSA ', 'ARIA_256', 'CBC ', 'SHA384'), CipherSuite(0xc04a, 'ECDH ', 'ECDSA ', 'ARIA_128', 'CBC ', 'SHA256'), CipherSuite(0xc04b, 'ECDH ', 'ECDSA ', 'ARIA_256', 'CBC ', 'SHA384'), CipherSuite(0xc04c, 'ECDHE', 'RSA ', 'ARIA_128', 'CBC ', 'SHA256'), CipherSuite(0xc04d, 'ECDHE', 'RSA ', 'ARIA_256', 'CBC ', 'SHA384'), CipherSuite(0xc04e, 'ECDH ', 'RSA ', 'ARIA_128', 'CBC ', 'SHA256'), CipherSuite(0xc04f, 'ECDH ', 'RSA ', 'ARIA_256', 'CBC ', 'SHA384'), CipherSuite(0xc050, 'RSA ', ' ', 'ARIA_128', 'GCM ', 'SHA256'), CipherSuite(0xc051, 'RSA ', ' ', 'ARIA_256', 'GCM ', 'SHA384'), CipherSuite(0xc052, 'DHE ', 'RSA ', 'ARIA_128', 'GCM ', 'SHA256'), CipherSuite(0xc053, 'DHE ', 'RSA ', 'ARIA_256', 'GCM ', 'SHA384'), CipherSuite(0xc054, 'DH ', 'RSA ', 'ARIA_128', 'GCM ', 'SHA256'), CipherSuite(0xc055, 'DH ', 'RSA ', 'ARIA_256', 'GCM ', 'SHA384'), CipherSuite(0xc056, 'DHE ', 'DSS ', 'ARIA_128', 'GCM ', 'SHA256'), CipherSuite(0xc057, 'DHE ', 'DSS ', 'ARIA_256', 'GCM ', 'SHA384'), CipherSuite(0xc058, 'DH ', 'DSS ', 'ARIA_128', 'GCM ', 'SHA256'), CipherSuite(0xc059, 'DH ', 'DSS ', 'ARIA_256', 'GCM ', 'SHA384'), CipherSuite(0xc05a, 'DH ', 'anon ', 'ARIA_128', 'GCM ', 'SHA256'), CipherSuite(0xc05b, 'DH ', 'anon ', 'ARIA_256', 'GCM ', 'SHA384'), CipherSuite(0xc05c, 'ECDHE', 'ECDSA ', 'ARIA_128', 'GCM ', 'SHA256'), CipherSuite(0xc05d, 'ECDHE', 'ECDSA ', 'ARIA_256', 'GCM ', 'SHA384'), CipherSuite(0xc05e, 'ECDH ', 'ECDSA ', 'ARIA_128', 'GCM ', 'SHA256'), CipherSuite(0xc05f, 'ECDH ', 'ECDSA ', 'ARIA_256', 'GCM ', 'SHA384'), CipherSuite(0xc060, 'ECDHE', 'RSA ', 'ARIA_128', 'GCM ', 'SHA256'), CipherSuite(0xc061, 'ECDHE', 'RSA ', 'ARIA_256', 'GCM ', 'SHA384'), CipherSuite(0xc062, 'ECDH ', 'RSA ', 'ARIA_128', 'GCM ', 'SHA256'), CipherSuite(0xc063, 'ECDH ', 'RSA ', 'ARIA_256', 'GCM ', 'SHA384'), CipherSuite(0xc064, ' ', 'PSK ', 'ARIA_128', 'CBC ', 'SHA256'), CipherSuite(0xc065, ' ', 'PSK ', 'ARIA_256', 'CBC ', 'SHA384'), CipherSuite(0xc066, 'DHE ', 'PSK ', 'ARIA_128', 'CBC ', 'SHA256'), CipherSuite(0xc067, 'DHE ', 'PSK ', 'ARIA_256', 'CBC ', 'SHA384'), CipherSuite(0xc068, 'RSA ', 'PSK ', 'ARIA_128', 'CBC ', 'SHA256'), CipherSuite(0xc069, 'RSA ', 'PSK ', 'ARIA_256', 'CBC ', 'SHA384'), CipherSuite(0xc06a, ' ', 'PSK ', 'ARIA_128', 'GCM ', 'SHA256'), CipherSuite(0xc06b, ' ', 'PSK ', 'ARIA_256', 'GCM ', 'SHA384'), CipherSuite(0xc06c, 'DHE ', 'PSK ', 'ARIA_128', 'GCM ', 'SHA256'), CipherSuite(0xc06d, 'DHE ', 'PSK ', 'ARIA_256', 'GCM ', 'SHA384'), CipherSuite(0xc06e, 'RSA ', 'PSK ', 'ARIA_128', 'GCM ', 'SHA256'), CipherSuite(0xc06f, 'RSA ', 'PSK ', 'ARIA_256', 'GCM ', 'SHA384'), CipherSuite(0xc070, 'ECDHE', 'PSK ', 'ARIA_128', 'GCM ', 'SHA256'), CipherSuite(0xc071, 'ECDHE', 'PSK ', 'ARIA_256', 'GCM ', 'SHA384'), # RFC6367 CipherSuite(0xc072, 'ECDHE', 'ECDSA ', 'CAMELLIA_128', 'CBC', 'SHA256'), CipherSuite(0xc073, 'ECDHE', 'ECDSA ', 'CAMELLIA_256', 'CBC', 'SHA384'), CipherSuite(0xc074, 'ECDH ', 'ECDSA ', 'CAMELLIA_128', 'CBC', 'SHA256'), CipherSuite(0xc075, 'ECDH ', 'ECDSA ', 'CAMELLIA_256', 'CBC', 'SHA384'), CipherSuite(0xc076, 'ECDHE', 'RSA ', 'CAMELLIA_128', 'CBC', 'SHA256'), CipherSuite(0xc077, 'ECDHE', 'RSA ', 'CAMELLIA_256', 'CBC', 'SHA384'), CipherSuite(0xc078, 'ECDH ', 'RSA ', 'CAMELLIA_128', 'CBC', 'SHA256'), CipherSuite(0xc079, 'ECDH ', 'RSA ', 'CAMELLIA_256', 'CBC', 'SHA384'), CipherSuite(0xc07a, 'RSA ', ' ', 'CAMELLIA_128', 'GCM', 'SHA256'), CipherSuite(0xc07b, 'RSA ', ' ', 'CAMELLIA_256', 'GCM', 'SHA384'), CipherSuite(0xc07c, 'DHE ', 'RSA ', 'CAMELLIA_128', 'GCM', 'SHA256'), CipherSuite(0xc07d, 'DHE ', 'RSA ', 'CAMELLIA_256', 'GCM', 'SHA384'), CipherSuite(0xc07e, 'DH ', 'RSA ', 'CAMELLIA_128', 'GCM', 'SHA256'), CipherSuite(0xc07f, 'DH ', 'RSA ', 'CAMELLIA_256', 'GCM', 'SHA384'), CipherSuite(0xc080, 'DHE ', 'DSS ', 'CAMELLIA_128', 'GCM', 'SHA256'), CipherSuite(0xc081, 'DHE ', 'DSS ', 'CAMELLIA_256', 'GCM', 'SHA384'), CipherSuite(0xc082, 'DH ', 'DSS ', 'CAMELLIA_128', 'GCM', 'SHA256'), CipherSuite(0xc083, 'DH ', 'DSS ', 'CAMELLIA_256', 'GCM', 'SHA384'), CipherSuite(0xc084, 'DH ', 'anon ', 'CAMELLIA_128', 'GCM', 'SHA256'), CipherSuite(0xc085, 'DH ', 'anon ', 'CAMELLIA_256', 'GCM', 'SHA384'), CipherSuite(0xc086, 'ECDHE', 'ECDSA ', 'CAMELLIA_128', 'GCM', 'SHA256'), CipherSuite(0xc087, 'ECDHE', 'ECDSA ', 'CAMELLIA_256', 'GCM', 'SHA384'), CipherSuite(0xc088, 'ECDH ', 'ECDSA ', 'CAMELLIA_128', 'GCM', 'SHA256'), CipherSuite(0xc089, 'ECDH ', 'ECDSA ', 'CAMELLIA_256', 'GCM', 'SHA384'), CipherSuite(0xc08a, 'ECDHE', 'RSA ', 'CAMELLIA_128', 'GCM', 'SHA256'), CipherSuite(0xc08b, 'ECDHE', 'RSA ', 'CAMELLIA_256', 'GCM', 'SHA384'), CipherSuite(0xc08c, 'ECDH ', 'RSA ', 'CAMELLIA_128', 'GCM', 'SHA256'), CipherSuite(0xc08d, 'ECDH ', 'RSA ', 'CAMELLIA_256', 'GCM', 'SHA384'), CipherSuite(0xc08e, ' ', 'PSK ', 'CAMELLIA_128', 'GCM', 'SHA256'), CipherSuite(0xc08f, ' ', 'PSK ', 'CAMELLIA_256', 'GCM', 'SHA384'), CipherSuite(0xc090, 'DHE ', 'PSK ', 'CAMELLIA_128', 'GCM', 'SHA256'), CipherSuite(0xc091, 'DHE ', 'PSK ', 'CAMELLIA_256', 'GCM', 'SHA384'), CipherSuite(0xc092, 'RSA ', 'PSK ', 'CAMELLIA_128', 'GCM', 'SHA256'), CipherSuite(0xc093, 'RSA ', 'PSK ', 'CAMELLIA_256', 'GCM', 'SHA384'), CipherSuite(0xc094, ' ', 'PSK ', 'CAMELLIA_128', 'CBC', 'SHA256'), CipherSuite(0xc095, ' ', 'PSK ', 'CAMELLIA_256', 'CBC', 'SHA384'), CipherSuite(0xc096, 'DHE ', 'PSK ', 'CAMELLIA_128', 'CBC', 'SHA256'), CipherSuite(0xc097, 'DHE ', 'PSK ', 'CAMELLIA_256', 'CBC', 'SHA384'), CipherSuite(0xc098, 'RSA ', 'PSK ', 'CAMELLIA_128', 'CBC', 'SHA256'), CipherSuite(0xc099, 'RSA ', 'PSK ', 'CAMELLIA_256', 'CBC', 'SHA384'), CipherSuite(0xc09a, 'ECDHE', 'PSK ', 'CAMELLIA_128', 'CBC', 'SHA256'), CipherSuite(0xc09b, 'ECDHE', 'PSK ', 'CAMELLIA_256', 'CBC', 'SHA384'), # RFC6655 CipherSuite(0xc09c, 'RSA ', ' ', 'AES_128 ', 'CCM ', ''), CipherSuite(0xc09d, 'RSA ', ' ', 'AES_256 ', 'CCM ', ''), CipherSuite(0xc09e, 'DHE ', 'RSA ', 'AES_128 ', 'CCM ', ''), CipherSuite(0xc09f, 'DHE ', 'RSA ', 'AES_256 ', 'CCM ', ''), CipherSuite(0xc0a0, 'RSA ', ' ', 'AES_128 ', 'CCM_8', ''), CipherSuite(0xc0a1, 'RSA ', ' ', 'AES_256 ', 'CCM_8', ''), CipherSuite(0xc0a2, 'DHE ', 'RSA ', 'AES_128 ', 'CCM_8', ''), CipherSuite(0xc0a3, 'DHE ', 'RSA ', 'AES_256 ', 'CCM_8', ''), CipherSuite(0xc0a4, ' ', 'PSK ', 'AES_128 ', 'CCM ', ''), CipherSuite(0xc0a5, ' ', 'PSK ', 'AES_256 ', 'CCM ', ''), CipherSuite(0xc0a6, 'DHE ', 'PSK ', 'AES_128 ', 'CCM ', ''), CipherSuite(0xc0a7, 'DHE ', 'PSK ', 'AES_256 ', 'CCM ', ''), CipherSuite(0xc0a8, ' ', 'PSK ', 'AES_128 ', 'CCM_8', ''), CipherSuite(0xc0a9, ' ', 'PSK ', 'AES_256 ', 'CCM_8', ''), CipherSuite(0xc0aa, 'DHE ', 'PSK ', 'AES_128 ', 'CCM_8', ''), CipherSuite(0xc0ab, 'DHE ', 'PSK ', 'AES_256 ', 'CCM_8', ''), # RFC7251 CipherSuite(0xc0ac, 'ECDHE', 'ECDSA ', 'AES_128 ', 'CCM ', ''), CipherSuite(0xc0ad, 'ECDHE', 'ECDSA ', 'AES_256 ', 'CCM ', ''), CipherSuite(0xc0ae, 'ECDHE', 'ECDSA ', 'AES_128 ', 'CCM_8', ''), CipherSuite(0xc0af, 'ECDHE', 'ECDSA ', 'AES_256 ', 'CCM_8', ''), # Unassigned: 0xc0b0-0xcca7 CipherSuite(0xcc13, 'ECDHE', 'RSA ', 'CHACHA20', 'POLY1305', 'SHA256', 'OLD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256'), CipherSuite(0xcc14, 'ECDHE', 'ECDSA ', 'CHACHA20', 'POLY1305', 'SHA256', 'OLD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256'), CipherSuite(0xcc15, 'DHE ', 'RSA ', 'CHACHA20', 'POLY1305', 'SHA256', 'OLD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256'), # RFC7905 CipherSuite(0xcca8, 'ECDHE', 'RSA ', 'CHACHA20', 'POLY1305', 'SHA256'), CipherSuite(0xcca9, 'ECDHE', 'ECDSA ', 'CHACHA20', 'POLY1305', 'SHA256'), CipherSuite(0xccaa, 'DHE ', 'RSA ', 'CHACHA20', 'POLY1305', 'SHA256'), CipherSuite(0xccab, ' ', 'PSK ', 'CHACHA20', 'POLY1305', 'SHA256'), CipherSuite(0xccac, 'ECDHE', 'PSK ', 'CHACHA20', 'POLY1305', 'SHA256'), CipherSuite(0xccad, 'DHE ', 'PSK ', 'CHACHA20', 'POLY1305', 'SHA256'), CipherSuite(0xccae, 'RSA ', 'PSK ', 'CHACHA20', 'POLY1305', 'SHA256'), # Unassigned: 0xccaf-0xfefd # Reserved: 0xfefe-0xffff ] BY_CODE = dict( (cipher.code, cipher) for cipher in CIPHERSUITES) # This is a function to avoid artificially increased coverage BY_NAME_DICT = None def BY_NAME(name): # We initialize the dictionary only on the first call global BY_NAME_DICT if BY_NAME_DICT is None: BY_NAME_DICT = dict((suite.name, suite) for suite in CIPHERSUITES) return BY_NAME_DICT[name] NULL_SUITE = BY_CODE[0x0000] class TestCipherSuites(object): def test_kx(self): # A test from each RFC assert (BY_CODE[0x0005].kx == 'RSA') assert (BY_CODE[0x0021].kx == 'KRB5') assert (BY_CODE[0x002d].kx == 'DHE') assert (BY_CODE[0x0034].kx == 'DH') assert (BY_CODE[0x003c].kx == 'RSA') assert (BY_CODE[0x0042].kx == 'DH') assert (BY_CODE[0x006a].kx == 'DHE') assert (BY_CODE[0x0084].kx == 'RSA') assert (BY_CODE[0x0091].kx == 'DHE') assert (BY_CODE[0x0098].kx == 'DH') assert (BY_CODE[0x00ab].kx == 'DHE') assert (BY_CODE[0x00b0].kx == 'PSK') assert (BY_CODE[0x00bb].kx == 'DH') assert (BY_CODE[0xc008].kx == 'ECDHE') assert (BY_CODE[0xc016].kx == 'ECDH') assert (BY_CODE[0xc01d].kx == 'SRP_SHA') assert (BY_CODE[0xc027].kx == 'ECDHE') assert (BY_CODE[0xc036].kx == 'ECDHE') assert (BY_CODE[0xc045].kx == 'DHE') assert (BY_CODE[0xc052].kx == 'DHE') assert (BY_CODE[0xc068].kx == 'RSA') assert (BY_CODE[0xc074].kx == 'ECDH') assert (BY_CODE[0xc08d].kx == 'ECDH') assert (BY_CODE[0xc09d].kx == 'RSA') assert (BY_CODE[0xc0a2].kx == 'DHE') assert (BY_CODE[0xc0ad].kx == 'ECDHE') assert (BY_CODE[0xcc13].kx == 'ECDHE') assert (BY_CODE[0xcca8].kx == 'ECDHE') assert (BY_CODE[0xccae].kx == 'RSA') def test_auth(self): # A test from each RFC assert (BY_CODE[0x0005].auth == 'RSA') assert (BY_CODE[0x0021].auth == 'KRB5') assert (BY_CODE[0x002d].auth == 'PSK') assert (BY_CODE[0x0034].auth == 'anon') assert (BY_CODE[0x003c].auth == 'RSA') assert (BY_CODE[0x0042].auth == 'DSS') assert (BY_CODE[0x006a].auth == 'DSS') assert (BY_CODE[0x0084].auth == 'RSA') assert (BY_CODE[0x0091].auth == 'PSK') assert (BY_CODE[0x0098].auth == 'RSA') assert (BY_CODE[0x00ab].auth == 'PSK') assert (BY_CODE[0x00b0].auth == 'PSK') assert (BY_CODE[0x00bb].auth == 'DSS') assert (BY_CODE[0xc008].auth == 'ECDSA') assert (BY_CODE[0xc016].auth == 'anon') assert (BY_CODE[0xc01d].auth == 'SRP_SHA') assert (BY_CODE[0xc027].auth == 'RSA') assert (BY_CODE[0xc036].auth == 'PSK') assert (BY_CODE[0xc045].auth == 'RSA') assert (BY_CODE[0xc052].auth == 'RSA') assert (BY_CODE[0xc068].auth == 'PSK') assert (BY_CODE[0xc074].auth == 'ECDSA') assert (BY_CODE[0xc08d].auth == 'RSA') assert (BY_CODE[0xc09d].auth == 'RSA') assert (BY_CODE[0xc0a2].auth == 'RSA') assert (BY_CODE[0xc0ad].auth == 'ECDSA') assert (BY_CODE[0xcc14].auth == 'ECDSA') assert (BY_CODE[0xcca8].auth == 'RSA') assert (BY_CODE[0xccae].auth == 'PSK') def test_by_name_and_code(self): # Special cases: # - explicit name assert (BY_CODE[0x00ff] == BY_NAME('TLS_EMPTY_RENEGOTIATION_INFO')) # - explicit encoding (DES_40 + CBC = DES_CBC_40) assert (BY_CODE[0x0026] == BY_NAME('TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA')) # A test from each RFC assert (BY_CODE[0x0005] == BY_NAME('TLS_RSA_WITH_RC4_128_SHA')) assert (BY_CODE[0x0021] == BY_NAME('TLS_KRB5_WITH_IDEA_CBC_SHA')) assert (BY_CODE[0x002d] == BY_NAME('TLS_DHE_PSK_WITH_NULL_SHA')) assert (BY_CODE[0x0034] == BY_NAME('TLS_DH_anon_WITH_AES_128_CBC_SHA')) assert (BY_CODE[0x003c] == BY_NAME('TLS_RSA_WITH_AES_128_CBC_SHA256')) assert (BY_CODE[0x0042] == BY_NAME('TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA')) assert (BY_CODE[0x006a] == BY_NAME('TLS_DHE_DSS_WITH_AES_256_CBC_SHA256')) assert (BY_CODE[0x0084] == BY_NAME('TLS_RSA_WITH_CAMELLIA_256_CBC_SHA')) assert (BY_CODE[0x0091] == BY_NAME('TLS_DHE_PSK_WITH_AES_256_CBC_SHA')) assert (BY_CODE[0x0098] == BY_NAME('TLS_DH_RSA_WITH_SEED_CBC_SHA')) assert (BY_CODE[0x00ab] == BY_NAME('TLS_DHE_PSK_WITH_AES_256_GCM_SHA384')) assert (BY_CODE[0x00b0] == BY_NAME('TLS_PSK_WITH_NULL_SHA256')) assert (BY_CODE[0x00bb] == BY_NAME('TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256')) assert (BY_CODE[0xc008] == BY_NAME('TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA')) assert (BY_CODE[0xc016] == BY_NAME('TLS_ECDH_anon_WITH_RC4_128_SHA')) assert (BY_CODE[0xc01d] == BY_NAME('TLS_SRP_SHA_WITH_AES_128_CBC_SHA')) assert (BY_CODE[0xc027] == BY_NAME('TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256')) assert (BY_CODE[0xc036] == BY_NAME('TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA')) assert (BY_CODE[0xc045] == BY_NAME('TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384')) assert (BY_CODE[0xc052] == BY_NAME('TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256')) assert (BY_CODE[0xc068] == BY_NAME('TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256')) assert (BY_CODE[0xc074] == BY_NAME('TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256')) assert (BY_CODE[0xc08d] == BY_NAME('TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384')) assert (BY_CODE[0xc09d] == BY_NAME('TLS_RSA_WITH_AES_256_CCM')) assert (BY_CODE[0xc0a2] == BY_NAME('TLS_DHE_RSA_WITH_AES_128_CCM_8')) assert (BY_CODE[0xc0ad] == BY_NAME('TLS_ECDHE_ECDSA_WITH_AES_256_CCM')) assert (BY_CODE[0xcca8] == BY_NAME('TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256')) assert (BY_CODE[0xccae] == BY_NAME('TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256')) assert (BY_CODE[0xcc15] == BY_NAME('OLD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256')) dpkt-1.9.2/dpkt/stp.py000066400000000000000000000036221340335175100146140ustar00rootroot00000000000000# $Id: stp.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Spanning Tree Protocol.""" from __future__ import print_function from __future__ import absolute_import from . import dpkt class STP(dpkt.Packet): """Spanning Tree Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of STP. TODO. """ __hdr__ = ( ('proto_id', 'H', 0), ('v', 'B', 0), ('type', 'B', 0), ('flags', 'B', 0), ('root_id', '8s', ''), ('root_path', 'I', 0), ('bridge_id', '8s', ''), ('port_id', 'H', 0), ('_age', 'H', 0), ('_max_age', 'H', 0), ('_hello', 'H', 0), ('_fd', 'H', 0) ) @property def age(self): return self._age >> 8 @age.setter def age(self, age): self._age = age << 8 @property def max_age(self): return self._max_age >> 8 @max_age.setter def max_age(self, max_age): self._max_age = max_age << 8 @property def hello(self): return self._hello >> 8 @hello.setter def hello(self, hello): self._hello = hello << 8 @property def fd(self): return self._fd >> 8 @fd.setter def fd(self, fd): self._fd = fd << 8 def test_stp(): buf = b'\x00\x00\x02\x02\x3e\x80\x00\x08\x00\x27\xad\xa3\x41\x00\x00\x00\x00\x80\x00\x08\x00\x27\xad\xa3\x41\x80\x01\x00\x00\x14\x00\x02\x00\x0f\x00\x00\x00\x00\x00\x02\x00\x14\x00' stp = STP(buf) assert stp.proto_id == 0 assert stp.port_id == 0x8001 assert stp.age == 0 assert stp.max_age == 20 assert stp.hello == 2 assert stp.fd == 15 assert bytes(stp) == buf stp.fd = 100 assert stp.pack_hdr()[-2:] == b'\x64\x00' # 100 << 8 if __name__ == '__main__': # Runs all the test associated with this class/file test_stp() print('Tests Successful...') dpkt-1.9.2/dpkt/stun.py000066400000000000000000000054061340335175100150010ustar00rootroot00000000000000# $Id: stun.py 47 2008-05-27 02:10:00Z jon.oberheide $ # -*- coding: utf-8 -*- """Simple Traversal of UDP through NAT.""" from __future__ import print_function from __future__ import absolute_import import struct from . import dpkt # STUN - RFC 3489 # http://tools.ietf.org/html/rfc3489 # Each packet has a 20 byte header followed by 0 or more attribute TLVs. # Message Types BINDING_REQUEST = 0x0001 BINDING_RESPONSE = 0x0101 BINDING_ERROR_RESPONSE = 0x0111 SHARED_SECRET_REQUEST = 0x0002 SHARED_SECRET_RESPONSE = 0x0102 SHARED_SECRET_ERROR_RESPONSE = 0x0112 # Message Attributes MAPPED_ADDRESS = 0x0001 RESPONSE_ADDRESS = 0x0002 CHANGE_REQUEST = 0x0003 SOURCE_ADDRESS = 0x0004 CHANGED_ADDRESS = 0x0005 USERNAME = 0x0006 PASSWORD = 0x0007 MESSAGE_INTEGRITY = 0x0008 ERROR_CODE = 0x0009 UNKNOWN_ATTRIBUTES = 0x000a REFLECTED_FROM = 0x000b class STUN(dpkt.Packet): """Simple Traversal of UDP through NAT. STUN - RFC 3489 http://tools.ietf.org/html/rfc3489 Each packet has a 20 byte header followed by 0 or more attribute TLVs. Attributes: __hdr__: Header fields of STUN. TODO. """ __hdr__ = ( ('type', 'H', 0), ('len', 'H', 0), ('xid', '16s', 0) ) def tlv(buf): n = 4 t, l = struct.unpack('>HH', buf[:n]) v = buf[n:n + l] pad = (n - l % n) % n buf = buf[n + l + pad:] return t, l, v, buf def parse_attrs(buf): """Parse STUN.data buffer into a list of (attribute, data) tuples.""" attrs = [] while buf: t, _, v, buf = tlv(buf) attrs.append((t, v)) return attrs def test_stun_response(): s = b'\x01\x01\x00\x0c\x21\x12\xa4\x42\x53\x4f\x70\x43\x69\x69\x35\x4a\x66\x63\x31\x7a\x00\x01\x00\x08\x00\x01\x11\x22\x33\x44\x55\x66' m = STUN(s) assert m.type == BINDING_RESPONSE assert m.len == 12 attrs = parse_attrs(m.data) assert attrs == [(MAPPED_ADDRESS, b'\x00\x01\x11\x22\x33\x44\x55\x66'), ] def test_stun_padded(): s = (b'\x00\x01\x00\x54\x21\x12\xa4\x42\x35\x59\x53\x6e\x42\x71\x70\x56\x77\x61\x39\x4f\x00\x06' b'\x00\x17\x70\x4c\x79\x5a\x48\x52\x3a\x47\x77\x4c\x33\x41\x48\x42\x6f\x76\x75\x62\x4c\x76' b'\x43\x71\x6e\x00\x80\x2a\x00\x08\x18\x8b\x10\x4c\x69\x7b\xf6\x5b\x00\x25\x00\x00\x00\x24' b'\x00\x04\x6e\x00\x1e\xff\x00\x08\x00\x14\x60\x2b\xc7\xfc\x0d\x10\x63\xaa\xc5\x38\x1c\xcb' b'\x96\xa9\x73\x08\x73\x9a\x96\x0c\x80\x28\x00\x04\xd1\x62\xea\x65') m = STUN(s) assert m.type == BINDING_REQUEST assert m.len == 84 attrs = parse_attrs(m.data) assert len(attrs) == 6 assert attrs[0] == (USERNAME, b'pLyZHR:GwL3AHBovubLvCqn') assert attrs[4][0] == MESSAGE_INTEGRITY if __name__ == '__main__': test_stun_response() test_stun_padded() print('Tests Successful...') dpkt-1.9.2/dpkt/tcp.py000066400000000000000000000115541340335175100145770ustar00rootroot00000000000000# $Id: tcp.py 42 2007-08-02 22:38:47Z jon.oberheide $ # -*- coding: utf-8 -*- """Transmission Control Protocol.""" from __future__ import print_function from __future__ import absolute_import from . import dpkt from .decorators import deprecated from .compat import compat_ord # TCP control flags TH_FIN = 0x01 # end of data TH_SYN = 0x02 # synchronize sequence numbers TH_RST = 0x04 # reset connection TH_PUSH = 0x08 # push TH_ACK = 0x10 # acknowledgment number set TH_URG = 0x20 # urgent pointer set TH_ECE = 0x40 # ECN echo, RFC 3168 TH_CWR = 0x80 # congestion window reduced TCP_PORT_MAX = 65535 # maximum port TCP_WIN_MAX = 65535 # maximum (unscaled) window class TCP(dpkt.Packet): """Transmission Control Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of TCP. TODO. """ __hdr__ = ( ('sport', 'H', 0xdead), ('dport', 'H', 0), ('seq', 'I', 0xdeadbeef), ('ack', 'I', 0), ('_off', 'B', ((5 << 4) | 0)), ('flags', 'B', TH_SYN), ('win', 'H', TCP_WIN_MAX), ('sum', 'H', 0), ('urp', 'H', 0) ) opts = b'' @property def off(self): return self._off >> 4 @off.setter def off(self, off): self._off = (off << 4) | (self._off & 0xf) def __len__(self): return self.__hdr_len__ + len(self.opts) + len(self.data) def __bytes__(self): return self.pack_hdr() + bytes(self.opts) + bytes(self.data) def unpack(self, buf): dpkt.Packet.unpack(self, buf) ol = ((self._off >> 4) << 2) - self.__hdr_len__ if ol < 0: raise dpkt.UnpackError('invalid header length') self.opts = buf[self.__hdr_len__:self.__hdr_len__ + ol] self.data = buf[self.__hdr_len__ + ol:] # Options (opt_type) - http://www.iana.org/assignments/tcp-parameters TCP_OPT_EOL = 0 # end of option list TCP_OPT_NOP = 1 # no operation TCP_OPT_MSS = 2 # maximum segment size TCP_OPT_WSCALE = 3 # window scale factor, RFC 1072 TCP_OPT_SACKOK = 4 # SACK permitted, RFC 2018 TCP_OPT_SACK = 5 # SACK, RFC 2018 TCP_OPT_ECHO = 6 # echo (obsolete), RFC 1072 TCP_OPT_ECHOREPLY = 7 # echo reply (obsolete), RFC 1072 TCP_OPT_TIMESTAMP = 8 # timestamp, RFC 1323 TCP_OPT_POCONN = 9 # partial order conn, RFC 1693 TCP_OPT_POSVC = 10 # partial order service, RFC 1693 TCP_OPT_CC = 11 # connection count, RFC 1644 TCP_OPT_CCNEW = 12 # CC.NEW, RFC 1644 TCP_OPT_CCECHO = 13 # CC.ECHO, RFC 1644 TCP_OPT_ALTSUM = 14 # alt checksum request, RFC 1146 TCP_OPT_ALTSUMDATA = 15 # alt checksum data, RFC 1146 TCP_OPT_SKEETER = 16 # Skeeter TCP_OPT_BUBBA = 17 # Bubba TCP_OPT_TRAILSUM = 18 # trailer checksum TCP_OPT_MD5 = 19 # MD5 signature, RFC 2385 TCP_OPT_SCPS = 20 # SCPS capabilities TCP_OPT_SNACK = 21 # selective negative acks TCP_OPT_REC = 22 # record boundaries TCP_OPT_CORRUPT = 23 # corruption experienced TCP_OPT_SNAP = 24 # SNAP TCP_OPT_TCPCOMP = 26 # TCP compression filter TCP_OPT_MAX = 27 def parse_opts(buf): """Parse TCP option buffer into a list of (option, data) tuples.""" opts = [] while buf: o = compat_ord(buf[0]) if o > TCP_OPT_NOP: try: # advance buffer at least 2 bytes = 1 type + 1 length l = max(2, compat_ord(buf[1])) d, buf = buf[2:l], buf[l:] except (IndexError, ValueError): # print 'bad option', repr(str(buf)) opts.append(None) # XXX break else: # options 0 and 1 are not followed by length byte d, buf = b'', buf[1:] opts.append((o, d)) return opts def test_parse_opts(): # normal scenarios buf = b'\x02\x04\x23\x00\x01\x01\x04\x02' opts = parse_opts(buf) assert opts == [ (TCP_OPT_MSS, b'\x23\x00'), (TCP_OPT_NOP, b''), (TCP_OPT_NOP, b''), (TCP_OPT_SACKOK, b'') ] buf = b'\x01\x01\x05\x0a\x37\xf8\x19\x70\x37\xf8\x29\x78' opts = parse_opts(buf) assert opts == [ (TCP_OPT_NOP, b''), (TCP_OPT_NOP, b''), (TCP_OPT_SACK, b'\x37\xf8\x19\x70\x37\xf8\x29\x78') ] # test a zero-length option buf = b'\x02\x00\x01' opts = parse_opts(buf) assert opts == [ (TCP_OPT_MSS, b''), (TCP_OPT_NOP, b'') ] # test a one-byte malformed option buf = b'\xff' opts = parse_opts(buf) assert opts == [None] def test_offset(): tcpheader = TCP(b'\x01\xbb\xc0\xd7\xb6\x56\xa8\xb9\xd1\xac\xaa\xb1\x50\x18\x40\x00\x56\xf8\x00\x00') assert tcpheader.off == 5 # test setting header offset tcpheader.off = 8 assert bytes(tcpheader) == b'\x01\xbb\xc0\xd7\xb6\x56\xa8\xb9\xd1\xac\xaa\xb1\x80\x18\x40\x00\x56\xf8\x00\x00' if __name__ == '__main__': # Runs all the test associated with this class/file test_parse_opts() test_offset() print('Tests Successful...') dpkt-1.9.2/dpkt/telnet.py000066400000000000000000000075471340335175100153130ustar00rootroot00000000000000# $Id: telnet.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Telnet.""" from __future__ import print_function from __future__ import absolute_import import struct from .compat import compat_ord IAC = 255 # interpret as command: DONT = 254 # you are not to use option DO = 253 # please, you use option WONT = 252 # I won't use option WILL = 251 # I will use option SB = 250 # interpret as subnegotiation GA = 249 # you may reverse the line EL = 248 # erase the current line EC = 247 # erase the current character AYT = 246 # are you there AO = 245 # abort output--but let prog finish IP = 244 # interrupt process--permanently BREAK = 243 # break DM = 242 # data mark--for connect. cleaning NOP = 241 # nop SE = 240 # end sub negotiation EOR = 239 # end of record (transparent mode) ABORT = 238 # Abort process SUSP = 237 # Suspend process xEOF = 236 # End of file: EOF is already used... SYNCH = 242 # for telfunc calls def strip_options(buf): """Return a list of lines and dict of options from telnet data.""" l = buf.split(struct.pack("B", IAC)) # print l b = [] d = {} subopt = False for w in l: if not w: continue o = compat_ord(w[0]) if o > SB: # print 'WILL/WONT/DO/DONT/IAC', `w` w = w[2:] elif o == SE: # print 'SE', `w` w = w[1:] subopt = False elif o == SB: # print 'SB', `w` subopt = True for opt in (b'USER', b'DISPLAY', b'TERM'): p = w.find(opt + b'\x01') if p != -1: d[opt] = w[p + len(opt) + 1:].split(b'\x00', 1)[0] w = None elif subopt: w = None if w: w = w.replace(b'\x00', b'\n').splitlines() if not w[-1]: w.pop() b.extend(w) return b, d def test_telnet(): l = [] s = b"\xff\xfb%\xff\xfa%\x00\x00\x00\xff\xf0\xff\xfd&\xff\xfa&\x05\xff\xf0\xff\xfa&\x01\x01\x02\xff\xf0\xff\xfb\x18\xff\xfb \xff\xfb#\xff\xfb'\xff\xfc$\xff\xfa \x0038400,38400\xff\xf0\xff\xfa#\x00doughboy.citi.umich.edu:0.0\xff\xf0\xff\xfa'\x00\x00DISPLAY\x01doughboy.citi.umich.edu:0.0\x00USER\x01dugsong\xff\xf0\xff\xfa\x18\x00XTERM\xff\xf0\xff\xfd\x03\xff\xfc\x01\xff\xfb\x1f\xff\xfa\x1f\x00P\x00(\xff\xf0\xff\xfd\x05\xff\xfb!\xff\xfd\x01fugly\r\x00yoda\r\x00bashtard\r\x00" l.append(s) s = b'\xff\xfd\x01\xff\xfd\x03\xff\xfb\x18\xff\xfb\x1f\xff\xfa\x1f\x00X\x002\xff\xf0admin\r\x00\xff\xfa\x18\x00LINUX\xff\xf0foobar\r\x00enable\r\x00foobar\r\x00\r\x00show ip int Vlan 666\r\x00' l.append(s) s = b'\xff\xfb%\xff\xfa%\x00\x00\x00\xff\xf0\xff\xfd&\xff\xfa&\x05\xff\xf0\xff\xfa&\x01\x01\x02\xff\xf0\xff\xfb&\xff\xfb\x18\xff\xfb \xff\xfb#\xff\xfb\'\xff\xfc$\xff\xfa \x0038400,38400\xff\xf0\xff\xfa#\x00doughboy.citi.umich.edu:0.0\xff\xf0\xff\xfa\'\x00\x00DISPLAY\x01doughboy.citi.umich.edu:0.0\x00USER\x01dugsong\xff\xf0\xff\xfa\x18\x00XTERM\xff\xf0\xff\xfd\x03\xff\xfc\x01\xff\xfb"\xff\xfa"\x03\x01\x03\x00\x03b\x03\x04\x02\x0f\x05\x00\xff\xff\x07b\x1c\x08\x02\x04\tB\x1a\n\x02\x7f\x0b\x02\x15\x0c\x02\x17\r\x02\x12\x0e\x02\x16\x0f\x02\x11\x10\x02\x13\x11\x00\xff\xff\x12\x00\xff\xff\xff\xf0\xff\xfb\x1f\xff\xfa\x1f\x00P\x00(\xff\xf0\xff\xfd\x05\xff\xfb!\xff\xfa"\x01\x0f\xff\xf0\xff\xfd\x01\xff\xfe\x01\xff\xfa"\x03\x01\x80\x00\xff\xf0\xff\xfd\x01werd\r\n\xff\xfe\x01yoda\r\n\xff\xfd\x01darthvader\r\n\xff\xfe\x01' l.append(s) exp = [([b'fugly', b'yoda', b'bashtard'], {b'USER': b'dugsong', b'DISPLAY': b'doughboy.citi.umich.edu:0.0'}), ([b'admin', b'foobar', b'enable', b'foobar', b'', b'show ip int Vlan 666'], {}), ([b'werd', b'yoda', b'darthvader'], {b'USER': b'dugsong', b'DISPLAY': b'doughboy.citi.umich.edu:0.0'})] assert (list(map(strip_options, l)) == exp) if __name__ == '__main__': test_telnet() print('Tests Successful...') dpkt-1.9.2/dpkt/tftp.py000066400000000000000000000050171340335175100147630ustar00rootroot00000000000000# $Id: tftp.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Trivial File Transfer Protocol.""" from __future__ import print_function from __future__ import absolute_import import struct from . import dpkt # Opcodes OP_RRQ = 1 # read request OP_WRQ = 2 # write request OP_DATA = 3 # data packet OP_ACK = 4 # acknowledgment OP_ERR = 5 # error code # Error codes EUNDEF = 0 # not defined ENOTFOUND = 1 # file not found EACCESS = 2 # access violation ENOSPACE = 3 # disk full or allocation exceeded EBADOP = 4 # illegal TFTP operation EBADID = 5 # unknown transfer ID EEXISTS = 6 # file already exists ENOUSER = 7 # no such user class TFTP(dpkt.Packet): """Trivial File Transfer Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of TFTP. TODO. """ __hdr__ = (('opcode', 'H', 1), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) if self.opcode in (OP_RRQ, OP_WRQ): l = self.data.split(b'\x00') self.filename = l[0] self.mode = l[1] self.data = b'' elif self.opcode in (OP_DATA, OP_ACK): self.block = struct.unpack('>H', self.data[:2])[0] self.data = self.data[2:] elif self.opcode == OP_ERR: self.errcode = struct.unpack('>H', self.data[:2]) self.errmsg = self.data[2:].split(b'\x00')[0] self.data = b'' def __len__(self): return len(bytes(self)) def __bytes__(self): if self.opcode in (OP_RRQ, OP_WRQ): s = self.filename + b'\x00' + self.mode + b'\x00' elif self.opcode in (OP_DATA, OP_ACK): s = struct.pack('>H', self.block) elif self.opcode == OP_ERR: s = struct.pack('>H', self.errcode) + (b'%s\x00' % self.errmsg) else: s = b'' return self.pack_hdr() + s + self.data def test_op_rrq(): s = b'\x00\x01\x72\x66\x63\x31\x33\x35\x30\x2e\x74\x78\x74\x00\x6f\x63\x74\x65\x74\x00' t = TFTP(s) assert t.filename == b'rfc1350.txt' assert t.mode == b'octet' assert bytes(t) == s def test_op_data(): s = b'\x00\x03\x00\x01\x0a\x0a\x4e\x65\x74\x77\x6f\x72\x6b\x20\x57\x6f\x72\x6b\x69\x6e\x67\x20\x47\x72\x6f\x75\x70' t = TFTP(s) assert t.block == 1 assert t.data == b'\x0a\x0aNetwork Working Group' assert bytes(t) == s def test_op_err(): pass # XXX - TODO if __name__ == '__main__': test_op_rrq() test_op_data() test_op_err() print('Tests Successful...') dpkt-1.9.2/dpkt/tns.py000066400000000000000000000024541340335175100146140ustar00rootroot00000000000000# $Id: tns.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Transparent Network Substrate.""" from __future__ import print_function from __future__ import absolute_import from . import dpkt class TNS(dpkt.Packet): """Transparent Network Substrate. TODO: Longer class information.... Attributes: __hdr__: Header fields of TNS. TODO. """ __hdr__ = ( ('length', 'H', 0), ('pktsum', 'H', 0), ('type', 'B', 0), ('rsvd', 'B', 0), ('hdrsum', 'H', 0), ('msg', '0s', ''), ) def unpack(self, buf): dpkt.Packet.unpack(self, buf) n = self.length - self.__hdr_len__ if n > len(self.data): raise dpkt.NeedData('short message (missing %d bytes)' % (n - len(self.data))) self.msg = self.data[:n] self.data = self.data[n:] def test_tns(): s = (b'\x00\x23\x00\x00\x01\x00\x00\x00\x01\x34\x01\x2c\x00\x00\x08\x00\x7f' b'\xff\x4f\x98\x00\x00\x00\x01\x00\x01\x00\x22\x00\x00\x00\x00\x01\x01X') t = TNS(s) assert t.msg.startswith(b'\x01\x34') # test a truncated packet try: t = TNS(s[:-10]) except dpkt.NeedData: pass if __name__ == '__main__': test_tns() print('Tests Successful...') dpkt-1.9.2/dpkt/tpkt.py000066400000000000000000000010541340335175100147650ustar00rootroot00000000000000# $Id: tpkt.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """ISO Transport Service on top of the TCP (TPKT).""" from __future__ import absolute_import from . import dpkt # TPKT - RFC 1006 Section 6 # http://www.faqs.org/rfcs/rfc1006.html class TPKT(dpkt.Packet): """ISO Transport Service on top of the TCP (TPKT). TODO: Longer class information.... Attributes: __hdr__: Header fields of TPKT. TODO. """ __hdr__ = ( ('v', 'B', 3), ('rsvd', 'B', 0), ('len', 'H', 0) ) dpkt-1.9.2/dpkt/udp.py000066400000000000000000000007761340335175100146050ustar00rootroot00000000000000# $Id: udp.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """User Datagram Protocol.""" from __future__ import absolute_import from . import dpkt UDP_HDR_LEN = 8 UDP_PORT_MAX = 65535 class UDP(dpkt.Packet): """User Datagram Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of UDP. TODO. """ __hdr__ = ( ('sport', 'H', 0xdead), ('dport', 'H', 0), ('ulen', 'H', 8), ('sum', 'H', 0) ) dpkt-1.9.2/dpkt/vrrp.py000066400000000000000000000045001340335175100147730ustar00rootroot00000000000000# $Id: vrrp.py 88 2013-03-05 19:43:17Z andrewflnr@gmail.com $ # -*- coding: utf-8 -*- """Virtual Router Redundancy Protocol.""" from __future__ import print_function from __future__ import absolute_import from . import dpkt from .decorators import deprecated class VRRP(dpkt.Packet): """Virtual Router Redundancy Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of VRRP. TODO. """ __hdr__ = ( ('_v_type', 'B', 0x21), ('vrid', 'B', 0), ('priority', 'B', 0), ('count', 'B', 0), ('atype', 'B', 0), ('advtime', 'B', 0), ('sum', 'H', 0), ) addrs = () auth = '' @property def v(self): # high 4 bits of _v_type return self._v_type >> 4 @v.setter def v(self, v): self._v_type = (self._v_type & 0x0f) | (v << 4) @property def type(self): # low 4 bits of _v_type return self._v_type & 0x0f @type.setter def type(self, v): self._v_type = (self._v_type & 0xf0) | (v & 0x0f) def unpack(self, buf): dpkt.Packet.unpack(self, buf) l = [] off = 0 for off in range(0, 4 * self.count, 4): l.append(self.data[off:off + 4]) self.addrs = l self.auth = self.data[off + 4:] self.data = '' def __len__(self): return self.__hdr_len__ + (4 * self.count) + len(self.auth) def __bytes__(self): data = b''.join(self.addrs) + self.auth if not self.sum: self.sum = dpkt.in_cksum(self.pack_hdr() + data) return self.pack_hdr() + data def test_vrrp(): # no addresses s = b'\x00\x00\x00\x00\x00\x00\xff\xff' v = VRRP(s) assert v.sum == 0xffff assert bytes(v) == s # have address s = b'\x21\x01\x64\x01\x00\x01\xba\x52\xc0\xa8\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00' v = VRRP(s) assert v.count == 1 assert v.addrs == [b'\xc0\xa8\x00\x01'] # 192.168.0.1 assert bytes(v) == s # test checksum generation v.sum = 0 assert bytes(v) == s # test length assert len(v) == len(s) # test getters assert v.v == 2 assert v.type == 1 # test setters v.v = 3 v.type = 2 assert bytes(v)[0] == b'\x32'[0] if __name__ == '__main__': test_vrrp() print('Tests Successful...') dpkt-1.9.2/dpkt/yahoo.py000066400000000000000000000015351340335175100151260ustar00rootroot00000000000000# $Id: yahoo.py 23 2006-11-08 15:45:33Z dugsong $ # -*- coding: utf-8 -*- """Yahoo Messenger.""" from __future__ import absolute_import from . import dpkt class YHOO(dpkt.Packet): """Yahoo Messenger. TODO: Longer class information.... Attributes: __hdr__: Header fields of Yahoo Messenger. TODO. """ __hdr__ = [ ('version', '8s', ' ' * 8), ('length', 'I', 0), ('service', 'I', 0), ('connid', 'I', 0), ('magic', 'I', 0), ('unknown', 'I', 0), ('type', 'I', 0), ('nick1', '36s', ' ' * 36), ('nick2', '36s', ' ' * 36) ] __byte_order__ = '<' class YMSG(dpkt.Packet): __hdr__ = [ ('version', '8s', ' ' * 8), ('length', 'H', 0), ('type', 'H', 0), ('unknown1', 'I', 0), ('unknown2', 'I', 0) ] dpkt-1.9.2/examples/000077500000000000000000000000001340335175100143055ustar00rootroot00000000000000dpkt-1.9.2/examples/__init__.py000066400000000000000000000000001340335175100164040ustar00rootroot00000000000000dpkt-1.9.2/examples/data/000077500000000000000000000000001340335175100152165ustar00rootroot00000000000000dpkt-1.9.2/examples/data/README.md000066400000000000000000000006131340335175100164750ustar00rootroot00000000000000### PCAP Data A good resource for PCAP data is : [https://wiki.wireshark.org/SampleCaptures]() - #### http.pcap: A simple HTTP request and response - #### nb6-http.pcap: provided by french ISP SFR, there are three different HTTP requests: first was sent on the private IPv4 network (IPoE), second was sent on the public IPv4 network, third was sent on the public IPv6 network (L2TP tunnel). dpkt-1.9.2/examples/data/dns_icmp.pcap000066400000000000000000000070641340335175100176660ustar00rootroot00000000000000ò}֧Q"PP;`3KXEBЦ@ҩ+ +5.hR8888in-addrarpa }֧Q8||`3KX;En@@c$++ 5ZR8888in-addrarpa   google-public-dns-agooglecom}֧Q3Rbb;`3KXET&@W+ ;Q}Q  !"#$%&'()*+,-./01234567}֧Q bb`3KX;ET(+ ó;Q}Q  !"#$%&'()*+,-./01234567~֧Qwibb;`3KXET@$+ h;Q~V-  !"#$%&'()*+,-./01234567~֧QRvbb`3KX;ET(+ h;Q~V-  !"#$%&'()*+,-./01234567֧Q!Ybb;`3KXET@d + ;QX  !"#$%&'()*+,-./01234567֧Qbb`3KX;ET(+ ;QX  !"#$%&'()*+,-./01234567֧QOPP;`3KXEB%@}Z+ +5.i]4488in-addrarpa ֧Q|||`3KX;En@@c$++ 5ZAi]4488in-addrarpa  ] google-public-dns-bgooglecom֧Qbb;`3KXET@$+ +;Qրݘ  !"#$%&'()*+,-./01234567֧QRbb;`3KXET@+ (;Qց  !"#$%&'()*+,-./01234567֧Q bb`3KX;ET(+ 0;Qց  !"#$%&'()*+,-./01234567֧Q.bb;`3KXET*@W+ $;Qւ  !"#$%&'()*+,-./01234567֧QPP;`3KXEB@g+ +5.:2224in-addrarpa ֧Q<tt`3KX;Ef@@c,++ 5R:2224in-addrarpa  b resolversLevel3net֧QQbb;`3KXET@-+ ;QքP  !"#$%&'()*+,-./01234567֧Qcbb`3KX;ET2p+ ;QքP  !"#$%&'()*+,-./01234567֧QSbb;`3KXET@+ ;QօS  !"#$%&'()*+,-./01234567֧Q bb`3KX;ET2o+ ;QօS  !"#$%&'()*+,-./01234567֧QVbb;`3KXETV@2.+ ;QֆU  !"#$%&'()*+,-./01234567֧Qebb`3KX;ET2n+ ;QֆU  !"#$%&'()*+,-./01234567֧Q݈MM;`3KXE?@+ +â5+T!!www wiresharkorg֧Q]]`3KX;EO@@cC++ 5â;!!www wiresharkorg X*A֧Qv"MM;`3KXE?dk+ +c5+\,Xwww wiresharkorg֧QH]]`3KX;EO@@cC++ 5c;,Xwww wiresharkorg X*A֧Q+bb;`3KXET@G+ *A;Qֈ  !"#$%&'()*+,-./01234567֧Q bb`3KX;ETJc0{ʮ*A+ ;Qֈ  !"#$%&'()*+,-./01234567֧Qbb;`3KXET@0+ *A<;Q։P  !"#$%&'()*+,-./01234567֧Qbb`3KX;ETJd0{ɮ*A+ <;Q։P  !"#$%&'()*+,-./01234567֧Qbb;`3KXETɍ@+ *AB;Q֊H  !"#$%&'()*+,-./01234567֧Q;bb`3KX;ETJe0{Ȯ*A+ B;Q֊H  !"#$%&'()*+,-./01234567dpkt-1.9.2/examples/data/http.pcap000066400000000000000000000623131340335175100170470ustar00rootroot00000000000000ò#K@>> E0A@A ,P8p"8 $K@Fe>> E0@/,AߑP ,La8p[d$K@Fe66 E(D@A ,P8LaP%yd$K@Fe EE@A ,P8LaP%XGET /download.html HTTP/1.1 Host: www.ethereal.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://www.ethereal.com/development.html $K@ 66 E(@/1AߑP ,La8P !$K@k) E@/,1AߑP ,La8P + HTTP/1.1 200 OK Date: Thu, 13 May 2004 10:17:12 GMT Server: Apache Last-Modified: Tue, 20 Apr 2004 13:17:00 GMT ETag: "9a01a-4696-7e354b00" Accept-Ranges: bytes Content-Length: 18070 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: text/html; charset=ISO-8859-1 Ethereal: Download

Ethereal

Download
%K@66 E(F@A ,P8LfP%r!%K@ E@/,0AߑP ,Lf8P Q Search:

Official Releases

The Official source code release and installers for Windows, Red Hat Linux/Fedora, and Solaris can be found on the main Ethereal web site and its mirrors.

Source Code

HTTP: Main site Australia Australia Germany Japan Korea Malaysia Sweden SourceForge

FTP: Main site Australia Australia Austria Germany Japan Mexico Sweden

The latest development sources are available via anonymous CVS.

Windows 98/ME/2000/XP/2003 Installers

HTTP: Main site Australia Australia Germany Japan Korea Malaysia Sweden SourceForge

FTP: Main site Australia Australia Austria Germany Japan Mexico Sweden

Red Hat Linux / Fedora Packages

HTTP: Main site Australia Australia Germany Japan Korea Malaysia Sweden

FTP: Main site Australia Australia Austria Germany Japan Mexico Sweden

Solaris Packages

HTTP: Main site Australia Australia Germany Japan Korea Malaysia Sweden SourceForge

FTP: Main site Australia Australia Austria Germany Japan Mexico Sweden

Other Platforms

Binary distributions and ready-to-compile packages are available for most platforms. Please note these packages may depend on external libraries including GLib/GTK+, libpcap, Net-SNMP, PCRE, and GNU ADNS. You may have to download and install them before installing Ethereal.

Platform Location(s)
Apple Computer:
Mac OS X
Fink Project DarwinPorts
Be (Palm?):
BeOS
BeBits
Debian:
Debian GNU/Linux
&K@iM  E@/,*AߑP ,LH8P  stable, testing, unstable
The FreeBSD Project:
FreeBSD
ports
Gentoo Technologies:
Gentoo Linux
portage
HP:
Tru64 Unix
The Written Word (4.0d, 5.1)1
HP:
HP-UX
UK, Germany, Netherlands, US, Canada, South Afr&K@iM 66 E(O@A ,P8LP%Le&K@q E@/,)AߑP ,L8P ica
(more mirrors are listed on each site's home page),
The Written Word (10.20, 11.00, 11.11)1
IBM:
AIX
Bull archive
Vienna University mirror
UCLA mirror
IBM:
S/390 Linux (Red Hat 7.2)
Ashley Chaloner
MandrakeSoft:
Mandrake Linux
Cooker (in the contrib section)
Microsoft:
Windows (Intel, 32-bit)
local archive
OPENEXTRA
NetBSD Foundation:
NetBSD
Ls"bO,BĀ=a3b6YeXH_@XYM$ #:D~OSTrt,4H9W!E&X=P9a<-Ol-mhp7(O?a:-knhie qZU#psgpuT߁`bpdBrHϠ@ LT#!CjbllaƝ,drp4嘳ڳ:ajpH=dz̼7zM}S%|GT5>#U Ȟgq*$4ky[r}UMៅ0[8<8?8utUt8GIyH يOh%|\4yn \r/:;rHjTjBĜ5典AnLIR񣹅. w y`Inp.'0hnp'T*@/w@5<ʺ(ϐ{5@_ /.}r=KJ qcbX}Q >R<ݯbsHuRφT>xJ+tb)LU(>bOOƞmOPoF'L mЋ(:m0hA]eBj'K@ Eȅ7;cP +.kY6 Pz)Gc/ ;孖u%\ ~+%@yPϲoǫ% )$P+-JyQ\vrmj h [擄}-e@)\ֈHWaqzOϺB gAx;MѼ6/¿{9'K@66 E(S@>;c +P6 .kYP"8Y'K@h] E@/,(AߑP ,L8P kgsrc/net/ethereal/README.html">packages
OpenBSD:
OpenBSD
ports
PLD Team:
PLD Linux
FTP site
Red Hat:
Red Hat Linux
RPMFind (requires glibc)
Henri Gomez
The Written Word (7.1)1
local archive
ROCK Linux:
ROCK Linux
package
SCO (formerly Caldera):
UnixWare/OpenUnix
Skunkware: UnixWare 7 Open UNIX 8
SGI:
Irix
The Written Word (6.5)1
SGI Freeware
Slackware Linux:
Slackware Linux
Linux Packages
Sun Microsystems:
Solaris/Intel
Solaris 01/01 update (unsupported)
Sun Microsystems:
Solaris/SPARC
local archive (8, 9)
The Written Word (2.5.1 - 9)1
Sunfreeware.com (7, 8)
Solaris 8 and 9 Companion Software CDs (unsupported)
SuSE:
SuSE Linux
SuSE FTP site. Mirrors are also available.

If you know of any binary distribution not listed here, please send mail to ethereal-web[AT]ethereal.com .

[1] Each Ethereal package produced by The Written Word depends on the zlib, Glib, GTK+, Perl, and Net-SNMP packages. Please refer to The Written Word's documentation for installation instructions. Please do not call The Written Word for support. Email free-support[AT]thewrittenword.com with questions.

Other Downloads

Sample Captures

A menagerie of capture files is available on our sample captures pag'K@`/ 66 E(W@ݑA ,P8L

Documentation

A PDF version of the Ethereal User's Guide is available in the documentation page.

AIX is a registered trademark of International Business Machines, Inc. Tru64 is a registered trademark of Compaq Computer Corporation. Debian is a registered trademark of Software In The Public Interest, Inc. FreeBSD is a registered trademark of Walnut Creek CDROM, Inc. HP-UX is a registered trademark of Hewlett-Packard Company. Irix is a registered trademark of Silicon Graphics, Inc. LinuxPPC is a trademark of Jeff Carr. Mac OS is a registered trademark of Apple Computer, Inc. NetBSD is a registered trademark of the NetBSD Foundation. Red Hat is a registered trademark of Red Hat, Inc. Linux is a registered trademark of Linus Torvalds. SCO and Unixware are registered trademarks of Santa Cruz Operation, Inc. Slackware is a registered trademark of Patrick Volkerding. Solaris is a registered trademark of Sun Microsystems, Inc. SuSE is a registered trademark of SuSE AG. Microsoft, Windows, Windows 95, Windows 98, Windows ME, Windows NT, Windows 2000, and Windows XP are registered trademarks of Microsoft, Inc. All other trademarks on this site are property of their respective owners.

(K@66 E(\@ؑA ,P8LHP$1q5K@O66 E(@/1AߑP ,LH8P  z/ns1 9servicescomadmindw3 :]%Rv ]]3asd;I!EGda@@N_cmB |53http service-ncdnsfrnet]%Rz s3ad;!E@9@umB _c5|nhttp service-ncdnsfrnet 2/ns1 9servicescomadmin;w3 :]%R __3asd;K!EId@@+_cmB 55Cncdnnb6dslneufboxneuffr]%Rlvs3ad;!E@9@gmB _c5|ncdnnb6dslneufboxneuffr http service-ncdnsfrnet9 t]9 t]]%R#zJJErE<P@@' ]P+kЬ d]%RJJrEE<@;"] PKŜ+k8Ϟ d ]%RBBErE4Q@@. ]P+kKŝ h+k d]%RErER@@ ]P+kKŝ hB dGET /nb6dsl_Vers%203.3.4_ter/nb6-3.3.4_ter.sha256sum HTTP/1.1 User-Agent: curl/7.33.0 Host: ncdn.nb6dsl.neufbox.neuf.fr Accept: */* ]%Rc*BBrEE4^@;] PKŝ+l~6$ d]%R9.rEE^@;] PKŝ+l~z dHTTP/1.1 200 OK Server: Apache Last-Modified: Thu, 01 Aug 2013 18:16:36 GMT Cache-Control: max-age=86400 Expires: Fri, 03 Jan 2014 02:45:16 GMT X-Varnish: 1740521562 Content-Length: 497 Accept-Ranges: bytes Date: Thu, 02 Jan 2014 08:37:49 GMT X-Varnish: 3638095267 3619940513 Age: 21153 Connection: keep-alive Via: 1.1 varnish, 1.1 cbv4-ncdn-cache06, 1.1 cbv4-ncdn-cache00 # # UUID: 27f4b1e0-6628-49cb-b59b-dc2234dc0e5d # # NB6 3.3.4 sha256sum # 3ece945cf370ff987ea184f3ac859d590b0a830d74949e8aa0c71900663d4d6c NB6-BOOTLOADER-R3.2.4 62797705144e82b7c44963aa8ea13442d12057e7d01f33ed67bfab3f6d4e70d5 NB6-MAIN-R3.3.4 0ea220adfb9dd1c845d9ec0e3d537aab281b5d45ba51b3688c69074225dd8cb4 NB6-CONFIG-R3.3.4.2 f00d0b3b8e6a88efaac18f80967e83c49b3454bbe26764a70a0dbfee3973442d NB6-RESCUE-R3.1.8 d6f592f35abe6e9914fe1b14560b764ee23c846d6c9b5bdecd3300a2b3afeb25 NB6-ADSL-A2pD035p ]%R.BBErE4S@@, ]P+l~K! d҉^%R:=BBErE4T@@+ ]P+l~K! d扏^%R{BBrEE4^@;] PK+l2u d^%R|BBErE4U@@* ]P+lK!m d`%R<<0~g~)EE   1RX<`%Rp<<0~`EE  z>s3ad;*!E(mH_c J2b%Rc JJs3ad;6!E4R.mH_c J2^! H 49"b%R HH3asd;4!E2[[@_&_cmH j! H e%RVVV3asd;B!E@@@9_cmBo5,:Vipv4 icanhazipcome%RLVV3asd;B!E@@@9_cmB o5,DVipv4 icanhazipcome%R>VV3asd;B!E@@@9_cmB؊5,6 ipv4 icanhazipcome%R,<<<EE  @ 1RBrvvs3ad;b!E`@9@mB _c5oLVipv4 icanhazipcom ,Ee ,Ede%R@s3asd;~!E|@r_cmB <E`@9@mB _c5oLVipv4 icanhazipcom ,Ee ,Ede%RzRR3asd;>!E!E<@,(&Ed_cP]mtfq  0J)e%Rd* JJ3asd;6!E4O[@?_cEd]Ptfn< )0Je%R* 3asd;!EO\@?_cEd]Ptfn )0JGET / HTTP/1.1 User-Agent: curl/7.34.0 Host: ipv4.icanhazip.com Accept: */* e%R u JJs3ad;6!E4p@,Ed_cP]ntgG; 0)e%Rz s3ad;!Ep@,=Ed_cP]ntgGm 0)HTTP/1.1 200 OK Date: Thu, 02 Jan 2014 08:37:57 GMT Server: Apache Content-Length: 14 Content-Type: text/plain; charset=UTF-8 X-RTFM: Learn about this site at http://bit.ly/14DAh2o and don't abuse the service X-YOU-SHOULD-APPLY-FOR-A-JOB: If you're reading this, apply here: http://rackertalent.com/ X-ICANHAZNODE: icanhazip1.nugget 95.136.242.99 e%R# JJ3asd;6!E4O]@?_cEd]PtgGӀ: * 0e%Rz JJ3asd;6!E4O^@?_cEd]PtgGӀ9 * 0e%R JJs3ad;6!E4p@,Ed_cP]tgH9n 0* e%Rr JJ3asd;6!E4O_@?_cEd]PtgHԀ97 *80j%R<<>?AEE  ,bR#!RŪomB_c54jT1eipv6 icanhazipcom2ns rackspacemajorhgmailRU^,m%Rts3ad;z!Ex@;>umB_c5f$d>kKipv6 icanhazipcom ,&  ,& n%RlO3asd;x!Ev[]@^_cmHb jW`(?*^!-%r"& PGlq 3n%Rxs3ad;z!Ex,%mH_cdJ2^W`(5& *^!-%r"PISGo 03n%RX3asd;p!En[^@^_cmHZ jW` ?*^!-%r"& PGISڶ 40n%R3asd;!E[_@^_cmH jW`r?*^!-%r"& PGISu 40GET / HTTP/1.1 User-Agent: curl/7.34.0 Host: ipv6.icanhazip.com Accept: */* n%Rs3ad;r!EpUmH_c\J2^W` 5& *^!-%r"PISG  04n%Rs3ad;!EmH_cJ2^W`5& *^!-%r"PISGZ 04HTTP/1.1 200 OK Date: Thu, 02 Jan 2014 08:38:06 GMT Server: Apache Content-Length: 38 Content-Type: text/plain; charset=UTF-8 X-RTFM: Learn about this site at http://bit.ly/14DAh2o and don't abuse the service X-YOU-SHOULD-APPLY-FOR-A-JOB: If you're reading this, apply here: http://rackertalent.com/ X-ICANHAZNODE: icanhazip1.nugget 2a00:5e80:101:212d:504:07b1:2572:db22 n%R3asd;p!En[`@^_cmHZ jW` ?*^!-%r"& PGISS 470n%RΨ3asd;p!En[a@^_cmHZ jW` ?*^!-%r"& PGISR 470n%R;W s3ad;r!EpmH_c\J2^W` 5& *^!-%r"PISGದ 0o47n%Re 3asd;p!En[b@^_cmHZ jW` ?*^!-%r"& PGISm 4m0odpkt-1.9.2/examples/old/000077500000000000000000000000001340335175100150635ustar00rootroot00000000000000dpkt-1.9.2/examples/old/dhcprequest.py000066400000000000000000000030441340335175100177650ustar00rootroot00000000000000#!/usr/bin/env python from __future__ import print_function import sys import socket # Since pcapy is not a requirement of dpkt, test the import and give message try: import pcapy except ImportError: print('Could not import pcapy. Please do a $pip install pcapy') sys.exit(1) # dpkt imports from dpkt import dhcp from dpkt import udp from dpkt import ip from dpkt import ethernet # Grab the default interface and use that for the injection devices = pcapy.findalldevs() iface_name = devices[0] print('Auto Setting Interface to: {:s}'.format(iface_name)) interface = pcapy.open_live(iface_name, 65536 , 1 , 0) # Get local ip src_ip = socket.inet_pton(socket.AF_INET, interface.getnet()) # Generate broadcast ip and eth_addr broadcast_ip = socket.inet_pton(socket.AF_INET, '255.255.255.255') broadcast_eth_addr = b'\xFF\xFF\xFF\xFF\xFF\xFF' # build a dhcp discover packet to request an ip d = dhcp.DHCP( xid=1337, op=dhcp.DHCPDISCOVER, opts=( (dhcp.DHCP_OP_REQUEST, b''), (dhcp.DHCP_OPT_REQ_IP, b''), (dhcp.DHCP_OPT_ROUTER, b''), (dhcp.DHCP_OPT_NETMASK, b''), (dhcp.DHCP_OPT_DNS_SVRS, b'') ) ) # build udp packet u = udp.UDP( dport=67, sport=68, data=d ) u.ulen = len(u) # build ip packet i = ip.IP( dst = broadcast_ip, src = src_ip, data = u, p = ip.IP_PROTO_UDP ) i.len = len(i) # build ethernet frame e = ethernet.Ethernet( dst = broadcast_eth_addr, data = i ) # Inject the packet (send it out) interface.sendpacket(bytes(e)) print('DHCP request sent!') dpkt-1.9.2/examples/old/dnsping.py000066400000000000000000000034661340335175100171100ustar00rootroot00000000000000#!/usr/bin/env python from __future__ import print_function import random, socket import dpkt import ping class DNSPing(ping.Ping): def __init__(self): ping.Ping.__init__(self) self.op.add_option('-z', dest='zone', type='string', default=socket.gethostname().split('.', 1)[1], help='Domain to formulate queries in') self.op.add_option('-n', dest='hostname', type='string', help='Query only for a given hostname') self.op.add_option('-p', dest='port', type='int', default=53, help='Remote DNS server port') self.op.add_option('-R', dest='norecurse', action='store_true', help='Disable recursive queries') def open_sock(self, opts): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.connect((opts.ip, opts.port)) sock.settimeout(opts.wait) return sock def gen_ping(self, opts): for i in range(opts.count): dns = dpkt.dns.DNS(id=i) if opts.norecurse: dns.op &= ~dpkt.dns.DNS_RD if not opts.hostname: name = '%s.%s' % (str(random.random())[-6:], opts.zone) else: name = opts.hostname dns.qd = [dpkt.dns.DNS.Q(name=name)] yield str(dns) def print_header(self, opts): print('DNSPING %s:' % opts.ip, end='') if opts.hostname: print('Name: %s' % opts.hostname) else: print('Name: *.%s' % opts.zone) def print_reply(self, opts, buf, rtt): dns = dpkt.dns.DNS(buf) print('%d bytes from %s: id=%d time=%.3f ms' % \ (len(buf), opts.ip, dns.id, rtt * 1000)) if __name__ == '__main__': DNSPing().main() dpkt-1.9.2/examples/old/nbtping.py000066400000000000000000000027121340335175100171000ustar00rootroot00000000000000#!/usr/bin/env python import socket from dpkt import netbios import ping class NBTPing(ping.Ping): def __init__(self): ping.Ping.__init__(self) self.op.add_option('-p', dest='port', type='int', default=137, help='Remote NetBIOS name server port') def open_sock(self, opts): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.connect((opts.ip, opts.port)) sock.settimeout(opts.wait) return sock def gen_ping(self, opts): for i in range(opts.count): ns = netbios.NS(id=i, qd=[netbios.NS.Q(type=netbios.NS_NBSTAT, name='*')]) yield str(ns) def print_header(self, opts): print('NBTPING %s:' % opts.ip) def print_reply(self, opts, buf, rtt): ns = netbios.NS(buf) d = {} for rr in ns.an: for name, svc, flags in rr.nodenames: unique = (flags & netbios.NS_NAME_G == 0) if svc == 0 and unique and 'host' not in d: d['host'] = name elif svc == 0x03 and unique: if 'user' not in d or d['user'].startswith(d['host']): d['user'] = name print('%d bytes from %s: id=%d time=%.3f ms host=%s user=%s' % \ (len(buf), opts.ip, ns.id, rtt * 1000, d.get('host', ''), d.get('user', ''))) if __name__ == '__main__': NBTPing().main() dpkt-1.9.2/examples/old/ping.py000066400000000000000000000072311340335175100163750ustar00rootroot00000000000000#!/usr/bin/env python import math, optparse, random, socket, sys, time import dpkt class Ping(object): def __init__(self): usage = '%prog [OPTIONS] ' self.op = optparse.OptionParser(usage=usage) self.op.add_option('-c', dest='count', type='int', default=sys.maxint, help='Total number of queries to send') self.op.add_option('-i', dest='wait', type='float', default=1, help='Specify packet interval timeout in seconds') def gen_ping(self, opts): pass def open_sock(self, opts): pass def print_header(self, opts): pass def print_reply(self, opts, buf, rtt): pass def main(self, argv=None): if not argv: argv = sys.argv[1:] opts, args = self.op.parse_args(argv) if not args: self.op.error('missing host') elif len(args) > 1: self.op.error('only one host may be specified') host = args[0] opts.ip = socket.gethostbyname(host) sock = self.open_sock(opts) sent = rcvd = rtt_max = rtt_sum = rtt_sumsq = 0 rtt_min = 0xffff try: self.print_header(opts) for ping in self.gen_ping(opts): try: start = time.time() sock.send(ping) buf = sock.recv(0xffff) rtt = time.time() - start if rtt < rtt_min: rtt_min = rtt if rtt > rtt_max: rtt_max = rtt rtt_sum += rtt rtt_sumsq += rtt * rtt self.print_reply(opts, buf, rtt) rcvd += 1 except socket.timeout: pass sent += 1 time.sleep(opts.wait) except KeyboardInterrupt: pass print('\n--- %s ping statistics ---' % opts.ip) print('%d packets transmitted, %d packets received, %.1f%% packet loss' % \ (sent, rcvd, (float(sent - rcvd) / sent) * 100)) rtt_avg = rtt_sum / sent if rtt_min == 0xffff: rtt_min = 0 print('round-trip min/avg/max/std-dev = %.3f/%.3f/%.3f/%.3f ms' % (rtt_min * 1000, rtt_avg * 1000, rtt_max * 1000, math.sqrt((rtt_sumsq / sent) - (rtt_avg * rtt_avg)) * 1000)) class ICMPPing(Ping): def __init__(self): Ping.__init__(self) self.op.add_option('-p', dest='payload', type='string', default='hello world!', help='Echo payload string') def open_sock(self, opts): sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, 1) sock.connect((opts.ip, 1)) sock.settimeout(opts.wait) return sock def gen_ping(self, opts): for i in range(opts.count): icmp = dpkt.icmp.ICMP( type=8, data=dpkt.icmp.ICMP.Echo(id=random.randint(0, 0xffff), seq=i, data=opts.payload)) yield str(icmp) def print_header(self, opts): print('PING %s: %d data bytes' % (opts.ip, len(opts.payload))) def print_reply(self, opts, buf, rtt): ip = dpkt.ip.IP(buf) if sys.platform == 'darwin': # XXX - work around raw socket bug on MacOS X ip.data = ip.icmp = dpkt.icmp.ICMP(buf[20:]) ip.len = len(ip.data) print('%d bytes from %s: icmp_seq=%d ip_id=%d ttl=%d time=%.3f ms' % (len(ip.icmp), opts.ip, ip.icmp.echo.seq, ip.id, ip.ttl, rtt * 1000)) if __name__ == '__main__': p = ICMPPing() p.main() dpkt-1.9.2/examples/print_http_requests.py000066400000000000000000000066701340335175100210160ustar00rootroot00000000000000#!/usr/bin/env python """ This example expands on the print_packets example. It checks for HTTP request headers and displays their contents. NOTE: We are not reconstructing 'flows' so the request (and response if you tried to parse it) will only parse correctly if they fit within a single packet. Requests can often fit in a single packet but Responses almost never will. For proper reconstruction of flows you may want to look at other projects that use DPKT (http://chains.readthedocs.io and others) """ import dpkt import datetime import socket from dpkt.compat import compat_ord def mac_addr(address): """Convert a MAC address to a readable/printable string Args: address (str): a MAC address in hex form (e.g. '\x01\x02\x03\x04\x05\x06') Returns: str: Printable/readable MAC address """ return ':'.join('%02x' % compat_ord(b) for b in address) def inet_to_str(inet): """Convert inet object to a string Args: inet (inet struct): inet network address Returns: str: Printable/readable IP address """ # First try ipv4 and then ipv6 try: return socket.inet_ntop(socket.AF_INET, inet) except ValueError: return socket.inet_ntop(socket.AF_INET6, inet) def print_http_requests(pcap): """Print out information about each packet in a pcap Args: pcap: dpkt pcap reader object (dpkt.pcap.Reader) """ # For each packet in the pcap process the contents for timestamp, buf in pcap: # Unpack the Ethernet frame (mac src/dst, ethertype) eth = dpkt.ethernet.Ethernet(buf) # Make sure the Ethernet data contains an IP packet if not isinstance(eth.data, dpkt.ip.IP): print('Non IP Packet type not supported %s\n' % eth.data.__class__.__name__) continue # Now grab the data within the Ethernet frame (the IP packet) ip = eth.data # Check for TCP in the transport layer if isinstance(ip.data, dpkt.tcp.TCP): # Set the TCP data tcp = ip.data # Now see if we can parse the contents as a HTTP request try: request = dpkt.http.Request(tcp.data) except (dpkt.dpkt.NeedData, dpkt.dpkt.UnpackError): continue # Pull out fragment information (flags and offset all packed into off field, so use bitmasks) do_not_fragment = bool(ip.off & dpkt.ip.IP_DF) more_fragments = bool(ip.off & dpkt.ip.IP_MF) fragment_offset = ip.off & dpkt.ip.IP_OFFMASK # Print out the info print('Timestamp: ', str(datetime.datetime.utcfromtimestamp(timestamp))) print('Ethernet Frame: ', mac_addr(eth.src), mac_addr(eth.dst), eth.type) print('IP: %s -> %s (len=%d ttl=%d DF=%d MF=%d offset=%d)' % (inet_to_str(ip.src), inet_to_str(ip.dst), ip.len, ip.ttl, do_not_fragment, more_fragments, fragment_offset)) print('HTTP request: %s\n' % repr(request)) # Check for Header spanning acrossed TCP segments if not tcp.data.endswith(b'\r\n'): print('\nHEADER TRUNCATED! Reassemble TCP segments!\n') def test(): """Open up a test pcap file and print out the packets""" with open('data/http.pcap', 'rb') as f: pcap = dpkt.pcap.Reader(f) print_http_requests(pcap) if __name__ == '__main__': test() dpkt-1.9.2/examples/print_icmp.py000066400000000000000000000052611340335175100170270ustar00rootroot00000000000000#!/usr/bin/env python """ This example expands on the print_packets example. It checks for ICMP packets and displays the ICMP contents. """ import dpkt import datetime import socket from dpkt.compat import compat_ord def mac_addr(address): """Convert a MAC address to a readable/printable string Args: address (str): a MAC address in hex form (e.g. '\x01\x02\x03\x04\x05\x06') Returns: str: Printable/readable MAC address """ return ':'.join('%02x' % compat_ord(b) for b in address) def inet_to_str(inet): """Convert inet object to a string Args: inet (inet struct): inet network address Returns: str: Printable/readable IP address """ # First try ipv4 and then ipv6 try: return socket.inet_ntop(socket.AF_INET, inet) except ValueError: return socket.inet_ntop(socket.AF_INET6, inet) def print_icmp(pcap): """Print out information about each packet in a pcap Args: pcap: dpkt pcap reader object (dpkt.pcap.Reader) """ # For each packet in the pcap process the contents for timestamp, buf in pcap: # Unpack the Ethernet frame (mac src/dst, ethertype) eth = dpkt.ethernet.Ethernet(buf) # Make sure the Ethernet data contains an IP packet if not isinstance(eth.data, dpkt.ip.IP): print('Non IP Packet type not supported %s\n' % eth.data.__class__.__name__) continue # Now grab the data within the Ethernet frame (the IP packet) ip = eth.data # Now check if this is an ICMP packet if isinstance(ip.data, dpkt.icmp.ICMP): icmp = ip.data # Pull out fragment information (flags and offset all packed into off field, so use bitmasks) do_not_fragment = bool(ip.off & dpkt.ip.IP_DF) more_fragments = bool(ip.off & dpkt.ip.IP_MF) fragment_offset = ip.off & dpkt.ip.IP_OFFMASK # Print out the info print('Timestamp: ', str(datetime.datetime.utcfromtimestamp(timestamp))) print( 'Ethernet Frame: ', mac_addr(eth.src), mac_addr(eth.dst), eth.type) print( 'IP: %s -> %s (len=%d ttl=%d DF=%d MF=%d offset=%d)' % \ (inet_to_str(ip.src), inet_to_str(ip.dst), ip.len, ip.ttl, do_not_fragment, more_fragments, fragment_offset)) print('ICMP: type:%d code:%d checksum:%d data: %s\n' % (icmp.type, icmp.code, icmp.sum, repr(icmp.data))) def test(): """Open up a test pcap file and print out the packets""" with open('data/dns_icmp.pcap', 'rb') as f: pcap = dpkt.pcap.Reader(f) print_icmp(pcap) if __name__ == '__main__': test() dpkt-1.9.2/examples/print_packets.py000066400000000000000000000050721340335175100175310ustar00rootroot00000000000000#!/usr/bin/env python """ Use DPKT to read in a pcap file and print out the contents of the packets This example is focused on the fields in the Ethernet Frame and IP packet """ import dpkt import datetime import socket from dpkt.compat import compat_ord def mac_addr(address): """Convert a MAC address to a readable/printable string Args: address (str): a MAC address in hex form (e.g. '\x01\x02\x03\x04\x05\x06') Returns: str: Printable/readable MAC address """ return ':'.join('%02x' % compat_ord(b) for b in address) def inet_to_str(inet): """Convert inet object to a string Args: inet (inet struct): inet network address Returns: str: Printable/readable IP address """ # First try ipv4 and then ipv6 try: return socket.inet_ntop(socket.AF_INET, inet) except ValueError: return socket.inet_ntop(socket.AF_INET6, inet) def print_packets(pcap): """Print out information about each packet in a pcap Args: pcap: dpkt pcap reader object (dpkt.pcap.Reader) """ # For each packet in the pcap process the contents for timestamp, buf in pcap: # Print out the timestamp in UTC print('Timestamp: ', str(datetime.datetime.utcfromtimestamp(timestamp))) # Unpack the Ethernet frame (mac src/dst, ethertype) eth = dpkt.ethernet.Ethernet(buf) print('Ethernet Frame: ', mac_addr(eth.src), mac_addr(eth.dst), eth.type) # Make sure the Ethernet data contains an IP packet if not isinstance(eth.data, dpkt.ip.IP): print('Non IP Packet type not supported %s\n' % eth.data.__class__.__name__) continue # Now unpack the data within the Ethernet frame (the IP packet) # Pulling out src, dst, length, fragment info, TTL, and Protocol ip = eth.data # Pull out fragment information (flags and offset all packed into off field, so use bitmasks) do_not_fragment = bool(ip.off & dpkt.ip.IP_DF) more_fragments = bool(ip.off & dpkt.ip.IP_MF) fragment_offset = ip.off & dpkt.ip.IP_OFFMASK # Print out the info print('IP: %s -> %s (len=%d ttl=%d DF=%d MF=%d offset=%d)\n' % \ (inet_to_str(ip.src), inet_to_str(ip.dst), ip.len, ip.ttl, do_not_fragment, more_fragments, fragment_offset)) def test(): """Open up a test pcap file and print out the packets""" with open('data/http.pcap', 'rb') as f: pcap = dpkt.pcap.Reader(f) print_packets(pcap) if __name__ == '__main__': test() dpkt-1.9.2/setup.cfg000066400000000000000000000004601340335175100143100ustar00rootroot00000000000000[bdist_wheel] [aliases] release = sdist bdist_wheel upload -r pypi test_release = sdist bdist_wheel upload -r pypitest [flake8] max-line-length = 140 [tool:pytest] addopts= -v --cov-report term-missing python_files=*.py python_functions=test norecursedirs=.tox .git *.egg-info __pycache__ dist build dpkt-1.9.2/setup.py000077500000000000000000000030511340335175100142030ustar00rootroot00000000000000import os import sys try: from setuptools import setup, Command except ImportError: from distutils.core import setup, Command package_name = 'dpkt' description = 'fast, simple packet creation / parsing, with definitions for the basic TCP/IP protocols' readme = open('README.rst').read() requirements = [] # PyPI Readme long_description = open('README.rst').read() # Pull in the package package = __import__(package_name) package_version = package.__version__ if "bdist_msi" in sys.argv: # The MSI build target does not support a 4 digit version, e.g. '1.2.3.4' # therefore we remove the last digit. package_version, _, _ = package_version.rpartition('.') setup(name=package_name, version=package_version, author=package.__author__, author_email=package.__author_email__, url=package.__url__, description=description, long_description=long_description, packages=['dpkt'], install_requires=requirements, license='BSD', zip_safe=False, classifiers=[ 'Development Status :: 4 - Beta', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Natural Language :: English', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', ] ) dpkt-1.9.2/tox.ini000066400000000000000000000012471340335175100140060ustar00rootroot00000000000000[tox] envlist = py26, py27, py35, py36, docs [testenv] install_command = pip install {opts} {packages} # FIXME: remove version pinning when py26 support is no longer needed deps = setuptools==36.8.0 wheel==0.29 pytest==3.2.5 coverage pytest-cov stdeb commands = py.test --cov=dpkt dpkt [testenv:style] deps = flake8 commands = python setup.py flake8 [testenv:coveralls] passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH deps = coveralls usedevelop = true commands = coverage report coveralls [testenv:docs] changedir=docs deps = -rdocs/requirements.txt commands = sphinx-build -b html -d {envtmpdir}/doctrees . {envtmpdir}/html