├── .gitignore ├── tests ├── 96pings.pcap └── pcapytests.py ├── MANIFEST.in ├── pcapdumper.h ├── pcapobj.h ├── bpfobj.h ├── pcap_pkthdr.h ├── win32 └── dllmain.cc ├── pcapy.h ├── appveyor ├── install.ps1 └── run_with_compiler.cmd ├── appveyor.yml ├── LICENSE ├── setup.py ├── README.md ├── ChangeLog ├── README ├── pcap_pkthdr.cc ├── pcapdumper.cc ├── bpfobj.cc ├── pcapy.cc ├── pcapobj.cc ├── pcapy.xml └── pcapy.html /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[co] 2 | *.so 3 | *.pyd 4 | *.egg-info 5 | /build/ 6 | /dist/ 7 | -------------------------------------------------------------------------------- /tests/96pings.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stamparm/pcapy-ng/HEAD/tests/96pings.pcap -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include MANIFEST.in 2 | include LICENSE 3 | include ChangeLog 4 | include pcapy.xml 5 | include pcapy.html 6 | include *.h 7 | recursive-include win32 *.cc 8 | -------------------------------------------------------------------------------- /pcapdumper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Miroslav Stampar (miroslav@sqlmap.org) 3 | * Copyright (c) 2014 CORE Security Technologies 4 | * 5 | * This software is provided under under the Apache Software License. 6 | * See the accompanying LICENSE file for more information. 7 | * 8 | */ 9 | 10 | #ifndef __pcapdumper__ 11 | #define __pcapdumper__ 12 | 13 | 14 | PyObject* 15 | new_pcapdumper(pcap_dumper_t *dumper); 16 | 17 | extern PyTypeObject Pdumpertype; 18 | 19 | #endif // __pcapdumper__ 20 | -------------------------------------------------------------------------------- /pcapobj.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Miroslav Stampar (miroslav@sqlmap.org) 3 | * Copyright (c) 2014 CORE Security Technologies 4 | * 5 | * This software is provided under under the Apache Software License. 6 | * See the accompanying LICENSE file for more information. 7 | * 8 | */ 9 | 10 | #ifndef __pcapobj__ 11 | #define __pcapobj__ 12 | 13 | 14 | PyObject* 15 | new_pcapobject(pcap_t *pcap, bpf_u_int32 net=0, bpf_u_int32 mask=0); 16 | 17 | extern PyTypeObject Pcaptype; 18 | 19 | #endif // __pcapobj__ 20 | -------------------------------------------------------------------------------- /bpfobj.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Miroslav Stampar (miroslav@sqlmap.org) 3 | * Copyright (c) 2014 CORE Security Technologies 4 | * 5 | * This software is provided under under the Apache Software License. 6 | * See the accompanying LICENSE file for more information. 7 | * 8 | */ 9 | 10 | #ifndef __bpfobj__ 11 | #define __bpfobj__ 12 | 13 | PyObject* 14 | new_bpfobject(const struct bpf_program &bpf); 15 | 16 | extern PyObject* BPFError; 17 | 18 | extern PyTypeObject BPFProgramType; 19 | 20 | extern PyTypeObject Pcaptype; 21 | 22 | #endif // __bpfobj__ 23 | -------------------------------------------------------------------------------- /pcap_pkthdr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Miroslav Stampar (miroslav@sqlmap.org) 3 | * Copyright (c) 2014 CORE Security Technologies 4 | * 5 | * This software is provided under under the Apache Software License. 6 | * See the accompanying LICENSE file for more information. 7 | * 8 | */ 9 | 10 | #ifndef __pcap_pkthdr__ 11 | #define __pcap_pkthdr__ 12 | 13 | #include 14 | 15 | PyObject* 16 | new_pcap_pkthdr(const struct pcap_pkthdr* hdr); 17 | int 18 | pkthdr_to_native(PyObject *pyhdr, struct pcap_pkthdr *hdr); 19 | 20 | extern PyTypeObject Pkthdr_type; 21 | 22 | #endif // __pcap_pkthdr__ 23 | -------------------------------------------------------------------------------- /win32/dllmain.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Miroslav Stampar (miroslav@sqlmap.org) 3 | * Copyright (c) 2014 CORE Security Technologies 4 | * 5 | * This software is provided under under the Apache Software License. 6 | * See the accompanying LICENSE file for more information. 7 | * 8 | * Win32 DLL entry point. 9 | * 10 | */ 11 | 12 | #include 13 | 14 | 15 | BOOL APIENTRY DllMain( HANDLE hModule, 16 | DWORD ul_reason_for_call, 17 | LPVOID lpReserved 18 | ) 19 | { 20 | switch (ul_reason_for_call) 21 | { 22 | case DLL_PROCESS_ATTACH: 23 | case DLL_THREAD_ATTACH: 24 | case DLL_THREAD_DETACH: 25 | case DLL_PROCESS_DETACH: 26 | break; 27 | } 28 | return TRUE; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /pcapy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Miroslav Stampar (miroslav@sqlmap.org) 3 | * Copyright (c) 2014 CORE Security Technologies 4 | * 5 | * This software is provided under under the Apache Software License. 6 | * See the accompanying LICENSE file for more information. 7 | * 8 | */ 9 | 10 | #ifndef __PCAPY_H__ 11 | 12 | #ifndef Py_TYPE // python3 compatible 13 | #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) 14 | #endif 15 | 16 | extern "C" { 17 | #ifdef WIN32 18 | __declspec(dllexport) 19 | char *get_windows_interface_friendly_name(const char *interface_devicename); 20 | static char* luid_to_guid(char *luid); 21 | #endif 22 | 23 | #if PY_MAJOR_VERSION >= 3 24 | PyMODINIT_FUNC PyInit_pcapy(void); 25 | #else 26 | void initpcapy(void); 27 | #endif 28 | } 29 | 30 | // exception object 31 | extern PyObject* PcapError; 32 | 33 | #endif // __PCAPY_H__ 34 | -------------------------------------------------------------------------------- /appveyor/install.ps1: -------------------------------------------------------------------------------- 1 | function InstallPackage ($python_home, $pkg) { 2 | $pip_path = $python_home + "/Scripts/pip.exe" 3 | & $pip_path install $pkg 4 | } 5 | 6 | function DownloadWinpcapDev () { 7 | $webclient = New-Object System.Net.WebClient 8 | 9 | $download_url = "https://www.winpcap.org/install/bin/WpdPack_4_1_2.zip" 10 | $filename = "WpdPack_4_1_2.zip" 11 | 12 | $basedir = $pwd.Path + "\" 13 | $filepath = $basedir + $filename 14 | if (Test-Path $filepath) { 15 | Write-Host "Reusing" $filepath 16 | return $filepath 17 | } 18 | 19 | # Download and retry up to 5 times in case of network transient errors. 20 | Write-Host "Downloading" $filename "from" $download_url 21 | $retry_attempts = 3 22 | for($i=0; $i -lt $retry_attempts; $i++){ 23 | try { 24 | $webclient.DownloadFile($download_url, $filepath) 25 | break 26 | } 27 | Catch [Exception]{ 28 | Start-Sleep 1 29 | } 30 | } 31 | Write-Host "File saved at" $filepath 32 | 33 | & 7z x $filename 34 | } 35 | 36 | 37 | function main () { 38 | InstallPackage $env:PYTHON wheel 39 | & DownloadWinpcapDev 40 | } 41 | 42 | main 43 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | 3 | global: 4 | # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the 5 | # /E:ON and /V:ON options are not enabled in the batch script intepreter 6 | # See: http://stackoverflow.com/a/13751649/163740 7 | WITH_COMPILER: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_compiler.cmd" 8 | DISTRIBUTIONS: "bdist_wheel" 9 | 10 | matrix: 11 | - PYTHON: "C:\\Python27" 12 | PYTHON_VERSION: "2.7.11" 13 | PYTHON_ARCH: "32" 14 | 15 | - PYTHON: "C:\\Python34" 16 | PYTHON_VERSION: "3.4.3" 17 | PYTHON_ARCH: "32" 18 | 19 | - PYTHON: "C:\\Python35" 20 | PYTHON_VERSION: "3.5.0" 21 | PYTHON_ARCH: "32" 22 | 23 | - PYTHON: "C:\\Python27-x64" 24 | PYTHON_VERSION: "2.7.11" 25 | PYTHON_ARCH: "64" 26 | 27 | - PYTHON: "C:\\Python34-x64" 28 | PYTHON_VERSION: "3.4.3" 29 | PYTHON_ARCH: "64" 30 | 31 | - PYTHON: "C:\\Python35-x64" 32 | PYTHON_VERSION: "3.5.0" 33 | PYTHON_ARCH: "64" 34 | 35 | init: 36 | - "ECHO %PYTHON% %PYTHON_VERSION% %PYTHON_ARCH%" 37 | 38 | install: 39 | - cinst winpcap 40 | - "powershell appveyor\\install.ps1" 41 | - "set HOME=%APPVEYOR_BUILD_FOLDER%" 42 | - "set WPDPACK_BASE=%APPVEYOR_BUILD_FOLDER%\\WpdPack" 43 | - "%PYTHON%/python -m pip install -U pip" # Upgrade pip 44 | - "%WITH_COMPILER% %PYTHON%/python setup.py build" 45 | - "%WITH_COMPILER% %PYTHON%/python setup.py %DISTRIBUTIONS%" 46 | - ps: "ls dist" 47 | 48 | # Install the wheel to test it 49 | - "%PYTHON%/python -m pip install --ignore-installed --pre --no-index --find-links dist/ pcapy" 50 | 51 | # Appveyor's build step is specific to .NET projects, so we build in the 52 | # install step instead. 53 | build: off 54 | 55 | test_script: 56 | - "cd tests" 57 | - "%PYTHON%/python pcapytests.py" 58 | 59 | # Move back to the project folder 60 | - "cd .." 61 | 62 | artifacts: 63 | - path: dist\* 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Licencing 2 | --------- 3 | 4 | The Apache Software License, Version 1.1 5 | 6 | Copyright (c) 2000 The Apache Software Foundation. All rights 7 | reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions 11 | are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright 14 | notice, this list of conditions and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright 17 | notice, this list of conditions and the following disclaimer in 18 | the documentation and/or other materials provided with the 19 | distribution. 20 | 21 | 3. The end-user documentation included with the redistribution, 22 | if any, must include the following acknowledgment: 23 | "This product includes software developed by the 24 | Apache Software Foundation (http://www.apache.org/)." 25 | Alternately, this acknowledgment may appear in the software itself, 26 | if and wherever such third-party acknowledgments normally appear. 27 | 28 | 4. The names "Apache" and "Apache Software Foundation" must 29 | not be used to endorse or promote products derived from this 30 | software without prior written permission. For written 31 | permission, please contact apache@apache.org. 32 | 33 | 5. Products derived from this software may not be called "Apache", 34 | nor may "Apache" appear in their name, without prior written 35 | permission of the Apache Software Foundation. 36 | 37 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 38 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 39 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 | DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 41 | ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 43 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 44 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 47 | OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 | SUCH DAMAGE. 49 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import glob 4 | from setuptools import setup, Extension 5 | 6 | PACKAGE_NAME = 'pcapy-ng' 7 | 8 | # You might want to change these to reflect your specific configuration 9 | include_dirs = [] 10 | library_dirs = [] 11 | libraries = [] 12 | 13 | if sys.platform == 'win32': 14 | if os.environ.get('WPDPACK_BASE'): 15 | wpdpack = os.environ['WPDPACK_BASE'] 16 | include_dirs.append(os.path.join(wpdpack, 'Include')) 17 | if sys.maxsize > 2**32: # x64 Python interpreter 18 | library_dirs.append(os.path.join(wpdpack, 'Lib', 'x64')) 19 | else: # x86 Python interpreter 20 | library_dirs.append(os.path.join(wpdpack, 'Lib')) 21 | else: 22 | # WinPcap include files 23 | include_dirs.append(r'c:\wpdpack\Include') 24 | # WinPcap library files 25 | if sys.maxsize > 2**32: # x64 Python interpreter 26 | library_dirs.append(r'c:\wpdpack\Lib\x64') 27 | else: # x86 Python interpreter 28 | library_dirs.append(r'c:\wpdpack\Lib') 29 | libraries = ['wpcap', 'packet', 'ws2_32'] 30 | else: 31 | libraries = ['pcap'] 32 | 33 | 34 | # end of user configurable parameters 35 | macros = [] 36 | sources = ['pcapdumper.cc', 37 | 'bpfobj.cc', 38 | 'pcapobj.cc', 39 | 'pcap_pkthdr.cc', 40 | 'pcapy.cc' 41 | ] 42 | 43 | if sys.platform == 'win32': 44 | sources.append(os.path.join('win32', 'dllmain.cc')) 45 | macros.append(('WIN32', '1')) 46 | 47 | def read(fname): 48 | return open(os.path.join(os.path.dirname(__file__), fname)).read() 49 | 50 | setup(name=PACKAGE_NAME, 51 | version="1.0.9", 52 | url="https://github.com/stamparm/pcapy-ng/", 53 | author="Miroslav Stampar", 54 | author_email="miroslav@sqlmap.org", 55 | maintainer="Miroslav Stampar", 56 | maintainer_email="miroslav@sqlmap.org", 57 | platforms=["Unix", "Windows"], 58 | description="Python pcap extension", 59 | long_description=read('README'), 60 | license="Apache", 61 | ext_modules=[Extension( 62 | name="pcapy", 63 | sources=sources, 64 | define_macros=macros, 65 | include_dirs=include_dirs, 66 | library_dirs=library_dirs, 67 | libraries=libraries)], 68 | #scripts=['tests/pcapytests.py', 'tests/96pings.pcap'], 69 | data_files=[ 70 | (os.path.join('share', 'doc', PACKAGE_NAME), ['README', 'LICENSE', 'pcapy.html']), 71 | (os.path.join('share', 'doc', PACKAGE_NAME, 'tests'), glob.glob('tests/*'))] 72 | ) 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## What is Pcapy-NG? ## 2 | 3 | [![Build status](https://ci.appveyor.com/api/projects/status/pi4bqe4kgubgr37x?svg=true)](https://ci.appveyor.com/project/CoreSecurity/pcapy) 4 | 5 | Pcapy-NG is a Python extension module that enables software written in 6 | Python to access the routines from the pcap packet capture library. It is 7 | a replacement of [Pcapy](https://github.com/helpsystems/pcapy), which is not 8 | maintained any more and stopped working altogether on Python3.10 9 | ([Issue](https://github.com/helpsystems/pcapy/issues/70)). 10 | 11 | From libpcap's documentation: "Libpcap is a system-independent 12 | interface for user-level packet capture. Libpcap provides a portable 13 | framework for low-level network monitoring. Applications include 14 | network statistics collection, security monitoring, network debugging, 15 | etc." 16 | 17 | ## Setup ## 18 | 19 | ### Quick start ### 20 | 21 | Grab the latest stable release, unpack it and run `python setup.py 22 | install` from the directory where you placed it. Isn't that easy? 23 | 24 | ### [Documentation](https://raw.githack.com/stamparm/pcapy-ng/master/pcapy.html) ### 25 | 26 | ### Requirements ### 27 | 28 | * A Python interpreter. Versions 2.1.3 and newer are known to work. 29 | * A C++ compiler. GCC G++ 2.95, as well as Microsoft Visual Studio 30 | 6.0, are known to work. 31 | * Libpcap 0.7.2 or newer. Windows user are best to check WinPcap 3.0 32 | or newer. 33 | 34 | ### Compiling the source and installing ### 35 | 36 | As this extension is written in C++ it needs to be compiled for the 37 | host system before it can be accessed from Python. Fortunately this 38 | process has been made easy by the setup.py script. In order to compile 39 | and install the source execute the following command from the 40 | directory where the pcapy's distribution has been unpacked: 'python 41 | setup.py install'. This will install the extension into the default 42 | Python's modules path; note that you might need special permissions to 43 | write there. For more information on what commands and options are 44 | available from setup.py, run `python setup.py --help-commands`. 45 | 46 | This extension has been tested under Linux and Windows systems 47 | and is known to work there, but it ought to work out-of-the-box on any 48 | system where Python and libpcap are available. 49 | 50 | ## Licensing ## 51 | 52 | This software is provided under under the Apache Software License. 53 | See the accompanying LICENSE file for more information. 54 | 55 | ## Contact Us ## 56 | 57 | Whether you want to report a bug, send a patch or give some 58 | suggestions on this package, drop a few lines at 59 | `miroslav@sqlmap.org`. 60 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2018-06-17 Alberto Solino 2 | * Version 0.11.4 tagged with the following changes 3 | * bpfobject support get_bpf method (by @palaviv) 4 | * Monitor mode support & missing methods fix (by @gpotter2) 5 | * Documentation update (@gpotter2) 6 | 7 | 2018-03-26 Alberto Solino 8 | * Version 0.11.2 tagged with the following substantial changes (since version 0.11.11): 9 | * Exporting pcap_get_selectable_fd as getfd (by @geekhckr) 10 | * Add a close method & context manager to Reader (by @segevfiner) 11 | 12 | 2017-01-16 Martin Balao 13 | * Version 0.11.1 tagged with the following changes (since version 0.10.10): 14 | * AppVeyor integration (continuous integration service) 15 | * @takluyver contribution 16 | * Close method for Pcap Dumper 17 | * @JinBlack contribution 18 | * Pcap stats added 19 | * @duggan contribution 20 | 21 | 2015-05-19 Andres Blanco 22 | * Added sendpacket support by default 23 | 24 | 2010-08-25 Ezequiel Gutesman 25 | * removed check for pcap_sendpacket function 26 | 27 | 2010-07-30 Ezequiel Gutesman 28 | * pcapy.cc: fixed bug in initpcapy, Pkthdr_type.ob_type and Pdumpertype.ob_type were not set. See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=589956 (reported by Piotr Lewandowski) 29 | 30 | 2007-03-27 Max Caceres 31 | * pcapobj.cc: wrapped pcap_sendpacket for sending packets in all platforms. 32 | 33 | 2005-12-09 Max Caceres 34 | * pcapy.cc: open_live doesn't raise an exception anymore when network/netmask information is not available (i.e. when sniffing on devices without an assigned IP address). Reported by Scott Raynel. 35 | 36 | 2005-09-14 Max Caceres 37 | * pcapobj.cc: fixed bug where exceptions thrown inside a callback where not handled properly. Fix relies on fairly new pcap_breakloop function. 38 | * pcapy.cc: in Windows uses findalldevs() packaged with new Winpcap 3.1 39 | 40 | 2005-08-15 Max Caceres 41 | * pcapy.cc: fixed bug where getnet() and getmask() always returned 0.0.0.0 (reported by Jeff Connelly) 42 | 43 | 2005-07-28 Max Caceres 44 | * pcapobj.cc: fixed a memory leak in PythonCallback (reported by fraca7 _at_ free.fr). 45 | 46 | 2004-01-05 Javier Kohen 47 | * setup.py: force linking with G++ when using GCC, to avoid a missing symbol in some setups. 48 | 49 | 2003-11-28 Javier Kohen 50 | * dcerpc_v4.py: Fixed self.bind variable having the same name than a method. 51 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This file is an extract from the the online documentation at 2 | https://github.com/stamparm/pcapy-ng/blob/master/README.md 3 | 4 | 5 | What is Pcapy-NG? 6 | ================= 7 | 8 | Pcapy-NG is a Python extension module that enables software written in 9 | Python to access the routines from the pcap packet capture library. It is 10 | a replacement of Pcapy, which is not maintained any more and stopped working 11 | altogether on Python3.10. 12 | 13 | From libpcap's documentation: "Libpcap is a system-independent 14 | interface for user-level packet capture. Libpcap provides a portable 15 | framework for low-level network monitoring. Applications include 16 | network statistics collection, security monitoring, network debugging, 17 | etc." 18 | 19 | What makes pcapy different from the others? 20 | ------------------------------------------- 21 | 22 | * works with Python threads. 23 | * works both in UNIX with libpcap and Windows with WinPcap. 24 | * provides a simpler Object Oriented API. 25 | 26 | 27 | Setup 28 | ===== 29 | 30 | Quick start 31 | ----------- 32 | 33 | Grab the latest stable release, unpack it and run 'python setup.py 34 | install' from the directory where you placed it. Isn't that easy? 35 | 36 | 37 | Requirements 38 | ------------ 39 | 40 | * A Python interpreter. Versions 2.1.3 and newer are known to work. 41 | * A C++ compiler. GCC G++ 2.95, as well as Microsoft Visual Studio 42 | 6.0, are known to work. 43 | * Libpcap 0.7.2 or newer. Windows user are best to check WinPcap 3.0 44 | or newer. 45 | * A recent release of Pcapy. 46 | 47 | Compiling the source and installing 48 | ----------------------------------- 49 | 50 | As this extension is written in C++ it needs to be compiled for the 51 | host system before it can be accessed from Python. Fortunately this 52 | process has been made easy by the setup.py script. In order to compile 53 | and install the source execute the following command from the 54 | directory where the pcapy's distribution has been unpacked: 'python 55 | setup.py install'. This will install the extension into the default 56 | Python's modules path; note that you might need special permissions to 57 | write there. For more information on what commands and options are 58 | available from setup.py, run 'python setup.py --help-commands'. 59 | 60 | This extension has been tested under Linux and Windows systems 61 | and is known to work there, but it ought to work out-of-the-box on any 62 | system where Python and libpcap are available. 63 | 64 | 65 | Licensing 66 | ========= 67 | 68 | This software is provided under under the Apache Software License. 69 | See the accompanying LICENSE file for more information. 70 | 71 | 72 | Contact Us 73 | ========== 74 | 75 | Whether you want to report a bug, send a patch or give some 76 | suggestions on this package, drop a few lines at 77 | miroslav@sqlmap.org. 78 | -------------------------------------------------------------------------------- /appveyor/run_with_compiler.cmd: -------------------------------------------------------------------------------- 1 | :: To build extensions for 64 bit Python 3, we need to configure environment 2 | :: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of: 3 | :: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1) 4 | :: 5 | :: To build extensions for 64 bit Python 2, we need to configure environment 6 | :: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of: 7 | :: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0) 8 | :: 9 | :: 32 bit builds, and 64-bit builds for 3.5 and beyond, do not require specific 10 | :: environment configurations. 11 | :: 12 | :: Note: this script needs to be run with the /E:ON and /V:ON flags for the 13 | :: cmd interpreter, at least for (SDK v7.0) 14 | :: 15 | :: More details at: 16 | :: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows 17 | :: http://stackoverflow.com/a/13751649/163740 18 | :: 19 | :: Author: Olivier Grisel 20 | :: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ 21 | :: 22 | :: Notes about batch files for Python people: 23 | :: 24 | :: Quotes in values are literally part of the values: 25 | :: SET FOO="bar" 26 | :: FOO is now five characters long: " b a r " 27 | :: If you don't want quotes, don't include them on the right-hand side. 28 | :: 29 | :: The CALL lines at the end of this file look redundant, but if you move them 30 | :: outside of the IF clauses, they do not run properly in the SET_SDK_64==Y 31 | :: case, I don't know why. 32 | @ECHO OFF 33 | 34 | SET COMMAND_TO_RUN=%* 35 | SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows 36 | SET WIN_WDK=c:\Program Files (x86)\Windows Kits\10\Include\wdf 37 | 38 | :: Extract the major and minor versions, and allow for the minor version to be 39 | :: more than 9. This requires the version number to have two dots in it. 40 | SET MAJOR_PYTHON_VERSION=%PYTHON_VERSION:~0,1% 41 | IF "%PYTHON_VERSION:~3,1%" == "." ( 42 | SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,1% 43 | ) ELSE ( 44 | SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,2% 45 | ) 46 | 47 | :: Based on the Python version, determine what SDK version to use, and whether 48 | :: to set the SDK for 64-bit. 49 | IF %MAJOR_PYTHON_VERSION% == 2 ( 50 | SET WINDOWS_SDK_VERSION="v7.0" 51 | SET SET_SDK_64=Y 52 | ) ELSE ( 53 | IF %MAJOR_PYTHON_VERSION% == 3 ( 54 | SET WINDOWS_SDK_VERSION="v7.1" 55 | IF %MINOR_PYTHON_VERSION% LEQ 4 ( 56 | SET SET_SDK_64=Y 57 | ) ELSE ( 58 | SET SET_SDK_64=N 59 | IF EXIST "%WIN_WDK%" ( 60 | :: See: https://connect.microsoft.com/VisualStudio/feedback/details/1610302/ 61 | REN "%WIN_WDK%" 0wdf 62 | ) 63 | ) 64 | ) ELSE ( 65 | ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%" 66 | EXIT 1 67 | ) 68 | ) 69 | 70 | IF %PYTHON_ARCH% == 64 ( 71 | IF %SET_SDK_64% == Y ( 72 | ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture 73 | SET DISTUTILS_USE_SDK=1 74 | SET MSSdk=1 75 | "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION% 76 | "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release 77 | ECHO Executing: %COMMAND_TO_RUN% 78 | call %COMMAND_TO_RUN% || EXIT 1 79 | ) ELSE ( 80 | ECHO Using default MSVC build environment for 64 bit architecture 81 | ECHO Executing: %COMMAND_TO_RUN% 82 | call %COMMAND_TO_RUN% || EXIT 1 83 | ) 84 | ) ELSE ( 85 | ECHO Using default MSVC build environment for 32 bit architecture 86 | ECHO Executing: %COMMAND_TO_RUN% 87 | call %COMMAND_TO_RUN% || EXIT 1 88 | ) 89 | -------------------------------------------------------------------------------- /tests/pcapytests.py: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2021 Miroslav Stampar (miroslav@sqlmap.org) 2 | ## Copyright (c) 2014 CORE Security Technologies 3 | ## 4 | ## This software is provided under under the Apache Software License. 5 | ## See the accompanying LICENSE file for more information. 6 | ## 7 | 8 | import pcapy 9 | import sys 10 | import unittest 11 | import os 12 | 13 | 14 | class TestPcapy(unittest.TestCase): 15 | 16 | _96PINGS = '96pings.pcap' 17 | _IFACE = 'vboxnet0' 18 | 19 | def testPacketHeaderRefCount(self): 20 | """ 21 | #1: when next() creates a pkthdr it makes one extra reference 22 | """ 23 | 24 | class _Simple: 25 | pass 26 | 27 | r = pcapy.open_offline(TestPcapy._96PINGS) 28 | 29 | # get one & check its refcount 30 | self.assertEqual( 31 | sys.getrefcount(r.next()[0]), 32 | sys.getrefcount(_Simple())) 33 | 34 | def testEOFValue(self): 35 | """ 36 | #2 empty string is returned as packet body at end of file 37 | """ 38 | 39 | r = pcapy.open_offline(TestPcapy._96PINGS) 40 | # get one & check its refcount 41 | 42 | i = 0 43 | refNone = sys.getrefcount(None) 44 | hdr, pkt = r.next() 45 | while hdr is not None: 46 | hdr, pkt = r.next() 47 | i += 1 48 | self.assertEqual(96, i) 49 | self.assertTrue(hdr is None) 50 | self.assertEqual(pkt, b'') 51 | del hdr 52 | self.assertEqual(refNone, sys.getrefcount(None)) 53 | 54 | def testBPFFilter(self): 55 | """ 56 | #3 test offline BPFFilter 57 | """ 58 | r = pcapy.open_offline(TestPcapy._96PINGS) 59 | bpf = pcapy.BPFProgram("ip dst host 192.168.1.1") 60 | 61 | hdr, pkt = r.next() 62 | while hdr is not None: 63 | f = bpf.filter(pkt) 64 | self.assertNotEqual(f, 0) 65 | hdr, pkt = r.next() 66 | 67 | def _testLiveCapture(self): 68 | """ 69 | #4 (disabled -- requires interface info) test live capture 70 | """ 71 | r = pcapy.open_live(TestPcapy._IFACE, 60000, 1, 1500) 72 | net = r.getnet() 73 | self.assertEqual(net, '192.168.56.0') 74 | hdr, body = r.next() 75 | self.assertTrue(hdr is not None) 76 | 77 | def _testSendPacket(self): 78 | """ 79 | #5 (disabled -- requires interface info) test sendpacket 80 | """ 81 | r = pcapy.open_offline(TestPcapy._96PINGS) 82 | w = pcapy.open_live(TestPcapy._IFACE, 60000, 1, 1500) 83 | # get one & check its refcount 84 | 85 | i = 0 86 | hdr, pkt = r.next() 87 | while hdr is not None: 88 | w.sendpacket(pkt) 89 | hdr, pkt = r.next() 90 | i += 1 91 | 92 | def testPacketDumper(self): 93 | """ 94 | #6 test that the dumper writes correct payload 95 | """ 96 | try: 97 | r = pcapy.open_offline(TestPcapy._96PINGS) 98 | dumper = r.dump_open('tmp.pcap') 99 | 100 | hdr, body = r.next() 101 | i = 0 102 | while hdr is not None: 103 | dumper.dump(hdr, body) 104 | i += 1 105 | hdr, body = r.next() 106 | 107 | # make sure file closes 108 | del dumper 109 | 110 | # check that the dumper wrote a legal pcap 111 | # file with same packer data 112 | r = pcapy.open_offline(TestPcapy._96PINGS) 113 | r2 = pcapy.open_offline('tmp.pcap') 114 | 115 | h1, b1 = r.next() 116 | h2, b2 = r2.next() 117 | while h1 is not None and h2 is not None: 118 | self.assertEqual(b1, b2) 119 | h1, b1 = r.next() 120 | h2, b2 = r2.next() 121 | 122 | self.assertTrue(h1 is None) 123 | self.assertTrue(h2 is None) 124 | del r2 125 | finally: 126 | os.unlink('tmp.pcap') 127 | 128 | def testClose(self): 129 | """ 130 | #7 Test the close method 131 | """ 132 | r = pcapy.open_offline(TestPcapy._96PINGS) 133 | hdr, body = r.next() 134 | assert hdr is not None 135 | r.close() 136 | with self.assertRaises(ValueError): 137 | r.next() 138 | 139 | def testContextManager(self): 140 | """ 141 | #8 Test the context manager support 142 | """ 143 | with pcapy.open_offline(TestPcapy._96PINGS) as r: 144 | hdr, body = r.next() 145 | assert hdr is not None 146 | 147 | with self.assertRaises(ValueError): 148 | r.next() 149 | 150 | def test_get_bpf(self): 151 | bpf = pcapy.compile(pcapy.DLT_EN10MB, 2**16, "icmp", 1, 1) 152 | code = bpf.get_bpf() 153 | 154 | # result of `tcpdump "icmp" -ddd -s 65536` on EN10MB interface 155 | expected = """6 156 | 40 0 0 12 157 | 21 0 3 2048 158 | 48 0 0 23 159 | 21 0 1 1 160 | 6 0 0 65536 161 | 6 0 0 0""" 162 | 163 | result = str(len(code)) + "\n" 164 | result += "\n".join([' '.join(map(str, inst)) for inst in code]) 165 | 166 | self.assertEqual(expected, result) 167 | 168 | 169 | suite = unittest.TestLoader().loadTestsFromTestCase(TestPcapy) 170 | result = unittest.TextTestRunner(verbosity=2).run(suite) 171 | if not result.wasSuccessful(): 172 | sys.exit(1) 173 | -------------------------------------------------------------------------------- /pcap_pkthdr.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Miroslav Stampar (miroslav@sqlmap.org) 3 | * Copyright (c) 2014 CORE Security Technologies 4 | * 5 | * This software is provided under under the Apache Software License. 6 | * See the accompanying LICENSE file for more information. 7 | * 8 | */ 9 | 10 | #define PY_SSIZE_T_CLEAN 11 | 12 | #include 13 | #include 14 | 15 | #include "pcapy.h" 16 | #include "pcap_pkthdr.h" 17 | 18 | #ifdef WIN32 19 | #include 20 | #else 21 | #include 22 | #endif 23 | 24 | 25 | // internal pcapobject 26 | typedef struct { 27 | PyObject_HEAD 28 | struct timeval ts; 29 | bpf_u_int32 caplen; 30 | bpf_u_int32 len; 31 | } pkthdr; 32 | 33 | 34 | // Pkthdr_Type 35 | 36 | static void 37 | pcap_dealloc(pkthdr* pp) 38 | { 39 | PyObject_Del(pp); 40 | } 41 | 42 | 43 | // pcap methods 44 | static PyObject* p_getts(pkthdr* pp, PyObject* args); 45 | static PyObject* p_getcaplen(pkthdr* pp, PyObject* args); 46 | static PyObject* p_getlen(pkthdr* pp, PyObject* args); 47 | 48 | 49 | static PyMethodDef p_methods[] = { 50 | {"getts", (PyCFunction) p_getts, METH_VARARGS, "get timestamp tuple (seconds, microseconds) since the Epoch"}, 51 | {"getcaplen", (PyCFunction) p_getcaplen, METH_VARARGS, "returns the length of portion present"}, 52 | {"getlen", (PyCFunction) p_getlen, METH_VARARGS, "returns the length of the packet (off wire)"}, 53 | {NULL, NULL} /* sentinel */ 54 | }; 55 | 56 | static PyObject* 57 | pcap_getattr(pkthdr* pp, char* name) 58 | { 59 | #if PY_MAJOR_VERSION >= 3 60 | PyObject *nameobj = PyUnicode_FromString(name); 61 | PyObject *attr = PyObject_GenericGetAttr((PyObject *)pp, nameobj); 62 | Py_DECREF(nameobj); 63 | return attr; 64 | #else 65 | return Py_FindMethod(p_methods, (PyObject*)pp, name); 66 | #endif 67 | } 68 | 69 | 70 | PyTypeObject Pkthdr_type = { 71 | #if PY_MAJOR_VERSION >= 3 72 | PyVarObject_HEAD_INIT(&PyType_Type, 0) 73 | "Pkthdr", /* tp_name */ 74 | sizeof(pkthdr), /* tp_basicsize */ 75 | 0, /* tp_itemsize */ 76 | (destructor)pcap_dealloc, /* tp_dealloc */ 77 | 0, /* tp_print */ 78 | (getattrfunc)pcap_getattr, /* tp_getattr */ 79 | 0, /* tp_setattr */ 80 | 0, /* tp_reserved */ 81 | 0, /* tp_repr */ 82 | 0, /* tp_as_number */ 83 | 0, /* tp_as_sequence */ 84 | 0, /* tp_as_mapping */ 85 | 0, /* tp_hash */ 86 | 0, /* tp_call */ 87 | 0, /* tp_str */ 88 | 0, /* tp_getattro */ 89 | 0, /* tp_setattro */ 90 | 0, /* tp_as_buffer */ 91 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 92 | NULL, /* tp_doc */ 93 | 0, /* tp_traverse */ 94 | 0, /* tp_clear */ 95 | 0, /* tp_richcompare */ 96 | 0, /* tp_weaklistoffset */ 97 | 0, /* tp_iter */ 98 | 0, /* tp_iternext */ 99 | p_methods, /* tp_methods */ 100 | 0, /* tp_members */ 101 | 0, /* tp_getset */ 102 | 0, /* tp_base */ 103 | 0, /* tp_dict */ 104 | 0, /* tp_descr_get */ 105 | 0, /* tp_descr_set */ 106 | 0, /* tp_dictoffset */ 107 | 0, /* tp_init */ 108 | 0, /* tp_alloc */ 109 | 0, /* tp_new */ 110 | #else 111 | PyObject_HEAD_INIT(NULL) 112 | 0, 113 | "Pkthdr", 114 | sizeof(pkthdr), 115 | 0, 116 | 117 | /* methods */ 118 | (destructor)pcap_dealloc, /* tp_dealloc*/ 119 | 0, /* tp_print*/ 120 | (getattrfunc)pcap_getattr, /* tp_getattr*/ 121 | 0, /* tp_setattr*/ 122 | 0, /* tp_compare*/ 123 | 0, /* tp_repr*/ 124 | 0, /* tp_as_number*/ 125 | 0, /* tp_as_sequence*/ 126 | 0, /* tp_as_mapping*/ 127 | #endif 128 | }; 129 | 130 | 131 | PyObject* 132 | new_pcap_pkthdr(const struct pcap_pkthdr* hdr) 133 | { 134 | if (PyType_Ready(&Pkthdr_type) < 0) 135 | return NULL; 136 | 137 | pkthdr *pp; 138 | 139 | pp = PyObject_New(pkthdr, &Pkthdr_type); 140 | if (pp == NULL) 141 | return NULL; 142 | 143 | pp->ts = hdr->ts; 144 | pp->caplen = hdr->caplen; 145 | pp->len = hdr->len; 146 | 147 | return (PyObject*)pp; 148 | } 149 | 150 | static PyObject* 151 | p_getts(pkthdr* pp, PyObject* args) 152 | { 153 | if (Py_TYPE(pp) != &Pkthdr_type) { 154 | PyErr_SetString(PcapError, "Not a pkthdr object"); 155 | return NULL; 156 | } 157 | 158 | return Py_BuildValue("(ll)", pp->ts.tv_sec, pp->ts.tv_usec); 159 | } 160 | 161 | static PyObject* 162 | p_getcaplen(pkthdr* pp, PyObject* args) 163 | { 164 | if (Py_TYPE(pp) != &Pkthdr_type) { 165 | PyErr_SetString(PcapError, "Not a pkthdr object"); 166 | return NULL; 167 | } 168 | 169 | return Py_BuildValue("l", pp->caplen); 170 | } 171 | 172 | static PyObject* 173 | p_getlen(pkthdr* pp, PyObject* args) 174 | { 175 | if (Py_TYPE(pp) != &Pkthdr_type) { 176 | PyErr_SetString(PcapError, "Not a pkthdr object"); 177 | return NULL; 178 | } 179 | 180 | return Py_BuildValue("l", pp->len); 181 | } 182 | 183 | int 184 | pkthdr_to_native(PyObject *pyhdr, struct pcap_pkthdr *hdr) 185 | { 186 | if (Py_TYPE(pyhdr) != &Pkthdr_type) { 187 | PyErr_SetString(PcapError, "Not a pkthdr object"); 188 | return -1; 189 | } 190 | 191 | pkthdr *pp = (pkthdr *) pyhdr; 192 | 193 | hdr->ts = pp->ts; 194 | hdr->caplen = pp->caplen; 195 | hdr->len = pp->len; 196 | 197 | return 0; 198 | } 199 | /* vim: set tabstop=2 shiftwidth=2 expandtab: */ 200 | -------------------------------------------------------------------------------- /pcapdumper.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Miroslav Stampar (miroslav@sqlmap.org) 3 | * Copyright (c) 2014 CORE Security Technologies 4 | * 5 | * This software is provided under under the Apache Software License. 6 | * See the accompanying LICENSE file for more information. 7 | * 8 | */ 9 | 10 | #define PY_SSIZE_T_CLEAN 11 | 12 | #include 13 | #include 14 | 15 | #include "pcapdumper.h" 16 | #include "pcap_pkthdr.h" 17 | #include "pcapy.h" 18 | 19 | // internal pcapdumper 20 | typedef struct { 21 | PyObject_HEAD 22 | pcap_dumper_t *dumper; 23 | } pcapdumper; 24 | 25 | static bool validate_pcapdumper(const pcapdumper* pp); 26 | 27 | // Pdumpertype 28 | 29 | static void 30 | pcap_dealloc(pcapdumper* pp) 31 | { 32 | if ( pp->dumper ) 33 | pcap_dump_close(pp->dumper); 34 | 35 | pp->dumper = NULL; 36 | 37 | PyObject_Del(pp); 38 | } 39 | 40 | 41 | // pcap methods 42 | static PyObject* p_close(pcapdumper* pp, PyObject* args); 43 | static PyObject* p_dump(pcapdumper* pp, PyObject* args); 44 | 45 | 46 | static PyMethodDef p_methods[] = { 47 | {"close", (PyCFunction) p_close, METH_VARARGS, "loops packet dispatching"}, 48 | {"dump", (PyCFunction) p_dump, METH_VARARGS, "dump a packet to the file"}, 49 | {NULL, NULL} /* sentinel */ 50 | }; 51 | 52 | static PyObject* 53 | pcap_getattr(pcapdumper* pp, char* name) 54 | { 55 | #if PY_MAJOR_VERSION >= 3 56 | PyObject *nameobj = PyUnicode_FromString(name); 57 | PyObject *attr = PyObject_GenericGetAttr((PyObject *)pp, nameobj); 58 | Py_DECREF(nameobj); 59 | return attr; 60 | #else 61 | return Py_FindMethod(p_methods, (PyObject*)pp, name); 62 | #endif 63 | } 64 | 65 | 66 | PyTypeObject Pdumpertype = { 67 | #if PY_MAJOR_VERSION >= 3 68 | PyVarObject_HEAD_INIT(&PyType_Type, 0) 69 | "Dumper", /* tp_name */ 70 | sizeof(pcapdumper), /* tp_basicsize */ 71 | 0, /* tp_itemsize */ 72 | (destructor)pcap_dealloc, /* tp_dealloc */ 73 | 0, /* tp_print */ 74 | (getattrfunc)pcap_getattr, /* tp_getattr */ 75 | 0, /* tp_setattr */ 76 | 0, /* tp_reserved */ 77 | 0, /* tp_repr */ 78 | 0, /* tp_as_number */ 79 | 0, /* tp_as_sequence */ 80 | 0, /* tp_as_mapping */ 81 | 0, /* tp_hash */ 82 | 0, /* tp_call */ 83 | 0, /* tp_str */ 84 | 0, /* tp_getattro */ 85 | 0, /* tp_setattro */ 86 | 0, /* tp_as_buffer */ 87 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 88 | NULL, /* tp_doc */ 89 | 0, /* tp_traverse */ 90 | 0, /* tp_clear */ 91 | 0, /* tp_richcompare */ 92 | 0, /* tp_weaklistoffset */ 93 | 0, /* tp_iter */ 94 | 0, /* tp_iternext */ 95 | p_methods, /* tp_methods */ 96 | 0, /* tp_members */ 97 | 0, /* tp_getset */ 98 | 0, /* tp_base */ 99 | 0, /* tp_dict */ 100 | 0, /* tp_descr_get */ 101 | 0, /* tp_descr_set */ 102 | 0, /* tp_dictoffset */ 103 | 0, /* tp_init */ 104 | 0, /* tp_alloc */ 105 | 0, /* tp_new */ 106 | #else 107 | PyObject_HEAD_INIT(NULL) 108 | 0, 109 | "Dumper", 110 | sizeof(pcapdumper), 111 | 0, 112 | /* methods */ 113 | (destructor)pcap_dealloc, /* tp_dealloc */ 114 | 0, /* tp_print */ 115 | (getattrfunc)pcap_getattr, /* tp_getattr */ 116 | 0, /* tp_setattr */ 117 | 0, /* tp_compare */ 118 | 0, /* tp_repr */ 119 | 0, /* tp_as_number */ 120 | 0, /* tp_as_sequence */ 121 | 0, /* tp_as_mapping */ 122 | #endif 123 | }; 124 | 125 | PyObject* 126 | new_pcapdumper(pcap_dumper_t *dumper) 127 | { 128 | if (PyType_Ready(&Pdumpertype) < 0) 129 | return NULL; 130 | 131 | pcapdumper *pp; 132 | 133 | pp = PyObject_New(pcapdumper, &Pdumpertype); 134 | if (pp == NULL) 135 | return NULL; 136 | 137 | pp->dumper = dumper; 138 | 139 | return (PyObject*)pp; 140 | } 141 | 142 | static PyObject* 143 | p_dump(pcapdumper* pp, PyObject* args) 144 | { 145 | PyObject *pyhdr; 146 | u_char *data; 147 | Py_ssize_t len; 148 | 149 | if(validate_pcapdumper(pp) == false){ 150 | return NULL; 151 | } 152 | 153 | #if PY_MAJOR_VERSION >= 3 154 | if (!PyArg_ParseTuple(args,"Oy#",&pyhdr,&data,&len)){ 155 | return NULL; 156 | } 157 | #else 158 | if (!PyArg_ParseTuple(args,"Os#",&pyhdr,&data,&len)){ 159 | return NULL; 160 | } 161 | #endif 162 | 163 | struct pcap_pkthdr hdr; 164 | if (-1 == pkthdr_to_native(pyhdr, &hdr)) 165 | return NULL; 166 | 167 | if (pp->dumper == NULL){ 168 | PyErr_SetString(PcapError, "Dumper is already closed."); 169 | return NULL; 170 | } 171 | 172 | pcap_dump((u_char *)pp->dumper, &hdr, data); 173 | 174 | Py_INCREF(Py_None); 175 | return Py_None; 176 | } 177 | 178 | // PdumperClose 179 | 180 | static PyObject* 181 | p_close(pcapdumper* pp, PyObject* args) 182 | { 183 | if(validate_pcapdumper(pp) == false){ 184 | return NULL; 185 | } 186 | 187 | if ( pp->dumper ) 188 | pcap_dump_close(pp->dumper); 189 | 190 | pp->dumper = NULL; 191 | 192 | Py_INCREF(Py_None); 193 | return Py_None; 194 | } 195 | 196 | static bool 197 | validate_pcapdumper(const pcapdumper* pp){ 198 | if (pp == NULL || Py_TYPE(pp) != &Pdumpertype) { 199 | PyErr_SetString(PcapError, "Not a pcapdumper object"); 200 | return false; 201 | } 202 | return true; 203 | } 204 | -------------------------------------------------------------------------------- /bpfobj.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Miroslav Stampar (miroslav@sqlmap.org) 3 | * Copyright (c) 2014 CORE Security Technologies 4 | * 5 | * This software is provided under under the Apache Software License. 6 | * See the accompanying LICENSE file for more information. 7 | * 8 | */ 9 | 10 | #define PY_SSIZE_T_CLEAN 11 | 12 | #include 13 | #include 14 | 15 | #include "bpfobj.h" 16 | #include "pcapy.h" 17 | 18 | 19 | // internal bpfobject 20 | typedef struct { 21 | PyObject_HEAD 22 | struct bpf_program bpf; 23 | } bpfobject; 24 | 25 | 26 | // BPFProgramType 27 | 28 | static void 29 | bpfprog_dealloc(bpfobject* bpf) 30 | { 31 | #ifndef WIN32 // XXX: is this missing from winpcap 2.3? 32 | pcap_freecode(&bpf->bpf); 33 | #endif 34 | PyObject_Del(bpf); 35 | } 36 | 37 | PyObject* BPFError; 38 | 39 | 40 | // BPFProgram methods 41 | static PyObject* p_filter(bpfobject* bpf, PyObject* args); 42 | static PyObject* p_get_bpf(bpfobject* bpf, PyObject* args); 43 | static PyObject* p_new_bpfobject(PyTypeObject *type, PyObject* args, PyObject *kwags); 44 | 45 | 46 | static PyMethodDef bpf_methods[] = { 47 | {"filter", (PyCFunction) p_filter, METH_VARARGS, "filter(packet) applies the filter to the packet, returns 0 if there's no match"}, 48 | {"get_bpf", (PyCFunction) p_get_bpf, METH_NOARGS, "return packet-matching code as decimal numbers"}, 49 | {NULL, NULL} /* sentinel */ 50 | }; 51 | 52 | static PyObject* 53 | bpfprog_getattr(bpfobject* pp, char* name) 54 | { 55 | #if PY_MAJOR_VERSION >= 3 56 | PyObject *nameobj = PyUnicode_FromString(name); 57 | PyObject *attr = PyObject_GenericGetAttr((PyObject *)pp, nameobj); 58 | Py_DECREF(nameobj); 59 | return attr; 60 | #else 61 | return Py_FindMethod(bpf_methods, (PyObject*)pp, name); 62 | #endif 63 | } 64 | 65 | 66 | PyTypeObject BPFProgramType = { 67 | #if PY_MAJOR_VERSION >= 3 68 | PyVarObject_HEAD_INIT(&PyType_Type, 0) 69 | "BPFProgram", /* tp_name */ 70 | sizeof(bpfobject), /* tp_basicsize */ 71 | 0, /* tp_itemsize */ 72 | (destructor)bpfprog_dealloc, /* tp_dealloc */ 73 | 0, /* tp_print */ 74 | (getattrfunc)bpfprog_getattr, /* tp_getattr */ 75 | 0, /* tp_setattr */ 76 | 0, /* tp_reserved */ 77 | 0, /* tp_repr */ 78 | 0, /* tp_as_number */ 79 | 0, /* tp_as_sequence */ 80 | 0, /* tp_as_mapping */ 81 | 0, /* tp_hash */ 82 | 0, /* tp_call */ 83 | 0, /* tp_str */ 84 | 0, /* tp_getattro */ 85 | 0, /* tp_setattro */ 86 | 0, /* tp_as_buffer */ 87 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 88 | "BPF Program Wrapper", /* tp_doc */ 89 | 0, /* tp_traverse */ 90 | 0, /* tp_clear */ 91 | 0, /* tp_richcompare */ 92 | 0, /* tp_weaklistoffset */ 93 | 0, /* tp_iter */ 94 | 0, /* tp_iternext */ 95 | bpf_methods, /* tp_methods */ 96 | 0, /* tp_members */ 97 | 0, /* tp_getset */ 98 | 0, /* tp_base */ 99 | 0, /* tp_dict */ 100 | 0, /* tp_descr_get */ 101 | 0, /* tp_descr_set */ 102 | 0, /* tp_dictoffset */ 103 | 0, /* tp_init */ 104 | 0, /* tp_alloc */ 105 | p_new_bpfobject /* tp_new */ 106 | #else 107 | PyObject_HEAD_INIT(NULL) 108 | 0, 109 | "BPFProgram", 110 | sizeof(bpfobject), 111 | 0, 112 | /* methods */ 113 | (destructor)bpfprog_dealloc, /* tp_dealloc*/ 114 | 0, /* tp_print*/ 115 | (getattrfunc)bpfprog_getattr, /* tp_getattr*/ 116 | 0, /* tp_setattr*/ 117 | 0, /*tp_compare*/ 118 | 0, /*tp_repr*/ 119 | 0, /*tp_as_number*/ 120 | 0, /*tp_as_sequence*/ 121 | 0, /*tp_as_mapping*/ 122 | 0, /*tp_hash */ 123 | 0, /*tp_call*/ 124 | 0, /*tp_str*/ 125 | 0, /*tp_getattro*/ 126 | 0, /*tp_setattro*/ 127 | 0, /*tp_as_buffer*/ 128 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 129 | /*tp_flags*/ 130 | "BPF Program Wrapper", /* tp_doc */ 131 | 0, /* tp_traverse */ 132 | 0, /* tp_clear */ 133 | 0, /* tp_richcompare */ 134 | 0, /* tp_weaklistoffset */ 135 | 0, /* tp_iter */ 136 | 0, /* tp_iternext */ 137 | bpf_methods, /* tp_methods */ 138 | 0, /* tp_members */ 139 | 0, /* tp_getset */ 140 | 0, /* tp_base */ 141 | 0, /* tp_dict */ 142 | 0, /* tp_descr_get */ 143 | 0, /* tp_descr_set */ 144 | 0, /* tp_dictoffset */ 145 | 0, /* tp_init */ 146 | 0, /* tp_alloc */ 147 | p_new_bpfobject /* tp_new */ 148 | #endif 149 | }; 150 | 151 | 152 | PyObject* 153 | new_bpfobject(const struct bpf_program &bpfprog) 154 | { 155 | if (PyType_Ready(&BPFProgramType) < 0) 156 | return NULL; 157 | 158 | bpfobject *bpf; 159 | bpf = PyObject_New(bpfobject, &BPFProgramType); 160 | if (bpf == NULL) 161 | { 162 | PyErr_SetString(BPFError, "Failed to create object"); 163 | return NULL; 164 | } 165 | 166 | bpf->bpf = bpfprog; 167 | return (PyObject*)bpf; 168 | } 169 | 170 | 171 | static PyObject* 172 | p_new_bpfobject(PyTypeObject *type, PyObject *args, PyObject *kwds) 173 | { 174 | char *filter_string; 175 | int linktype = 1; // DLT_EN10MB 176 | if (!PyArg_ParseTuple(args, "s|i", &filter_string, &linktype)){ 177 | return NULL; 178 | } 179 | 180 | struct bpf_program bpfprog; 181 | 182 | if (pcap_compile_nopcap((1<<16), linktype, &bpfprog, filter_string, 0, 0)){ 183 | PyErr_SetString(BPFError, "Couldn't compile BPF program"); 184 | return NULL; 185 | } 186 | 187 | return new_bpfobject(bpfprog); 188 | } 189 | 190 | 191 | static PyObject* 192 | p_filter(bpfobject* bpf, PyObject* args) 193 | { 194 | int status; 195 | u_char* packet; 196 | Py_ssize_t len; 197 | 198 | if (Py_TYPE(bpf) != &BPFProgramType) 199 | { 200 | PyErr_SetString(BPFError, "Not a bpfprogram object"); 201 | return NULL; 202 | } 203 | 204 | #if PY_MAJOR_VERSION >= 3 205 | if (!PyArg_ParseTuple(args,"y#:filter",&packet, &len)){ 206 | return NULL; 207 | } 208 | #else 209 | if (!PyArg_ParseTuple(args,"s#:filter",&packet, &len)){ 210 | return NULL; 211 | } 212 | #endif 213 | 214 | status = bpf_filter(bpf->bpf.bf_insns, 215 | packet, 216 | len, len); 217 | 218 | return Py_BuildValue("i", status); 219 | } 220 | 221 | static PyObject* 222 | p_get_bpf(bpfobject* bpf, PyObject* args) 223 | { 224 | struct bpf_insn *insn; 225 | int i; 226 | int n = bpf->bpf.bf_len; 227 | PyObject* list; 228 | PyObject* instruction; 229 | 230 | insn = bpf->bpf.bf_insns; 231 | 232 | if (Py_TYPE(bpf) != &BPFProgramType) 233 | { 234 | PyErr_SetString(BPFError, "Not a bpfprogram object"); 235 | return NULL; 236 | } 237 | 238 | list = PyList_New(n); 239 | if (!list) { 240 | return NULL; 241 | } 242 | 243 | for (i = 0; i < n; ++insn, ++i) { 244 | instruction = Py_BuildValue("IIII", insn->code, insn->jt, insn->jf, insn->k); 245 | if (!instruction) { 246 | Py_DECREF(list); 247 | return NULL; 248 | } 249 | PyList_SET_ITEM(list, i, instruction); 250 | } 251 | 252 | return list; 253 | } 254 | -------------------------------------------------------------------------------- /pcapy.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Miroslav Stampar (miroslav@sqlmap.org) 3 | * Copyright (c) 2014 CORE Security Technologies 4 | * 5 | * This software is provided under under the Apache Software License. 6 | * See the accompanying LICENSE file for more information. 7 | * 8 | */ 9 | 10 | #define PY_SSIZE_T_CLEAN 11 | 12 | #include 13 | #include 14 | #ifdef WIN32 15 | #include // IPHelper API for luid/guid conversions 16 | #endif 17 | 18 | #include "pcapy.h" 19 | #include "pcapobj.h" 20 | #include "bpfobj.h" 21 | #include "pcapdumper.h" 22 | #include "pcap_pkthdr.h" 23 | 24 | 25 | PyObject *PcapError; 26 | 27 | 28 | 29 | // module methods 30 | 31 | static PyObject* 32 | lookupdev(PyObject* self, PyObject* args) 33 | { 34 | char errbuff[PCAP_ERRBUF_SIZE]; 35 | char* dev; 36 | 37 | dev = pcap_lookupdev(errbuff); 38 | if(!dev) 39 | { 40 | PyErr_SetString(PcapError, errbuff); 41 | return NULL; 42 | } 43 | 44 | return Py_BuildValue("u", dev); 45 | } 46 | 47 | static PyObject* 48 | findalldevs(PyObject *self, PyObject *args) 49 | { 50 | char errbuff[PCAP_ERRBUF_SIZE]; 51 | pcap_if_t *devs; 52 | 53 | int status = pcap_findalldevs(&devs, errbuff); 54 | if(status) 55 | { 56 | PyErr_SetString(PcapError, errbuff); 57 | return NULL; 58 | } 59 | 60 | if(devs==NULL) 61 | { 62 | PyErr_SetString(PcapError, "No valid interfaces to open"); 63 | return NULL; 64 | } 65 | 66 | pcap_if_t *cursor = devs; 67 | PyObject* list = PyList_New(0); 68 | while(cursor) 69 | { 70 | #ifdef WIN32 71 | /* If we are on windows, then display LUID's like "Local Area Connection" 72 | * instead of GUID's like "\Device\NPF_{AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA}". 73 | */ 74 | char *luid = get_windows_interface_friendly_name(cursor->name); 75 | PyList_Append(list, Py_BuildValue("s", luid)); 76 | free(luid); 77 | #else 78 | PyList_Append(list, Py_BuildValue("s", cursor->name)); 79 | #endif 80 | cursor = cursor->next; 81 | } 82 | 83 | pcap_freealldevs(devs); 84 | 85 | return list; 86 | } 87 | 88 | static PyObject* 89 | open_live(PyObject *self, PyObject *args) 90 | { 91 | char errbuff[PCAP_ERRBUF_SIZE]; 92 | char * device; 93 | int snaplen; 94 | int promisc; 95 | int to_ms; 96 | 97 | bpf_u_int32 net, mask; 98 | 99 | 100 | if(!PyArg_ParseTuple(args,"siii:open_live",&device,&snaplen,&promisc,&to_ms)) 101 | return NULL; 102 | 103 | #ifdef WIN32 104 | /* If we are on windows, then device is an LUID like "Local Area Connection". 105 | * pcap on Windows needs a GUID like "\Device\NPF_{AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA}". 106 | */ 107 | device = luid_to_guid(device); 108 | #endif 109 | int status = pcap_lookupnet(device, &net, &mask, errbuff); 110 | if(status) 111 | { 112 | net = 0; 113 | mask = 0; 114 | } 115 | 116 | pcap_t* pt; 117 | 118 | pt = pcap_open_live(device, snaplen, promisc!=0, to_ms, errbuff); 119 | #ifdef WIN32 120 | free(device); 121 | #endif 122 | 123 | if(!pt) 124 | { 125 | PyErr_SetString(PcapError, errbuff); 126 | return NULL; 127 | } 128 | #ifdef WIN32 129 | //According to the doc 130 | // pcap_setmintocopy() changes the minimum amount of data in the kernel buffer that causes a read from the application to return (unless the timeout expires) 131 | // [...] pcap_open_live() sets a default mintocopy value of 16000 bytes. 132 | //It is a better practice to set it to 0, so that we are transparent about what we receive 133 | pcap_setmintocopy(pt, 0); 134 | #endif 135 | 136 | return new_pcapobject( pt, net, mask ); 137 | } 138 | 139 | static PyObject* 140 | pcap_create(PyObject *self, PyObject *args) 141 | { 142 | char errbuff[PCAP_ERRBUF_SIZE]; 143 | char * device; 144 | 145 | bpf_u_int32 net, mask; 146 | 147 | 148 | if (!PyArg_ParseTuple(args, "s:pcap_create", &device)) 149 | return NULL; 150 | 151 | int status = pcap_lookupnet(device, &net, &mask, errbuff); 152 | if (status) 153 | { 154 | net = 0; 155 | mask = 0; 156 | } 157 | 158 | pcap_t* pt; 159 | 160 | pt = pcap_create(device, errbuff); 161 | if (!pt) 162 | { 163 | PyErr_SetString(PcapError, errbuff); 164 | return NULL; 165 | } 166 | #ifdef WIN32 167 | //Same than in open_live 168 | pcap_setmintocopy(pt, 0); 169 | #endif 170 | 171 | return new_pcapobject(pt, net, mask); 172 | } 173 | 174 | static PyObject* 175 | open_offline(PyObject *self, PyObject *args) 176 | { 177 | char errbuff[PCAP_ERRBUF_SIZE]; 178 | char * filename; 179 | 180 | 181 | if(!PyArg_ParseTuple(args,"s",&filename)) 182 | return NULL; 183 | 184 | pcap_t* pt; 185 | 186 | pt = pcap_open_offline(filename, errbuff); 187 | if(!pt) 188 | { 189 | PyErr_SetString(PcapError, errbuff); 190 | return NULL; 191 | } 192 | #ifdef WIN32 193 | pcap_setmintocopy(pt, 0); 194 | #endif 195 | 196 | return new_pcapobject( pt ); 197 | } 198 | 199 | 200 | static PyObject* 201 | bpf_compile(PyObject* self, PyObject* args) 202 | { 203 | int linktype; 204 | int snaplen; 205 | char *filter; 206 | int optimize; 207 | unsigned int netmask; 208 | 209 | if(!PyArg_ParseTuple(args, 210 | "iisiI:compile", 211 | &linktype, 212 | &snaplen, 213 | &filter, 214 | &optimize, 215 | &netmask)) 216 | return NULL; 217 | 218 | pcap_t *pp; 219 | 220 | pp = pcap_open_dead(linktype, snaplen); 221 | if(pp == NULL) 222 | return NULL; 223 | 224 | struct bpf_program bpf; 225 | int status = pcap_compile(pp, &bpf, filter, optimize, netmask); 226 | pcap_close(pp); 227 | 228 | if(status) 229 | { 230 | PyErr_SetString(PcapError, pcap_geterr(pp)); 231 | return NULL; 232 | } 233 | 234 | return new_bpfobject( bpf ); 235 | } 236 | 237 | 238 | static PyMethodDef pcap_methods[] = { 239 | {"open_live", open_live, METH_VARARGS, "open_live(device, snaplen, promisc, to_ms) opens a pcap device"}, 240 | {"open_offline", open_offline, METH_VARARGS, "open_offline(filename) opens a pcap formated file"}, 241 | {"lookupdev", lookupdev, METH_VARARGS, "lookupdev() looks up a pcap device"}, 242 | {"findalldevs", findalldevs, METH_VARARGS, "findalldevs() lists all available interfaces"}, 243 | {"compile", bpf_compile, METH_VARARGS, "compile(linktype, snaplen, filter, optimize, netmask) creates a bpfprogram object"}, 244 | {"create", pcap_create, METH_VARARGS, "create(device) is used to create a packet capture handle to look at packets on the network."}, 245 | {NULL, NULL} 246 | }; 247 | 248 | #if PY_MAJOR_VERSION >= 3 249 | PyDoc_STRVAR(pcap_doc, 250 | "A wrapper for the Packet Capture (PCAP) library"); 251 | 252 | static struct PyModuleDef pcapy_module = { 253 | PyModuleDef_HEAD_INIT, 254 | "pcapy", /* m_name */ 255 | pcap_doc, /* m_doc */ 256 | -1, /* m_size */ 257 | pcap_methods, /* m_methods */ 258 | NULL, /* m_reload */ 259 | NULL, /* m_traverse */ 260 | NULL, /* m_clear */ 261 | NULL, /* m_free */ 262 | }; 263 | #else 264 | 265 | static char *pcap_doc = 266 | "\nA wrapper for the Packet Capture (PCAP) library\n"; 267 | #endif //PY_MAJOR_VERSION >= 3 268 | 269 | 270 | #if PY_MAJOR_VERSION >= 3 271 | PyMODINIT_FUNC 272 | PyInit_pcapy(void) 273 | #else 274 | void 275 | initpcapy(void) 276 | #endif //PY_MAJOR_VERSION >= 3 277 | 278 | 279 | { 280 | PyObject *m, *d; 281 | 282 | 283 | #if PY_MAJOR_VERSION < 3 284 | Pcaptype.ob_type = &PyType_Type; 285 | Pkthdr_type.ob_type = &PyType_Type; 286 | Pdumpertype.ob_type = &PyType_Type; 287 | #endif 288 | 289 | 290 | #if PY_MAJOR_VERSION >= 3 291 | m = PyModule_Create(&pcapy_module); 292 | #else 293 | m = Py_InitModule3("pcapy", pcap_methods, pcap_doc); 294 | #endif 295 | 296 | if (PyType_Ready(&BPFProgramType) < 0) { 297 | #if PY_MAJOR_VERSION >= 3 298 | return NULL; 299 | #else 300 | return; 301 | #endif //PY_MAJOR_VERSION >= 3 302 | } 303 | 304 | PyModule_AddObject(m, "BPFProgram", (PyObject *) &BPFProgramType); 305 | 306 | /* Direct from pcap's net/bpf.h. */ 307 | PyModule_AddIntConstant(m, "DLT_NULL", 0); 308 | PyModule_AddIntConstant(m, "DLT_EN10MB", 1); 309 | PyModule_AddIntConstant(m, "DLT_IEEE802", 6); 310 | PyModule_AddIntConstant(m, "DLT_ARCNET", 7); 311 | PyModule_AddIntConstant(m, "DLT_SLIP", 8); 312 | PyModule_AddIntConstant(m, "DLT_PPP", 9); 313 | PyModule_AddIntConstant(m, "DLT_FDDI", 10); 314 | PyModule_AddIntConstant(m, "DLT_ATM_RFC1483", 11); 315 | PyModule_AddIntConstant(m, "DLT_RAW", 12); 316 | PyModule_AddIntConstant(m, "DLT_PPP_SERIAL", 50); 317 | PyModule_AddIntConstant(m, "DLT_PPP_ETHER", 51); 318 | PyModule_AddIntConstant(m, "DLT_C_HDLC", 104); 319 | PyModule_AddIntConstant(m, "DLT_IEEE802_11", 105); 320 | PyModule_AddIntConstant(m, "DLT_LOOP", 108); 321 | PyModule_AddIntConstant(m, "DLT_LINUX_SLL", 113); 322 | PyModule_AddIntConstant(m, "DLT_LTALK", 114); 323 | 324 | /* Direct from pcap's net/pcap.h.*/ 325 | PyModule_AddIntConstant(m, "PCAP_D_INOUT", 0); 326 | PyModule_AddIntConstant(m, "PCAP_D_IN", 1); 327 | PyModule_AddIntConstant(m, "PCAP_D_OUT", 2); 328 | 329 | d = PyModule_GetDict(m); 330 | PcapError = PyErr_NewException("pcapy.PcapError", NULL, NULL ); 331 | BPFError = PyErr_NewException("pcapy.BPFError", NULL, NULL ); 332 | if( PcapError ) 333 | { 334 | PyDict_SetItemString( d, "PcapError", PcapError ); 335 | } 336 | 337 | if ( BPFError ) 338 | { 339 | PyDict_SetItemString( d, "BPFError", BPFError ); 340 | } 341 | #if PY_MAJOR_VERSION >= 3 342 | return m; 343 | #endif //PY_MAJOR_VERSION >= 3 344 | } 345 | /* vim: set tabstop=2 shiftwidth=2 expandtab: */ 346 | 347 | #ifdef WIN32 348 | /* All of the following code takes care of LUID/GUID conversions. 349 | * Copied from Wireshark. 350 | */ 351 | 352 | static BOOL gethexdigit(const char *p) 353 | { 354 | if(*p >= '0' && *p <= '9'){ 355 | return *p - '0'; 356 | }else if(*p >= 'A' && *p <= 'F'){ 357 | return *p - 'A' + 0xA; 358 | }else if(*p >= 'a' && *p <= 'f'){ 359 | return *p - 'a' + 0xa; 360 | }else{ 361 | return -1; /* Not a hex digit */ 362 | } 363 | } 364 | 365 | static BOOL get8hexdigits(const char *p, DWORD *d) 366 | { 367 | int digit; 368 | DWORD val; 369 | int i; 370 | 371 | val = 0; 372 | for(i = 0; i < 8; i++){ 373 | digit = gethexdigit(p++); 374 | if(digit == -1){ 375 | return FALSE; /* Not a hex digit */ 376 | } 377 | val = (val << 4) | digit; 378 | } 379 | *d = val; 380 | return TRUE; 381 | } 382 | 383 | static BOOL get4hexdigits(const char *p, WORD *w) 384 | { 385 | int digit; 386 | WORD val; 387 | int i; 388 | 389 | val = 0; 390 | for(i = 0; i < 4; i++){ 391 | digit = gethexdigit(p++); 392 | if(digit == -1){ 393 | return FALSE; /* Not a hex digit */ 394 | } 395 | val = (val << 4) | digit; 396 | } 397 | *w = val; 398 | return TRUE; 399 | } 400 | 401 | static BOOL 402 | parse_as_guid(const char *guid_text, GUID *guid) 403 | { 404 | int i; 405 | int digit1, digit2; 406 | 407 | if(*guid_text != '{'){ 408 | return FALSE; /* Nope, not enclosed in {} */ 409 | } 410 | guid_text++; 411 | /* There must be 8 hex digits; if so, they go into guid->Data1 */ 412 | if(!get8hexdigits(guid_text, &guid->Data1)){ 413 | return FALSE; /* nope, not 8 hex digits */ 414 | } 415 | guid_text += 8; 416 | /* Now there must be a hyphen */ 417 | if(*guid_text != '-'){ 418 | return FALSE; /* Nope */ 419 | } 420 | guid_text++; 421 | /* There must be 4 hex digits; if so, they go into guid->Data2 */ 422 | if(!get4hexdigits(guid_text, &guid->Data2)){ 423 | return FALSE; /* nope, not 4 hex digits */ 424 | } 425 | guid_text += 4; 426 | /* Now there must be a hyphen */ 427 | if(*guid_text != '-'){ 428 | return FALSE; /* Nope */ 429 | } 430 | guid_text++; 431 | /* There must be 4 hex digits; if so, they go into guid->Data3 */ 432 | if(!get4hexdigits(guid_text, &guid->Data3)){ 433 | return FALSE; /* nope, not 4 hex digits */ 434 | } 435 | guid_text += 4; 436 | /* Now there must be a hyphen */ 437 | if(*guid_text != '-'){ 438 | return FALSE; /* Nope */ 439 | } 440 | guid_text++; 441 | /* 442 | * There must be 4 hex digits; if so, they go into the first 2 bytes 443 | * of guid->Data4. 444 | */ 445 | for(i = 0; i < 2; i++){ 446 | digit1 = gethexdigit(guid_text); 447 | if(digit1 == -1){ 448 | return FALSE; /* Not a hex digit */ 449 | } 450 | guid_text++; 451 | digit2 = gethexdigit(guid_text); 452 | if(digit2 == -1){ 453 | return FALSE; /* Not a hex digit */ 454 | } 455 | guid_text++; 456 | guid->Data4[i] = (digit1 << 4)|(digit2); 457 | } 458 | /* Now there must be a hyphen */ 459 | if(*guid_text != '-'){ 460 | return FALSE; /* Nope */ 461 | } 462 | guid_text++; 463 | /* 464 | * There must be 12 hex digits; if so,t hey go into the next 6 bytes 465 | * of guid->Data4. 466 | */ 467 | for(i = 0; i < 6; i++){ 468 | digit1 = gethexdigit(guid_text); 469 | if(digit1 == -1){ 470 | return FALSE; /* Not a hex digit */ 471 | } 472 | guid_text++; 473 | digit2 = gethexdigit(guid_text); 474 | if(digit2 == -1){ 475 | return FALSE; /* Not a hex digit */ 476 | } 477 | guid_text++; 478 | guid->Data4[i+2] = (digit1 << 4)|(digit2); 479 | } 480 | /* Now there must be a closing } */ 481 | if(*guid_text != '}'){ 482 | return FALSE; /* Nope */ 483 | } 484 | guid_text++; 485 | /* And that must be the end of the string */ 486 | if(*guid_text != '\0'){ 487 | return FALSE; /* Nope */ 488 | } 489 | return TRUE; 490 | } 491 | 492 | 493 | static char* luid_to_guid(char *luid) 494 | { 495 | char errbuff[PCAP_ERRBUF_SIZE]; 496 | pcap_if_t *devs; 497 | 498 | int status = pcap_findalldevs(&devs, errbuff); 499 | if(status) 500 | { 501 | PyErr_SetString(PcapError, errbuff); 502 | return NULL; 503 | } 504 | 505 | if(devs==NULL) 506 | { 507 | PyErr_SetString(PcapError, "No valid interfaces to open"); 508 | return NULL; 509 | } 510 | 511 | pcap_if_t *cursor = devs; 512 | 513 | char* cursor_luid; 514 | char *ret_guid = NULL; 515 | while(cursor) 516 | { 517 | cursor_luid = get_windows_interface_friendly_name(cursor->name); 518 | 519 | 520 | if (!strcmp(cursor_luid, luid)) 521 | { 522 | ret_guid = strdup(cursor->name); 523 | goto done; 524 | } 525 | 526 | free(cursor_luid); 527 | 528 | cursor = cursor->next; 529 | } 530 | 531 | done: 532 | 533 | pcap_freealldevs(devs); 534 | 535 | return ret_guid; 536 | } 537 | 538 | static char* guid_to_luid(GUID *guid) 539 | { 540 | BOOL status; 541 | int size; 542 | char *name; 543 | 544 | WCHAR wName[128 + 1]; 545 | HMODULE hIPHlpApi = LoadLibrary(TEXT("iphlpapi.dll")); 546 | 547 | typedef HRESULT (WINAPI *ProcAddr_nhGINFG) ( GUID *InterfaceGuid, PCWSTR InterfaceAlias, DWORD *LengthAddress, wchar_t *a4, wchar_t *a5); 548 | 549 | ProcAddr_nhGINFG Proc_nhGetInterfaceNameFromGuid = NULL; 550 | Proc_nhGetInterfaceNameFromGuid = (ProcAddr_nhGINFG) GetProcAddress(hIPHlpApi, "NhGetInterfaceNameFromGuid"); 551 | if (Proc_nhGetInterfaceNameFromGuid!= NULL) 552 | { 553 | wchar_t *p4=NULL, *p5=NULL; 554 | DWORD NameSize; 555 | 556 | /* testing of nhGetInterfaceNameFromGuid indicates the unpublished API function expects the 3rd parameter 557 | * to be the available space in bytes (as compared to wchar's) available in the second parameter buffer 558 | * to receive the friendly name (in unicode format) including the space for the nul termination.*/ 559 | NameSize = sizeof(wName); 560 | 561 | /* do the guid->friendlyname lookup */ 562 | status = ( 0 == Proc_nhGetInterfaceNameFromGuid(guid, wName, &NameSize, p4, p5) ); 563 | } 564 | 565 | /* we have finished with iphlpapi.dll - release it */ 566 | FreeLibrary(hIPHlpApi); 567 | 568 | if(FALSE == status){ 569 | /* failed to get the friendly name, nothing further to do */ 570 | return NULL; 571 | } 572 | 573 | /* Get the required buffer size, and then convert the string 574 | * from UTF-16 to UTF-8. */ 575 | size=WideCharToMultiByte(CP_UTF8, 0, wName, -1, NULL, 0, NULL, NULL); 576 | name=(char *) malloc(size); 577 | if (name == NULL){ 578 | return NULL; 579 | } 580 | size=WideCharToMultiByte(CP_UTF8, 0, wName, -1, name, size, NULL, NULL); 581 | if(size==0){ 582 | /* bytes written == 0, indicating some form of error*/ 583 | free(name); 584 | return NULL; 585 | } 586 | return name; 587 | } 588 | 589 | char * 590 | get_windows_interface_friendly_name(const char *interface_devicename) 591 | { 592 | const char* guid_text; 593 | GUID guid; 594 | 595 | /* Extract the guid text from the interface device name */ 596 | if(strncmp("\\Device\\NPF_", interface_devicename, 12)==0){ 597 | guid_text=interface_devicename+12; /* skip over the '\Device\NPF_' prefix, assume the rest is the guid text */ 598 | }else{ 599 | guid_text=interface_devicename; 600 | 601 | } 602 | 603 | if (!parse_as_guid(guid_text, &guid)){ 604 | return strdup(interface_devicename); /* not a GUID, so no friendly name */ 605 | } 606 | 607 | /* guid okay, get the interface friendly name associated with the guid */ 608 | return guid_to_luid(&guid); 609 | } 610 | #endif 611 | -------------------------------------------------------------------------------- /pcapobj.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Miroslav Stampar (miroslav@sqlmap.org) 3 | * Copyright (c) 2014 CORE Security Technologies 4 | * 5 | * This software is provided under under the Apache Software License. 6 | * See the accompanying LICENSE file for more information. 7 | * 8 | */ 9 | 10 | #define PY_SSIZE_T_CLEAN 11 | 12 | #include 13 | #include 14 | 15 | #include "pcapobj.h" 16 | #include "pcapy.h" 17 | #include "pcapdumper.h" 18 | #include "pcap_pkthdr.h" 19 | 20 | #ifdef WIN32 21 | #include 22 | #else 23 | #include 24 | #endif 25 | 26 | 27 | // internal pcapobject 28 | typedef struct { 29 | PyObject_HEAD 30 | pcap_t *pcap; 31 | bpf_u_int32 net; 32 | bpf_u_int32 mask; 33 | } pcapobject; 34 | 35 | 36 | // PcapType 37 | 38 | static PyObject* 39 | p_close(pcapobject* pp, PyObject*) 40 | { 41 | if ( pp->pcap ) 42 | pcap_close(pp->pcap); 43 | 44 | pp->pcap = NULL; 45 | 46 | Py_RETURN_NONE; 47 | } 48 | 49 | static void 50 | pcap_dealloc(pcapobject* pp) 51 | { 52 | p_close(pp, NULL); 53 | 54 | PyObject_Del(pp); 55 | } 56 | 57 | static PyObject * 58 | err_closed(void) 59 | { 60 | PyErr_SetString(PyExc_ValueError, "pcap is closed"); 61 | return NULL; 62 | } 63 | 64 | // pcap methods 65 | static PyObject* p_getnet(pcapobject* pp, PyObject* args); 66 | static PyObject* p_getmask(pcapobject* pp, PyObject* args); 67 | static PyObject* p_setfilter( pcapobject* pp, PyObject* args ); 68 | static PyObject* p_next(pcapobject* pp, PyObject*); 69 | static PyObject* p_dispatch(pcapobject* pp, PyObject* args); 70 | static PyObject* p_loop(pcapobject* pp, PyObject* args); 71 | static PyObject* p_datalink(pcapobject* pp, PyObject* args); 72 | static PyObject* p_setdirection(pcapobject* pp, PyObject* args); 73 | static PyObject* p_setnonblock(pcapobject* pp, PyObject* args); 74 | static PyObject* p_getnonblock(pcapobject* pp, PyObject* args); 75 | static PyObject* p_dump_open(pcapobject* pp, PyObject* args); 76 | static PyObject* p_sendpacket(pcapobject* pp, PyObject* args); 77 | static PyObject* p_stats( pcapobject* pp, PyObject*); 78 | static PyObject* p__enter__( pcapobject* pp, PyObject*); 79 | static PyObject* p_getfd(pcapobject* pp, PyObject* args); 80 | static PyObject* p_set_snaplen(pcapobject* pp, PyObject* args); 81 | static PyObject* p_set_promisc(pcapobject* pp, PyObject* args); 82 | static PyObject* p_set_timeout(pcapobject* pp, PyObject* args); 83 | static PyObject* p_set_buffer_size(pcapobject* pp, PyObject* args); 84 | static PyObject* p_set_rfmon(pcapobject* pp, PyObject* args); 85 | static PyObject* p_activate(pcapobject* pp, PyObject* args); 86 | 87 | static PyMethodDef p_methods[] = { 88 | {"loop", (PyCFunction) p_loop, METH_VARARGS, "loops packet dispatching"}, 89 | {"dispatch", (PyCFunction) p_dispatch, METH_VARARGS, "dispatchs packets"}, 90 | {"next", (PyCFunction) p_next, METH_NOARGS, "returns next packet"}, 91 | {"setfilter", (PyCFunction) p_setfilter, METH_VARARGS, "compiles and sets a BPF capture filter"}, 92 | {"getnet", (PyCFunction) p_getnet, METH_VARARGS, "returns the network address for the device"}, 93 | {"getmask", (PyCFunction) p_getmask, METH_VARARGS, "returns the netmask for the device"}, 94 | {"datalink", (PyCFunction) p_datalink, METH_VARARGS, "returns the link layer type"}, 95 | {"getnonblock", (PyCFunction) p_getnonblock, METH_VARARGS, "returns the current `non-blocking' state"}, 96 | {"setnonblock", (PyCFunction) p_setnonblock, METH_VARARGS, "puts into `non-blocking' mode, or take it out, depending on the argument"}, 97 | {"setdirection", (PyCFunction) p_setdirection, METH_VARARGS, "set the direction for which packets will be captured"}, 98 | {"dump_open", (PyCFunction) p_dump_open, METH_VARARGS, "creates a dumper object"}, 99 | {"sendpacket", (PyCFunction) p_sendpacket, METH_VARARGS, "sends a packet through the interface"}, 100 | {"stats", (PyCFunction) p_stats, METH_NOARGS, "returns capture statistics"}, 101 | {"close", (PyCFunction) p_close, METH_NOARGS, "close the capture"}, 102 | {"set_snaplen", (PyCFunction)p_set_snaplen, METH_VARARGS, "set the snapshot length for a not-yet-activated capture handle"}, 103 | {"set_promisc", (PyCFunction)p_set_promisc, METH_VARARGS, "set promiscuous mode for a not-yet-activated capture handle"}, 104 | {"set_timeout", (PyCFunction)p_set_timeout, METH_VARARGS, "set the read timeout for a not-yet-activated capture handle"}, 105 | {"set_buffer_size", (PyCFunction)p_set_buffer_size, METH_VARARGS, "set the buffer size for a not-yet-activated capture handle"}, 106 | {"activate", (PyCFunction)p_activate, METH_NOARGS, "activate a capture handle created using create()"}, 107 | {"__enter__", (PyCFunction) p__enter__, METH_NOARGS, NULL}, 108 | {"__exit__", (PyCFunction) p_close, METH_VARARGS, NULL}, 109 | #ifndef WIN32 110 | {"getfd", (PyCFunction) p_getfd, METH_VARARGS, "get selectable pcap fd"}, 111 | {"set_rfmon", (PyCFunction)p_set_rfmon, METH_VARARGS, "set monitor mode for a not-yet-activated capture handle"}, /* Available on Npcap, not on Winpcap. */ 112 | #endif 113 | {NULL, NULL} /* sentinel */ 114 | }; 115 | 116 | static PyObject* 117 | pcap_getattr(pcapobject* pp, char* name) 118 | { 119 | #if PY_MAJOR_VERSION >= 3 120 | PyObject *nameobj = PyUnicode_FromString(name); 121 | PyObject *attr = PyObject_GenericGetAttr((PyObject *)pp, nameobj); 122 | Py_DECREF(nameobj); 123 | return attr; 124 | #else 125 | return Py_FindMethod(p_methods, (PyObject*)pp, name); 126 | #endif 127 | } 128 | 129 | 130 | PyTypeObject Pcaptype = { 131 | #if PY_MAJOR_VERSION >= 3 132 | PyVarObject_HEAD_INIT(&PyType_Type, 0) 133 | "Reader", /* tp_name */ 134 | sizeof(pcapobject), /* tp_basicsize */ 135 | 0, /* tp_itemsize */ 136 | (destructor)pcap_dealloc, /* tp_dealloc */ 137 | 0, /* tp_print */ 138 | (getattrfunc)pcap_getattr, /* tp_getattr */ 139 | 0, /* tp_setattr */ 140 | 0, /* tp_reserved */ 141 | 0, /* tp_repr */ 142 | 0, /* tp_as_number */ 143 | 0, /* tp_as_sequence */ 144 | 0, /* tp_as_mapping */ 145 | 0, /* tp_hash */ 146 | 0, /* tp_call */ 147 | 0, /* tp_str */ 148 | 0, /* tp_getattro */ 149 | 0, /* tp_setattro */ 150 | 0, /* tp_as_buffer */ 151 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 152 | NULL, /* tp_doc */ 153 | 0, /* tp_traverse */ 154 | 0, /* tp_clear */ 155 | 0, /* tp_richcompare */ 156 | 0, /* tp_weaklistoffset */ 157 | 0, /* tp_iter */ 158 | 0, /* tp_iternext */ 159 | p_methods, /* tp_methods */ 160 | 0, /* tp_members */ 161 | 0, /* tp_getset */ 162 | 0, /* tp_base */ 163 | 0, /* tp_dict */ 164 | 0, /* tp_descr_get */ 165 | 0, /* tp_descr_set */ 166 | 0, /* tp_dictoffset */ 167 | 0, /* tp_init */ 168 | 0, /* tp_alloc */ 169 | 0, /* tp_new */ 170 | #else 171 | PyObject_HEAD_INIT(NULL) 172 | 0, 173 | "Reader", 174 | sizeof(pcapobject), 175 | 0, 176 | /* methods */ 177 | (destructor)pcap_dealloc, /* tp_dealloc*/ 178 | 0, /* tp_print*/ 179 | (getattrfunc)pcap_getattr, /* tp_getattr*/ 180 | 0, /* tp_setattr*/ 181 | 0, /* tp_compare*/ 182 | 0, /* tp_repr*/ 183 | 0, /* tp_as_number*/ 184 | 0, /* tp_as_sequence*/ 185 | 0, /* tp_as_mapping*/ 186 | 0, /* tp_hash */ 187 | 0, /* tp_call */ 188 | 0, /* tp_str */ 189 | 0, /* tp_getattro */ 190 | 0, /* tp_setattro */ 191 | 0, /* tp_as_buffer */ 192 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 193 | NULL, /* tp_doc */ 194 | 0, /* tp_traverse */ 195 | 0, /* tp_clear */ 196 | 0, /* tp_richcompare */ 197 | 0, /* tp_weaklistoffset */ 198 | 0, /* tp_iter */ 199 | 0, /* tp_iternext */ 200 | p_methods, /* tp_methods */ 201 | 0, /* tp_members */ 202 | 0, /* tp_getset */ 203 | 0, /* tp_base */ 204 | 0, /* tp_dict */ 205 | 0, /* tp_descr_get */ 206 | 0, /* tp_descr_set */ 207 | 0, /* tp_dictoffset */ 208 | 0, /* tp_init */ 209 | 0, /* tp_alloc */ 210 | 0, /* tp_new */ 211 | #endif 212 | }; 213 | 214 | 215 | PyObject* 216 | new_pcapobject(pcap_t *pcap, bpf_u_int32 net, bpf_u_int32 mask) 217 | { 218 | if (PyType_Ready(&Pcaptype) < 0) 219 | return NULL; 220 | 221 | pcapobject *pp; 222 | 223 | pp = PyObject_New(pcapobject, &Pcaptype); 224 | if (pp == NULL) 225 | return NULL; 226 | 227 | pp->pcap = pcap; 228 | pp->net = net; 229 | pp->mask = mask; 230 | 231 | return (PyObject*)pp; 232 | } 233 | 234 | static void ntos(char* dst, unsigned int n, int ip) 235 | { 236 | ip = htonl(ip); 237 | snprintf(dst, n, "%i.%i.%i.%i", 238 | ((ip >> 24) & 0xFF), 239 | ((ip >> 16) & 0xFF), 240 | ((ip >> 8) & 0xFF), 241 | (ip & 0xFF)); 242 | } 243 | 244 | static PyObject* 245 | p_getnet(pcapobject* pp, PyObject* args) 246 | { 247 | if (Py_TYPE(pp) != &Pcaptype) 248 | { 249 | PyErr_SetString(PcapError, "Not a pcap object"); 250 | return NULL; 251 | } 252 | 253 | if (!pp->pcap) 254 | return err_closed(); 255 | 256 | char ip_str[20]; 257 | ntos(ip_str, sizeof(ip_str), pp->net); 258 | return Py_BuildValue("s", ip_str); 259 | } 260 | 261 | static PyObject* 262 | p_getmask(pcapobject* pp, PyObject* args) 263 | { 264 | if (Py_TYPE(pp) != &Pcaptype) 265 | { 266 | PyErr_SetString(PcapError, "Not a pcap object"); 267 | return NULL; 268 | } 269 | 270 | if (!pp->pcap) 271 | return err_closed(); 272 | 273 | char ip_str[20]; 274 | ntos(ip_str, sizeof(ip_str), pp->mask); 275 | return Py_BuildValue("s", ip_str); 276 | } 277 | 278 | static PyObject* 279 | p_setfilter(pcapobject* pp, PyObject* args) 280 | { 281 | struct bpf_program bpfprog; 282 | int status; 283 | char* str; 284 | 285 | if (Py_TYPE(pp) != &Pcaptype) 286 | { 287 | PyErr_SetString(PcapError, "Not a pcap object"); 288 | return NULL; 289 | } 290 | 291 | if (!pp->pcap) 292 | return err_closed(); 293 | 294 | if (!PyArg_ParseTuple(args,"s:setfilter",&str)) 295 | return NULL; 296 | 297 | status = pcap_compile(pp->pcap, &bpfprog, str, 1, pp->mask); 298 | if (status) 299 | { 300 | PyErr_SetString(PcapError, pcap_geterr(pp->pcap)); 301 | return NULL; 302 | } 303 | 304 | status = pcap_setfilter(pp->pcap, &bpfprog); 305 | if (status) 306 | { 307 | PyErr_SetString(PcapError, pcap_geterr(pp->pcap)); 308 | return NULL; 309 | } 310 | 311 | Py_INCREF(Py_None); 312 | return Py_None; 313 | } 314 | 315 | static PyObject* 316 | p_next(pcapobject* pp, PyObject*) 317 | { 318 | struct pcap_pkthdr *hdr = NULL; 319 | const unsigned char *buf = (const unsigned char*)""; 320 | int err_code = 1; 321 | 322 | if (Py_TYPE(pp) != &Pcaptype) 323 | { 324 | PyErr_SetString(PcapError, "Not a pcap object"); 325 | return NULL; 326 | } 327 | 328 | if (!pp->pcap) 329 | return err_closed(); 330 | 331 | // allow threads as this might block 332 | Py_BEGIN_ALLOW_THREADS; 333 | err_code = pcap_next_ex(pp->pcap, &hdr, &buf); 334 | Py_END_ALLOW_THREADS; 335 | 336 | if(err_code == -1) 337 | { 338 | PyErr_SetString(PcapError, pcap_geterr(pp->pcap)); 339 | return NULL; 340 | } 341 | 342 | 343 | PyObject *pkthdr; 344 | int _caplen = 0; 345 | if (err_code == 1) { 346 | pkthdr = new_pcap_pkthdr(hdr); 347 | _caplen = hdr->caplen; 348 | } else { 349 | pkthdr = Py_None; 350 | Py_INCREF(pkthdr); 351 | _caplen = 0; 352 | } 353 | 354 | 355 | if (pkthdr) 356 | { 357 | PyObject *ret = NULL; 358 | 359 | #if PY_MAJOR_VERSION >= 3 360 | /* return bytes */ 361 | ret = Py_BuildValue("(Oy#)", pkthdr, buf, _caplen); 362 | #else 363 | ret = Py_BuildValue("(Os#)", pkthdr, buf, _caplen); 364 | #endif 365 | 366 | Py_DECREF(pkthdr); 367 | return ret; 368 | } 369 | 370 | PyErr_SetString(PcapError, "Can't build pkthdr"); 371 | return NULL; 372 | } 373 | 374 | struct PcapCallbackContext { 375 | PcapCallbackContext(pcap_t* p, PyObject* f, PyThreadState* ts) 376 | : ppcap_t(p), pyfunc(f), thread_state(ts) 377 | { 378 | Py_INCREF(pyfunc); 379 | } 380 | ~PcapCallbackContext() 381 | { 382 | Py_DECREF(pyfunc); 383 | } 384 | 385 | pcap_t* ppcap_t; 386 | PyObject *pyfunc; 387 | PyThreadState *thread_state; 388 | 389 | }; 390 | 391 | 392 | static void 393 | PythonCallBack(u_char *user, 394 | const struct pcap_pkthdr *header, 395 | const u_char *packetdata) 396 | { 397 | PyObject *arglist, *result; 398 | unsigned int *len; 399 | PcapCallbackContext *pctx; 400 | len = (unsigned int *)&header->caplen; 401 | pctx = (PcapCallbackContext *)user; 402 | 403 | PyEval_RestoreThread(pctx->thread_state); 404 | 405 | PyObject *hdr = new_pcap_pkthdr(header); 406 | 407 | #if PY_MAJOR_VERSION >= 3 408 | /* pass bytes */ 409 | arglist = Py_BuildValue("Oy#", hdr, packetdata, *len); 410 | #else 411 | arglist = Py_BuildValue("Os#", hdr, packetdata, *len); 412 | #endif 413 | 414 | result = PyObject_CallObject(pctx->pyfunc,arglist); 415 | 416 | Py_XDECREF(arglist); 417 | if (result) 418 | Py_DECREF(result); 419 | 420 | Py_DECREF(hdr); 421 | 422 | if (!result) 423 | pcap_breakloop(pctx->ppcap_t); 424 | 425 | PyEval_SaveThread(); 426 | } 427 | 428 | static PyObject* 429 | p_dispatch(pcapobject* pp, PyObject* args) 430 | { 431 | int cant, ret; 432 | PyObject *PyFunc; 433 | 434 | if (Py_TYPE(pp) != &Pcaptype) 435 | { 436 | PyErr_SetString(PcapError, "Not a pcap object"); 437 | return NULL; 438 | } 439 | 440 | if (!pp->pcap) 441 | return err_closed(); 442 | 443 | if(!PyArg_ParseTuple(args,"iO:dispatch",&cant,&PyFunc)) 444 | return NULL; 445 | 446 | PcapCallbackContext ctx(pp->pcap, PyFunc, PyThreadState_Get()); 447 | PyEval_SaveThread(); 448 | ret = pcap_dispatch(pp->pcap, cant, PythonCallBack, (u_char*)&ctx); 449 | PyEval_RestoreThread(ctx.thread_state); 450 | 451 | if(ret<0) { 452 | if (ret!=-2) 453 | /* pcap error, pcap_breakloop was not called so error is not set */ 454 | PyErr_SetString(PcapError, pcap_geterr(pp->pcap)); 455 | return NULL; 456 | } 457 | 458 | return Py_BuildValue("i", ret); 459 | } 460 | 461 | static PyObject* 462 | p_stats(pcapobject* pp, PyObject*) 463 | { 464 | if (Py_TYPE(pp) != &Pcaptype) 465 | { 466 | PyErr_SetString(PcapError, "Not a pcap object"); 467 | return NULL; 468 | } 469 | 470 | if (!pp->pcap) 471 | return err_closed(); 472 | 473 | struct pcap_stat stats; 474 | 475 | if (-1 == pcap_stats(pp->pcap, &stats)) { 476 | PyErr_SetString(PcapError, pcap_geterr(pp->pcap)); 477 | return NULL; 478 | } 479 | 480 | return Py_BuildValue("III", stats.ps_recv, stats.ps_drop, stats.ps_ifdrop); 481 | } 482 | 483 | static PyObject* 484 | p__enter__( pcapobject* pp, PyObject*) 485 | { 486 | if (Py_TYPE(pp) != &Pcaptype) 487 | { 488 | PyErr_SetString(PcapError, "Not a pcap object"); 489 | return NULL; 490 | } 491 | 492 | if (!pp->pcap) 493 | return err_closed(); 494 | 495 | Py_INCREF(pp); 496 | return (PyObject*)pp; 497 | } 498 | 499 | static PyObject* 500 | p_dump_open(pcapobject* pp, PyObject* args) 501 | { 502 | char *filename; 503 | pcap_dumper_t *ret; 504 | 505 | if (Py_TYPE(pp) != &Pcaptype) 506 | { 507 | PyErr_SetString(PcapError, "Not a pcap object"); 508 | return NULL; 509 | } 510 | 511 | if (!pp->pcap) 512 | return err_closed(); 513 | 514 | if(!PyArg_ParseTuple(args,"s",&filename)) 515 | return NULL; 516 | 517 | ret = pcap_dump_open(pp->pcap, filename); 518 | 519 | if (ret==NULL) { 520 | PyErr_SetString(PcapError, pcap_geterr(pp->pcap)); 521 | return NULL; 522 | } 523 | 524 | return new_pcapdumper(ret); 525 | } 526 | 527 | 528 | static PyObject* 529 | p_loop(pcapobject* pp, PyObject* args) 530 | { 531 | int cant, ret; 532 | PyObject *PyFunc; 533 | 534 | if (Py_TYPE(pp) != &Pcaptype) 535 | { 536 | PyErr_SetString(PcapError, "Not a pcap object"); 537 | return NULL; 538 | } 539 | 540 | if (!pp->pcap) 541 | return err_closed(); 542 | 543 | if(!PyArg_ParseTuple(args,"iO:loop",&cant,&PyFunc)) 544 | return NULL; 545 | 546 | PcapCallbackContext ctx(pp->pcap, PyFunc, PyThreadState_Get()); 547 | PyEval_SaveThread(); 548 | ret = pcap_loop(pp->pcap, cant, PythonCallBack, (u_char*)&ctx); 549 | PyEval_RestoreThread(ctx.thread_state); 550 | 551 | if(ret<0) { 552 | if (ret!=-2) 553 | /* pcap error, pcap_breakloop was not called so error is not set */ 554 | PyErr_SetString(PcapError, pcap_geterr(pp->pcap)); 555 | return NULL; 556 | } 557 | 558 | Py_INCREF(Py_None); 559 | return Py_None; 560 | } 561 | 562 | 563 | static PyObject* 564 | p_datalink(pcapobject* pp, PyObject* args) 565 | { 566 | if (Py_TYPE(pp) != &Pcaptype) { 567 | PyErr_SetString(PcapError, "Not a pcap object"); 568 | return NULL; 569 | } 570 | 571 | if (!pp->pcap) 572 | return err_closed(); 573 | 574 | int type = pcap_datalink(pp->pcap); 575 | 576 | return Py_BuildValue("i", type); 577 | } 578 | 579 | static PyObject* 580 | p_setdirection(pcapobject* pp, PyObject* args) 581 | { 582 | if (Py_TYPE(pp) != &Pcaptype) { 583 | PyErr_SetString(PcapError, "Not a pcap object"); 584 | return NULL; 585 | } 586 | 587 | if (!pp->pcap) 588 | return err_closed(); 589 | 590 | pcap_direction_t direction; 591 | 592 | if (!PyArg_ParseTuple(args, "i", &direction)) 593 | return NULL; 594 | 595 | int ret = pcap_setdirection(pp->pcap, direction); 596 | if (-1 == ret) { 597 | PyErr_SetString(PcapError, "Failed setting direction"); 598 | return NULL; 599 | } 600 | 601 | Py_INCREF(Py_None); 602 | return Py_None; 603 | } 604 | 605 | static PyObject* 606 | p_setnonblock(pcapobject* pp, PyObject* args) 607 | { 608 | if (Py_TYPE(pp) != &Pcaptype) { 609 | PyErr_SetString(PcapError, "Not a pcap object"); 610 | return NULL; 611 | } 612 | 613 | if (!pp->pcap) 614 | return err_closed(); 615 | 616 | int state; 617 | 618 | if (!PyArg_ParseTuple(args, "i", &state)) 619 | return NULL; 620 | 621 | char errbuf[PCAP_ERRBUF_SIZE]; 622 | int ret = pcap_setnonblock(pp->pcap, state, errbuf); 623 | if (-1 == ret) { 624 | PyErr_SetString(PcapError, errbuf); 625 | return NULL; 626 | } 627 | 628 | Py_INCREF(Py_None); 629 | return Py_None; 630 | } 631 | 632 | static PyObject* 633 | p_getnonblock(pcapobject* pp, PyObject* args) 634 | { 635 | if (Py_TYPE(pp) != &Pcaptype) { 636 | PyErr_SetString(PcapError, "Not a pcap object"); 637 | return NULL; 638 | } 639 | 640 | if (!pp->pcap) 641 | return err_closed(); 642 | 643 | char errbuf[PCAP_ERRBUF_SIZE]; 644 | int state = pcap_getnonblock(pp->pcap, errbuf); 645 | if (-1 == state) { 646 | PyErr_SetString(PcapError, errbuf); 647 | return NULL; 648 | } 649 | 650 | return Py_BuildValue("i", state); 651 | } 652 | 653 | static PyObject* 654 | p_set_snaplen(pcapobject* pp, PyObject* args) 655 | { 656 | if (Py_TYPE(pp) != &Pcaptype) { 657 | PyErr_SetString(PcapError, "Not a pcap object"); 658 | return NULL; 659 | } 660 | 661 | if (!pp->pcap) 662 | return err_closed(); 663 | 664 | int snaplen; 665 | 666 | if (!PyArg_ParseTuple(args, "i", &snaplen)) 667 | return NULL; 668 | 669 | int ret = pcap_set_snaplen(pp->pcap, snaplen); 670 | return Py_BuildValue("i", ret); 671 | } 672 | 673 | static PyObject* 674 | p_set_promisc(pcapobject* pp, PyObject* args) 675 | { 676 | if (Py_TYPE(pp) != &Pcaptype) { 677 | PyErr_SetString(PcapError, "Not a pcap object"); 678 | return NULL; 679 | } 680 | 681 | if (!pp->pcap) 682 | return err_closed(); 683 | 684 | int promisc; 685 | 686 | if (!PyArg_ParseTuple(args, "i", &promisc)) 687 | return NULL; 688 | 689 | int ret = pcap_set_promisc(pp->pcap, promisc); 690 | return Py_BuildValue("i", ret); 691 | } 692 | 693 | static PyObject* 694 | p_set_timeout(pcapobject* pp, PyObject* args) 695 | { 696 | if (Py_TYPE(pp) != &Pcaptype) { 697 | PyErr_SetString(PcapError, "Not a pcap object"); 698 | return NULL; 699 | } 700 | 701 | if (!pp->pcap) 702 | return err_closed(); 703 | 704 | int to_ms; 705 | 706 | if (!PyArg_ParseTuple(args, "i", &to_ms)) 707 | return NULL; 708 | 709 | int ret = pcap_set_timeout(pp->pcap, to_ms); 710 | return Py_BuildValue("i", ret); 711 | } 712 | 713 | static PyObject* 714 | p_set_buffer_size(pcapobject* pp, PyObject* args) 715 | { 716 | if (Py_TYPE(pp) != &Pcaptype) { 717 | PyErr_SetString(PcapError, "Not a pcap object"); 718 | return NULL; 719 | } 720 | 721 | if (!pp->pcap) 722 | return err_closed(); 723 | 724 | int buffer_size; 725 | 726 | if (!PyArg_ParseTuple(args, "i", &buffer_size)) 727 | return NULL; 728 | 729 | int ret = pcap_set_buffer_size(pp->pcap, buffer_size); 730 | return Py_BuildValue("i", ret); 731 | } 732 | 733 | static PyObject* 734 | p_set_rfmon(pcapobject* pp, PyObject* args) 735 | { 736 | if (Py_TYPE(pp) != &Pcaptype) { 737 | PyErr_SetString(PcapError, "Not a pcap object"); 738 | return NULL; 739 | } 740 | 741 | if (!pp->pcap) 742 | return err_closed(); 743 | 744 | int rfmon; 745 | 746 | if (!PyArg_ParseTuple(args, "i", &rfmon)) 747 | return NULL; 748 | 749 | int ret = pcap_set_rfmon(pp->pcap, rfmon); 750 | return Py_BuildValue("i", ret); 751 | } 752 | 753 | static PyObject* 754 | p_activate(pcapobject* pp, PyObject*) 755 | { 756 | if (Py_TYPE(pp) != &Pcaptype) { 757 | PyErr_SetString(PcapError, "Not a pcap object"); 758 | return NULL; 759 | } 760 | 761 | if (!pp->pcap) 762 | return err_closed(); 763 | 764 | int ret = pcap_activate(pp->pcap); 765 | return Py_BuildValue("i", ret); 766 | } 767 | 768 | 769 | static PyObject* 770 | p_sendpacket(pcapobject* pp, PyObject* args) 771 | { 772 | int status; 773 | unsigned char* str; 774 | Py_ssize_t length; 775 | 776 | if (Py_TYPE(pp) != &Pcaptype) 777 | { 778 | PyErr_SetString(PcapError, "Not a pcap object"); 779 | return NULL; 780 | } 781 | 782 | if (!pp->pcap) 783 | return err_closed(); 784 | 785 | #if PY_MAJOR_VERSION >= 3 786 | /* accept bytes */ 787 | if (!PyArg_ParseTuple(args,"y#", &str, &length)) { 788 | return NULL; 789 | } 790 | #else 791 | if (!PyArg_ParseTuple(args,"s#", &str, &length)) { 792 | return NULL; 793 | } 794 | #endif 795 | 796 | 797 | status = pcap_sendpacket(pp->pcap, str, length); 798 | if (status) 799 | { 800 | PyErr_SetString(PcapError, pcap_geterr(pp->pcap)); 801 | return NULL; 802 | } 803 | 804 | Py_INCREF(Py_None); 805 | return Py_None; 806 | } 807 | 808 | #ifndef WIN32 809 | static PyObject* 810 | p_getfd(pcapobject* pp, PyObject* args) 811 | { 812 | if (Py_TYPE(pp) != &Pcaptype) 813 | { 814 | PyErr_SetString(PcapError, "Not a pcap object"); 815 | return NULL; 816 | } 817 | 818 | if (!pp->pcap) 819 | return err_closed(); 820 | 821 | int fd = pcap_get_selectable_fd(pp->pcap); 822 | return Py_BuildValue("i", fd); 823 | } 824 | #endif 825 | -------------------------------------------------------------------------------- /pcapy.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | ]> 6 | 7 | 8 | 9 | 2016-2018 10 | &corest; 11 | 12 | &corest; 13 | 14 | pcap 15 | packet 16 | capture 17 | python 18 | 19 | 20 | 21 | Revision: 16 22 | Date: 2018-06-04 23 | Author: jkohen 24 | 2018 updated 25 | 26 | 27 | 28 | Pcapy Reference 29 | 30 | 31 | Pcapy Module Reference 32 | 33 | 34 | open_live 35 | Obtain a packet capture descriptor to look at packets on the network 36 | 37 | 38 | 39 | 40 | 41 | 42 | Reader open_live 43 | 44 | 45 | string device 46 | 47 | 48 | int snaplen 49 | 50 | 51 | int promisc 52 | 53 | 54 | int to_ms 55 | 56 | 57 | 58 | 59 | 60 | 61 | DESCRIPTION 62 | 63 | open_live is used to obtain a packet 64 | capture descriptor to look at packets on the network. 65 | device is a string that specifies the 66 | network device to open; on Linux systems with 2.2 or later 67 | kernels, a device argument of any or 68 | NULL can be used to capture packets 69 | from all interfaces. snaplen 70 | specifies the maximum number of bytes to capture. 71 | promisc specifies if the interface is 72 | to be put into promiscuous mode. (Note that even if this 73 | parameter is false, the interface could well be in 74 | promiscuous mode for some other reason.) For now, this 75 | doesn't work on the any device; if an 76 | argument of any or 77 | NULL is supplied, the 78 | promisc flag is ignored. 79 | to_ms specifies the read timeout in 80 | milliseconds. The read timeout is used to arrange that the 81 | read not necessarily return immediately when a packet is 82 | seen, but that it wait for some amount of time to allow more 83 | packets to arrive and to read multiple packets from the OS 84 | kernel in one operation. Not all platforms support a read 85 | timeout; on platforms that don't, the read timeout is 86 | ignored. 87 | 88 | 89 | 90 | 91 | 92 | 93 | open_offline 94 | 95 | Obtain a packet capture descriptor to look at packets on a savefile 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | Reader open_offline 104 | 105 | 106 | string filename 107 | 108 | 109 | 110 | 111 | 112 | 113 | DESCRIPTION 114 | 115 | open_offline is called to open a 116 | savefile for reading. filename 117 | specifies the name of the file to open. The file has the 118 | same format as those used by 119 | 120 | tcpdump 121 | 8 122 | and 123 | 124 | tcpslice 125 | 8 126 | . The name 127 | - is a synonym for 128 | stdin. 129 | 130 | 131 | 132 | 133 | 134 | 135 | lookupdev 136 | 137 | Return a network device suitable for use with 138 | open_live 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | string lookupdev 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | DESCRIPTION 155 | 156 | lookupdev returns the name of a network 157 | device suitable for use with open_live. 158 | 159 | 160 | 161 | 162 | 163 | 164 | findalldevs 165 | Obtain the list of available network devices 166 | 167 | 168 | 169 | 170 | 171 | 172 | string[] findalldevs 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | DESCRIPTION 181 | 182 | findalldevs constructs a list of 183 | network devices that can be opened with 184 | open_live. (Note that there may be 185 | network devices that cannot be opened with 186 | open_live, because, for example, that 187 | process might not have sufficient privileges to open them 188 | for capturing; if so, those devices will not appear on the 189 | list.) 190 | 191 | 192 | 193 | 194 | 195 | 196 | compile 197 | Compile a BPF filter 198 | 199 | 200 | 201 | 202 | 203 | 204 | Bpf compile 205 | 206 | 207 | int linktype 208 | 209 | 210 | int snaplen 211 | 212 | 213 | string filter 214 | 215 | 216 | int optimize 217 | 218 | 219 | int32 netmask 220 | 221 | 222 | 223 | 224 | 225 | 226 | DESCRIPTION 227 | 228 | compile is used to compile the 229 | filter into a filter program. 230 | snaplen specifies the maximum number of 231 | bytes to capture. optimize controls 232 | whether optimization on the resulting code is performed. 233 | netmask specifies the netmask of the 234 | local network. 235 | 236 | 237 | 238 | 239 | 240 | 241 | create 242 | Creates a non-activated packet capture handle to look at packets on the network 243 | 244 | 245 | 246 | 247 | 248 | 249 | Reader create 250 | 251 | 252 | string device 253 | 254 | 255 | 256 | 257 | 258 | 259 | DESCRIPTION 260 | 261 | create is used to create a 262 | packet capture handle to look at packets on the network. 263 | The returned handle must be activated with 264 | activate() before packets can be captured 265 | with it; options for the capture, such as promiscuous mode, 266 | can be set on the handle before activating it. 267 | 268 | 269 | 270 | 271 | 272 | 273 | Reader Object Reference 274 | 275 | 276 | dispatch 277 | loop 278 | Collect and process packets 279 | 280 | 281 | 282 | 283 | 284 | 285 | int dispatch 286 | 287 | 288 | int maxcant 289 | 290 | 291 | void (* callback) 292 | Pkthdr, string 293 | 294 | 295 | 296 | 297 | 298 | int loop 299 | 300 | 301 | int maxcant 302 | 303 | 304 | void (* callback) 305 | Pkthdr, string 306 | 307 | 308 | 309 | 310 | 311 | 312 | DESCRIPTION 313 | 314 | dispatch is used to collect and process 315 | packets. maxcant specifies the 316 | maximum number of packets to process before returning. This 317 | is not a minimum number; when reading a live capture, only 318 | one bufferful of packets is read at a time, so fewer than 319 | maxcant packets may be processed. A 320 | cnt of -1 321 | processes all the packets received in one buffer when 322 | reading a live capture, or all the packets in the file when 323 | reading a savefile. callback 324 | specifies a routine to be called with two arguments: a 325 | Pkthdr instance describing the data 326 | passed and the data itself. 327 | 328 | 329 | The number of packets read is returned. 330 | 0 is returned if no packets were 331 | read from a live capture (if, for example, they were 332 | discarded because they didn't pass the packet filter, or if, 333 | on platforms that support a read timeout that starts before 334 | any packets arrive, the timeout expires before any packets 335 | arrive, or if the file descriptor for the capture device is 336 | in non-blocking mode and no packets were available to be 337 | read) or if no more packets are available in a savefile. 338 | 339 | 340 | 341 | When reading a live capture, dispatch 342 | will not necessarily return when the read times out; on 343 | some platforms, the read timeout isn't supported, and, on 344 | other platforms, the timer doesn't start until at least 345 | one packet arrives. This means that the read timeout 346 | should not be used in, for example, 347 | an interactive application, to allow the packet capture 348 | loop to poll for user input periodically, as there's no 349 | guarantee that dispatch will return 350 | after the timeout expires. 351 | 352 | 353 | 354 | loop is similar to 355 | dispatch except it keeps reading 356 | packets until maxcant packets are 357 | processed or an error occurs. It does 358 | not return when live read timeouts 359 | occur. Rather, specifying a non-zero read timeout to 360 | open_live and then calling 361 | dispatch allows the reception and 362 | processing of any packets that arrive when the timeout 363 | occurs. A negative maxcant causes 364 | loop to loop forever (or at least until 365 | an error occurs). 0 is returned 366 | if maxcant is exhausted. 367 | 368 | 369 | 370 | 371 | 372 | 373 | next 374 | Collect the next packet 375 | 376 | 377 | 378 | 379 | 380 | 381 | (Pkthdr, string) next 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | DESCRIPTION 390 | 391 | next reads the next packet (by calling 392 | dispatch with a 393 | maxcant of 1) 394 | and returns a tuple (header, data) where 395 | header is a 396 | Pkthdr instance describing the data 397 | passed and data is the data itself. 398 | 399 | 400 | 401 | 402 | 403 | 404 | stats 405 | get capture statistics 406 | 407 | 408 | 409 | 410 | 411 | 412 | (int32, int32, int32) stats 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | DESCRIPTION 421 | 422 | stats returns statistics on the current 423 | capture as a tuple (recv, drop, ifdrop) 424 | 425 | 426 | 427 | 428 | 429 | 430 | setfilter 431 | Specify a filter 432 | 433 | 434 | 435 | 436 | 437 | 438 | setfilter 439 | 440 | 441 | string filter 442 | 443 | 444 | 445 | 446 | 447 | 448 | DESCRIPTION 449 | 450 | setfilter is used to specify a filter 451 | for this object. 452 | 453 | 454 | 455 | 456 | 457 | 458 | getfd 459 | get a file descriptor on which a select() can be 460 | done for a live capture 461 | 462 | 463 | 464 | 465 | 466 | 467 | int getfd 468 | 469 | 470 | string filter 471 | 472 | 473 | 474 | 475 | 476 | 477 | DESCRIPTION 478 | 479 | getfd returns, on UNIX, a file descriptor 480 | number for a file descriptor on which one can do a select(), 481 | poll(), epoll_wait(), kevent(), or other such call to wait 482 | for it to be possible to read packets without blocking, if 483 | such a descriptor exists, or -1, if no such descriptor exists. 484 | 485 | 486 | 487 | 488 | 489 | 490 | set_snaplen 491 | Set the snapshot length for a not-yet-activated 492 | capture handle 493 | 494 | 495 | 496 | 497 | 498 | 499 | int set_snaplen 500 | 501 | 502 | int snaplen 503 | 504 | 505 | 506 | 507 | 508 | 509 | DESCRIPTION 510 | 511 | set_snaplen sets the snapshot length 512 | to be used on a capture handle when the handle is activated 513 | to snaplen. 514 | set_snaplen returns 0 on success 515 | or PCAP_ERROR_ACTIVATED if called on a capture handle that 516 | has been activated. 517 | 518 | 519 | 520 | 521 | 522 | 523 | set_promisc 524 | Set promiscuous mode for a not-yet-activated 525 | capture handle 526 | 527 | 528 | 529 | 530 | 531 | 532 | int set_promisc 533 | 534 | 535 | int promisc 536 | 537 | 538 | 539 | 540 | 541 | 542 | DESCRIPTION 543 | 544 | set_promisc sets whether promiscuous mode 545 | should be set on a capture handle when the handle is activated. 546 | If promisc is non-zero, promiscuous mode will be set, otherwise 547 | it will not be set. 548 | set_promisc returns 0 on success 549 | or PCAP_ERROR_ACTIVATED if called on a capture handle that 550 | has been activated. 551 | 552 | 553 | 554 | 555 | 556 | 557 | set_timeout 558 | Set the read timeout for a not-yet-activated 559 | capture handle 560 | 561 | 562 | 563 | 564 | 565 | 566 | int set_timeout 567 | 568 | 569 | int timeout 570 | 571 | 572 | 573 | 574 | 575 | 576 | DESCRIPTION 577 | 578 | set_timeout sets the read timeout 579 | that will be used on a capture handle when the handle 580 | is activated to to_ms, which is in units of milliseconds. 581 | set_timeout returns 0 on success 582 | or PCAP_ERROR_ACTIVATED if called on a capture handle that 583 | has been activated. 584 | 585 | 586 | 587 | 588 | 589 | 590 | set_buffer_size 591 | Set the buffer size for a not-yet-activated capture handle 592 | capture handle 593 | 594 | 595 | 596 | 597 | 598 | 599 | int set_buffer_size 600 | 601 | 602 | int buffer_size 603 | 604 | 605 | 606 | 607 | 608 | 609 | DESCRIPTION 610 | 611 | set_buffer_size sets the buffer size 612 | that will be used on a capture handle when the handle is 613 | activated to buffer_size, which is in units of bytes. 614 | set_buffer_size returns 0 on success 615 | or PCAP_ERROR_ACTIVATED if called on a capture handle that 616 | has been activated. 617 | 618 | 619 | 620 | 621 | 622 | 623 | activate 624 | Activate a capture handle 625 | 626 | 627 | 628 | 629 | 630 | 631 | int activate 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | DESCRIPTION 640 | 641 | activate is used to activate a 642 | packet capture handle to look at packets on the network, 643 | with the options that were set on the handle being in effect. 644 | activate returns 0 on success without 645 | warnings, a non-zero positive value on success with warnings, 646 | and a negative value on error. A non-zero return value indicates 647 | what warning or error condition occurred. 648 | has been activated. 649 | See https://www.tcpdump.org/manpages/pcap_activate.3pcap.html for 650 | all possible return values. 651 | 652 | 653 | 654 | 655 | 656 | 657 | getnet 658 | getmask 659 | Get the associated network number and mask 660 | 661 | 662 | 663 | 664 | 665 | 666 | int32 getnet 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | int32 getmask 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | DESCRIPTION 684 | 685 | getnet and getmask 686 | are used to determine the network number and mask associated 687 | with the network device attached to this 688 | Reader. 689 | 690 | 691 | 692 | 693 | 694 | 695 | datalink 696 | Obtain the link layer type 697 | 698 | 699 | 700 | 701 | 702 | 703 | int datalink 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | DESCRIPTION 712 | 713 | datalink returns the link layer type; link layer types it can return include: 714 | 715 | 716 | 717 | DLT_NULL 718 | 719 | 720 | 721 | BSD loopback encapsulation; the 722 | link layer header is a 4-byte field, in host 723 | byte order, containing a PF_ 724 | value from socket.h for the 726 | network-layer protocol of the packet. 727 | 728 | 729 | 730 | host byte order is the byte order 731 | of the machine on which the packets are captured, 732 | and the PF_ values are for 733 | the OS of the machine on which 734 | the packets are captured; if a live capture is 735 | being done, host byte order is the 736 | byte order of the machine capturing the packets, 737 | and the PF_ values are those 738 | of the OS of the machine 739 | capturing the packets, but if a savefile is being 740 | read, the byte order and PF_ 741 | values are not necessarily 742 | those of the machine reading the capture file. 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | DLT_EN10MB 751 | 752 | 753 | Ethernet (10Mb, 100Mb, 1000Mb, and up) 754 | 755 | 756 | 757 | 758 | 759 | DLT_IEEE802 760 | 761 | 762 | 763 | IEEE 802.5 Token Ring 764 | 765 | 766 | 767 | 768 | 769 | 770 | DLT_ARCNET 771 | 772 | 773 | 774 | ARCNET 775 | 776 | 777 | 778 | 779 | 780 | 781 | DLT_SLIP 782 | 783 | 784 | 785 | SLIP; the link layer header contains, in order: 786 | 787 | 788 | 789 | a 1-byte flag, which is 790 | 0 for packets received by 791 | the machine and 1 for 792 | packets sent by the machine. 793 | 794 | 795 | 796 | 797 | 798 | a 1-byte field, the upper 4 bits of which indicate the type of packet, as per RFC 1144: 799 | 800 | 801 | 802 | 803 | 0x40; an unmodified 804 | IP datagram 805 | (TYPE_IP) 806 | 807 | 808 | 809 | 810 | 811 | 0x70; an 812 | uncompressed-TCP/IP 813 | datagram 814 | (UNCOMPRESSED_TCP), 815 | with that byte being the first byte of 816 | the raw IP header on 817 | the wire, containing the connection 818 | number in the protocol field 819 | 820 | 821 | 822 | 823 | 824 | 0x80; a 825 | compressed-TCP/IP 826 | datagram 827 | (COMPRESSED_TCP), 828 | with that byte being the first byte of 829 | the compressed TCP/IP 830 | datagram header 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | for UNCOMPRESSED_TCP, the 840 | rest of the modified IP 841 | header, and for 842 | COMPRESSED_TCP, the 843 | compressed TCP/IP datagram 844 | header 845 | 846 | 847 | 848 | 849 | for a total of 16 bytes; the uncompressed IP datagram follows the header. 850 | 851 | 852 | 853 | 854 | 855 | 856 | DLT_PPP 857 | 858 | 859 | 860 | PPP; if the first 2 bytes are 861 | 0xff and 0x03, 862 | it's PPP in 863 | HDLC-like framing, with the 864 | PPP header following those two 865 | bytes, otherwise it's PPP without 866 | framing, and the packet begins with the 867 | PPP header. 868 | 869 | 870 | 871 | 872 | 873 | 874 | DLT_FDDI 875 | 876 | 877 | 878 | FDDI 879 | 880 | 881 | 882 | 883 | 884 | 885 | DLT_ATM_RFC1483 886 | 887 | 888 | 889 | RFC 1483 890 | LLC/SNAP-encapsulated 891 | ATM; the packet begins with an 892 | IEEE 802.2 LLC 893 | header. 894 | 895 | 896 | 897 | 898 | 899 | 900 | DLT_RAW 901 | 902 | 903 | 904 | Raw IP; the packet begins with an 905 | IP header. 906 | 907 | 908 | 909 | 910 | 911 | 912 | DLT_PPP_SERIAL 913 | 914 | 915 | 916 | PPP in 917 | HDLC-like framing, as per 918 | RFC 1662, or Cisco 919 | PPP with HDLC 920 | framing, as per section 4.3.1 of 921 | RFC 1547; the first byte will be 922 | 0xFF for PPP 923 | in HDLC-like framing, and 924 | will be 0x0F or 925 | 0x8F for Cisco 926 | PPP with HDLC 927 | framing. 928 | 929 | 930 | 931 | 932 | 933 | 934 | DLT_PPP_ETHER 935 | 936 | 937 | 938 | PPPoE; the packet begins with a 939 | PPPoE header, as per 940 | RFC 2516. 941 | 942 | 943 | 944 | 945 | 946 | 947 | DLT_C_HDLC 948 | 949 | 950 | 951 | Cisco PPP with 952 | HDLC framing, as per section 953 | 4.3.1 of RFC 1547. 954 | 955 | 956 | 957 | 958 | 959 | 960 | DLT_IEEE802_11 961 | 962 | 963 | 964 | IEEE 802.11 wireless 965 | LAN. 966 | 967 | 968 | 969 | 970 | 971 | 972 | DLT_LOOP 973 | 974 | 975 | 976 | OpenBSD loopback encapsulation; the link layer 977 | header is a 4-byte field, in network byte 978 | order, containing a PF_ value 979 | from OpenBSD's socket.h for the 981 | network-layer protocol of the packet. 982 | 983 | 984 | 985 | Note that, if a savefile is being read, those 986 | PF_ values are 987 | not necessarily those of the 988 | machine reading the capture file. 989 | 990 | 991 | 992 | 993 | 994 | 995 | 996 | DLT_LINUX_SLL 997 | 998 | 999 | 1000 | Linux cooked capture encapsulation; the link layer 1001 | header contains, in order: 1002 | 1003 | 1004 | 1005 | 1006 | a 2-byte "packet type", in network 1007 | byte order, which is one of: 1008 | 1009 | 1010 | 1011 | 1012 | 0; packet was sent to 1013 | us by somebody else. 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1; packet was 1020 | broadcast by somebody else. 1021 | 1022 | 1023 | 1024 | 1025 | 1026 | 2; packet was 1027 | multicast, but not broadcast, by 1028 | somebody else. 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 3; packet was sent by 1035 | somebody else to somebody else. 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 4; packet was sent by 1042 | us. 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | 1049 | 1050 | 1051 | a 2-byte field, in network byte order, 1052 | containing a Linux 1053 | ARPHRD_ value for the 1054 | link layer device type. 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | a 2-byte field, in network byte order, 1061 | containing the length of the link layer 1062 | address of the sender of the packet (which 1063 | could be 0). 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | an 8-byte field containing that number 1070 | of bytes of the link layer header (if there 1071 | are more than 8 bytes, only the first 8 are 1072 | present). 1073 | 1074 | 1075 | 1076 | 1077 | 1078 | a 2-byte field containing an Ethernet 1079 | protocol type, in network byte order, or 1080 | containing 1 for Novell 1081 | 802.3 frames without an 802.2 1082 | LLC header or 1083 | 4 for frames beginning with 1084 | an 802.2 LLC header. 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | DLT_LTALK 1095 | 1096 | 1097 | 1098 | Apple LocalTalk; the packet begins with an AppleTalk 1099 | LLAP header. 1100 | 1101 | 1102 | 1103 | 1104 | 1105 | 1106 | 1107 | 1108 | 1109 | 1110 | getnonblock / setnonblock 1111 | 1112 | Manipulate the 1113 | non-blocking flag 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | int getnonblock 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | setnonblock 1131 | 1132 | 1133 | int state 1134 | 1135 | 1136 | 1137 | 1138 | 1139 | 1140 | DESCRIPTION 1141 | 1142 | getnonblock returns the current 1143 | non-blocking state of the capture descriptor; it 1144 | always returns 0 on savefiles. 1145 | 1146 | 1147 | 1148 | 1149 | DESCRIPTION 1150 | 1151 | setnonblock puts a capture descriptor, 1152 | opened with open_live, into 1153 | non-blocking mode, or takes it out of 1154 | non-blocking mode, depending on whether the 1155 | state argument is non-zero or 1156 | zero. It has no effect on savefiles. In non-blocking 1157 | mode, an attempt to read from the capture descriptor with 1158 | dispatch will, if no packets are 1159 | currently available to be read, return 1160 | 0 immediately rather than 1161 | blocking waiting for packets to arrive. 1162 | loop and next will 1163 | not work in non-blocking mode. 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 | dump_open 1171 | Create a Dumper object 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | Dumper dump_open 1179 | 1180 | 1181 | string filename 1182 | 1183 | 1184 | 1185 | 1186 | 1187 | 1188 | DESCRIPTION 1189 | 1190 | dump_open is called to open a savefile 1191 | for writing and associate it to a newly created 1192 | Dumper instance. The name 1193 | - is a synonym for stdout. 1195 | filename specifies the name of the 1196 | file to open. 1197 | 1198 | 1199 | 1200 | 1201 | 1202 | 1203 | close 1204 | 1205 | Close a Reader 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | 1212 | Reader close 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | DESCRIPTION 1220 | 1221 | close closes a Reader using pcap_close. 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | Dumper Object Reference 1230 | 1231 | 1232 | dump 1233 | 1234 | Dump a packet to a savefile 1235 | 1236 | 1237 | 1238 | 1239 | 1240 | 1241 | dump 1242 | 1243 | 1244 | Pkthdr header 1245 | 1246 | 1247 | string data 1248 | 1249 | 1250 | 1251 | 1252 | 1253 | 1254 | DESCRIPTION 1255 | 1256 | dump outputs a packet to the savefile 1257 | opened with dump_open from type 1258 | Reader. 1259 | 1260 | 1261 | 1262 | 1263 | 1264 | close 1265 | 1266 | Close a Dumper 1267 | 1268 | 1269 | 1270 | 1271 | 1272 | 1273 | Dumper close 1274 | 1275 | 1276 | 1277 | 1278 | 1279 | 1280 | DESCRIPTION 1281 | 1282 | close closes a Dumper. 1283 | 1284 | 1285 | 1286 | 1287 | 1288 | 1289 | Pkthdr Object Reference 1290 | 1291 | 1292 | getts 1293 | getcaplen 1294 | getlen 1295 | Obtain packet header information 1296 | 1297 | 1298 | 1299 | 1300 | 1301 | 1302 | (long, long) getts 1303 | 1304 | 1305 | 1306 | 1307 | 1308 | 1309 | 1310 | 1311 | long getcaplen 1312 | 1313 | 1314 | 1315 | 1316 | 1317 | 1318 | 1319 | 1320 | long getlen 1321 | 1322 | 1323 | 1324 | 1325 | 1326 | 1327 | 1328 | DESCRIPTION 1329 | 1330 | getts, getcaplen 1331 | and getlen return the timestamp, 1332 | capture length and total length fields of the packet header, 1333 | respectively. 1334 | 1335 | 1336 | Timestamp is a tuple with two elements: the number of 1337 | seconds since the Epoch, and the amount of microseconds past 1338 | the current second. The capture length is the number of 1339 | bytes of the packet that are available from the capture. 1340 | Finally, total length gives the length of the packet, in 1341 | bytes (which might be more than the number of bytes 1342 | available from the capture, if the length of the packet is 1343 | larger than the maximum number of bytes to capture). 1344 | 1345 | 1346 | 1347 | 1348 | 1349 | 1350 | Bpf Object Reference 1351 | 1352 | 1353 | filter 1354 | Test a packet against a compiled filter 1355 | 1356 | 1357 | 1358 | 1359 | 1360 | 1361 | int filter 1362 | 1363 | 1364 | string packet 1365 | 1366 | 1367 | 1368 | 1369 | 1370 | 1371 | DESCRIPTION 1372 | 1373 | filter tests a packet against a 1374 | compiled filter as returned by 1375 | pcapy's compile. 1376 | If the packet is allowed to pass through 1377 | -1 is returned, otherwise 1378 | filter returns 1379 | 0. 1380 | 1381 | 1382 | 1383 | 1384 | 1385 | 1386 | Bibliography 1387 | 1388 | Sources 1389 | 1390 | 1391 | Portions of this work based on 1392 | 1393 | pcap 1394 | 3 1395 | by the Lawrence 1396 | Berkeley National Laboratory, University of California, 1397 | Berkeley, CA. 1398 | 1399 | 1400 | 1401 | 1402 | 1403 | -------------------------------------------------------------------------------- /pcapy.html: -------------------------------------------------------------------------------- 1 | 2 | Part I. Pcapy Reference

Part I. Pcapy Reference

CORE SECURITY TECHNOLOGIES

Revision History
Revision Revision: 16Date: 2018-06-04Author: jkohen
2018 updated

Table of Contents

I. Pcapy Module Reference
open_live — Obtain a packet capture descriptor to look at packets on the network
open_offline — 3 | Obtain a packet capture descriptor to look at packets on a savefile 4 |
lookupdev — 5 | Return a network device suitable for use with 6 | open_live 7 |
findalldevs — Obtain the list of available network devices
compile — Compile a BPF filter
create — Creates a non-activated packet capture handle to look at packets on the network
II. Reader Object Reference
dispatch — Collect and process packets
next — Collect the next packet
stats — get capture statistics
setfilter — Specify a filter
getfd — get a file descriptor on which a select() can be 8 | done for a live capture
set_snaplen — Set the snapshot length for a not-yet-activated 9 | capture handle
set_promisc — Set promiscuous mode for a not-yet-activated 10 | capture handle
set_timeout — Set the read timeout for a not-yet-activated 11 | capture handle
set_buffer_size — Set the buffer size for a not-yet-activated capture handle 12 | capture handle
activate — Activate a capture handle
getnet — Get the associated network number and mask
datalink — Obtain the link layer type
getnonblock / setnonblock — 13 | Manipulate the 14 | non-blocking flag 15 |
dump_open — Create a Dumper object
close — 16 | Close a Reader 17 |
III. Dumper Object Reference
dump — 18 | Dump a packet to a savefile 19 |
close — 20 | Close a Dumper 21 |
IV. Pkthdr Object Reference
getts — Obtain packet header information
V. Bpf Object Reference
filter — Test a packet against a compiled filter
Bibliography

Pcapy Module Reference


Table of Contents

open_live — Obtain a packet capture descriptor to look at packets on the network
open_offline — 22 | Obtain a packet capture descriptor to look at packets on a savefile 23 |
lookupdev — 24 | Return a network device suitable for use with 25 | open_live 26 |
findalldevs — Obtain the list of available network devices
compile — Compile a BPF filter
create — Creates a non-activated packet capture handle to look at packets on the network

Name

open_live — Obtain a packet capture descriptor to look at packets on the network

Synopsis

27 | Reader open_live 28 | (device,  
 snaplen,  
 promisc,  
 to_ms); 
29 | string device 30 | ;
31 | int snaplen 32 | ;
33 | int promisc 34 | ;
35 | int to_ms 36 | ;
 

DESCRIPTION

37 | open_live is used to obtain a packet 38 | capture descriptor to look at packets on the network. 39 | device is a string that specifies the 40 | network device to open; on Linux systems with 2.2 or later 41 | kernels, a device argument of any or 42 | NULL can be used to capture packets 43 | from all interfaces. snaplen 44 | specifies the maximum number of bytes to capture. 45 | promisc specifies if the interface is 46 | to be put into promiscuous mode. (Note that even if this 47 | parameter is false, the interface could well be in 48 | promiscuous mode for some other reason.) For now, this 49 | doesn't work on the any device; if an 50 | argument of any or 51 | NULL is supplied, the 52 | promisc flag is ignored. 53 | to_ms specifies the read timeout in 54 | milliseconds. The read timeout is used to arrange that the 55 | read not necessarily return immediately when a packet is 56 | seen, but that it wait for some amount of time to allow more 57 | packets to arrive and to read multiple packets from the OS 58 | kernel in one operation. Not all platforms support a read 59 | timeout; on platforms that don't, the read timeout is 60 | ignored. 61 |


Name

open_offline — 62 | Obtain a packet capture descriptor to look at packets on a savefile 63 |

Synopsis

64 | Reader open_offline 65 | (filename); 
66 | string filename 67 | ;
 

DESCRIPTION

68 | open_offline is called to open a 69 | savefile for reading. filename 70 | specifies the name of the file to open. The file has the 71 | same format as those used by 72 | tcpdump(8) and 73 | tcpslice(8). The name 74 | - is a synonym for 75 | stdin. 76 |


Name

lookupdev — 77 | Return a network device suitable for use with 78 | open_live 79 |

Synopsis

80 | string lookupdev 81 | (); 
 

DESCRIPTION

82 | lookupdev returns the name of a network 83 | device suitable for use with open_live. 84 |


Name

findalldevs — Obtain the list of available network devices

Synopsis

85 | string[] findalldevs 86 | (); 
 

DESCRIPTION

87 | findalldevs constructs a list of 88 | network devices that can be opened with 89 | open_live. (Note that there may be 90 | network devices that cannot be opened with 91 | open_live, because, for example, that 92 | process might not have sufficient privileges to open them 93 | for capturing; if so, those devices will not appear on the 94 | list.) 95 |


Name

compile — Compile a BPF filter

Synopsis

96 | Bpf compile 97 | (linktype,  
 snaplen,  
 filter,  
 optimize,  
 netmask); 
98 | int linktype 99 | ;
100 | int snaplen 101 | ;
102 | string filter 103 | ;
104 | int optimize 105 | ;
106 | int32 netmask 107 | ;
 

DESCRIPTION

108 | compile is used to compile the 109 | filter into a filter program. 110 | snaplen specifies the maximum number of 111 | bytes to capture. optimize controls 112 | whether optimization on the resulting code is performed. 113 | netmask specifies the netmask of the 114 | local network. 115 |


Name

create — Creates a non-activated packet capture handle to look at packets on the network

Synopsis

116 | Reader create 117 | (device); 
118 | string device 119 | ;
 

DESCRIPTION

120 | create is used to create a 121 | packet capture handle to look at packets on the network. 122 | The returned handle must be activated with 123 | activate() before packets can be captured 124 | with it; options for the capture, such as promiscuous mode, 125 | can be set on the handle before activating it. 126 |

Reader Object Reference


Table of Contents

dispatch — Collect and process packets
next — Collect the next packet
stats — get capture statistics
setfilter — Specify a filter
getfd — get a file descriptor on which a select() can be 127 | done for a live capture
set_snaplen — Set the snapshot length for a not-yet-activated 128 | capture handle
set_promisc — Set promiscuous mode for a not-yet-activated 129 | capture handle
set_timeout — Set the read timeout for a not-yet-activated 130 | capture handle
set_buffer_size — Set the buffer size for a not-yet-activated capture handle 131 | capture handle
activate — Activate a capture handle
getnet — Get the associated network number and mask
datalink — Obtain the link layer type
getnonblock / setnonblock — 132 | Manipulate the 133 | non-blocking flag 134 |
dump_open — Create a Dumper object
close — 135 | Close a Reader 136 |

Name

dispatch, loop — Collect and process packets

Synopsis

137 | int dispatch 138 | (maxcant,  
 (* callback)); 
139 | int maxcant 140 | ;
141 | void (* callback) 142 | (Pkthdr, string) 143 | ;
 
144 | int loop 145 | (maxcant,  
 (* callback)); 
146 | int maxcant 147 | ;
148 | void (* callback) 149 | (Pkthdr, string) 150 | ;
 

DESCRIPTION

151 | dispatch is used to collect and process 152 | packets. maxcant specifies the 153 | maximum number of packets to process before returning. This 154 | is not a minimum number; when reading a live capture, only 155 | one bufferful of packets is read at a time, so fewer than 156 | maxcant packets may be processed. A 157 | cnt of -1 158 | processes all the packets received in one buffer when 159 | reading a live capture, or all the packets in the file when 160 | reading a savefile. callback 161 | specifies a routine to be called with two arguments: a 162 | Pkthdr instance describing the data 163 | passed and the data itself. 164 |

165 | The number of packets read is returned. 166 | 0 is returned if no packets were 167 | read from a live capture (if, for example, they were 168 | discarded because they didn't pass the packet filter, or if, 169 | on platforms that support a read timeout that starts before 170 | any packets arrive, the timeout expires before any packets 171 | arrive, or if the file descriptor for the capture device is 172 | in non-blocking mode and no packets were available to be 173 | read) or if no more packets are available in a savefile. 174 |

Note

175 | When reading a live capture, dispatch 176 | will not necessarily return when the read times out; on 177 | some platforms, the read timeout isn't supported, and, on 178 | other platforms, the timer doesn't start until at least 179 | one packet arrives. This means that the read timeout 180 | should not be used in, for example, 181 | an interactive application, to allow the packet capture 182 | loop to poll for user input periodically, as there's no 183 | guarantee that dispatch will return 184 | after the timeout expires. 185 |

186 | loop is similar to 187 | dispatch except it keeps reading 188 | packets until maxcant packets are 189 | processed or an error occurs. It does 190 | not return when live read timeouts 191 | occur. Rather, specifying a non-zero read timeout to 192 | open_live and then calling 193 | dispatch allows the reception and 194 | processing of any packets that arrive when the timeout 195 | occurs. A negative maxcant causes 196 | loop to loop forever (or at least until 197 | an error occurs). 0 is returned 198 | if maxcant is exhausted. 199 |


Name

next — Collect the next packet

Synopsis

200 | (Pkthdr, string) next 201 | (); 
 

DESCRIPTION

202 | next reads the next packet (by calling 203 | dispatch with a 204 | maxcant of 1) 205 | and returns a tuple (header, data) where 206 | header is a 207 | Pkthdr instance describing the data 208 | passed and data is the data itself. 209 |


Name

stats — get capture statistics

Synopsis

210 | (int32, int32, int32) stats 211 | (); 
 

DESCRIPTION

212 | stats returns statistics on the current 213 | capture as a tuple (recv, drop, ifdrop) 214 |


Name

setfilter — Specify a filter

Synopsis

215 | setfilter 216 | (filter); 
217 | string filter 218 | ;
 

DESCRIPTION

219 | setfilter is used to specify a filter 220 | for this object. 221 |


Name

getfd — get a file descriptor on which a select() can be 222 | done for a live capture

Synopsis

223 | int getfd 224 | (filter); 
225 | string filter 226 | ;
 

DESCRIPTION

227 | getfd returns, on UNIX, a file descriptor 228 | number for a file descriptor on which one can do a select(), 229 | poll(), epoll_wait(), kevent(), or other such call to wait 230 | for it to be possible to read packets without blocking, if 231 | such a descriptor exists, or -1, if no such descriptor exists. 232 |


Name

set_snaplen — Set the snapshot length for a not-yet-activated 233 | capture handle

Synopsis

234 | int set_snaplen 235 | (snaplen); 
236 | int snaplen 237 | ;
 

DESCRIPTION

238 | set_snaplen sets the snapshot length 239 | to be used on a capture handle when the handle is activated 240 | to snaplen. 241 | set_snaplen returns 0 on success 242 | or PCAP_ERROR_ACTIVATED if called on a capture handle that 243 | has been activated. 244 |


Name

set_promisc — Set promiscuous mode for a not-yet-activated 245 | capture handle

Synopsis

246 | int set_promisc 247 | (promisc); 
248 | int promisc 249 | ;
 

DESCRIPTION

250 | set_promisc sets whether promiscuous mode 251 | should be set on a capture handle when the handle is activated. 252 | If promisc is non-zero, promiscuous mode will be set, otherwise 253 | it will not be set. 254 | set_promisc returns 0 on success 255 | or PCAP_ERROR_ACTIVATED if called on a capture handle that 256 | has been activated. 257 |


Name

set_timeout — Set the read timeout for a not-yet-activated 258 | capture handle

Synopsis

259 | int set_timeout 260 | (timeout); 
261 | int timeout 262 | ;
 

DESCRIPTION

263 | set_timeout sets the read timeout 264 | that will be used on a capture handle when the handle 265 | is activated to to_ms, which is in units of milliseconds. 266 | set_timeout returns 0 on success 267 | or PCAP_ERROR_ACTIVATED if called on a capture handle that 268 | has been activated. 269 |


Name

set_buffer_size — Set the buffer size for a not-yet-activated capture handle 270 | capture handle

Synopsis

271 | int set_buffer_size 272 | (buffer_size); 
273 | int buffer_size 274 | ;
 

DESCRIPTION

275 | set_buffer_size sets the buffer size 276 | that will be used on a capture handle when the handle is 277 | activated to buffer_size, which is in units of bytes. 278 | set_buffer_size returns 0 on success 279 | or PCAP_ERROR_ACTIVATED if called on a capture handle that 280 | has been activated. 281 |


Name

activate — Activate a capture handle

Synopsis

282 | int activate 283 | (); 
 

DESCRIPTION

284 | activate is used to activate a 285 | packet capture handle to look at packets on the network, 286 | with the options that were set on the handle being in effect. 287 | activate returns 0 on success without 288 | warnings, a non-zero positive value on success with warnings, 289 | and a negative value on error. A non-zero return value indicates 290 | what warning or error condition occurred. 291 | has been activated. 292 | See https://www.tcpdump.org/manpages/pcap_activate.3pcap.html for 293 | all possible return values. 294 |


Name

getnet, getmask — Get the associated network number and mask

Synopsis

295 | int32 getnet 296 | (); 
 
297 | int32 getmask 298 | (); 
 

DESCRIPTION

299 | getnet and getmask 300 | are used to determine the network number and mask associated 301 | with the network device attached to this 302 | Reader. 303 |


Name

datalink — Obtain the link layer type

Synopsis

304 | int datalink 305 | (); 
 

DESCRIPTION

306 | datalink returns the link layer type; link layer types it can return include: 307 |

308 | DLT_NULL 309 |

310 | BSD loopback encapsulation; the 311 | link layer header is a 4-byte field, in host 312 | byte order, containing a PF_ 313 | value from socket.h for the 314 | network-layer protocol of the packet. 315 |

Note

316 | host byte order is the byte order 317 | of the machine on which the packets are captured, 318 | and the PF_ values are for 319 | the OS of the machine on which 320 | the packets are captured; if a live capture is 321 | being done, host byte order is the 322 | byte order of the machine capturing the packets, 323 | and the PF_ values are those 324 | of the OS of the machine 325 | capturing the packets, but if a savefile is being 326 | read, the byte order and PF_ 327 | values are not necessarily 328 | those of the machine reading the capture file. 329 |

330 | DLT_EN10MB 331 |
Ethernet (10Mb, 100Mb, 1000Mb, and up)
332 | DLT_IEEE802 333 |
334 | IEEE 802.5 Token Ring 335 |
336 | DLT_ARCNET 337 |
338 | ARCNET 339 |
340 | DLT_SLIP 341 |

342 | SLIP; the link layer header contains, in order: 343 |

  • 344 | a 1-byte flag, which is 345 | 0 for packets received by 346 | the machine and 1 for 347 | packets sent by the machine. 348 |
  • 349 | a 1-byte field, the upper 4 bits of which indicate the type of packet, as per RFC 1144: 350 | 351 |

    • 352 | 0x40; an unmodified 353 | IP datagram 354 | (TYPE_IP) 355 |
    • 356 | 0x70; an 357 | uncompressed-TCP/IP 358 | datagram 359 | (UNCOMPRESSED_TCP), 360 | with that byte being the first byte of 361 | the raw IP header on 362 | the wire, containing the connection 363 | number in the protocol field 364 |
    • 365 | 0x80; a 366 | compressed-TCP/IP 367 | datagram 368 | (COMPRESSED_TCP), 369 | with that byte being the first byte of 370 | the compressed TCP/IP 371 | datagram header 372 |

    373 |

  • 374 | for UNCOMPRESSED_TCP, the 375 | rest of the modified IP 376 | header, and for 377 | COMPRESSED_TCP, the 378 | compressed TCP/IP datagram 379 | header 380 |

381 | for a total of 16 bytes; the uncompressed IP datagram follows the header. 382 |

383 | DLT_PPP 384 |
385 | PPP; if the first 2 bytes are 386 | 0xff and 0x03, 387 | it's PPP in 388 | HDLC-like framing, with the 389 | PPP header following those two 390 | bytes, otherwise it's PPP without 391 | framing, and the packet begins with the 392 | PPP header. 393 |
394 | DLT_FDDI 395 |
396 | FDDI 397 |
398 | DLT_ATM_RFC1483 399 |
400 | RFC 1483 401 | LLC/SNAP-encapsulated 402 | ATM; the packet begins with an 403 | IEEE 802.2 LLC 404 | header. 405 |
406 | DLT_RAW 407 |
408 | Raw IP; the packet begins with an 409 | IP header. 410 |
411 | DLT_PPP_SERIAL 412 |
413 | PPP in 414 | HDLC-like framing, as per 415 | RFC 1662, or Cisco 416 | PPP with HDLC 417 | framing, as per section 4.3.1 of 418 | RFC 1547; the first byte will be 419 | 0xFF for PPP 420 | in HDLC-like framing, and 421 | will be 0x0F or 422 | 0x8F for Cisco 423 | PPP with HDLC 424 | framing. 425 |
426 | DLT_PPP_ETHER 427 |
428 | PPPoE; the packet begins with a 429 | PPPoE header, as per 430 | RFC 2516. 431 |
432 | DLT_C_HDLC 433 |
434 | Cisco PPP with 435 | HDLC framing, as per section 436 | 4.3.1 of RFC 1547. 437 |
438 | DLT_IEEE802_11 439 |
440 | IEEE 802.11 wireless 441 | LAN. 442 |
443 | DLT_LOOP 444 |

445 | OpenBSD loopback encapsulation; the link layer 446 | header is a 4-byte field, in network byte 447 | order, containing a PF_ value 448 | from OpenBSD's socket.h for the 449 | network-layer protocol of the packet. 450 |

Note

451 | Note that, if a savefile is being read, those 452 | PF_ values are 453 | not necessarily those of the 454 | machine reading the capture file. 455 |

456 | DLT_LINUX_SLL 457 |

458 | Linux cooked capture encapsulation; the link layer 459 | header contains, in order: 460 | 461 |

  • 462 | a 2-byte "packet type", in network 463 | byte order, which is one of: 464 | 465 |

    • 466 | 0; packet was sent to 467 | us by somebody else. 468 |
    • 469 | 1; packet was 470 | broadcast by somebody else. 471 |
    • 472 | 2; packet was 473 | multicast, but not broadcast, by 474 | somebody else. 475 |
    • 476 | 3; packet was sent by 477 | somebody else to somebody else. 478 |
    • 479 | 4; packet was sent by 480 | us. 481 |

    482 |

  • 483 | a 2-byte field, in network byte order, 484 | containing a Linux 485 | ARPHRD_ value for the 486 | link layer device type. 487 |
  • 488 | a 2-byte field, in network byte order, 489 | containing the length of the link layer 490 | address of the sender of the packet (which 491 | could be 0). 492 |
  • 493 | an 8-byte field containing that number 494 | of bytes of the link layer header (if there 495 | are more than 8 bytes, only the first 8 are 496 | present). 497 |
  • 498 | a 2-byte field containing an Ethernet 499 | protocol type, in network byte order, or 500 | containing 1 for Novell 501 | 802.3 frames without an 802.2 502 | LLC header or 503 | 4 for frames beginning with 504 | an 802.2 LLC header. 505 |

506 |

507 | DLT_LTALK 508 |
509 | Apple LocalTalk; the packet begins with an AppleTalk 510 | LLAP header. 511 |

512 |


Name

getnonblock / setnonblock — 513 | Manipulate the 514 | non-blocking flag 515 |

Synopsis

516 | int getnonblock 517 | (); 
 
518 | setnonblock 519 | (state); 
520 | int state 521 | ;
 

DESCRIPTION

522 | getnonblock returns the current 523 | non-blocking state of the capture descriptor; it 524 | always returns 0 on savefiles. 525 |

DESCRIPTION

526 | setnonblock puts a capture descriptor, 527 | opened with open_live, into 528 | non-blocking mode, or takes it out of 529 | non-blocking mode, depending on whether the 530 | state argument is non-zero or 531 | zero. It has no effect on savefiles. In non-blocking 532 | mode, an attempt to read from the capture descriptor with 533 | dispatch will, if no packets are 534 | currently available to be read, return 535 | 0 immediately rather than 536 | blocking waiting for packets to arrive. 537 | loop and next will 538 | not work in non-blocking mode. 539 |


Name

dump_open — Create a Dumper object

Synopsis

540 | Dumper dump_open 541 | (filename); 
542 | string filename 543 | ;
 

DESCRIPTION

544 | dump_open is called to open a savefile 545 | for writing and associate it to a newly created 546 | Dumper instance. The name 547 | - is a synonym for stdout. 548 | filename specifies the name of the 549 | file to open. 550 |


Name

close — 551 | Close a Reader 552 |

Synopsis

553 | Reader close 554 | (); 
 

DESCRIPTION

555 | close closes a Reader using pcap_close. 556 |

Dumper Object Reference


Table of Contents

dump — 557 | Dump a packet to a savefile 558 |
close — 559 | Close a Dumper 560 |

Name

dump — 561 | Dump a packet to a savefile 562 |

Synopsis

563 | dump 564 | (header,  
 data); 
565 | Pkthdr header 566 | ;
567 | string data 568 | ;
 

DESCRIPTION

569 | dump outputs a packet to the savefile 570 | opened with dump_open from type 571 | Reader. 572 |


Name

close — 573 | Close a Dumper 574 |

Synopsis

575 | Dumper close 576 | (); 
 

DESCRIPTION

577 | close closes a Dumper. 578 |

Pkthdr Object Reference


Table of Contents

getts — Obtain packet header information

Name

getts, getcaplen, getlen — Obtain packet header information

Synopsis

579 | (long, long) getts 580 | (); 
 
581 | long getcaplen 582 | (); 
 
583 | long getlen 584 | (); 
 

DESCRIPTION

585 | getts, getcaplen 586 | and getlen return the timestamp, 587 | capture length and total length fields of the packet header, 588 | respectively. 589 |

590 | Timestamp is a tuple with two elements: the number of 591 | seconds since the Epoch, and the amount of microseconds past 592 | the current second. The capture length is the number of 593 | bytes of the packet that are available from the capture. 594 | Finally, total length gives the length of the packet, in 595 | bytes (which might be more than the number of bytes 596 | available from the capture, if the length of the packet is 597 | larger than the maximum number of bytes to capture). 598 |

Bpf Object Reference


Table of Contents

filter — Test a packet against a compiled filter

Name

filter — Test a packet against a compiled filter

Synopsis

599 | int filter 600 | (packet); 
601 | string packet 602 | ;
 

DESCRIPTION

603 | filter tests a packet against a 604 | compiled filter as returned by 605 | pcapy's compile. 606 | If the packet is allowed to pass through 607 | -1 is returned, otherwise 608 | filter returns 609 | 0. 610 |

Bibliography

Sources

611 | Portions of this work based on 612 | pcap(3) by the Lawrence 613 | Berkeley National Laboratory, University of California, 614 | Berkeley, CA. 615 | .

--------------------------------------------------------------------------------