ubertooth script
parent
91dc86c072
commit
6330636b28
|
@ -0,0 +1,11 @@
|
|||
Description='A basic dhcp ethernet connection'
|
||||
Interface=eno1
|
||||
Connection=ethernet
|
||||
IP=dhcp
|
||||
#DHCPClient=dhcpcd
|
||||
#DHCPReleaseOnStop=no
|
||||
## for DHCPv6
|
||||
IP6=dhcp
|
||||
DHCP6Client=dhclient
|
||||
## for IPv6 autoconfiguration
|
||||
IP6=stateless
|
|
@ -0,0 +1,11 @@
|
|||
Description='A basic dhcp ethernet connection'
|
||||
Interface=enp0s20u1u3
|
||||
Connection=ethernet
|
||||
IP=dhcp
|
||||
#DHCPClient=dhcpcd
|
||||
#DHCPReleaseOnStop=no
|
||||
## for DHCPv6
|
||||
IP6=dhcp
|
||||
DHCP6Client=dhclient
|
||||
## for IPv6 autoconfiguration
|
||||
IP6=stateless
|
|
@ -0,0 +1 @@
|
|||
sudo pacman -S syncthing alsa alsa-utils pulseaudio pavucontrol i3 xf86-86-video-amdgpu mesa-libgl lib32-mesa-libgl mesa-vdpau lib32-mesa-vdpau firefox openssh flashplugin
|
|
@ -0,0 +1 @@
|
|||
sudo pacman -S syncthing alsa alsa-utils pulseaudio pavucontrol i3 xf86-86-video-amdgpu mesa-libgl lib32-mesa-libgl mesa-vdpau lib32-mesa-vdpau firefox openssh flashplugin
|
Binary file not shown.
|
@ -0,0 +1,17 @@
|
|||
*.o
|
||||
*.so.*
|
||||
*.so
|
||||
*.pyc
|
||||
|
||||
# Output directory
|
||||
build/
|
||||
|
||||
# wireshark plugins
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
plugin.c
|
||||
wireshark/plugins/btatt/Makefile
|
||||
wireshark/plugins/btle/Makefile
|
||||
wireshark/plugins/btsm/Makefile
|
|
@ -0,0 +1,21 @@
|
|||
language: c
|
||||
|
||||
cache: apt
|
||||
|
||||
sudo: false
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libpcap-dev
|
||||
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
|
||||
before_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- CFLAGS="-g -Wall -Wextra -Werror -Wno-zero-length-array" cmake ..
|
||||
|
||||
script: make
|
|
@ -0,0 +1,50 @@
|
|||
#
|
||||
# Copyright 2013 Dominic Spill
|
||||
#
|
||||
# This file is part of Libbtbb.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#top level cmake project for libbtbb lib + tools
|
||||
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
set(MAJOR_VERSION 0)
|
||||
set(MINOR_VERSION 3)
|
||||
project(libbtbb_all)
|
||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules)
|
||||
|
||||
set(INSTALL_DEFAULT_BINDIR "bin" CACHE STRING "Appended to CMAKE_INSTALL_PREFIX")
|
||||
|
||||
set( VERSION ${MAJOR_VERSION}.${MINOR_VERSION} )
|
||||
add_definitions( -DVERSION="${VERSION}" )
|
||||
|
||||
# Comment the following out for releases.
|
||||
set(CMAKE_C_FLAGS "$ENV{CFLAGS}")
|
||||
|
||||
add_subdirectory(lib)
|
||||
if(NOT DISABLE_PYTHON)
|
||||
add_subdirectory(python)
|
||||
endif()
|
||||
|
||||
# Create uninstall target
|
||||
configure_file(
|
||||
${PROJECT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
|
||||
@ONLY)
|
||||
|
||||
add_custom_target(uninstall
|
||||
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
|
||||
)
|
|
@ -0,0 +1,12 @@
|
|||
CMake Settings
|
||||
==============
|
||||
The following are flags that may be of use when configuing this project.
|
||||
|
||||
* DISABLE_PYTHON
|
||||
* A boolean flag for building and installing btaptap python tool.
|
||||
|
||||
* USE_PCAP
|
||||
* USE_PCAP=ON - Build with pcap support, the build will fail if
|
||||
libpcap is not found.
|
||||
* USE_PCAP=OFF - Disable pcap support will be disabled.
|
||||
* If left undefined pcap support will be enabled if libpcap is present.
|
|
@ -0,0 +1,43 @@
|
|||
libbtbb
|
||||
=======
|
||||
|
||||
This is the Bluetooth baseband decoding library, forked from the GR-Bluetooth
|
||||
project. It can be used to extract Bluetooth packet and piconet information
|
||||
from Ubertooth devices as well as GR-Bluetooth/USRP.
|
||||
|
||||
This code is incomplete, it is still under active development. Patches and
|
||||
bug reports should be submitted to the bug tracker on GitHub:
|
||||
https://github.com/greatscottgadgets/libbtbb/issues
|
||||
|
||||
This software has been developed and tested on Linux, it should work on other
|
||||
platforms but this has yet to be tested.
|
||||
|
||||
|
||||
Build Instructions
|
||||
==================
|
||||
|
||||
Libbtbb can be built and installed as follows:
|
||||
```
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake ..
|
||||
$ make
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
This will install the library to /usr/local/lib and the headers to
|
||||
/usr/local/include, to install to different locations use:
|
||||
```
|
||||
$ cmake -DINSTALL_DIR=/path/to/install -DINCLUDE_DIR=/path/to/include ..
|
||||
```
|
||||
|
||||
If you have previous versions of libbtbb, libubertooth or the Ubertooth tools
|
||||
installed, you can use the cleanup script to remove them:
|
||||
```
|
||||
$ sudo cmake/cleanup.sh -d
|
||||
```
|
||||
|
||||
To list the installed files without removing them, use:
|
||||
```
|
||||
$ cmake/cleanup.sh
|
||||
```
|
|
@ -0,0 +1,39 @@
|
|||
#!/bin/bash
|
||||
|
||||
# A quick and dirty script to remove old installs of
|
||||
# libbtbb, libubertooth and associated Ubertooth tools
|
||||
# Copyright 2014 Dominic Spill
|
||||
# License: GPL v2
|
||||
|
||||
FIND=`which find`
|
||||
|
||||
INSTALL_DIRS="/usr /usr/local"
|
||||
|
||||
LIBS="btbb ubertooth"
|
||||
|
||||
HEADERS="bluetooth_packet.h \
|
||||
bluetooth_piconet.h \
|
||||
bluetooth_le_packet.h \
|
||||
ubertooth_interface.h \
|
||||
ubertooth_control.h \
|
||||
ubertooth.h \
|
||||
"
|
||||
|
||||
if [ "$1" == "-d" ]
|
||||
then
|
||||
EXEC="-print -exec rm -f {} ;"
|
||||
echo "Deleting previous installs:"
|
||||
else
|
||||
EXEC=-print
|
||||
echo 'Installed files, use "sudo cleanup.sh -d" to delete these files'
|
||||
fi
|
||||
|
||||
for dir in $INSTALL_DIRS; do
|
||||
for lib in $LIBS; do
|
||||
$FIND ${dir}/lib -maxdepth 1 -name "lib$lib.so*" $EXEC
|
||||
done
|
||||
for header in $HEADERS; do
|
||||
$FIND ${dir}/include -maxdepth 1 -name "$header" $EXEC
|
||||
done
|
||||
$FIND ${dir}/bin -maxdepth 1 -name "ubertooth-*" $EXEC
|
||||
done
|
|
@ -0,0 +1,32 @@
|
|||
# http://www.vtk.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F
|
||||
|
||||
IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
|
||||
ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
|
||||
FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
||||
STRING(REGEX REPLACE "\n" ";" files "${files}")
|
||||
FOREACH(file ${files})
|
||||
MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
|
||||
IF(EXISTS "$ENV{DESTDIR}${file}")
|
||||
EXEC_PROGRAM(
|
||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
OUTPUT_VARIABLE rm_out
|
||||
RETURN_VALUE rm_retval
|
||||
)
|
||||
IF(NOT "${rm_retval}" STREQUAL 0)
|
||||
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
|
||||
ENDIF(NOT "${rm_retval}" STREQUAL 0)
|
||||
ELSEIF(IS_SYMLINK "$ENV{DESTDIR}${file}")
|
||||
EXEC_PROGRAM(
|
||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
OUTPUT_VARIABLE rm_out
|
||||
RETURN_VALUE rm_retval
|
||||
)
|
||||
IF(NOT "${rm_retval}" STREQUAL 0)
|
||||
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
|
||||
ENDIF(NOT "${rm_retval}" STREQUAL 0)
|
||||
ELSE(EXISTS "$ENV{DESTDIR}${file}")
|
||||
MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
|
||||
ENDIF(EXISTS "$ENV{DESTDIR}${file}")
|
||||
ENDFOREACH(file)
|
|
@ -0,0 +1,138 @@
|
|||
# CMAKE_PARSE_ARGUMENTS(<prefix> <options> <one_value_keywords> <multi_value_keywords> args...)
|
||||
#
|
||||
# CMAKE_PARSE_ARGUMENTS() is intended to be used in macros or functions for
|
||||
# parsing the arguments given to that macro or function.
|
||||
# It processes the arguments and defines a set of variables which hold the
|
||||
# values of the respective options.
|
||||
#
|
||||
# The <options> argument contains all options for the respective macro,
|
||||
# i.e. keywords which can be used when calling the macro without any value
|
||||
# following, like e.g. the OPTIONAL keyword of the install() command.
|
||||
#
|
||||
# The <one_value_keywords> argument contains all keywords for this macro
|
||||
# which are followed by one value, like e.g. DESTINATION keyword of the
|
||||
# install() command.
|
||||
#
|
||||
# The <multi_value_keywords> argument contains all keywords for this macro
|
||||
# which can be followed by more than one value, like e.g. the TARGETS or
|
||||
# FILES keywords of the install() command.
|
||||
#
|
||||
# When done, CMAKE_PARSE_ARGUMENTS() will have defined for each of the
|
||||
# keywords listed in <options>, <one_value_keywords> and
|
||||
# <multi_value_keywords> a variable composed of the given <prefix>
|
||||
# followed by "_" and the name of the respective keyword.
|
||||
# These variables will then hold the respective value from the argument list.
|
||||
# For the <options> keywords this will be TRUE or FALSE.
|
||||
#
|
||||
# All remaining arguments are collected in a variable
|
||||
# <prefix>_UNPARSED_ARGUMENTS, this can be checked afterwards to see whether
|
||||
# your macro was called with unrecognized parameters.
|
||||
#
|
||||
# As an example here a my_install() macro, which takes similar arguments as the
|
||||
# real install() command:
|
||||
#
|
||||
# function(MY_INSTALL)
|
||||
# set(options OPTIONAL FAST)
|
||||
# set(oneValueArgs DESTINATION RENAME)
|
||||
# set(multiValueArgs TARGETS CONFIGURATIONS)
|
||||
# cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
|
||||
# ...
|
||||
#
|
||||
# Assume my_install() has been called like this:
|
||||
# my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub)
|
||||
#
|
||||
# After the cmake_parse_arguments() call the macro will have set the following
|
||||
# variables:
|
||||
# MY_INSTALL_OPTIONAL = TRUE
|
||||
# MY_INSTALL_FAST = FALSE (this option was not used when calling my_install()
|
||||
# MY_INSTALL_DESTINATION = "bin"
|
||||
# MY_INSTALL_RENAME = "" (was not used)
|
||||
# MY_INSTALL_TARGETS = "foo;bar"
|
||||
# MY_INSTALL_CONFIGURATIONS = "" (was not used)
|
||||
# MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL"
|
||||
#
|
||||
# You can the continue and process these variables.
|
||||
#
|
||||
# Keywords terminate lists of values, e.g. if directly after a one_value_keyword
|
||||
# another recognized keyword follows, this is interpreted as the beginning of
|
||||
# the new option.
|
||||
# E.g. my_install(TARGETS foo DESTINATION OPTIONAL) would result in
|
||||
# MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION would
|
||||
# be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2010 Alexander Neundorf <neundorf@kde.org>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
|
||||
if(__CMAKE_PARSE_ARGUMENTS_INCLUDED)
|
||||
return()
|
||||
endif()
|
||||
set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE)
|
||||
|
||||
|
||||
function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames)
|
||||
# first set all result variables to empty/FALSE
|
||||
foreach(arg_name ${_singleArgNames} ${_multiArgNames})
|
||||
set(${prefix}_${arg_name})
|
||||
endforeach()
|
||||
|
||||
foreach(option ${_optionNames})
|
||||
set(${prefix}_${option} FALSE)
|
||||
endforeach()
|
||||
|
||||
set(${prefix}_UNPARSED_ARGUMENTS)
|
||||
|
||||
set(insideValues FALSE)
|
||||
set(currentArgName)
|
||||
|
||||
# now iterate over all arguments and fill the result variables
|
||||
foreach(currentArg ${ARGN})
|
||||
list(FIND _optionNames "${currentArg}" optionIndex) # ... then this marks the end of the arguments belonging to this keyword
|
||||
list(FIND _singleArgNames "${currentArg}" singleArgIndex) # ... then this marks the end of the arguments belonging to this keyword
|
||||
list(FIND _multiArgNames "${currentArg}" multiArgIndex) # ... then this marks the end of the arguments belonging to this keyword
|
||||
|
||||
if(${optionIndex} EQUAL -1 AND ${singleArgIndex} EQUAL -1 AND ${multiArgIndex} EQUAL -1)
|
||||
if(insideValues)
|
||||
if("${insideValues}" STREQUAL "SINGLE")
|
||||
set(${prefix}_${currentArgName} ${currentArg})
|
||||
set(insideValues FALSE)
|
||||
elseif("${insideValues}" STREQUAL "MULTI")
|
||||
list(APPEND ${prefix}_${currentArgName} ${currentArg})
|
||||
endif()
|
||||
else()
|
||||
list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg})
|
||||
endif()
|
||||
else()
|
||||
if(NOT ${optionIndex} EQUAL -1)
|
||||
set(${prefix}_${currentArg} TRUE)
|
||||
set(insideValues FALSE)
|
||||
elseif(NOT ${singleArgIndex} EQUAL -1)
|
||||
set(currentArgName ${currentArg})
|
||||
set(${prefix}_${currentArgName})
|
||||
set(insideValues "SINGLE")
|
||||
elseif(NOT ${multiArgIndex} EQUAL -1)
|
||||
set(currentArgName ${currentArg})
|
||||
set(${prefix}_${currentArgName})
|
||||
set(insideValues "MULTI")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
|
||||
# propagate the result variables to the caller:
|
||||
foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames})
|
||||
set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE)
|
||||
endforeach()
|
||||
set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE)
|
||||
|
||||
endfunction()
|
|
@ -0,0 +1,55 @@
|
|||
# Try to find the libbtbb library
|
||||
#
|
||||
# Once done this defines:
|
||||
# LIBBTBB_FOUND - system has libbtbb
|
||||
# LIBBTBB_INCLUDE_DIR - the libbtbb include directory
|
||||
# LIBBTBB_LIBRARIES - Link these to use libbtbb
|
||||
#
|
||||
# Copyright (c) 2013 Dominic Spill
|
||||
|
||||
|
||||
if (LIBBTBB_INCLUDE_DIR AND LIBBTBB_LIBRARIES)
|
||||
|
||||
# in cache already
|
||||
set(LIBBTBB_FOUND TRUE)
|
||||
|
||||
else (LIBBTBB_INCLUDE_DIR AND LIBBTBB_LIBRARIES)
|
||||
IF (NOT WIN32)
|
||||
# use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_LIBBTBB QUIET libbtbb)
|
||||
ENDIF(NOT WIN32)
|
||||
|
||||
FIND_PATH(LIBBTBB_INCLUDE_DIR
|
||||
NAMES btbb.h
|
||||
HINTS $ENV{LIBBTBB_DIR}/include ${PC_LIBBTBB_INCLUDEDIR}
|
||||
PATHS /usr/include /usr/local/include
|
||||
/opt/local/include
|
||||
${CMAKE_SOURCE_DIR}/../libbtbb/src
|
||||
${LIBBTBB_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
set(libbtbb_library_names btbb)
|
||||
|
||||
FIND_LIBRARY(LIBBTBB_LIBRARIES
|
||||
NAMES ${libbtbb_library_names}
|
||||
HINTS $ENV{LIBBTBB_DIR}/lib ${PC_LIBBTBB_LIBDIR}
|
||||
PATHS /usr/local/lib /usr/lib /opt/local/lib ${PC_LIBBTBB_LIBDIR}
|
||||
${PC_LIBBTBB_LIBRARY_DIRS} ${CMAKE_SOURCE_DIR}/../libbtbb/src
|
||||
)
|
||||
|
||||
if(LIBBTBB_INCLUDE_DIR)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${LIBBTBB_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
if(LIBBTBB_LIBRARIES)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${LIBBTBB_LIBRARIES})
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBBTBB DEFAULT_MSG LIBBTBB_LIBRARIES LIBBTBB_INCLUDE_DIR)
|
||||
|
||||
MARK_AS_ADVANCED(LIBBTBB_INCLUDE_DIR LIBBTBB_LIBRARIES)
|
||||
|
||||
endif (LIBBTBB_INCLUDE_DIR AND LIBBTBB_LIBRARIES)
|
|
@ -0,0 +1,146 @@
|
|||
#
|
||||
# $Id: FindPCAP.cmake 38372 2011-08-05 18:52:53Z gerald $
|
||||
#
|
||||
###################################################################
|
||||
#
|
||||
# Copyright (c) 2006 Frederic Heem, <frederic.heem@telsey.it>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# * Neither the name of the Telsey nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
###################################################################
|
||||
# - Find pcap
|
||||
# Find the PCAP includes and library
|
||||
# http://www.tcpdump.org/
|
||||
#
|
||||
# The environment variable PCAPDIR allows to specficy where to find
|
||||
# libpcap in non standard location.
|
||||
#
|
||||
# PCAP_INCLUDE_DIRS - where to find pcap.h, etc.
|
||||
# PCAP_LIBRARIES - List of libraries when using pcap.
|
||||
# PCAP_FOUND - True if pcap found.
|
||||
|
||||
|
||||
IF(EXISTS $ENV{PCAPDIR})
|
||||
FIND_PATH(PCAP_INCLUDE_DIR
|
||||
NAMES
|
||||
pcap/pcap.h
|
||||
pcap.h
|
||||
PATHS
|
||||
$ENV{PCAPDIR}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
FIND_LIBRARY(PCAP_LIBRARY
|
||||
NAMES
|
||||
pcap
|
||||
PATHS
|
||||
$ENV{PCAPDIR}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
|
||||
ELSE(EXISTS $ENV{PCAPDIR})
|
||||
FIND_PATH(PCAP_INCLUDE_DIR
|
||||
NAMES
|
||||
pcap/pcap.h
|
||||
pcap.h
|
||||
HINTS
|
||||
/usr/local/opt/libpcap/include
|
||||
)
|
||||
|
||||
FIND_LIBRARY(PCAP_LIBRARY
|
||||
NAMES
|
||||
pcap
|
||||
HINTS
|
||||
/usr/local/opt/libpcap/lib
|
||||
)
|
||||
|
||||
ENDIF(EXISTS $ENV{PCAPDIR})
|
||||
|
||||
SET(PCAP_INCLUDE_DIRS ${PCAP_INCLUDE_DIR})
|
||||
SET(PCAP_LIBRARIES ${PCAP_LIBRARY})
|
||||
|
||||
IF(PCAP_INCLUDE_DIRS)
|
||||
MESSAGE(STATUS "Pcap include dirs set to ${PCAP_INCLUDE_DIRS}")
|
||||
ELSE(PCAP_INCLUDE_DIRS)
|
||||
MESSAGE(FATAL " Pcap include dirs cannot be found")
|
||||
ENDIF(PCAP_INCLUDE_DIRS)
|
||||
|
||||
IF(PCAP_LIBRARIES)
|
||||
MESSAGE(STATUS "Pcap library set to ${PCAP_LIBRARIES}")
|
||||
ELSE(PCAP_LIBRARIES)
|
||||
MESSAGE(FATAL "Pcap library cannot be found")
|
||||
ENDIF(PCAP_LIBRARIES)
|
||||
|
||||
#Functions
|
||||
INCLUDE(CheckFunctionExists)
|
||||
INCLUDE(CheckVariableExists)
|
||||
SET(CMAKE_REQUIRED_INCLUDES ${PCAP_INCLUDE_DIRS})
|
||||
SET(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARIES})
|
||||
CHECK_VARIABLE_EXISTS("pcap_version" HAVE_PCAP_VERSION)
|
||||
CHECK_FUNCTION_EXISTS("pcap_open_dead" HAVE_PCAP_OPEN_DEAD)
|
||||
CHECK_FUNCTION_EXISTS("pcap_freecode" HAVE_PCAP_FREECODE)
|
||||
#
|
||||
# Note: for pcap_breakloop() and pcap_findalldevs(), the autoconf script
|
||||
# checks for more than just whether the function exists, it also checks
|
||||
# for whether pcap.h declares it; Mac OS X software/security updates can
|
||||
# update libpcap without updating the headers.
|
||||
#
|
||||
CHECK_FUNCTION_EXISTS("pcap_breakloop" HAVE_PCAP_BREAKLOOP)
|
||||
CHECK_FUNCTION_EXISTS("pcap_create" HAVE_PCAP_CREATE)
|
||||
CHECK_FUNCTION_EXISTS("pcap_datalink_name_to_val" HAVE_PCAP_DATALINK_NAME_TO_VAL)
|
||||
CHECK_FUNCTION_EXISTS("pcap_datalink_val_to_description" HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION)
|
||||
CHECK_FUNCTION_EXISTS("pcap_datalink_val_to_name" HAVE_PCAP_DATALINK_VAL_TO_NAME)
|
||||
CHECK_FUNCTION_EXISTS("pcap_findalldevs" HAVE_PCAP_FINDALLDEVS)
|
||||
CHECK_FUNCTION_EXISTS("pcap_free_datalinks" HAVE_PCAP_FREE_DATALINKS)
|
||||
CHECK_FUNCTION_EXISTS("pcap_get_selectable_fd" HAVE_PCAP_GET_SELECTABLE_FD)
|
||||
CHECK_FUNCTION_EXISTS("pcap_lib_version" HAVE_PCAP_LIB_VERSION)
|
||||
CHECK_FUNCTION_EXISTS("pcap_list_datalinks" HAVE_PCAP_LIST_DATALINKS)
|
||||
CHECK_FUNCTION_EXISTS("pcap_set_datalink" HAVE_PCAP_SET_DATALINK)
|
||||
# Remote pcap checks
|
||||
CHECK_FUNCTION_EXISTS("pcap_open" H_PCAP_OPEN)
|
||||
CHECK_FUNCTION_EXISTS("pcap_findalldevs_ex" H_FINDALLDEVS_EX)
|
||||
CHECK_FUNCTION_EXISTS("pcap_createsrcstr" H_CREATESRCSTR)
|
||||
if(H_PCAP_OPEN AND H_FINDALLDEVS_EX AND H_CREATESRCSTR)
|
||||
SET(HAVE_PCAP_REMOTE 1)
|
||||
SET(HAVE_REMOTE 1)
|
||||
endif()
|
||||
# reset vars
|
||||
SET(CMAKE_REQUIRED_INCLUDES "")
|
||||
SET(CMAKE_REQUIRED_LIBRARIES "")
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCAP DEFAULT_MSG PCAP_INCLUDE_DIRS PCAP_LIBRARIES)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
PCAP_LIBRARIES
|
||||
PCAP_INCLUDE_DIRS
|
||||
)
|
|
@ -0,0 +1,299 @@
|
|||
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(<name> ... )
|
||||
#
|
||||
# This function is intended to be used in FindXXX.cmake modules files.
|
||||
# It handles the REQUIRED, QUIET and version-related arguments to find_package().
|
||||
# It also sets the <UPPERCASED_NAME>_FOUND variable.
|
||||
# The package is considered found if all variables <var1>... listed contain
|
||||
# valid results, e.g. valid filepaths.
|
||||
#
|
||||
# There are two modes of this function. The first argument in both modes is
|
||||
# the name of the Find-module where it is called (in original casing).
|
||||
#
|
||||
# The first simple mode looks like this:
|
||||
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(<name> (DEFAULT_MSG|"Custom failure message") <var1>...<varN> )
|
||||
# If the variables <var1> to <varN> are all valid, then <UPPERCASED_NAME>_FOUND
|
||||
# will be set to TRUE.
|
||||
# If DEFAULT_MSG is given as second argument, then the function will generate
|
||||
# itself useful success and error messages. You can also supply a custom error message
|
||||
# for the failure case. This is not recommended.
|
||||
#
|
||||
# The second mode is more powerful and also supports version checking:
|
||||
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME [REQUIRED_VARS <var1>...<varN>]
|
||||
# [VERSION_VAR <versionvar>]
|
||||
# [HANDLE_COMPONENTS]
|
||||
# [CONFIG_MODE]
|
||||
# [FAIL_MESSAGE "Custom failure message"] )
|
||||
#
|
||||
# As above, if <var1> through <varN> are all valid, <UPPERCASED_NAME>_FOUND
|
||||
# will be set to TRUE.
|
||||
# After REQUIRED_VARS the variables which are required for this package are listed.
|
||||
# Following VERSION_VAR the name of the variable can be specified which holds
|
||||
# the version of the package which has been found. If this is done, this version
|
||||
# will be checked against the (potentially) specified required version used
|
||||
# in the find_package() call. The EXACT keyword is also handled. The default
|
||||
# messages include information about the required version and the version
|
||||
# which has been actually found, both if the version is ok or not.
|
||||
# If the package supports components, use the HANDLE_COMPONENTS option to enable
|
||||
# handling them. In this case, find_package_handle_standard_args() will report
|
||||
# which components have been found and which are missing, and the <NAME>_FOUND
|
||||
# variable will be set to FALSE if any of the required components (i.e. not the
|
||||
# ones listed after OPTIONAL_COMPONENTS) are missing.
|
||||
# Use the option CONFIG_MODE if your FindXXX.cmake module is a wrapper for
|
||||
# a find_package(... NO_MODULE) call. In this case VERSION_VAR will be set
|
||||
# to <NAME>_VERSION and the macro will automatically check whether the
|
||||
# Config module was found.
|
||||
# Via FAIL_MESSAGE a custom failure message can be specified, if this is not
|
||||
# used, the default message will be displayed.
|
||||
#
|
||||
# Example for mode 1:
|
||||
#
|
||||
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXml2 DEFAULT_MSG LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)
|
||||
#
|
||||
# LibXml2 is considered to be found, if both LIBXML2_LIBRARY and
|
||||
# LIBXML2_INCLUDE_DIR are valid. Then also LIBXML2_FOUND is set to TRUE.
|
||||
# If it is not found and REQUIRED was used, it fails with FATAL_ERROR,
|
||||
# independent whether QUIET was used or not.
|
||||
# If it is found, success will be reported, including the content of <var1>.
|
||||
# On repeated Cmake runs, the same message won't be printed again.
|
||||
#
|
||||
# Example for mode 2:
|
||||
#
|
||||
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(BISON REQUIRED_VARS BISON_EXECUTABLE
|
||||
# VERSION_VAR BISON_VERSION)
|
||||
# In this case, BISON is considered to be found if the variable(s) listed
|
||||
# after REQUIRED_VAR are all valid, i.e. BISON_EXECUTABLE in this case.
|
||||
# Also the version of BISON will be checked by using the version contained
|
||||
# in BISON_VERSION.
|
||||
# Since no FAIL_MESSAGE is given, the default messages will be printed.
|
||||
#
|
||||
# Another example for mode 2:
|
||||
#
|
||||
# find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4)
|
||||
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(Automoc4 CONFIG_MODE)
|
||||
# In this case, FindAutmoc4.cmake wraps a call to find_package(Automoc4 NO_MODULE)
|
||||
# and adds an additional search directory for automoc4.
|
||||
# The following FIND_PACKAGE_HANDLE_STANDARD_ARGS() call produces a proper
|
||||
# success/error message.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2007-2009 Kitware, Inc.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
include(FindPackageMessage)
|
||||
include(CMakeParseArguments)
|
||||
|
||||
# internal helper macro
|
||||
macro(_FPHSA_FAILURE_MESSAGE _msg)
|
||||
if (${_NAME}_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "${_msg}")
|
||||
else ()
|
||||
if (NOT ${_NAME}_FIND_QUIETLY)
|
||||
message(STATUS "${_msg}")
|
||||
endif ()
|
||||
endif ()
|
||||
endmacro()
|
||||
|
||||
|
||||
# internal helper macro to generate the failure message when used in CONFIG_MODE:
|
||||
macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
|
||||
# <name>_CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found:
|
||||
if(${_NAME}_CONFIG)
|
||||
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})")
|
||||
else()
|
||||
# If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version.
|
||||
# List them all in the error message:
|
||||
if(${_NAME}_CONSIDERED_CONFIGS)
|
||||
set(configsText "")
|
||||
list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount)
|
||||
math(EXPR configsCount "${configsCount} - 1")
|
||||
foreach(currentConfigIndex RANGE ${configsCount})
|
||||
list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename)
|
||||
list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
|
||||
set(configsText "${configsText} ${filename} (version ${version})\n")
|
||||
endforeach()
|
||||
if (${_NAME}_NOT_FOUND_MESSAGE)
|
||||
set(configsText "${configsText} Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n")
|
||||
endif()
|
||||
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
|
||||
|
||||
else()
|
||||
# Simple case: No Config-file was found at all:
|
||||
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}")
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
||||
function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
|
||||
|
||||
# set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in
|
||||
# new extended or in the "old" mode:
|
||||
set(options CONFIG_MODE HANDLE_COMPONENTS)
|
||||
set(oneValueArgs FAIL_MESSAGE VERSION_VAR)
|
||||
set(multiValueArgs REQUIRED_VARS)
|
||||
set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} )
|
||||
list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)
|
||||
|
||||
if(${INDEX} EQUAL -1)
|
||||
set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG})
|
||||
set(FPHSA_REQUIRED_VARS ${ARGN})
|
||||
set(FPHSA_VERSION_VAR)
|
||||
else()
|
||||
|
||||
CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN})
|
||||
|
||||
if(FPHSA_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"")
|
||||
endif()
|
||||
|
||||
if(NOT FPHSA_FAIL_MESSAGE)
|
||||
set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# now that we collected all arguments, process them
|
||||
|
||||
if("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG")
|
||||
set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}")
|
||||
endif()
|
||||
|
||||
# In config-mode, we rely on the variable <package>_CONFIG, which is set by find_package()
|
||||
# when it successfully found the config-file, including version checking:
|
||||
if(FPHSA_CONFIG_MODE)
|
||||
list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
|
||||
list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS)
|
||||
set(FPHSA_VERSION_VAR ${_NAME}_VERSION)
|
||||
endif()
|
||||
|
||||
if(NOT FPHSA_REQUIRED_VARS)
|
||||
message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
|
||||
endif()
|
||||
|
||||
list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
|
||||
|
||||
string(TOUPPER ${_NAME} _NAME_UPPER)
|
||||
string(TOLOWER ${_NAME} _NAME_LOWER)
|
||||
|
||||
# collect all variables which were not found, so they can be printed, so the
|
||||
# user knows better what went wrong (#6375)
|
||||
set(MISSING_VARS "")
|
||||
set(DETAILS "")
|
||||
set(${_NAME_UPPER}_FOUND TRUE)
|
||||
# check if all passed variables are valid
|
||||
foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS})
|
||||
if(NOT ${_CURRENT_VAR})
|
||||
set(${_NAME_UPPER}_FOUND FALSE)
|
||||
set(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}")
|
||||
else()
|
||||
set(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# component handling
|
||||
unset(FOUND_COMPONENTS_MSG)
|
||||
unset(MISSING_COMPONENTS_MSG)
|
||||
|
||||
if(FPHSA_HANDLE_COMPONENTS)
|
||||
foreach(comp ${${_NAME}_FIND_COMPONENTS})
|
||||
if(${_NAME}_${comp}_FOUND)
|
||||
|
||||
if(NOT DEFINED FOUND_COMPONENTS_MSG)
|
||||
set(FOUND_COMPONENTS_MSG "found components: ")
|
||||
endif()
|
||||
set(FOUND_COMPONENTS_MSG "${FOUND_COMPONENTS_MSG} ${comp}")
|
||||
|
||||
else()
|
||||
|
||||
if(NOT DEFINED MISSING_COMPONENTS_MSG)
|
||||
set(MISSING_COMPONENTS_MSG "missing components: ")
|
||||
endif()
|
||||
set(MISSING_COMPONENTS_MSG "${MISSING_COMPONENTS_MSG} ${comp}")
|
||||
|
||||
if(${_NAME}_FIND_REQUIRED_${comp})
|
||||
set(${_NAME_UPPER}_FOUND FALSE)
|
||||
set(MISSING_VARS "${MISSING_VARS} ${comp}")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
endforeach()
|
||||
set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}")
|
||||
set(DETAILS "${DETAILS}[c${COMPONENT_MSG}]")
|
||||
endif()
|
||||
|
||||
# version handling:
|
||||
set(VERSION_MSG "")
|
||||
set(VERSION_OK TRUE)
|
||||
set(VERSION ${${FPHSA_VERSION_VAR}} )
|
||||
if (${_NAME}_FIND_VERSION)
|
||||
|
||||
if(VERSION)
|
||||
|
||||
if(${_NAME}_FIND_VERSION_EXACT) # exact version required
|
||||
if (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}")
|
||||
set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
|
||||
set(VERSION_OK FALSE)
|
||||
else ()
|
||||
set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
|
||||
endif ()
|
||||
|
||||
else() # minimum version specified:
|
||||
if ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}")
|
||||
set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"")
|
||||
set(VERSION_OK FALSE)
|
||||
else ()
|
||||
set(VERSION_MSG "(found suitable version \"${VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")")
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
else()
|
||||
|
||||
# if the package was not found, but a version was given, add that to the output:
|
||||
if(${_NAME}_FIND_VERSION_EXACT)
|
||||
set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")")
|
||||
else()
|
||||
set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
else ()
|
||||
if(VERSION)
|
||||
set(VERSION_MSG "(found version \"${VERSION}\")")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if(VERSION_OK)
|
||||
set(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]")
|
||||
else()
|
||||
set(${_NAME_UPPER}_FOUND FALSE)
|
||||
endif()
|
||||
|
||||
|
||||
# print the result:
|
||||
if (${_NAME_UPPER}_FOUND)
|
||||
FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}")
|
||||
else ()
|
||||
|
||||
if(FPHSA_CONFIG_MODE)
|
||||
_FPHSA_HANDLE_FAILURE_CONFIG_MODE()
|
||||
else()
|
||||
if(NOT VERSION_OK)
|
||||
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
|
||||
else()
|
||||
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endif ()
|
||||
|
||||
set(${_NAME_UPPER}_FOUND ${${_NAME_UPPER}_FOUND} PARENT_SCOPE)
|
||||
|
||||
endfunction()
|
|
@ -0,0 +1,141 @@
|
|||
# - Find python interpreter
|
||||
# This module finds if Python interpreter is installed and determines where the
|
||||
# executables are. This code sets the following variables:
|
||||
#
|
||||
# PYTHONINTERP_FOUND - Was the Python executable found
|
||||
# PYTHON_EXECUTABLE - path to the Python interpreter
|
||||
#
|
||||
# PYTHON_VERSION_STRING - Python version found e.g. 2.5.2
|
||||
# PYTHON_VERSION_MAJOR - Python major version found e.g. 2
|
||||
# PYTHON_VERSION_MINOR - Python minor version found e.g. 5
|
||||
# PYTHON_VERSION_PATCH - Python patch version found e.g. 2
|
||||
#
|
||||
# The Python_ADDITIONAL_VERSIONS variable can be used to specify a list of
|
||||
# version numbers that should be taken into account when searching for Python.
|
||||
# You need to set this variable before calling find_package(PythonInterp).
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2005-2010 Kitware, Inc.
|
||||
# Copyright 2011 Bjoern Ricks <bjoern.ricks@gmail.com>
|
||||
# Copyright 2012 Rolf Eike Beer <eike@sf-mail.de>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
unset(_Python_NAMES)
|
||||
|
||||
set(_PYTHON1_VERSIONS 1.6 1.5)
|
||||
set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
|
||||
set(_PYTHON3_VERSIONS 3.3 3.2 3.1 3.0)
|
||||
|
||||
if(PythonInterp_FIND_VERSION)
|
||||
if(PythonInterp_FIND_VERSION MATCHES "^[0-9]+\\.[0-9]+(\\.[0-9]+.*)?$")
|
||||
string(REGEX REPLACE "^([0-9]+\\.[0-9]+).*" "\\1" _PYTHON_FIND_MAJ_MIN "${PythonInterp_FIND_VERSION}")
|
||||
string(REGEX REPLACE "^([0-9]+).*" "\\1" _PYTHON_FIND_MAJ "${_PYTHON_FIND_MAJ_MIN}")
|
||||
list(APPEND _Python_NAMES python${_PYTHON_FIND_MAJ_MIN} python${_PYTHON_FIND_MAJ})
|
||||
unset(_PYTHON_FIND_OTHER_VERSIONS)
|
||||
if(NOT PythonInterp_FIND_VERSION_EXACT)
|
||||
foreach(_PYTHON_V ${_PYTHON${_PYTHON_FIND_MAJ}_VERSIONS})
|
||||
if(NOT _PYTHON_V VERSION_LESS _PYTHON_FIND_MAJ_MIN)
|
||||
list(APPEND _PYTHON_FIND_OTHER_VERSIONS ${_PYTHON_V})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
unset(_PYTHON_FIND_MAJ_MIN)
|
||||
unset(_PYTHON_FIND_MAJ)
|
||||
else()
|
||||
list(APPEND _Python_NAMES python${PythonInterp_FIND_VERSION})
|
||||
set(_PYTHON_FIND_OTHER_VERSIONS ${_PYTHON${PythonInterp_FIND_VERSION}_VERSIONS})
|
||||
endif()
|
||||
else()
|
||||
set(_PYTHON_FIND_OTHER_VERSIONS ${_PYTHON3_VERSIONS} ${_PYTHON2_VERSIONS} ${_PYTHON1_VERSIONS})
|
||||
endif()
|
||||
|
||||
list(APPEND _Python_NAMES python)
|
||||
|
||||
# Search for the current active python version first
|
||||
find_program(PYTHON_EXECUTABLE NAMES ${_Python_NAMES})
|
||||
|
||||
# Set up the versions we know about, in the order we will search. Always add
|
||||
# the user supplied additional versions to the front.
|
||||
set(_Python_VERSIONS
|
||||
${Python_ADDITIONAL_VERSIONS}
|
||||
${_PYTHON_FIND_OTHER_VERSIONS}
|
||||
)
|
||||
|
||||
unset(_PYTHON_FIND_OTHER_VERSIONS)
|
||||
unset(_PYTHON1_VERSIONS)
|
||||
unset(_PYTHON2_VERSIONS)
|
||||
unset(_PYTHON3_VERSIONS)
|
||||
|
||||
# Search for newest python version if python executable isn't found
|
||||
if(NOT PYTHON_EXECUTABLE)
|
||||
foreach(_CURRENT_VERSION ${_Python_VERSIONS})
|
||||
set(_Python_NAMES python${_CURRENT_VERSION})
|
||||
if(WIN32)
|
||||
list(APPEND _Python_NAMES python)
|
||||
endif()
|
||||
find_program(PYTHON_EXECUTABLE
|
||||
NAMES ${_Python_NAMES}
|
||||
PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# determine python version string
|
||||
if(PYTHON_EXECUTABLE)
|
||||
execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c
|
||||
"import sys; sys.stdout.write(';'.join([str(x) for x in sys.version_info[:3]]))"
|
||||
OUTPUT_VARIABLE _VERSION
|
||||
RESULT_VARIABLE _PYTHON_VERSION_RESULT
|
||||
ERROR_QUIET)
|
||||
if(NOT _PYTHON_VERSION_RESULT)
|
||||
string(REPLACE ";" "." PYTHON_VERSION_STRING "${_VERSION}")
|
||||
list(GET _VERSION 0 PYTHON_VERSION_MAJOR)
|
||||
list(GET _VERSION 1 PYTHON_VERSION_MINOR)
|
||||
list(GET _VERSION 2 PYTHON_VERSION_PATCH)
|
||||
if(PYTHON_VERSION_PATCH EQUAL 0)
|
||||
# it's called "Python 2.7", not "2.7.0"
|
||||
string(REGEX REPLACE "\\.0$" "" PYTHON_VERSION_STRING "${PYTHON_VERSION_STRING}")
|
||||
endif()
|
||||
else()
|
||||
# sys.version predates sys.version_info, so use that
|
||||
execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c "import sys; sys.stdout.write(sys.version)"
|
||||
OUTPUT_VARIABLE _VERSION
|
||||
RESULT_VARIABLE _PYTHON_VERSION_RESULT
|
||||
ERROR_QUIET)
|
||||
if(NOT _PYTHON_VERSION_RESULT)
|
||||
string(REGEX REPLACE " .*" "" PYTHON_VERSION_STRING "${_VERSION}")
|
||||
string(REGEX REPLACE "^([0-9]+)\\.[0-9]+.*" "\\1" PYTHON_VERSION_MAJOR "${PYTHON_VERSION_STRING}")
|
||||
string(REGEX REPLACE "^[0-9]+\\.([0-9])+.*" "\\1" PYTHON_VERSION_MINOR "${PYTHON_VERSION_STRING}")
|
||||
if(PYTHON_VERSION_STRING MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+.*")
|
||||
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" PYTHON_VERSION_PATCH "${PYTHON_VERSION_STRING}")
|
||||
else()
|
||||
set(PYTHON_VERSION_PATCH "0")
|
||||
endif()
|
||||
else()
|
||||
# sys.version was first documented for Python 1.5, so assume
|
||||
# this is older.
|
||||
set(PYTHON_VERSION_STRING "1.4")
|
||||
set(PYTHON_VERSION_MAJOR "1")
|
||||
set(PYTHON_VERSION_MAJOR "4")
|
||||
set(PYTHON_VERSION_MAJOR "0")
|
||||
endif()
|
||||
endif()
|
||||
unset(_PYTHON_VERSION_RESULT)
|
||||
unset(_VERSION)
|
||||
endif()
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set PYTHONINTERP_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonInterp REQUIRED_VARS PYTHON_EXECUTABLE VERSION_VAR PYTHON_VERSION_STRING)
|
||||
|
||||
mark_as_advanced(PYTHON_EXECUTABLE)
|
|
@ -0,0 +1,130 @@
|
|||
# - Returns a version string from Git
|
||||
#
|
||||
# These functions force a re-configure on each git commit so that you can
|
||||
# trust the values of the variables in your build system.
|
||||
#
|
||||
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the refspec and sha hash of the current head revision
|
||||
#
|
||||
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the source tree, and adjusting
|
||||
# the output so that it tests false if an error occurs.
|
||||
#
|
||||
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe --exact-match on the source tree,
|
||||
# and adjusting the output so that it tests false if there was no exact
|
||||
# matching tag.
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
if(__get_git_revision_description)
|
||||
return()
|
||||
endif()
|
||||
set(__get_git_revision_description YES)
|
||||
|
||||
# We must run the following at "include" time, not at function call time,
|
||||
# to find the path to this module rather than the path to a calling list file
|
||||
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
|
||||
function(get_git_head_revision _refspecvar _hashvar)
|
||||
set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
|
||||
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
|
||||
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
|
||||
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
|
||||
# We have reached the root directory, we are not in git
|
||||
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
endwhile()
|
||||
# check if this is a submodule
|
||||
if(NOT IS_DIRECTORY ${GIT_DIR})
|
||||
file(READ ${GIT_DIR} submodule)
|
||||
string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
|
||||
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
||||
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
|
||||
endif()
|
||||
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||
if(NOT EXISTS "${GIT_DATA}")
|
||||
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${GIT_DIR}/HEAD")
|
||||
return()
|
||||
endif()
|
||||
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
|
||||
|
||||
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||
"${GIT_DATA}/grabRef.cmake"
|
||||
@ONLY)
|
||||
include("${GIT_DATA}/grabRef.cmake")
|
||||
|
||||
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
|
||||
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_describe _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# TODO sanitize
|
||||
#if((${ARGN}" MATCHES "&&") OR
|
||||
# (ARGN MATCHES "||") OR
|
||||
# (ARGN MATCHES "\\;"))
|
||||
# message("Please report the following error to the project!")
|
||||
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||
#endif()
|
||||
|
||||
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||
|
||||
execute_process(COMMAND
|
||||
"${GIT_EXECUTABLE}"
|
||||
describe
|
||||
${hash}
|
||||
${ARGN}
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE
|
||||
res
|
||||
OUTPUT_VARIABLE
|
||||
out
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT res EQUAL 0)
|
||||
set(out "${out}-${res}-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(${_var} "${out}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_get_exact_tag _var)
|
||||
git_describe(out --exact-match ${ARGN})
|
||||
set(${_var} "${out}" PARENT_SCOPE)
|
||||
endfunction()
|
|
@ -0,0 +1,39 @@
|
|||
#
|
||||
# Internal file for GetGitRevisionDescription.cmake
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
set(HEAD_HASH)
|
||||
|
||||
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||
|
||||
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||
if(HEAD_CONTENTS MATCHES "ref")
|
||||
# named branch
|
||||
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
set(HEAD_HASH "${HEAD_REF}")
|
||||
endif()
|
||||
else()
|
||||
# detached HEAD
|
||||
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
endif()
|
||||
|
||||
if(NOT HEAD_HASH)
|
||||
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||
string(SUBSTRING ${HEAD_HASH} 0 7 HEAD_HASH)
|
||||
endif()
|
|
@ -0,0 +1,39 @@
|
|||
#
|
||||
# Copyright 2013 Dominic Spill
|
||||
#
|
||||
# This file is part of Libbtbb.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Based heavily upon the hackrf cmake setup.
|
||||
|
||||
project(libbtbb C)
|
||||
set(PACKAGE libbtbb)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
CONFIGURE_FILE(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libbtbb.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libbtbb.pc
|
||||
@ONLY)
|
||||
|
||||
INSTALL(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/libbtbb.pc
|
||||
DESTINATION lib${LIB_SUFFIX}/pkgconfig
|
||||
)
|
|
@ -0,0 +1,11 @@
|
|||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
|
||||
Name: Bluetooth Baseband Library
|
||||
Description: C Utility Library
|
||||
Version: @VERSION@
|
||||
Cflags: -I${includedir}/ @BTBB_PC_CFLAGS@
|
||||
Libs: -L${libdir} -lbtbb
|
||||
Libs.private: @BTBB_PC_LIBS@
|
|
@ -0,0 +1,105 @@
|
|||
#
|
||||
# This file is part of Libbtbb.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# Based slightly upon the hackrf cmake setup.
|
||||
|
||||
# FIXME Set static release version here to avoid pulling from git
|
||||
set(RELEASE "")
|
||||
set(DIRTY_FLAG "")
|
||||
|
||||
if ( "${RELEASE}" STREQUAL "" )
|
||||
# automatic git version when working out of git
|
||||
include(GetGitRevisionDescription)
|
||||
get_git_head_revision(GIT_REFSPEC RELEASE)
|
||||
|
||||
execute_process(COMMAND git status -s --untracked-files=no OUTPUT_VARIABLE DIRTY)
|
||||
if ( NOT "${DIRTY}" STREQUAL "" )
|
||||
set(DIRTY_FLAG "*")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_definitions( -DRELEASE="${RELEASE}${DIRTY_FLAG}" )
|
||||
|
||||
# Source
|
||||
set(c_sources ${CMAKE_CURRENT_SOURCE_DIR}/bluetooth_packet.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bluetooth_piconet.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bluetooth_le_packet.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/pcap.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/pcapng.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/pcapng-bt.c
|
||||
CACHE INTERNAL "List of C sources")
|
||||
set(c_headers ${CMAKE_CURRENT_SOURCE_DIR}/btbb.h
|
||||
CACHE INTERNAL "List of C headers")
|
||||
|
||||
# For cygwin just force UNIX OFF and WIN32 ON
|
||||
if( ${CYGWIN} )
|
||||
SET(UNIX OFF)
|
||||
SET(WIN32 ON)
|
||||
endif( ${CYGWIN} )
|
||||
|
||||
# FIXME: This may be a hack
|
||||
# perhaps there should be separate libbtbb and libbtbb-static targets?
|
||||
if( ${WIN32} )
|
||||
# Static library
|
||||
add_library(btbb STATIC ${c_sources})
|
||||
set_target_properties(btbb PROPERTIES OUTPUT_NAME "btbb_static")
|
||||
else()
|
||||
# Dynamic library
|
||||
add_library(btbb SHARED ${c_sources})
|
||||
set_target_properties(btbb PROPERTIES VERSION ${MAJOR_VERSION}.${MINOR_VERSION} SOVERSION 0)
|
||||
endif()
|
||||
|
||||
set_target_properties(btbb PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
|
||||
# PCAP Support
|
||||
if( (NOT DEFINED USE_PCAP) OR USE_PCAP )
|
||||
find_package(PCAP)
|
||||
|
||||
if( USE_PCAP AND NOT ${PCAP_FOUND} )
|
||||
message( FATAL_ERROR
|
||||
"Cannot find libpcap, which is required for USE_PCAP")
|
||||
endif()
|
||||
|
||||
if( ${PCAP_FOUND} )
|
||||
include_directories(${PCAP_INCLUDE_DIRS})
|
||||
target_link_libraries(btbb ${PCAP_LIBRARIES})
|
||||
add_definitions( -DENABLE_PCAP )
|
||||
endif( ${PCAP_FOUND} )
|
||||
endif( (NOT DEFINED USE_PCAP) OR USE_PCAP )
|
||||
|
||||
if( ${UNIX} )
|
||||
install(TARGETS btbb
|
||||
LIBRARY DESTINATION lib${LIB_SUFFIX}
|
||||
COMPONENT sharedlibs
|
||||
)
|
||||
install(FILES ${c_headers}
|
||||
DESTINATION include
|
||||
COMPONENT headers
|
||||
)
|
||||
endif( ${UNIX} )
|
||||
|
||||
if( ${WIN32} )
|
||||
install(TARGETS btbb
|
||||
DESTINATION bin
|
||||
COMPONENT staticlibs
|
||||
)
|
||||
install(FILES ${c_headers}
|
||||
DESTINATION include
|
||||
COMPONENT headers
|
||||
)
|
||||
endif( ${WIN32} )
|
|
@ -0,0 +1,607 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2007 - 2012 Mike Ryan, Dominic Spill, Michael Ossmann
|
||||
* Copyright 2005, 2006 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "btbb.h"
|
||||
#include "bluetooth_le_packet.h"
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
/* string representations of advertising packet type */
|
||||
static const char *ADV_TYPE_NAMES[] = {
|
||||
"ADV_IND", "ADV_DIRECT_IND", "ADV_NONCONN_IND", "SCAN_REQ",
|
||||
"SCAN_RSP", "CONNECT_REQ", "ADV_SCAN_IND",
|
||||
};
|
||||
|
||||
/* source clock accuracy in a connect packet */
|
||||
static const char *CONNECT_SCA[] = {
|
||||
"251 ppm to 500 ppm", "151 ppm to 250 ppm", "101 ppm to 150 ppm",
|
||||
"76 ppm to 100 ppm", "51 ppm to 75 ppm", "31 ppm to 50 ppm",
|
||||
"21 ppm to 30 ppm", "0 ppm to 20 ppm",
|
||||
};
|
||||
|
||||
// count of objects in an array, shamelessly stolen from Chrome
|
||||
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
|
||||
|
||||
static uint8_t count_bits(uint32_t n)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
for (i = 0; n != 0; i++)
|
||||
n &= n - 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
static int aa_access_channel_off_by_one(const uint32_t aa) {
|
||||
int retval = 0;
|
||||
if(count_bits(aa ^ LE_ADV_AA) == 1) {
|
||||
retval = 1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* A helper function for filtering bogus packets on data channels.
|
||||
*
|
||||
* If a candidate capture packet is random noise we would expect its
|
||||
* Access Address to be a randomly distributed 32-bit number. An
|
||||
* exhaustive software analysis reveals that of 4294967296 possible
|
||||
* 32-bit Access Address values, 2900629660 (67.5%) are acceptable and
|
||||
* 1394337636 (32.5%) are invalid. This function will identify which
|
||||
* category a candidate Access Address falls into by returning the
|
||||
* number of offenses contained.
|
||||
*
|
||||
* Refer to BT 4.x, Vol 6, Par B, Section 2.1.2.
|
||||
*
|
||||
* The Access Address in data channel packets meet the
|
||||
* following requirements:
|
||||
* - It shall have no more than six consecutive zeros or ones.
|
||||
* - It shall not be the advertising channel packets’ Access Address.
|
||||
* - It shall not be a sequence that differs from the advertising channel packets’
|
||||
* Access Address by only one bit.
|
||||
* - It shall not have all four octets equal.
|
||||
* - It shall have no more than 24 transitions.
|
||||
* - It shall have a minimum of two transitions in the most significant six bits.
|
||||
*/
|
||||
static int aa_data_channel_offenses(const uint32_t aa) {
|
||||
int retval = 0, transitions = 0;
|
||||
unsigned shift, odd = (unsigned) (aa & 1);
|
||||
uint8_t aab3, aab2, aab1, aab0 = (uint8_t) (aa & 0xff);
|
||||
|
||||
const uint8_t EIGHT_BIT_TRANSITIONS_EVEN[256] = {
|
||||
0, 2, 2, 2, 2, 4, 2, 2, 2, 4, 4, 4, 2, 4, 2, 2,
|
||||
2, 4, 4, 4, 4, 6, 4, 4, 2, 4, 4, 4, 2, 4, 2, 2,
|
||||
2, 4, 4, 4, 4, 6, 4, 4, 4, 6, 6, 6, 4, 6, 4, 4,
|
||||
2, 4, 4, 4, 4, 6, 4, 4, 2, 4, 4, 4, 2, 4, 2, 2,
|
||||
2, 4, 4, 4, 4, 6, 4, 4, 4, 6, 6, 6, 4, 6, 4, 4,
|
||||
4, 6, 6, 6, 6, 8, 6, 6, 4, 6, 6, 6, 4, 6, 4, 4,
|
||||
2, 4, 4, 4, 4, 6, 4, 4, 4, 6, 6, 6, 4, 6, 4, 4,
|
||||
2, 4, 4, 4, 4, 6, 4, 4, 2, 4, 4, 4, 2, 4, 2, 2,
|
||||
1, 3, 3, 3, 3, 5, 3, 3, 3, 5, 5, 5, 3, 5, 3, 3,
|
||||
3, 5, 5, 5, 5, 7, 5, 5, 3, 5, 5, 5, 3, 5, 3, 3,
|
||||
3, 5, 5, 5, 5, 7, 5, 5, 5, 7, 7, 7, 5, 7, 5, 5,
|
||||
3, 5, 5, 5, 5, 7, 5, 5, 3, 5, 5, 5, 3, 5, 3, 3,
|
||||
1, 3, 3, 3, 3, 5, 3, 3, 3, 5, 5, 5, 3, 5, 3, 3,
|
||||
3, 5, 5, 5, 5, 7, 5, 5, 3, 5, 5, 5, 3, 5, 3, 3,
|
||||
1, 3, 3, 3, 3, 5, 3, 3, 3, 5, 5, 5, 3, 5, 3, 3,
|
||||
1, 3, 3, 3, 3, 5, 3, 3, 1, 3, 3, 3, 1, 3, 1, 1
|
||||
};
|
||||
|
||||
const uint8_t EIGHT_BIT_TRANSITIONS_ODD[256] = {
|
||||
1, 1, 3, 1, 3, 3, 3, 1, 3, 3, 5, 3, 3, 3, 3, 1,
|
||||
3, 3, 5, 3, 5, 5, 5, 3, 3, 3, 5, 3, 3, 3, 3, 1,
|
||||
3, 3, 5, 3, 5, 5, 5, 3, 5, 5, 7, 5, 5, 5, 5, 3,
|
||||
3, 3, 5, 3, 5, 5, 5, 3, 3, 3, 5, 3, 3, 3, 3, 1,
|
||||
3, 3, 5, 3, 5, 5, 5, 3, 5, 5, 7, 5, 5, 5, 5, 3,
|
||||
5, 5, 7, 5, 7, 7, 7, 5, 5, 5, 7, 5, 5, 5, 5, 3,
|
||||
3, 3, 5, 3, 5, 5, 5, 3, 5, 5, 7, 5, 5, 5, 5, 3,
|
||||
3, 3, 5, 3, 5, 5, 5, 3, 3, 3, 5, 3, 3, 3, 3, 1,
|
||||
2, 2, 4, 2, 4, 4, 4, 2, 4, 4, 6, 4, 4, 4, 4, 2,
|
||||
4, 4, 6, 4, 6, 6, 6, 4, 4, 4, 6, 4, 4, 4, 4, 2,
|
||||
4, 4, 6, 4, 6, 6, 6, 4, 6, 6, 8, 6, 6, 6, 6, 4,
|
||||
4, 4, 6, 4, 6, 6, 6, 4, 4, 4, 6, 4, 4, 4, 4, 2,
|
||||
2, 2, 4, 2, 4, 4, 4, 2, 4, 4, 6, 4, 4, 4, 4, 2,
|
||||
4, 4, 6, 4, 6, 6, 6, 4, 4, 4, 6, 4, 4, 4, 4, 2,
|
||||
2, 2, 4, 2, 4, 4, 4, 2, 4, 4, 6, 4, 4, 4, 4, 2,
|
||||
2, 2, 4, 2, 4, 4, 4, 2, 2, 2, 4, 2, 2, 2, 2, 0
|
||||
};
|
||||
|
||||
transitions += (odd ? EIGHT_BIT_TRANSITIONS_ODD[aab0] : EIGHT_BIT_TRANSITIONS_EVEN[aab0] );
|
||||
odd = (unsigned) (aab0 & 0x80);
|
||||
aab1 = (uint8_t) (aa >> 8);
|
||||
transitions += (odd ? EIGHT_BIT_TRANSITIONS_ODD[aab1] : EIGHT_BIT_TRANSITIONS_EVEN[aab1] );
|
||||
odd = (unsigned) (aab1 & 0x80);
|
||||
aab2 = (uint8_t) (aa >> 16);
|
||||
transitions += (odd ? EIGHT_BIT_TRANSITIONS_ODD[aab2] : EIGHT_BIT_TRANSITIONS_EVEN[aab2] );
|
||||
odd = (unsigned) (aab2 & 0x80);
|
||||
aab3 = (uint8_t) (aa >> 24);
|
||||
transitions += (odd ? EIGHT_BIT_TRANSITIONS_ODD[aab3] : EIGHT_BIT_TRANSITIONS_EVEN[aab3] );
|
||||
|
||||
/* consider excessive transitions as offenses */
|
||||
if (transitions > 24) {
|
||||
retval += (transitions - 24);
|
||||
}
|
||||
|
||||
const uint8_t AA_MSB6_ALLOWED[64] = {
|
||||
0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0
|
||||
};
|
||||
|
||||
/* consider excessive transitions in the 6 MSBs as an offense */
|
||||
retval += (1 - AA_MSB6_ALLOWED[aab3>>2]);
|
||||
|
||||
/* consider all bytes as being equal an offense */
|
||||
retval += (((aab0 == aab1) && (aab0 == aab2) && (aab0 == aab3)) ? 1 : 0);
|
||||
|
||||
/* access-channel address and off-by-ones are illegal */
|
||||
retval += ((aa == LE_ADV_AA) ? 1 : 0);
|
||||
retval += aa_access_channel_off_by_one(aa);
|
||||
|
||||
/* inspect nibble triples for insufficient bit transitions */
|
||||
for(shift=0; shift<=20; shift+=4) {
|
||||
uint16_t twelvebits = (uint16_t) ((aa >> shift) & 0xfff);
|
||||
switch( twelvebits ) {
|
||||
/* seven consecutive zeroes */
|
||||
case 0x080: case 0x180: case 0x280: case 0x380: case 0x480:
|
||||
case 0x580: case 0x680: case 0x780: case 0x880: case 0x980:
|
||||
case 0xa80: case 0xb80: case 0xc80: case 0xd80: case 0xe80:
|
||||
case 0xf80: case 0x101: case 0x301: case 0x501: case 0x701:
|
||||
case 0x901: case 0xb01: case 0xd01: case 0xf01: case 0x202:
|
||||
case 0x602: case 0xa02: case 0xe02: case 0x203: case 0x603:
|
||||
case 0xa03: case 0xe03: case 0x404: case 0xc04: case 0x405:
|
||||
case 0xc05: case 0x406: case 0xc06: case 0x407: case 0xc07:
|
||||
case 0x808: case 0x809: case 0x80a: case 0x80b: case 0x80c:
|
||||
case 0x80d: case 0x80e: case 0x80f: case 0x010: case 0x011:
|
||||
case 0x012: case 0x013: case 0x014: case 0x015: case 0x016:
|
||||
case 0x017: case 0x018: case 0x019: case 0x01a: case 0x01b:
|
||||
case 0x01c: case 0x01d: case 0x01e: case 0x01f:
|
||||
/* eight consecutive zeroes */
|
||||
case 0x100: case 0x300: case 0x500: case 0x700: case 0x900:
|
||||
case 0xb00: case 0xd00: case 0xf00: case 0x201: case 0x601:
|
||||
case 0xa01: case 0xe01: case 0x402: case 0xc02: case 0x403:
|
||||
case 0xc03: case 0x804: case 0x805: case 0x806: case 0x807:
|
||||
case 0x008: case 0x009: case 0x00a: case 0x00b: case 0x00c:
|
||||
case 0x00d: case 0x00e: case 0x00f:
|
||||
/* nine consecutive zeroes */
|
||||
case 0xe00: case 0xc01: case 0x802: case 0x803: case 0x004:
|
||||
case 0x005: case 0x006: case 0x007:
|
||||
/* ten consecutive zeroes */
|
||||
case 0x400: case 0xc00: case 0x801: case 0x002: case 0x003:
|
||||
/* eleven consecutive zeroes */
|
||||
case 0x800: case 0x001:
|
||||
/* twelve consecutive zeroes */
|
||||
case 0x000:
|
||||
/* seven consecutive ones */
|
||||
case 0x07f: case 0x0fe: case 0x2fe: case 0x4fe: case 0x6fe:
|
||||
case 0x8fe: case 0xafe: case 0xcfe: case 0xefe: case 0x1fc:
|
||||
case 0x5fc: case 0x9fc: case 0xdfc: case 0x1fd: case 0x5fd:
|
||||
case 0x9fd: case 0xdfd: case 0x3f8: case 0xbf8: case 0x3f9:
|
||||
case 0xbf9: case 0x3fa: case 0xbfa: case 0x3fb: case 0xbfb:
|
||||
case 0x7f4: case 0x7f5: case 0x7f6: case 0x7f7: case 0xfe0:
|
||||
/* eight consecutive ones */
|
||||
case 0x0ff: case 0x2ff: case 0x4ff: case 0x6ff: case 0x8ff:
|
||||
case 0xaff: case 0xcff: case 0xeff: case 0x1fe: case 0x5fe:
|
||||
case 0x9fe: case 0xdfe: case 0x3fc: case 0xbfc: case 0x3fd:
|
||||
case 0xbfd: case 0x7f8: case 0x7f9: case 0x7fa: case 0x7fb:
|
||||
case 0xff0: case 0xff1: case 0xff2: case 0xff3: case 0xff4:
|
||||
case 0xff5: case 0xff6: case 0xff7:
|
||||
/* nine consecutive ones */
|
||||
case 0x1ff: case 0x5ff: case 0x9ff: case 0xdff: case 0x3fe:
|
||||
case 0xbfe: case 0x7fc: case 0x7fd: case 0xff8: case 0xff9:
|
||||
case 0xffa: case 0xffb:
|
||||
/* ten consecutive ones */
|
||||
case 0x3ff: case 0xbff: case 0x7fe: case 0xffc: case 0xffd:
|
||||
/* eleven consecutive ones */
|
||||
case 0x7ff: case 0xffe:
|
||||
/* all ones */
|
||||
case 0xfff:
|
||||
retval++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
lell_packet *
|
||||
lell_packet_new(void)
|
||||
{
|
||||
lell_packet *pkt = (lell_packet *)calloc(1, sizeof(lell_packet));
|
||||
pkt->refcount = 1;
|
||||
return pkt;
|
||||
}
|
||||
|
||||
void
|
||||
lell_packet_ref(lell_packet *pkt)
|
||||
{
|
||||
pkt->refcount++;
|
||||
}
|
||||
|
||||
void
|
||||
lell_packet_unref(lell_packet *pkt)
|
||||
{
|
||||
pkt->refcount--;
|
||||
if (pkt->refcount == 0)
|
||||
free(pkt);
|
||||
}
|
||||
|
||||
static uint8_t le_channel_index(uint16_t phys_channel) {
|
||||
uint8_t ret;
|
||||
if (phys_channel == 2402) {
|
||||
ret = 37;
|
||||
} else if (phys_channel < 2426) { // 0 - 10
|
||||
ret = (phys_channel - 2404) / 2;
|
||||
} else if (phys_channel == 2426) {
|
||||
ret = 38;
|
||||
} else if (phys_channel < 2480) { // 11 - 36
|
||||
ret = 11 + (phys_channel - 2428) / 2;
|
||||
} else {
|
||||
ret = 39;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void lell_allocate_and_decode(const uint8_t *stream, uint16_t phys_channel, uint32_t clk100ns, lell_packet **pkt)
|
||||
{
|
||||
*pkt = lell_packet_new( );
|
||||
memcpy((*pkt)->symbols, stream, MAX_LE_SYMBOLS);
|
||||
|
||||
(*pkt)->channel_idx = le_channel_index(phys_channel);
|
||||
(*pkt)->channel_k = (phys_channel-2402)/2;
|
||||
(*pkt)->clk100ns = clk100ns;
|
||||
|
||||
(*pkt)->access_address = 0;
|
||||
(*pkt)->access_address |= (*pkt)->symbols[0];
|
||||
(*pkt)->access_address |= (*pkt)->symbols[1] << 8;
|
||||
(*pkt)->access_address |= (*pkt)->symbols[2] << 16;
|
||||
(*pkt)->access_address |= (*pkt)->symbols[3] << 24;
|
||||
|
||||
if (lell_packet_is_data(*pkt)) {
|
||||
// data PDU
|
||||
(*pkt)->length = (*pkt)->symbols[5] & 0x1f;
|
||||
(*pkt)->access_address_offenses = aa_data_channel_offenses((*pkt)->access_address);
|
||||
(*pkt)->flags.as_bits.access_address_ok = (*pkt)->access_address_offenses ? 0 : 1;
|
||||
} else {
|
||||
// advertising PDU
|
||||
(*pkt)->length = (*pkt)->symbols[5] & 0x3f;
|
||||
(*pkt)->adv_type = (*pkt)->symbols[4] & 0xf;
|
||||
(*pkt)->adv_tx_add = (*pkt)->symbols[4] & 0x40 ? 1 : 0;
|
||||
(*pkt)->adv_rx_add = (*pkt)->symbols[4] & 0x80 ? 1 : 0;
|
||||
(*pkt)->flags.as_bits.access_address_ok = ((*pkt)->access_address == 0x8e89bed6);
|
||||
(*pkt)->access_address_offenses = (*pkt)->flags.as_bits.access_address_ok ? 0 :
|
||||
(aa_access_channel_off_by_one((*pkt)->access_address) ? 1 : 32);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned lell_packet_is_data(const lell_packet *pkt)
|
||||
{
|
||||
return (unsigned) (pkt->channel_idx < 37);
|
||||
}
|
||||
|
||||
uint32_t lell_get_access_address(const lell_packet *pkt)
|
||||
{
|
||||
return pkt->access_address;
|
||||
}
|
||||
|
||||
unsigned lell_get_access_address_offenses(const lell_packet *pkt)
|
||||
{
|
||||
return pkt->access_address_offenses;
|
||||
}
|
||||
|
||||
unsigned lell_get_channel_index(const lell_packet *pkt)
|
||||
{
|
||||
return pkt->channel_idx;
|
||||
}
|
||||
|
||||
unsigned lell_get_channel_k(const lell_packet *pkt)
|
||||
{
|
||||
return pkt->channel_k;
|
||||
}
|
||||
|
||||
const char * lell_get_adv_type_str(const lell_packet *pkt)
|
||||
{
|
||||
if (lell_packet_is_data(pkt))
|
||||
return NULL;
|
||||
if (pkt->adv_type < COUNT_OF(ADV_TYPE_NAMES))
|
||||
return ADV_TYPE_NAMES[pkt->adv_type];
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static void _dump_addr(const char *name, const uint8_t *buf, int offset, int random) {
|
||||
int i;
|
||||
printf(" %s%02x", name, buf[offset+5]);
|
||||
for (i = 4; i >= 0; --i)
|
||||
printf(":%02x", buf[offset+i]);
|
||||
printf(" (%s)\n", random ? "random" : "public");
|
||||
}
|
||||
|
||||
static void _dump_8(const char *name, const uint8_t *buf, int offset) {
|
||||
printf(" %s%02x (%d)\n", name, buf[offset], buf[offset]);
|
||||
}
|
||||
|
||||
static void _dump_16(const char *name, const uint8_t *buf, int offset) {
|
||||
uint16_t val = buf[offset+1] << 8 | buf[offset];
|
||||
printf(" %s%04x (%d)\n", name, val, val);
|
||||
}
|
||||
|
||||
static void _dump_24(char *name, const uint8_t *buf, int offset) {
|
||||
uint32_t val = buf[offset+2] << 16 | buf[offset+1] << 8 | buf[offset];
|
||||
printf(" %s%06x\n", name, val);
|
||||
}
|
||||
|
||||
static void _dump_32(const char *name, const uint8_t *buf, int offset) {
|
||||
uint32_t val = buf[offset+3] << 24 |
|
||||
buf[offset+2] << 16 |
|
||||
buf[offset+1] << 8 |
|
||||
buf[offset+0];
|
||||
printf(" %s%08x\n", name, val);
|
||||
}
|
||||
|
||||
static void _dump_uuid(const uint8_t *uuid) {
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i)
|
||||
printf("%02x", uuid[i]);
|
||||
printf("-");
|
||||
for (i = 4; i < 6; ++i)
|
||||
printf("%02x", uuid[i]);
|
||||
printf("-");
|
||||
for (i = 6; i < 8; ++i)
|
||||
printf("%02x", uuid[i]);
|
||||
printf("-");
|
||||
for (i = 8; i < 10; ++i)
|
||||
printf("%02x", uuid[i]);
|
||||
printf("-");
|
||||
for (i = 10; i < 16; ++i)
|
||||
printf("%02x", uuid[i]);
|
||||
}
|
||||
|
||||
// Refer to pg 1735 of Bluetooth Core Spec 4.0
|
||||
static void _dump_scan_rsp_data(const uint8_t *buf, int len) {
|
||||
int pos = 0;
|
||||
int sublen, i;
|
||||
uint8_t type;
|
||||
uint16_t val;
|
||||
char *cval;
|
||||
|
||||
while (pos < len) {
|
||||
sublen = buf[pos];
|
||||
++pos;
|
||||
if (pos + sublen > len) {
|
||||
printf("Error: attempt to read past end of buffer (%d + %d > %d)\n", pos, sublen, len);
|
||||
return;
|
||||
}
|
||||
if (sublen == 0) {
|
||||
printf("Early return due to 0 length\n");
|
||||
return;
|
||||
}
|
||||
type = buf[pos];
|
||||
printf(" Type %02x", type);
|
||||
switch (type) {
|
||||
case 0x01:
|
||||
printf(" (Flags)\n");
|
||||
printf(" ");
|
||||
for (i = 0; i < 8; ++i)
|
||||
printf("%d", buf[pos+1] & (1 << (7-i)) ? 1 : 0);
|
||||
printf("\n");
|
||||
break;
|
||||
case 0x06:
|
||||
printf(" (128-bit Service UUIDs, more available)\n");
|
||||
goto print128;
|
||||
case 0x07:
|
||||
printf(" (128-bit Service UUIDs)\n");
|
||||
print128:
|
||||
if ((sublen - 1) % 16 == 0) {
|
||||
uint8_t uuid[16];
|
||||
for (i = 0; i < sublen - 1; ++i) {
|
||||
uuid[15 - (i % 16)] = buf[pos+1+i];
|
||||
if ((i & 15) == 15) {
|
||||
printf(" ");
|
||||
_dump_uuid(uuid);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("Wrong length (%d, must be divisible by 16)\n", sublen-1);
|
||||
}
|
||||
break;
|
||||
case 0x09:
|
||||
printf(" (Complete Local Name)\n");
|
||||
printf(" ");
|
||||
for (i = 1; i < sublen; ++i)
|
||||
printf("%c", isprint(buf[pos+i]) ? buf[pos+i] : '.');
|
||||
printf("\n");
|
||||
break;
|
||||
case 0x0a:
|
||||
printf(" (Tx Power Level)\n");
|
||||
printf(" ");
|
||||
if (sublen-1 == 1) {
|
||||
cval = (char *)&buf[pos+1];
|
||||
printf("%d dBm\n", *cval);
|
||||
} else {
|
||||
printf("Wrong length (%d, should be 1)\n", sublen-1);
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
printf(" (Slave Connection Interval Range)\n");
|
||||
printf(" ");
|
||||
if (sublen-1 == 4) {
|
||||
val = (buf[pos+2] << 8) | buf[pos+1];
|
||||
printf("(%0.2f, ", val * 1.25);
|
||||
val = (buf[pos+4] << 8) | buf[pos+3];
|
||||
printf("%0.2f) ms\n", val * 1.25);
|
||||
}
|
||||
else {
|
||||
printf("Wrong length (%d, should be 4)\n", sublen-1);
|
||||
}
|
||||
break;
|
||||
case 0x16:
|
||||
printf(" (Service Data)\n");
|
||||
printf(" ");
|
||||
if (sublen-1 >= 2) {
|
||||
val = (buf[pos+2] << 8) | buf[pos+1];
|
||||
printf("UUID: %02x", val);
|
||||
if (sublen-1 > 2) {
|
||||
printf(", Additional:");
|
||||
for (i = 3; i < sublen; ++i)
|
||||
printf(" %02x", buf[pos+i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
else {
|
||||
printf("Wrong length (%d, should be >= 2)\n", sublen-1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("\n");
|
||||
printf(" ");
|
||||
for (i = 1; i < sublen; ++i)
|
||||
printf(" %02x", buf[pos+i]);
|
||||
printf("\n");
|
||||
}
|
||||
pos += sublen;
|
||||
}
|
||||
}
|
||||
|
||||
void lell_print(const lell_packet *pkt)
|
||||
{
|
||||
int i, opcode;
|
||||
if (lell_packet_is_data(pkt)) {
|
||||
int llid = pkt->symbols[4] & 0x3;
|
||||
static const char *llid_str[] = {
|
||||
"Reserved",
|
||||
"LL Data PDU / empty or L2CAP continuation",
|
||||
"LL Data PDU / L2CAP start",
|
||||
"LL Control PDU",
|
||||
};
|
||||
|
||||
printf("Data / AA %08x (%s) / %2d bytes\n", pkt->access_address,
|
||||
pkt->flags.as_bits.access_address_ok ? "valid" : "invalid",
|
||||
pkt->length);
|
||||
printf(" Channel Index: %d\n", pkt->channel_idx);
|
||||
printf(" LLID: %d / %s\n", llid, llid_str[llid]);
|
||||
printf(" NESN: %d SN: %d MD: %d\n", (pkt->symbols[4] >> 2) & 1,
|
||||
(pkt->symbols[4] >> 3) & 1,
|
||||
(pkt->symbols[4] >> 4) & 1);
|
||||
switch (llid) {
|
||||
case 3: // LL Control PDU
|
||||
opcode = pkt->symbols[6];
|
||||
static const char *opcode_str[] = {
|
||||
"LL_CONNECTION_UPDATE_REQ",
|
||||
"LL_CHANNEL_MAP_REQ",
|
||||
"LL_TERMINATE_IND",
|
||||
"LL_ENC_REQ",
|
||||
"LL_ENC_RSP",
|
||||
"LL_START_ENC_REQ",
|
||||
"LL_START_ENC_RSP",
|
||||
"LL_UNKNOWN_RSP",
|
||||
"LL_FEATURE_REQ",
|
||||
"LL_FEATURE_RSP",
|
||||
"LL_PAUSE_ENC_REQ",
|
||||
"LL_PAUSE_ENC_RSP",
|
||||
"LL_VERSION_IND",
|
||||
"LL_REJECT_IND",
|
||||
"LL_SLAVE_FEATURE_REQ",
|
||||
"LL_CONNECTION_PARAM_REQ",
|
||||
"LL_CONNECTION_PARAM_RSP",
|
||||
"LL_REJECT_IND_EXT",
|
||||
"LL_PING_REQ",
|
||||
"LL_PING_RSP",
|
||||
"Reserved for Future Use",
|
||||
};
|
||||
printf(" Opcode: %d / %s\n", opcode, opcode_str[(opcode<0x14)?opcode:0x14]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
printf("Advertising / AA %08x (%s)/ %2d bytes\n", pkt->access_address,
|
||||
pkt->flags.as_bits.access_address_ok ? "valid" : "invalid",
|
||||
pkt->length);
|
||||
printf(" Channel Index: %d\n", pkt->channel_idx);
|
||||
printf(" Type: %s\n", lell_get_adv_type_str(pkt));
|
||||
|
||||
switch(pkt->adv_type) {
|
||||
case ADV_IND:
|
||||
_dump_addr("AdvA: ", pkt->symbols, 6, pkt->adv_tx_add);
|
||||
if (pkt->length-6 > 0) {
|
||||
printf(" AdvData:");
|
||||
for (i = 0; i < pkt->length - 6; ++i)
|
||||
printf(" %02x", pkt->symbols[12+i]);
|
||||
printf("\n");
|
||||
_dump_scan_rsp_data(&pkt->symbols[12], pkt->length-6);
|
||||
}
|
||||
break;
|
||||
case SCAN_REQ:
|
||||
_dump_addr("ScanA: ", pkt->symbols, 6, pkt->adv_tx_add);
|
||||
_dump_addr("AdvA: ", pkt->symbols, 12, pkt->adv_rx_add);
|
||||
break;
|
||||
case SCAN_RSP:
|
||||
_dump_addr("AdvA: ", pkt->symbols, 6, pkt->adv_tx_add);
|
||||
printf(" ScanRspData:");
|
||||
for (i = 0; i < pkt->length - 6; ++i)
|
||||
printf(" %02x", pkt->symbols[12+i]);
|
||||
printf("\n");
|
||||
_dump_scan_rsp_data(&pkt->symbols[12], pkt->length-6);
|
||||
break;
|
||||
case CONNECT_REQ:
|
||||
_dump_addr("InitA: ", pkt->symbols, 6, pkt->adv_tx_add);
|
||||
_dump_addr("AdvA: ", pkt->symbols, 12, pkt->adv_rx_add);
|
||||
_dump_32("AA: ", pkt->symbols, 18);
|
||||
_dump_24("CRCInit: ", pkt->symbols, 22);
|
||||
_dump_8("WinSize: ", pkt->symbols, 25);
|
||||
_dump_16("WinOffset: ", pkt->symbols, 26);
|
||||
_dump_16("Interval: ", pkt->symbols, 28);
|
||||
_dump_16("Latency: ", pkt->symbols, 30);
|
||||
_dump_16("Timeout: ", pkt->symbols, 32);
|
||||
|
||||
printf(" ChM:");
|
||||
for (i = 0; i < 5; ++i)
|
||||
printf(" %02x", pkt->symbols[34+i]);
|
||||
printf("\n");
|
||||
|
||||
printf(" Hop: %d\n", pkt->symbols[39] & 0x1f);
|
||||
printf(" SCA: %d, %s\n",
|
||||
pkt->symbols[39] >> 5,
|
||||
CONNECT_SCA[pkt->symbols[39] >> 5]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf(" Data: ");
|
||||
for (i = 6; i < 6 + pkt->length; ++i)
|
||||
printf(" %02x", pkt->symbols[i]);
|
||||
printf("\n");
|
||||
|
||||
printf(" CRC: ");
|
||||
for (i = 0; i < 3; ++i)
|
||||
printf(" %02x", pkt->symbols[6 + pkt->length + i]);
|
||||
printf("\n");
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2007 - 2012 Mike Ryan, Dominic Spill, Michael Ossmann
|
||||
* Copyright 2005, 2006 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#ifndef INCLUDED_BLUETOOTH_LE_PACKET_H
|
||||
#define INCLUDED_BLUETOOTH_LE_PACKET_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_LE_SYMBOLS 64
|
||||
|
||||
#define LE_ADV_AA 0x8E89BED6
|
||||
|
||||
#define ADV_IND 0
|
||||
#define ADV_DIRECT_IND 1
|
||||
#define ADV_NONCONN_IND 2
|
||||
#define SCAN_REQ 3
|
||||
#define SCAN_RSP 4
|
||||
#define CONNECT_REQ 5
|
||||
#define ADV_SCAN_IND 6
|
||||
|
||||
struct lell_packet {
|
||||
// raw unwhitened bytes of packet, including access address
|
||||
uint8_t symbols[MAX_LE_SYMBOLS];
|
||||
|
||||
uint32_t access_address;
|
||||
|
||||
// channel index
|
||||
uint8_t channel_idx;
|
||||
uint8_t channel_k;
|
||||
|
||||
// number of symbols
|
||||
int length;
|
||||
|
||||
uint32_t clk100ns;
|
||||
|
||||
// advertising packet header info
|
||||
uint8_t adv_type;
|
||||
int adv_tx_add;
|
||||
int adv_rx_add;
|
||||
|
||||
unsigned access_address_offenses;
|
||||
uint32_t refcount;
|
||||
|
||||
/* flags */
|
||||
union {
|
||||
struct {
|
||||
uint32_t access_address_ok : 1;
|
||||
} as_bits;
|
||||
uint32_t as_word;
|
||||
} flags;
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_BLUETOOTH_LE_PACKET_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,147 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2007 - 2013 Dominic Spill, Michael Ossmann, Will Code
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#ifndef INCLUDED_BLUETOOTH_PACKET_H
|
||||
#define INCLUDED_BLUETOOTH_PACKET_H
|
||||
#include "btbb.h"
|
||||
|
||||
/* maximum number of symbols */
|
||||
#define MAX_SYMBOLS 3125
|
||||
|
||||
/* maximum number of payload bits */
|
||||
#define MAX_PAYLOAD_LENGTH 2744
|
||||
|
||||
/* minimum header bit errors to indicate that this is an ID packet */
|
||||
#define ID_THRESHOLD 5
|
||||
|
||||
#define PACKET_TYPE_NULL 0
|
||||
#define PACKET_TYPE_POLL 1
|
||||
#define PACKET_TYPE_FHS 2
|
||||
#define PACKET_TYPE_DM1 3
|
||||
#define PACKET_TYPE_DH1 4
|
||||
#define PACKET_TYPE_HV1 5
|
||||
#define PACKET_TYPE_HV2 6
|
||||
#define PACKET_TYPE_HV3 7
|
||||
#define PACKET_TYPE_DV 8
|
||||
#define PACKET_TYPE_AUX1 9
|
||||
#define PACKET_TYPE_DM3 10
|
||||
#define PACKET_TYPE_DH3 11
|
||||
#define PACKET_TYPE_EV4 12
|
||||
#define PACKET_TYPE_EV5 13
|
||||
#define PACKET_TYPE_DM5 14
|
||||
#define PACKET_TYPE_DH5 15
|
||||
|
||||
struct btbb_packet {
|
||||
|
||||
uint32_t refcount;
|
||||
|
||||
uint32_t flags;
|
||||
|
||||
uint8_t channel; /* Bluetooth channel (0-79) */
|
||||
uint8_t UAP; /* upper address part */
|
||||
uint16_t NAP; /* non-significant address part */
|
||||
uint32_t LAP; /* lower address part found in access code */
|
||||
|
||||
uint8_t modulation;
|
||||
uint8_t transport;
|
||||
uint8_t packet_type;
|
||||
uint8_t packet_lt_addr; /* LLID field of payload header (2 bits) */
|
||||
uint8_t packet_flags; /* Flags - FLOW/ARQN/SQEN */
|
||||
uint8_t packet_hec; /* Flags - FLOW/ARQN/SQEN */
|
||||
|
||||
/* packet header, one bit per char */
|
||||
char packet_header[18];
|
||||
|
||||
/* number of payload header bytes: 0, 1, 2, or -1 for
|
||||
* unknown. payload is one bit per char. */
|
||||
int payload_header_length;
|
||||
char payload_header[16];
|
||||
|
||||
/* LLID field of payload header (2 bits) */
|
||||
uint8_t payload_llid;
|
||||
|
||||
/* flow field of payload header (1 bit) */
|
||||
uint8_t payload_flow;
|
||||
|
||||
/* payload length: the total length of the asynchronous data
|
||||
* in bytes. This does not include the length of synchronous
|
||||
* data, such as the voice field of a DV packet. If there is a
|
||||
* payload header, this payload length is payload body length
|
||||
* (the length indicated in the payload header's length field)
|
||||
* plus payload_header_length plus 2 bytes CRC (if present).
|
||||
*/
|
||||
int payload_length;
|
||||
|
||||
/* The actual payload data in host format
|
||||
* Ready for passing to wireshark
|
||||
* 2744 is the maximum length, but most packets are shorter.
|
||||
* Dynamic allocation would probably be better in the long run but is
|
||||
* problematic in the short run.
|
||||
*/
|
||||
char payload[MAX_PAYLOAD_LENGTH];
|
||||
|
||||
uint16_t crc;
|
||||
uint32_t clock; /* CLK1-27 of master */
|
||||
uint32_t clkn; /* native (local) clock, CLK0-27 */
|
||||
uint8_t ac_errors; /* Number of bit errors in the AC */
|
||||
|
||||
/* the raw symbol stream (less the preamble), one bit per char */
|
||||
//FIXME maybe this should be a vector so we can grow it only
|
||||
//to the size needed and later shrink it if we find we have
|
||||
//more symbols than necessary
|
||||
uint16_t length; /* number of symbols */
|
||||
char symbols[MAX_SYMBOLS];
|
||||
|
||||
};
|
||||
|
||||
/* type-specific CRC checks and decoding */
|
||||
int fhs(int clock, btbb_packet* p);
|
||||
int DM(int clock, btbb_packet* p);
|
||||
int DH(int clock, btbb_packet* p);
|
||||
int EV3(int clock, btbb_packet* p);
|
||||
int EV4(int clock, btbb_packet* p);
|
||||
int EV5(int clock, btbb_packet* p);
|
||||
int HV(int clock, btbb_packet* p);
|
||||
|
||||
/* check if the packet's CRC is correct for a given clock (CLK1-6) */
|
||||
int crc_check(int clock, btbb_packet* p);
|
||||
|
||||
/* format payload for tun interface */
|
||||
char *tun_format(btbb_packet* p);
|
||||
|
||||
/* try a clock value (CLK1-6) to unwhiten packet header,
|
||||
* sets resultant d_packet_type and d_UAP, returns UAP.
|
||||
*/
|
||||
uint8_t try_clock(int clock, btbb_packet* p);
|
||||
|
||||
/* extract LAP from FHS payload */
|
||||
uint32_t lap_from_fhs(btbb_packet* p);
|
||||
|
||||
/* extract UAP from FHS payload */
|
||||
uint8_t uap_from_fhs(btbb_packet* p);
|
||||
|
||||
/* extract NAP from FHS payload */
|
||||
uint16_t nap_from_fhs(btbb_packet* p);
|
||||
|
||||
/* extract clock from FHS payload */
|
||||
uint32_t clock_from_fhs(btbb_packet* p);
|
||||
|
||||
#endif /* INCLUDED_BLUETOOTH_PACKET_H */
|
|
@ -0,0 +1,953 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2007 - 2013 Dominic Spill, Michael Ossmann, Will Code
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "bluetooth_packet.h"
|
||||
#include "bluetooth_piconet.h"
|
||||
#include "uthash.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int perm_table_initialized = 0;
|
||||
char perm_table[0x20][0x20][0x200];
|
||||
|
||||
/* count the number of 1 bits in a uint64_t */
|
||||
int count_bits(uint8_t n)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; n != 0; i++)
|
||||
n &= n - 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
btbb_piconet *
|
||||
btbb_piconet_new(void)
|
||||
{
|
||||
btbb_piconet *pn = (btbb_piconet *)calloc(1, sizeof(btbb_piconet));
|
||||
pn->refcount = 1;
|
||||
return pn;
|
||||
}
|
||||
|
||||
void
|
||||
btbb_piconet_ref(btbb_piconet *pn)
|
||||
{
|
||||
pn->refcount++;
|
||||
}
|
||||
|
||||
void
|
||||
btbb_piconet_unref(btbb_piconet *pn)
|
||||
{
|
||||
pn->refcount--;
|
||||
if (pn->refcount == 0)
|
||||
free(pn);
|
||||
}
|
||||
|
||||
/* A bit of a hack? to set survey mode */
|
||||
static int survey_mode = 0;
|
||||
int btbb_init_survey() {
|
||||
survey_mode = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void btbb_init_piconet(btbb_piconet *pn, uint32_t lap)
|
||||
{
|
||||
pn->LAP = lap;
|
||||
btbb_piconet_set_flag(pn, BTBB_LAP_VALID, 1);
|
||||
}
|
||||
|
||||
void btbb_piconet_set_flag(btbb_piconet *pn, int flag, int val)
|
||||
{
|
||||
uint32_t mask = 1L << flag;
|
||||
pn->flags &= ~mask;
|
||||
if (val)
|
||||
pn->flags |= mask;
|
||||
}
|
||||
|
||||
int btbb_piconet_get_flag(const btbb_piconet *pn, const int flag)
|
||||
{
|
||||
uint32_t mask = 1L << flag;
|
||||
return ((pn->flags & mask) != 0);
|
||||
}
|
||||
|
||||
void btbb_piconet_set_uap(btbb_piconet *pn, uint8_t uap)
|
||||
{
|
||||
pn->UAP = uap;
|
||||
btbb_piconet_set_flag(pn, BTBB_UAP_VALID, 1);
|
||||
}
|
||||
|
||||
uint8_t btbb_piconet_get_uap(const btbb_piconet *pn)
|
||||
{
|
||||
return pn->UAP;
|
||||
}
|
||||
|
||||
uint32_t btbb_piconet_get_lap(const btbb_piconet *pn)
|
||||
{
|
||||
return pn->LAP;
|
||||
}
|
||||
|
||||
uint16_t btbb_piconet_get_nap(const btbb_piconet *pn)
|
||||
{
|
||||
return pn->NAP;
|
||||
}
|
||||
|
||||
uint64_t btbb_piconet_get_bdaddr(const btbb_piconet *pn)
|
||||
{
|
||||
return ((uint64_t) pn->NAP) << 32 | pn->UAP << 24 | pn->LAP;
|
||||
}
|
||||
|
||||
int btbb_piconet_get_clk_offset(const btbb_piconet *pn)
|
||||
{
|
||||
return pn->clk_offset;
|
||||
}
|
||||
|
||||
void btbb_piconet_set_clk_offset(btbb_piconet *pn, int clk_offset)
|
||||
{
|
||||
pn->clk_offset = clk_offset;
|
||||
}
|
||||
|
||||
void btbb_piconet_set_afh_map(btbb_piconet *pn, uint8_t *afh_map) {
|
||||
int i;
|
||||
pn->used_channels = 0;
|
||||
// DGS: Unroll this?
|
||||
for(i=0; i<10; i++) {
|
||||
pn->afh_map[i] = afh_map[i];
|
||||
pn->used_channels += count_bits(pn->afh_map[i]);
|
||||
}
|
||||
if(btbb_piconet_get_flag(pn, BTBB_UAP_VALID))
|
||||
get_hop_pattern(pn);
|
||||
}
|
||||
|
||||
uint8_t *btbb_piconet_get_afh_map(btbb_piconet *pn) {
|
||||
return pn->afh_map;
|
||||
}
|
||||
|
||||
void btbb_piconet_set_channel_seen(btbb_piconet *pn, uint8_t channel)
|
||||
{
|
||||
if(!(pn->afh_map[channel/8] & 0x1 << (channel % 8))) {
|
||||
pn->afh_map[channel/8] |= 0x1 << (channel % 8);
|
||||
pn->used_channels++;
|
||||
if(btbb_piconet_get_flag(pn, BTBB_UAP_VALID) && !survey_mode)
|
||||
get_hop_pattern(pn);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t btbb_piconet_get_channel_seen(btbb_piconet *pn, uint8_t channel)
|
||||
{
|
||||
if(channel < BT_NUM_CHANNELS)
|
||||
return ( pn->afh_map[channel/8] & (1 << (channel % 8)) ) != 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* do all the precalculation that can be done before knowing the address */
|
||||
void precalc(btbb_piconet *pn)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int chan;
|
||||
|
||||
/* populate frequency register bank*/
|
||||
for (i = 0; i < BT_NUM_CHANNELS; i++) {
|
||||
|
||||
/* AFH is used, hopping sequence contains only used channels */
|
||||
if(btbb_piconet_get_flag(pn, BTBB_IS_AFH)) {
|
||||
chan = (i * 2) % BT_NUM_CHANNELS;
|
||||
if(btbb_piconet_get_channel_seen(pn, chan))
|
||||
pn->bank[j++] = chan;
|
||||
}
|
||||
|
||||
/* all channels are used */
|
||||
else {
|
||||
pn->bank[i] = ((i * 2) % BT_NUM_CHANNELS);
|
||||
}
|
||||
}
|
||||
/* actual frequency is 2402 + pn->bank[i] MHz */
|
||||
|
||||
}
|
||||
|
||||
/* do precalculation that requires the address */
|
||||
void address_precalc(int address, btbb_piconet *pn)
|
||||
{
|
||||
/* precalculate some of single_hop()/gen_hop()'s variables */
|
||||
pn->a1 = (address >> 23) & 0x1f;
|
||||
pn->b = (address >> 19) & 0x0f;
|
||||
pn->c1 = ((address >> 4) & 0x10) +
|
||||
((address >> 3) & 0x08) +
|
||||
((address >> 2) & 0x04) +
|
||||
((address >> 1) & 0x02) +
|
||||
(address & 0x01);
|
||||
pn->d1 = (address >> 10) & 0x1ff;
|
||||
pn->e = ((address >> 7) & 0x40) +
|
||||
((address >> 6) & 0x20) +
|
||||
((address >> 5) & 0x10) +
|
||||
((address >> 4) & 0x08) +
|
||||
((address >> 3) & 0x04) +
|
||||
((address >> 2) & 0x02) +
|
||||
((address >> 1) & 0x01);
|
||||
}
|
||||
|
||||
#ifdef WC4
|
||||
/* These are optimization experiments, which don't help much for
|
||||
* x86. Hold on to them to see whether they're useful on ARM. */
|
||||
|
||||
#ifdef NEVER
|
||||
#define BUTTERFLY(z,p,c,a,b) \
|
||||
if ( ((p&(1<<c))!=0) & (((z&(1<<a))!=0) ^ ((z&(1<<b))!=0)) ) \
|
||||
z ^= ((1<<a)|(1<<b))
|
||||
#endif
|
||||
|
||||
#define BUTTERFLY(z,p,c,a,b) \
|
||||
if ( (((z>>a)^(z>>b)) & (p>>c)) & 0x1 ) \
|
||||
z ^= ((1<<a)|(1<<b))
|
||||
|
||||
int perm5(int z, int p_high, int p_low)
|
||||
{
|
||||
int p = (p_high << 5) | p_low;
|
||||
BUTTERFLY(z,p,13,1,2);
|
||||
BUTTERFLY(z,p,12,0,3);
|
||||
BUTTERFLY(z,p,11,1,3);
|
||||
BUTTERFLY(z,p,10,2,4);
|
||||
BUTTERFLY(z,p, 9,0,3);
|
||||
BUTTERFLY(z,p, 8,1,4);
|
||||
BUTTERFLY(z,p, 7,3,4);
|
||||
BUTTERFLY(z,p, 6,0,2);
|
||||
BUTTERFLY(z,p, 5,1,3);
|
||||
BUTTERFLY(z,p, 4,0,4);
|
||||
BUTTERFLY(z,p, 3,3,4);
|
||||
BUTTERFLY(z,p, 2,1,2);
|
||||
BUTTERFLY(z,p, 1,2,3);
|
||||
BUTTERFLY(z,p, 0,0,1);
|
||||
|
||||
return z;
|
||||
}
|
||||
#endif // WC4
|
||||
|
||||
/* 5 bit permutation */
|
||||
/* assumes z is constrained to 5 bits, p_high to 5 bits, p_low to 9 bits */
|
||||
int perm5(int z, int p_high, int p_low)
|
||||
{
|
||||
int i, tmp, output, z_bit[5], p[14];
|
||||
int index1[] = {0, 2, 1, 3, 0, 1, 0, 3, 1, 0, 2, 1, 0, 1};
|
||||
int index2[] = {1, 3, 2, 4, 4, 3, 2, 4, 4, 3, 4, 3, 3, 2};
|
||||
|
||||
/* bits of p_low and p_high are control signals */
|
||||
for (i = 0; i < 9; i++)
|
||||
p[i] = (p_low >> i) & 0x01;
|
||||
for (i = 0; i < 5; i++)
|
||||
p[i+9] = (p_high >> i) & 0x01;
|
||||
|
||||
/* bit swapping will be easier with an array of bits */
|
||||
for (i = 0; i < 5; i++)
|
||||
z_bit[i] = (z >> i) & 0x01;
|
||||
|
||||
/* butterfly operations */
|
||||
for (i = 13; i >= 0; i--) {
|
||||
/* swap bits according to index arrays if control signal tells us to */
|
||||
if (p[i]) {
|
||||
tmp = z_bit[index1[i]];
|
||||
z_bit[index1[i]] = z_bit[index2[i]];
|
||||
z_bit[index2[i]] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* reconstruct output from rearranged bits */
|
||||
output = 0;
|
||||
for (i = 0; i < 5; i++)
|
||||
output += z_bit[i] << i;
|
||||
|
||||
return(output);
|
||||
}
|
||||
|
||||
void perm_table_init(void)
|
||||
{
|
||||
/* populate perm_table for all possible inputs */
|
||||
int z, p_high, p_low;
|
||||
for (z = 0; z < 0x20; z++)
|
||||
for (p_high = 0; p_high < 0x20; p_high++)
|
||||
for (p_low = 0; p_low < 0x200; p_low++)
|
||||
perm_table[z][p_high][p_low] = perm5(z, p_high, p_low);
|
||||
}
|
||||
|
||||
/* drop-in replacement for perm5() using lookup table */
|
||||
int fast_perm(int z, int p_high, int p_low)
|
||||
{
|
||||
if (!perm_table_initialized) {
|
||||
perm_table_init();
|
||||
perm_table_initialized = 1;
|
||||
}
|
||||
|
||||
return(perm_table[z][p_high][p_low]);
|
||||
}
|
||||
|
||||
/* generate the complete hopping sequence */
|
||||
static void gen_hops(btbb_piconet *pn)
|
||||
{
|
||||
/* a, b, c, d, e, f, x, y1, y2 are variable names used in section 2.6 of the spec */
|
||||
/* b is already defined */
|
||||
/* e is already defined */
|
||||
int a, c, d, x;
|
||||
uint32_t base_f, f, f_dash;
|
||||
int h, i, j, k, c_flipped, perm_in, perm_out;
|
||||
|
||||
/* sequence index = clock >> 1 */
|
||||
/* (hops only happen at every other clock value) */
|
||||
int index = 0;
|
||||
base_f = 0;
|
||||
f = 0;
|
||||
f_dash = 0;
|
||||
|
||||
/* nested loops for optimization (not recalculating every variable with every clock tick) */
|
||||
for (h = 0; h < 0x04; h++) { /* clock bits 26-27 */
|
||||
for (i = 0; i < 0x20; i++) { /* clock bits 21-25 */
|
||||
a = pn->a1 ^ i;
|
||||
for (j = 0; j < 0x20; j++) { /* clock bits 16-20 */
|
||||
c = pn->c1 ^ j;
|
||||
c_flipped = c ^ 0x1f;
|
||||
for (k = 0; k < 0x200; k++) { /* clock bits 7-15 */
|
||||
d = pn->d1 ^ k;
|
||||
for (x = 0; x < 0x20; x++) { /* clock bits 2-6 */
|
||||
perm_in = ((x + a) % 32) ^ pn->b;
|
||||
|
||||
/* y1 (clock bit 1) = 0, y2 = 0 */
|
||||
perm_out = fast_perm(perm_in, c, d);
|
||||
if (btbb_piconet_get_flag(pn, BTBB_IS_AFH))
|
||||
pn->sequence[index] = pn->bank[(perm_out + pn->e + f_dash) % pn->used_channels];
|
||||
else
|
||||
pn->sequence[index] = pn->bank[(perm_out + pn->e + f) % BT_NUM_CHANNELS];
|
||||
|
||||
/* y1 (clock bit 1) = 1, y2 = 32 */
|
||||
perm_out = fast_perm(perm_in, c_flipped, d);
|
||||
if (btbb_piconet_get_flag(pn, BTBB_IS_AFH))
|
||||
pn->sequence[index + 1] = pn->bank[(perm_out + pn->e + f_dash + 32) % pn->used_channels];
|
||||
else
|
||||
pn->sequence[index + 1] = pn->bank[(perm_out + pn->e + f + 32) % BT_NUM_CHANNELS];
|
||||
|
||||
index += 2;
|
||||
}
|
||||
base_f += 16;
|
||||
f = base_f % BT_NUM_CHANNELS;
|
||||
f_dash = f % pn->used_channels;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to calculate piconet hopping patterns and add to hash map */
|
||||
void gen_hop_pattern(btbb_piconet *pn)
|
||||
{
|
||||
printf("\nCalculating complete hopping sequence.\n");
|
||||
/* this holds the entire hopping sequence */
|
||||
pn->sequence = (char*) malloc(SEQUENCE_LENGTH);
|
||||
|
||||
precalc(pn);
|
||||
address_precalc(((pn->UAP<<24) | pn->LAP) & 0xfffffff, pn);
|
||||
gen_hops(pn);
|
||||
|
||||
printf("Hopping sequence calculated.\n");
|
||||
}
|
||||
|
||||
/* Container for hopping pattern */
|
||||
typedef struct {
|
||||
uint64_t key; /* afh flag + address */
|
||||
char *sequence;
|
||||
UT_hash_handle hh;
|
||||
} hopping_struct;
|
||||
|
||||
static hopping_struct *hopping_map = NULL;
|
||||
|
||||
/* Function to fetch piconet hopping patterns */
|
||||
void get_hop_pattern(btbb_piconet *pn)
|
||||
{
|
||||
hopping_struct *s;
|
||||
uint64_t key;
|
||||
|
||||
/* Two stages to avoid "left shift count >= width of type" warning */
|
||||
key = btbb_piconet_get_flag(pn, BTBB_IS_AFH);
|
||||
key = (key<<39) | ((uint64_t)pn->used_channels<<32) | (pn->UAP<<24) | pn->LAP;
|
||||
HASH_FIND(hh, hopping_map, &key, 4, s);
|
||||
|
||||
if (s == NULL) {
|
||||
gen_hop_pattern(pn);
|
||||
s = malloc(sizeof(hopping_struct));
|
||||
s->key = key;
|
||||
s->sequence = pn->sequence;
|
||||
HASH_ADD(hh, hopping_map, key, 4, s);
|
||||
} else {
|
||||
printf("\nFound hopping sequence in cache.\n");
|
||||
pn->sequence = s->sequence;
|
||||
}
|
||||
}
|
||||
|
||||
/* determine channel for a particular hop */
|
||||
/* borrowed from ubertooth firmware to support AFH */
|
||||
char single_hop(int clock, btbb_piconet *pn)
|
||||
{
|
||||
int a, c, d, x, y1, y2, perm, next_channel;
|
||||
uint32_t base_f, f, f_dash;
|
||||
|
||||
/* following variable names used in section 2.6 of the spec */
|
||||
x = (clock >> 2) & 0x1f;
|
||||
y1 = (clock >> 1) & 0x01;
|
||||
y2 = y1 << 5;
|
||||
a = (pn->a1 ^ (clock >> 21)) & 0x1f;
|
||||
/* b is already defined */
|
||||
c = (pn->c1 ^ (clock >> 16)) & 0x1f;
|
||||
d = (pn->d1 ^ (clock >> 7)) & 0x1ff;
|
||||
/* e is already defined */
|
||||
base_f = (clock >> 3) & 0x1fffff0;
|
||||
f = base_f % BT_NUM_CHANNELS;
|
||||
|
||||
perm = fast_perm(
|
||||
((x + a) % 32) ^ pn->b,
|
||||
(y1 * 0x1f) ^ c,
|
||||
d);
|
||||
/* hop selection */
|
||||
if(btbb_piconet_get_flag(pn, BTBB_IS_AFH)) {
|
||||
f_dash = base_f % pn->used_channels;
|
||||
next_channel = pn->bank[(perm + pn->e + f_dash + y2) % pn->used_channels];
|
||||
} else {
|
||||
next_channel = pn->bank[(perm + pn->e + f + y2) % BT_NUM_CHANNELS];
|
||||
}
|
||||
return next_channel;
|
||||
}
|
||||
|
||||
/* look up channel for a particular hop */
|
||||
char hop(int clock, btbb_piconet *pn)
|
||||
{
|
||||
return pn->sequence[clock];
|
||||
}
|
||||
|
||||
static char aliased_channel(char channel)
|
||||
{
|
||||
return ((channel + 24) % ALIASED_CHANNELS) + 26;
|
||||
}
|
||||
|
||||
/* create list of initial candidate clock values (hops with same channel as first observed hop) */
|
||||
static int init_candidates(char channel, int known_clock_bits, btbb_piconet *pn)
|
||||
{
|
||||
int i;
|
||||
int count = 0; /* total number of candidates */
|
||||
char observable_channel; /* accounts for aliasing if necessary */
|
||||
|
||||
/* only try clock values that match our known bits */
|
||||
for (i = known_clock_bits; i < SEQUENCE_LENGTH; i += 0x40) {
|
||||
if (pn->aliased)
|
||||
observable_channel = aliased_channel(pn->sequence[i]);
|
||||
else
|
||||
observable_channel = pn->sequence[i];
|
||||
if (observable_channel == channel)
|
||||
pn->clock_candidates[count++] = i;
|
||||
//FIXME ought to throw exception if count gets too big
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/* initialize the hop reversal process */
|
||||
int btbb_init_hop_reversal(int aliased, btbb_piconet *pn)
|
||||
{
|
||||
int max_candidates;
|
||||
uint32_t clock;
|
||||
|
||||
get_hop_pattern(pn);
|
||||
|
||||
if(aliased)
|
||||
max_candidates = (SEQUENCE_LENGTH / ALIASED_CHANNELS) / 32;
|
||||
else
|
||||
max_candidates = (SEQUENCE_LENGTH / BT_NUM_CHANNELS) / 32;
|
||||
/* this can hold twice the approximate number of initial candidates */
|
||||
pn->clock_candidates = (uint32_t*) malloc(sizeof(uint32_t) * max_candidates);
|
||||
|
||||
clock = (pn->clk_offset + pn->first_pkt_time) & 0x3f;
|
||||
pn->num_candidates = init_candidates(pn->pattern_channels[0], clock, pn);
|
||||
pn->winnowed = 0;
|
||||
btbb_piconet_set_flag(pn, BTBB_HOP_REVERSAL_INIT, 1);
|
||||
btbb_piconet_set_flag(pn, BTBB_CLK27_VALID, 0);
|
||||
btbb_piconet_set_flag(pn, BTBB_IS_ALIASED, aliased);
|
||||
|
||||
printf("%d initial CLK1-27 candidates\n", pn->num_candidates);
|
||||
|
||||
return pn->num_candidates;
|
||||
}
|
||||
|
||||
void try_hop(btbb_packet *pkt, btbb_piconet *pn)
|
||||
{
|
||||
uint8_t filter_uap = pn->UAP;
|
||||
|
||||
/* Decode packet - fixing clock drift in the process */
|
||||
btbb_decode(pkt, pn);
|
||||
|
||||
if (btbb_piconet_get_flag(pn, BTBB_HOP_REVERSAL_INIT)) {
|
||||
//pn->winnowed = 0;
|
||||
pn->pattern_indices[pn->packets_observed] =
|
||||
pkt->clkn - pn->first_pkt_time;
|
||||
pn->pattern_channels[pn->packets_observed] = pkt->channel;
|
||||
pn->packets_observed++;
|
||||
pn->total_packets_observed++;
|
||||
btbb_winnow(pn);
|
||||
if (btbb_piconet_get_flag(pn, BTBB_CLK27_VALID)) {
|
||||
printf("got CLK1-27\n");
|
||||
printf("clock offset = %d.\n", pn->clk_offset);
|
||||
}
|
||||
} else {
|
||||
if (btbb_piconet_get_flag(pn, BTBB_CLK6_VALID)) {
|
||||
btbb_uap_from_header(pkt, pn);
|
||||
if (btbb_piconet_get_flag(pn, BTBB_CLK27_VALID)) {
|
||||
printf("got CLK1-27\n");
|
||||
printf("clock offset = %d.\n", pn->clk_offset);
|
||||
}
|
||||
} else {
|
||||
if (btbb_uap_from_header(pkt, pn)) {
|
||||
if (filter_uap == pn->UAP) {
|
||||
btbb_init_hop_reversal(0, pn);
|
||||
btbb_winnow(pn);
|
||||
} else {
|
||||
printf("failed to confirm UAP\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!btbb_piconet_get_flag(pn, BTBB_UAP_VALID)) {
|
||||
btbb_piconet_set_flag(pn, BTBB_UAP_VALID, 1);
|
||||
pn->UAP = filter_uap;
|
||||
}
|
||||
}
|
||||
|
||||
/* return the observable channel (26-50) for a given channel (0-78) */
|
||||
/* reset UAP/clock discovery */
|
||||
static void reset(btbb_piconet *pn)
|
||||
{
|
||||
//printf("no candidates remaining! starting over . . .\n");
|
||||
|
||||
if(btbb_piconet_get_flag(pn, BTBB_HOP_REVERSAL_INIT)) {
|
||||
free(pn->clock_candidates);
|
||||
pn->sequence = NULL;
|
||||
}
|
||||
btbb_piconet_set_flag(pn, BTBB_GOT_FIRST_PACKET, 0);
|
||||
btbb_piconet_set_flag(pn, BTBB_HOP_REVERSAL_INIT, 0);
|
||||
btbb_piconet_set_flag(pn, BTBB_UAP_VALID, 0);
|
||||
btbb_piconet_set_flag(pn, BTBB_CLK6_VALID, 0);
|
||||
btbb_piconet_set_flag(pn, BTBB_CLK27_VALID, 0);
|
||||
pn->packets_observed = 0;
|
||||
|
||||
/*
|
||||
* If we have recently observed two packets in a row on the same
|
||||
* channel, try AFH next time. If not, don't.
|
||||
*/
|
||||
btbb_piconet_set_flag(pn, BTBB_IS_AFH,
|
||||
btbb_piconet_get_flag(pn, BTBB_LOOKS_LIKE_AFH));
|
||||
// btbb_piconet_set_flag(pn, BTBB_LOOKS_LIKE_AFH, 0);
|
||||
//int i;
|
||||
//for(i=0; i<10; i++)
|
||||
// pn->afh_map[i] = 0;
|
||||
}
|
||||
|
||||
/* narrow a list of candidate clock values based on a single observed hop */
|
||||
static int channel_winnow(int offset, char channel, btbb_piconet *pn)
|
||||
{
|
||||
int i;
|
||||
int new_count = 0; /* number of candidates after winnowing */
|
||||
char observable_channel; /* accounts for aliasing if necessary */
|
||||
|
||||
/* check every candidate */
|
||||
for (i = 0; i < pn->num_candidates; i++) {
|
||||
if (pn->aliased)
|
||||
observable_channel = aliased_channel(pn->sequence[(pn->clock_candidates[i] + offset) % SEQUENCE_LENGTH]);
|
||||
else
|
||||
observable_channel = pn->sequence[(pn->clock_candidates[i] + offset) % SEQUENCE_LENGTH];
|
||||
if (observable_channel == channel) {
|
||||
/* this candidate matches the latest hop */
|
||||
/* blow away old list of candidates with new one */
|
||||
/* safe because new_count can never be greater than i */
|
||||
pn->clock_candidates[new_count++] = pn->clock_candidates[i];
|
||||
}
|
||||
}
|
||||
pn->num_candidates = new_count;
|
||||
|
||||
if (new_count == 1) {
|
||||
// Calculate clock offset for CLKN, not CLK1-27
|
||||
pn->clk_offset = ((pn->clock_candidates[0]<<1) - (pn->first_pkt_time<<1));
|
||||
printf("\nAcquired CLK1-27 = 0x%07x\n", pn->clock_candidates[0]);
|
||||
btbb_piconet_set_flag(pn, BTBB_CLK27_VALID, 1);
|
||||
}
|
||||
else if (new_count == 0) {
|
||||
reset(pn);
|
||||
}
|
||||
//else {
|
||||
//printf("%d CLK1-27 candidates remaining (channel=%d)\n", new_count, channel);
|
||||
//}
|
||||
|
||||
return new_count;
|
||||
}
|
||||
|
||||
/* narrow a list of candidate clock values based on all observed hops */
|
||||
int btbb_winnow(btbb_piconet *pn)
|
||||
{
|
||||
int new_count = pn->num_candidates;
|
||||
int index, last_index;
|
||||
uint8_t channel, last_channel;
|
||||
|
||||
for (; pn->winnowed < pn->packets_observed; pn->winnowed++) {
|
||||
index = pn->pattern_indices[pn->winnowed];
|
||||
channel = pn->pattern_channels[pn->winnowed];
|
||||
new_count = channel_winnow(index, channel, pn);
|
||||
if (new_count <= 1)
|
||||
break;
|
||||
|
||||
if (pn->packets_observed > 0) {
|
||||
last_index = pn->pattern_indices[pn->winnowed - 1];
|
||||
last_channel = pn->pattern_channels[pn->winnowed - 1];
|
||||
/*
|
||||
* Two packets in a row on the same channel should only
|
||||
* happen if adaptive frequency hopping is in use.
|
||||
* There can be false positives, though, especially if
|
||||
* there is aliasing.
|
||||
*/
|
||||
if (!btbb_piconet_get_flag(pn, BTBB_LOOKS_LIKE_AFH)
|
||||
&& (index == last_index + 1)
|
||||
&& (channel == last_channel)) {
|
||||
btbb_piconet_set_flag(pn, BTBB_LOOKS_LIKE_AFH, 1);
|
||||
printf("Hopping pattern appears to be AFH\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new_count;
|
||||
}
|
||||
|
||||
/* use packet headers to determine UAP */
|
||||
int btbb_uap_from_header(btbb_packet *pkt, btbb_piconet *pn)
|
||||
{
|
||||
uint8_t UAP;
|
||||
int count, crc_chk, first_clock = 0;
|
||||
|
||||
int starting = 0;
|
||||
int remaining = 0;
|
||||
uint32_t clkn = pkt->clkn;
|
||||
|
||||
if (!btbb_piconet_get_flag(pn, BTBB_GOT_FIRST_PACKET))
|
||||
pn->first_pkt_time = clkn;
|
||||
|
||||
// Set afh channel map
|
||||
btbb_piconet_set_channel_seen(pn, pkt->channel);
|
||||
|
||||
if (pn->packets_observed < MAX_PATTERN_LENGTH) {
|
||||
pn->pattern_indices[pn->packets_observed] = clkn - pn->first_pkt_time;
|
||||
pn->pattern_channels[pn->packets_observed] = pkt->channel;
|
||||
} else {
|
||||
printf("Oops. More hops than we can remember.\n");
|
||||
reset(pn);
|
||||
return 0; //FIXME ought to throw exception
|
||||
}
|
||||
pn->packets_observed++;
|
||||
pn->total_packets_observed++;
|
||||
|
||||
/* try every possible first packet clock value */
|
||||
for (count = 0; count < 64; count++) {
|
||||
/* skip eliminated candidates unless this is our first time through */
|
||||
if (pn->clock6_candidates[count] > -1
|
||||
|| !btbb_piconet_get_flag(pn, BTBB_GOT_FIRST_PACKET)) {
|
||||
/* clock value for the current packet assuming count was the clock of the first packet */
|
||||
int clock = (count + clkn - pn->first_pkt_time) % 64;
|
||||
starting++;
|
||||
UAP = try_clock(clock, pkt);
|
||||
crc_chk = -1;
|
||||
|
||||
/* if this is the first packet: populate the candidate list */
|
||||
/* if not: check CRCs if UAPs match */
|
||||
if (!btbb_piconet_get_flag(pn, BTBB_GOT_FIRST_PACKET)
|
||||
|| UAP == pn->clock6_candidates[count])
|
||||
crc_chk = crc_check(clock, pkt);
|
||||
|
||||
if (btbb_piconet_get_flag(pn, BTBB_UAP_VALID) &&
|
||||
(UAP != pn->UAP))
|
||||
crc_chk = -1;
|
||||
|
||||
switch(crc_chk) {
|
||||
case -1: /* UAP mismatch */
|
||||
case 0: /* CRC failure */
|
||||
pn->clock6_candidates[count] = -1;
|
||||
break;
|
||||
|
||||
case 1: /* inconclusive result */
|
||||
case 2: /* Inconclusive, but looks better */
|
||||
pn->clock6_candidates[count] = UAP;
|
||||
/* remember this count because it may be the correct clock of the first packet */
|
||||
first_clock = count;
|
||||
remaining++;
|
||||
break;
|
||||
|
||||
default: /* CRC success */
|
||||
pn->clk_offset = (count - (pn->first_pkt_time & 0x3f)) & 0x3f;
|
||||
if (!btbb_piconet_get_flag(pn, BTBB_UAP_VALID))
|
||||
printf("Correct CRC! UAP = 0x%x found after %d total packets.\n",
|
||||
UAP, pn->total_packets_observed);
|
||||
else
|
||||
printf("Correct CRC! CLK6 = 0x%x found after %d total packets.\n",
|
||||
pn->clk_offset, pn->total_packets_observed);
|
||||
pn->UAP = UAP;
|
||||
btbb_piconet_set_flag(pn, BTBB_CLK6_VALID, 1);
|
||||
btbb_piconet_set_flag(pn, BTBB_UAP_VALID, 1);
|
||||
pn->total_packets_observed = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
btbb_piconet_set_flag(pn, BTBB_GOT_FIRST_PACKET, 1);
|
||||
|
||||
//printf("reduced from %d to %d CLK1-6 candidates\n", starting, remaining);
|
||||
|
||||
if (remaining == 1) {
|
||||
pn->clk_offset = (first_clock - (pn->first_pkt_time & 0x3f)) & 0x3f;
|
||||
if (!btbb_piconet_get_flag(pn, BTBB_UAP_VALID))
|
||||
printf("UAP = 0x%x found after %d total packets.\n",
|
||||
pn->clock6_candidates[first_clock], pn->total_packets_observed);
|
||||
else
|
||||
printf("CLK6 = 0x%x found after %d total packets.\n",
|
||||
pn->clk_offset, pn->total_packets_observed);
|
||||
pn->UAP = pn->clock6_candidates[first_clock];
|
||||
btbb_piconet_set_flag(pn, BTBB_CLK6_VALID, 1);
|
||||
btbb_piconet_set_flag(pn, BTBB_UAP_VALID, 1);
|
||||
pn->total_packets_observed = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (remaining == 0) {
|
||||
reset(pn);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: comment out enqueue and dequeue because they are
|
||||
* never used. Try to find out what tey were meant to be
|
||||
* used for before the next release.
|
||||
*/
|
||||
///* add a packet to the queue */
|
||||
//static void enqueue(btbb_packet *pkt, btbb_piconet *pn)
|
||||
//{
|
||||
// pkt_queue *head;
|
||||
// //pkt_queue item;
|
||||
//
|
||||
// btbb_packet_ref(pkt);
|
||||
// pkt_queue item = {pkt, NULL};
|
||||
// head = pn->queue;
|
||||
//
|
||||
// if (head == NULL) {
|
||||
// pn->queue = &item;
|
||||
// } else {
|
||||
// for(; head->next != NULL; head = head->next)
|
||||
// ;
|
||||
// head->next = &item;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
///* pull the first packet from the queue (FIFO) */
|
||||
//static btbb_packet *dequeue(btbb_piconet *pn)
|
||||
//{
|
||||
// btbb_packet *pkt;
|
||||
//
|
||||
// if (pn->queue == NULL) {
|
||||
// pkt = NULL;
|
||||
// } else {
|
||||
// pkt = pn->queue->pkt;
|
||||
// pn->queue = pn->queue->next;
|
||||
// btbb_packet_unref(pkt);
|
||||
// }
|
||||
//
|
||||
// return pkt;
|
||||
//}
|
||||
|
||||
/* decode the whole packet */
|
||||
int btbb_decode(btbb_packet* pkt, btbb_piconet *pn)
|
||||
{
|
||||
btbb_packet_set_flag(pkt, BTBB_HAS_PAYLOAD, 0);
|
||||
uint8_t clk6, i, best_clk;
|
||||
int rv = 0, max_rv = 0;
|
||||
if (btbb_piconet_get_flag(pn, BTBB_CLK27_VALID)) {
|
||||
/* Removing this section until we can more reliably handle AFH */
|
||||
//if(pn->sequence == NULL)
|
||||
// get_hop_pattern(pn);
|
||||
//clk6 = pkt->clock & 0x3f;
|
||||
//for(i=0; i<64; i++) {
|
||||
// pkt->clock = (pkt->clock & 0xffffffc0) | ((clk6 + i) & 0x3f);
|
||||
// if ((pn->sequence[pkt->clock] == pkt->channel) && (btbb_decode_header(pkt))) {
|
||||
// rv = btbb_decode_payload(pkt);
|
||||
// if(rv > max_rv) {
|
||||
// max_rv = rv;
|
||||
// best_clk = (clk6 + i) & 0x3f;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
// If we found nothing, try again, ignoring channel
|
||||
if(max_rv <= 1) {
|
||||
clk6 = pkt->clock & 0x3f;
|
||||
for(i=0; i<64; i++) {
|
||||
pkt->clock = (pkt->clock & 0xffffffc0) | ((clk6 + i) & 0x3f);
|
||||
if (btbb_decode_header(pkt)) {
|
||||
rv = btbb_decode_payload(pkt);
|
||||
if(rv > max_rv) {
|
||||
//printf("Packet decoded with clock 0x%07x (rv=%d)\n", pkt->clock, rv);
|
||||
//btbb_print_packet(pkt);
|
||||
max_rv = rv;
|
||||
best_clk = (clk6 + i) & 0x3f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (btbb_decode_header(pkt)) {
|
||||
for(i=0; i<64; i++) {
|
||||
pkt->clock = (pkt->clock & 0xffffffc0) | (i & 0x3f);
|
||||
if (btbb_decode_header(pkt)) {
|
||||
rv = btbb_decode_payload(pkt);
|
||||
if(rv > max_rv) {
|
||||
//printf("Packet decoded with clock 0x%02x (rv=%d)\n", i, rv);
|
||||
//btbb_print_packet(pkt);
|
||||
max_rv = rv;
|
||||
best_clk = i & 0x3f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If we were successful, print the packet */
|
||||
if(max_rv > 0) {
|
||||
pkt->clock = (pkt->clock & 0xffffffc0) | (best_clk & 0x3f);
|
||||
btbb_decode_payload(pkt);
|
||||
printf("Packet decoded with clock 0x%02x (rv=%d)\n", i, rv);
|
||||
btbb_print_packet(pkt);
|
||||
}
|
||||
|
||||
return max_rv;
|
||||
}
|
||||
|
||||
/* Print AFH map from observed packets */
|
||||
void btbb_print_afh_map(btbb_piconet *pn) {
|
||||
uint8_t *afh_map;
|
||||
afh_map = pn->afh_map;
|
||||
|
||||
/* Print like hcitool does */
|
||||
printf("AFH map: 0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
|
||||
afh_map[0], afh_map[1], afh_map[2], afh_map[3], afh_map[4],
|
||||
afh_map[5], afh_map[6], afh_map[7], afh_map[8], afh_map[9]);
|
||||
|
||||
// /* Printed ch78 -> ch0 */
|
||||
// printf("\tAFH Map=0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
|
||||
// afh_map[9], afh_map[8], afh_map[7], afh_map[6], afh_map[5],
|
||||
// afh_map[4], afh_map[3], afh_map[2], afh_map[1], afh_map[0]);
|
||||
}
|
||||
|
||||
/* Container for survey piconets */
|
||||
typedef struct {
|
||||
uint32_t key; /* LAP */
|
||||
btbb_piconet *pn;
|
||||
UT_hash_handle hh;
|
||||
} survey_hash;
|
||||
|
||||
static survey_hash *piconet_survey = NULL;
|
||||
|
||||
/* Check for existing piconets in survey results */
|
||||
btbb_piconet *get_piconet(uint32_t lap)
|
||||
{
|
||||
survey_hash *s;
|
||||
btbb_piconet *pn;
|
||||
HASH_FIND(hh, piconet_survey, &lap, 4, s);
|
||||
|
||||
if (s == NULL) {
|
||||
pn = btbb_piconet_new();
|
||||
btbb_init_piconet(pn, lap);
|
||||
|
||||
s = malloc(sizeof(survey_hash));
|
||||
s->key = lap;
|
||||
s->pn = pn;
|
||||
HASH_ADD(hh, piconet_survey, key, 4, s);
|
||||
} else {
|
||||
pn = s->pn;
|
||||
}
|
||||
return pn;
|
||||
}
|
||||
|
||||
/* Destructively iterate over survey results */
|
||||
btbb_piconet *btbb_next_survey_result() {
|
||||
btbb_piconet *pn = NULL;
|
||||
survey_hash *tmp;
|
||||
|
||||
if (piconet_survey != NULL) {
|
||||
pn = piconet_survey->pn;
|
||||
tmp = piconet_survey;
|
||||
piconet_survey = piconet_survey->hh.next;
|
||||
free(tmp);
|
||||
}
|
||||
return pn;
|
||||
}
|
||||
|
||||
int btbb_process_packet(btbb_packet *pkt, btbb_piconet *pn) {
|
||||
if (survey_mode) {
|
||||
pn = get_piconet(btbb_packet_get_lap(pkt));
|
||||
btbb_piconet_set_channel_seen(pn, pkt->channel);
|
||||
if(btbb_header_present(pkt) && !btbb_piconet_get_flag(pn, BTBB_UAP_VALID))
|
||||
btbb_uap_from_header(pkt, pn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(pn)
|
||||
btbb_piconet_set_channel_seen(pn, pkt->channel);
|
||||
|
||||
/* If piconet structure is given, a LAP is given, and packet
|
||||
* header is readable, do further analysis. If UAP has not yet
|
||||
* been determined, attempt to calculate it from headers. Once
|
||||
* UAP is known, try to determine clk6 and clk27. Once clocks
|
||||
* are known, follow the piconet. */
|
||||
if (pn && btbb_piconet_get_flag(pn, BTBB_LAP_VALID) &&
|
||||
btbb_header_present(pkt)) {
|
||||
|
||||
/* Have LAP/UAP/clocks, now hopping along with the piconet. */
|
||||
if (btbb_piconet_get_flag(pn, BTBB_FOLLOWING)) {
|
||||
btbb_packet_set_uap(pkt, btbb_piconet_get_uap(pn));
|
||||
btbb_packet_set_flag(pkt, BTBB_CLK6_VALID, 1);
|
||||
btbb_packet_set_flag(pkt, BTBB_CLK27_VALID, 1);
|
||||
|
||||
if(btbb_decode(pkt, pn))
|
||||
btbb_print_packet(pkt);
|
||||
else
|
||||
printf("Failed to decode packet\n");
|
||||
}
|
||||
|
||||
/* Have LAP/UAP, need clocks. */
|
||||
else if (btbb_piconet_get_uap(pn)) {
|
||||
try_hop(pkt, pn);
|
||||
if (btbb_piconet_get_flag(pn, BTBB_CLK6_VALID) &&
|
||||
btbb_piconet_get_flag(pn, BTBB_CLK27_VALID)) {
|
||||
btbb_piconet_set_flag(pn, BTBB_FOLLOWING, 1);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Have LAP, need UAP. */
|
||||
else {
|
||||
btbb_uap_from_header(pkt, pn);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2007 - 2013 Dominic Spill, Michael Ossmann, Will Code
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#ifndef INCLUDED_BLUETOOTH_PICONET_H
|
||||
#define INCLUDED_BLUETOOTH_PICONET_H
|
||||
#include "btbb.h"
|
||||
|
||||
/* maximum number of hops to remember */
|
||||
#define MAX_PATTERN_LENGTH 1000
|
||||
|
||||
/* number of channels in use */
|
||||
#define BT_NUM_CHANNELS 79
|
||||
|
||||
struct btbb_piconet {
|
||||
|
||||
uint32_t refcount;
|
||||
|
||||
uint32_t flags;
|
||||
|
||||
/* true if using a particular aliased receiver implementation */
|
||||
int aliased;
|
||||
|
||||
/* AFH channel map - either read or derived from observed packets */
|
||||
uint8_t afh_map[10];
|
||||
|
||||
/* Number of used channel derived from AFH channel map */
|
||||
uint8_t used_channels;
|
||||
|
||||
/* lower address part (of master's BD_ADDR) */
|
||||
uint32_t LAP;
|
||||
|
||||
/* upper address part (of master's BD_ADDR) */
|
||||
uint8_t UAP;
|
||||
|
||||
/* non-significant address part (of master's BD_ADDR) */
|
||||
uint16_t NAP;
|
||||
|
||||
/* CLK1-27 candidates */
|
||||
uint32_t *clock_candidates;
|
||||
|
||||
/* these values for hop() can be precalculated */
|
||||
int b, e;
|
||||
|
||||
/* these values for hop() can be precalculated in part (e.g. a1 is the
|
||||
* precalculated part of a) */
|
||||
int a1, c1, d1;
|
||||
|
||||
/* frequency register bank */
|
||||
int bank[BT_NUM_CHANNELS];
|
||||
|
||||
/* this holds the entire hopping sequence */
|
||||
char *sequence;
|
||||
|
||||
/* number of candidates for CLK1-27 */
|
||||
int num_candidates;
|
||||
|
||||
/* number of packets observed during one attempt at UAP/clock discovery */
|
||||
int packets_observed;
|
||||
|
||||
/* total number of packets observed */
|
||||
int total_packets_observed;
|
||||
|
||||
/* number of observed packets that have been used to winnow the candidates */
|
||||
int winnowed;
|
||||
|
||||
/* CLK1-6 candidates */
|
||||
int clock6_candidates[64];
|
||||
|
||||
/* remember patterns of observed hops */
|
||||
int pattern_indices[MAX_PATTERN_LENGTH];
|
||||
uint8_t pattern_channels[MAX_PATTERN_LENGTH];
|
||||
|
||||
/* offset between CLKN (local) and CLK of piconet */
|
||||
int clk_offset;
|
||||
|
||||
/* local clock (clkn) at time of first packet */
|
||||
uint32_t first_pkt_time;
|
||||
|
||||
/* queue of packets to be decoded */
|
||||
pkt_queue *queue;
|
||||
};
|
||||
|
||||
/* number of hops in the hopping sequence (i.e. number of possible values of CLK1-27) */
|
||||
#define SEQUENCE_LENGTH 134217728
|
||||
|
||||
/* number of aliased channels received */
|
||||
#define ALIASED_CHANNELS 25
|
||||
|
||||
/* do all the precalculation that can be done before knowing the address */
|
||||
void precalc(btbb_piconet *pnet);
|
||||
|
||||
/* do precalculation that requires the address */
|
||||
void address_precalc(int address, btbb_piconet *pnet);
|
||||
|
||||
/* drop-in replacement for perm5() using lookup table */
|
||||
int fast_perm(int z, int p_high, int p_low);
|
||||
|
||||
/* 5 bit permutation */
|
||||
/* assumes z is constrained to 5 bits, p_high to 5 bits, p_low to 9 bits */
|
||||
int perm5(int z, int p_high, int p_low);
|
||||
|
||||
/* determine channel for a particular hop */
|
||||
/* replaced with gen_hops() for a complete sequence but could still come in handy */
|
||||
char single_hop(int clock, btbb_piconet *pnet);
|
||||
|
||||
/* look up channel for a particular hop */
|
||||
char hop(int clock, btbb_piconet *pnet);
|
||||
|
||||
void try_hop(btbb_packet *pkt, btbb_piconet *pn);
|
||||
|
||||
void get_hop_pattern(btbb_piconet *pn);
|
||||
|
||||
#endif /* INCLUDED_BLUETOOTH_PICONET_H */
|
|
@ -0,0 +1,288 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2007 - 2013 Dominic Spill, Michael Ossmann, Will Code
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#ifndef INCLUDED_BTBB_H
|
||||
#define INCLUDED_BTBB_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define BTBB_WHITENED 0
|
||||
#define BTBB_NAP_VALID 1
|
||||
#define BTBB_UAP_VALID 2
|
||||
#define BTBB_LAP_VALID 3
|
||||
#define BTBB_CLK6_VALID 4
|
||||
#define BTBB_CLK27_VALID 5
|
||||
#define BTBB_CRC_CORRECT 6
|
||||
#define BTBB_HAS_PAYLOAD 7
|
||||
#define BTBB_IS_EDR 8
|
||||
|
||||
#define BTBB_HOP_REVERSAL_INIT 9
|
||||
#define BTBB_GOT_FIRST_PACKET 10
|
||||
#define BTBB_IS_AFH 11
|
||||
#define BTBB_LOOKS_LIKE_AFH 12
|
||||
#define BTBB_IS_ALIASED 13
|
||||
#define BTBB_FOLLOWING 14
|
||||
|
||||
/* Payload modulation */
|
||||
#define BTBB_MOD_UNKNOWN 0x00
|
||||
#define BTBB_MOD_GFSK 0x01
|
||||
#define BTBB_MOD_PI_OVER_2_DQPSK 0x02
|
||||
#define BTBB_MOD_8DPSK 0x03
|
||||
|
||||
/* Transport types */
|
||||
#define BTBB_TRANSPORT_ANY 0x00
|
||||
#define BTBB_TRANSPORT_SCO 0x01
|
||||
#define BTBB_TRANSPORT_ESCO 0x02
|
||||
#define BTBB_TRANSPORT_ACL 0x03
|
||||
#define BTBB_TRANSPORT_CSB 0x04
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* BT BR/EDR support */
|
||||
|
||||
typedef struct btbb_packet btbb_packet;
|
||||
|
||||
/* Initialize the library. Compute the syndrome. Return 0 on success,
|
||||
* negative on error.
|
||||
*
|
||||
* The library limits max_ac_errors to 5. Using a larger value will
|
||||
* take up a lot of memory (several GB), without decoding many useful
|
||||
* packets. Even a limit of 5 results in a syndrome table of several
|
||||
* hundred MB and lots of noise. For embedded targets, a value of 2 is
|
||||
* reasonable. */
|
||||
int btbb_init(int max_ac_errors);
|
||||
|
||||
char *btbb_get_release(void);
|
||||
char *btbb_get_version(void);
|
||||
|
||||
btbb_packet *btbb_packet_new(void);
|
||||
void btbb_packet_ref(btbb_packet *pkt);
|
||||
void btbb_packet_unref(btbb_packet *pkt);
|
||||
|
||||
/* Search for a packet with specified LAP (or LAP_ANY). The stream
|
||||
* must be at least of length serch_length + 72. Limit to
|
||||
* 'max_ac_errors' bit errors.
|
||||
*
|
||||
* Returns offset into 'stream' at which packet was found. If no
|
||||
* packet was found, returns a negative number. If LAP_ANY was
|
||||
* specified, fills lap. 'ac_errors' must be set as an input, replaced
|
||||
* by actual number of errors on output. */
|
||||
int btbb_find_ac(char *stream,
|
||||
int search_length,
|
||||
uint32_t lap,
|
||||
int max_ac_errors,
|
||||
btbb_packet **pkt);
|
||||
#define LAP_ANY 0xffffffffUL
|
||||
#define UAP_ANY 0xff
|
||||
|
||||
void btbb_packet_set_flag(btbb_packet *pkt, int flag, int val);
|
||||
int btbb_packet_get_flag(const btbb_packet *pkt, int flag);
|
||||
|
||||
uint32_t btbb_packet_get_lap(const btbb_packet *pkt);
|
||||
void btbb_packet_set_uap(btbb_packet *pkt, uint8_t uap);
|
||||
uint8_t btbb_packet_get_uap(const btbb_packet *pkt);
|
||||
uint16_t btbb_packet_get_nap(const btbb_packet *pkt);
|
||||
|
||||
void btbb_packet_set_modulation(btbb_packet *pkt, uint8_t modulation);
|
||||
void btbb_packet_set_transport(btbb_packet *pkt, uint8_t transport);
|
||||
uint8_t btbb_packet_get_modulation(const btbb_packet *pkt);
|
||||
uint8_t btbb_packet_get_transport(const btbb_packet *pkt);
|
||||
|
||||
uint8_t btbb_packet_get_channel(const btbb_packet *pkt);
|
||||
uint8_t btbb_packet_get_ac_errors(const btbb_packet *pkt);
|
||||
uint32_t btbb_packet_get_clkn(const btbb_packet *pkt);
|
||||
uint32_t btbb_packet_get_header_packed(const btbb_packet* pkt);
|
||||
|
||||
void btbb_packet_set_data(btbb_packet *pkt,
|
||||
char *syms, // Symbol data
|
||||
int length, // Number of symbols
|
||||
uint8_t channel, // Bluetooth channel 0-79
|
||||
uint32_t clkn); // 312.5us clock (CLK27-0)
|
||||
|
||||
/* Get a pointer to packet symbols. */
|
||||
const char *btbb_get_symbols(const btbb_packet* pkt);
|
||||
|
||||
int btbb_packet_get_payload_length(const btbb_packet* pkt);
|
||||
|
||||
/* Get a pointer to payload. */
|
||||
const char *btbb_get_payload(const btbb_packet* pkt);
|
||||
|
||||
/* Pack the payload in to bytes */
|
||||
int btbb_get_payload_packed(const btbb_packet* pkt, char *dst);
|
||||
|
||||
uint8_t btbb_packet_get_type(const btbb_packet* pkt);
|
||||
uint8_t btbb_packet_get_lt_addr(const btbb_packet* pkt);
|
||||
uint8_t btbb_packet_get_header_flags(const btbb_packet* pkt);
|
||||
uint8_t btbb_packet_get_hec(const btbb_packet *pkt);
|
||||
|
||||
/* Generate Sync Word from an LAP */
|
||||
uint64_t btbb_gen_syncword(const int LAP);
|
||||
|
||||
/* decode the packet header */
|
||||
int btbb_decode_header(btbb_packet* pkt);
|
||||
|
||||
/* decode the packet header */
|
||||
int btbb_decode_payload(btbb_packet* pkt);
|
||||
|
||||
/* print packet information */
|
||||
void btbb_print_packet(const btbb_packet* pkt);
|
||||
|
||||
/* check to see if the packet has a header */
|
||||
int btbb_header_present(const btbb_packet* pkt);
|
||||
|
||||
/* Packet queue (linked list) */
|
||||
typedef struct pkt_queue {
|
||||
btbb_packet *pkt;
|
||||
|
||||
struct pkt_queue *next;
|
||||
|
||||
} pkt_queue;
|
||||
|
||||
typedef struct btbb_piconet btbb_piconet;
|
||||
|
||||
btbb_piconet *btbb_piconet_new(void);
|
||||
void btbb_piconet_ref(btbb_piconet *pn);
|
||||
void btbb_piconet_unref(btbb_piconet *pn);
|
||||
|
||||
/* initialize the piconet struct */
|
||||
void btbb_init_piconet(btbb_piconet *pn, uint32_t lap);
|
||||
|
||||
void btbb_piconet_set_uap(btbb_piconet *pn, uint8_t uap);
|
||||
uint8_t btbb_piconet_get_uap(const btbb_piconet *pn);
|
||||
uint32_t btbb_piconet_get_lap(const btbb_piconet *pn);
|
||||
uint16_t btbb_piconet_get_nap(const btbb_piconet *pn);
|
||||
uint64_t btbb_piconet_get_bdaddr(const btbb_piconet *pn);
|
||||
|
||||
int btbb_piconet_get_clk_offset(const btbb_piconet *pn);
|
||||
void btbb_piconet_set_clk_offset(btbb_piconet *pn, int clk_offset);
|
||||
|
||||
void btbb_piconet_set_flag(btbb_piconet *pn, int flag, int val);
|
||||
int btbb_piconet_get_flag(const btbb_piconet *pn, int flag);
|
||||
|
||||
void btbb_piconet_set_channel_seen(btbb_piconet *pn, uint8_t channel);
|
||||
void btbb_piconet_set_afh_map(btbb_piconet *pn, uint8_t *afh_map);
|
||||
uint8_t *btbb_piconet_get_afh_map(btbb_piconet *pn);
|
||||
|
||||
/* Extract as much information (LAP/UAP/CLK) as possible from received packet */
|
||||
int btbb_process_packet(btbb_packet *pkt, btbb_piconet *pn);
|
||||
|
||||
/* use packet headers to determine UAP */
|
||||
int btbb_uap_from_header(btbb_packet *pkt, btbb_piconet *pn);
|
||||
|
||||
/* Print hexadecimal representation of the derived AFH map */
|
||||
void btbb_print_afh_map(btbb_piconet *pn);
|
||||
|
||||
/* decode a whole packet from the given piconet */
|
||||
int btbb_decode(btbb_packet* pkt, btbb_piconet *pn);
|
||||
|
||||
|
||||
/* initialize the hop reversal process */
|
||||
/* returns number of initial candidates for CLK1-27 */
|
||||
int btbb_init_hop_reversal(int aliased, btbb_piconet *pn);
|
||||
|
||||
/* narrow a list of candidate clock values based on all observed hops */
|
||||
int btbb_winnow(btbb_piconet *pn);
|
||||
|
||||
int btbb_init_survey(void);
|
||||
/* Destructively iterate over survey results - optionally remove elements */
|
||||
btbb_piconet *btbb_next_survey_result(void);
|
||||
|
||||
typedef struct btbb_pcapng_handle btbb_pcapng_handle;
|
||||
/* create a PCAPNG file for BREDR captures */
|
||||
int btbb_pcapng_create_file(const char *filename, const char *interface_desc, btbb_pcapng_handle ** ph);
|
||||
/* save a BREDR packet to PCAPNG capture file */
|
||||
int btbb_pcapng_append_packet(btbb_pcapng_handle * h, const uint64_t ns,
|
||||
const int8_t sigdbm, const int8_t noisedbm,
|
||||
const uint32_t reflap, const uint8_t refuap,
|
||||
const btbb_packet *pkt);
|
||||
/* record a BDADDR to PCAPNG capture file */
|
||||
int btbb_pcapng_record_bdaddr(btbb_pcapng_handle * h, const uint64_t bdaddr,
|
||||
const uint8_t uapmask, const uint8_t napvalid);
|
||||
/* record BT CLOCK to PCAPNG capture file */
|
||||
int btbb_pcapng_record_btclock(btbb_pcapng_handle * h, const uint64_t bdaddr,
|
||||
const uint64_t ns, const uint32_t clk, const uint32_t clkmask);
|
||||
int btbb_pcapng_close(btbb_pcapng_handle * h);
|
||||
|
||||
|
||||
/* BLE support */
|
||||
typedef struct lell_packet lell_packet;
|
||||
/* decode and allocate LE packet */
|
||||
void lell_allocate_and_decode(const uint8_t *stream, uint16_t phys_channel, uint32_t clk100ns, lell_packet **pkt);
|
||||
lell_packet *lell_packet_new(void);
|
||||
void lell_packet_ref(lell_packet *pkt);
|
||||
void lell_packet_unref(lell_packet *pkt);
|
||||
uint32_t lell_get_access_address(const lell_packet *pkt);
|
||||
unsigned lell_get_access_address_offenses(const lell_packet *pkt);
|
||||
unsigned lell_packet_is_data(const lell_packet *pkt);
|
||||
unsigned lell_get_channel_index(const lell_packet *pkt);
|
||||
unsigned lell_get_channel_k(const lell_packet *pkt);
|
||||
const char * lell_get_adv_type_str(const lell_packet *pkt);
|
||||
void lell_print(const lell_packet *pkt);
|
||||
|
||||
typedef struct lell_pcapng_handle lell_pcapng_handle;
|
||||
/* create a PCAPNG file for LE captures */
|
||||
int lell_pcapng_create_file(const char *filename, const char *interface_desc, lell_pcapng_handle ** ph);
|
||||
/* save an LE packet to PCAPNG capture file */
|
||||
int lell_pcapng_append_packet(lell_pcapng_handle * h, const uint64_t ns,
|
||||
const int8_t sigdbm, const int8_t noisedbm,
|
||||
const uint32_t refAA, const lell_packet *pkt);
|
||||
/* record LE CONNECT_REQ parameters to PCAPNG capture file */
|
||||
int lell_pcapng_record_connect_req(lell_pcapng_handle * h, const uint64_t ns, const uint8_t * pdu);
|
||||
int lell_pcapng_close(lell_pcapng_handle *h);
|
||||
|
||||
|
||||
/* PCAP Support */
|
||||
#if defined(ENABLE_PCAP)
|
||||
typedef struct btbb_pcap_handle btbb_pcap_handle;
|
||||
/* create a PCAP file for BREDR captures with LINKTYPE_BLUETOOTH_BREDR_BB */
|
||||
int btbb_pcap_create_file(const char *filename, btbb_pcap_handle ** ph);
|
||||
/* write a BREDR packet to PCAP file */
|
||||
int btbb_pcap_append_packet(btbb_pcap_handle * h, const uint64_t ns,
|
||||
const int8_t sigdbm, const int8_t noisedbm,
|
||||
const uint32_t reflap, const uint8_t refuap,
|
||||
const btbb_packet *pkt);
|
||||
int btbb_pcap_close(btbb_pcap_handle * h);
|
||||
|
||||
typedef struct lell_pcap_handle lell_pcap_handle;
|
||||
/* create a PCAP file for LE captures using LINKTYPE_BLUETOOTH_LE_LL_WITH_PHDR */
|
||||
int lell_pcap_create_file(const char *filename, lell_pcap_handle ** ph);
|
||||
/* create a PCAP file for LE captures using LINKTYPE_PPI */
|
||||
int lell_pcap_ppi_create_file(const char *filename, int btle_ppi_version, lell_pcap_handle ** ph);
|
||||
/* save an LE packet to PCAP capture file */
|
||||
int lell_pcap_append_packet(lell_pcap_handle * h, const uint64_t ns,
|
||||
const int8_t sigdbm, const int8_t noisedbm,
|
||||
const uint32_t refAA, const lell_packet *pkt);
|
||||
int lell_pcap_append_ppi_packet(lell_pcap_handle * h, const uint64_t ns,
|
||||
const uint8_t clkn_high,
|
||||
const int8_t rssi_min, const int8_t rssi_max,
|
||||
const int8_t rssi_avg, const uint8_t rssi_count,
|
||||
const lell_packet *pkt);
|
||||
int lell_pcap_close(lell_pcap_handle *h);
|
||||
#endif // ENABLE_PCAP
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // __cplusplus defined.
|
||||
#endif
|
||||
|
||||
#endif /* INCLUDED_BTBB_H */
|
|
@ -0,0 +1,129 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2014 Christopher D. Kilgour techie AT whiterocker.com
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#ifndef PCAP_COMMON_DOT_H
|
||||
#define PCAP_COMMON_DOT_H
|
||||
|
||||
/* pull definitions for BT DLTs and pseudoheaders from libpcap, if possible */
|
||||
#if defined(ENABLE_PCAP)
|
||||
#include <pcap/pcap.h>
|
||||
#include <pcap/bluetooth.h>
|
||||
#endif /* ENABLE_PCAP */
|
||||
|
||||
#if defined( __APPLE__ )
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#define htobe32 EndianU32_NtoB
|
||||
#define be32toh EndianU32_BtoN
|
||||
#define le32toh EndianU32_LtoN
|
||||
#define htobe64 EndianU64_NtoB
|
||||
#define be64toh EndianU64_BtoN
|
||||
#define htole16 EndianU16_NtoL
|
||||
#define htole32 EndianU32_NtoL
|
||||
#else
|
||||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
#if !defined( htole16 ) /* will be defined under Linux when endian.h already included */
|
||||
#if defined( __GNUC__ )
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
inline uint16_t htole16(uint16_t host_16bits) { return host_16bits; }
|
||||
inline uint16_t le16toh(uint16_t little_endian_16bits) { return little_endian_16bits; }
|
||||
inline uint32_t htole32(uint32_t host_32bits) { return host_32bits; }
|
||||
inline uint32_t le32toh(uint32_t little_endian_32bits) { return little_endian_32bits; }
|
||||
inline uint64_t htole64(uint64_t host_64bits) { return host_64bits; }
|
||||
inline uint64_t le64toh(uint64_t little_endian_64bits) { return little_endian_64bits; }
|
||||
#else
|
||||
#error "FIXME: need to support big-endian under GNU"
|
||||
#endif /* __BYTE_ORDER__ */
|
||||
#else /* not GNU C */
|
||||
#error "FIXME: need to support non-GNU compiler"
|
||||
#endif /* __GNUC__ */
|
||||
#endif /* htole16 */
|
||||
|
||||
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
|
||||
|
||||
/* --------------------------------- BR/EDR ----------------------------- */
|
||||
|
||||
#if !defined( DLT_BLUETOOTH_BREDR_BB )
|
||||
#define DLT_BLUETOOTH_BREDR_BB 255
|
||||
#endif
|
||||
typedef struct __attribute__((packed)) _pcap_bluetooth_bredr_bb_header {
|
||||
uint8_t rf_channel;
|
||||
int8_t signal_power;
|
||||
int8_t noise_power;
|
||||
uint8_t access_code_offenses;
|
||||
uint8_t payload_transport_rate;
|
||||
uint8_t corrected_header_bits;
|
||||
int16_t corrected_payload_bits;
|
||||
uint32_t lap;
|
||||
uint32_t ref_lap_uap;
|
||||
uint32_t bt_header;
|
||||
uint16_t flags;
|
||||
uint8_t br_edr_payload[0];
|
||||
} pcap_bluetooth_bredr_bb_header;
|
||||
|
||||
#define BREDR_DEWHITENED 0x0001
|
||||
#define BREDR_SIGPOWER_VALID 0x0002
|
||||
#define BREDR_NOISEPOWER_VALID 0x0004
|
||||
#define BREDR_PAYLOAD_DECRYPTED 0x0008
|
||||
#define BREDR_REFLAP_VALID 0x0010
|
||||
#define BREDR_PAYLOAD_PRESENT 0x0020
|
||||
#define BREDR_CHANNEL_ALIASED 0x0040
|
||||
#define BREDR_REFUAP_VALID 0x0080
|
||||
#define BREDR_HEC_CHECKED 0x0100
|
||||
#define BREDR_HEC_VALID 0x0200
|
||||
#define BREDR_CRC_CHECKED 0x0400
|
||||
#define BREDR_CRC_VALID 0x0800
|
||||
#define BREDR_MIC_CHECKED 0x1000
|
||||
#define BREDR_MIC_VALID 0x2000
|
||||
|
||||
#define BREDR_MAX_PAYLOAD 400
|
||||
|
||||
/* --------------------------------- Low Energy ---------------------------- */
|
||||
|
||||
#if !defined( DLT_BLUETOOTH_LE_LL_WITH_PHDR )
|
||||
#define DLT_BLUETOOTH_LE_LL_WITH_PHDR 256
|
||||
#endif
|
||||
typedef struct __attribute__((packed)) _pcap_bluetooth_le_ll_header {
|
||||
uint8_t rf_channel;
|
||||
int8_t signal_power;
|
||||
int8_t noise_power;
|
||||
uint8_t access_address_offenses;
|
||||
uint32_t ref_access_address;
|
||||
uint16_t flags;
|
||||
uint8_t le_packet[0];
|
||||
} pcap_bluetooth_le_ll_header;
|
||||
|
||||
#define LE_DEWHITENED 0x0001
|
||||
#define LE_SIGPOWER_VALID 0x0002
|
||||
#define LE_NOISEPOWER_VALID 0x0004
|
||||
#define LE_PACKET_DECRYPTED 0x0008
|
||||
#define LE_REF_AA_VALID 0x0010
|
||||
#define LE_AA_OFFENSES_VALID 0x0020
|
||||
#define LE_CHANNEL_ALIASED 0x0040
|
||||
#define LE_CRC_CHECKED 0x0400
|
||||
#define LE_CRC_VALID 0x0800
|
||||
#define LE_MIC_CHECKED 0x1000
|
||||
#define LE_MIC_VALID 0x2000
|
||||
|
||||
#define LE_MAX_PAYLOAD 48
|
||||
|
||||
#endif /* PCAP_COMMON_DOT_H */
|
|
@ -0,0 +1,422 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2014 Christopher D. Kilgour techie AT whiterocker.com
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#include "bluetooth_le_packet.h"
|
||||
#include "bluetooth_packet.h"
|
||||
#include "btbb.h"
|
||||
#include "pcap-common.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef enum {
|
||||
PCAP_OK = 0,
|
||||
PCAP_INVALID_HANDLE,
|
||||
PCAP_FILE_NOT_ALLOWED,
|
||||
PCAP_NO_MEMORY,
|
||||
} PCAP_RESULT;
|
||||
|
||||
#if defined(ENABLE_PCAP)
|
||||
|
||||
/* BT BR/EDR support */
|
||||
|
||||
struct btbb_pcap_handle {
|
||||
pcap_t * pcap;
|
||||
pcap_dumper_t * dumper;
|
||||
};
|
||||
|
||||
int
|
||||
btbb_pcap_create_file(const char *filename, btbb_pcap_handle ** ph)
|
||||
{
|
||||
int retval = 0;
|
||||
btbb_pcap_handle * handle = malloc( sizeof(btbb_pcap_handle) );
|
||||
if (handle) {
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
#ifdef PCAP_TSTAMP_PRECISION_NANO
|
||||
handle->pcap = pcap_open_dead_with_tstamp_precision(DLT_BLUETOOTH_BREDR_BB,
|
||||
BREDR_MAX_PAYLOAD,
|
||||
PCAP_TSTAMP_PRECISION_NANO);
|
||||
#else
|
||||
handle->pcap = pcap_open_dead(DLT_BLUETOOTH_BREDR_BB, BREDR_MAX_PAYLOAD);
|
||||
#endif
|
||||
if (handle->pcap) {
|
||||
handle->dumper = pcap_dump_open(handle->pcap, filename);
|
||||
if (handle->dumper) {
|
||||
*ph = handle;
|
||||
}
|
||||
else {
|
||||
pcap_perror(handle->pcap, "PCAP error:");
|
||||
retval = -PCAP_FILE_NOT_ALLOWED;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
retval = -PCAP_INVALID_HANDLE;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
retval = -PCAP_NO_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
return retval;
|
||||
fail:
|
||||
(void) btbb_pcap_close( handle );
|
||||
return retval;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
struct pcap_pkthdr pcap_header;
|
||||
pcap_bluetooth_bredr_bb_header bredr_bb_header;
|
||||
uint8_t bredr_payload[BREDR_MAX_PAYLOAD];
|
||||
} pcap_bredr_packet;
|
||||
|
||||
static void
|
||||
assemble_pcapng_bredr_packet( pcap_bredr_packet * pkt,
|
||||
const uint32_t interface_id __attribute__((unused)),
|
||||
const uint64_t ns,
|
||||
const uint32_t caplen,
|
||||
const uint8_t rf_channel,
|
||||
const int8_t signal_power,
|
||||
const int8_t noise_power,
|
||||
const uint8_t access_code_offenses,
|
||||
const uint8_t payload_transport,
|
||||
const uint8_t payload_rate,
|
||||
const uint8_t corrected_header_bits,
|
||||
const int16_t corrected_payload_bits,
|
||||
const uint32_t lap,
|
||||
const uint32_t ref_lap,
|
||||
const uint8_t ref_uap,
|
||||
const uint32_t bt_header,
|
||||
const uint16_t flags,
|
||||
const uint8_t * payload )
|
||||
{
|
||||
uint32_t pcap_caplen = sizeof(pcap_bluetooth_bredr_bb_header)+caplen;
|
||||
uint32_t reflapuap = (ref_lap&0xffffff) | (ref_uap<<24);
|
||||
|
||||
pkt->pcap_header.ts.tv_sec = ns / 1000000000ull;
|
||||
pkt->pcap_header.ts.tv_usec = ns % 1000000000ull;
|
||||
pkt->pcap_header.caplen = pcap_caplen;
|
||||
pkt->pcap_header.len = pcap_caplen;
|
||||
|
||||
pkt->bredr_bb_header.rf_channel = rf_channel;
|
||||
pkt->bredr_bb_header.signal_power = signal_power;
|
||||
pkt->bredr_bb_header.noise_power = noise_power;
|
||||
pkt->bredr_bb_header.access_code_offenses = access_code_offenses;
|
||||
pkt->bredr_bb_header.payload_transport_rate =
|
||||
(payload_transport << 4) | payload_rate;
|
||||
pkt->bredr_bb_header.corrected_header_bits = corrected_header_bits;
|
||||
pkt->bredr_bb_header.corrected_payload_bits = htole16( corrected_payload_bits );
|
||||
pkt->bredr_bb_header.lap = htole32( lap );
|
||||
pkt->bredr_bb_header.ref_lap_uap = htole32( reflapuap );
|
||||
pkt->bredr_bb_header.bt_header = htole16( bt_header );
|
||||
pkt->bredr_bb_header.flags = htole16( flags );
|
||||
if (caplen) {
|
||||
(void) memcpy( &pkt->bredr_payload[0], payload, caplen );
|
||||
}
|
||||
else {
|
||||
pkt->bredr_bb_header.flags &= htole16( ~BREDR_PAYLOAD_PRESENT );
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
btbb_pcap_append_packet(btbb_pcap_handle * h, const uint64_t ns,
|
||||
const int8_t sigdbm, const int8_t noisedbm,
|
||||
const uint32_t reflap, const uint8_t refuap,
|
||||
const btbb_packet *pkt)
|
||||
{
|
||||
if (h && h->dumper) {
|
||||
uint16_t flags = BREDR_DEWHITENED | BREDR_SIGPOWER_VALID |
|
||||
((noisedbm < sigdbm) ? BREDR_NOISEPOWER_VALID : 0) |
|
||||
((reflap != LAP_ANY) ? BREDR_REFLAP_VALID : 0) |
|
||||
((refuap != UAP_ANY) ? BREDR_REFUAP_VALID : 0);
|
||||
uint32_t caplen = (uint32_t) btbb_packet_get_payload_length(pkt);
|
||||
uint8_t payload_bytes[caplen];
|
||||
btbb_get_payload_packed( pkt, (char *) &payload_bytes[0] );
|
||||
caplen = MIN(BREDR_MAX_PAYLOAD, caplen);
|
||||
pcap_bredr_packet pcap_pkt;
|
||||
assemble_pcapng_bredr_packet( &pcap_pkt,
|
||||
0,
|
||||
ns,
|
||||
caplen,
|
||||
btbb_packet_get_channel(pkt),
|
||||
sigdbm,
|
||||
noisedbm,
|
||||
btbb_packet_get_ac_errors(pkt),
|
||||
btbb_packet_get_transport(pkt),
|
||||
btbb_packet_get_modulation(pkt),
|
||||
0, /* TODO: corrected header bits */
|
||||
0, /* TODO: corrected payload bits */
|
||||
btbb_packet_get_lap(pkt),
|
||||
reflap,
|
||||
refuap,
|
||||
btbb_packet_get_header_packed(pkt),
|
||||
flags,
|
||||
payload_bytes );
|
||||
pcap_dump((u_char *)h->dumper, &pcap_pkt.pcap_header, (u_char *)&pcap_pkt.bredr_bb_header);
|
||||
return 0;
|
||||
}
|
||||
return -PCAP_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
int
|
||||
btbb_pcap_close(btbb_pcap_handle * h)
|
||||
{
|
||||
if (h && h->dumper) {
|
||||
pcap_dump_close(h->dumper);
|
||||
}
|
||||
if (h && h->pcap) {
|
||||
pcap_close(h->pcap);
|
||||
}
|
||||
if (h) {
|
||||
free(h);
|
||||
return 0;
|
||||
}
|
||||
return -PCAP_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/* BTLE support */
|
||||
|
||||
struct lell_pcap_handle {
|
||||
pcap_t * pcap;
|
||||
pcap_dumper_t * dumper;
|
||||
int dlt;
|
||||
uint8_t btle_ppi_version;
|
||||
};
|
||||
|
||||
static int
|
||||
lell_pcap_create_file_dlt(const char *filename, int dlt, lell_pcap_handle ** ph)
|
||||
{
|
||||
int retval = 0;
|
||||
lell_pcap_handle * handle = malloc( sizeof(lell_pcap_handle) );
|
||||
if (handle) {
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
#ifdef PCAP_TSTAMP_PRECISION_NANO
|
||||
handle->pcap = pcap_open_dead_with_tstamp_precision(dlt,
|
||||
BREDR_MAX_PAYLOAD,
|
||||
PCAP_TSTAMP_PRECISION_NANO);
|
||||
#else
|
||||
handle->pcap = pcap_open_dead(dlt, BREDR_MAX_PAYLOAD);
|
||||
#endif
|
||||
if (handle->pcap) {
|
||||
handle->dumper = pcap_dump_open(handle->pcap, filename);
|
||||
if (handle->dumper) {
|
||||
handle->dlt = dlt;
|
||||
*ph = handle;
|
||||
}
|
||||
else {
|
||||
retval = -PCAP_FILE_NOT_ALLOWED;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
retval = -PCAP_INVALID_HANDLE;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
retval = -PCAP_NO_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
return retval;
|
||||
fail:
|
||||
(void) lell_pcap_close( handle );
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
lell_pcap_create_file(const char *filename, lell_pcap_handle ** ph)
|
||||
{
|
||||
return lell_pcap_create_file_dlt(filename, DLT_BLUETOOTH_LE_LL_WITH_PHDR, ph);
|
||||
}
|
||||
|
||||
int
|
||||
lell_pcap_ppi_create_file(const char *filename, int btle_ppi_version,
|
||||
lell_pcap_handle ** ph)
|
||||
{
|
||||
int retval = lell_pcap_create_file_dlt(filename, DLT_PPI, ph);
|
||||
if (!retval) {
|
||||
(*ph)->btle_ppi_version = btle_ppi_version;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
struct pcap_pkthdr pcap_header;
|
||||
pcap_bluetooth_le_ll_header le_ll_header;
|
||||
uint8_t le_packet[LE_MAX_PAYLOAD];
|
||||
} pcap_le_packet;
|
||||
|
||||
static void
|
||||
assemble_pcapng_le_packet( pcap_le_packet * pkt,
|
||||
const uint32_t interface_id __attribute__((unused)),
|
||||
const uint64_t ns,
|
||||
const uint32_t caplen,
|
||||
const uint8_t rf_channel,
|
||||
const int8_t signal_power,
|
||||
const int8_t noise_power,
|
||||
const uint8_t access_address_offenses,
|
||||
const uint32_t ref_access_address,
|
||||
const uint16_t flags,
|
||||
const uint8_t * lepkt )
|
||||
{
|
||||
uint32_t pcap_caplen = sizeof(pcap_bluetooth_le_ll_header)+caplen;
|
||||
|
||||
pkt->pcap_header.ts.tv_sec = ns / 1000000000ull;
|
||||
pkt->pcap_header.ts.tv_usec = ns % 1000000000ull;
|
||||
pkt->pcap_header.caplen = pcap_caplen;
|
||||
pkt->pcap_header.len = pcap_caplen;
|
||||
|
||||
pkt->le_ll_header.rf_channel = rf_channel;
|
||||
pkt->le_ll_header.signal_power = signal_power;
|
||||
pkt->le_ll_header.noise_power = noise_power;
|
||||
pkt->le_ll_header.access_address_offenses = access_address_offenses;
|
||||
pkt->le_ll_header.ref_access_address = htole32( ref_access_address );
|
||||
pkt->le_ll_header.flags = htole16( flags );
|
||||
(void) memcpy( &pkt->le_packet[0], lepkt, caplen );
|
||||
}
|
||||
|
||||
int
|
||||
lell_pcap_append_packet(lell_pcap_handle * h, const uint64_t ns,
|
||||
const int8_t sigdbm, const int8_t noisedbm,
|
||||
const uint32_t refAA, const lell_packet *pkt)
|
||||
{
|
||||
if (h && h->dumper &&
|
||||
(h->dlt == DLT_BLUETOOTH_LE_LL_WITH_PHDR)) {
|
||||
uint16_t flags = LE_DEWHITENED | LE_AA_OFFENSES_VALID |
|
||||
LE_SIGPOWER_VALID |
|
||||
((noisedbm < sigdbm) ? LE_NOISEPOWER_VALID : 0) |
|
||||
(lell_packet_is_data(pkt) ? 0 : LE_REF_AA_VALID);
|
||||
pcap_le_packet pcap_pkt;
|
||||
assemble_pcapng_le_packet( &pcap_pkt,
|
||||
0,
|
||||
ns,
|
||||
9+pkt->length,
|
||||
pkt->channel_k,
|
||||
sigdbm,
|
||||
noisedbm,
|
||||
pkt->access_address_offenses,
|
||||
refAA,
|
||||
flags,
|
||||
&pkt->symbols[0] );
|
||||
pcap_dump((u_char *)h->dumper, &pcap_pkt.pcap_header, (u_char *)&pcap_pkt.le_ll_header);
|
||||
return 0;
|
||||
}
|
||||
return -PCAP_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
#define PPI_BTLE 30006
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t pph_version;
|
||||
uint8_t pph_flags;
|
||||
uint16_t pph_len;
|
||||
uint32_t pph_dlt;
|
||||
} ppi_packet_header_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint16_t pfh_type;
|
||||
uint16_t pfh_datalen;
|
||||
} ppi_fieldheader_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t btle_version;
|
||||
uint16_t btle_channel;
|
||||
uint8_t btle_clkn_high;
|
||||
uint32_t btle_clk100ns;
|
||||
int8_t rssi_max;
|
||||
int8_t rssi_min;
|
||||
int8_t rssi_avg;
|
||||
uint8_t rssi_count;
|
||||
} ppi_btle_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
struct pcap_pkthdr pcap_header;
|
||||
ppi_packet_header_t ppi_packet_header;
|
||||
ppi_fieldheader_t ppi_fieldheader;
|
||||
ppi_btle_t le_ll_ppi_header;
|
||||
uint8_t le_packet[LE_MAX_PAYLOAD];
|
||||
} pcap_ppi_le_packet;
|
||||
|
||||
int
|
||||
lell_pcap_append_ppi_packet(lell_pcap_handle * h, const uint64_t ns,
|
||||
const uint8_t clkn_high,
|
||||
const int8_t rssi_min, const int8_t rssi_max,
|
||||
const int8_t rssi_avg, const uint8_t rssi_count,
|
||||
const lell_packet *pkt)
|
||||
{
|
||||
const uint16_t ppi_packet_header_sz = sizeof(ppi_packet_header_t);
|
||||
const uint16_t ppi_fieldheader_sz = sizeof(ppi_fieldheader_t);
|
||||
const uint16_t le_ll_ppi_header_sz = sizeof(ppi_btle_t);
|
||||
|
||||
if (h && h->dumper &&
|
||||
(h->dlt == DLT_PPI)) {
|
||||
pcap_ppi_le_packet pcap_pkt;
|
||||
uint32_t pcap_caplen =
|
||||
ppi_packet_header_sz+ppi_fieldheader_sz+le_ll_ppi_header_sz+pkt->length+9;
|
||||
uint16_t MHz = 2402 + 2*lell_get_channel_k(pkt);
|
||||
|
||||
pcap_pkt.pcap_header.ts.tv_sec = ns / 1000000000ull;
|
||||
pcap_pkt.pcap_header.ts.tv_usec = ns % 1000000000ull;
|
||||
pcap_pkt.pcap_header.caplen = pcap_caplen;
|
||||
pcap_pkt.pcap_header.len = pcap_caplen;
|
||||
|
||||
pcap_pkt.ppi_packet_header.pph_version = 0;
|
||||
pcap_pkt.ppi_packet_header.pph_flags = 0;
|
||||
pcap_pkt.ppi_packet_header.pph_len = htole16(ppi_packet_header_sz+ppi_fieldheader_sz+le_ll_ppi_header_sz);
|
||||
pcap_pkt.ppi_packet_header.pph_dlt = htole32(DLT_USER0);
|
||||
|
||||
pcap_pkt.ppi_fieldheader.pfh_type = htole16(PPI_BTLE);
|
||||
pcap_pkt.ppi_fieldheader.pfh_datalen = htole16(le_ll_ppi_header_sz);
|
||||
|
||||
pcap_pkt.le_ll_ppi_header.btle_version = h->btle_ppi_version;
|
||||
pcap_pkt.le_ll_ppi_header.btle_channel = htole16(MHz);
|
||||
pcap_pkt.le_ll_ppi_header.btle_clkn_high = clkn_high;
|
||||
pcap_pkt.le_ll_ppi_header.btle_clk100ns = htole32(pkt->clk100ns);
|
||||
pcap_pkt.le_ll_ppi_header.rssi_max = rssi_max;
|
||||
pcap_pkt.le_ll_ppi_header.rssi_min = rssi_min;
|
||||
pcap_pkt.le_ll_ppi_header.rssi_avg = rssi_avg;
|
||||
pcap_pkt.le_ll_ppi_header.rssi_count = rssi_count;
|
||||
(void) memcpy( &pcap_pkt.le_packet[0], &pkt->symbols[0], pkt->length + 9 ); // FIXME where does the 9 come from?
|
||||
pcap_dump((u_char *)h->dumper, &pcap_pkt.pcap_header, (u_char *)&pcap_pkt.ppi_packet_header);
|
||||
pcap_dump_flush(h->dumper);
|
||||
return 0;
|
||||
}
|
||||
return -PCAP_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
int
|
||||
lell_pcap_close(lell_pcap_handle *h)
|
||||
{
|
||||
if (h && h->dumper) {
|
||||
pcap_dump_close(h->dumper);
|
||||
}
|
||||
if (h && h->pcap) {
|
||||
pcap_close(h->pcap);
|
||||
}
|
||||
if (h) {
|
||||
free(h);
|
||||
return 0;
|
||||
}
|
||||
return -PCAP_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
#endif /* ENABLE_PCAP */
|
|
@ -0,0 +1,522 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2014 Christopher D. Kilgour techie AT whiterocker.com
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "btbb.h"
|
||||
#include "bluetooth_le_packet.h"
|
||||
#include "bluetooth_packet.h"
|
||||
#include "pcapng-bt.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* generic section options indicating libbtbb */
|
||||
const struct {
|
||||
struct {
|
||||
option_header hdr;
|
||||
char libname[8];
|
||||
} libopt;
|
||||
struct {
|
||||
option_header hdr;
|
||||
} termopt;
|
||||
} libbtbb_section_options = {
|
||||
.libopt = {
|
||||
.hdr = {
|
||||
.option_code = SHB_USERAPPL,
|
||||
.option_length = 7 },
|
||||
.libname = "libbtbb"
|
||||
},
|
||||
.termopt = {
|
||||
.hdr = {
|
||||
.option_code = OPT_ENDOFOPT,
|
||||
.option_length = 0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static PCAPNG_RESULT
|
||||
check_and_fix_tsresol( PCAPNG_HANDLE * handle,
|
||||
const option_header * interface_options )
|
||||
{
|
||||
PCAPNG_RESULT retval = PCAPNG_OK;
|
||||
int got_tsresol = 0;
|
||||
|
||||
while( !got_tsresol &&
|
||||
interface_options &&
|
||||
interface_options->option_code &&
|
||||
interface_options->option_length) {
|
||||
if (interface_options->option_code == IF_TSRESOL) {
|
||||
got_tsresol = 1;
|
||||
}
|
||||
else {
|
||||
size_t step = 4+4*((interface_options->option_length+3)/4);
|
||||
uint8_t * next = &((uint8_t *)interface_options)[step];
|
||||
interface_options = (const option_header *) next;
|
||||
}
|
||||
}
|
||||
|
||||
if (!got_tsresol) {
|
||||
const struct {
|
||||
option_header hdr;
|
||||
uint8_t resol;
|
||||
} tsresol = {
|
||||
.hdr = {
|
||||
.option_code = IF_TSRESOL,
|
||||
.option_length = 1,
|
||||
},
|
||||
.resol = 9 /* 10^-9 is nanoseconds */
|
||||
};
|
||||
|
||||
retval = pcapng_append_interface_option( handle,
|
||||
(const option_header *) &tsresol );
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* --------------------------------- BR/EDR ----------------------------- */
|
||||
|
||||
static PCAPNG_RESULT
|
||||
create_bredr_capture_file_single_interface( PCAPNG_HANDLE * handle,
|
||||
const char * filename,
|
||||
const option_header * interface_options )
|
||||
{
|
||||
PCAPNG_RESULT retval = PCAPNG_OK;
|
||||
|
||||
retval = pcapng_create( handle,
|
||||
filename,
|
||||
(const option_header *) &libbtbb_section_options,
|
||||
(size_t) getpagesize( ),
|
||||
DLT_BLUETOOTH_BREDR_BB,
|
||||
BREDR_MAX_PAYLOAD,
|
||||
interface_options,
|
||||
(size_t) getpagesize( ) );
|
||||
|
||||
if (retval == PCAPNG_OK) {
|
||||
/* if there is no timestamp resolution alread in the
|
||||
interface options, record nanosecond resolution */
|
||||
retval = check_and_fix_tsresol( handle, interface_options );
|
||||
|
||||
if (retval != PCAPNG_OK) {
|
||||
(void) pcapng_close( handle );
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int btbb_pcapng_create_file( const char *filename,
|
||||
const char *interface_desc,
|
||||
btbb_pcapng_handle ** ph )
|
||||
{
|
||||
int retval = PCAPNG_OK;
|
||||
PCAPNG_HANDLE * handle = malloc( sizeof(PCAPNG_HANDLE) );
|
||||
if (handle) {
|
||||
const option_header * popt = NULL;
|
||||
struct {
|
||||
option_header header;
|
||||
char desc[256];
|
||||
} ifopt = {
|
||||
.header = {
|
||||
.option_code = IF_DESCRIPTION,
|
||||
}
|
||||
};
|
||||
if (interface_desc) {
|
||||
(void) strncpy( &ifopt.desc[0], interface_desc, 256 );
|
||||
ifopt.desc[255] = '\0';
|
||||
ifopt.header.option_length = strlen( ifopt.desc );
|
||||
popt = (const option_header *) &ifopt;
|
||||
}
|
||||
|
||||
retval = -create_bredr_capture_file_single_interface( handle,
|
||||
filename,
|
||||
popt );
|
||||
if (retval == PCAPNG_OK) {
|
||||
*ph = (btbb_pcapng_handle *) handle;
|
||||
}
|
||||
else {
|
||||
free( handle );
|
||||
}
|
||||
}
|
||||
else {
|
||||
retval = -PCAPNG_NO_MEMORY;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static PCAPNG_RESULT
|
||||
append_bredr_packet( PCAPNG_HANDLE * handle,
|
||||
pcapng_bredr_packet * pkt )
|
||||
{
|
||||
return pcapng_append_packet( handle, ( const enhanced_packet_block *) pkt );
|
||||
}
|
||||
|
||||
static void
|
||||
assemble_pcapng_bredr_packet( pcapng_bredr_packet * pkt,
|
||||
const uint32_t interface_id,
|
||||
const uint64_t ns,
|
||||
const uint32_t caplen,
|
||||
const uint8_t rf_channel,
|
||||
const int8_t signal_power,
|
||||
const int8_t noise_power,
|
||||
const uint8_t access_code_offenses,
|
||||
const uint8_t payload_transport,
|
||||
const uint8_t payload_rate,
|
||||
const uint8_t corrected_header_bits,
|
||||
const int16_t corrected_payload_bits,
|
||||
const uint32_t lap,
|
||||
const uint32_t ref_lap,
|
||||
const uint8_t ref_uap,
|
||||
const uint32_t bt_header,
|
||||
const uint16_t flags,
|
||||
const char * payload )
|
||||
{
|
||||
uint32_t pcapng_caplen = sizeof(pcap_bluetooth_bredr_bb_header)+caplen;
|
||||
uint32_t block_length = 4*((36+pcapng_caplen+3)/4);
|
||||
uint32_t reflapuap = (ref_lap&0xffffff) | (ref_uap<<24);
|
||||
|
||||
pkt->blk_header.block_type = BLOCK_TYPE_ENHANCED_PACKET;
|
||||
pkt->blk_header.block_total_length = block_length;
|
||||
pkt->blk_header.interface_id = interface_id;
|
||||
pkt->blk_header.timestamp_high = (uint32_t) (ns >> 32);
|
||||
pkt->blk_header.timestamp_low = (uint32_t) (ns & 0x0ffffffffull);
|
||||
pkt->blk_header.captured_len = pcapng_caplen;
|
||||
pkt->blk_header.packet_len = pcapng_caplen;
|
||||
pkt->bredr_bb_header.rf_channel = rf_channel;
|
||||
pkt->bredr_bb_header.signal_power = signal_power;
|
||||
pkt->bredr_bb_header.noise_power = noise_power;
|
||||
pkt->bredr_bb_header.access_code_offenses = access_code_offenses;
|
||||
pkt->bredr_bb_header.payload_transport_rate =
|
||||
(payload_transport << 4) | payload_rate;
|
||||
pkt->bredr_bb_header.corrected_header_bits = corrected_header_bits;
|
||||
pkt->bredr_bb_header.corrected_payload_bits = htole16( corrected_payload_bits );
|
||||
pkt->bredr_bb_header.lap = htole32( lap );
|
||||
pkt->bredr_bb_header.ref_lap_uap = htole32( reflapuap );
|
||||
pkt->bredr_bb_header.bt_header = htole16( bt_header );
|
||||
pkt->bredr_bb_header.flags = htole16( flags );
|
||||
if (caplen) {
|
||||
(void) memcpy( &pkt->bredr_payload[0], payload, caplen );
|
||||
}
|
||||
else {
|
||||
pkt->bredr_bb_header.flags &= htole16( ~BREDR_PAYLOAD_PRESENT );
|
||||
}
|
||||
((uint32_t *)pkt)[block_length/4-2] = 0x00000000; /* no-options */
|
||||
((uint32_t *)pkt)[block_length/4-1] = block_length;
|
||||
}
|
||||
|
||||
int btbb_pcapng_append_packet(btbb_pcapng_handle * h, const uint64_t ns,
|
||||
const int8_t sigdbm, const int8_t noisedbm,
|
||||
const uint32_t reflap, const uint8_t refuap,
|
||||
const btbb_packet *pkt)
|
||||
{
|
||||
uint16_t flags = BREDR_DEWHITENED | BREDR_SIGPOWER_VALID |
|
||||
((noisedbm < sigdbm) ? BREDR_NOISEPOWER_VALID : 0) |
|
||||
((reflap != LAP_ANY) ? BREDR_REFLAP_VALID : 0) |
|
||||
((refuap != UAP_ANY) ? BREDR_REFUAP_VALID : 0);
|
||||
int caplen = btbb_packet_get_payload_length(pkt);
|
||||
char payload_bytes[caplen];
|
||||
btbb_get_payload_packed( pkt, &payload_bytes[0] );
|
||||
caplen = MIN(BREDR_MAX_PAYLOAD, caplen);
|
||||
pcapng_bredr_packet pcapng_pkt;
|
||||
assemble_pcapng_bredr_packet( &pcapng_pkt,
|
||||
0,
|
||||
ns,
|
||||
caplen,
|
||||
btbb_packet_get_channel(pkt),
|
||||
sigdbm,
|
||||
noisedbm,
|
||||
btbb_packet_get_ac_errors(pkt),
|
||||
btbb_packet_get_transport(pkt),
|
||||
btbb_packet_get_modulation(pkt),
|
||||
0, /* TODO: corrected header bits */
|
||||
0, /* TODO: corrected payload bits */
|
||||
btbb_packet_get_lap(pkt),
|
||||
reflap,
|
||||
refuap,
|
||||
btbb_packet_get_header_packed(pkt),
|
||||
flags,
|
||||
payload_bytes );
|
||||
return -append_bredr_packet( (PCAPNG_HANDLE *)h, &pcapng_pkt );
|
||||
}
|
||||
|
||||
static PCAPNG_RESULT
|
||||
record_bd_addr_info( PCAPNG_HANDLE * handle,
|
||||
const uint64_t bd_addr,
|
||||
const uint8_t uap_mask,
|
||||
const uint8_t nap_valid )
|
||||
{
|
||||
const bredr_br_addr_option bdopt = {
|
||||
.header = {
|
||||
.option_code = PCAPNG_BREDR_OPTION_BD_ADDR,
|
||||
.option_length = sizeof(bredr_br_addr_option),
|
||||
},
|
||||
.bd_addr_info = {
|
||||
.bd_addr = {
|
||||
((bd_addr>>0) & 0xff),
|
||||
((bd_addr>>8) & 0xff),
|
||||
((bd_addr>>16) & 0xff),
|
||||
((bd_addr>>24) & 0xff),
|
||||
((bd_addr>>32) & 0xff),
|
||||
((bd_addr>>40) & 0xff)
|
||||
},
|
||||
.uap_mask = uap_mask,
|
||||
.nap_valid = nap_valid,
|
||||
}
|
||||
};
|
||||
return pcapng_append_interface_option( handle,
|
||||
(const option_header *) &bdopt );
|
||||
}
|
||||
|
||||
int btbb_pcapng_record_bdaddr(btbb_pcapng_handle * h, const uint64_t bdaddr,
|
||||
const uint8_t uapmask, const uint8_t napvalid)
|
||||
{
|
||||
return -record_bd_addr_info( (PCAPNG_HANDLE *) h,
|
||||
bdaddr, uapmask, napvalid );
|
||||
}
|
||||
|
||||
static PCAPNG_RESULT
|
||||
record_bredr_master_clock_info( PCAPNG_HANDLE * handle,
|
||||
const uint64_t bd_addr,
|
||||
const uint64_t ns,
|
||||
const uint32_t clk,
|
||||
const uint32_t clk_mask)
|
||||
{
|
||||
const bredr_clk_option mcopt = {
|
||||
.header = {
|
||||
.option_code = PCAPNG_BREDR_OPTION_MASTER_CLOCK_INFO,
|
||||
.option_length = sizeof(bredr_clk_option)
|
||||
},
|
||||
.clock_info = {
|
||||
.ts = ns,
|
||||
.lap_uap = htole32(bd_addr & 0xffffffff),
|
||||
.clk = clk,
|
||||
.clk_mask = clk_mask
|
||||
}
|
||||
};
|
||||
return pcapng_append_interface_option( handle,
|
||||
(const option_header *) &mcopt );
|
||||
}
|
||||
|
||||
int btbb_pcapng_record_btclock(btbb_pcapng_handle * h, const uint64_t bdaddr,
|
||||
const uint64_t ns, const uint32_t clk,
|
||||
const uint32_t clkmask)
|
||||
{
|
||||
return -record_bredr_master_clock_info( (PCAPNG_HANDLE *) h,
|
||||
bdaddr, ns, clk, clkmask );
|
||||
}
|
||||
|
||||
int btbb_pcapng_close(btbb_pcapng_handle * h)
|
||||
{
|
||||
pcapng_close( (PCAPNG_HANDLE *) h );
|
||||
if (h) {
|
||||
free( h );
|
||||
}
|
||||
return -PCAPNG_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/* --------------------------------- Low Energy ---------------------------- */
|
||||
|
||||
static PCAPNG_RESULT
|
||||
create_le_capture_file_single_interface( PCAPNG_HANDLE * handle,
|
||||
const char * filename,
|
||||
const option_header * interface_options )
|
||||
{
|
||||
PCAPNG_RESULT retval = PCAPNG_OK;
|
||||
|
||||
retval = pcapng_create( handle,
|
||||
filename,
|
||||
(const option_header *) &libbtbb_section_options,
|
||||
(size_t) getpagesize( ),
|
||||
DLT_BLUETOOTH_LE_LL_WITH_PHDR,
|
||||
64,
|
||||
interface_options,
|
||||
(size_t) getpagesize( ) );
|
||||
|
||||
if (retval == PCAPNG_OK) {
|
||||
/* if there is no timestamp resolution alread in the
|
||||
interface options, record nanosecond resolution */
|
||||
retval = check_and_fix_tsresol( handle, interface_options );
|
||||
|
||||
if (retval != PCAPNG_OK) {
|
||||
(void) pcapng_close( handle );
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
lell_pcapng_create_file(const char *filename, const char *interface_desc,
|
||||
lell_pcapng_handle ** ph)
|
||||
{
|
||||
int retval = PCAPNG_OK;
|
||||
PCAPNG_HANDLE * handle = malloc( sizeof(PCAPNG_HANDLE) );
|
||||
if (handle) {
|
||||
const option_header * popt = NULL;
|
||||
struct {
|
||||
option_header header;
|
||||
char desc[256];
|
||||
} ifopt = {
|
||||
.header = {
|
||||
.option_code = IF_DESCRIPTION,
|
||||
}
|
||||
};
|
||||
if (interface_desc) {
|
||||
(void) strncpy( &ifopt.desc[0], interface_desc, 256 );
|
||||
ifopt.desc[255] = '\0';
|
||||
ifopt.header.option_length = strlen( ifopt.desc );
|
||||
popt = (const option_header *) &ifopt;
|
||||
}
|
||||
|
||||
retval = -create_le_capture_file_single_interface( handle,
|
||||
filename,
|
||||
popt );
|
||||
if (retval == PCAPNG_OK) {
|
||||
*ph = (lell_pcapng_handle *) handle;
|
||||
}
|
||||
else {
|
||||
free( handle );
|
||||
}
|
||||
}
|
||||
else {
|
||||
retval = -PCAPNG_NO_MEMORY;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static PCAPNG_RESULT
|
||||
append_le_packet( PCAPNG_HANDLE * handle,
|
||||
pcapng_le_packet * pkt )
|
||||
{
|
||||
return pcapng_append_packet( handle, ( const enhanced_packet_block *) pkt );
|
||||
}
|
||||
|
||||
/* Size of a PCAPNG enhanced packet block with no packet data.
|
||||
NOTE: The pcap_bluetooth_le_ll_header is part of the packet data of
|
||||
the enhanced block. */
|
||||
#define PCAPNG_ENHANCED_BLK_SZ 36
|
||||
|
||||
static void
|
||||
assemble_pcapng_le_packet( pcapng_le_packet * pkt,
|
||||
const uint32_t interface_id,
|
||||
const uint64_t ns,
|
||||
const uint32_t caplen,
|
||||
const uint8_t rf_channel,
|
||||
const int8_t signal_power,
|
||||
const int8_t noise_power,
|
||||
const uint8_t access_address_offenses,
|
||||
const uint32_t ref_access_address,
|
||||
const uint16_t flags,
|
||||
const uint8_t * lepkt )
|
||||
{
|
||||
uint32_t pcapng_caplen = sizeof(pcap_bluetooth_le_ll_header)+caplen;
|
||||
uint32_t block_length = 4*((PCAPNG_ENHANCED_BLK_SZ+pcapng_caplen+3)/4);
|
||||
|
||||
assert(caplen <= LE_MAX_PAYLOAD);
|
||||
|
||||
pkt->blk_header.block_type = BLOCK_TYPE_ENHANCED_PACKET;
|
||||
pkt->blk_header.block_total_length = block_length;
|
||||
pkt->blk_header.interface_id = interface_id;
|
||||
pkt->blk_header.timestamp_high = (uint32_t) (ns >> 32);
|
||||
pkt->blk_header.timestamp_low = (uint32_t) (ns & 0x0ffffffffull);
|
||||
pkt->blk_header.captured_len = pcapng_caplen;
|
||||
pkt->blk_header.packet_len = pcapng_caplen;
|
||||
pkt->le_ll_header.rf_channel = rf_channel;
|
||||
pkt->le_ll_header.signal_power = signal_power;
|
||||
pkt->le_ll_header.noise_power = noise_power;
|
||||
pkt->le_ll_header.access_address_offenses = access_address_offenses;
|
||||
pkt->le_ll_header.ref_access_address = htole32( ref_access_address );
|
||||
pkt->le_ll_header.flags = htole16( flags );
|
||||
(void) memcpy( &pkt->le_packet[0], lepkt, caplen );
|
||||
((uint32_t *)pkt)[block_length/4-2] = 0x00000000; /* no-options */
|
||||
((uint32_t *)pkt)[block_length/4-1] = block_length;
|
||||
}
|
||||
|
||||
int
|
||||
lell_pcapng_append_packet(lell_pcapng_handle * h, const uint64_t ns,
|
||||
const int8_t sigdbm, const int8_t noisedbm,
|
||||
const uint32_t refAA, const lell_packet *pkt)
|
||||
{
|
||||
uint16_t flags = LE_DEWHITENED | LE_AA_OFFENSES_VALID |
|
||||
LE_SIGPOWER_VALID |
|
||||
((noisedbm < sigdbm) ? LE_NOISEPOWER_VALID : 0) |
|
||||
(lell_packet_is_data(pkt) ? 0 : LE_REF_AA_VALID);
|
||||
pcapng_le_packet pcapng_pkt;
|
||||
|
||||
/* The extra 9 bytes added to the packet length are for:
|
||||
4 bytes for Access Address
|
||||
2 bytes for PDU header
|
||||
3 bytes for CRC */
|
||||
assemble_pcapng_le_packet( &pcapng_pkt,
|
||||
0,
|
||||
ns,
|
||||
9+pkt->length,
|
||||
pkt->channel_k,
|
||||
sigdbm,
|
||||
noisedbm,
|
||||
pkt->access_address_offenses,
|
||||
refAA,
|
||||
flags,
|
||||
&pkt->symbols[0] );
|
||||
int retval = -append_le_packet( (PCAPNG_HANDLE *) h, &pcapng_pkt );
|
||||
if ((retval == 0) && !lell_packet_is_data(pkt) && (pkt->adv_type == CONNECT_REQ)) {
|
||||
(void) lell_pcapng_record_connect_req(h, ns, &pkt->symbols[0]);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static PCAPNG_RESULT
|
||||
record_le_connect_req_info( PCAPNG_HANDLE * handle,
|
||||
const uint64_t ns,
|
||||
const uint8_t * pdu )
|
||||
{
|
||||
le_ll_connection_info_option cropt = {
|
||||
.header = {
|
||||
.option_code = PCAPNG_LE_LL_CONNECTION_INFO,
|
||||
.option_length = sizeof(le_ll_connection_info_option)
|
||||
},
|
||||
.connection_info = {
|
||||
.ns = ns
|
||||
}
|
||||
};
|
||||
(void) memcpy( &cropt.connection_info.pdu.bytes[0], pdu, 34 );
|
||||
return pcapng_append_interface_option( handle,
|
||||
(const option_header *) &cropt );
|
||||
}
|
||||
|
||||
int
|
||||
lell_pcapng_record_connect_req(lell_pcapng_handle * h, const uint64_t ns,
|
||||
const uint8_t * pdu)
|
||||
{
|
||||
return -record_le_connect_req_info( (PCAPNG_HANDLE *) h, ns, pdu );
|
||||
}
|
||||
|
||||
int lell_pcapng_close(lell_pcapng_handle *h)
|
||||
{
|
||||
pcapng_close( (PCAPNG_HANDLE *) h );
|
||||
if (h) {
|
||||
free( h );
|
||||
}
|
||||
return -PCAPNG_INVALID_HANDLE;
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2014 Christopher D. Kilgour techie AT whiterocker.com
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#ifndef PCAPNG_BT_DOT_H
|
||||
#define PCAPNG_BT_DOT_H
|
||||
|
||||
#include "pcap-common.h"
|
||||
#include "pcapng.h"
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t centre_freq;
|
||||
uint32_t analog_bandwidth;
|
||||
int32_t intermediate_freq;
|
||||
uint32_t sampling_bandwidth;
|
||||
} bt_wideband_rf_info;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
option_header header;
|
||||
bt_wideband_rf_info wideband_rf_info;
|
||||
} bt_wideband_rf_option;
|
||||
|
||||
#define PCAPNG_BT_WIDEBAND_RF_INFO 0xd300
|
||||
|
||||
/* --------------------------------- BR/EDR ----------------------------- */
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
enhanced_packet_block blk_header;
|
||||
pcap_bluetooth_bredr_bb_header bredr_bb_header;
|
||||
uint8_t bredr_payload[BREDR_MAX_PAYLOAD];
|
||||
} pcapng_bredr_packet;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bd_addr[6];
|
||||
uint8_t uap_mask;
|
||||
uint8_t nap_valid;
|
||||
} bredr_bd_addr_info;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
option_header header;
|
||||
bredr_bd_addr_info bd_addr_info;
|
||||
} bredr_br_addr_option;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint64_t ts;
|
||||
uint32_t lap_uap;
|
||||
uint32_t clk;
|
||||
uint32_t clk_mask;
|
||||
} bredr_clk_info;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
option_header header;
|
||||
bredr_clk_info clock_info;
|
||||
} bredr_clk_option;
|
||||
|
||||
#define PCAPNG_BREDR_OPTION_BD_ADDR 0xd340
|
||||
#define PCAPNG_BREDR_OPTION_MASTER_CLOCK_INFO 0xd341
|
||||
|
||||
/* --------------------------------- Low Energy ---------------------------- */
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
enhanced_packet_block blk_header;
|
||||
pcap_bluetooth_le_ll_header le_ll_header;
|
||||
uint8_t le_packet[LE_MAX_PAYLOAD];
|
||||
|
||||
/* Force 32 bit alignment for options and blk_tot_length. */
|
||||
uint8_t pad[2];
|
||||
|
||||
/* Add space for OPTIONS and BLOCK_TOTAL_LENGTH at end of
|
||||
block. These won't be at this position in the structure unless
|
||||
the LE PDU is the full 39 bytes. */
|
||||
uint32_t options;
|
||||
uint32_t blk_tot_length;
|
||||
} pcapng_le_packet;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint64_t ns;
|
||||
union {
|
||||
struct {
|
||||
uint8_t InitA[6];
|
||||
uint8_t AdvA[6];
|
||||
uint8_t AA[4];
|
||||
uint8_t CRCInit[3];
|
||||
uint8_t WinSize;
|
||||
uint8_t WinOffset[2];
|
||||
uint8_t Interval[2];
|
||||
uint8_t Latency[2];
|
||||
uint8_t Timeout[2];
|
||||
uint8_t ChM[5];
|
||||
uint8_t HopSCA;
|
||||
} fields;
|
||||
uint8_t bytes[0];
|
||||
} pdu;
|
||||
} le_ll_connection_info;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
option_header header;
|
||||
le_ll_connection_info connection_info;
|
||||
} le_ll_connection_info_option;
|
||||
|
||||
#define PCAPNG_LE_LL_CONNECTION_INFO 0xd380
|
||||
|
||||
#endif /* PCAPNG_BT_DOT_H */
|
|
@ -0,0 +1,323 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2014 Christopher D. Kilgour techie AT whiterocker.com
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "pcapng.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static option_header padopt = {
|
||||
.option_code = 0xffff,
|
||||
};
|
||||
|
||||
PCAPNG_RESULT pcapng_create( PCAPNG_HANDLE * handle,
|
||||
const char * filename,
|
||||
const option_header * section_options,
|
||||
const size_t section_options_space,
|
||||
const uint16_t link_type,
|
||||
const uint32_t snaplen,
|
||||
const option_header * interface_options,
|
||||
const size_t interface_options_space )
|
||||
{
|
||||
PCAPNG_RESULT retval = PCAPNG_OK;
|
||||
int PGSZ = getpagesize( );
|
||||
size_t zeroes = 0;
|
||||
ssize_t result = -1;
|
||||
|
||||
handle->section_header = NULL;
|
||||
handle->interface_description = NULL;
|
||||
handle->section_header_size = handle->next_section_option_offset =
|
||||
handle->interface_description_size =
|
||||
handle->next_interface_option_offset = 0;
|
||||
|
||||
handle->fd = open( filename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP );
|
||||
if (handle->fd == -1) {
|
||||
switch( errno ) {
|
||||
case EEXIST:
|
||||
retval = PCAPNG_FILE_EXISTS;
|
||||
break;
|
||||
case EMFILE:
|
||||
case ENFILE:
|
||||
retval = PCAPNG_TOO_MANY_FILES_OPEN;
|
||||
break;
|
||||
case ENOMEM:
|
||||
case ENOSPC:
|
||||
retval = PCAPNG_NO_MEMORY;
|
||||
break;
|
||||
default:
|
||||
retval = PCAPNG_FILE_NOT_ALLOWED;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == PCAPNG_OK) {
|
||||
/* section header */
|
||||
const section_header_block shb = {
|
||||
.block_type = BLOCK_TYPE_SECTION_HEADER,
|
||||
.block_total_length = 28,
|
||||
.byte_order_magic = SECTION_HEADER_BYTE_ORDER_MAGIC,
|
||||
.major_version = 1,
|
||||
.minor_version = 0,
|
||||
.section_length = (uint64_t) -1,
|
||||
};
|
||||
handle->section_header_size = sizeof( shb );
|
||||
result = write( handle->fd, &shb, sizeof( shb ) );
|
||||
/* write initial section options */
|
||||
while ((result != -1) &&
|
||||
section_options &&
|
||||
section_options->option_code &&
|
||||
section_options->option_length) {
|
||||
size_t paddedsz = 4*((section_options->option_length+3)/4);
|
||||
zeroes = paddedsz - section_options->option_length;
|
||||
result = write( handle->fd, section_options, 4+section_options->option_length );
|
||||
while ((zeroes > 0) && (result != -1)) {
|
||||
result = write( handle->fd, "\0", 1 );
|
||||
zeroes--;
|
||||
}
|
||||
section_options = (const option_header *) &((uint8_t *)section_options)[4+paddedsz];
|
||||
handle->section_header_size += (4+paddedsz);
|
||||
}
|
||||
handle->next_section_option_offset = handle->section_header_size;
|
||||
}
|
||||
|
||||
if (result == -1) {
|
||||
retval = PCAPNG_FILE_WRITE_ERROR;
|
||||
}
|
||||
else {
|
||||
/* determine the size of section header with desired space */
|
||||
zeroes = (size_t) PGSZ*((handle->section_header_size + 4 +
|
||||
section_options_space + PGSZ - 1)/PGSZ) -
|
||||
handle->section_header_size;
|
||||
handle->section_header_size += zeroes;
|
||||
while ((zeroes > 0) && (result != -1)) {
|
||||
result = write( handle->fd, "\0", 1 );
|
||||
zeroes--;
|
||||
}
|
||||
|
||||
/* mmap the section header */
|
||||
handle->section_header = mmap( NULL, handle->section_header_size,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
handle->fd, 0 );
|
||||
}
|
||||
|
||||
if (retval == PCAPNG_OK) {
|
||||
if (result == -1) {
|
||||
retval = PCAPNG_FILE_WRITE_ERROR;
|
||||
}
|
||||
else if (handle->section_header == MAP_FAILED) {
|
||||
retval = PCAPNG_MMAP_FAILED;
|
||||
}
|
||||
else {
|
||||
/* write the interface header */
|
||||
const interface_description_block idb = {
|
||||
.block_type = BLOCK_TYPE_INTERFACE,
|
||||
.block_total_length = 0,
|
||||
.link_type = link_type,
|
||||
.snaplen = snaplen
|
||||
};
|
||||
handle->interface_description_size = sizeof( idb );
|
||||
result = write( handle->fd, &idb, sizeof( idb ) );
|
||||
|
||||
/* write interface options */
|
||||
while ((result != -1) &&
|
||||
interface_options &&
|
||||
interface_options->option_code &&
|
||||
interface_options->option_length) {
|
||||
size_t paddedsz = 4*((interface_options->option_length+3)/4);
|
||||
zeroes = paddedsz - interface_options->option_length;
|
||||
result = write( handle->fd, interface_options, 4+interface_options->option_length );
|
||||
while ((zeroes > 0) && (result != -1)) {
|
||||
result = write( handle->fd, "\0", 1 );
|
||||
zeroes--;
|
||||
}
|
||||
interface_options = (const option_header *) &((uint8_t *)interface_options)[4+paddedsz];
|
||||
handle->interface_description_size += (4+paddedsz);
|
||||
}
|
||||
handle->next_interface_option_offset = handle->interface_description_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == PCAPNG_OK) {
|
||||
if (result == -1) {
|
||||
retval = PCAPNG_FILE_WRITE_ERROR;
|
||||
}
|
||||
else {
|
||||
/* determine the size of interface description with desired space */
|
||||
zeroes = (size_t) PGSZ*((handle->interface_description_size + 4 +
|
||||
interface_options_space + PGSZ - 1)/PGSZ) -
|
||||
handle->interface_description_size;
|
||||
handle->interface_description_size += zeroes;
|
||||
while ((zeroes > 0) && (result != -1)) {
|
||||
result = write( handle->fd, "\0", 1 );
|
||||
zeroes--;
|
||||
}
|
||||
|
||||
/* mmap the interface description */
|
||||
handle->interface_description = mmap( NULL, handle->interface_description_size,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
handle->fd,
|
||||
handle->section_header_size );
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == PCAPNG_OK) {
|
||||
if (result == -1) {
|
||||
retval = PCAPNG_FILE_WRITE_ERROR;
|
||||
}
|
||||
else if (handle->interface_description == MAP_FAILED) {
|
||||
retval = PCAPNG_MMAP_FAILED;
|
||||
}
|
||||
else {
|
||||
uint8_t * dest = &((uint8_t *)handle->section_header)[handle->next_section_option_offset];
|
||||
padopt.option_length = handle->section_header_size -
|
||||
handle->next_section_option_offset - 12;
|
||||
|
||||
/* Add padding options, update the header sizes. */
|
||||
(void) memcpy( dest, &padopt, sizeof( padopt ) );
|
||||
handle->section_header->block_total_length =
|
||||
(uint32_t) handle->section_header_size;
|
||||
((uint32_t*)handle->section_header)[handle->section_header_size/4-1] =
|
||||
(uint32_t) handle->section_header_size;
|
||||
|
||||
padopt.option_length = handle->interface_description_size -
|
||||
handle->next_interface_option_offset - 12;
|
||||
dest = &((uint8_t *)handle->interface_description)[handle->next_interface_option_offset];
|
||||
(void) memcpy( dest, &padopt, sizeof( padopt ) );
|
||||
handle->interface_description->block_total_length =
|
||||
(uint32_t) handle->interface_description_size;
|
||||
((uint32_t*)handle->interface_description)[handle->interface_description_size/4-1] =
|
||||
(uint32_t) handle->interface_description_size;
|
||||
|
||||
handle->section_header->section_length = (uint64_t) handle->interface_description_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval != PCAPNG_OK) {
|
||||
(void) pcapng_close( handle );
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
PCAPNG_RESULT pcapng_append_section_option( PCAPNG_HANDLE * handle,
|
||||
const option_header * section_option )
|
||||
{
|
||||
PCAPNG_RESULT retval = PCAPNG_OK;
|
||||
if (handle && (handle->fd != -1)) {
|
||||
if (handle->section_header &&
|
||||
(handle->section_header != MAP_FAILED) &&
|
||||
handle->next_section_option_offset &&
|
||||
section_option) {
|
||||
size_t copysz = 4+section_option->option_length;
|
||||
uint8_t * dest = &((uint8_t *)handle->section_header)[handle->next_section_option_offset];
|
||||
(void) memcpy( dest, section_option, copysz );
|
||||
handle->next_section_option_offset += 4*((copysz+3)/4);
|
||||
|
||||
/* update padding option */
|
||||
dest = &((uint8_t *)handle->section_header)[handle->next_section_option_offset];
|
||||
padopt.option_length = handle->section_header_size -
|
||||
handle->next_section_option_offset - 12;
|
||||
(void) memcpy( dest, &padopt, sizeof( padopt ) );
|
||||
}
|
||||
else {
|
||||
retval = PCAPNG_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
retval = PCAPNG_INVALID_HANDLE;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
PCAPNG_RESULT pcapng_append_interface_option( PCAPNG_HANDLE * handle,
|
||||
const option_header * interface_option )
|
||||
{
|
||||
PCAPNG_RESULT retval = PCAPNG_OK;
|
||||
if (handle && (handle->fd != -1)) {
|
||||
if (handle->interface_description &&
|
||||
(handle->interface_description != MAP_FAILED) &&
|
||||
handle->next_interface_option_offset &&
|
||||
interface_option) {
|
||||
size_t copysz = 4+interface_option->option_length;
|
||||
uint8_t * dest = &((uint8_t *)handle->interface_description)[handle->next_interface_option_offset];
|
||||
(void) memcpy( dest, interface_option, copysz );
|
||||
handle->next_interface_option_offset += 4*((copysz+3)/4);
|
||||
|
||||
/* update padding option */
|
||||
dest = &((uint8_t *)handle->interface_description)[handle->next_interface_option_offset];
|
||||
padopt.option_length = handle->interface_description_size -
|
||||
handle->next_interface_option_offset - 12;
|
||||
(void) memcpy( dest, &padopt, sizeof( padopt ) );
|
||||
}
|
||||
else {
|
||||
retval = PCAPNG_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
retval = PCAPNG_INVALID_HANDLE;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
PCAPNG_RESULT pcapng_append_packet( PCAPNG_HANDLE * handle,
|
||||
const enhanced_packet_block * packet )
|
||||
{
|
||||
PCAPNG_RESULT retval = PCAPNG_OK;
|
||||
if (handle && (handle->fd != -1)) {
|
||||
size_t writesz = packet->block_total_length;
|
||||
ssize_t result = write( handle->fd, packet, writesz );
|
||||
if (result == -1) {
|
||||
result = PCAPNG_FILE_WRITE_ERROR;
|
||||
}
|
||||
else {
|
||||
handle->section_header->section_length += writesz;
|
||||
}
|
||||
}
|
||||
else {
|
||||
retval = PCAPNG_INVALID_HANDLE;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
PCAPNG_RESULT pcapng_close( PCAPNG_HANDLE * handle )
|
||||
{
|
||||
if (handle->interface_description &&
|
||||
(handle->interface_description != MAP_FAILED)) {
|
||||
(void) munmap( handle->interface_description,
|
||||
handle->interface_description_size );
|
||||
}
|
||||
if (handle->section_header &&
|
||||
(handle->section_header != MAP_FAILED)) {
|
||||
(void) munmap( handle->section_header,
|
||||
handle->section_header_size );
|
||||
}
|
||||
if (handle->fd != -1) {
|
||||
(void) close( handle->fd );
|
||||
}
|
||||
return PCAPNG_OK;
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2014 Christopher D. Kilgour techie AT whiterocker.com
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#ifndef PCAPNG_DOT_H
|
||||
#define PCAPNG_DOT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint16_t option_code;
|
||||
uint16_t option_length;
|
||||
uint32_t option_value[0];
|
||||
} option_header;
|
||||
|
||||
#define OPT_ENDOFOPT 0
|
||||
#define OPT_COMMENT 1
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t block_type;
|
||||
uint32_t block_total_length;
|
||||
uint32_t byte_order_magic;
|
||||
uint16_t major_version;
|
||||
uint16_t minor_version;
|
||||
uint64_t section_length;
|
||||
option_header options[0];
|
||||
} section_header_block;
|
||||
|
||||
#define SECTION_HEADER_BYTE_ORDER_MAGIC 0x1a2b3c4d
|
||||
|
||||
#define SHB_HARDWARE 2
|
||||
#define SHB_OS 3
|
||||
#define SHB_USERAPPL 4
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t block_type;
|
||||
uint32_t block_total_length;
|
||||
uint16_t link_type;
|
||||
uint16_t reserved;
|
||||
uint32_t snaplen;
|
||||
option_header options[0];
|
||||
} interface_description_block;
|
||||
|
||||
#define IF_NAME 2
|
||||
#define IF_DESCRIPTION 3
|
||||
#define IF_IPV4ADDR 4
|
||||
#define IF_IPV6ADDR 5
|
||||
#define IF_MACADDR 6
|
||||
#define IF_EUIADDR 7
|
||||
#define IF_SPEED 8
|
||||
#define IF_TSRESOL 9
|
||||
#define IF_TZONE 10
|
||||
#define IF_FILTER 11
|
||||
#define IF_OS 12
|
||||
#define IF_FCSLEN 13
|
||||
#define IF_TSOFFSET 14
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t block_type;
|
||||
uint32_t block_total_length;
|
||||
uint32_t interface_id;
|
||||
uint32_t timestamp_high;
|
||||
uint32_t timestamp_low;
|
||||
uint32_t captured_len;
|
||||
uint32_t packet_len;
|
||||
uint32_t packet_data[0];
|
||||
} enhanced_packet_block;
|
||||
|
||||
#define EPB_FLAGS 2
|
||||
#define EPB_HASH 3
|
||||
#define EPB_DROPCOUNT 4
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t block_type;
|
||||
uint32_t block_total_length;
|
||||
uint32_t packet_len;
|
||||
uint32_t packet_data[0];
|
||||
} simple_packet_block;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t block_type;
|
||||
uint32_t block_total_length;
|
||||
uint16_t record_type;
|
||||
uint16_t record_length;
|
||||
uint32_t record_value[0];
|
||||
} name_resolution_block;
|
||||
|
||||
#define NRES_ENDOFRECORD 0
|
||||
#define NRES_IP4RECORD 1
|
||||
#define NRES_IP6RECORD 2
|
||||
|
||||
#define NS_DNSNAME 2
|
||||
#define NS_DNSIP4ADDR 3
|
||||
#define NS_DNSIP6ADDR 4
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t block_type;
|
||||
uint32_t block_total_length;
|
||||
uint32_t interface_id;
|
||||
uint32_t timestamp_high;
|
||||
uint32_t timestamp_low;
|
||||
option_header options[0];
|
||||
} interface_statistics_block;
|
||||
|
||||
#define ISB_STARTTIME 2
|
||||
#define ISB_ENDTIME 3
|
||||
#define ISB_IFRECV 4
|
||||
#define ISB_IFDROP 5
|
||||
#define ISB_FILTERACCEPT 6
|
||||
#define ISB_OSDROP 7
|
||||
#define ISB_USRDELIV 8
|
||||
|
||||
#define BLOCK_TYPE_INTERFACE 0x00000001
|
||||
#define BLOCK_TYPE_SIMPLE_PACKET 0x00000003
|
||||
#define BLOCK_TYPE_NAME_RESOLUTION 0x00000004
|
||||
#define BLOCK_TYPE_INTERFACE_STATISTICS 0x00000005
|
||||
#define BLOCK_TYPE_ENHANCED_PACKET 0x00000006
|
||||
#define BLOCK_TYPE_SECTION_HEADER 0x0a0d0d0a
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
section_header_block * section_header;
|
||||
size_t section_header_size;
|
||||
size_t next_section_option_offset;
|
||||
interface_description_block * interface_description;
|
||||
size_t interface_description_size;
|
||||
size_t next_interface_option_offset;
|
||||
} PCAPNG_HANDLE;
|
||||
|
||||
typedef enum {
|
||||
PCAPNG_OK = 0,
|
||||
PCAPNG_INVALID_HANDLE,
|
||||
PCAPNG_FILE_NOT_ALLOWED,
|
||||
PCAPNG_FILE_EXISTS,
|
||||
PCAPNG_TOO_MANY_FILES_OPEN,
|
||||
PCAPNG_NO_MEMORY,
|
||||
PCAPNG_FILE_WRITE_ERROR,
|
||||
PCAPNG_MMAP_FAILED,
|
||||
} PCAPNG_RESULT;
|
||||
|
||||
/**
|
||||
* Create a new PCAP-NG file and set aside space in the section and
|
||||
* interface headers for options to be recorded/added while packets
|
||||
* are captured.
|
||||
*
|
||||
* @param handle pointer to a handle that is populated by this call
|
||||
* @param filename file to create
|
||||
* @param section_options list of initial section options, can be NULL
|
||||
* @param section_options_space size in bytes dedicated to storing extra section
|
||||
* options; will be rounded up so section header
|
||||
* is an integer number of memory pages
|
||||
* @param link_type
|
||||
* @param snaplen
|
||||
* @param interface_options list of initial interface options, can be NULL
|
||||
* @param interface_options_space size in bytes dedicated to storing extra interface
|
||||
* options; will be rounded up so interface header
|
||||
* is an integer number of memory pages
|
||||
* @returns 0 on success, non zero result code otherwisex
|
||||
*/
|
||||
PCAPNG_RESULT pcapng_create( PCAPNG_HANDLE * handle,
|
||||
const char * filename,
|
||||
const option_header * section_options,
|
||||
const size_t section_options_space,
|
||||
const uint16_t link_type,
|
||||
const uint32_t snaplen,
|
||||
const option_header * interface_options,
|
||||
const size_t interface_options_space );
|
||||
|
||||
PCAPNG_RESULT pcapng_append_section_option( PCAPNG_HANDLE * handle,
|
||||
const option_header * section_option );
|
||||
|
||||
PCAPNG_RESULT pcapng_append_interface_option( PCAPNG_HANDLE * handle,
|
||||
const option_header * interface_option );
|
||||
|
||||
PCAPNG_RESULT pcapng_append_packet( PCAPNG_HANDLE * handle,
|
||||
const enhanced_packet_block * packet );
|
||||
|
||||
PCAPNG_RESULT pcapng_close( PCAPNG_HANDLE * handle );
|
||||
|
||||
#endif /* PCAPNG_DOT_H */
|
|
@ -0,0 +1,4 @@
|
|||
static const uint64_t sw_check_table4[] = {0x000000000ULL, 0x100000000ULL, 0x200000000ULL, 0x300000000ULL, 0x185713da9ULL, 0x085713da9ULL, 0x385713da9ULL, 0x285713da9ULL, 0x30ae27b52ULL, 0x20ae27b52ULL, 0x10ae27b52ULL, 0x00ae27b52ULL, 0x28f9346fbULL, 0x38f9346fbULL, 0x08f9346fbULL, 0x18f9346fbULL, 0x390b5cb0dULL, 0x290b5cb0dULL, 0x190b5cb0dULL, 0x090b5cb0dULL, 0x215c4f6a4ULL, 0x315c4f6a4ULL, 0x015c4f6a4ULL, 0x115c4f6a4ULL, 0x09a57b05fULL, 0x19a57b05fULL, 0x29a57b05fULL, 0x39a57b05fULL, 0x11f268df6ULL, 0x01f268df6ULL, 0x31f268df6ULL, 0x21f268df6ULL, 0x2a41aabb3ULL, 0x3a41aabb3ULL, 0x0a41aabb3ULL, 0x1a41aabb3ULL, 0x3216b961aULL, 0x2216b961aULL, 0x1216b961aULL, 0x0216b961aULL, 0x1aef8d0e1ULL, 0x0aef8d0e1ULL, 0x3aef8d0e1ULL, 0x2aef8d0e1ULL, 0x02b89ed48ULL, 0x12b89ed48ULL, 0x22b89ed48ULL, 0x32b89ed48ULL, 0x134af60beULL, 0x034af60beULL, 0x334af60beULL, 0x234af60beULL, 0x0b1de5d17ULL, 0x1b1de5d17ULL, 0x2b1de5d17ULL, 0x3b1de5d17ULL, 0x23e4d1becULL, 0x33e4d1becULL, 0x03e4d1becULL, 0x13e4d1becULL, 0x3bb3c2645ULL, 0x2bb3c2645ULL, 0x1bb3c2645ULL, 0x0bb3c2645ULL, 0x0cd446acfULL, 0x1cd446acfULL, 0x2cd446acfULL, 0x3cd446acfULL, 0x148355766ULL, 0x048355766ULL, 0x348355766ULL, 0x248355766ULL, 0x3c7a6119dULL, 0x2c7a6119dULL, 0x1c7a6119dULL, 0x0c7a6119dULL, 0x242d72c34ULL, 0x342d72c34ULL, 0x042d72c34ULL, 0x142d72c34ULL, 0x35df1a1c2ULL, 0x25df1a1c2ULL, 0x15df1a1c2ULL, 0x05df1a1c2ULL, 0x2d8809c6bULL, 0x3d8809c6bULL, 0x0d8809c6bULL, 0x1d8809c6bULL, 0x05713da90ULL, 0x15713da90ULL, 0x25713da90ULL, 0x35713da90ULL, 0x1d262e739ULL, 0x0d262e739ULL, 0x3d262e739ULL, 0x2d262e739ULL, 0x2695ec17cULL, 0x3695ec17cULL, 0x0695ec17cULL, 0x1695ec17cULL, 0x3ec2ffcd5ULL, 0x2ec2ffcd5ULL, 0x1ec2ffcd5ULL, 0x0ec2ffcd5ULL, 0x163bcba2eULL, 0x063bcba2eULL, 0x363bcba2eULL, 0x263bcba2eULL, 0x0e6cd8787ULL, 0x1e6cd8787ULL, 0x2e6cd8787ULL, 0x3e6cd8787ULL, 0x1f9eb0a71ULL, 0x0f9eb0a71ULL, 0x3f9eb0a71ULL, 0x2f9eb0a71ULL, 0x07c9a37d8ULL, 0x17c9a37d8ULL, 0x27c9a37d8ULL, 0x37c9a37d8ULL, 0x2f3097123ULL, 0x3f3097123ULL, 0x0f3097123ULL, 0x1f3097123ULL, 0x376784c8aULL, 0x276784c8aULL, 0x176784c8aULL, 0x076784c8aULL, 0x19a88d59eULL, 0x09a88d59eULL, 0x39a88d59eULL, 0x29a88d59eULL, 0x01ff9e837ULL, 0x11ff9e837ULL, 0x21ff9e837ULL, 0x31ff9e837ULL, 0x2906aaeccULL, 0x3906aaeccULL, 0x0906aaeccULL, 0x1906aaeccULL, 0x3151b9365ULL, 0x2151b9365ULL, 0x1151b9365ULL, 0x0151b9365ULL, 0x20a3d1e93ULL, 0x30a3d1e93ULL, 0x00a3d1e93ULL, 0x10a3d1e93ULL, 0x38f4c233aULL, 0x28f4c233aULL, 0x18f4c233aULL, 0x08f4c233aULL, 0x100df65c1ULL, 0x000df65c1ULL, 0x300df65c1ULL, 0x200df65c1ULL, 0x085ae5868ULL, 0x185ae5868ULL, 0x285ae5868ULL, 0x385ae5868ULL, 0x33e927e2dULL, 0x23e927e2dULL, 0x13e927e2dULL, 0x03e927e2dULL, 0x2bbe34384ULL, 0x3bbe34384ULL, 0x0bbe34384ULL, 0x1bbe34384ULL, 0x03470057fULL, 0x13470057fULL, 0x23470057fULL, 0x33470057fULL, 0x1b10138d6ULL, 0x0b10138d6ULL, 0x3b10138d6ULL, 0x2b10138d6ULL, 0x0ae27b520ULL, 0x1ae27b520ULL, 0x2ae27b520ULL, 0x3ae27b520ULL, 0x12b568889ULL, 0x02b568889ULL, 0x32b568889ULL, 0x22b568889ULL, 0x3a4c5ce72ULL, 0x2a4c5ce72ULL, 0x1a4c5ce72ULL, 0x0a4c5ce72ULL, 0x221b4f3dbULL, 0x321b4f3dbULL, 0x021b4f3dbULL, 0x121b4f3dbULL, 0x157ccbf51ULL, 0x057ccbf51ULL, 0x357ccbf51ULL, 0x257ccbf51ULL, 0x0d2bd82f8ULL, 0x1d2bd82f8ULL, 0x2d2bd82f8ULL, 0x3d2bd82f8ULL, 0x25d2ec403ULL, 0x35d2ec403ULL, 0x05d2ec403ULL, 0x15d2ec403ULL, 0x3d85ff9aaULL, 0x2d85ff9aaULL, 0x1d85ff9aaULL, 0x0d85ff9aaULL, 0x2c779745cULL, 0x3c779745cULL, 0x0c779745cULL, 0x1c779745cULL, 0x3420849f5ULL, 0x2420849f5ULL, 0x1420849f5ULL, 0x0420849f5ULL, 0x1cd9b0f0eULL, 0x0cd9b0f0eULL, 0x3cd9b0f0eULL, 0x2cd9b0f0eULL, 0x048ea32a7ULL, 0x148ea32a7ULL, 0x248ea32a7ULL, 0x348ea32a7ULL, 0x3f3d614e2ULL, 0x2f3d614e2ULL, 0x1f3d614e2ULL, 0x0f3d614e2ULL, 0x276a7294bULL, 0x376a7294bULL, 0x076a7294bULL, 0x176a7294bULL, 0x0f9346fb0ULL, 0x1f9346fb0ULL, 0x2f9346fb0ULL, 0x3f9346fb0ULL, 0x17c455219ULL, 0x07c455219ULL, 0x37c455219ULL, 0x27c455219ULL, 0x06363dfefULL, 0x16363dfefULL, 0x26363dfefULL, 0x36363dfefULL, 0x1e612e246ULL, 0x0e612e246ULL, 0x3e612e246ULL, 0x2e612e246ULL, 0x36981a4bdULL, 0x26981a4bdULL, 0x16981a4bdULL, 0x06981a4bdULL, 0x2ecf09914ULL, 0x3ecf09914ULL, 0x0ecf09914ULL, 0x1ecf09914ULL};
|
||||
static const uint64_t sw_check_table5[] = {0x000000000ULL, 0x33511ab3cULL, 0x3ef526bd1ULL, 0x0da43c0edULL, 0x25bd5ea0bULL, 0x16ec44137ULL, 0x1b48781daULL, 0x281962ae6ULL, 0x132dae9bfULL, 0x207cb4283ULL, 0x2dd88826eULL, 0x1e8992952ULL, 0x3690f03b4ULL, 0x05c1ea888ULL, 0x0865d6865ULL, 0x3b34cc359ULL, 0x265b5d37eULL, 0x150a47842ULL, 0x18ae7b8afULL, 0x2bff61393ULL, 0x03e603975ULL, 0x30b719249ULL, 0x3d13252a4ULL, 0x0e423f998ULL, 0x3576f3ac1ULL, 0x0627e91fdULL, 0x0b83d5110ULL, 0x38d2cfa2cULL, 0x10cbad0caULL, 0x239ab7bf6ULL, 0x2e3e8bb1bULL, 0x1d6f91027ULL, 0x14e1a9b55ULL, 0x27b0b3069ULL, 0x2a148f084ULL, 0x194595bb8ULL, 0x315cf715eULL, 0x020deda62ULL, 0x0fa9d1a8fULL, 0x3cf8cb1b3ULL, 0x07cc072eaULL, 0x349d1d9d6ULL, 0x39392193bULL, 0x0a683b207ULL, 0x2271598e1ULL, 0x1120433ddULL, 0x1c847f330ULL, 0x2fd56580cULL, 0x32baf482bULL, 0x01ebee317ULL, 0x0c4fd23faULL, 0x3f1ec88c6ULL, 0x1707aa220ULL, 0x2456b091cULL, 0x29f28c9f1ULL, 0x1aa3962cdULL, 0x21975a194ULL, 0x12c640aa8ULL, 0x1f627ca45ULL, 0x2c3366179ULL, 0x042a04b9fULL, 0x377b1e0a3ULL, 0x3adf2204eULL, 0x098e38b72ULL, 0x29c3536aaULL, 0x1a9249d96ULL, 0x173675d7bULL, 0x24676f647ULL, 0x0c7e0dca1ULL, 0x3f2f1779dULL, 0x328b2b770ULL, 0x01da31c4cULL, 0x3aeefdf15ULL, 0x09bfe7429ULL, 0x041bdb4c4ULL, 0x374ac1ff8ULL, 0x1f53a351eULL, 0x2c02b9e22ULL, 0x21a685ecfULL, 0x12f79f5f3ULL, 0x0f980e5d4ULL, 0x3cc914ee8ULL, 0x316d28e05ULL, 0x023c32539ULL, 0x2a2550fdfULL, 0x19744a4e3ULL, 0x14d07640eULL, 0x27816cf32ULL, 0x1cb5a0c6bULL, 0x2fe4ba757ULL, 0x2240867baULL, 0x11119cc86ULL, 0x3908fe660ULL, 0x0a59e4d5cULL, 0x07fdd8db1ULL, 0x34acc268dULL, 0x3d22fadffULL, 0x0e73e06c3ULL, 0x03d7dc62eULL, 0x3086c6d12ULL, 0x189fa47f4ULL, 0x2bcebecc8ULL, 0x266a82c25ULL, 0x153b98719ULL, 0x2e0f54440ULL, 0x1d5e4ef7cULL, 0x10fa72f91ULL, 0x23ab684adULL, 0x0bb20ae4bULL, 0x38e310577ULL, 0x35472c59aULL, 0x061636ea6ULL, 0x1b79a7e81ULL, 0x2828bd5bdULL, 0x258c81550ULL, 0x16dd9be6cULL, 0x3ec4f948aULL, 0x0d95e3fb6ULL, 0x0031dff5bULL, 0x3360c5467ULL, 0x08540973eULL, 0x3b0513c02ULL, 0x36a12fcefULL, 0x05f0357d3ULL, 0x2de957d35ULL, 0x1eb84d609ULL, 0x131c716e4ULL, 0x204d6bdd8ULL, 0x0bd1b50fdULL, 0x3880afbc1ULL, 0x352493b2cULL, 0x067589010ULL, 0x2e6cebaf6ULL, 0x1d3df11caULL, 0x1099cd127ULL, 0x23c8d7a1bULL, 0x18fc1b942ULL, 0x2bad0127eULL, 0x26093d293ULL, 0x1558279afULL, 0x3d4145349ULL, 0x0e105f875ULL, 0x03b463898ULL, 0x30e5793a4ULL, 0x2d8ae8383ULL, 0x1edbf28bfULL, 0x137fce852ULL, 0x202ed436eULL, 0x0837b6988ULL, 0x3b66ac2b4ULL, 0x36c290259ULL, 0x05938a965ULL, 0x3ea746a3cULL, 0x0df65c100ULL, 0x0052601edULL, 0x33037aad1ULL, 0x1b1a18037ULL, 0x284b02b0bULL, 0x25ef3ebe6ULL, 0x16be240daULL, 0x1f301cba8ULL, 0x2c6106094ULL, 0x21c53a079ULL, 0x129420b45ULL, 0x3a8d421a3ULL, 0x09dc58a9fULL, 0x047864a72ULL, 0x37297e14eULL, 0x0c1db2217ULL, 0x3f4ca892bULL, 0x32e8949c6ULL, 0x01b98e2faULL, 0x29a0ec81cULL, 0x1af1f6320ULL, 0x1755ca3cdULL, 0x2404d08f1ULL, 0x396b418d6ULL, 0x0a3a5b3eaULL, 0x079e67307ULL, 0x34cf7d83bULL, 0x1cd61f2ddULL, 0x2f87059e1ULL, 0x22233990cULL, 0x117223230ULL, 0x2a46ef169ULL, 0x1917f5a55ULL, 0x14b3c9ab8ULL, 0x27e2d3184ULL, 0x0ffbb1b62ULL, 0x3caaab05eULL, 0x310e970b3ULL, 0x025f8db8fULL, 0x2212e6657ULL, 0x1143fcd6bULL, 0x1ce7c0d86ULL, 0x2fb6da6baULL, 0x07afb8c5cULL, 0x34fea2760ULL, 0x395a9e78dULL, 0x0a0b84cb1ULL, 0x313f48fe8ULL, 0x026e524d4ULL, 0x0fca6e439ULL, 0x3c9b74f05ULL, 0x1482165e3ULL, 0x27d30cedfULL, 0x2a7730e32ULL, 0x19262a50eULL, 0x0449bb529ULL, 0x3718a1e15ULL, 0x3abc9def8ULL, 0x09ed875c4ULL, 0x21f4e5f22ULL, 0x12a5ff41eULL, 0x1f01c34f3ULL, 0x2c50d9fcfULL, 0x176415c96ULL, 0x24350f7aaULL, 0x299133747ULL, 0x1ac029c7bULL, 0x32d94b69dULL, 0x018851da1ULL, 0x0c2c6dd4cULL, 0x3f7d77670ULL, 0x36f34fd02ULL, 0x05a25563eULL, 0x0806696d3ULL, 0x3b5773defULL, 0x134e11709ULL, 0x201f0bc35ULL, 0x2dbb37cd8ULL, 0x1eea2d7e4ULL, 0x25dee14bdULL, 0x168ffbf81ULL, 0x1b2bc7f6cULL, 0x287add450ULL, 0x0063bfeb6ULL, 0x3332a558aULL, 0x3e9699567ULL, 0x0dc783e5bULL, 0x10a812e7cULL, 0x23f908540ULL, 0x2e5d345adULL, 0x1d0c2ee91ULL, 0x35154c477ULL, 0x064456f4bULL, 0x0be06afa6ULL, 0x38b17049aULL, 0x0385bc7c3ULL, 0x30d4a6cffULL, 0x3d709ac12ULL, 0x0e218072eULL, 0x2638e2dc8ULL, 0x1569f86f4ULL, 0x18cdc4619ULL, 0x2b9cded25ULL};
|
||||
static const uint64_t sw_check_table6[] = {0x000000000ULL, 0x17a36a1faULL, 0x2f46d43f4ULL, 0x38e5be20eULL, 0x06dabba41ULL, 0x1179d1bbbULL, 0x299c6f9b5ULL, 0x3e3f0584fULL, 0x0db577482ULL, 0x1a161d578ULL, 0x22f3a3776ULL, 0x3550c968cULL, 0x0b6fccec3ULL, 0x1ccca6f39ULL, 0x242918d37ULL, 0x338a72ccdULL, 0x1b6aee904ULL, 0x0cc9848feULL, 0x342c3aaf0ULL, 0x238f50b0aULL, 0x1db055345ULL, 0x0a133f2bfULL, 0x32f6810b1ULL, 0x2555eb14bULL, 0x16df99d86ULL, 0x017cf3c7cULL, 0x39994de72ULL, 0x2e3a27f88ULL, 0x1005227c7ULL, 0x07a64863dULL, 0x3f43f6433ULL, 0x28e09c5c9ULL, 0x36d5dd208ULL, 0x2176b73f2ULL, 0x1993091fcULL, 0x0e3063006ULL, 0x300f66849ULL, 0x27ac0c9b3ULL, 0x1f49b2bbdULL, 0x08ead8a47ULL, 0x3b60aa68aULL, 0x2cc3c0770ULL, 0x14267e57eULL, 0x038514484ULL, 0x3dba11ccbULL, 0x2a197bd31ULL, 0x12fcc5f3fULL, 0x055fafec5ULL, 0x2dbf33b0cULL, 0x3a1c59af6ULL, 0x02f9e78f8ULL, 0x155a8d902ULL, 0x2b658814dULL, 0x3cc6e20b7ULL, 0x04235c2b9ULL, 0x138036343ULL, 0x200a44f8eULL, 0x37a92ee74ULL, 0x0f4c90c7aULL, 0x18effad80ULL, 0x26d0ff5cfULL, 0x317395435ULL, 0x09962b63bULL, 0x1e35417c1ULL, 0x35fca99b9ULL, 0x225fc3843ULL, 0x1aba7da4dULL, 0x0d1917bb7ULL, 0x3326123f8ULL, 0x248578202ULL, 0x1c60c600cULL, 0x0bc3ac1f6ULL, 0x3849ded3bULL, 0x2feab4cc1ULL, 0x170f0aecfULL, 0x00ac60f35ULL, 0x3e936577aULL, 0x29300f680ULL, 0x11d5b148eULL, 0x0676db574ULL, 0x2e96470bdULL, 0x39352d147ULL, 0x01d093349ULL, 0x1673f92b3ULL, 0x284cfcafcULL, 0x3fef96b06ULL, 0x070a28908ULL, 0x10a9428f2ULL, 0x23233043fULL, 0x34805a5c5ULL, 0x0c65e47cbULL, 0x1bc68e631ULL, 0x25f98be7eULL, 0x325ae1f84ULL, 0x0abf5fd8aULL, 0x1d1c35c70ULL, 0x032974bb1ULL, 0x148a1ea4bULL, 0x2c6fa0845ULL, 0x3bccca9bfULL, 0x05f3cf1f0ULL, 0x1250a500aULL, 0x2ab51b204ULL, 0x3d16713feULL, 0x0e9c03f33ULL, 0x193f69ec9ULL, 0x21dad7cc7ULL, 0x3679bdd3dULL, 0x0846b8572ULL, 0x1fe5d2488ULL, 0x27006c686ULL, 0x30a30677cULL, 0x18439a2b5ULL, 0x0fe0f034fULL, 0x37054e141ULL, 0x20a6240bbULL, 0x1e99218f4ULL, 0x093a4b90eULL, 0x31dff5b00ULL, 0x267c9fafaULL, 0x15f6ed637ULL, 0x0255877cdULL, 0x3ab0395c3ULL, 0x2d1353439ULL, 0x132c56c76ULL, 0x048f3cd8cULL, 0x3c6a82f82ULL, 0x2bc9e8e78ULL, 0x33ae40edbULL, 0x240d2af21ULL, 0x1ce894d2fULL, 0x0b4bfecd5ULL, 0x3574fb49aULL, 0x22d791560ULL, 0x1a322f76eULL, 0x0d9145694ULL, 0x3e1b37a59ULL, 0x29b85dba3ULL, 0x115de39adULL, 0x06fe89857ULL, 0x38c18c018ULL, 0x2f62e61e2ULL, 0x1787583ecULL, 0x002432216ULL, 0x28c4ae7dfULL, 0x3f67c4625ULL, 0x07827a42bULL, 0x1021105d1ULL, 0x2e1e15d9eULL, 0x39bd7fc64ULL, 0x0158c1e6aULL, 0x16fbabf90ULL, 0x2571d935dULL, 0x32d2b32a7ULL, 0x0a370d0a9ULL, 0x1d9467153ULL, 0x23ab6291cULL, 0x3408088e6ULL, 0x0cedb6ae8ULL, 0x1b4edcb12ULL, 0x057b9dcd3ULL, 0x12d8f7d29ULL, 0x2a3d49f27ULL, 0x3d9e23eddULL, 0x03a126692ULL, 0x14024c768ULL, 0x2ce7f2566ULL, 0x3b449849cULL, 0x08ceea851ULL, 0x1f6d809abULL, 0x27883eba5ULL, 0x302b54a5fULL, 0x0e1451210ULL, 0x19b73b3eaULL, 0x2152851e4ULL, 0x36f1ef01eULL, 0x1e11735d7ULL, 0x09b21942dULL, 0x3157a7623ULL, 0x26f4cd7d9ULL, 0x18cbc8f96ULL, 0x0f68a2e6cULL, 0x378d1cc62ULL, 0x202e76d98ULL, 0x13a404155ULL, 0x04076e0afULL, 0x3ce2d02a1ULL, 0x2b41ba35bULL, 0x157ebfb14ULL, 0x02ddd5aeeULL, 0x3a386b8e0ULL, 0x2d9b0191aULL, 0x0652e9762ULL, 0x11f183698ULL, 0x29143d496ULL, 0x3eb75756cULL, 0x008852d23ULL, 0x172b38cd9ULL, 0x2fce86ed7ULL, 0x386decf2dULL, 0x0be79e3e0ULL, 0x1c44f421aULL, 0x24a14a014ULL, 0x3302201eeULL, 0x0d3d259a1ULL, 0x1a9e4f85bULL, 0x227bf1a55ULL, 0x35d89bbafULL, 0x1d3807e66ULL, 0x0a9b6df9cULL, 0x327ed3d92ULL, 0x25ddb9c68ULL, 0x1be2bc427ULL, 0x0c41d65ddULL, 0x34a4687d3ULL, 0x230702629ULL, 0x108d70ae4ULL, 0x072e1ab1eULL, 0x3fcba4910ULL, 0x2868ce8eaULL, 0x1657cb0a5ULL, 0x01f4a115fULL, 0x39111f351ULL, 0x2eb2752abULL, 0x30873456aULL, 0x27245e490ULL, 0x1fc1e069eULL, 0x08628a764ULL, 0x365d8ff2bULL, 0x21fee5ed1ULL, 0x191b5bcdfULL, 0x0eb831d25ULL, 0x3d32431e8ULL, 0x2a9129012ULL, 0x12749721cULL, 0x05d7fd3e6ULL, 0x3be8f8ba9ULL, 0x2c4b92a53ULL, 0x14ae2c85dULL, 0x030d469a7ULL, 0x2beddac6eULL, 0x3c4eb0d94ULL, 0x04ab0ef9aULL, 0x130864e60ULL, 0x2d376162fULL, 0x3a940b7d5ULL, 0x0271b55dbULL, 0x15d2df421ULL, 0x2658ad8ecULL, 0x31fbc7916ULL, 0x091e79b18ULL, 0x1ebd13ae2ULL, 0x2082162adULL, 0x37217c357ULL, 0x0fc4c2159ULL, 0x1867a80a3ULL};
|
||||
static const uint64_t sw_check_table7[] = {0x000000000ULL, 0x3f0b9201fULL, 0x264037d97ULL, 0x194ba5d88ULL, 0x14d77c687ULL, 0x2bdcee698ULL, 0x32974bb10ULL, 0x0d9cd9b0fULL, 0x29aef8d0eULL, 0x16a56ad11ULL, 0x0feecf099ULL, 0x30e55d086ULL, 0x3d7984b89ULL, 0x027216b96ULL, 0x1b39b361eULL, 0x243221601ULL, 0x0b0ae27b5ULL, 0x3401707aaULL, 0x2d4ad5a22ULL, 0x124147a3dULL, 0x1fdd9e132ULL, 0x20d60c12dULL, 0x399da9ca5ULL, 0x06963bcbaULL, 0x22a41aabbULL, 0x1daf88aa4ULL, 0x04e42d72cULL, 0x3befbf733ULL, 0x367366c3cULL, 0x0978f4c23ULL, 0x1033511abULL, 0x2f38c31b4ULL, 0x1615c4f6aULL, 0x291e56f75ULL, 0x3055f32fdULL, 0x0f5e612e2ULL, 0x02c2b89edULL, 0x3dc92a9f2ULL, 0x24828f47aULL, 0x1b891d465ULL, 0x3fbb3c264ULL, 0x00b0ae27bULL, 0x19fb0bff3ULL, 0x26f099fecULL, 0x2b6c404e3ULL, 0x1467d24fcULL, 0x0d2c77974ULL, 0x3227e596bULL, 0x1d1f268dfULL, 0x2214b48c0ULL, 0x3b5f11548ULL, 0x045483557ULL, 0x09c85ae58ULL, 0x36c3c8e47ULL, 0x2f886d3cfULL, 0x1083ff3d0ULL, 0x34b1de5d1ULL, 0x0bba4c5ceULL, 0x12f1e9846ULL, 0x2dfa7b859ULL, 0x2066a2356ULL, 0x1f6d30349ULL, 0x062695ec1ULL, 0x392d07edeULL, 0x2c2b89ed4ULL, 0x13201becbULL, 0x0a6bbe343ULL, 0x35602c35cULL, 0x38fcf5853ULL, 0x07f76784cULL, 0x1ebcc25c4ULL, 0x21b7505dbULL, 0x0585713daULL, 0x3a8ee33c5ULL, 0x23c546e4dULL, 0x1cced4e52ULL, 0x11520d55dULL, 0x2e599f542ULL, 0x37123a8caULL, 0x0819a88d5ULL, 0x27216b961ULL, 0x182af997eULL, 0x01615c4f6ULL, 0x3e6ace4e9ULL, 0x33f617fe6ULL, 0x0cfd85ff9ULL, 0x15b620271ULL, 0x2abdb226eULL, 0x0e8f9346fULL, 0x318401470ULL, 0x28cfa49f8ULL, 0x17c4369e7ULL, 0x1a58ef2e8ULL, 0x25537d2f7ULL, 0x3c18d8f7fULL, 0x03134af60ULL, 0x3a3e4d1beULL, 0x0535df1a1ULL, 0x1c7e7ac29ULL, 0x2375e8c36ULL, 0x2ee931739ULL, 0x11e2a3726ULL, 0x08a906aaeULL, 0x37a294ab1ULL, 0x1390b5cb0ULL, 0x2c9b27cafULL, 0x35d082127ULL, 0x0adb10138ULL, 0x0747c9a37ULL, 0x384c5ba28ULL, 0x2107fe7a0ULL, 0x1e0c6c7bfULL, 0x3134af60bULL, 0x0e3f3d614ULL, 0x177498b9cULL, 0x287f0ab83ULL, 0x25e3d308cULL, 0x1ae841093ULL, 0x03a3e4d1bULL, 0x3ca876d04ULL, 0x189a57b05ULL, 0x2791c5b1aULL, 0x3eda60692ULL, 0x01d1f268dULL, 0x0c4d2bd82ULL, 0x3346b9d9dULL, 0x2a0d1c015ULL, 0x15068e00aULL, 0x000000001ULL, 0x3f0b9201eULL, 0x264037d96ULL, 0x194ba5d89ULL, 0x14d77c686ULL, 0x2bdcee699ULL, 0x32974bb11ULL, 0x0d9cd9b0eULL, 0x29aef8d0fULL, 0x16a56ad10ULL, 0x0feecf098ULL, 0x30e55d087ULL, 0x3d7984b88ULL, 0x027216b97ULL, 0x1b39b361fULL, 0x243221600ULL, 0x0b0ae27b4ULL, 0x3401707abULL, 0x2d4ad5a23ULL, 0x124147a3cULL, 0x1fdd9e133ULL, 0x20d60c12cULL, 0x399da9ca4ULL, 0x06963bcbbULL, 0x22a41aabaULL, 0x1daf88aa5ULL, 0x04e42d72dULL, 0x3befbf732ULL, 0x367366c3dULL, 0x0978f4c22ULL, 0x1033511aaULL, 0x2f38c31b5ULL, 0x1615c4f6bULL, 0x291e56f74ULL, 0x3055f32fcULL, 0x0f5e612e3ULL, 0x02c2b89ecULL, 0x3dc92a9f3ULL, 0x24828f47bULL, 0x1b891d464ULL, 0x3fbb3c265ULL, 0x00b0ae27aULL, 0x19fb0bff2ULL, 0x26f099fedULL, 0x2b6c404e2ULL, 0x1467d24fdULL, 0x0d2c77975ULL, 0x3227e596aULL, 0x1d1f268deULL, 0x2214b48c1ULL, 0x3b5f11549ULL, 0x045483556ULL, 0x09c85ae59ULL, 0x36c3c8e46ULL, 0x2f886d3ceULL, 0x1083ff3d1ULL, 0x34b1de5d0ULL, 0x0bba4c5cfULL, 0x12f1e9847ULL, 0x2dfa7b858ULL, 0x2066a2357ULL, 0x1f6d30348ULL, 0x062695ec0ULL, 0x392d07edfULL, 0x2c2b89ed5ULL, 0x13201becaULL, 0x0a6bbe342ULL, 0x35602c35dULL, 0x38fcf5852ULL, 0x07f76784dULL, 0x1ebcc25c5ULL, 0x21b7505daULL, 0x0585713dbULL, 0x3a8ee33c4ULL, 0x23c546e4cULL, 0x1cced4e53ULL, 0x11520d55cULL, 0x2e599f543ULL, 0x37123a8cbULL, 0x0819a88d4ULL, 0x27216b960ULL, 0x182af997fULL, 0x01615c4f7ULL, 0x3e6ace4e8ULL, 0x33f617fe7ULL, 0x0cfd85ff8ULL, 0x15b620270ULL, 0x2abdb226fULL, 0x0e8f9346eULL, 0x318401471ULL, 0x28cfa49f9ULL, 0x17c4369e6ULL, 0x1a58ef2e9ULL, 0x25537d2f6ULL, 0x3c18d8f7eULL, 0x03134af61ULL, 0x3a3e4d1bfULL, 0x0535df1a0ULL, 0x1c7e7ac28ULL, 0x2375e8c37ULL, 0x2ee931738ULL, 0x11e2a3727ULL, 0x08a906aafULL, 0x37a294ab0ULL, 0x1390b5cb1ULL, 0x2c9b27caeULL, 0x35d082126ULL, 0x0adb10139ULL, 0x0747c9a36ULL, 0x384c5ba29ULL, 0x2107fe7a1ULL, 0x1e0c6c7beULL, 0x3134af60aULL, 0x0e3f3d615ULL, 0x177498b9dULL, 0x287f0ab82ULL, 0x25e3d308dULL, 0x1ae841092ULL, 0x03a3e4d1aULL, 0x3ca876d05ULL, 0x189a57b04ULL, 0x2791c5b1bULL, 0x3eda60693ULL, 0x01d1f268cULL, 0x0c4d2bd83ULL, 0x3346b9d9cULL, 0x2a0d1c014ULL, 0x15068e00bULL};
|
|
@ -0,0 +1,960 @@
|
|||
/*
|
||||
Copyright (c) 2003-2014, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef UTHASH_H
|
||||
#define UTHASH_H
|
||||
|
||||
#include <string.h> /* memcmp,strlen */
|
||||
#include <stddef.h> /* ptrdiff_t */
|
||||
#include <stdlib.h> /* exit() */
|
||||
|
||||
/* These macros use decltype or the earlier __typeof GNU extension.
|
||||
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
|
||||
when compiling c++ source) this code uses whatever method is needed
|
||||
or, for VS2008 where neither is available, uses casting workarounds. */
|
||||
#if defined(_MSC_VER) /* MS compiler */
|
||||
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
|
||||
#define DECLTYPE(x) (decltype(x))
|
||||
#else /* VS2008 or older (or VS2010 in C mode) */
|
||||
#define NO_DECLTYPE
|
||||
#define DECLTYPE(x)
|
||||
#endif
|
||||
#elif defined(__BORLANDC__) || defined(__LCC__) || defined(__WATCOMC__)
|
||||
#define NO_DECLTYPE
|
||||
#define DECLTYPE(x)
|
||||
#else /* GNU, Sun and other compilers */
|
||||
#define DECLTYPE(x) (__typeof(x))
|
||||
#endif
|
||||
|
||||
#ifdef NO_DECLTYPE
|
||||
#define DECLTYPE_ASSIGN(dst,src) \
|
||||
do { \
|
||||
char **_da_dst = (char**)(&(dst)); \
|
||||
*_da_dst = (char*)(src); \
|
||||
} while(0)
|
||||
#else
|
||||
#define DECLTYPE_ASSIGN(dst,src) \
|
||||
do { \
|
||||
(dst) = DECLTYPE(dst)(src); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */
|
||||
#if defined (_WIN32)
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1600
|
||||
#include <stdint.h>
|
||||
#elif defined(__WATCOMC__)
|
||||
#include <stdint.h>
|
||||
#else
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
#endif
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define UTHASH_VERSION 1.9.9
|
||||
|
||||
#ifndef uthash_fatal
|
||||
#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
|
||||
#endif
|
||||
#ifndef uthash_malloc
|
||||
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
|
||||
#endif
|
||||
#ifndef uthash_free
|
||||
#define uthash_free(ptr,sz) free(ptr) /* free fcn */
|
||||
#endif
|
||||
|
||||
#ifndef uthash_noexpand_fyi
|
||||
#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
|
||||
#endif
|
||||
#ifndef uthash_expand_fyi
|
||||
#define uthash_expand_fyi(tbl) /* can be defined to log expands */
|
||||
#endif
|
||||
|
||||
/* initial number of buckets */
|
||||
#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
|
||||
#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
|
||||
#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
|
||||
|
||||
/* calculate the element whose hash handle address is hhe */
|
||||
#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
|
||||
|
||||
#define HASH_FIND(hh,head,keyptr,keylen,out) \
|
||||
do { \
|
||||
out=NULL; \
|
||||
if (head) { \
|
||||
unsigned _hf_bkt,_hf_hashv; \
|
||||
HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
|
||||
if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
|
||||
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
|
||||
keyptr,keylen,out); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef HASH_BLOOM
|
||||
#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
|
||||
#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
|
||||
#define HASH_BLOOM_MAKE(tbl) \
|
||||
do { \
|
||||
(tbl)->bloom_nbits = HASH_BLOOM; \
|
||||
(tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
|
||||
if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
|
||||
memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
|
||||
(tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
|
||||
} while (0)
|
||||
|
||||
#define HASH_BLOOM_FREE(tbl) \
|
||||
do { \
|
||||
uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
|
||||
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
|
||||
|
||||
#define HASH_BLOOM_ADD(tbl,hashv) \
|
||||
HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
|
||||
|
||||
#define HASH_BLOOM_TEST(tbl,hashv) \
|
||||
HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
|
||||
|
||||
#else
|
||||
#define HASH_BLOOM_MAKE(tbl)
|
||||
#define HASH_BLOOM_FREE(tbl)
|
||||
#define HASH_BLOOM_ADD(tbl,hashv)
|
||||
#define HASH_BLOOM_TEST(tbl,hashv) (1)
|
||||
#define HASH_BLOOM_BYTELEN 0
|
||||
#endif
|
||||
|
||||
#define HASH_MAKE_TABLE(hh,head) \
|
||||
do { \
|
||||
(head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
|
||||
sizeof(UT_hash_table)); \
|
||||
if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
|
||||
memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
|
||||
(head)->hh.tbl->tail = &((head)->hh); \
|
||||
(head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
|
||||
(head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
|
||||
(head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
|
||||
(head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
|
||||
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
|
||||
if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
|
||||
memset((head)->hh.tbl->buckets, 0, \
|
||||
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
|
||||
HASH_BLOOM_MAKE((head)->hh.tbl); \
|
||||
(head)->hh.tbl->signature = HASH_SIGNATURE; \
|
||||
} while(0)
|
||||
|
||||
#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
|
||||
HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
|
||||
|
||||
#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \
|
||||
do { \
|
||||
replaced=NULL; \
|
||||
HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \
|
||||
if (replaced!=NULL) { \
|
||||
HASH_DELETE(hh,head,replaced); \
|
||||
} \
|
||||
HASH_ADD(hh,head,fieldname,keylen_in,add); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
|
||||
do { \
|
||||
unsigned _ha_bkt; \
|
||||
(add)->hh.next = NULL; \
|
||||
(add)->hh.key = (char*)(keyptr); \
|
||||
(add)->hh.keylen = (unsigned)(keylen_in); \
|
||||
if (!(head)) { \
|
||||
head = (add); \
|
||||
(head)->hh.prev = NULL; \
|
||||
HASH_MAKE_TABLE(hh,head); \
|
||||
} else { \
|
||||
(head)->hh.tbl->tail->next = (add); \
|
||||
(add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
|
||||
(head)->hh.tbl->tail = &((add)->hh); \
|
||||
} \
|
||||
(head)->hh.tbl->num_items++; \
|
||||
(add)->hh.tbl = (head)->hh.tbl; \
|
||||
HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
|
||||
(add)->hh.hashv, _ha_bkt); \
|
||||
HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
|
||||
HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
|
||||
HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
|
||||
HASH_FSCK(hh,head); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
|
||||
do { \
|
||||
bkt = ((hashv) & ((num_bkts) - 1)); \
|
||||
} while(0)
|
||||
|
||||
/* delete "delptr" from the hash table.
|
||||
* "the usual" patch-up process for the app-order doubly-linked-list.
|
||||
* The use of _hd_hh_del below deserves special explanation.
|
||||
* These used to be expressed using (delptr) but that led to a bug
|
||||
* if someone used the same symbol for the head and deletee, like
|
||||
* HASH_DELETE(hh,users,users);
|
||||
* We want that to work, but by changing the head (users) below
|
||||
* we were forfeiting our ability to further refer to the deletee (users)
|
||||
* in the patch-up process. Solution: use scratch space to
|
||||
* copy the deletee pointer, then the latter references are via that
|
||||
* scratch pointer rather than through the repointed (users) symbol.
|
||||
*/
|
||||
#define HASH_DELETE(hh,head,delptr) \
|
||||
do { \
|
||||
struct UT_hash_handle *_hd_hh_del; \
|
||||
if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
|
||||
uthash_free((head)->hh.tbl->buckets, \
|
||||
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
|
||||
HASH_BLOOM_FREE((head)->hh.tbl); \
|
||||
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
|
||||
head = NULL; \
|
||||
} else { \
|
||||
unsigned _hd_bkt; \
|
||||
_hd_hh_del = &((delptr)->hh); \
|
||||
if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
|
||||
(head)->hh.tbl->tail = \
|
||||
(UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
|
||||
(head)->hh.tbl->hho); \
|
||||
} \
|
||||
if ((delptr)->hh.prev) { \
|
||||
((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
|
||||
(head)->hh.tbl->hho))->next = (delptr)->hh.next; \
|
||||
} else { \
|
||||
DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
|
||||
} \
|
||||
if (_hd_hh_del->next) { \
|
||||
((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \
|
||||
(head)->hh.tbl->hho))->prev = \
|
||||
_hd_hh_del->prev; \
|
||||
} \
|
||||
HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
|
||||
HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
|
||||
(head)->hh.tbl->num_items--; \
|
||||
} \
|
||||
HASH_FSCK(hh,head); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
|
||||
#define HASH_FIND_STR(head,findstr,out) \
|
||||
HASH_FIND(hh,head,findstr,(unsigned)strlen(findstr),out)
|
||||
#define HASH_ADD_STR(head,strfield,add) \
|
||||
HASH_ADD(hh,head,strfield[0],strlen(add->strfield),add)
|
||||
#define HASH_REPLACE_STR(head,strfield,add,replaced) \
|
||||
HASH_REPLACE(hh,head,strfield[0],(unsigned)strlen(add->strfield),add,replaced)
|
||||
#define HASH_FIND_INT(head,findint,out) \
|
||||
HASH_FIND(hh,head,findint,sizeof(int),out)
|
||||
#define HASH_ADD_INT(head,intfield,add) \
|
||||
HASH_ADD(hh,head,intfield,sizeof(int),add)
|
||||
#define HASH_REPLACE_INT(head,intfield,add,replaced) \
|
||||
HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)
|
||||
#define HASH_FIND_PTR(head,findptr,out) \
|
||||
HASH_FIND(hh,head,findptr,sizeof(void *),out)
|
||||
#define HASH_ADD_PTR(head,ptrfield,add) \
|
||||
HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
|
||||
#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \
|
||||
HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)
|
||||
#define HASH_DEL(head,delptr) \
|
||||
HASH_DELETE(hh,head,delptr)
|
||||
|
||||
/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
|
||||
* This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
|
||||
*/
|
||||
#ifdef HASH_DEBUG
|
||||
#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
|
||||
#define HASH_FSCK(hh,head) \
|
||||
do { \
|
||||
struct UT_hash_handle *_thh; \
|
||||
if (head) { \
|
||||
unsigned _bkt_i; \
|
||||
unsigned _count; \
|
||||
char *_prev; \
|
||||
_count = 0; \
|
||||
for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
|
||||
unsigned _bkt_count = 0; \
|
||||
_thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
|
||||
_prev = NULL; \
|
||||
while (_thh) { \
|
||||
if (_prev != (char*)(_thh->hh_prev)) { \
|
||||
HASH_OOPS("invalid hh_prev %p, actual %p\n", \
|
||||
_thh->hh_prev, _prev ); \
|
||||
} \
|
||||
_bkt_count++; \
|
||||
_prev = (char*)(_thh); \
|
||||
_thh = _thh->hh_next; \
|
||||
} \
|
||||
_count += _bkt_count; \
|
||||
if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
|
||||
HASH_OOPS("invalid bucket count %u, actual %u\n", \
|
||||
(head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
|
||||
} \
|
||||
} \
|
||||
if (_count != (head)->hh.tbl->num_items) { \
|
||||
HASH_OOPS("invalid hh item count %u, actual %u\n", \
|
||||
(head)->hh.tbl->num_items, _count ); \
|
||||
} \
|
||||
/* traverse hh in app order; check next/prev integrity, count */ \
|
||||
_count = 0; \
|
||||
_prev = NULL; \
|
||||
_thh = &(head)->hh; \
|
||||
while (_thh) { \
|
||||
_count++; \
|
||||
if (_prev !=(char*)(_thh->prev)) { \
|
||||
HASH_OOPS("invalid prev %p, actual %p\n", \
|
||||
_thh->prev, _prev ); \
|
||||
} \
|
||||
_prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
|
||||
_thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
|
||||
(head)->hh.tbl->hho) : NULL ); \
|
||||
} \
|
||||
if (_count != (head)->hh.tbl->num_items) { \
|
||||
HASH_OOPS("invalid app item count %u, actual %u\n", \
|
||||
(head)->hh.tbl->num_items, _count ); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define HASH_FSCK(hh,head)
|
||||
#endif
|
||||
|
||||
/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
|
||||
* the descriptor to which this macro is defined for tuning the hash function.
|
||||
* The app can #include <unistd.h> to get the prototype for write(2). */
|
||||
#ifdef HASH_EMIT_KEYS
|
||||
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
|
||||
do { \
|
||||
unsigned _klen = fieldlen; \
|
||||
write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
|
||||
write(HASH_EMIT_KEYS, keyptr, fieldlen); \
|
||||
} while (0)
|
||||
#else
|
||||
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
|
||||
#endif
|
||||
|
||||
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
|
||||
#ifdef HASH_FUNCTION
|
||||
#define HASH_FCN HASH_FUNCTION
|
||||
#else
|
||||
#define HASH_FCN HASH_JEN
|
||||
#endif
|
||||
|
||||
/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */
|
||||
#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _hb_keylen=keylen; \
|
||||
char *_hb_key=(char*)(key); \
|
||||
(hashv) = 0; \
|
||||
while (_hb_keylen--) { (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; } \
|
||||
bkt = (hashv) & (num_bkts-1); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
|
||||
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
|
||||
#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _sx_i; \
|
||||
char *_hs_key=(char*)(key); \
|
||||
hashv = 0; \
|
||||
for(_sx_i=0; _sx_i < keylen; _sx_i++) \
|
||||
hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while (0)
|
||||
/* FNV-1a variation */
|
||||
#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _fn_i; \
|
||||
char *_hf_key=(char*)(key); \
|
||||
hashv = 2166136261UL; \
|
||||
for(_fn_i=0; _fn_i < keylen; _fn_i++) { \
|
||||
hashv = hashv ^ _hf_key[_fn_i]; \
|
||||
hashv = hashv * 16777619; \
|
||||
} \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _ho_i; \
|
||||
char *_ho_key=(char*)(key); \
|
||||
hashv = 0; \
|
||||
for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
|
||||
hashv += _ho_key[_ho_i]; \
|
||||
hashv += (hashv << 10); \
|
||||
hashv ^= (hashv >> 6); \
|
||||
} \
|
||||
hashv += (hashv << 3); \
|
||||
hashv ^= (hashv >> 11); \
|
||||
hashv += (hashv << 15); \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_JEN_MIX(a,b,c) \
|
||||
do { \
|
||||
a -= b; a -= c; a ^= ( c >> 13 ); \
|
||||
b -= c; b -= a; b ^= ( a << 8 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 13 ); \
|
||||
a -= b; a -= c; a ^= ( c >> 12 ); \
|
||||
b -= c; b -= a; b ^= ( a << 16 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 5 ); \
|
||||
a -= b; a -= c; a ^= ( c >> 3 ); \
|
||||
b -= c; b -= a; b ^= ( a << 10 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 15 ); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _hj_i,_hj_j,_hj_k; \
|
||||
unsigned char *_hj_key=(unsigned char*)(key); \
|
||||
hashv = 0xfeedbeef; \
|
||||
_hj_i = _hj_j = 0x9e3779b9; \
|
||||
_hj_k = (unsigned)(keylen); \
|
||||
while (_hj_k >= 12) { \
|
||||
_hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[2] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[3] << 24 ) ); \
|
||||
_hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[6] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[7] << 24 ) ); \
|
||||
hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[10] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[11] << 24 ) ); \
|
||||
\
|
||||
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
|
||||
\
|
||||
_hj_key += 12; \
|
||||
_hj_k -= 12; \
|
||||
} \
|
||||
hashv += keylen; \
|
||||
switch ( _hj_k ) { \
|
||||
case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
|
||||
case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
|
||||
case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
|
||||
case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
|
||||
case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
|
||||
case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
|
||||
case 5: _hj_j += _hj_key[4]; \
|
||||
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
|
||||
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
|
||||
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
|
||||
case 1: _hj_i += _hj_key[0]; \
|
||||
} \
|
||||
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
/* The Paul Hsieh hash function */
|
||||
#undef get16bits
|
||||
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|
||||
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
|
||||
#define get16bits(d) (*((const uint16_t *) (d)))
|
||||
#endif
|
||||
|
||||
#if !defined (get16bits)
|
||||
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned char *_sfh_key=(unsigned char*)(key); \
|
||||
uint32_t _sfh_tmp, _sfh_len = keylen; \
|
||||
\
|
||||
int _sfh_rem = _sfh_len & 3; \
|
||||
_sfh_len >>= 2; \
|
||||
hashv = 0xcafebabe; \
|
||||
\
|
||||
/* Main loop */ \
|
||||
for (;_sfh_len > 0; _sfh_len--) { \
|
||||
hashv += get16bits (_sfh_key); \
|
||||
_sfh_tmp = (uint32_t)(get16bits (_sfh_key+2)) << 11 ^ hashv; \
|
||||
hashv = (hashv << 16) ^ _sfh_tmp; \
|
||||
_sfh_key += 2*sizeof (uint16_t); \
|
||||
hashv += hashv >> 11; \
|
||||
} \
|
||||
\
|
||||
/* Handle end cases */ \
|
||||
switch (_sfh_rem) { \
|
||||
case 3: hashv += get16bits (_sfh_key); \
|
||||
hashv ^= hashv << 16; \
|
||||
hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)] << 18); \
|
||||
hashv += hashv >> 11; \
|
||||
break; \
|
||||
case 2: hashv += get16bits (_sfh_key); \
|
||||
hashv ^= hashv << 11; \
|
||||
hashv += hashv >> 17; \
|
||||
break; \
|
||||
case 1: hashv += *_sfh_key; \
|
||||
hashv ^= hashv << 10; \
|
||||
hashv += hashv >> 1; \
|
||||
} \
|
||||
\
|
||||
/* Force "avalanching" of final 127 bits */ \
|
||||
hashv ^= hashv << 3; \
|
||||
hashv += hashv >> 5; \
|
||||
hashv ^= hashv << 4; \
|
||||
hashv += hashv >> 17; \
|
||||
hashv ^= hashv << 25; \
|
||||
hashv += hashv >> 6; \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
#ifdef HASH_USING_NO_STRICT_ALIASING
|
||||
/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
|
||||
* For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
|
||||
* MurmurHash uses the faster approach only on CPU's where we know it's safe.
|
||||
*
|
||||
* Note the preprocessor built-in defines can be emitted using:
|
||||
*
|
||||
* gcc -m64 -dM -E - < /dev/null (on gcc)
|
||||
* cc -## a.c (where a.c is a simple test file) (Sun Studio)
|
||||
*/
|
||||
#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86))
|
||||
#define MUR_GETBLOCK(p,i) p[i]
|
||||
#else /* non intel */
|
||||
#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
|
||||
#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1)
|
||||
#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2)
|
||||
#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3)
|
||||
#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
|
||||
#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
|
||||
#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
|
||||
#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
|
||||
#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8))
|
||||
#else /* assume little endian non-intel */
|
||||
#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
|
||||
#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
|
||||
#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8))
|
||||
#endif
|
||||
#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \
|
||||
(MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
|
||||
(MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \
|
||||
MUR_ONE_THREE(p))))
|
||||
#endif
|
||||
#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
|
||||
#define MUR_FMIX(_h) \
|
||||
do { \
|
||||
_h ^= _h >> 16; \
|
||||
_h *= 0x85ebca6b; \
|
||||
_h ^= _h >> 13; \
|
||||
_h *= 0xc2b2ae35l; \
|
||||
_h ^= _h >> 16; \
|
||||
} while(0)
|
||||
|
||||
#define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
const uint8_t *_mur_data = (const uint8_t*)(key); \
|
||||
const int _mur_nblocks = (keylen) / 4; \
|
||||
uint32_t _mur_h1 = 0xf88D5353; \
|
||||
uint32_t _mur_c1 = 0xcc9e2d51; \
|
||||
uint32_t _mur_c2 = 0x1b873593; \
|
||||
uint32_t _mur_k1 = 0; \
|
||||
const uint8_t *_mur_tail; \
|
||||
const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \
|
||||
int _mur_i; \
|
||||
for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \
|
||||
_mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \
|
||||
_mur_k1 *= _mur_c1; \
|
||||
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
|
||||
_mur_k1 *= _mur_c2; \
|
||||
\
|
||||
_mur_h1 ^= _mur_k1; \
|
||||
_mur_h1 = MUR_ROTL32(_mur_h1,13); \
|
||||
_mur_h1 = _mur_h1*5+0xe6546b64; \
|
||||
} \
|
||||
_mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \
|
||||
_mur_k1=0; \
|
||||
switch((keylen) & 3) { \
|
||||
case 3: _mur_k1 ^= _mur_tail[2] << 16; \
|
||||
case 2: _mur_k1 ^= _mur_tail[1] << 8; \
|
||||
case 1: _mur_k1 ^= _mur_tail[0]; \
|
||||
_mur_k1 *= _mur_c1; \
|
||||
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
|
||||
_mur_k1 *= _mur_c2; \
|
||||
_mur_h1 ^= _mur_k1; \
|
||||
} \
|
||||
_mur_h1 ^= (keylen); \
|
||||
MUR_FMIX(_mur_h1); \
|
||||
hashv = _mur_h1; \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
#endif /* HASH_USING_NO_STRICT_ALIASING */
|
||||
|
||||
/* key comparison function; return 0 if keys equal */
|
||||
#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
|
||||
|
||||
/* iterate over items in a known bucket to find desired item */
|
||||
#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
|
||||
do { \
|
||||
if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \
|
||||
else out=NULL; \
|
||||
while (out) { \
|
||||
if ((out)->hh.keylen == keylen_in) { \
|
||||
if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break; \
|
||||
} \
|
||||
if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \
|
||||
else out = NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* add an item to a bucket */
|
||||
#define HASH_ADD_TO_BKT(head,addhh) \
|
||||
do { \
|
||||
head.count++; \
|
||||
(addhh)->hh_next = head.hh_head; \
|
||||
(addhh)->hh_prev = NULL; \
|
||||
if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
|
||||
(head).hh_head=addhh; \
|
||||
if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
|
||||
&& (addhh)->tbl->noexpand != 1) { \
|
||||
HASH_EXPAND_BUCKETS((addhh)->tbl); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* remove an item from a given bucket */
|
||||
#define HASH_DEL_IN_BKT(hh,head,hh_del) \
|
||||
(head).count--; \
|
||||
if ((head).hh_head == hh_del) { \
|
||||
(head).hh_head = hh_del->hh_next; \
|
||||
} \
|
||||
if (hh_del->hh_prev) { \
|
||||
hh_del->hh_prev->hh_next = hh_del->hh_next; \
|
||||
} \
|
||||
if (hh_del->hh_next) { \
|
||||
hh_del->hh_next->hh_prev = hh_del->hh_prev; \
|
||||
}
|
||||
|
||||
/* Bucket expansion has the effect of doubling the number of buckets
|
||||
* and redistributing the items into the new buckets. Ideally the
|
||||
* items will distribute more or less evenly into the new buckets
|
||||
* (the extent to which this is true is a measure of the quality of
|
||||
* the hash function as it applies to the key domain).
|
||||
*
|
||||
* With the items distributed into more buckets, the chain length
|
||||
* (item count) in each bucket is reduced. Thus by expanding buckets
|
||||
* the hash keeps a bound on the chain length. This bounded chain
|
||||
* length is the essence of how a hash provides constant time lookup.
|
||||
*
|
||||
* The calculation of tbl->ideal_chain_maxlen below deserves some
|
||||
* explanation. First, keep in mind that we're calculating the ideal
|
||||
* maximum chain length based on the *new* (doubled) bucket count.
|
||||
* In fractions this is just n/b (n=number of items,b=new num buckets).
|
||||
* Since the ideal chain length is an integer, we want to calculate
|
||||
* ceil(n/b). We don't depend on floating point arithmetic in this
|
||||
* hash, so to calculate ceil(n/b) with integers we could write
|
||||
*
|
||||
* ceil(n/b) = (n/b) + ((n%b)?1:0)
|
||||
*
|
||||
* and in fact a previous version of this hash did just that.
|
||||
* But now we have improved things a bit by recognizing that b is
|
||||
* always a power of two. We keep its base 2 log handy (call it lb),
|
||||
* so now we can write this with a bit shift and logical AND:
|
||||
*
|
||||
* ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
|
||||
*
|
||||
*/
|
||||
#define HASH_EXPAND_BUCKETS(tbl) \
|
||||
do { \
|
||||
unsigned _he_bkt; \
|
||||
unsigned _he_bkt_i; \
|
||||
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
|
||||
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
|
||||
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
|
||||
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
|
||||
if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
|
||||
memset(_he_new_buckets, 0, \
|
||||
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
|
||||
tbl->ideal_chain_maxlen = \
|
||||
(tbl->num_items >> (tbl->log2_num_buckets+1)) + \
|
||||
((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
|
||||
tbl->nonideal_items = 0; \
|
||||
for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
|
||||
{ \
|
||||
_he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
|
||||
while (_he_thh) { \
|
||||
_he_hh_nxt = _he_thh->hh_next; \
|
||||
HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
|
||||
_he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
|
||||
if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
|
||||
tbl->nonideal_items++; \
|
||||
_he_newbkt->expand_mult = _he_newbkt->count / \
|
||||
tbl->ideal_chain_maxlen; \
|
||||
} \
|
||||
_he_thh->hh_prev = NULL; \
|
||||
_he_thh->hh_next = _he_newbkt->hh_head; \
|
||||
if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
|
||||
_he_thh; \
|
||||
_he_newbkt->hh_head = _he_thh; \
|
||||
_he_thh = _he_hh_nxt; \
|
||||
} \
|
||||
} \
|
||||
uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
|
||||
tbl->num_buckets *= 2; \
|
||||
tbl->log2_num_buckets++; \
|
||||
tbl->buckets = _he_new_buckets; \
|
||||
tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
|
||||
(tbl->ineff_expands+1) : 0; \
|
||||
if (tbl->ineff_expands > 1) { \
|
||||
tbl->noexpand=1; \
|
||||
uthash_noexpand_fyi(tbl); \
|
||||
} \
|
||||
uthash_expand_fyi(tbl); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
|
||||
/* Note that HASH_SORT assumes the hash handle name to be hh.
|
||||
* HASH_SRT was added to allow the hash handle name to be passed in. */
|
||||
#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
|
||||
#define HASH_SRT(hh,head,cmpfcn) \
|
||||
do { \
|
||||
unsigned _hs_i; \
|
||||
unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
|
||||
struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
|
||||
if (head) { \
|
||||
_hs_insize = 1; \
|
||||
_hs_looping = 1; \
|
||||
_hs_list = &((head)->hh); \
|
||||
while (_hs_looping) { \
|
||||
_hs_p = _hs_list; \
|
||||
_hs_list = NULL; \
|
||||
_hs_tail = NULL; \
|
||||
_hs_nmerges = 0; \
|
||||
while (_hs_p) { \
|
||||
_hs_nmerges++; \
|
||||
_hs_q = _hs_p; \
|
||||
_hs_psize = 0; \
|
||||
for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
|
||||
_hs_psize++; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
if (! (_hs_q) ) break; \
|
||||
} \
|
||||
_hs_qsize = _hs_insize; \
|
||||
while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
|
||||
if (_hs_psize == 0) { \
|
||||
_hs_e = _hs_q; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
_hs_qsize--; \
|
||||
} else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
|
||||
_hs_e = _hs_p; \
|
||||
if (_hs_p){ \
|
||||
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
|
||||
((void*)((char*)(_hs_p->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
} \
|
||||
_hs_psize--; \
|
||||
} else if (( \
|
||||
cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
|
||||
DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
|
||||
) <= 0) { \
|
||||
_hs_e = _hs_p; \
|
||||
if (_hs_p){ \
|
||||
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
|
||||
((void*)((char*)(_hs_p->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
} \
|
||||
_hs_psize--; \
|
||||
} else { \
|
||||
_hs_e = _hs_q; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
_hs_qsize--; \
|
||||
} \
|
||||
if ( _hs_tail ) { \
|
||||
_hs_tail->next = ((_hs_e) ? \
|
||||
ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
|
||||
} else { \
|
||||
_hs_list = _hs_e; \
|
||||
} \
|
||||
if (_hs_e) { \
|
||||
_hs_e->prev = ((_hs_tail) ? \
|
||||
ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
|
||||
} \
|
||||
_hs_tail = _hs_e; \
|
||||
} \
|
||||
_hs_p = _hs_q; \
|
||||
} \
|
||||
if (_hs_tail){ \
|
||||
_hs_tail->next = NULL; \
|
||||
} \
|
||||
if ( _hs_nmerges <= 1 ) { \
|
||||
_hs_looping=0; \
|
||||
(head)->hh.tbl->tail = _hs_tail; \
|
||||
DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
|
||||
} \
|
||||
_hs_insize *= 2; \
|
||||
} \
|
||||
HASH_FSCK(hh,head); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* This function selects items from one hash into another hash.
|
||||
* The end result is that the selected items have dual presence
|
||||
* in both hashes. There is no copy of the items made; rather
|
||||
* they are added into the new hash through a secondary hash
|
||||
* hash handle that must be present in the structure. */
|
||||
#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
|
||||
do { \
|
||||
unsigned _src_bkt, _dst_bkt; \
|
||||
void *_last_elt=NULL, *_elt; \
|
||||
UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
|
||||
ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
|
||||
if (src) { \
|
||||
for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
|
||||
for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
|
||||
_src_hh; \
|
||||
_src_hh = _src_hh->hh_next) { \
|
||||
_elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
|
||||
if (cond(_elt)) { \
|
||||
_dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
|
||||
_dst_hh->key = _src_hh->key; \
|
||||
_dst_hh->keylen = _src_hh->keylen; \
|
||||
_dst_hh->hashv = _src_hh->hashv; \
|
||||
_dst_hh->prev = _last_elt; \
|
||||
_dst_hh->next = NULL; \
|
||||
if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
|
||||
if (!dst) { \
|
||||
DECLTYPE_ASSIGN(dst,_elt); \
|
||||
HASH_MAKE_TABLE(hh_dst,dst); \
|
||||
} else { \
|
||||
_dst_hh->tbl = (dst)->hh_dst.tbl; \
|
||||
} \
|
||||
HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
|
||||
HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
|
||||
(dst)->hh_dst.tbl->num_items++; \
|
||||
_last_elt = _elt; \
|
||||
_last_elt_hh = _dst_hh; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
HASH_FSCK(hh_dst,dst); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_CLEAR(hh,head) \
|
||||
do { \
|
||||
if (head) { \
|
||||
uthash_free((head)->hh.tbl->buckets, \
|
||||
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
|
||||
HASH_BLOOM_FREE((head)->hh.tbl); \
|
||||
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
|
||||
(head)=NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define HASH_OVERHEAD(hh,head) \
|
||||
((head) ? ( \
|
||||
(size_t)((((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \
|
||||
((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \
|
||||
(sizeof(UT_hash_table)) + \
|
||||
(HASH_BLOOM_BYTELEN)))) : 0)
|
||||
|
||||
#ifdef NO_DECLTYPE
|
||||
#define HASH_ITER(hh,head,el,tmp) \
|
||||
for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \
|
||||
el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
|
||||
#else
|
||||
#define HASH_ITER(hh,head,el,tmp) \
|
||||
for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \
|
||||
el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
|
||||
#endif
|
||||
|
||||
/* obtain a count of items in the hash */
|
||||
#define HASH_COUNT(head) HASH_CNT(hh,head)
|
||||
#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
|
||||
|
||||
typedef struct UT_hash_bucket {
|
||||
struct UT_hash_handle *hh_head;
|
||||
unsigned count;
|
||||
|
||||
/* expand_mult is normally set to 0. In this situation, the max chain length
|
||||
* threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
|
||||
* the bucket's chain exceeds this length, bucket expansion is triggered).
|
||||
* However, setting expand_mult to a non-zero value delays bucket expansion
|
||||
* (that would be triggered by additions to this particular bucket)
|
||||
* until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
|
||||
* (The multiplier is simply expand_mult+1). The whole idea of this
|
||||
* multiplier is to reduce bucket expansions, since they are expensive, in
|
||||
* situations where we know that a particular bucket tends to be overused.
|
||||
* It is better to let its chain length grow to a longer yet-still-bounded
|
||||
* value, than to do an O(n) bucket expansion too often.
|
||||
*/
|
||||
unsigned expand_mult;
|
||||
|
||||
} UT_hash_bucket;
|
||||
|
||||
/* random signature used only to find hash tables in external analysis */
|
||||
#define HASH_SIGNATURE 0xa0111fe1
|
||||
#define HASH_BLOOM_SIGNATURE 0xb12220f2
|
||||
|
||||
typedef struct UT_hash_table {
|
||||
UT_hash_bucket *buckets;
|
||||
unsigned num_buckets, log2_num_buckets;
|
||||
unsigned num_items;
|
||||
struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
|
||||
ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
|
||||
|
||||
/* in an ideal situation (all buckets used equally), no bucket would have
|
||||
* more than ceil(#items/#buckets) items. that's the ideal chain length. */
|
||||
unsigned ideal_chain_maxlen;
|
||||
|
||||
/* nonideal_items is the number of items in the hash whose chain position
|
||||
* exceeds the ideal chain maxlen. these items pay the penalty for an uneven
|
||||
* hash distribution; reaching them in a chain traversal takes >ideal steps */
|
||||
unsigned nonideal_items;
|
||||
|
||||
/* ineffective expands occur when a bucket doubling was performed, but
|
||||
* afterward, more than half the items in the hash had nonideal chain
|
||||
* positions. If this happens on two consecutive expansions we inhibit any
|
||||
* further expansion, as it's not helping; this happens when the hash
|
||||
* function isn't a good fit for the key domain. When expansion is inhibited
|
||||
* the hash will still work, albeit no longer in constant time. */
|
||||
unsigned ineff_expands, noexpand;
|
||||
|
||||
uint32_t signature; /* used only to find hash tables in external analysis */
|
||||
#ifdef HASH_BLOOM
|
||||
uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
|
||||
uint8_t *bloom_bv;
|
||||
char bloom_nbits;
|
||||
#endif
|
||||
|
||||
} UT_hash_table;
|
||||
|
||||
typedef struct UT_hash_handle {
|
||||
struct UT_hash_table *tbl;
|
||||
void *prev; /* prev element in app order */
|
||||
void *next; /* next element in app order */
|
||||
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
|
||||
struct UT_hash_handle *hh_next; /* next hh in bucket order */
|
||||
void *key; /* ptr to enclosing struct's key */
|
||||
unsigned keylen; /* enclosing struct's key len */
|
||||
unsigned hashv; /* result of hash-fcn(key) */
|
||||
} UT_hash_handle;
|
||||
|
||||
#endif /* UTHASH_H */
|
|
@ -0,0 +1,34 @@
|
|||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
# $Id$
|
||||
|
||||
PortSystem 1.0
|
||||
PortGroup cmake 1.0
|
||||
PortGroup github 1.0
|
||||
|
||||
github.setup greatscottgadgets libbtbb 2014-02-R2
|
||||
categories net security
|
||||
platforms darwin
|
||||
maintainers gmail.com:dominicgs
|
||||
license GPL-2+
|
||||
|
||||
description Bluetooth Baseband Decoding Library
|
||||
|
||||
long_description \
|
||||
LibBTBB is a Bluetooth Baseband processing library that supports Basic \
|
||||
Rate and Bluetooth Smart (BLE) packets. It is used by the Ubertooth and \
|
||||
gr-bluetooth packet sniffer implementations.
|
||||
|
||||
homepage https://github.com/greatscottgadgets/libbtbb
|
||||
|
||||
checksums rmd160 0adc5d59e611509cdcf8959be8b6e31704529e48 \
|
||||
sha256 04a187b6f17836437e5f9deecb0b643c75ec0eafce671e373d1d4c13fc104984
|
||||
|
||||
configure.dir ${workpath}/build
|
||||
build.dir ${configure.dir}
|
||||
|
||||
post-extract {
|
||||
file mkdir ${configure.dir}
|
||||
}
|
||||
|
||||
configure.post_args ../${name}-${version}
|
||||
configure.args-append -DPACKAGE_MANAGER=1
|
|
@ -0,0 +1,26 @@
|
|||
require "formula"
|
||||
|
||||
class Libbtbb < Formula
|
||||
homepage "https://github.com/greatscottgadgets/libbtbb"
|
||||
url "https://github.com/greatscottgadgets/libbtbb/archive/2014-02-R2.tar.gz"
|
||||
sha1 "aa94b7d92465704aa647123f11e906491a26d090"
|
||||
version "2014-02-R2"
|
||||
|
||||
head "https://github.com/greatscottgadgets/libbtbb.git"
|
||||
|
||||
option :universal
|
||||
|
||||
depends_on "cmake" => :build
|
||||
depends_on :python
|
||||
|
||||
def install
|
||||
if build.universal?
|
||||
ENV.universal_binary
|
||||
ENV["CMAKE_OSX_ARCHITECTURES"] = Hardware::CPU.universal_archs.as_cmake_arch_flags
|
||||
end
|
||||
mkdir "build" do
|
||||
system "cmake", "..", *std_cmake_args
|
||||
system "make", "install"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,64 @@
|
|||
#
|
||||
#Copyright 2013 Dominic Spill
|
||||
#
|
||||
#This file is part of libbtbb
|
||||
#
|
||||
#This program is free software; you can redistribute it and/or modify
|
||||
#it under the terms of the GNU General Public License as published by
|
||||
#the Free Software Foundation; either version 2, or (at your option)
|
||||
#any later version.
|
||||
#
|
||||
#This program is distributed in the hope that it will be useful,
|
||||
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
#GNU General Public License for more details.
|
||||
#
|
||||
#You should have received a copy of the GNU General Public License
|
||||
#along with libbtbb; see the file COPYING. If not, write to
|
||||
#the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
#Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
Summary: Bluetooth baseband library
|
||||
Name: libbtbb
|
||||
Version: 2013.06
|
||||
Release: 1
|
||||
Summary: A Bluetooth basebad decoding library
|
||||
License: GPLv2
|
||||
URL: http://mooedit.sourceforge.net/
|
||||
Source: %{name}-%{version}.tar.gz
|
||||
|
||||
BuildRequires: cmake gcc python
|
||||
|
||||
Autoreqprov: on
|
||||
|
||||
%description
|
||||
A library for decoding and processing Bluetooth baseband packets.
|
||||
It can be used with any raw bitstream receiver, such as Ubertooth or
|
||||
gr-bluetooth.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
%build
|
||||
cmake -DCMAKE_SKIP_RPATH=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=%{_prefix} \
|
||||
-DBUILD_ROOT=%{buildroot}
|
||||
|
||||
%{__make} %{?jobs:-j%jobs}
|
||||
|
||||
%install
|
||||
%{__make} DESTDIR=%{buildroot} install
|
||||
|
||||
%files
|
||||
%{_prefix}/lib/libbtbb.so
|
||||
%{_prefix}/lib/libbtbb.so.0
|
||||
%{_prefix}/lib/libbtbb.so.0.2.0
|
||||
%{_prefix}/lib/python*
|
||||
%{_bindir}/btaptap
|
||||
%{_libdir}/../include/libbtbb/bluetooth_le_packet.h
|
||||
%{_libdir}/../include/libbtbb/btbb.h
|
||||
%doc COPYING README.md
|
||||
|
||||
%changelog
|
||||
* Thu Jun 06 2013 Dominic Spill <dominincgs@gmail.com> - 0.2.0
|
||||
- First binary release
|
|
@ -0,0 +1,40 @@
|
|||
# Copyright 2013 Dominic Spill
|
||||
#
|
||||
# This file is part of Libbtbb
|
||||
#
|
||||
# GNU Radio is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# GNU Radio is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with GNU Radio; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
project(btbb-python)
|
||||
|
||||
# Check for python installation
|
||||
find_package(PythonInterp)
|
||||
if(NOT PYTHONINTERP_FOUND)
|
||||
return()
|
||||
else()
|
||||
add_subdirectory(pcaptools)
|
||||
endif()
|
||||
|
||||
# Create uninstall target
|
||||
if(NOT libbtbb_all_SOURCE_DIR)
|
||||
configure_file(
|
||||
${PROJECT_SOURCE_DIR}/../cmake/cmake_uninstall.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
|
||||
@ONLY)
|
||||
|
||||
add_custom_target(uninstall
|
||||
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
|
||||
)
|
||||
endif()
|
|
@ -0,0 +1,38 @@
|
|||
# Copyright 2013 Dominic Spill
|
||||
#
|
||||
# This file is part of Libbtbb (pcapdump)
|
||||
#
|
||||
# GNU Radio is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# GNU Radio is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with GNU Radio; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
set(SETUP_PY_IN ${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in)
|
||||
set(SETUP_PY ${CMAKE_CURRENT_BINARY_DIR}/setup.py)
|
||||
set(DEPS ${CMAKE_CURRENT_SOURCE_DIR}/pcapdump/__init__.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/pcapdump/pcapdump.py)
|
||||
set(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/build)
|
||||
|
||||
configure_file(${SETUP_PY_IN} ${SETUP_PY})
|
||||
|
||||
add_custom_command(OUTPUT ${OUTPUT}/timestamp
|
||||
COMMAND ${PYTHON_EXECUTABLE} setup.py build
|
||||
COMMAND ${CMAKE_COMMAND} -E touch ${OUTPUT}/timestamp
|
||||
DEPENDS ${DEPS})
|
||||
|
||||
add_custom_target(pcapdump ALL DEPENDS ${OUTPUT}/timestamp)
|
||||
install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} build -b ${OUTPUT} install --prefix=${BUILD_ROOT}/${CMAKE_INSTALL_PREFIX})")
|
||||
|
||||
add_custom_target(btaptap ALL DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/btaptap)
|
||||
install(PROGRAMS btaptap DESTINATION ${INSTALL_DEFAULT_BINDIR})
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# Copyright 2012 Michael Ossmann, Dominic Spill
|
||||
#
|
||||
# This file is part of Project Ubertooth.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
INSTALL ?= /usr/bin/install
|
||||
PYTHON ?= /usr/bin/env python
|
||||
|
||||
INSTALL_DIR ?= /usr/bin
|
||||
|
||||
EXECUTABLE_FILES = btaptap
|
||||
|
||||
all: pcapdump
|
||||
|
||||
pcapdump:
|
||||
$(PYTHON) setup.py build
|
||||
|
||||
clean:
|
||||
rm -rf build
|
||||
|
||||
install: pcapdump
|
||||
$(PYTHON) setup.py install
|
||||
$(INSTALL) -m 0755 $(EXECUTABLE_FILES) $(INSTALL_DIR)
|
||||
|
||||
.PHONY: all clean install pcapdump
|
|
@ -0,0 +1,20 @@
|
|||
This directory contains supplemental tools for working with pcap files produced
|
||||
by libbtbb. (Actually libbtbb doesn't produce such files by itself at this
|
||||
time, but you can produce them with the Ubertooth tools.
|
||||
|
||||
These tools are not automatically installed as part of the libbtbb
|
||||
installation but can be used right out of this directory or manually installed.
|
||||
|
||||
pcapdump: a Python module for pcap
|
||||
|
||||
Pcapdump us used by btaptap to read and write pcap files. It should work with
|
||||
python 2.4 and above (python 3 support requires using the 2to3 tool).
|
||||
|
||||
|
||||
btaptap: a Bluetooth keyboard sniffer
|
||||
|
||||
Many Bluetooth keyboards operate by default in "boot mode" which features
|
||||
simplified HID messaging that can be interpreted, for example, by a PC BIOS.
|
||||
Some of those keyboards also transmit these messages over unencrypted
|
||||
Bluetooth. This tool can be used to extract keystrokes from such
|
||||
transmissions.
|
|
@ -0,0 +1,520 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2009 Joshua Wright, Michael Ossmann
|
||||
#
|
||||
# This file is part of gr-bluetooth
|
||||
#
|
||||
# gr-bluetooth is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# gr-bluetooth is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with gr-bluetooth; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
import sys
|
||||
import struct
|
||||
import time
|
||||
from pcapdump.pcapdump import *
|
||||
|
||||
DLT_EN10MB = 1
|
||||
DLT_BLUETOOTH_HCI_H4 = 187
|
||||
ELLISYS_CSV_HDR = "\"Depth\",\"Time\",\"Name\",\"Data\"\x0d\x0a"
|
||||
ELLISYS_HID_INPUT = "HID Input 1"
|
||||
USBHID_MAP = {
|
||||
0x04 : "a",
|
||||
0x05 : "b",
|
||||
0x06 : "c",
|
||||
0x07 : "d",
|
||||
0x08 : "e",
|
||||
0x09 : "f",
|
||||
0x0A : "g",
|
||||
0x0B : "h",
|
||||
0x0C : "i",
|
||||
0x0D : "j",
|
||||
0x0E : "k",
|
||||
0x0F : "l",
|
||||
0x10 : "m",
|
||||
0x11 : "n",
|
||||
0x12 : "o",
|
||||
0x13 : "p",
|
||||
0x14 : "q",
|
||||
0x15 : "r",
|
||||
0x16 : "s",
|
||||
0x17 : "t",
|
||||
0x18 : "u",
|
||||
0x19 : "v",
|
||||
0x1A : "w",
|
||||
0x1B : "x",
|
||||
0x1C : "y",
|
||||
0x1D : "z",
|
||||
0x1E : "1",
|
||||
0x1F : "2",
|
||||
0x20 : "3",
|
||||
0x21 : "4",
|
||||
0x22 : "5",
|
||||
0x23 : "6",
|
||||
0x24 : "7",
|
||||
0x25 : "8",
|
||||
0x26 : "9",
|
||||
0x27 : "0",
|
||||
0x28 : "[Return]\n",
|
||||
0x29 : "[Esc]",
|
||||
0x2A : "[Backspace]",
|
||||
0x2B : "[Tab]\t",
|
||||
0x2C : " ",
|
||||
0x2D : "-",
|
||||
0x2E : "=",
|
||||
0x2F : "[",
|
||||
0x30 : "]",
|
||||
0x31 : "\\",
|
||||
0x32 : "#",
|
||||
0x33 : ";",
|
||||
0x34 : "'",
|
||||
0x35 : "[Grave Accent]",
|
||||
0x36 : ",",
|
||||
0x37 : ".",
|
||||
0x38 : "/",
|
||||
0x39 : "[Caps Lock]",
|
||||
0x3A : "[F1]",
|
||||
0x3B : "[F2]",
|
||||
0x3C : "[F3]",
|
||||
0x3D : "[F4]",
|
||||
0x3E : "[F5]",
|
||||
0x3F : "[F6]",
|
||||
0x40 : "[F7]",
|
||||
0x41 : "[F8]",
|
||||
0x42 : "[F9]",
|
||||
0x43 : "[F10]",
|
||||
0x44 : "[F11]",
|
||||
0x45 : "[F12]",
|
||||
0x46 : "[PrintScreen]",
|
||||
0x47 : "[Scroll]",
|
||||
0x48 : "[Pause]",
|
||||
0x49 : "[Insert]",
|
||||
0x4A : "[Home]",
|
||||
0x4B : "[PageUp]",
|
||||
0x4C : "[Delete]",
|
||||
0x4D : "[End]",
|
||||
0x4E : "[PageDown]",
|
||||
0x4F : "[RightArrow]",
|
||||
0x50 : "[LeftArrow]",
|
||||
0x51 : "[DownArrow]",
|
||||
0x52 : "[UpArrow]",
|
||||
0x53 : "[Keypad Num Lock and Clear]",
|
||||
0x54 : "[Keypad /]",
|
||||
0x55 : "[Keypad *]",
|
||||
0x56 : "[Keypad -]",
|
||||
0x57 : "[Keypad +]",
|
||||
0x58 : "[Keypad Enter]\n",
|
||||
0x59 : "[Keypad 1 and End]",
|
||||
0x5A : "[Keypad 2 and Down Arrow]",
|
||||
0x5B : "[Keypad 3 and PageDn]",
|
||||
0x5C : "[Keypad 4 and Left Arrow]",
|
||||
0x5D : "[Keypad 5]",
|
||||
0x5E : "[Keypad 6 and Right Arrow]",
|
||||
0x5F : "[Keypad 7 and Home]",
|
||||
0x60 : "[Keypad 8 and Up Arrow]",
|
||||
0x61 : "[Keypad 9 and PageUp]",
|
||||
0x62 : "[Keypad 0 and Insert]",
|
||||
0x63 : "[Keypad . and Delete]",
|
||||
0x64 : "\\",
|
||||
0x65 : "[WinKey]",
|
||||
0x66 : "[Power9]",
|
||||
0x67 : "[Keypad =]",
|
||||
0x68 : "[F13]",
|
||||
0x69 : "[F14]",
|
||||
0x6A : "[F15]",
|
||||
0x6B : "[F16]",
|
||||
0x6C : "[F17]",
|
||||
0x6D : "[F18]",
|
||||
0x6E : "[F19]",
|
||||
0x6F : "[F20]",
|
||||
0x70 : "[F21]",
|
||||
0x71 : "[F22]",
|
||||
0x72 : "[F23]",
|
||||
0x73 : "[F24]",
|
||||
0x74 : "[Execute]",
|
||||
0x75 : "[Help]",
|
||||
0x76 : "[Menu]",
|
||||
0x77 : "[Select]",
|
||||
0x78 : "[Stop]",
|
||||
0x79 : "[Again]",
|
||||
0x7A : "[Undo]",
|
||||
0x7B : "[Cut]",
|
||||
0x7C : "[Copy]",
|
||||
0x7D : "[Paste]",
|
||||
0x7E : "[Find]",
|
||||
0x7F : "[Mute]",
|
||||
0x80 : "[Volume Up]",
|
||||
0x81 : "[Volume Down]",
|
||||
0x82 : "[Locking Caps Lock]",
|
||||
0x83 : "[Locking Num Lock]",
|
||||
0x84 : "[Locking Scroll Lock]",
|
||||
0x85 : "[Keypad Comma]",
|
||||
0x86 : "[Keypad Equal]",
|
||||
0x87 : "[International1]",
|
||||
0x88 : "[International2]",
|
||||
0x89 : "[International3]",
|
||||
0x8A : "[International4]",
|
||||
0x8B : "[International5]",
|
||||
0x8C : "[International6]",
|
||||
0x8D : "[International7]",
|
||||
0x8E : "[International8]",
|
||||
0x8F : "[International9]",
|
||||
0x90 : "[LANG1]",
|
||||
0x91 : "[LANG2]",
|
||||
0x92 : "[LANG3]",
|
||||
0x93 : "[LANG4]",
|
||||
0x94 : "[LANG5]",
|
||||
0x95 : "[LANG6]",
|
||||
0x96 : "[LANG7]",
|
||||
0x97 : "[LANG8]",
|
||||
0x98 : "[LANG9]",
|
||||
0x99 : "[Alternate Erase]",
|
||||
0x9A : "[SysReq/Attention]",
|
||||
0x9B : "[Cancel]",
|
||||
0x9C : "[Clear]",
|
||||
0x9D : "[Prior]",
|
||||
0x9E : "[Return]\n",
|
||||
0x9F : "[Separator]",
|
||||
0xA0 : "[Out]",
|
||||
0xA1 : "[Oper]",
|
||||
0xA2 : "[Clear/Again]",
|
||||
0xA3 : "[CrSel/Props]",
|
||||
0xA4 : "[ExSel]",
|
||||
0xB0 : "[Keypad 00]",
|
||||
0xB1 : "[Keypad 000]",
|
||||
0xB2 : "[Thousands Separator]",
|
||||
0xB3 : "[Decimal Separator]",
|
||||
0xB4 : "[Currency Unit]",
|
||||
0xB5 : "[Currency Sub-unit]",
|
||||
0xB6 : "[Keypad (]",
|
||||
0xB7 : "[Keypad )]",
|
||||
0xB8 : "[Keypad {]",
|
||||
0xB9 : "[Keypad }]",
|
||||
0xBA : "[Keypad Tab]\t",
|
||||
0xBB : "[Keypad Backspace]",
|
||||
0xBC : "[Keypad A]",
|
||||
0xBD : "[Keypad B]",
|
||||
0xBE : "[Keypad C]",
|
||||
0xBF : "[Keypad D]",
|
||||
0xC0 : "[Keypad E]",
|
||||
0xC1 : "[Keypad F]",
|
||||
0xC2 : "[Keypad XOR]",
|
||||
0xC3 : "[Keypad ^]",
|
||||
0xC4 : "[Keypad %]",
|
||||
0xC5 : "[Keypad <]",
|
||||
0xC6 : "[Keypad >]",
|
||||
0xC7 : "[Keypad &]",
|
||||
0xC8 : "[Keypad &&]",
|
||||
0xC9 : "[Keypad |]",
|
||||
0xCA : "[Keypad ||]",
|
||||
0xCB : "[Keypad :]",
|
||||
0xCC : "[Keypad #]",
|
||||
0xCD : "[Keypad Space]",
|
||||
0xCE : "[Keypad @]",
|
||||
0xCF : "[Keypad !]",
|
||||
0xD0 : "[Keypad Memory Store]",
|
||||
0xD1 : "[Keypad Memory Recall]",
|
||||
0xD2 : "[Keypad Memory Clear]",
|
||||
0xD3 : "[Keypad Memory Add]",
|
||||
0xD4 : "[Keypad Memory Subtract]",
|
||||
0xD5 : "[Keypad Memory Multiply]",
|
||||
0xD6 : "[Keypad Memory Divide]",
|
||||
0xD7 : "[Keypad +/-]",
|
||||
0xD8 : "[Keypad Clear]",
|
||||
0xD9 : "[Keypad Clear Entry]",
|
||||
0xDA : "[Keypad Binary]",
|
||||
0xDB : "[Keypad Octal]",
|
||||
0xDC : "[Keypad Decimal]",
|
||||
0xDD : "[Keypad Hexadecimal]",
|
||||
0xE0 : "[LeftControl]",
|
||||
0xE1 : "[LeftShift]",
|
||||
0xE2 : "[LeftAlt]",
|
||||
0xE3 : "[LeftWinKey]",
|
||||
0xE4 : "[RightControl]",
|
||||
0xE5 : "[RightShift]",
|
||||
0xE6 : "[RightAlt]",
|
||||
0xE7 : "[RightWinKey]"
|
||||
}
|
||||
|
||||
# some keycodes represent different things when Shift is held down
|
||||
USBHID_SHIFT_MAP = {
|
||||
0x04 : "A",
|
||||
0x05 : "B",
|
||||
0x06 : "C",
|
||||
0x07 : "D",
|
||||
0x08 : "E",
|
||||
0x09 : "F",
|
||||
0x0A : "G",
|
||||
0x0B : "H",
|
||||
0x0C : "I",
|
||||
0x0D : "J",
|
||||
0x0E : "K",
|
||||
0x0F : "L",
|
||||
0x10 : "M",
|
||||
0x11 : "N",
|
||||
0x12 : "O",
|
||||
0x13 : "P",
|
||||
0x14 : "Q",
|
||||
0x15 : "R",
|
||||
0x16 : "S",
|
||||
0x17 : "T",
|
||||
0x18 : "U",
|
||||
0x19 : "V",
|
||||
0x1A : "W",
|
||||
0x1B : "X",
|
||||
0x1C : "Y",
|
||||
0x1D : "Z",
|
||||
0x1E : "!",
|
||||
0x1F : "@",
|
||||
0x20 : "#",
|
||||
0x21 : "$",
|
||||
0x22 : "%",
|
||||
0x23 : "^",
|
||||
0x24 : "&",
|
||||
0x25 : "*",
|
||||
0x26 : "(",
|
||||
0x27 : ")",
|
||||
0x2D : "_",
|
||||
0x2E : "+",
|
||||
0x2F : "{",
|
||||
0x30 : "}",
|
||||
0x31 : "|",
|
||||
0x32 : "~",
|
||||
0x33 : ":",
|
||||
0x34 : "\"",
|
||||
0x35 : "~",
|
||||
0x36 : "<",
|
||||
0x37 : ">",
|
||||
0x38 : "?",
|
||||
0x64 : "|"
|
||||
}
|
||||
|
||||
# global variable to track currently depressed keys
|
||||
active_keys = []
|
||||
|
||||
def hid2ascii(scancode, shift):
|
||||
'''
|
||||
Convert the specified scancode value to the ASCII equivalent using the
|
||||
USBHID_MAP list.
|
||||
'''
|
||||
if shift:
|
||||
try:
|
||||
code = USBHID_SHIFT_MAP[scancode]
|
||||
return code
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
code = USBHID_MAP[scancode]
|
||||
except KeyError:
|
||||
return "[Reserved]"
|
||||
return code
|
||||
|
||||
def usage():
|
||||
print >>sys.stderr, "Usage: btaptap [-r pcapfile.pcap | -e ellisysfile.csv] [-c count] [-h]\n"
|
||||
sys.exit(0)
|
||||
|
||||
def parse_l2cap_keydata(l2cappkt):
|
||||
global active_keys
|
||||
|
||||
TRANS_HDR_IN_DATA = 0xA1
|
||||
REPORT_ID_KEYBOARD = 0x01
|
||||
CTRL = 1
|
||||
SHIFT = 2
|
||||
ALT = 4
|
||||
GUI = 8
|
||||
|
||||
# Keyboard keystrokes are only seen in L2CAP packets at least 10 bytes long
|
||||
l2clen = (ord(l2cappkt[1]) << 8) | ord(l2cappkt[0])
|
||||
if l2clen < 10:
|
||||
return
|
||||
|
||||
# Keyboard keystrokes are only carried by Channel ID >= 0x40
|
||||
cid = (ord(l2cappkt[3]) << 8) | ord(l2cappkt[2])
|
||||
if cid < 0x40:
|
||||
return
|
||||
# Ideally we would check for the particular CID for the HID_INTERRUPT
|
||||
# channel, but we don't handle the negotiation (and may not have even
|
||||
# seen it).
|
||||
|
||||
# Transaction Header should indicate input data
|
||||
thdr = ord(l2cappkt[4])
|
||||
if thdr != TRANS_HDR_IN_DATA:
|
||||
return
|
||||
|
||||
# Report ID should indicate this is a keyboard
|
||||
rid = ord(l2cappkt[5])
|
||||
if rid != REPORT_ID_KEYBOARD:
|
||||
return
|
||||
|
||||
# This byte describes modifier key status (one bit per key)
|
||||
mod = ord(l2cappkt[6])
|
||||
|
||||
# We don't care whether left or right modifier keys are pressed, so we
|
||||
# combine the status bits.
|
||||
leftmod = mod & 0x0f
|
||||
rightmod = (mod & 0xf0) >> 4
|
||||
mod = leftmod | rightmod
|
||||
|
||||
# up to six keys can be reported at once
|
||||
keycodes = []
|
||||
#for byte in range(8,14):
|
||||
for byte in range(8,11):
|
||||
keystroke = ord(l2cappkt[byte])
|
||||
if keystroke != 0x00:
|
||||
keycodes.append(keystroke)
|
||||
|
||||
for keystroke in keycodes:
|
||||
# don't repeat keys that are still held down
|
||||
if active_keys.count(keystroke) == 0:
|
||||
|
||||
if (mod & CTRL):
|
||||
sys.stdout.write("CTRL^")
|
||||
if (mod & ALT):
|
||||
sys.stdout.write("ALT^")
|
||||
if (mod & GUI): # e.g. Windows key
|
||||
sys.stdout.write("GUI^")
|
||||
|
||||
sys.stdout.write(hid2ascii(keystroke, mod & SHIFT))
|
||||
|
||||
active_keys = keycodes
|
||||
|
||||
def parse_ellisys_export(exportfile):
|
||||
try:
|
||||
cap = open(exportfile, "r")
|
||||
except (OSError, IOError) as e:
|
||||
print >>sys.stderr, "Unable to open Ellisys capture file."
|
||||
return
|
||||
|
||||
# Check to make sure the CSV file header matches out expectations
|
||||
hdr=cap.readline()
|
||||
if (hdr != ELLISYS_CSV_HDR):
|
||||
print >>sys.stderr, "Invalid CSV file (does not match Ellisys export format)"
|
||||
return
|
||||
|
||||
for packetline in cap.xreadlines():
|
||||
try:
|
||||
(edepth, etime, ename, edata) = packetline.replace('"', '').strip().split(",")
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
# We are only interedted in HID Input data
|
||||
if (ename != ELLISYS_HID_INPUT): continue
|
||||
|
||||
parse_ellisys_keydata(edata)
|
||||
|
||||
def parse_ellisys_keydata(payload):
|
||||
TRANS_HDR_IN_DATA = "\xA1"
|
||||
DEST_CHANNEL_ID = "\x06\x03"
|
||||
|
||||
# Convert space-separated hex into string
|
||||
payload = payload.replace(' ','').decode("hex")
|
||||
|
||||
# The Ellisys CSV file format doesn't give us the L2CAP data, so we fake it here by adding
|
||||
# a 2-byte length field, destination CID, and transaction header
|
||||
packet = chr(len(payload)+1) + "\x00" + DEST_CHANNEL_ID + TRANS_HDR_IN_DATA + payload
|
||||
parse_l2cap_keydata(packet)
|
||||
|
||||
def parse_bb_keydata(packet):
|
||||
|
||||
BTBBHDR_TYPE_MASK = 0x78
|
||||
BTBBHDR_TYPE_SHIFT = 3
|
||||
BTBBHDR_TYPE_DM1 = 3
|
||||
BTBBPAYLOADHDR_LLID_MASK = 0x03
|
||||
BTBBPAYLOADHDR_LLID_SHIFT = 0
|
||||
BTBBPAYLOADHDR_LEN_MASK = 0xF8
|
||||
BTBBPAYLOADHDR_LEN_SHIFT = 3
|
||||
LLID_L2CAP = 2
|
||||
|
||||
# Keyboard keystrokes are only seen in frames at least 40 bytes long
|
||||
if len(packet) < 40:
|
||||
return
|
||||
|
||||
# Keyboard keystrokes are only seen in DM1 frames
|
||||
btbbhdr = packet[20:23]
|
||||
type = (ord(btbbhdr[0]) & BTBBHDR_TYPE_MASK) >> BTBBHDR_TYPE_SHIFT
|
||||
if type != BTBBHDR_TYPE_DM1:
|
||||
return
|
||||
|
||||
# Keyboard keystrokes are only seen in L2CAP packets 14 bytes long
|
||||
btbbpayloadhdr = ord(packet[23])
|
||||
llid = btbbpayloadhdr & (BTBBPAYLOADHDR_LLID_MASK) >> BTBBPAYLOADHDR_LLID_SHIFT
|
||||
l2clen = (btbbpayloadhdr & BTBBPAYLOADHDR_LEN_MASK) >> BTBBPAYLOADHDR_LEN_SHIFT
|
||||
#print "Debug btbbpayloadhdr 0x%02x, llid %d, l2clen %d"%(btbbpayloadhdr, llid, l2clen)
|
||||
if llid != LLID_L2CAP or l2clen < 14:
|
||||
return
|
||||
|
||||
parse_l2cap_keydata(packet[24:38])
|
||||
|
||||
def parse_hci_keydata(packet):
|
||||
|
||||
HCI_TYPE_ACL_DATA = 2
|
||||
|
||||
# Keyboard keystrokes are only seen in frames at least 19 bytes long
|
||||
if len(packet) < 19:
|
||||
return
|
||||
|
||||
# Keyboard keystrokes are only seen in ACL Data frames
|
||||
type = ord(packet[0])
|
||||
if type != HCI_TYPE_ACL_DATA:
|
||||
return
|
||||
|
||||
parse_l2cap_keydata(packet[5:])
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
arg_pcapfile = None
|
||||
arg_ellisysfile = None
|
||||
arg_count = -1
|
||||
packetcount = 0
|
||||
|
||||
while len(sys.argv) > 1:
|
||||
op = sys.argv.pop(1)
|
||||
if op == '-r':
|
||||
arg_pcapfile = sys.argv.pop(1)
|
||||
if op == '-c':
|
||||
arg_count = int(sys.argv.pop(1))
|
||||
if op == '-e':
|
||||
arg_ellisysfile = sys.argv.pop(1)
|
||||
if op == '-h':
|
||||
usage()
|
||||
sys.exit(0)
|
||||
|
||||
if (arg_ellisysfile == None and arg_pcapfile == None):
|
||||
print >>sys.stderr, "Must specify a libpcap capture or an Ellisys CSV file"
|
||||
usage()
|
||||
sys.exit(0)
|
||||
|
||||
if arg_pcapfile != None:
|
||||
cap = PcapReader(arg_pcapfile)
|
||||
|
||||
while arg_count != packetcount:
|
||||
try:
|
||||
(pheader, packet) = cap.pnext()
|
||||
pkttime = pheader[0]
|
||||
packetcount+=1
|
||||
|
||||
if cap.datalink() == DLT_EN10MB:
|
||||
parse_bb_keydata(packet)
|
||||
elif cap.datalink() == DLT_BLUETOOTH_HCI_H4:
|
||||
parse_hci_keydata(packet)
|
||||
else:
|
||||
print >>sys.stderr, "Unsupported libpcap data link layer: %d\n" % cap.datalink()
|
||||
except TypeError: # raised when pnext returns Null (end of capture)
|
||||
break
|
||||
|
||||
cap.close()
|
||||
|
||||
if arg_ellisysfile != None:
|
||||
parse_ellisys_export(arg_ellisysfile)
|
||||
|
||||
print
|
|
@ -0,0 +1,193 @@
|
|||
# Copyright 2009 Joshua Wright
|
||||
#
|
||||
# This file is part of gr-bluetooth
|
||||
#
|
||||
# gr-bluetooth is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# gr-bluetooth is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with gr-bluetooth; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
import struct
|
||||
import time
|
||||
|
||||
PCAPH_MAGIC_NUM = 0xa1b2c3d4
|
||||
PCAPH_VER_MAJOR = 2
|
||||
PCAPH_VER_MINOR = 4
|
||||
PCAPH_THISZONE = 0
|
||||
PCAPH_SIGFIGS = 0
|
||||
PCAPH_SNAPLEN = 65535
|
||||
|
||||
class PcapReader:
|
||||
|
||||
def __init__(self, savefile):
|
||||
'''
|
||||
Opens the specified file, validates a libpcap header is present.
|
||||
@type savefile: String
|
||||
@param savefile: Input libpcap filename to open
|
||||
@rtype: None
|
||||
'''
|
||||
PCAPH_LEN = 24
|
||||
self.__fh = open(savefile, mode='rb')
|
||||
self._pcaphsnaplen = 0
|
||||
header = self.__fh.read(PCAPH_LEN)
|
||||
|
||||
# Read the first 4 bytes for the magic number, determine endianness
|
||||
magicnum = struct.unpack("I", header[0:4])[0]
|
||||
if magicnum != 0xd4c3b2a1:
|
||||
# Little endian
|
||||
self.__endflag = "<"
|
||||
elif magicnum == 0xa1b2c3d4:
|
||||
# Big endign
|
||||
self.__endflag = ">"
|
||||
else:
|
||||
raise Exception('Specified file is not a libpcap capture')
|
||||
|
||||
pcaph = struct.unpack("%sIHHIIII"%self.__endflag, header)
|
||||
if pcaph[1] != PCAPH_VER_MAJOR and pcaph[2] != PCAPH_VER_MINOR \
|
||||
and pcaph[3] != PCAPH_THISZONE and pcaph[4] != PCAPH_SIGFIGS \
|
||||
and pcaph[5] != PCAPH_SNAPLEN:
|
||||
raise Exception('Unsupported pcap header format or version')
|
||||
|
||||
self._pcaphsnaplen = pcaph[5]
|
||||
self._datalink = pcaph[6]
|
||||
|
||||
def datalink(self):
|
||||
return self._datalink
|
||||
|
||||
def close(self):
|
||||
'''
|
||||
Closes the output packet capture; wrapper for pcap_close().
|
||||
@rtype: None
|
||||
'''
|
||||
self.pcap_close()
|
||||
|
||||
def pcap_close(self):
|
||||
'''
|
||||
Closes the output packet capture.
|
||||
@rtype: None
|
||||
'''
|
||||
self.__fh.close()
|
||||
|
||||
def pnext(self):
|
||||
'''
|
||||
Wrapper for pcap_next to mimic method for Daintree SNA
|
||||
'''
|
||||
return self.pcap_next()
|
||||
|
||||
def pcap_next(self):
|
||||
'''
|
||||
Retrieves the next packet from the capture file. Returns a list of
|
||||
[Hdr, packet] where Hdr is a list of [timestamp, snaplen, plen] and
|
||||
packet is a string of the payload content. Returns None at the end
|
||||
of the packet capture.
|
||||
@rtype: List
|
||||
'''
|
||||
# Read the next header block
|
||||
PCAPH_RECLEN = 16
|
||||
rechdrdata = self.__fh.read(PCAPH_RECLEN)
|
||||
|
||||
try:
|
||||
rechdrtmp = struct.unpack("%sIIII"%self.__endflag, rechdrdata)
|
||||
except struct.error:
|
||||
return [None,None]
|
||||
|
||||
rechdr = [
|
||||
float("%s.%s"%(rechdrtmp[0],rechdrtmp[1])),
|
||||
rechdrtmp[2],
|
||||
rechdrtmp[3]
|
||||
]
|
||||
if rechdr[1] > rechdr[2] or rechdr[1] > self._pcaphsnaplen or rechdr[2] > self._pcaphsnaplen:
|
||||
raise Exception('Corrupted or invalid libpcap record header (included length exceeds actual length)')
|
||||
|
||||
# Read the included packet length
|
||||
frame = self.__fh.read(rechdr[1])
|
||||
return [rechdr, frame]
|
||||
|
||||
|
||||
class PcapDumper:
|
||||
|
||||
def __init__(self, datalink, savefile):
|
||||
'''
|
||||
Creates a libpcap file using the specified datalink type.
|
||||
@type datalink: Integer
|
||||
@param datalink: Datalink type, one of DLT_* defined in pcap-bpf.h
|
||||
@type savefile: String
|
||||
@param savefile: Output libpcap filename to open
|
||||
@rtype: None
|
||||
'''
|
||||
self.__fh = open(savefile, mode='wb')
|
||||
self.__fh.write(''.join([
|
||||
struct.pack("I", PCAPH_MAGIC_NUM),
|
||||
struct.pack("H", PCAPH_VER_MAJOR),
|
||||
struct.pack("H", PCAPH_VER_MINOR),
|
||||
struct.pack("I", PCAPH_THISZONE),
|
||||
struct.pack("I", PCAPH_SIGFIGS),
|
||||
struct.pack("I", PCAPH_SNAPLEN),
|
||||
struct.pack("I", datalink)
|
||||
]))
|
||||
|
||||
def pcap_dump(self, packet, ts_sec=None, ts_usec=None, orig_len=None):
|
||||
'''
|
||||
Appends a new packet to the libpcap file. Optionally specify ts_sec
|
||||
and tv_usec for timestamp information, otherwise the current time is
|
||||
used. Specify orig_len if your snaplen is smaller than the entire
|
||||
packet contents.
|
||||
@type ts_sec: Integer
|
||||
@param ts_sec: Timestamp, number of seconds since Unix epoch. Default
|
||||
is the current timestamp.
|
||||
@type ts_usec: Integer
|
||||
@param ts_usec: Timestamp microseconds. Defaults to current timestamp.
|
||||
@type orig_len: Integer
|
||||
@param orig_len: Length of the original packet, used if the packet you
|
||||
are writing is smaller than the original packet. Defaults to the
|
||||
specified packet's length.
|
||||
@type packet: String
|
||||
@param packet: Packet contents
|
||||
@rtype: None
|
||||
'''
|
||||
|
||||
if ts_sec == None or ts_usec == None:
|
||||
# There must be a better way here that I don't know -JW
|
||||
s_sec, s_usec = str(time.time()).split(".")
|
||||
ts_sec = int(s_sec)
|
||||
ts_usec = int(s_usec)
|
||||
|
||||
if orig_len == None:
|
||||
orig_len = len(packet)
|
||||
|
||||
plen = len(packet)
|
||||
|
||||
self.__fh.write(''.join([
|
||||
struct.pack("I", ts_sec),
|
||||
struct.pack("I", ts_usec),
|
||||
struct.pack("I", orig_len),
|
||||
struct.pack("I", plen),
|
||||
packet
|
||||
]))
|
||||
|
||||
return
|
||||
|
||||
|
||||
def close(self):
|
||||
'''
|
||||
Closes the output packet capture; wrapper for pcap_close().
|
||||
@rtype: None
|
||||
'''
|
||||
self.pcap_close()
|
||||
|
||||
def pcap_close(self):
|
||||
'''
|
||||
Closed the output packet capture.
|
||||
@rtype: None
|
||||
'''
|
||||
self.__fh.close()
|
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
pcapdump setup
|
||||
|
||||
Install script for pcapdump
|
||||
|
||||
Usage: python setup.py install
|
||||
|
||||
This file is part of libbtbb
|
||||
Copyright 2012 Dominic Spill
|
||||
"""
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
setup(
|
||||
name = "pcapdump",
|
||||
version = "0.8",
|
||||
description = "A reader and dump utility for Pcap files",
|
||||
author = "Joshua Wright",
|
||||
url = "https://sourceforge.net/projects/libbtbb/",
|
||||
license = "GPL",
|
||||
packages = ['pcapdump'],
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Beta',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||
'Programming Language :: Python',
|
||||
'Operating System :: OS Independent',
|
||||
'Topic :: System :: Networking :: Monitoring',
|
||||
],
|
||||
)
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
pcapdump setup
|
||||
|
||||
Install script for pcapdump
|
||||
|
||||
Usage: python setup.py install
|
||||
|
||||
This file is part of libbtbb
|
||||
Copyright 2012-2013 Dominic Spill
|
||||
"""
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
setup(
|
||||
name = "pcapdump",
|
||||
description = "A reader and dump utility for Pcap files",
|
||||
author = "Joshua Wright",
|
||||
url = "https://sourceforge.net/projects/libbtbb/",
|
||||
license = "GPL",
|
||||
version = '${PACKAGE_VERSION}',
|
||||
package_dir = { '': '${CMAKE_CURRENT_SOURCE_DIR}' },
|
||||
packages = ['pcapdump'],
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Beta',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||
'Programming Language :: Python',
|
||||
'Operating System :: OS Independent',
|
||||
'Topic :: System :: Networking :: Monitoring',
|
||||
],
|
||||
)
|
|
@ -0,0 +1,866 @@
|
|||
"Depth","Time","Name","Data"
|
||||
"0","7.248613000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","7.249863000","HID Input 1","01 00 00 28 00 00 00 00 00"
|
||||
"0","7.251113000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","10.646359000","HID Input 1","01 00 00 28 00 00 00 00 00"
|
||||
"0","10.658858750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","10.681358750","HID Input 1","01 00 00 28 00 00 00 00 00"
|
||||
"0","10.758865000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","10.893876750","HID Input 1","01 00 00 28 00 00 00 00 00"
|
||||
"0","10.983884250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","12.558997750","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","13.009032500","HID Input 1","01 02 00 08 00 00 00 00 00"
|
||||
"0","13.144044625","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","13.189048625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","13.324059500","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","13.414067500","HID Input 1","01 00 00 11 17 00 00 00 00"
|
||||
"0","13.459070500","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","13.504074375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","13.549077875","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","13.594078750","HID Input 1","01 00 00 08 15 00 00 00 00"
|
||||
"0","13.684083375","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","13.729087500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","13.774091625","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","13.864099125","HID Input 1","01 00 00 2C 17 00 00 00 00"
|
||||
"0","13.865349125","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","13.954107375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","13.955357375","HID Input 1","01 00 00 0B 00 00 00 00 00"
|
||||
"0","13.999108000","HID Input 1","01 00 00 0B 08 00 00 00 00"
|
||||
"0","14.044112125","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","14.089117000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","14.134119250","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","14.269131375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","14.270381375","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","14.404141250","HID Input 1","01 02 00 17 00 00 00 00 00"
|
||||
"0","14.449145125","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","14.584155625","HID Input 1","01 02 00 06 00 00 00 00 00"
|
||||
"0","14.674164250","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","14.675414250","HID Input 1","01 02 00 13 00 00 00 00 00"
|
||||
"0","14.809176000","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","14.854179250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","14.855429250","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","14.944184000","HID Input 1","01 00 00 2C 16 00 00 00 00"
|
||||
"0","14.989186250","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","15.034189500","HID Input 1","01 00 00 16 08 00 00 00 00"
|
||||
"0","15.079194375","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","15.169201125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","15.214205250","HID Input 1","01 00 00 14 00 00 00 00 00"
|
||||
"0","15.349217625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","15.350467625","HID Input 1","01 00 00 18 00 00 00 00 00"
|
||||
"0","15.394222125","HID Input 1","01 00 00 18 08 00 00 00 00"
|
||||
"0","15.439224500","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","15.484228000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","15.619238750","HID Input 1","01 00 00 11 06 00 00 00 00"
|
||||
"0","15.620488750","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","15.709246125","HID Input 1","01 00 00 06 08 00 00 00 00"
|
||||
"0","15.710496125","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","15.754250625","HID Input 1","01 00 00 08 2C 00 00 00 00"
|
||||
"0","15.799253375","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","15.844256875","HID Input 1","01 00 00 2C 11 00 00 00 00"
|
||||
"0","15.889262250","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","15.934265375","HID Input 1","01 00 00 11 18 00 00 00 00"
|
||||
"0","15.979269125","HID Input 1","01 00 00 18 00 00 00 00 00"
|
||||
"0","16.024272875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","16.114280375","HID Input 1","01 00 00 10 00 00 00 00 00"
|
||||
"0","16.249286750","HID Input 1","01 00 00 10 05 00 00 00 00"
|
||||
"0","16.294289875","HID Input 1","01 00 00 05 00 00 00 00 00"
|
||||
"0","16.295540000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","16.384296125","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","16.474304000","HID Input 1","01 00 00 08 15 00 00 00 00"
|
||||
"0","16.519306375","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","16.564310750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","16.834333625","HID Input 1","01 20 00 00 00 00 00 00 00"
|
||||
"0","16.924341375","HID Input 1","01 20 00 33 00 00 00 00 00"
|
||||
"0","17.014348625","HID Input 1","01 00 00 33 00 00 00 00 00"
|
||||
"0","17.059353250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","17.194365625","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","17.329375625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","17.330625625","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","17.419381000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","17.420631000","HID Input 1","01 00 00 0B 00 00 00 00 00"
|
||||
"0","17.509384500","HID Input 1","01 00 00 0B 08 00 00 00 00"
|
||||
"0","17.510634375","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","17.554388500","HID Input 1","01 00 00 08 2C 00 00 00 00"
|
||||
"0","17.599393125","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","17.689399750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","17.734403750","HID Input 1","01 00 00 13 00 00 00 00 00"
|
||||
"0","17.869416125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","17.870666125","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","17.959421875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","18.004424875","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","18.184440500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","18.185690625","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","18.274448625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","18.319453375","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","18.409461000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","18.454464375","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","18.544471500","HID Input 1","01 00 00 06 12 00 00 00 00"
|
||||
"0","18.545721500","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","18.634478875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","18.724483000","HID Input 1","01 00 00 0F 00 00 00 00 00"
|
||||
"0","18.814490375","HID Input 1","01 00 00 0F 2C 00 00 00 00"
|
||||
"0","18.859493750","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","18.949501375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","18.994505500","HID Input 1","01 00 00 18 00 00 00 00 00"
|
||||
"0","19.129516125","HID Input 1","01 00 00 18 16 00 00 00 00"
|
||||
"0","19.130766250","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","19.219524125","HID Input 1","01 00 00 16 08 00 00 00 00"
|
||||
"0","19.220773875","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","19.309531000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","19.354534125","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","19.444542000","HID Input 1","01 00 00 16 2C 00 00 00 00"
|
||||
"0","19.445792000","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","19.579553625","HID Input 1","01 00 00 2C 16 00 00 00 00"
|
||||
"0","19.580803625","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","19.669561125","HID Input 1","01 00 00 16 08 00 00 00 00"
|
||||
"0","19.714563625","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","19.759568375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","19.850826125","HID Input 1","01 00 00 14 00 00 00 00 00"
|
||||
"0","19.939581000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","19.940831125","HID Input 1","01 00 00 18 00 00 00 00 00"
|
||||
"0","20.029584250","HID Input 1","01 00 00 18 08 00 00 00 00"
|
||||
"0","20.074588375","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","20.075838500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","20.164594500","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","20.209599125","HID Input 1","01 00 00 11 06 00 00 00 00"
|
||||
"0","20.254602250","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","20.299605750","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","20.344609375","HID Input 1","01 00 00 08 2C 00 00 00 00"
|
||||
"0","20.390862750","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","20.479621250","HID Input 1","01 00 00 2C 11 00 00 00 00"
|
||||
"0","20.480871250","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","20.524623750","HID Input 1","01 00 00 11 18 00 00 00 00"
|
||||
"0","20.569627750","HID Input 1","01 00 00 18 00 00 00 00 00"
|
||||
"0","20.614630625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","20.659633750","HID Input 1","01 00 00 10 00 00 00 00 00"
|
||||
"0","20.794646250","HID Input 1","01 00 00 10 05 00 00 00 00"
|
||||
"0","20.839650500","HID Input 1","01 00 00 05 00 00 00 00 00"
|
||||
"0","20.840900375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","20.929658125","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","20.974661000","HID Input 1","01 00 00 08 15 00 00 00 00"
|
||||
"0","21.019666125","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","21.109672625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","21.110922625","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","21.199678625","HID Input 1","01 00 00 16 2C 00 00 00 00"
|
||||
"0","21.244683250","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","21.289683500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","21.334685625","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","21.379689625","HID Input 1","01 00 00 17 12 00 00 00 00"
|
||||
"0","21.424694000","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","21.425944125","HID Input 1","01 00 00 12 2C 00 00 00 00"
|
||||
"0","21.514699625","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","21.515949625","HID Input 1","01 00 00 2C 04 00 00 00 00"
|
||||
"0","21.604709125","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","21.605959125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","21.694713500","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","21.784722750","HID Input 1","01 00 00 06 0E 00 00 00 00"
|
||||
"0","21.785972625","HID Input 1","01 00 00 0E 00 00 00 00 00"
|
||||
"0","21.829726625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","22.009742500","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","22.010992625","HID Input 1","01 00 00 11 12 00 00 00 00"
|
||||
"0","22.054743875","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","22.144752500","HID Input 1","01 00 00 12 1A 00 00 00 00"
|
||||
"0","22.146002500","HID Input 1","01 00 00 1A 00 00 00 00 00"
|
||||
"0","22.189756125","HID Input 1","01 00 00 1A 08 00 00 00 00"
|
||||
"0","22.191006125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","22.234757000","HID Input 1","01 00 00 0F 00 00 00 00 00"
|
||||
"0","22.414772750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","22.416022875","HID Input 1","01 00 00 07 00 00 00 00 00"
|
||||
"0","22.549782750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","23.269841500","HID Input 1","01 00 00 0A 00 00 00 00 00"
|
||||
"0","23.359849625","HID Input 1","01 00 00 0A 08 00 00 00 00"
|
||||
"0","23.404853625","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","23.494860375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","23.629872625","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","23.764884000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","23.809888500","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","23.899893375","HID Input 1","01 00 00 17 0B 00 00 00 00"
|
||||
"0","23.901143375","HID Input 1","01 00 00 0B 00 00 00 00 00"
|
||||
"0","23.944895500","HID Input 1","01 00 00 0B 08 00 00 00 00"
|
||||
"0","23.989898500","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","24.034901500","HID Input 1","01 00 00 08 2C 00 00 00 00"
|
||||
"0","24.036151500","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","24.079906625","HID Input 1","01 00 00 2C 15 00 00 00 00"
|
||||
"0","24.169913375","HID Input 1","01 00 00 2C 15 08 00 00 00"
|
||||
"0","24.171163250","HID Input 1","01 00 00 2C 08 00 00 00 00"
|
||||
"0","24.214916375","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","24.216166375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","24.259920750","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","24.394933000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","24.439935000","HID Input 1","01 00 00 0C 00 00 00 00 00"
|
||||
"0","24.574946625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","24.619951625","HID Input 1","01 00 00 13 00 00 00 00 00"
|
||||
"0","24.754963125","HID Input 1","01 00 00 13 17 00 00 00 00"
|
||||
"0","24.756213125","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","24.844968875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","24.979979750","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","25.024984125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","25.610031625","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","25.700039125","HID Input 1","01 00 00 12 09 00 00 00 00"
|
||||
"0","25.745042375","HID Input 1","01 00 00 09 00 00 00 00 00"
|
||||
"0","25.790047750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","25.880054250","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","26.015066000","HID Input 1","01 00 00 2C 07 00 00 00 00"
|
||||
"0","26.016316000","HID Input 1","01 00 00 07 00 00 00 00 00"
|
||||
"0","26.105073000","HID Input 1","01 00 00 07 04 00 00 00 00"
|
||||
"0","26.150076625","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","26.240083250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","26.330091750","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","26.375095000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","26.465100250","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","26.555108125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","26.600111000","HID Input 1","01 00 00 37 00 00 00 00 00"
|
||||
"0","26.690120000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","26.735123625","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","26.825130625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","26.915137500","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","26.960140750","HID Input 1","01 02 00 2C 00 00 00 00 00"
|
||||
"0","27.005146375","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","27.095152500","HID Input 1","01 02 00 0C 00 00 00 00 00"
|
||||
"0","27.140156250","HID Input 1","01 00 00 0C 00 00 00 00 00"
|
||||
"0","27.185160250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","27.230164000","HID Input 1","01 00 00 09 00 00 00 00 00"
|
||||
"0","27.275166750","HID Input 1","01 00 00 09 2C 00 00 00 00"
|
||||
"0","27.276416875","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","27.365174625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","27.366424625","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","27.410178500","HID Input 1","01 00 00 17 0B 00 00 00 00"
|
||||
"0","27.455182125","HID Input 1","01 00 00 17 0B 08 00 00 00"
|
||||
"0","27.456432125","HID Input 1","01 00 00 08 0B 00 00 00 00"
|
||||
"0","27.500184375","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","27.545187375","HID Input 1","01 00 00 08 2C 00 00 00 00"
|
||||
"0","27.546437375","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","27.635196750","HID Input 1","01 00 00 2C 04 00 00 00 00"
|
||||
"0","27.680197375","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","27.725198625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","27.815207125","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","27.860210750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","27.950218375","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","28.040226500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","28.085229750","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","28.220240875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","28.221490750","HID Input 1","01 00 00 0E 00 00 00 00 00"
|
||||
"0","28.400254625","HID Input 1","01 00 00 0E 08 00 00 00 00"
|
||||
"0","28.445259750","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","28.446509750","HID Input 1","01 00 00 08 15 00 00 00 00"
|
||||
"0","28.535264375","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","28.536514250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","28.580269250","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","28.715280625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","28.716530750","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","28.805287875","HID Input 137","89 CA 52 04 12 00 00 00 00"
|
||||
"0","28.850291125","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","28.851541125","HID Input 1","01 00 00 12 18 00 00 00 00"
|
||||
"0","28.895294250","HID Input 1","01 00 00 18 00 00 00 00 00"
|
||||
"0","28.985298125","HID Input 1","01 00 00 0F 00 00 00 00 00"
|
||||
"0","29.030302250","HID Input 1","01 00 00 0F 07 00 00 00 00"
|
||||
"0","29.120309375","HID Input 1","01 00 00 07 00 00 00 00 00"
|
||||
"0","29.121559375","HID Input 1","01 00 00 07 2C 00 00 00 00"
|
||||
"0","29.165310625","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","29.210314625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","29.211564625","HID Input 1","01 00 00 13 00 00 00 00 00"
|
||||
"0","29.256569625","HID Input 1","01 00 00 13 15 00 00 00 00"
|
||||
"0","29.300324125","HID Input 1","01 00 00 13 15 08 00 00 00"
|
||||
"0","29.345327500","HID Input 1","01 00 00 13 08 00 00 00 00"
|
||||
"0","29.390330125","HID Input 1","01 00 00 13 00 00 00 00 00"
|
||||
"0","29.391580000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","29.480336875","HID Input 1","01 00 00 07 00 00 00 00 00"
|
||||
"0","29.525340750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","29.570344125","HID Input 1","01 00 00 0C 00 00 00 00 00"
|
||||
"0","29.615347125","HID Input 1","01 00 00 0C 06 00 00 00 00"
|
||||
"0","29.705355375","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","29.706605375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","29.795362750","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","29.885371250","HID Input 1","01 00 00 17 2C 00 00 00 00"
|
||||
"0","29.886621250","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","29.975376500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","30.021631000","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","30.065381000","HID Input 1","01 00 00 17 0B 00 00 00 00"
|
||||
"0","30.066631000","HID Input 1","01 00 00 17 0B 08 00 00 00"
|
||||
"0","30.110383625","HID Input 1","01 00 00 08 0B 00 00 00 00"
|
||||
"0","30.111633625","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","30.155388250","HID Input 1","01 00 00 08 2C 00 00 00 00"
|
||||
"0","30.156638250","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","30.290395125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","30.650425125","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","30.740433125","HID Input 1","01 00 00 16 08 00 00 00 00"
|
||||
"0","30.741683125","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","30.830439500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","30.875442375","HID Input 1","01 00 00 14 00 00 00 00 00"
|
||||
"0","30.965450250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","30.966700250","HID Input 1","01 00 00 18 00 00 00 00 00"
|
||||
"0","31.055458375","HID Input 1","01 00 00 18 08 00 00 00 00"
|
||||
"0","31.056708375","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","31.100461875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","31.190469125","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","31.235472500","HID Input 1","01 00 00 11 06 00 00 00 00"
|
||||
"0","31.236722375","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","31.280477250","HID Input 1","01 00 00 06 08 00 00 00 00"
|
||||
"0","31.325481000","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","31.326731000","HID Input 1","01 00 00 08 2C 00 00 00 00"
|
||||
"0","31.370482500","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","31.460490375","HID Input 1","01 00 00 2C 11 00 00 00 00"
|
||||
"0","31.461740375","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","31.550493750","HID Input 1","01 00 00 11 18 00 00 00 00"
|
||||
"0","31.595498000","HID Input 1","01 00 00 18 00 00 00 00 00"
|
||||
"0","31.640501250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","31.685504375","HID Input 1","01 00 00 10 00 00 00 00 00"
|
||||
"0","31.820516875","HID Input 1","01 00 00 10 05 00 00 00 00"
|
||||
"0","31.865519750","HID Input 1","01 00 00 05 00 00 00 00 00"
|
||||
"0","31.866769750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","31.955528625","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","32.000532625","HID Input 1","01 00 00 08 15 00 00 00 00"
|
||||
"0","32.090540250","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","32.091790000","HID Input 1","01 00 00 15 2C 00 00 00 00"
|
||||
"0","32.135542000","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","32.180545000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","32.225548750","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","32.270553125","HID Input 1","01 00 00 12 09 00 00 00 00"
|
||||
"0","32.315557250","HID Input 1","01 00 00 12 09 2C 00 00 00"
|
||||
"0","32.360559375","HID Input 1","01 00 00 12 2C 00 00 00 00"
|
||||
"0","32.361809375","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","32.450569375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","32.451819250","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","32.495570750","HID Input 1","01 00 00 17 0B 00 00 00 00"
|
||||
"0","32.540573375","HID Input 1","01 00 00 17 0B 08 00 00 00"
|
||||
"0","32.541823375","HID Input 1","01 00 00 08 0B 00 00 00 00"
|
||||
"0","32.585578375","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","32.586828500","HID Input 1","01 00 00 08 2C 00 00 00 00"
|
||||
"0","32.630580250","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","32.675584750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","32.765592000","HID Input 1","01 00 00 13 00 00 00 00 00"
|
||||
"0","32.810591375","HID Input 1","01 00 00 13 04 00 00 00 00"
|
||||
"0","32.900599250","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","32.901849250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","32.945604375","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","32.990608125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","33.035611125","HID Input 1","01 00 00 0E 00 00 00 00 00"
|
||||
"0","33.125619250","HID Input 1","01 00 00 0E 08 00 00 00 00"
|
||||
"0","33.170623500","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","33.171873500","HID Input 1","01 00 00 08 17 00 00 00 00"
|
||||
"0","33.215623875","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","33.260627625","HID Input 1","01 00 00 17 2C 00 00 00 00"
|
||||
"0","33.261877625","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","33.395640500","HID Input 1","01 00 00 2C 05 00 00 00 00"
|
||||
"0","33.396890500","HID Input 1","01 00 00 05 00 00 00 00 00"
|
||||
"0","33.440643625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","33.485647375","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","33.575654500","HID Input 1","01 00 00 08 0C 00 00 00 00"
|
||||
"0","33.576904375","HID Input 1","01 00 00 0C 00 00 00 00 00"
|
||||
"0","33.620658000","HID Input 1","01 00 00 0C 11 00 00 00 00"
|
||||
"0","33.665661500","HID Input 1","01 00 00 0C 11 0A 00 00 00"
|
||||
"0","33.666911500","HID Input 1","01 00 00 0A 11 00 00 00 00"
|
||||
"0","33.755668250","HID Input 1","01 00 00 0A 00 00 00 00 00"
|
||||
"0","33.756918125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","33.800673125","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","33.845676250","HID Input 1","01 00 00 2C 16 00 00 00 00"
|
||||
"0","33.890680625","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","33.935684125","HID Input 1","01 00 00 16 08 00 00 00 00"
|
||||
"0","33.980687375","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","34.025691500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","34.026941500","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","34.115695000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","34.116945000","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","34.205701875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","34.206951875","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","34.295709250","HID Input 1","01 00 00 2C 09 00 00 00 00"
|
||||
"0","34.340712875","HID Input 1","01 00 00 09 00 00 00 00 00"
|
||||
"0","34.385717250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","34.430721000","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","34.520728875","HID Input 1","01 00 00 15 12 00 00 00 00"
|
||||
"0","34.521978750","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","34.565731750","HID Input 1","01 00 00 12 10 00 00 00 00"
|
||||
"0","34.610734500","HID Input 1","01 00 00 12 10 2C 00 00 00"
|
||||
"0","34.700742750","HID Input 1","01 00 00 12 2C 00 00 00 00"
|
||||
"0","34.701992750","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","34.745747375","HID Input 1","01 00 00 2C 17 00 00 00 00"
|
||||
"0","34.746997375","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","34.790748375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","34.791998250","HID Input 1","01 00 00 0B 00 00 00 00 00"
|
||||
"0","34.835752125","HID Input 1","01 00 00 0B 08 00 00 00 00"
|
||||
"0","34.925760250","HID Input 1","01 00 00 0B 08 2C 00 00 00"
|
||||
"0","34.927010125","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","35.060771625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","35.062021500","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","35.105775000","HID Input 1","01 00 00 00 70 20 06 2C 00"
|
||||
"0","35.195782250","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","35.285790375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","35.330794375","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","35.375792625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","35.465801500","HID Input 1","01 00 00 0A 00 00 00 00 00"
|
||||
"0","35.555808750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","35.600812000","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","35.645815375","HID Input 1","01 00 00 08 17 00 00 00 00"
|
||||
"0","35.690818625","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","35.735823875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","35.737074000","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","35.825830875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","35.870835125","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","35.915839250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","35.960841500","HID Input 1","01 00 00 1C 00 00 00 00 00"
|
||||
"0","36.005846000","HID Input 1","01 00 00 1C 16 00 00 00 00"
|
||||
"0","36.050850500","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","36.095853625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","36.140856625","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","36.230864750","HID Input 1","01 00 00 17 08 00 00 00 00"
|
||||
"0","36.232114750","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","36.275867250","HID Input 1","01 00 00 08 10 00 00 00 00"
|
||||
"0","36.320869875","HID Input 1","01 00 00 10 00 00 00 00 00"
|
||||
"0","36.365874125","HID Input 1","01 00 00 10 2C 00 00 00 00"
|
||||
"0","36.410877625","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","36.500885125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","36.502135125","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","36.545889500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","36.590893875","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","36.635894625","HID Input 1","01 00 00 12 2C 00 00 00 00"
|
||||
"0","36.680895625","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","36.682145625","HID Input 1","01 00 00 2C 17 00 00 00 00"
|
||||
"0","36.725899500","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","36.770904625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","36.815908250","HID Input 1","01 00 00 0B 00 00 00 00 00"
|
||||
"0","36.860910750","HID Input 1","01 00 00 0B 08 00 00 00 00"
|
||||
"0","36.905914625","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","36.907164500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","36.950917500","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","36.995921250","HID Input 1","01 00 00 2C 15 00 00 00 00"
|
||||
"0","37.040924750","HID Input 1","01 00 00 2C 15 08 00 00 00"
|
||||
"0","37.085929000","HID Input 1","01 00 00 08 15 00 00 00 00"
|
||||
"0","37.087179000","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","37.130933125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","37.220940750","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","37.265944250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","37.310947000","HID Input 1","01 00 00 0F 00 00 00 00 00"
|
||||
"0","37.355951750","HID Input 1","01 00 00 0F 2C 00 00 00 00"
|
||||
"0","37.445958625","HID Input 1","01 00 00 0F 2C 16 00 00 00"
|
||||
"0","37.447208625","HID Input 1","01 00 00 16 2C 00 00 00 00"
|
||||
"0","37.490961375","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","37.535965375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","37.580968750","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","37.625971750","HID Input 1","01 00 00 08 15 00 00 00 00"
|
||||
"0","37.670975375","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","37.672225500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","37.760984625","HID Input 1","01 00 00 19 00 00 00 00 00"
|
||||
"0","37.805989000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","37.850992125","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","37.940995250","HID Input 1","01 00 00 08 15 00 00 00 00"
|
||||
"0","37.985997750","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","37.987247625","HID Input 1","01 00 00 15 2C 00 00 00 00"
|
||||
"0","38.031002125","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","38.121009750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","38.122259750","HID Input 1","01 00 00 07 00 00 00 00 00"
|
||||
"0","38.166013250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","38.167263250","HID Input 1","01 00 00 18 00 00 00 00 00"
|
||||
"0","38.256020625","HID Input 1","01 00 00 18 15 00 00 00 00"
|
||||
"0","38.302274625","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","38.346028500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","38.391031375","HID Input 1","01 00 00 0C 00 00 00 00 00"
|
||||
"0","38.436035125","HID Input 1","01 00 00 0C 11 00 00 00 00"
|
||||
"0","38.481040125","HID Input 1","01 00 00 0C 11 0A 00 00 00"
|
||||
"0","38.482290125","HID Input 1","01 00 00 0C 11 0A 2C 00 00"
|
||||
"0","38.526041625","HID Input 1","01 00 00 0C 11 2C 00 00 00"
|
||||
"0","38.527291500","HID Input 1","01 00 00 2C 11 00 00 00 00"
|
||||
"0","38.571045500","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","38.616049125","HID Input 1","01 00 00 2C 17 00 00 00 00"
|
||||
"0","38.617299125","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","38.661052375","HID Input 1","01 00 00 17 0B 00 00 00 00"
|
||||
"0","38.706055375","HID Input 1","01 00 00 17 0B 08 00 00 00"
|
||||
"0","38.707306500","HID Input 1","01 00 00 08 0B 00 00 00 00"
|
||||
"0","38.751058750","HID Input 1","01 00 00 08 0B 2C 00 00 00"
|
||||
"0","38.796062750","HID Input 1","01 00 00 08 2C 00 00 00 00"
|
||||
"0","38.797312875","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","38.886069250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","38.931073625","HID Input 1","01 00 00 0C 00 00 00 00 00"
|
||||
"0","38.976077250","HID Input 1","01 00 00 0C 11 00 00 00 00"
|
||||
"0","39.066085000","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","39.156092000","HID Input 1","01 00 00 11 0C 00 00 00 00"
|
||||
"0","39.157342000","HID Input 1","01 00 00 0C 00 00 00 00 00"
|
||||
"0","39.246096250","HID Input 1","01 00 00 0C 17 00 00 00 00"
|
||||
"0","39.247346125","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","39.291099375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","39.336103000","HID Input 1","01 00 00 0C 00 00 00 00 00"
|
||||
"0","39.426111000","HID Input 1","01 00 00 0C 04 00 00 00 00"
|
||||
"0","39.427361000","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","39.516119250","HID Input 1","01 00 00 04 0F 00 00 00 00"
|
||||
"0","39.517369250","HID Input 1","01 00 00 0F 00 00 00 00 00"
|
||||
"0","39.606125250","HID Input 1","01 00 00 0F 2C 00 00 00 00"
|
||||
"0","39.607375250","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","39.651128500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","39.741136750","HID Input 1","01 00 00 0B 00 00 00 00 00"
|
||||
"0","39.831143875","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","39.876147375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","39.921152375","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","39.966155750","HID Input 1","01 00 00 11 07 00 00 00 00"
|
||||
"0","40.056163750","HID Input 1","01 00 00 07 00 00 00 00 00"
|
||||
"0","40.057413750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","40.146169625","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","40.236177500","HID Input 1","01 00 00 16 0B 00 00 00 00"
|
||||
"0","40.237427500","HID Input 1","01 00 00 0B 00 00 00 00 00"
|
||||
"0","40.327434250","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","40.461194250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","40.506195750","HID Input 1","01 00 00 0E 00 00 00 00 00"
|
||||
"0","40.597453125","HID Input 1","01 00 00 0E 08 00 00 00 00"
|
||||
"0","40.641202375","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","40.731211125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","40.866222125","HID Input 1","01 00 00 36 00 00 00 00 00"
|
||||
"0","40.956230125","HID Input 1","01 00 00 36 2C 00 00 00 00"
|
||||
"0","41.001234000","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","41.091241000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","41.226251750","HID Input 1","01 00 00 0B 00 00 00 00 00"
|
||||
"0","41.316260625","HID Input 1","01 00 00 0B 08 00 00 00 00"
|
||||
"0","41.317510625","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","41.361262875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","41.406265375","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","41.496272500","HID Input 1","01 00 00 2C 06 00 00 00 00"
|
||||
"0","41.497522625","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","41.541277000","HID Input 1","01 00 00 06 12 00 00 00 00"
|
||||
"0","41.586280625","HID Input 1","01 00 00 06 12 18 00 00 00"
|
||||
"0","41.587530750","HID Input 1","01 00 00 18 12 00 00 00 00"
|
||||
"0","41.631283125","HID Input 1","01 00 00 18 00 00 00 00 00"
|
||||
"0","41.721291500","HID Input 1","01 00 00 18 0F 00 00 00 00"
|
||||
"0","41.722541500","HID Input 1","01 00 00 0F 00 00 00 00 00"
|
||||
"0","41.766292625","HID Input 1","01 00 00 0F 07 00 00 00 00"
|
||||
"0","41.811293250","HID Input 1","01 00 00 0F 07 2C 00 00 00"
|
||||
"0","41.812543250","HID Input 1","01 00 00 0F 2C 00 00 00 00"
|
||||
"0","41.856297750","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","41.946305125","HID Input 1","01 00 00 2C 06 00 00 00 00"
|
||||
"0","41.947555125","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","42.037562000","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","42.081317000","HID Input 1","01 00 00 12 10 00 00 00 00"
|
||||
"0","42.171324125","HID Input 1","01 00 00 10 00 00 00 00 00"
|
||||
"0","42.216328625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","42.261330625","HID Input 1","01 00 00 13 00 00 00 00 00"
|
||||
"0","42.351339750","HID Input 1","01 00 00 13 0F 00 00 00 00"
|
||||
"0","42.396343375","HID Input 1","01 00 00 13 0F 08 00 00 00"
|
||||
"0","42.441346125","HID Input 1","01 00 00 08 0F 00 00 00 00"
|
||||
"0","42.486349500","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","42.487599500","HID Input 1","01 00 00 08 17 00 00 00 00"
|
||||
"0","42.531352875","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","42.576356000","HID Input 1","01 00 00 17 08 00 00 00 00"
|
||||
"0","42.621359000","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","42.666363000","HID Input 1","01 00 00 08 2C 00 00 00 00"
|
||||
"0","42.711367125","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","42.756371250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","42.757621250","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","42.801376000","HID Input 1","01 00 00 17 0B 00 00 00 00"
|
||||
"0","42.891383500","HID Input 1","01 00 00 0B 00 00 00 00 00"
|
||||
"0","42.892633500","HID Input 1","01 00 00 0B 08 00 00 00 00"
|
||||
"0","42.936384375","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","42.937634250","HID Input 1","01 00 00 08 2C 00 00 00 00"
|
||||
"0","42.981389000","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","43.071391375","HID Input 1","01 00 00 2C 13 00 00 00 00"
|
||||
"0","43.072641375","HID Input 1","01 00 00 13 00 00 00 00 00"
|
||||
"0","43.161397250","HID Input 1","01 00 00 13 15 00 00 00 00"
|
||||
"0","43.162647250","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","43.206403125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","43.251407000","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","43.296409250","HID Input 1","01 00 00 12 06 00 00 00 00"
|
||||
"0","43.386418125","HID Input 1","01 00 00 01 01 01 01 01 01"
|
||||
"0","43.521429125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","43.522679000","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","43.611434875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","43.701442750","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","43.746447250","HID Input 1","01 00 00 16 2C 00 00 00 00"
|
||||
"0","43.791449250","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","43.881458500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","43.926462125","HID Input 1","01 00 00 05 00 00 00 00 00"
|
||||
"0","43.971464750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","43.972714875","HID Input 1","01 00 00 1C 00 00 00 00 00"
|
||||
"0","44.061472625","HID Input 1","01 00 00 1C 2C 00 00 00 00"
|
||||
"0","44.106478000","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","44.151481875","HID Input 1","01 00 00 2C 16 00 00 00 00"
|
||||
"0","44.197735250","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","44.241489250","HID Input 1","01 00 00 16 08 00 00 00 00"
|
||||
"0","44.242739250","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","44.286490000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","44.331490375","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","44.376494750","HID Input 1","01 00 00 11 07 00 00 00 00"
|
||||
"0","44.421498625","HID Input 1","01 00 00 07 00 00 00 00 00"
|
||||
"0","44.466501000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","44.511505000","HID Input 1","01 00 00 0C 00 00 00 00 00"
|
||||
"0","44.556509375","HID Input 1","01 00 00 0C 11 00 00 00 00"
|
||||
"0","44.646516375","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","44.691520375","HID Input 1","01 00 00 11 0A 00 00 00 00"
|
||||
"0","44.692770500","HID Input 1","01 00 00 0A 00 00 00 00 00"
|
||||
"0","44.736524875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","44.826532500","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","44.961543750","HID Input 1","01 00 00 2C 04 00 00 00 00"
|
||||
"0","44.962793625","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","45.096553625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","45.097803625","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","45.186561250","HID Input 1","01 00 00 11 2C 00 00 00 00"
|
||||
"0","45.231566000","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","45.232815875","HID Input 1","01 00 00 2C 04 00 00 00 00"
|
||||
"0","45.276568500","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","45.321572375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","45.411580125","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","45.501587625","HID Input 1","01 00 00 06 0E 00 00 00 00"
|
||||
"0","45.502837625","HID Input 1","01 00 00 0E 00 00 00 00 00"
|
||||
"0","45.546591000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","45.681598375","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","45.771605625","HID Input 1","01 00 00 11 12 00 00 00 00"
|
||||
"0","45.816608750","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","45.861612250","HID Input 1","01 00 00 1A 00 00 00 00 00"
|
||||
"0","45.951621250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","45.996624125","HID Input 1","01 00 00 0F 00 00 00 00 00"
|
||||
"0","46.041626750","HID Input 1","01 00 00 0F 08 00 00 00 00"
|
||||
"0","46.086630500","HID Input 1","01 00 00 0F 00 00 00 00 00"
|
||||
"0","46.131635875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","46.176639250","HID Input 1","01 00 00 07 00 00 00 00 00"
|
||||
"0","46.266646625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","46.356654375","HID Input 1","01 00 00 0A 00 00 00 00 00"
|
||||
"0","46.446661000","HID Input 1","01 00 00 0A 08 00 00 00 00"
|
||||
"0","46.491665000","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","46.536668125","HID Input 1","01 00 00 10 00 00 00 00 00"
|
||||
"0","46.581671750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","46.626677000","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","46.716683375","HID Input 1","01 00 00 08 11 00 00 00 00"
|
||||
"0","46.717933375","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","46.806691875","HID Input 1","01 00 00 11 17 00 00 00 00"
|
||||
"0","46.807942000","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","46.896693500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","46.941697625","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","47.031705000","HID Input 1","01 00 00 2C 13 00 00 00 00"
|
||||
"0","47.032955125","HID Input 1","01 00 00 13 00 00 00 00 00"
|
||||
"0","47.121712625","HID Input 1","01 00 00 13 04 00 00 00 00"
|
||||
"0","47.211720625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","47.257972500","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","47.346731500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","47.347981500","HID Input 1","01 00 00 0E 00 00 00 00 00"
|
||||
"0","47.481743250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","47.482993250","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","47.526745000","HID Input 1","01 00 00 08 17 00 00 00 00"
|
||||
"0","47.571747750","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","47.616752750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","47.618002625","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","47.751763625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","47.753013625","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","47.841771250","HID Input 1","01 02 00 25 00 00 00 00 00"
|
||||
"0","47.976783000","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","48.246801750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","48.606832750","HID Input 1","01 00 00 2A 00 00 00 00 00"
|
||||
"0","48.786848750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","48.876855500","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","49.011866500","HID Input 1","01 02 00 26 00 00 00 00 00"
|
||||
"0","49.146879125","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","49.236886750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","49.371897125","HID Input 1","01 00 00 1A 00 00 00 00 00"
|
||||
"0","49.461902125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","49.506905750","HID Input 1","01 00 00 0C 00 00 00 00 00"
|
||||
"0","49.551908500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","49.596913250","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","49.641917250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","49.686919375","HID Input 1","01 00 00 0B 00 00 00 00 00"
|
||||
"0","49.731923125","HID Input 1","01 00 00 0B 2C 00 00 00 00"
|
||||
"0","49.821930625","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","49.823180750","HID Input 1","01 00 00 2C 17 00 00 00 00"
|
||||
"0","49.866936000","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","49.911939750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","49.913189750","HID Input 1","01 00 00 0B 00 00 00 00 00"
|
||||
"0","49.956941750","HID Input 1","01 00 00 0B 08 00 00 00 00"
|
||||
"0","50.001945000","HID Input 1","01 00 00 0B 08 2C 00 00 00"
|
||||
"0","50.003194750","HID Input 1","01 00 00 2C 08 00 00 00 00"
|
||||
"0","50.046949875","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","50.136957125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","50.183211125","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","50.226962625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","50.271965625","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","50.361975125","HID Input 1","01 00 00 12 15 00 00 00 00"
|
||||
"0","50.406978625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","50.541989125","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","50.543239125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","50.631998250","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","50.677001500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","50.767003000","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","50.857010125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","50.948268375","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","51.037021125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","51.038271125","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","51.172032125","HID Input 1","01 00 00 2C 16 00 00 00 00"
|
||||
"0","51.217036750","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","51.218286625","HID Input 1","01 00 00 16 08 00 00 00 00"
|
||||
"0","51.262039000","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","51.352046625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","51.397049375","HID Input 1","01 00 00 14 00 00 00 00 00"
|
||||
"0","51.487058500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","51.532061875","HID Input 1","01 00 00 18 00 00 00 00 00"
|
||||
"0","51.577066000","HID Input 1","01 00 00 18 08 00 00 00 00"
|
||||
"0","51.622069125","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","51.667073000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","51.712076250","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","51.802084625","HID Input 1","01 00 00 11 06 00 00 00 00"
|
||||
"0","51.847088000","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","51.892091125","HID Input 1","01 00 00 06 08 00 00 00 00"
|
||||
"0","51.893341250","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","51.982098250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","51.983348375","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","52.072100750","HID Input 1","01 00 00 2C 11 00 00 00 00"
|
||||
"0","52.117105250","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","52.162109125","HID Input 1","01 00 00 11 18 00 00 00 00"
|
||||
"0","52.207111750","HID Input 1","01 00 00 18 00 00 00 00 00"
|
||||
"0","52.252116125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","52.342123375","HID Input 1","01 00 00 10 00 00 00 00 00"
|
||||
"0","52.432130625","HID Input 1","01 00 00 10 05 00 00 00 00"
|
||||
"0","52.477135375","HID Input 1","01 00 00 10 00 00 00 00 00"
|
||||
"0","52.478385250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","52.567143250","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","52.612147125","HID Input 1","01 00 00 08 15 00 00 00 00"
|
||||
"0","52.657151250","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","52.747158125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","52.837166000","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","53.467215875","HID Input 1","01 02 00 26 00 00 00 00 00"
|
||||
"0","53.468465875","HID Input 1","01 02 00 26 27 00 00 00 00"
|
||||
"0","53.512220250","HID Input 1","01 02 00 26 00 00 00 00 00"
|
||||
"0","53.557222375","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","53.872250500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","54.007262250","HID Input 1","01 00 00 2A 00 00 00 00 00"
|
||||
"0","54.142273375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","54.277285625","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","54.457299750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","54.502303750","HID Input 1","01 00 00 2A 00 00 00 00 00"
|
||||
"0","54.637311625","HID Input 1","01 02 00 2A 00 00 00 00 00"
|
||||
"0","54.638561625","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","54.773573375","HID Input 1","01 02 00 27 00 00 00 00 00"
|
||||
"0","54.862331375","HID Input 1","01 02 00 00 00 00 00 00 00"
|
||||
"0","55.042347000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","55.222360250","HID Input 1","01 00 00 36 00 00 00 00 00"
|
||||
"0","55.312369125","HID Input 1","01 00 00 36 2C 00 00 00 00"
|
||||
"0","55.402376500","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","55.492384125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","55.493634125","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","55.582389375","HID Input 1","01 00 00 04 11 00 00 00 00"
|
||||
"0","55.627393375","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","55.672398250","HID Input 1","01 00 00 11 07 00 00 00 00"
|
||||
"0","55.673648250","HID Input 1","01 00 00 07 00 00 00 00 00"
|
||||
"0","55.762406250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","55.763656000","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","55.942415000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","55.943665000","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","55.987417000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","56.077425250","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","56.167432250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","56.302444625","HID Unknown",""
|
||||
"0","56.392451875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","56.437456375","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","56.527463625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","56.662474625","HID Input 1","01 00 00 05 00 00 00 00 00"
|
||||
"0","56.707480000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","56.708729875","HID Input 1","01 00 00 0F 00 00 00 00 00"
|
||||
"0","56.797485375","HID Input 1","01 00 00 0F 0C 00 00 00 00"
|
||||
"0","56.842489625","HID Input 1","01 00 00 0F 00 00 00 00 00"
|
||||
"0","56.887493250","HID Input 1","01 00 00 0F 16 00 00 00 00"
|
||||
"0","56.888743250","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","56.977502000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","57.022503625","HID Input 1","01 00 00 0B 00 00 00 00 00"
|
||||
"0","57.067507500","HID Input 1","01 00 00 0B 2C 00 00 00 00"
|
||||
"0","57.112511500","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","57.157510875","HID Input 1","01 00 00 2C 04 00 00 00 00"
|
||||
"0","57.158760750","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","57.247519000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","57.292522125","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","57.382531000","HID Input 1","01 00 00 2C 06 00 00 00 00"
|
||||
"0","57.517541500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","57.518791500","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","57.607548750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","57.652552250","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","57.742559750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","57.832567250","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","57.877572375","HID Input 1","01 00 00 11 08 00 00 00 00"
|
||||
"0","57.922575875","HID Input 1","01 00 00 11 00 00 00 00 00"
|
||||
"0","57.967580250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","58.012583250","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","58.102590750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","58.192599000","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","58.282606625","HID Input 1","01 00 00 17 0C 00 00 00 00"
|
||||
"0","58.327609125","HID Input 1","01 00 00 0C 00 00 00 00 00"
|
||||
"0","58.372612500","HID Input 1","01 00 00 0C 12 00 00 00 00"
|
||||
"0","58.373862500","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","58.462618125","HID Input 1","01 00 00 12 11 00 00 00 00"
|
||||
"0","58.507622375","HID Input 1","01 00 00 12 11 2C 00 00 00"
|
||||
"0","58.508872375","HID Input 1","01 00 00 2C 11 00 00 00 00"
|
||||
"0","58.552624250","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","58.597627500","HID Input 1","01 00 00 2C 04 00 00 00 00"
|
||||
"0","58.642631250","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","58.687634750","HID Input 1","01 00 00 04 13 00 00 00 00"
|
||||
"0","58.688884625","HID Input 1","01 00 00 13 00 00 00 00 00"
|
||||
"0","58.732638750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","58.822646125","HID Input 1","01 00 00 13 00 00 00 00 00"
|
||||
"0","58.912654125","HID Input 1","01 00 00 13 08 00 00 00 00"
|
||||
"0","59.002661500","HID Input 1","01 00 00 13 08 04 00 00 00"
|
||||
"0","59.003911500","HID Input 1","01 00 00 13 04 00 00 00 00"
|
||||
"0","59.047665000","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","59.092668625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","59.137671250","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","59.227679750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","59.272683500","HID Input 1","01 00 00 0C 00 00 00 00 00"
|
||||
"0","59.407694500","HID Input 1","01 00 00 0C 11 0A 00 00 00"
|
||||
"0","59.452698250","HID Input 1","01 00 00 0A 11 00 00 00 00"
|
||||
"0","59.453948250","HID Input 1","01 00 00 0A 00 00 00 00 00"
|
||||
"0","59.497703125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","59.498953125","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","59.632713000","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","59.633963000","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","59.722715250","HID Input 1","01 00 00 17 12 00 00 00 00"
|
||||
"0","59.723965250","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","59.767718375","HID Input 1","01 00 00 12 2C 00 00 00 00"
|
||||
"0","59.857727375","HID Input 1","01 00 00 12 2C 05 00 00 00"
|
||||
"0","59.902730250","HID Input 1","01 00 00 05 2C 00 00 00 00"
|
||||
"0","59.903980250","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","59.947732125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","59.992735500","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","60.037739000","HID Input 1","01 00 00 08 2C 00 00 00 00"
|
||||
"0","60.082743625","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","60.172751000","HID Input 1","01 00 00 2C 09 00 00 00 00"
|
||||
"0","60.174001000","HID Input 1","01 00 00 09 00 00 00 00 00"
|
||||
"0","60.262759500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","60.307763625","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","60.397771000","HID Input 1","01 00 00 15 12 00 00 00 00"
|
||||
"0","60.399021000","HID Input 1","01 00 00 12 00 00 00 00 00"
|
||||
"0","60.442772250","HID Input 1","01 00 00 12 10 00 00 00 00"
|
||||
"0","60.487776000","HID Input 1","01 00 00 12 10 2C 00 00 00"
|
||||
"0","60.577784000","HID Input 1","01 00 00 12 2C 00 00 00 00"
|
||||
"0","60.579033875","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","60.622788500","HID Input 1","01 00 00 2C 17 00 00 00 00"
|
||||
"0","60.624038625","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","60.667791250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","60.712794375","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","60.714044500","HID Input 1","01 00 00 08 0B 00 00 00 00"
|
||||
"0","60.802801875","HID Input 1","01 00 00 08 0B 2C 00 00 00"
|
||||
"0","60.804052000","HID Input 1","01 00 00 08 2C 00 00 00 00"
|
||||
"0","60.847804000","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","60.937812125","HID Input 1","01 00 00 2C 17 00 00 00 00"
|
||||
"0","60.939062375","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","60.982813125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","61.072820000","HID Input 1","01 00 00 15 00 00 00 00 00"
|
||||
"0","61.162828125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","61.207832375","HID Input 1","01 00 00 18 00 00 00 00 00"
|
||||
"0","61.252834500","HID Input 1","01 00 00 18 16 00 00 00 00"
|
||||
"0","61.344092625","HID Input 1","01 00 00 16 00 00 00 00 00"
|
||||
"0","61.387843500","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","61.432846875","HID Input 1","01 00 00 17 00 00 00 00 00"
|
||||
"0","61.522854875","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","61.567857750","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","61.657865625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","61.702869375","HID Input 1","01 00 00 07 00 00 00 00 00"
|
||||
"0","61.837880125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","62.332919500","HID Input 1","01 00 00 2C 00 00 00 00 00"
|
||||
"0","62.422927500","HID Input 1","01 00 00 2C 10 00 00 00 00"
|
||||
"0","62.424177500","HID Input 1","01 00 00 10 00 00 00 00 00"
|
||||
"0","62.557937875","HID Input 1","01 00 00 10 04 00 00 00 00"
|
||||
"0","62.602940875","HID Input 1","01 00 00 04 00 00 00 00 00"
|
||||
"0","62.604190750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","62.692948750","HID Input 1","01 00 00 06 00 00 00 00 00"
|
||||
"0","62.737952750","HID Input 1","01 00 00 06 0B 00 00 00 00"
|
||||
"0","62.782957500","HID Input 1","01 00 00 0B 00 00 00 00 00"
|
||||
"0","62.872964375","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","62.874214250","HID Input 1","01 00 00 0C 00 00 00 00 00"
|
||||
"0","62.962971250","HID Input 1","01 00 00 0C 11 00 00 00 00"
|
||||
"0","63.007974750","HID Input 1","01 00 00 0C 11 08 00 00 00"
|
||||
"0","63.052978125","HID Input 1","01 00 00 08 11 00 00 00 00"
|
||||
"0","63.054228125","HID Input 1","01 00 00 08 00 00 00 00 00"
|
||||
"0","63.097981750","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","63.187990000","HID Input 1","01 00 00 37 00 00 00 00 00"
|
||||
"0","63.323001250","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","63.593020125","HID Input 1","01 00 00 28 00 00 00 00 00"
|
||||
"0","63.683028125","HID Input 1","01 00 00 00 00 00 00 00 00"
|
||||
"0","63.773035125","HID Input 1","01 00 00 28 00 00 00 00 00"
|
||||
"0","63.818038625","HID Input 1","01 00 00 00 00 00 00 00 00"
|
|
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# produce a sync word for a given LAP
|
||||
|
||||
lap = 0xffffff
|
||||
|
||||
pn = 0x83848D96BBCC54FC
|
||||
|
||||
# generator matrix for (64,30) linear block code
|
||||
# based on polynomial 0260534236651
|
||||
# (see gen_check_tables.py for automatic generation)
|
||||
g = (
|
||||
0x8000000000000001,
|
||||
0x40000002c2b89ed4,
|
||||
0x20000001615c4f6a,
|
||||
0x10000000b0ae27b5,
|
||||
0x080000029aef8d0e,
|
||||
0x040000014d77c687,
|
||||
0x0200000264037d97,
|
||||
0x01000003f0b9201f,
|
||||
0x008000033ae40edb,
|
||||
0x004000035fca99b9,
|
||||
0x002000036d5dd208,
|
||||
0x00100001b6aee904,
|
||||
0x00080000db577482,
|
||||
0x000400006dabba41,
|
||||
0x00020002f46d43f4,
|
||||
0x000100017a36a1fa,
|
||||
0x00008000bd1b50fd,
|
||||
0x000040029c3536aa,
|
||||
0x000020014e1a9b55,
|
||||
0x0000100265b5d37e,
|
||||
0x0000080132dae9bf,
|
||||
0x000004025bd5ea0b,
|
||||
0x00000203ef526bd1,
|
||||
0x000001033511ab3c,
|
||||
0x000000819a88d59e,
|
||||
0x00000040cd446acf,
|
||||
0x00000022a41aabb3,
|
||||
0x0000001390b5cb0d,
|
||||
0x0000000b0ae27b52,
|
||||
0x0000000585713da9)
|
||||
|
||||
def encode(data):
|
||||
assert data < 2**30
|
||||
codeword = 0
|
||||
for i in range(30):
|
||||
if (data & (0x20000000 >> i)):
|
||||
codeword ^= g[i]
|
||||
return codeword
|
||||
|
||||
# append barker code
|
||||
if (lap & 0x800000):
|
||||
data = 0x13000000 | lap
|
||||
else:
|
||||
data = 0x2c000000 | lap
|
||||
|
||||
# scramble
|
||||
data ^= (pn >> 34)
|
||||
|
||||
# encode
|
||||
codeword = encode(data)
|
||||
|
||||
# scramble again
|
||||
syncword = codeword ^ pn
|
||||
|
||||
print "0x%06x 0x%016x 0x%016x" % (lap, codeword, syncword)
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Reverse the binary of thesebarker codes for the host code
|
||||
barkers = (0x0d, 0x72)
|
||||
distances = []
|
||||
corrections = []
|
||||
|
||||
def count_bits(x):
|
||||
i = 0
|
||||
while x:
|
||||
i += 1
|
||||
x &= x - 1
|
||||
return i
|
||||
|
||||
for i in range(128):
|
||||
diffs = [(count_bits(barkers[0] ^ i), barkers[0]),
|
||||
(count_bits(barkers[1] ^ i), barkers[1])]
|
||||
diffs.sort()
|
||||
distances.append(diffs[0][0])
|
||||
corrections.append(diffs[0][1])
|
||||
|
||||
print "Barker distance:", distances
|
||||
print "Barker correct:", ["0x%x" % c for c in corrections]
|
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# (64,30) linear block code stuff
|
||||
|
||||
polynomial = 0260534236651
|
||||
|
||||
# produce generator matrix g
|
||||
g = []
|
||||
for i in range(30):
|
||||
g.append(polynomial << i)
|
||||
for j in range(i):
|
||||
if g[i] & (1 << (33 + i - j)):
|
||||
g[i] ^= g[i-j-1]
|
||||
|
||||
#print
|
||||
#for i in range(29,-1,-1):
|
||||
#print "0x%016x," % g[i]
|
||||
#print
|
||||
|
||||
# produce check matrix h
|
||||
h = []
|
||||
for i in range(34):
|
||||
h.append(0)
|
||||
for j in range(30):
|
||||
h[i] |= (g[29-j] >> i) & 0x1
|
||||
h[i] <<= 1
|
||||
h[i] <<= 33
|
||||
h[i] |= (0x1 << i)
|
||||
|
||||
#print
|
||||
#for i in range(34):
|
||||
#print "0x%016x," % h[i]
|
||||
#print
|
||||
|
||||
# reverse the order
|
||||
g = g[::-1]
|
||||
h = h[::-1]
|
||||
|
||||
def count_bits(n):
|
||||
i = 0
|
||||
while n != 0:
|
||||
n &= n - 1
|
||||
i += 1
|
||||
return i
|
||||
|
||||
def gen_syndrome(c):
|
||||
assert c < 2**64
|
||||
s = 0
|
||||
# look for a faster GF(2) matrix multiplication algorithm
|
||||
for i in range(34):
|
||||
s <<= 1
|
||||
s |= (count_bits(c & h[i]) % 2)
|
||||
return s
|
||||
|
||||
# optimized check table generation (sw_check_tables.h)
|
||||
for shift in range(8):
|
||||
for i in range(256):
|
||||
print "0x%09x, " % gen_syndrome(i<<(shift*8)),
|
||||
print
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
num_channels = 40
|
||||
bits = []
|
||||
channels = {}
|
||||
reg = 0x57
|
||||
|
||||
while not (len(bits) and reg==0x57):
|
||||
if reg & 0x3f < num_channels and reg & 0x40:
|
||||
channels[reg & 0x3f] = len(bits)
|
||||
bit = (reg & 1)
|
||||
bits.append(bit)
|
||||
reg >>= 1
|
||||
reg |= (bit << 6)
|
||||
reg ^= (bit << 2)
|
||||
|
||||
print bits
|
||||
|
||||
print "\nArray index:"
|
||||
for k in sorted(channels.keys()):
|
||||
print channels[k]
|
|
@ -0,0 +1,36 @@
|
|||
# Copyright 2011 Michael Ossmann, Dominic Spill
|
||||
#
|
||||
# This file is part of Project Ubertooth.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
CC ?= gcc
|
||||
|
||||
SOURCE_FILES = test_syndromes.c
|
||||
LIBRARY_SOURCE = ../bluetooth_packet.c
|
||||
BINARY_FILES = test_syndromes
|
||||
HEADER_FILES = ../bluetooth_packet.h
|
||||
|
||||
CFLAGS += -DHASH_FUNCTION=HASH_FNV -DHASH_EMIT_KEYS=3
|
||||
|
||||
all: test_packet
|
||||
|
||||
test_packet:
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -O2 -Wall $(LIBRARY_SOURCE) $(SOURCE_FILES) -o $(BINARY_FILES)
|
||||
|
||||
clean:
|
||||
rm -f $(BINARY_FILES)
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2007 - 2011 Dominic Spill, Michael Ossmann
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "../bluetooth_packet.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int test_unfec23() {
|
||||
char *optr;
|
||||
int i, j, ret, err;
|
||||
ret = 0;
|
||||
|
||||
printf("Testing unfec23\n");
|
||||
printf("---------------\n");
|
||||
|
||||
char input[20][15] = {
|
||||
/* No errors */
|
||||
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0},
|
||||
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1},
|
||||
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0},
|
||||
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0},
|
||||
{0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
|
||||
{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1},
|
||||
{0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1},
|
||||
/* Errors */
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}
|
||||
};
|
||||
|
||||
char output[20][15] = {
|
||||
/* No errors */
|
||||
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 1, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 1, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
/* Errors */
|
||||
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 1, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 1, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
|
||||
};
|
||||
|
||||
for(i = 0; i < 20; i++) {
|
||||
if (optr = unfec23(input[i], 1)) {
|
||||
err = 0;
|
||||
for(j = 0; j < 10; j++) {
|
||||
if (optr[j] != output[i][j]) {
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (err == 1) {
|
||||
printf("E");
|
||||
ret++;
|
||||
}
|
||||
else
|
||||
printf(".");
|
||||
} else {
|
||||
printf("F");
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret > 0)
|
||||
printf("%d errors\n", ret);
|
||||
printf("\n--------------------\n");
|
||||
printf("Done testing unfec23\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int ret = 0;
|
||||
|
||||
ret += test_unfec23();
|
||||
|
||||
exit(ret);
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2012 Dominic Spill
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
/*
|
||||
UAP Data HEC Header (octal)
|
||||
----------------------------------
|
||||
00 123 e1 770007 007070 000777
|
||||
47 123 06 770007 007007 700000
|
||||
00 124 32 007007 007007 007700
|
||||
47 124 d5 007007 007070 707077
|
||||
00 125 5a 707007 007007 077070
|
||||
47 125 bd 707007 007070 777707
|
||||
00 126 e2 077007 007007 000777
|
||||
47 126 05 077007 007070 700000
|
||||
00 127 8a 777007 007007 070007
|
||||
47 127 6d 777007 007070 770770
|
||||
00 11b 9e 770770 007007 777007
|
||||
47 11b 79 770770 007070 077770
|
||||
00 11c 4d 007770 007070 770070
|
||||
47 11c aa 007770 007007 070707
|
||||
00 11d 25 707770 007070 700700
|
||||
47 11d c2 707770 007007 000077
|
||||
00 11e 9d 077770 007070 777007
|
||||
47 11e 7a 077770 007007 077770
|
||||
00 11f f5 777770 007070 707777
|
||||
47 11f 12 777770 007007 007000
|
||||
*/
|
||||
|
||||
#include "../bluetooth_packet_tx.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int test_gen_packet_header() {
|
||||
char *optr;
|
||||
int i, j, ret, err;
|
||||
ret = 0;
|
||||
|
||||
printf("Testing header\n");
|
||||
printf("---------------\n");
|
||||
|
||||
/* lt_addr, type, flow, arqn, seqn, UAP, HEC */
|
||||
uint8_t data[20][7] = {
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
UAP Data HE
|
||||
-----------
|
||||
00 123 e1
|
||||
47 123 06
|
||||
00 124 32
|
||||
47 124 d5
|
||||
00 125 5a
|
||||
47 125 bd
|
||||
00 126 e2
|
||||
47 126 05
|
||||
00 127 8a
|
||||
47 127 6d
|
||||
00 11b 9e
|
||||
47 11b 79
|
||||
00 11c 4d
|
||||
47 11c aa
|
||||
00 11d 25
|
||||
47 11d c2
|
||||
00 11e 9d
|
||||
47 11e 7a
|
||||
00 11f f5
|
||||
47 11f 12
|
||||
|
||||
};
|
||||
|
||||
for(i = 0; i < 20; i++) {
|
||||
gen_packet_header(uint8_t lt_addr, uint8_t type, uint8_t flow, uint8_t arqn, uint8_t seqn)
|
||||
if (uap == 1) {
|
||||
printf("E");
|
||||
ret++;
|
||||
}
|
||||
else
|
||||
printf(".");
|
||||
}
|
||||
|
||||
if (ret > 0)
|
||||
printf("%d errors\n", ret);
|
||||
printf("\n--------------------\n");
|
||||
printf("Done testing unfec23\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int ret = 0;
|
||||
|
||||
ret += test_unfec23();
|
||||
|
||||
exit(ret);
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/* -*- c -*- */
|
||||
/*
|
||||
* Copyright 2007 - 2011 Dominic Spill, Michael Ossmann
|
||||
*
|
||||
* This file is part of libbtbb
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libbtbb; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "../bluetooth_packet.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int test_syndromes() {
|
||||
int ret, i;
|
||||
uint64_t syndrome, syncword;
|
||||
ret = 0;
|
||||
|
||||
printf("Testing syndromes\n");
|
||||
printf("-----------------\n");
|
||||
|
||||
uint64_t syndrome_input[2] = {
|
||||
/* No errors */
|
||||
0xcc7b7268ff614e1b,
|
||||
/* Errors */
|
||||
0xcc7d7268ff614e1b
|
||||
};
|
||||
|
||||
uint64_t syndrome_output[2] = {
|
||||
/* No errors */
|
||||
0,
|
||||
/* Errors */
|
||||
0x0000000299c6f9b5
|
||||
};
|
||||
|
||||
for(i = 0; i < 2; i++) {
|
||||
syndrome = gen_syndrome(syndrome_input[i]);
|
||||
if (syndrome == syndrome_output[i]) {
|
||||
printf(".");
|
||||
} else {
|
||||
printf("F");
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t syncword_input[2] = {
|
||||
/* No errors */
|
||||
0xcc7b7268ff614e1b,
|
||||
/* Errors */
|
||||
0xcc7b7268ff514e1b
|
||||
};
|
||||
|
||||
uint64_t syncword_output[2] = {
|
||||
/* No errors */
|
||||
0x4ffffffe44ad1ae7,
|
||||
/* Errors */
|
||||
0x4ffffffe44ad1ae7
|
||||
};
|
||||
|
||||
gen_syndrome_map();
|
||||
for(i = 0; i < 2; i++) {
|
||||
syncword = decode_syncword(syncword_input[i] ^ pn);
|
||||
if (syncword == syncword_output[i]) {
|
||||
printf(".");
|
||||
} else {
|
||||
printf("F");
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret > 0)
|
||||
printf("%d errors\n", ret);
|
||||
printf("\n-----------------\n");
|
||||
printf("Done testing syndrome generation\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int ret = 0;
|
||||
|
||||
ret += test_syndromes();
|
||||
|
||||
exit(ret);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<title>Libbtbb - Bluetooth baseband library</title>
|
||||
</head>
|
||||
<body style="width:600px">
|
||||
<h1>Libbtbb - Bluetooth baseband library</h1>
|
||||
<p>Libbtbb is the Bluetooth baseband library used by the Ubertooth and
|
||||
gr-bluetooth projects. It is freely available under the
|
||||
<a href="http://www.gnu.org/licenses/gpl-2.0.html">GPL v2 license</a>.</p>
|
||||
|
||||
<h3>Getting libbtbb</h3>
|
||||
<p>Libbtbb is built from source using either a released archive or the latest
|
||||
code from our <a href="https://www.github.com/greatscottgadgets/libbtbb">git repository</a>.
|
||||
To get started, do either of the following:</p>
|
||||
<ul>
|
||||
<li><a href="http://sourceforge.net/projects/libbtbb/files/latest/download?source=files">
|
||||
Download the latest release</a></li>
|
||||
<li>or clone the git repository using the following command:
|
||||
<pre>git clone https://github.com/greatscottgadgets/libbtbb.git</pre></li>
|
||||
<li style="list-style-type:none">If you prefer to use ssh and have a GitHub
|
||||
account, you can use this command:
|
||||
<pre>git clone git@github.com:greatscottgadgets/libbtbb.git</pre></li>
|
||||
</ul>
|
||||
|
||||
<h3>Support</h3>
|
||||
<p>Support for libbtbb is provided by
|
||||
<a href="http://ubertooth.sourceforge.net/">project Ubertooth</a>, either using
|
||||
the <a href="https://lists.sourceforge.net/lists/listinfo/ubertooth-general">
|
||||
mailing list</a> or via IRC in #ubertooth on
|
||||
<a href="http://freenode.net/irc_servers.shtml">chat.freenode.net</a></p>
|
||||
<p>Bugs may be reported and tracked in the
|
||||
<a href="https://github.com/greatscottgadgets/libbtbb/issues">ticketing system</a>.
|
||||
Although it often helps to mention the bug report on the
|
||||
<a href="https://lists.sourceforge.net/lists/listinfo/ubertooth-general">
|
||||
Ubertooth mailing list</a> to be sure that it has been seen.</p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,5 @@
|
|||
Authors:
|
||||
Allan M. Madsen <allan.m@madsen.dk>
|
||||
|
||||
Converted to plugin by:
|
||||
Mike Ryan <mikeryan@lacklustre.net>
|
|
@ -0,0 +1,88 @@
|
|||
# CMakeLists.txt
|
||||
#
|
||||
# $Id: CMakeLists.txt 31995 2010-02-24 22:32:10Z jmayer $
|
||||
#
|
||||
# Wireshark - Network traffic analyzer
|
||||
# By Gerald Combs <gerald@wireshark.org>
|
||||
# Copyright 1998 Gerald Combs
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
|
||||
project(btatt-wireshark-plugin C)
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
set(CMAKE_BACKWARDS_COMPATIBILITY 2.6)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
|
||||
IF ( NOT CMAKE_INSTALL_LIBDIR )
|
||||
set(CMAKE_INSTALL_LIBDIR ~/.wireshark/plugins)
|
||||
ENDIF ( NOT CMAKE_INSTALL_LIBDIR )
|
||||
MESSAGE (STATUS "Plugin will be installed in: ${CMAKE_INSTALL_LIBDIR}")
|
||||
|
||||
INCLUDE(UseMakeDissectorReg)
|
||||
|
||||
set(GLIB2_MIN_VERSION 2.4.0)
|
||||
|
||||
find_package(GLIB2)
|
||||
include_directories (${GLIB2_INCLUDE_DIRS})
|
||||
|
||||
find_package(Wireshark)
|
||||
include_directories (${WIRESHARK_INCLUDE_DIRS})
|
||||
|
||||
set(LINK_MODE_LIB SHARED)
|
||||
set(LINK_MODE_MODULE MODULE)
|
||||
|
||||
|
||||
set(DISSECTOR_SRC
|
||||
packet-btatt.c
|
||||
)
|
||||
|
||||
set(PLUGIN_FILES
|
||||
plugin.c
|
||||
${DISSECTOR_SRC}
|
||||
)
|
||||
|
||||
set(CLEAN_FILES
|
||||
${PLUGIN_FILES}
|
||||
)
|
||||
|
||||
if (WERROR)
|
||||
set_source_files_properties(
|
||||
${CLEAN_FILES}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS -Werror
|
||||
)
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
register_dissector_files(plugin.c
|
||||
plugin
|
||||
${DISSECTOR_SRC}
|
||||
)
|
||||
|
||||
add_library(btatt ${LINK_MODE_MODULE}
|
||||
${PLUGIN_FILES}
|
||||
)
|
||||
set_target_properties(btatt PROPERTIES PREFIX "")
|
||||
set_target_properties(btatt PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}")
|
||||
|
||||
target_link_libraries(btatt wireshark)
|
||||
|
||||
install(TARGETS btatt
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/ NAMELINK_SKIP
|
||||
)
|
||||
|
|
@ -0,0 +1,340 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,125 @@
|
|||
# Makefile.am
|
||||
# Automake file for AgentX plugin
|
||||
#
|
||||
# $Id: Makefile.am 24488 2008-02-27 16:18:30Z stig $
|
||||
#
|
||||
# Wireshark - Network traffic analyzer
|
||||
# By Gerald Combs <gerald@wireshark.org>
|
||||
# Copyright 1998 Gerald Combs
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
|
||||
INCLUDES = -I$(top_srcdir) -I$(includedir)
|
||||
|
||||
include Makefile.common
|
||||
|
||||
#if HAVE_WARNINGS_AS_ERRORS
|
||||
#AM_CFLAGS = -Werror
|
||||
#endif
|
||||
|
||||
plugindir = @plugindir@
|
||||
|
||||
plugin_LTLIBRARIES = btatt.la
|
||||
btatt_la_SOURCES = \
|
||||
plugin.c \
|
||||
moduleinfo.h \
|
||||
$(DISSECTOR_SRC) \
|
||||
$(DISSECTOR_SUPPORT_SRC) \
|
||||
$(DISSECTOR_INCLUDES)
|
||||
btatt_la_LDFLAGS = -module -avoid-version
|
||||
btatt_la_LIBADD = @PLUGIN_LIBS@
|
||||
|
||||
# Libs must be cleared, or else libtool won't create a shared module.
|
||||
# If your module needs to be linked against any particular libraries,
|
||||
# add them here.
|
||||
LIBS =
|
||||
|
||||
#
|
||||
# Build plugin.c, which contains the plugin version[] string, a
|
||||
# function plugin_register() that calls the register routines for all
|
||||
# protocols, and a function plugin_reg_handoff() that calls the handoff
|
||||
# registration routines for all protocols.
|
||||
#
|
||||
# We do this by scanning sources. If that turns out to be too slow,
|
||||
# maybe we could just require every .o file to have an register routine
|
||||
# of a given name (packet-aarp.o -> proto_register_aarp, etc.).
|
||||
#
|
||||
# Formatting conventions: The name of the proto_register_* routines an
|
||||
# proto_reg_handoff_* routines must start in column zero, or must be
|
||||
# preceded only by "void " starting in column zero, and must not be
|
||||
# inside #if.
|
||||
#
|
||||
# DISSECTOR_SRC is assumed to have all the files that need to be scanned.
|
||||
#
|
||||
# For some unknown reason, having a big "for" loop in the Makefile
|
||||
# to scan all the files doesn't work with some "make"s; they seem to
|
||||
# pass only the first few names in the list to the shell, for some
|
||||
# reason.
|
||||
#
|
||||
# Therefore, we have a script to generate the plugin.c file.
|
||||
# The shell script runs slowly, as multiple greps and seds are run
|
||||
# for each input file; this is especially slow on Windows. Therefore,
|
||||
# if Python is present (as indicated by PYTHON being defined), we run
|
||||
# a faster Python script to do that work instead.
|
||||
#
|
||||
# The first argument is the directory in which the source files live.
|
||||
# The second argument is "plugin", to indicate that we should build
|
||||
# a plugin.c file for a plugin.
|
||||
# All subsequent arguments are the files to scan.
|
||||
#
|
||||
plugin.c: $(DISSECTOR_SRC) $(top_srcdir)/tools/make-dissector-reg \
|
||||
$(top_srcdir)/tools/make-dissector-reg.py
|
||||
@if test -n "$(PYTHON)"; then \
|
||||
echo Making plugin.c with python ; \
|
||||
$(PYTHON) $(top_srcdir)/tools/make-dissector-reg.py $(srcdir) \
|
||||
plugin $(DISSECTOR_SRC) ; \
|
||||
else \
|
||||
echo Making plugin.c with shell script ; \
|
||||
$(top_srcdir)/tools/make-dissector-reg $(srcdir) \
|
||||
$(plugin_src) plugin $(DISSECTOR_SRC) ; \
|
||||
fi
|
||||
|
||||
#
|
||||
# Currently plugin.c can be included in the distribution because
|
||||
# we always build all protocol dissectors. We used to have to check
|
||||
# whether or not to build the snmp dissector. If we again need to
|
||||
# variably build something, making plugin.c non-portable, uncomment
|
||||
# the dist-hook line below.
|
||||
#
|
||||
# Oh, yuk. We don't want to include "plugin.c" in the distribution, as
|
||||
# its contents depend on the configuration, and therefore we want it
|
||||
# to be built when the first "make" is done; however, Automake insists
|
||||
# on putting *all* source into the distribution.
|
||||
#
|
||||
# We work around this by having a "dist-hook" rule that deletes
|
||||
# "plugin.c", so that "dist" won't pick it up.
|
||||
#
|
||||
#dist-hook:
|
||||
# @rm -f $(distdir)/plugin.c
|
||||
|
||||
CLEANFILES = \
|
||||
btatt \
|
||||
*~
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
Makefile.in \
|
||||
plugin.c
|
||||
|
||||
EXTRA_DIST = \
|
||||
Makefile.common \
|
||||
Makefile.nmake \
|
||||
moduleinfo.nmake \
|
||||
plugin.rc.in
|
|
@ -0,0 +1,39 @@
|
|||
# Makefile.common for AgentX plugin
|
||||
# Contains the stuff from Makefile.am and Makefile.nmake that is
|
||||
# a) common to both files and
|
||||
# b) portable between both files
|
||||
#
|
||||
# $Id: Makefile.common 23848 2007-12-12 22:10:50Z jake $
|
||||
#
|
||||
# Wireshark - Network traffic analyzer
|
||||
# By Gerald Combs <gerald@wireshark.org>
|
||||
# Copyright 1998 Gerald Combs
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
# the name of the plugin
|
||||
PLUGIN_NAME = btatt
|
||||
|
||||
# the dissector sources (without any helpers)
|
||||
DISSECTOR_SRC = \
|
||||
packet-btatt.c
|
||||
|
||||
# corresponding headers
|
||||
DISSECTOR_INCLUDES =
|
||||
|
||||
# Dissector helpers. They're included in the source files in this
|
||||
# directory, but they're not dissectors themselves, i.e. they're not
|
||||
# used to generate "plugin.c".
|
||||
DISSECTOR_SUPPORT_SRC =
|
|
@ -0,0 +1,100 @@
|
|||
# Makefile.nmake
|
||||
# nmake file for Wireshark plugin
|
||||
#
|
||||
# $Id: Makefile.nmake 24520 2008-03-01 12:31:01Z jake $
|
||||
#
|
||||
|
||||
include ..\..\config.nmake
|
||||
include moduleinfo.nmake
|
||||
|
||||
include Makefile.common
|
||||
|
||||
CFLAGS=/WX /DHAVE_CONFIG_H /I../.. /I../../wiretap $(GLIB_CFLAGS) \
|
||||
/I$(PCAP_DIR)\include -D_U_="" $(LOCAL_CFLAGS)
|
||||
|
||||
.c.obj::
|
||||
$(CC) $(CFLAGS) -Fd.\ -c $<
|
||||
|
||||
LDFLAGS = $(PLUGIN_LDFLAGS)
|
||||
|
||||
!IFDEF ENABLE_LIBWIRESHARK
|
||||
LINK_PLUGIN_WITH=..\..\epan\libwireshark.lib
|
||||
CFLAGS=/DHAVE_WIN32_LIBWIRESHARK_LIB /D_NEED_VAR_IMPORT_ $(CFLAGS)
|
||||
|
||||
DISSECTOR_OBJECTS = $(DISSECTOR_SRC:.c=.obj)
|
||||
|
||||
DISSECTOR_SUPPORT_OBJECTS = $(DISSECTOR_SUPPORT_SRC:.c=.obj)
|
||||
|
||||
OBJECTS = $(DISSECTOR_OBJECTS) $(DISSECTOR_SUPPORT_OBJECTS) plugin.obj
|
||||
|
||||
RESOURCE=$(PLUGIN_NAME).res
|
||||
|
||||
all: $(PLUGIN_NAME).dll
|
||||
|
||||
$(PLUGIN_NAME).rc : moduleinfo.nmake
|
||||
sed -e s/@PLUGIN_NAME@/$(PLUGIN_NAME)/ \
|
||||
-e s/@RC_MODULE_VERSION@/$(RC_MODULE_VERSION)/ \
|
||||
-e s/@RC_VERSION@/$(RC_VERSION)/ \
|
||||
-e s/@MODULE_VERSION@/$(MODULE_VERSION)/ \
|
||||
-e s/@PACKAGE@/$(PACKAGE)/ \
|
||||
-e s/@VERSION@/$(VERSION)/ \
|
||||
-e s/@MSVC_VARIANT@/$(MSVC_VARIANT)/ \
|
||||
< plugin.rc.in > $@
|
||||
|
||||
$(PLUGIN_NAME).dll $(PLUGIN_NAME).exp $(PLUGIN_NAME).lib : $(OBJECTS) $(LINK_PLUGIN_WITH) $(RESOURCE)
|
||||
link -dll /out:$(PLUGIN_NAME).dll $(LDFLAGS) $(OBJECTS) $(LINK_PLUGIN_WITH) \
|
||||
$(GLIB_LIBS) $(RESOURCE)
|
||||
|
||||
#
|
||||
# Build plugin.c, which contains the plugin version[] string, a
|
||||
# function plugin_register() that calls the register routines for all
|
||||
# protocols, and a function plugin_reg_handoff() that calls the handoff
|
||||
# registration routines for all protocols.
|
||||
#
|
||||
# We do this by scanning sources. If that turns out to be too slow,
|
||||
# maybe we could just require every .o file to have an register routine
|
||||
# of a given name (packet-aarp.o -> proto_register_aarp, etc.).
|
||||
#
|
||||
# Formatting conventions: The name of the proto_register_* routines an
|
||||
# proto_reg_handoff_* routines must start in column zero, or must be
|
||||
# preceded only by "void " starting in column zero, and must not be
|
||||
# inside #if.
|
||||
#
|
||||
# DISSECTOR_SRC is assumed to have all the files that need to be scanned.
|
||||
#
|
||||
# For some unknown reason, having a big "for" loop in the Makefile
|
||||
# to scan all the files doesn't work with some "make"s; they seem to
|
||||
# pass only the first few names in the list to the shell, for some
|
||||
# reason.
|
||||
#
|
||||
# Therefore, we have a script to generate the plugin.c file.
|
||||
# The shell script runs slowly, as multiple greps and seds are run
|
||||
# for each input file; this is especially slow on Windows. Therefore,
|
||||
# if Python is present (as indicated by PYTHON being defined), we run
|
||||
# a faster Python script to do that work instead.
|
||||
#
|
||||
# The first argument is the directory in which the source files live.
|
||||
# The second argument is "plugin", to indicate that we should build
|
||||
# a plugin.c file for a plugin.
|
||||
# All subsequent arguments are the files to scan.
|
||||
#
|
||||
!IFDEF PYTHON
|
||||
plugin.c: $(DISSECTOR_SRC) moduleinfo.h ../../tools/make-dissector-reg.py
|
||||
@echo Making plugin.c (using python)
|
||||
@$(PYTHON) "../../tools/make-dissector-reg.py" . plugin $(DISSECTOR_SRC)
|
||||
!ELSE
|
||||
plugin.c: $(DISSECTOR_SRC) moduleinfo.h ../../tools/make-dissector-reg
|
||||
@echo Making plugin.c (using sh)
|
||||
@$(SH) ../../tools/make-dissector-reg . plugin $(DISSECTOR_SRC)
|
||||
!ENDIF
|
||||
|
||||
!ENDIF
|
||||
|
||||
clean:
|
||||
rm -f $(OBJECTS) $(RESOURCE) plugin.c *.pdb \
|
||||
$(PLUGIN_NAME).dll $(PLUGIN_NAME).dll.manifest $(PLUGIN_NAME).lib \
|
||||
$(PLUGIN_NAME).exp $(PLUGIN_NAME).rc
|
||||
|
||||
distclean: clean
|
||||
|
||||
maintainer-clean: distclean
|
|
@ -0,0 +1,11 @@
|
|||
Bluetooth ATT Protocol Dissector
|
||||
================================
|
||||
|
||||
This is a plugin-ized version of the Bluetooth ATT protocol dissector
|
||||
from the Wireshark trunk. I made the very minimal changes necessary to
|
||||
get it to build as a plugin: defining a couple constants and changing an
|
||||
include path.
|
||||
|
||||
This plugin is unneccessary if you are using Wireshark trunk. Only use
|
||||
it if you are using a distro packaged Wireshark that does not have btatt
|
||||
protocol support.
|
|
@ -0,0 +1,22 @@
|
|||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,27 @@
|
|||
Copyright notice for the files copied from
|
||||
http://www.opensync.org/browser/branches/3rd-party-cmake-modules/modules
|
||||
|
||||
$Id: COPYING-CMAKE-SCRIPTS 34248 2010-09-25 15:38:12Z jmayer $
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,238 @@
|
|||
#
|
||||
# $Id: FindGLIB2.cmake 34248 2010-09-25 15:38:12Z jmayer $
|
||||
#
|
||||
# - Try to find GLib2
|
||||
# Once done this will define
|
||||
#
|
||||
# GLIB2_FOUND - system has GLib2
|
||||
# GLIB2_INCLUDE_DIRS - the GLib2 include directory
|
||||
# GLIB2_LIBRARIES - Link these to use GLib2
|
||||
#
|
||||
# HAVE_GLIB_GREGEX_H glib has gregex.h header and
|
||||
# supports g_regex_match_simple
|
||||
#
|
||||
# Copyright (c) 2006 Andreas Schneider <mail@cynapses.org>
|
||||
# Copyright (c) 2006 Philippe Bernery <philippe.bernery@gmail.com>
|
||||
# Copyright (c) 2007 Daniel Gollub <gollub@b1-systems.de>
|
||||
# Copyright (c) 2007 Alban Browaeys <prahal@yahoo.com>
|
||||
# Copyright (c) 2008 Michael Bell <michael.bell@web.de>
|
||||
# Copyright (c) 2008-2009 Bjoern Ricks <bjoern.ricks@googlemail.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
|
||||
IF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS )
|
||||
# in cache already
|
||||
SET(GLIB2_FOUND TRUE)
|
||||
ELSE (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS )
|
||||
|
||||
INCLUDE(FindPkgConfig)
|
||||
|
||||
## Glib
|
||||
IF ( GLIB2_FIND_REQUIRED )
|
||||
SET( _pkgconfig_REQUIRED "REQUIRED" )
|
||||
ELSE ( GLIB2_FIND_REQUIRED )
|
||||
SET( _pkgconfig_REQUIRED "" )
|
||||
ENDIF ( GLIB2_FIND_REQUIRED )
|
||||
|
||||
IF ( GLIB2_MIN_VERSION )
|
||||
PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0>=${GLIB2_MIN_VERSION} )
|
||||
ELSE ( GLIB2_MIN_VERSION )
|
||||
PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0 )
|
||||
ENDIF ( GLIB2_MIN_VERSION )
|
||||
IF ( PKG_CONFIG_FOUND )
|
||||
IF ( GLIB2_FOUND )
|
||||
SET ( GLIB2_CORE_FOUND TRUE )
|
||||
ELSE ( GLIB2_FOUND )
|
||||
SET ( GLIB2_CORE_FOUND FALSE )
|
||||
ENDIF ( GLIB2_FOUND )
|
||||
ENDIF ( PKG_CONFIG_FOUND )
|
||||
|
||||
# Look for glib2 include dir and libraries w/o pkgconfig
|
||||
IF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND )
|
||||
FIND_PATH(
|
||||
_glibconfig_include_DIR
|
||||
NAMES
|
||||
glibconfig.h
|
||||
PATHS
|
||||
/opt/gnome/lib64
|
||||
/opt/gnome/lib
|
||||
/opt/lib/
|
||||
/opt/local/lib
|
||||
/sw/lib/
|
||||
/usr/lib64
|
||||
/usr/lib
|
||||
/usr/local/include
|
||||
${CMAKE_LIBRARY_PATH}
|
||||
PATH_SUFFIXES
|
||||
glib-2.0/include
|
||||
)
|
||||
|
||||
FIND_PATH(
|
||||
_glib2_include_DIR
|
||||
NAMES
|
||||
glib.h
|
||||
PATHS
|
||||
/opt/gnome/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
PATH_SUFFIXES
|
||||
glib-2.0
|
||||
)
|
||||
|
||||
#MESSAGE(STATUS "Glib headers: ${_glib2_include_DIR}")
|
||||
|
||||
FIND_LIBRARY(
|
||||
_glib2_link_DIR
|
||||
NAMES
|
||||
glib-2.0
|
||||
glib
|
||||
PATHS
|
||||
/opt/gnome/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
)
|
||||
IF ( _glib2_include_DIR AND _glib2_link_DIR )
|
||||
SET ( _glib2_FOUND TRUE )
|
||||
ENDIF ( _glib2_include_DIR AND _glib2_link_DIR )
|
||||
|
||||
|
||||
IF ( _glib2_FOUND )
|
||||
SET ( GLIB2_INCLUDE_DIRS ${_glib2_include_DIR} ${_glibconfig_include_DIR} )
|
||||
SET ( GLIB2_LIBRARIES ${_glib2_link_DIR} )
|
||||
SET ( GLIB2_CORE_FOUND TRUE )
|
||||
ELSE ( _glib2_FOUND )
|
||||
SET ( GLIB2_CORE_FOUND FALSE )
|
||||
ENDIF ( _glib2_FOUND )
|
||||
|
||||
# Handle dependencies
|
||||
# libintl
|
||||
IF ( NOT LIBINTL_FOUND )
|
||||
FIND_PATH(LIBINTL_INCLUDE_DIR
|
||||
NAMES
|
||||
libintl.h
|
||||
PATHS
|
||||
/opt/gnome/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
)
|
||||
|
||||
FIND_LIBRARY(LIBINTL_LIBRARY
|
||||
NAMES
|
||||
intl
|
||||
PATHS
|
||||
/opt/gnome/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/local/lib
|
||||
/usr/lib
|
||||
)
|
||||
|
||||
IF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR)
|
||||
SET (LIBINTL_FOUND TRUE)
|
||||
ENDIF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR)
|
||||
ENDIF ( NOT LIBINTL_FOUND )
|
||||
|
||||
# libiconv
|
||||
IF ( NOT LIBICONV_FOUND )
|
||||
FIND_PATH(LIBICONV_INCLUDE_DIR
|
||||
NAMES
|
||||
iconv.h
|
||||
PATHS
|
||||
/opt/gnome/include
|
||||
/opt/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
/sw/include
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
PATH_SUFFIXES
|
||||
glib-2.0
|
||||
)
|
||||
|
||||
FIND_LIBRARY(LIBICONV_LIBRARY
|
||||
NAMES
|
||||
iconv
|
||||
PATHS
|
||||
/opt/gnome/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
)
|
||||
|
||||
IF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
|
||||
SET (LIBICONV_FOUND TRUE)
|
||||
ENDIF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
|
||||
ENDIF ( NOT LIBICONV_FOUND )
|
||||
|
||||
IF (LIBINTL_FOUND)
|
||||
SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBINTL_LIBRARY})
|
||||
SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBINTL_INCLUDE_DIR})
|
||||
ENDIF (LIBINTL_FOUND)
|
||||
|
||||
IF (LIBICONV_FOUND)
|
||||
SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY})
|
||||
SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR})
|
||||
ENDIF (LIBICONV_FOUND)
|
||||
|
||||
ENDIF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND )
|
||||
##
|
||||
|
||||
IF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES)
|
||||
SET (GLIB2_FOUND TRUE)
|
||||
ENDIF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES)
|
||||
|
||||
IF (GLIB2_FOUND)
|
||||
IF (NOT GLIB2_FIND_QUIETLY)
|
||||
MESSAGE (STATUS "Found GLib2: ${GLIB2_LIBRARIES} ${GLIB2_INCLUDE_DIRS}")
|
||||
ENDIF (NOT GLIB2_FIND_QUIETLY)
|
||||
ELSE (GLIB2_FOUND)
|
||||
IF (GLIB2_FIND_REQUIRED)
|
||||
MESSAGE (SEND_ERROR "Could not find GLib2")
|
||||
ENDIF (GLIB2_FIND_REQUIRED)
|
||||
ENDIF (GLIB2_FOUND)
|
||||
|
||||
# show the GLIB2_INCLUDE_DIRS and GLIB2_LIBRARIES variables only in the advanced view
|
||||
MARK_AS_ADVANCED(GLIB2_INCLUDE_DIRS GLIB2_LIBRARIES)
|
||||
MARK_AS_ADVANCED(LIBICONV_INCLUDE_DIR LIBICONV_LIBRARY)
|
||||
MARK_AS_ADVANCED(LIBINTL_INCLUDE_DIR LIBINTL_LIBRARY)
|
||||
|
||||
ENDIF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS)
|
||||
|
||||
IF ( WIN32 )
|
||||
# include libiconv for win32
|
||||
IF ( NOT LIBICONV_FOUND )
|
||||
FIND_PATH(LIBICONV_INCLUDE_DIR iconv.h PATH_SUFFIXES glib-2.0)
|
||||
|
||||
FIND_LIBRARY(LIBICONV_LIBRARY NAMES iconv)
|
||||
|
||||
IF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
|
||||
SET (LIBICONV_FOUND TRUE)
|
||||
ENDIF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
|
||||
ENDIF ( NOT LIBICONV_FOUND )
|
||||
IF (LIBICONV_FOUND)
|
||||
SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY})
|
||||
SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR})
|
||||
ENDIF (LIBICONV_FOUND)
|
||||
ENDIF ( WIN32 )
|
||||
|
||||
IF ( GLIB2_FOUND )
|
||||
# Check if system has a newer version of glib
|
||||
# which supports g_regex_match_simple
|
||||
INCLUDE( CheckIncludeFiles )
|
||||
SET( CMAKE_REQUIRED_INCLUDES ${GLIB2_INCLUDE_DIRS} )
|
||||
CHECK_INCLUDE_FILES ( glib/gregex.h HAVE_GLIB_GREGEX_H )
|
||||
CHECK_INCLUDE_FILES ( glib/gchecksum.h HAVE_GLIB_GCHECKSUM_H )
|
||||
# Reset CMAKE_REQUIRED_INCLUDES
|
||||
SET( CMAKE_REQUIRED_INCLUDES "" )
|
||||
ENDIF( GLIB2_FOUND )
|
|
@ -0,0 +1,28 @@
|
|||
#
|
||||
# Try to find the wireshark library and its includes
|
||||
#
|
||||
# This snippet sets the following variables:
|
||||
# WIRESHARK_FOUND True if wireshark library got found
|
||||
# WIRESHARK_INCLUDE_DIRS Location of the wireshark headers
|
||||
# WIRESHARK_LIBRARIES List of libraries to use wireshark
|
||||
#
|
||||
# Copyright (c) 2011 Reinhold Kainhofer <reinhold@kainhofer.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
# wireshark does not install its library with pkg-config information,
|
||||
# so we need to manually find the libraries and headers
|
||||
|
||||
FIND_PATH( WIRESHARK_INCLUDE_DIRS epan/packet.h PATH_SUFFIXES wireshark )
|
||||
FIND_LIBRARY( WIRESHARK_LIBRARIES wireshark )
|
||||
|
||||
# Report results
|
||||
IF ( WIRESHARK_LIBRARIES AND WIRESHARK_INCLUDE_DIRS )
|
||||
SET( WIRESHARK_FOUND 1 )
|
||||
ELSE ( WIRESHARK_LIBRARIES AND WIRESHARK_INCLUDE_DIRS )
|
||||
MESSAGE( SEND_ERROR "Could NOT find the wireshark library and headers" )
|
||||
ENDIF ( WIRESHARK_LIBRARIES AND WIRESHARK_INCLUDE_DIRS )
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#
|
||||
# $Id: UseMakeDissectorReg.cmake 33616 2010-07-22 12:18:36Z stig $
|
||||
#
|
||||
MACRO(REGISTER_DISSECTOR_FILES _outputfile _registertype )
|
||||
# FIXME: Only the Python stuff has been implemented
|
||||
# Make this into a MACRO, to avoid duplication with plugins/.../
|
||||
#register.c: $(plugin_src) $(ALL_DISSECTORS_SRC) $(top_srcdir)/tools/make-dissector-reg \
|
||||
# $(top_srcdir)/tools/make-dissector-reg.py
|
||||
# @if test -n "$(PYTHON)"; then \
|
||||
# echo Making register.c with python ; \
|
||||
# $(PYTHON) $(top_srcdir)/tools/make-dissector-reg.py $(srcdir) \
|
||||
# dissectors $(ALL_DISSECTORS_SRC) ; \
|
||||
# else \
|
||||
# echo Making register.c with shell script ; \
|
||||
# $(top_srcdir)/tools/make-dissector-reg $(srcdir) \
|
||||
# dissectors $(plugin_src) $(ALL_DISSECTORS_SRC) ; \
|
||||
# fi
|
||||
set( _sources ${ARGN} )
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT
|
||||
${_outputfile}
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
${CMAKE_SOURCE_DIR}/tools/make-dissector-reg.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${_registertype}
|
||||
${_sources}
|
||||
DEPENDS
|
||||
${_sources}
|
||||
${CMAKE_SOURCE_DIR}/tools/make-dissector-reg
|
||||
${CMAKE_SOURCE_DIR}/tools/make-dissector-reg.py
|
||||
)
|
||||
ENDMACRO(REGISTER_DISSECTOR_FILES)
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
/* Included *after* config.h, in order to re-define these macros */
|
||||
|
||||
#ifdef PACKAGE
|
||||
#undef PACKAGE
|
||||
#endif
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "btle"
|
||||
|
||||
|
||||
#ifdef VERSION
|
||||
#undef VERSION
|
||||
#endif
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.0.1"
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#
|
||||
# $Id: moduleinfo.nmake 20155 2006-12-19 22:22:34Z jake $
|
||||
#
|
||||
|
||||
# The name
|
||||
PACKAGE=btle
|
||||
|
||||
# The version
|
||||
MODULE_VERSION_MAJOR=0
|
||||
MODULE_VERSION_MINOR=0
|
||||
MODULE_VERSION_MICRO=0
|
||||
MODULE_VERSION_EXTRA=1
|
||||
|
||||
#
|
||||
# The RC_VERSION should be comma-separated, not dot-separated,
|
||||
# as per Graham Bloice's message in
|
||||
#
|
||||
# http://www.ethereal.com/lists/ethereal-dev/200303/msg00283.html
|
||||
#
|
||||
# "The RC_VERSION variable in config.nmake should be comma separated.
|
||||
# This allows the resources to be built correctly and the version
|
||||
# number to be correctly displayed in the explorer properties dialog
|
||||
# for the executables, and XP's tooltip, rather than 0.0.0.0."
|
||||
#
|
||||
|
||||
MODULE_VERSION=$(MODULE_VERSION_MAJOR).$(MODULE_VERSION_MINOR).$(MODULE_VERSION_MICRO).$(MODULE_VERSION_EXTRA)
|
||||
RC_MODULE_VERSION=$(MODULE_VERSION_MAJOR),$(MODULE_VERSION_MINOR),$(MODULE_VERSION_MICRO),$(MODULE_VERSION_EXTRA)
|
||||
|
|
@ -0,0 +1,698 @@
|
|||
/* packet-btatt.c
|
||||
* Routines for Bluetooth Attribute Protocol dissection
|
||||
*
|
||||
* Copyright 2012, Allan M. Madsen <allan.m@madsen.dk>
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <epan/packet.h>
|
||||
#include <epan/prefs.h>
|
||||
#include <epan/expert.h>
|
||||
#include <epan/dissectors/packet-btl2cap.h>
|
||||
|
||||
#define BTL2CAP_PSM_ATT 0x001f
|
||||
#define BTL2CAP_FIXED_CID_ATT 0x0004
|
||||
|
||||
/* Initialize the protocol and registered fields */
|
||||
static int proto_btatt = -1;
|
||||
|
||||
static int hf_btatt_opcode = -1;
|
||||
static int hf_btatt_handle = -1;
|
||||
static int hf_btatt_starting_handle = -1;
|
||||
static int hf_btatt_ending_handle = -1;
|
||||
static int hf_btatt_group_end_handle = -1;
|
||||
static int hf_btatt_value = -1;
|
||||
static int hf_btatt_req_opcode_in_error = -1;
|
||||
static int hf_btatt_handle_in_error = -1;
|
||||
static int hf_btatt_error_code = -1;
|
||||
static int hf_btatt_uuid16 = -1;
|
||||
static int hf_btatt_uuid128 = -1;
|
||||
static int hf_btatt_client_rx_mtu = -1;
|
||||
static int hf_btatt_server_rx_mtu = -1;
|
||||
static int hf_btatt_uuid_format = -1;
|
||||
static int hf_btatt_length = -1;
|
||||
static int hf_btatt_offset = -1;
|
||||
static int hf_btatt_flags = -1;
|
||||
static int hf_btatt_sign_counter = -1;
|
||||
static int hf_btatt_signature = -1;
|
||||
|
||||
/* Initialize the subtree pointers */
|
||||
static gint ett_btatt = -1;
|
||||
static gint ett_btatt_list = -1;
|
||||
|
||||
/* Opcodes */
|
||||
static const value_string opcode_vals[] = {
|
||||
{0x01, "Error Response"},
|
||||
{0x02, "Exchange MTU Request"},
|
||||
{0x03, "Exchange MTU Response"},
|
||||
{0x04, "Find Information Request"},
|
||||
{0x05, "Find Information Response"},
|
||||
{0x06, "Find By Type Value Request"},
|
||||
{0x07, "Find By Type Value Response"},
|
||||
{0x08, "Read By Type Request"},
|
||||
{0x09, "Read By Type Response"},
|
||||
{0x0a, "Read Request"},
|
||||
{0x0b, "Read Response"},
|
||||
{0x0c, "Read Blob Request"},
|
||||
{0x0d, "Read Blob Response"},
|
||||
{0x0e, "Read Multiple Request"},
|
||||
{0x0f, "Read Multiple Response"},
|
||||
{0x10, "Read By Group Type Request"},
|
||||
{0x11, "Read By Group Type Response"},
|
||||
{0x12, "Write Request"},
|
||||
{0x13, "Write Response"},
|
||||
{0x16, "Prepare Write Request"},
|
||||
{0x17, "Prepare Write Response"},
|
||||
{0x18, "Execute Write Request"},
|
||||
{0x19, "Execute Write Response"},
|
||||
{0x1B, "Handle Value Notification"},
|
||||
{0x1D, "Handle Value Indication"},
|
||||
{0x1E, "Handle Value Confirmation"},
|
||||
{0x52, "Write Command"},
|
||||
{0xD2, "Signed Write Command"},
|
||||
{0x0, NULL}
|
||||
};
|
||||
|
||||
/* Error codes */
|
||||
static const value_string error_vals[] = {
|
||||
{0x01, "Invalid Handle"},
|
||||
{0x02, "Read Not Permitted"},
|
||||
{0x03, "Write Not Permitted"},
|
||||
{0x04, "Invalid PDU"},
|
||||
{0x05, "Insufficient Authentication"},
|
||||
{0x06, "Request Not Supported"},
|
||||
{0x07, "Invalid Offset"},
|
||||
{0x08, "Insufficient Authorization"},
|
||||
{0x09, "Prepare Queue Full"},
|
||||
{0x0a, "Attribute Not Found"},
|
||||
{0x0b, "Attribute Not Long"},
|
||||
{0x0c, "Insufficient Encryption Key Size"},
|
||||
{0x0d, "Invalid Attribute Value Length"},
|
||||
{0x0e, "Unlikely Error"},
|
||||
{0x0f, "Insufficient Encryption"},
|
||||
{0x10, "Unsupported Group Type"},
|
||||
{0x11, "Insufficient Resources"},
|
||||
{0x80, "Application Error"},
|
||||
{0xfd, "Improper Client Characteristic Configuration Descriptor"},
|
||||
{0xfe, "Procedure Already In Progress"},
|
||||
{0xff, "Out of Range"},
|
||||
{0x0, NULL}
|
||||
};
|
||||
|
||||
static const value_string uuid_vals[] = {
|
||||
/* Services - http://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx */
|
||||
{0x1800, "Generic Access"},
|
||||
{0x1801, "Generic Attribute"},
|
||||
{0x1802, "Immediate Alert"},
|
||||
{0x1803, "Link Loss"},
|
||||
{0x1804, "Tx Power"},
|
||||
{0x1805, "Current Time Service"},
|
||||
{0x1806, "Reference Time Update Service"},
|
||||
{0x1807, "Next DST Change Service"},
|
||||
{0x1808, "Glucose"},
|
||||
{0x1809, "Health Thermometer"},
|
||||
{0x180a, "Device Information"},
|
||||
{0x180d, "Heart Rate"},
|
||||
{0x180e, "Phone Alert Status Service"},
|
||||
{0x180f, "Battery Service"},
|
||||
{0x1810, "Blood Pressure"},
|
||||
{0x1811, "Alert Notification Service"},
|
||||
{0x1812, "Human Interface Device"},
|
||||
{0x1813, "Scan Parameters"},
|
||||
{0x1814, "Running Speed and Cadence"},
|
||||
{0x1816, "Cycling Speed and Cadence"},
|
||||
/* Declarations - http://developer.bluetooth.org/gatt/declarations/Pages/DeclarationsHome.aspx */
|
||||
{0x2800, "GATT Primary Service Declaration"},
|
||||
{0x2801, "GATT Secondary Service Declaration"},
|
||||
{0x2802, "GATT Include Declaration"},
|
||||
{0x2803, "GATT Characteristic Declaration"},
|
||||
/* Descriptors - http://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorsHomePage.aspx */
|
||||
{0x2900, "Characteristic Extended Properties"},
|
||||
{0x2901, "Characteristic User Description"},
|
||||
{0x2902, "Client Characteristic Configuration"},
|
||||
{0x2903, "Server Characteristic Configuration"},
|
||||
{0x2904, "Characteristic Presentation Format"},
|
||||
{0x2905, "Characteristic Aggregate Format"},
|
||||
{0x2906, "Valid Range"},
|
||||
{0x2907, "External Report Reference"},
|
||||
{0x2908, "Report Reference"},
|
||||
/* Characteristics - http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicsHome.aspx */
|
||||
{0x2a00, "Device Name"},
|
||||
{0x2a01, "Appearance"},
|
||||
{0x2a02, "Peripheral Privacy Flag"},
|
||||
{0x2a03, "Reconnection Address"},
|
||||
{0x2a04, "Peripheral Preferred Connection Parameters"},
|
||||
{0x2a05, "Service Changed"},
|
||||
{0x2a06, "Alert Level"},
|
||||
{0x2a07, "Tx Power Level"},
|
||||
{0x2a08, "Date Time"},
|
||||
{0x2a09, "Day of Week"},
|
||||
{0x2a0a, "Day Date Time"},
|
||||
{0x2a0c, "Exact Time 256"},
|
||||
{0x2a0d, "DST Offset"},
|
||||
{0x2a0e, "Time Zone"},
|
||||
{0x2a0f, "Local Time Information"},
|
||||
{0x2a11, "Time with DST"},
|
||||
{0x2a12, "Time Accuracy"},
|
||||
{0x2a13, "Time Source"},
|
||||
{0x2a14, "Reference Time Information"},
|
||||
{0x2a16, "Time Update Control Point"},
|
||||
{0x2a17, "Time Update State"},
|
||||
{0x2a18, "Glucose Measurement"},
|
||||
{0x2a19, "Battery Level"},
|
||||
{0x2a1c, "Temperature Measurement"},
|
||||
{0x2a1d, "Temperature Type"},
|
||||
{0x2a1e, "Intermediate Temperature"},
|
||||
{0x2a21, "Measurement Interval"},
|
||||
{0x2a22, "Boot Keyboard Input Report"},
|
||||
{0x2a23, "System ID"},
|
||||
{0x2a24, "Model Number String"},
|
||||
{0x2a25, "Serial Number String"},
|
||||
{0x2a26, "Firmware Revision String"},
|
||||
{0x2a27, "Hardware Revision String"},
|
||||
{0x2a28, "Software Revision String"},
|
||||
{0x2a29, "Manufacturer Name String"},
|
||||
{0x2a2a, "IEEE 11073-20601 Reg. Cert. Data List"},
|
||||
{0x2a2b, "Current Time"},
|
||||
{0x2a31, "Scan Refresh"},
|
||||
{0x2a32, "Boot Keyboard Output Report"},
|
||||
{0x2a33, "Boot Mouse Input Report"},
|
||||
{0x2a34, "Glucose Measurement Context"},
|
||||
{0x2a35, "Blood Pressure Measurement"},
|
||||
{0x2a36, "Intermediate Cuff Pressure"},
|
||||
{0x2a37, "Heart Rate Measurement"},
|
||||
{0x2a38, "Body Sensor Location"},
|
||||
{0x2a39, "Heart Rate Control Point"},
|
||||
{0x2a3f, "Alert Status"},
|
||||
{0x2a40, "Ringer Control Point"},
|
||||
{0x2a41, "Ringer Setting"},
|
||||
{0x2a42, "Alert Category ID Bit Mask"},
|
||||
{0x2a43, "Alert Category ID"},
|
||||
{0x2a44, "Alert Notification Control Point"},
|
||||
{0x2a45, "Unread Alert Status"},
|
||||
{0x2a46, "New Alert"},
|
||||
{0x2a47, "Supported New Alert Category"},
|
||||
{0x2a48, "Supported Unread Alert Category"},
|
||||
{0x2a49, "Blood Pressure Feature"},
|
||||
{0x2a4a, "HID Information"},
|
||||
{0x2a4b, "Report Map"},
|
||||
{0x2a4c, "HID Control Point"},
|
||||
{0x2a4d, "Report"},
|
||||
{0x2a4e, "Protocol Mode"},
|
||||
{0x2a4f, "Scan Interval Window"},
|
||||
{0x2a50, "PnP ID"},
|
||||
{0x2a51, "Glucose Feature"},
|
||||
{0x2a52, "Record Access Control Point"},
|
||||
{0x2a53, "RSC Measurement"},
|
||||
{0x2a54, "RSC Feature"},
|
||||
{0x2a55, "SC Control Point"},
|
||||
{0x2a5b, "CSC Measurement"},
|
||||
{0x2a5c, "CSC Feature"},
|
||||
{0x2a5d, "Sensor Location"},
|
||||
{0x0, NULL}
|
||||
};
|
||||
static value_string_ext uuid_vals_ext = VALUE_STRING_EXT_INIT(uuid_vals);
|
||||
|
||||
static const value_string uuid_format_vals[] = {
|
||||
{0x01, "16-bit UUIDs"},
|
||||
{0x02, "128-bit UUIDs"},
|
||||
{0x0, NULL}
|
||||
};
|
||||
|
||||
static const value_string flags_vals[] = {
|
||||
{0x00, "Cancel All"},
|
||||
{0x01, "Immediately Write All"},
|
||||
{0x0, NULL}
|
||||
};
|
||||
|
||||
static void
|
||||
dissect_btatt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||
{
|
||||
int offset = 0;
|
||||
proto_item *ti, *item;
|
||||
proto_tree *st, *ltree;
|
||||
guint8 opcode;
|
||||
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATT");
|
||||
|
||||
switch (pinfo->p2p_dir) {
|
||||
|
||||
case P2P_DIR_SENT:
|
||||
col_add_str(pinfo->cinfo, COL_INFO, "Sent ");
|
||||
break;
|
||||
|
||||
case P2P_DIR_RECV:
|
||||
col_add_str(pinfo->cinfo, COL_INFO, "Rcvd ");
|
||||
break;
|
||||
|
||||
case P2P_DIR_UNKNOWN:
|
||||
break;
|
||||
|
||||
default:
|
||||
col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
|
||||
pinfo->p2p_dir);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tvb_length_remaining(tvb, 0) < 1)
|
||||
return;
|
||||
|
||||
ti = proto_tree_add_item(tree, proto_btatt, tvb, 0, -1, ENC_NA);
|
||||
st = proto_item_add_subtree(ti, ett_btatt);
|
||||
|
||||
item = proto_tree_add_item(st, hf_btatt_opcode, tvb, 0, 1, ENC_LITTLE_ENDIAN);
|
||||
opcode = tvb_get_guint8(tvb, 0);
|
||||
offset++;
|
||||
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(opcode, opcode_vals, "<unknown>"));
|
||||
|
||||
switch (opcode) {
|
||||
case 0x01: /* Error Response */
|
||||
proto_tree_add_item(st, hf_btatt_req_opcode_in_error, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
||||
offset++;
|
||||
proto_tree_add_item(st, hf_btatt_handle_in_error, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, " - %s, Handle: 0x%04x",
|
||||
val_to_str(tvb_get_guint8(tvb, offset+2), error_vals, "<unknown>"),
|
||||
tvb_get_letohs(tvb, offset));
|
||||
offset += 2;
|
||||
proto_tree_add_item(st, hf_btatt_error_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
||||
offset++;
|
||||
break;
|
||||
|
||||
case 0x02: /* Exchange MTU Request */
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", Client Rx MTU: %u", tvb_get_letohs(tvb, offset));
|
||||
proto_tree_add_item(st, hf_btatt_client_rx_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
break;
|
||||
|
||||
case 0x03: /* Exchange MTU Response */
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", Server Rx MTU: %u", tvb_get_letohs(tvb, offset));
|
||||
proto_tree_add_item(st, hf_btatt_server_rx_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
break;
|
||||
|
||||
case 0x04: /* Find Information Request */
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", Handles: 0x%04x..0x%04x",
|
||||
tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
|
||||
proto_tree_add_item(st, hf_btatt_starting_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
break;
|
||||
|
||||
case 0x05: /* Find Information Response */
|
||||
{
|
||||
guint8 format = tvb_get_guint8(tvb, offset);
|
||||
|
||||
item = proto_tree_add_item(st, hf_btatt_uuid_format, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
||||
offset++;
|
||||
|
||||
if( format == 1 ) {
|
||||
while( tvb_length_remaining(tvb, offset) > 0) {
|
||||
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
}
|
||||
}
|
||||
else if( format == 2 ) {
|
||||
while( tvb_length_remaining(tvb, offset) > 0) {
|
||||
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(st, hf_btatt_uuid128, tvb, offset, 16, ENC_NA);
|
||||
offset += 16;
|
||||
}
|
||||
}
|
||||
else {
|
||||
expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "Unknown format");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x06: /* Find By Type Value Request */
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, Handles: 0x%04x..0x%04x",
|
||||
val_to_str_ext_const(tvb_get_letohs(tvb, offset+4), &uuid_vals_ext, "<unknown>"),
|
||||
tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
|
||||
|
||||
proto_tree_add_item(st, hf_btatt_starting_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
if( tvb_length_remaining(tvb, offset) > 0)
|
||||
proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
|
||||
break;
|
||||
|
||||
case 0x07: /* Find By Type Value Response */
|
||||
while( tvb_length_remaining(tvb, offset) > 0 ) {
|
||||
item = proto_tree_add_text(st, tvb, offset, 4,
|
||||
"Handles Info, Handle: 0x%04x, Group End Handle: 0x%04x",
|
||||
tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
|
||||
|
||||
ltree = proto_item_add_subtree(item, ett_btatt_list);
|
||||
|
||||
proto_tree_add_item(ltree, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(ltree, hf_btatt_group_end_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x08: /* Read By Type Request */
|
||||
case 0x10: /* Read By Group Type Request */
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, Handles: 0x%04x..0x%04x",
|
||||
val_to_str_ext_const(tvb_get_letohs(tvb, offset+4), &uuid_vals_ext, "<unknown>"),
|
||||
tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
|
||||
|
||||
proto_tree_add_item(st, hf_btatt_starting_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
|
||||
if (tvb_length_remaining(tvb, offset) == 2) {
|
||||
proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
}
|
||||
else if (tvb_length_remaining(tvb, offset) == 16) {
|
||||
item = proto_tree_add_item(st, hf_btatt_uuid128, tvb, offset, 16, ENC_NA);
|
||||
proto_item_append_text(item, " (%s)", val_to_str_ext_const(tvb_get_letohs(tvb, offset),
|
||||
&uuid_vals_ext, "<unknown>"));
|
||||
offset += 16;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x09: /* Read By Type Response */
|
||||
{
|
||||
guint8 length = tvb_get_guint8(tvb, offset);
|
||||
|
||||
proto_tree_add_item(st, hf_btatt_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
||||
offset++;
|
||||
|
||||
if(length > 0) {
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", Attribute List Length: %u",
|
||||
tvb_length_remaining(tvb, offset)/length);
|
||||
|
||||
while (tvb_length_remaining(tvb, offset) >= length)
|
||||
{
|
||||
item = proto_tree_add_text(st, tvb, offset, length, "Attribute Data, Handle: 0x%04x",
|
||||
tvb_get_letohs(tvb, offset));
|
||||
|
||||
ltree = proto_item_add_subtree(item, ett_btatt_list);
|
||||
|
||||
proto_tree_add_item(ltree, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(ltree, hf_btatt_value, tvb, offset, length-2, ENC_LITTLE_ENDIAN);
|
||||
offset += (length-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0a: /* Read Request */
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x", tvb_get_letohs(tvb, offset));
|
||||
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
break;
|
||||
|
||||
case 0x0b: /* Read Response */
|
||||
case 0x0d: /* Read Blob Response */
|
||||
case 0x0f: /* Multiple Read Response */
|
||||
proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
|
||||
break;
|
||||
|
||||
case 0x0c: /* Read Blob Request */
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x, Offset: %u",
|
||||
tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
|
||||
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(st, hf_btatt_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
break;
|
||||
|
||||
case 0x0e: /* Multiple Read Request */
|
||||
if(tvb_length_remaining(tvb, offset) < 4) {
|
||||
expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN,
|
||||
"Too few handles, should be 2 or more");
|
||||
break;
|
||||
}
|
||||
|
||||
col_append_str(pinfo->cinfo, COL_INFO, ", Handles: ");
|
||||
while (tvb_length_remaining(tvb, offset) >= 2) {
|
||||
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, "0x%04x ", tvb_get_letohs(tvb, offset));
|
||||
offset += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x11: /* Read By Group Type Response */
|
||||
{
|
||||
guint8 length = tvb_get_guint8(tvb, offset);
|
||||
|
||||
proto_tree_add_item(st, hf_btatt_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
||||
offset++;
|
||||
|
||||
if(length > 0) {
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", Attribute List Length: %u", tvb_length_remaining(tvb, offset)/length);
|
||||
|
||||
while (tvb_length_remaining(tvb, offset) >= length) {
|
||||
item = proto_tree_add_text(st, tvb, offset, length,
|
||||
"Attribute Data, Handle: 0x%04x, Group End Handle: 0x%04x",
|
||||
tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
|
||||
|
||||
ltree = proto_item_add_subtree(item, ett_btatt_list);
|
||||
|
||||
proto_tree_add_item(ltree, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(ltree, hf_btatt_group_end_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(ltree, hf_btatt_value, tvb, offset, length-4, ENC_LITTLE_ENDIAN);
|
||||
offset += (length-4);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x12: /* Write Request */
|
||||
case 0x52: /* Write Command */
|
||||
case 0x1b: /* Handle Value Notification */
|
||||
case 0x1d: /* Handle Value Indication */
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x", tvb_get_letohs(tvb, offset));
|
||||
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
|
||||
break;
|
||||
|
||||
case 0x16: /* Prepare Write Request */
|
||||
case 0x17: /* Prepare Write Response */
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x, Offset: %u",
|
||||
tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
|
||||
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(st, hf_btatt_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
|
||||
break;
|
||||
|
||||
case 0x18: /* Execute Write Request */
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
|
||||
val_to_str(tvb_get_guint8(tvb, offset), flags_vals, "<unknown>"));
|
||||
proto_tree_add_item(st, hf_btatt_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
||||
offset++;
|
||||
break;
|
||||
|
||||
case 0xd2: /* Signed Write Command */
|
||||
{
|
||||
guint8 length;
|
||||
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x", tvb_get_letohs(tvb, offset));
|
||||
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
length = tvb_length_remaining(tvb, offset);
|
||||
if (length > 12) {
|
||||
proto_tree_add_item(st, hf_btatt_value, tvb, offset, length-12, ENC_NA);
|
||||
offset+=length-12;
|
||||
}
|
||||
|
||||
proto_tree_add_item(st, hf_btatt_sign_counter, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
||||
offset+=4;
|
||||
proto_tree_add_item(st, hf_btatt_signature, tvb, offset, 8, ENC_NA);
|
||||
offset+=8;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
proto_register_btatt(void)
|
||||
{
|
||||
module_t *module;
|
||||
|
||||
static hf_register_info hf[] = {
|
||||
{&hf_btatt_opcode,
|
||||
{"Opcode", "btatt.opcode",
|
||||
FT_UINT8, BASE_HEX, VALS(opcode_vals), 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_handle,
|
||||
{"Handle", "btatt.handle",
|
||||
FT_UINT16, BASE_HEX, NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_starting_handle,
|
||||
{"Starting Handle", "btatt.starting_handle",
|
||||
FT_UINT16, BASE_HEX, NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_ending_handle,
|
||||
{"Ending Handle", "btatt.ending_handle",
|
||||
FT_UINT16, BASE_HEX, NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_group_end_handle,
|
||||
{"Group End Handle", "btatt.group_end_handle",
|
||||
FT_UINT16, BASE_HEX, NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_value,
|
||||
{"Value", "btatt.value",
|
||||
FT_BYTES, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_req_opcode_in_error,
|
||||
{"Request Opcode in Error", "btatt.req_opcode_in_error",
|
||||
FT_UINT8, BASE_HEX, VALS(opcode_vals), 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_handle_in_error,
|
||||
{"Handle in Error", "btatt.handle_in_error",
|
||||
FT_UINT16, BASE_HEX, NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_error_code,
|
||||
{"Error Code", "btatt.error_code",
|
||||
FT_UINT8, BASE_HEX, VALS(error_vals), 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_uuid16,
|
||||
{"UUID", "btatt.uuid16",
|
||||
FT_UINT16, BASE_HEX |BASE_EXT_STRING, &uuid_vals_ext, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_uuid128,
|
||||
{"UUID", "btatt.uuid128",
|
||||
FT_BYTES, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_client_rx_mtu,
|
||||
{"Client Rx MTU", "btatt.client_rx_mtu",
|
||||
FT_UINT16, BASE_DEC, NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_server_rx_mtu,
|
||||
{"Server Rx MTU", "btatt.server_rx_mtu",
|
||||
FT_UINT16, BASE_DEC, NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_uuid_format,
|
||||
{"UUID Format", "btatt.uuid_format",
|
||||
FT_UINT8, BASE_HEX, VALS(uuid_format_vals), 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_length,
|
||||
{"Length", "btatt.length",
|
||||
FT_UINT8, BASE_DEC, NULL, 0x0,
|
||||
"Length of Handle/Value Pair", HFILL}
|
||||
},
|
||||
{&hf_btatt_offset,
|
||||
{"Offset", "btatt.offset",
|
||||
FT_UINT16, BASE_DEC, NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_flags,
|
||||
{"Flags", "btatt.flags",
|
||||
FT_UINT8, BASE_HEX, VALS(flags_vals), 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_sign_counter,
|
||||
{"Sign Counter", "btatt.sign_counter",
|
||||
FT_UINT32, BASE_DEC, NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{&hf_btatt_signature,
|
||||
{"Signature", "btatt.signature",
|
||||
FT_BYTES, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
}
|
||||
};
|
||||
|
||||
/* Setup protocol subtree array */
|
||||
static gint *ett[] = {
|
||||
&ett_btatt,
|
||||
&ett_btatt_list
|
||||
};
|
||||
|
||||
/* Register the protocol name and description */
|
||||
proto_btatt = proto_register_protocol("Bluetooth Attribute Protocol", "ATT", "btatt");
|
||||
|
||||
register_dissector("btatt", dissect_btatt, proto_btatt);
|
||||
|
||||
/* Required function calls to register the header fields and subtrees used */
|
||||
proto_register_field_array(proto_btatt, hf, array_length(hf));
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
|
||||
module = prefs_register_protocol(proto_btatt, NULL);
|
||||
prefs_register_static_text_preference(module, "att.version",
|
||||
"Bluetooth Protocol ATT version from Core 4.0",
|
||||
"Version of protocol supported by this dissector.");
|
||||
}
|
||||
|
||||
void
|
||||
proto_reg_handoff_btatt(void)
|
||||
{
|
||||
dissector_handle_t btatt_handle;
|
||||
|
||||
btatt_handle = find_dissector("btatt");
|
||||
dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_ATT, btatt_handle);
|
||||
dissector_add_uint("btl2cap.cid", BTL2CAP_FIXED_CID_ATT, btatt_handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
|
@ -0,0 +1,34 @@
|
|||
#include "winver.h"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION @RC_MODULE_VERSION@
|
||||
PRODUCTVERSION @RC_VERSION@
|
||||
FILEFLAGSMASK 0x0L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "The Wireshark developer community, http://www.wireshark.org/\0"
|
||||
VALUE "FileDescription", "@PACKAGE@ dissector\0"
|
||||
VALUE "FileVersion", "@MODULE_VERSION@\0"
|
||||
VALUE "InternalName", "@PACKAGE@ @MODULE_VERSION@\0"
|
||||
VALUE "LegalCopyright", "Copyright © 1998 Gerald Combs <gerald@wireshark.org>, Gilbert Ramirez <gram@alumni.rice.edu> and others\0"
|
||||
VALUE "OriginalFilename", "@PLUGIN_NAME@.dll\0"
|
||||
VALUE "ProductName", "Wireshark\0"
|
||||
VALUE "ProductVersion", "@VERSION@\0"
|
||||
VALUE "Comments", "Build with @MSVC_VARIANT@\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
|
@ -0,0 +1,186 @@
|
|||
#! /bin/sh
|
||||
|
||||
#
|
||||
# $Id: make-dissector-reg 21716 2007-05-07 17:55:42Z gal $
|
||||
#
|
||||
|
||||
#
|
||||
# The first argument is the directory in which the source files live.
|
||||
#
|
||||
srcdir="$1"
|
||||
shift
|
||||
|
||||
#
|
||||
# The second argument is either "plugin" or "dissectors"; if it's
|
||||
# "plugin", we build a plugin.c for a plugin, and if it's
|
||||
# "dissectors", we build a register.c for libwireshark.
|
||||
#
|
||||
registertype="$1"
|
||||
shift
|
||||
if [ "$registertype" = plugin ]
|
||||
then
|
||||
outfile="plugin.c"
|
||||
elif [ "$registertype" = dissectors ]
|
||||
then
|
||||
outfile="register.c"
|
||||
else
|
||||
echo "Unknown output type '$registertype'" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# All subsequent arguments are the files to scan.
|
||||
#
|
||||
rm -f ${outfile}-tmp
|
||||
echo '/* Do not modify this file. */' >${outfile}-tmp
|
||||
echo '/* It is created automatically by the Makefile. */'>>${outfile}-tmp
|
||||
if [ "$registertype" = plugin ]
|
||||
then
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
#include "moduleinfo.h"
|
||||
|
||||
#ifndef ENABLE_STATIC
|
||||
G_MODULE_EXPORT const gchar version[] = VERSION;
|
||||
|
||||
/* Start the functions we need for the plugin stuff */
|
||||
|
||||
G_MODULE_EXPORT void
|
||||
plugin_register (void)
|
||||
{
|
||||
EOF
|
||||
#
|
||||
# Build code to call all the protocol registration routines.
|
||||
#
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^void proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
|
||||
else
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
#include "register.h"
|
||||
void
|
||||
register_all_protocols(register_cb cb, gpointer client_data)
|
||||
{
|
||||
EOF
|
||||
#
|
||||
# Build code to call all the protocol registration routines.
|
||||
#
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_REGISTER, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^void proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_REGISTER, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
|
||||
|
||||
fi
|
||||
echo '}' >>${outfile}-tmp
|
||||
|
||||
|
||||
#
|
||||
# Build code to call all the protocol handoff registration routines.
|
||||
#
|
||||
if [ "$registertype" = plugin ]
|
||||
then
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
G_MODULE_EXPORT void
|
||||
plugin_reg_handoff(void)
|
||||
{
|
||||
EOF
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^void proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
|
||||
else
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
void
|
||||
register_all_protocol_handoffs(register_cb cb, gpointer client_data)
|
||||
{
|
||||
EOF
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_HANDOFF, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^void proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_HANDOFF, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
|
||||
fi
|
||||
echo '}' >>${outfile}-tmp
|
||||
if [ "$registertype" = plugin ]
|
||||
then
|
||||
echo '#endif' >>${outfile}-tmp
|
||||
else
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
gulong register_count(void)
|
||||
{
|
||||
EOF
|
||||
proto_regs=`grep RA_REGISTER ${outfile}-tmp | wc -l`
|
||||
handoff_regs=`grep RA_HANDOFF ${outfile}-tmp | wc -l`
|
||||
echo " return $proto_regs + $handoff_regs;" >>${outfile}-tmp
|
||||
echo '}' >>${outfile}-tmp
|
||||
fi
|
||||
mv ${outfile}-tmp ${outfile}
|
|
@ -0,0 +1,311 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Looks for registration routines in the protocol dissectors,
|
||||
# and assembles C code to call all the routines.
|
||||
#
|
||||
# This is a Python version of the make-reg-dotc shell script.
|
||||
# Running the shell script on Win32 is very very slow because of
|
||||
# all the process-launching that goes on --- multiple greps and
|
||||
# seds for each input file. I wrote this python version so that
|
||||
# less processes would have to be started.
|
||||
#
|
||||
# $Id: make-dissector-reg.py 40736 2012-01-26 21:38:53Z gerald $
|
||||
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import pickle
|
||||
from stat import *
|
||||
|
||||
VERSION_KEY = '_VERSION'
|
||||
CUR_VERSION = '$Id: make-dissector-reg.py 40736 2012-01-26 21:38:53Z gerald $'
|
||||
|
||||
#
|
||||
# The first argument is the directory in which the source files live.
|
||||
#
|
||||
srcdir = sys.argv[1]
|
||||
|
||||
#
|
||||
# The second argument is either "plugin" or "dissectors"; if it's
|
||||
# "plugin", we build a plugin.c for a plugin, and if it's
|
||||
# "dissectors", we build a register.c for libwireshark.
|
||||
#
|
||||
registertype = sys.argv[2]
|
||||
if registertype == "plugin" or registertype == "plugin_wtap":
|
||||
tmp_filename = "plugin.c-tmp"
|
||||
final_filename = "plugin.c"
|
||||
cache_filename = None
|
||||
preamble = """\
|
||||
/*
|
||||
* Do not modify this file.
|
||||
*
|
||||
* It is created automatically by Makefile or Makefile.nmake.
|
||||
*/
|
||||
"""
|
||||
elif registertype == "dissectors":
|
||||
tmp_filename = "register.c-tmp"
|
||||
final_filename = "register.c"
|
||||
cache_filename = "register-cache.pkl"
|
||||
preamble = """\
|
||||
/*
|
||||
* Do not modify this file.
|
||||
*
|
||||
* It is created automatically by the "register.c" target in
|
||||
* epan/dissectors/Makefile or Makefile.nmake using information in
|
||||
* epan/dissectors/register-cache.pkl.
|
||||
*
|
||||
* You can force this file to be regenerated completely by deleting
|
||||
* it along with epan/dissectors/register-cache.pkl.
|
||||
*/
|
||||
"""
|
||||
else:
|
||||
print(("Unknown output type '%s'" % registertype))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
#
|
||||
# All subsequent arguments are the files to scan.
|
||||
#
|
||||
files = sys.argv[3:]
|
||||
|
||||
# Create the proper list of filenames
|
||||
filenames = []
|
||||
for file in files:
|
||||
if os.path.isfile(file):
|
||||
filenames.append(file)
|
||||
else:
|
||||
filenames.append(os.path.join(srcdir, file))
|
||||
|
||||
if len(filenames) < 1:
|
||||
print("No files found")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# Look through all files, applying the regex to each line.
|
||||
# If the pattern matches, save the "symbol" section to the
|
||||
# appropriate array.
|
||||
regs = {
|
||||
'proto_reg': [],
|
||||
'handoff_reg': [],
|
||||
'wtap_register': [],
|
||||
}
|
||||
|
||||
# For those that don't know Python, r"" indicates a raw string,
|
||||
# devoid of Python escapes.
|
||||
proto_regex0 = r"^(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||||
proto_regex1 = r"void\s+(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||||
|
||||
handoff_regex0 = r"^(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||||
handoff_regex1 = r"void\s+(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||||
|
||||
wtap_reg_regex0 = r"^(?P<symbol>wtap_register_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||||
wtap_reg_regex1 = r"void\s+(?P<symbol>wtap_register_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||||
|
||||
# This table drives the pattern-matching and symbol-harvesting
|
||||
patterns = [
|
||||
( 'proto_reg', re.compile(proto_regex0) ),
|
||||
( 'proto_reg', re.compile(proto_regex1) ),
|
||||
( 'handoff_reg', re.compile(handoff_regex0) ),
|
||||
( 'handoff_reg', re.compile(handoff_regex1) ),
|
||||
( 'wtap_register', re.compile(wtap_reg_regex0) ),
|
||||
( 'wtap_register', re.compile(wtap_reg_regex1) ),
|
||||
]
|
||||
|
||||
# Open our registration symbol cache
|
||||
cache = None
|
||||
if cache_filename:
|
||||
try:
|
||||
cache_file = open(cache_filename, 'rb')
|
||||
cache = pickle.load(cache_file)
|
||||
cache_file.close()
|
||||
if VERSION_KEY not in cache or cache[VERSION_KEY] != CUR_VERSION:
|
||||
cache = {VERSION_KEY: CUR_VERSION}
|
||||
except:
|
||||
cache = {VERSION_KEY: CUR_VERSION}
|
||||
|
||||
print(("Registering %d files, %d cached" % (len(filenames), len(list(cache.keys()))-1)))
|
||||
|
||||
# Grep
|
||||
cache_hits = 0
|
||||
cache_misses = 0
|
||||
for filename in filenames:
|
||||
file = open(filename)
|
||||
cur_mtime = os.fstat(file.fileno())[ST_MTIME]
|
||||
if cache and filename in cache:
|
||||
cdict = cache[filename]
|
||||
if cur_mtime == cdict['mtime']:
|
||||
cache_hits += 1
|
||||
# print "Pulling %s from cache" % (filename)
|
||||
regs['proto_reg'].extend(cdict['proto_reg'])
|
||||
regs['handoff_reg'].extend(cdict['handoff_reg'])
|
||||
regs['wtap_register'].extend(cdict['wtap_register'])
|
||||
file.close()
|
||||
continue
|
||||
# We don't have a cache entry
|
||||
if cache is not None:
|
||||
cache_misses += 1
|
||||
cache[filename] = {
|
||||
'mtime': cur_mtime,
|
||||
'proto_reg': [],
|
||||
'handoff_reg': [],
|
||||
'wtap_register': [],
|
||||
}
|
||||
# print "Searching %s" % (filename)
|
||||
for line in file.readlines():
|
||||
for action in patterns:
|
||||
regex = action[1]
|
||||
match = regex.search(line)
|
||||
if match:
|
||||
symbol = match.group("symbol")
|
||||
sym_type = action[0]
|
||||
regs[sym_type].append(symbol)
|
||||
if cache is not None:
|
||||
# print "Caching %s for %s: %s" % (sym_type, filename, symbol)
|
||||
cache[filename][sym_type].append(symbol)
|
||||
file.close()
|
||||
|
||||
|
||||
if cache is not None and cache_filename is not None:
|
||||
cache_file = open(cache_filename, 'wb')
|
||||
pickle.dump(cache, cache_file)
|
||||
cache_file.close()
|
||||
print(("Cache hits: %d, misses: %d" % (cache_hits, cache_misses)))
|
||||
|
||||
# Make sure we actually processed something
|
||||
if len(regs['proto_reg']) < 1:
|
||||
print("No protocol registrations found")
|
||||
sys.exit(1)
|
||||
|
||||
# Sort the lists to make them pretty
|
||||
regs['proto_reg'].sort()
|
||||
regs['handoff_reg'].sort()
|
||||
regs['wtap_register'].sort()
|
||||
|
||||
reg_code = open(tmp_filename, "w")
|
||||
|
||||
reg_code.write(preamble)
|
||||
|
||||
# Make the routine to register all protocols
|
||||
if registertype == "plugin" or registertype == "plugin_wtap":
|
||||
reg_code.write("""
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
#include "moduleinfo.h"
|
||||
|
||||
#ifndef ENABLE_STATIC
|
||||
G_MODULE_EXPORT const gchar version[] = VERSION;
|
||||
|
||||
/* Start the functions we need for the plugin stuff */
|
||||
|
||||
G_MODULE_EXPORT void
|
||||
plugin_register (void)
|
||||
{
|
||||
""");
|
||||
else:
|
||||
reg_code.write("""
|
||||
#include "register.h"
|
||||
void
|
||||
register_all_protocols(register_cb cb, gpointer client_data)
|
||||
{
|
||||
""");
|
||||
|
||||
for symbol in regs['proto_reg']:
|
||||
if registertype == "plugin" or registertype == "plugin_wtap":
|
||||
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
|
||||
else:
|
||||
line = " {extern void %s (void); if(cb) (*cb)(RA_REGISTER, \"%s\", client_data); %s ();}\n" % (symbol, symbol, symbol)
|
||||
reg_code.write(line)
|
||||
|
||||
reg_code.write("}\n")
|
||||
|
||||
|
||||
# Make the routine to register all protocol handoffs
|
||||
if registertype == "plugin" or registertype == "plugin_wtap":
|
||||
reg_code.write("""
|
||||
G_MODULE_EXPORT void
|
||||
plugin_reg_handoff(void)
|
||||
{
|
||||
""");
|
||||
else:
|
||||
reg_code.write("""
|
||||
void
|
||||
register_all_protocol_handoffs(register_cb cb, gpointer client_data)
|
||||
{
|
||||
""");
|
||||
|
||||
for symbol in regs['handoff_reg']:
|
||||
if registertype == "plugin" or registertype == "plugin_wtap":
|
||||
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
|
||||
else:
|
||||
line = " {extern void %s (void); if(cb) (*cb)(RA_HANDOFF, \"%s\", client_data); %s ();}\n" % (symbol, symbol, symbol)
|
||||
reg_code.write(line)
|
||||
|
||||
reg_code.write("}\n")
|
||||
|
||||
if registertype == "plugin":
|
||||
reg_code.write("#endif\n");
|
||||
elif registertype == "plugin_wtap":
|
||||
reg_code.write("""
|
||||
G_MODULE_EXPORT void
|
||||
register_wtap_module(void)
|
||||
{
|
||||
""");
|
||||
|
||||
for symbol in regs['wtap_register']:
|
||||
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
|
||||
reg_code.write(line)
|
||||
|
||||
reg_code.write("}\n");
|
||||
reg_code.write("#endif\n");
|
||||
else:
|
||||
reg_code.write("""
|
||||
static gulong proto_reg_count(void)
|
||||
{
|
||||
""");
|
||||
|
||||
line = " return %d;\n" % len(regs['proto_reg'])
|
||||
reg_code.write(line)
|
||||
|
||||
reg_code.write("""
|
||||
}
|
||||
""");
|
||||
reg_code.write("""
|
||||
static gulong handoff_reg_count(void)
|
||||
{
|
||||
""");
|
||||
|
||||
line = " return %d;\n" % len(regs['handoff_reg'])
|
||||
reg_code.write(line)
|
||||
|
||||
reg_code.write("""
|
||||
}
|
||||
""");
|
||||
reg_code.write("""
|
||||
gulong register_count(void)
|
||||
{
|
||||
""");
|
||||
|
||||
line = " return proto_reg_count() + handoff_reg_count();"
|
||||
reg_code.write(line)
|
||||
|
||||
reg_code.write("""
|
||||
}\n
|
||||
""");
|
||||
|
||||
|
||||
# Close the file
|
||||
reg_code.close()
|
||||
|
||||
# Remove the old final_file if it exists.
|
||||
try:
|
||||
os.stat(final_filename)
|
||||
os.remove(final_filename)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# Move from tmp file to final file
|
||||
os.rename(tmp_filename, final_filename)
|
|
@ -0,0 +1,2 @@
|
|||
Authors:
|
||||
Michael Ossmann <mike@ossmann.com>
|
|
@ -0,0 +1,89 @@
|
|||
# CMakeLists.txt
|
||||
#
|
||||
# $Id: CMakeLists.txt 31995 2010-02-24 22:32:10Z jmayer $
|
||||
#
|
||||
# Wireshark - Network traffic analyzer
|
||||
# By Gerald Combs <gerald@wireshark.org>
|
||||
# Copyright 1998 Gerald Combs
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
|
||||
project(btbb-wireshark-plugin C)
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
set(CMAKE_BACKWARDS_COMPATIBILITY 2.6)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
|
||||
IF ( NOT CMAKE_INSTALL_LIBDIR )
|
||||
set(CMAKE_INSTALL_LIBDIR ~/.wireshark/plugins)
|
||||
ENDIF ( NOT CMAKE_INSTALL_LIBDIR )
|
||||
MESSAGE (STATUS "Plugin will be installed in: ${CMAKE_INSTALL_LIBDIR}")
|
||||
|
||||
INCLUDE(UseMakeDissectorReg)
|
||||
|
||||
set(GLIB2_MIN_VERSION 2.4.0)
|
||||
|
||||
find_package(GLIB2)
|
||||
include_directories (${GLIB2_INCLUDE_DIRS})
|
||||
|
||||
find_package(Wireshark)
|
||||
include_directories (${WIRESHARK_INCLUDE_DIRS})
|
||||
|
||||
set(LINK_MODE_LIB SHARED)
|
||||
set(LINK_MODE_MODULE MODULE)
|
||||
|
||||
|
||||
set(DISSECTOR_SRC
|
||||
packet-btbb.c
|
||||
packet-btbrlmp.c
|
||||
)
|
||||
|
||||
set(PLUGIN_FILES
|
||||
plugin.c
|
||||
${DISSECTOR_SRC}
|
||||
)
|
||||
|
||||
set(CLEAN_FILES
|
||||
${PLUGIN_FILES}
|
||||
)
|
||||
|
||||
if (WERROR)
|
||||
set_source_files_properties(
|
||||
${CLEAN_FILES}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS -Werror
|
||||
)
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
register_dissector_files(plugin.c
|
||||
plugin
|
||||
${DISSECTOR_SRC}
|
||||
)
|
||||
|
||||
add_library(btbb ${LINK_MODE_MODULE}
|
||||
${PLUGIN_FILES}
|
||||
)
|
||||
set_target_properties(btbb PROPERTIES PREFIX "")
|
||||
set_target_properties(btbb PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}")
|
||||
|
||||
target_link_libraries(btbb wireshark)
|
||||
|
||||
install(TARGETS btbb
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/ NAMELINK_SKIP
|
||||
)
|
||||
|
|
@ -0,0 +1,340 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,17 @@
|
|||
BTBB Wireshark plugin
|
||||
|
||||
This is the Bluetooth baseband plugin for Wireshark, it also includes an LMP
|
||||
level dissector.
|
||||
|
||||
To build this on Debian/Ubuntu/BackTrack linux distributions:
|
||||
sudo apt-get install wireshark-dev wireshark
|
||||
cd libbtbb/wireshark/plugins/btbb/
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
make install
|
||||
|
||||
This will install to the .wireshark/ in your home directory. To override this
|
||||
set the DESTDIR environment variable when running cmake.
|
||||
|
Binary file not shown.
|
@ -0,0 +1,22 @@
|
|||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,27 @@
|
|||
Copyright notice for the files copied from
|
||||
http://www.opensync.org/browser/branches/3rd-party-cmake-modules/modules
|
||||
|
||||
$Id: COPYING-CMAKE-SCRIPTS 34248 2010-09-25 15:38:12Z jmayer $
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,238 @@
|
|||
#
|
||||
# $Id: FindGLIB2.cmake 34248 2010-09-25 15:38:12Z jmayer $
|
||||
#
|
||||
# - Try to find GLib2
|
||||
# Once done this will define
|
||||
#
|
||||
# GLIB2_FOUND - system has GLib2
|
||||
# GLIB2_INCLUDE_DIRS - the GLib2 include directory
|
||||
# GLIB2_LIBRARIES - Link these to use GLib2
|
||||
#
|
||||
# HAVE_GLIB_GREGEX_H glib has gregex.h header and
|
||||
# supports g_regex_match_simple
|
||||
#
|
||||
# Copyright (c) 2006 Andreas Schneider <mail@cynapses.org>
|
||||
# Copyright (c) 2006 Philippe Bernery <philippe.bernery@gmail.com>
|
||||
# Copyright (c) 2007 Daniel Gollub <gollub@b1-systems.de>
|
||||
# Copyright (c) 2007 Alban Browaeys <prahal@yahoo.com>
|
||||
# Copyright (c) 2008 Michael Bell <michael.bell@web.de>
|
||||
# Copyright (c) 2008-2009 Bjoern Ricks <bjoern.ricks@googlemail.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
|
||||
IF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS )
|
||||
# in cache already
|
||||
SET(GLIB2_FOUND TRUE)
|
||||
ELSE (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS )
|
||||
|
||||
INCLUDE(FindPkgConfig)
|
||||
|
||||
## Glib
|
||||
IF ( GLIB2_FIND_REQUIRED )
|
||||
SET( _pkgconfig_REQUIRED "REQUIRED" )
|
||||
ELSE ( GLIB2_FIND_REQUIRED )
|
||||
SET( _pkgconfig_REQUIRED "" )
|
||||
ENDIF ( GLIB2_FIND_REQUIRED )
|
||||
|
||||
IF ( GLIB2_MIN_VERSION )
|
||||
PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0>=${GLIB2_MIN_VERSION} )
|
||||
ELSE ( GLIB2_MIN_VERSION )
|
||||
PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0 )
|
||||
ENDIF ( GLIB2_MIN_VERSION )
|
||||
IF ( PKG_CONFIG_FOUND )
|
||||
IF ( GLIB2_FOUND )
|
||||
SET ( GLIB2_CORE_FOUND TRUE )
|
||||
ELSE ( GLIB2_FOUND )
|
||||
SET ( GLIB2_CORE_FOUND FALSE )
|
||||
ENDIF ( GLIB2_FOUND )
|
||||
ENDIF ( PKG_CONFIG_FOUND )
|
||||
|
||||
# Look for glib2 include dir and libraries w/o pkgconfig
|
||||
IF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND )
|
||||
FIND_PATH(
|
||||
_glibconfig_include_DIR
|
||||
NAMES
|
||||
glibconfig.h
|
||||
PATHS
|
||||
/opt/gnome/lib64
|
||||
/opt/gnome/lib
|
||||
/opt/lib/
|
||||
/opt/local/lib
|
||||
/sw/lib/
|
||||
/usr/lib64
|
||||
/usr/lib
|
||||
/usr/local/include
|
||||
${CMAKE_LIBRARY_PATH}
|
||||
PATH_SUFFIXES
|
||||
glib-2.0/include
|
||||
)
|
||||
|
||||
FIND_PATH(
|
||||
_glib2_include_DIR
|
||||
NAMES
|
||||
glib.h
|
||||
PATHS
|
||||
/opt/gnome/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
PATH_SUFFIXES
|
||||
glib-2.0
|
||||
)
|
||||
|
||||
#MESSAGE(STATUS "Glib headers: ${_glib2_include_DIR}")
|
||||
|
||||
FIND_LIBRARY(
|
||||
_glib2_link_DIR
|
||||
NAMES
|
||||
glib-2.0
|
||||
glib
|
||||
PATHS
|
||||
/opt/gnome/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
)
|
||||
IF ( _glib2_include_DIR AND _glib2_link_DIR )
|
||||
SET ( _glib2_FOUND TRUE )
|
||||
ENDIF ( _glib2_include_DIR AND _glib2_link_DIR )
|
||||
|
||||
|
||||
IF ( _glib2_FOUND )
|
||||
SET ( GLIB2_INCLUDE_DIRS ${_glib2_include_DIR} ${_glibconfig_include_DIR} )
|
||||
SET ( GLIB2_LIBRARIES ${_glib2_link_DIR} )
|
||||
SET ( GLIB2_CORE_FOUND TRUE )
|
||||
ELSE ( _glib2_FOUND )
|
||||
SET ( GLIB2_CORE_FOUND FALSE )
|
||||
ENDIF ( _glib2_FOUND )
|
||||
|
||||
# Handle dependencies
|
||||
# libintl
|
||||
IF ( NOT LIBINTL_FOUND )
|
||||
FIND_PATH(LIBINTL_INCLUDE_DIR
|
||||
NAMES
|
||||
libintl.h
|
||||
PATHS
|
||||
/opt/gnome/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
)
|
||||
|
||||
FIND_LIBRARY(LIBINTL_LIBRARY
|
||||
NAMES
|
||||
intl
|
||||
PATHS
|
||||
/opt/gnome/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/local/lib
|
||||
/usr/lib
|
||||
)
|
||||
|
||||
IF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR)
|
||||
SET (LIBINTL_FOUND TRUE)
|
||||
ENDIF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR)
|
||||
ENDIF ( NOT LIBINTL_FOUND )
|
||||
|
||||
# libiconv
|
||||
IF ( NOT LIBICONV_FOUND )
|
||||
FIND_PATH(LIBICONV_INCLUDE_DIR
|
||||
NAMES
|
||||
iconv.h
|
||||
PATHS
|
||||
/opt/gnome/include
|
||||
/opt/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
/sw/include
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
PATH_SUFFIXES
|
||||
glib-2.0
|
||||
)
|
||||
|
||||
FIND_LIBRARY(LIBICONV_LIBRARY
|
||||
NAMES
|
||||
iconv
|
||||
PATHS
|
||||
/opt/gnome/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
)
|
||||
|
||||
IF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
|
||||
SET (LIBICONV_FOUND TRUE)
|
||||
ENDIF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
|
||||
ENDIF ( NOT LIBICONV_FOUND )
|
||||
|
||||
IF (LIBINTL_FOUND)
|
||||
SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBINTL_LIBRARY})
|
||||
SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBINTL_INCLUDE_DIR})
|
||||
ENDIF (LIBINTL_FOUND)
|
||||
|
||||
IF (LIBICONV_FOUND)
|
||||
SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY})
|
||||
SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR})
|
||||
ENDIF (LIBICONV_FOUND)
|
||||
|
||||
ENDIF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND )
|
||||
##
|
||||
|
||||
IF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES)
|
||||
SET (GLIB2_FOUND TRUE)
|
||||
ENDIF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES)
|
||||
|
||||
IF (GLIB2_FOUND)
|
||||
IF (NOT GLIB2_FIND_QUIETLY)
|
||||
MESSAGE (STATUS "Found GLib2: ${GLIB2_LIBRARIES} ${GLIB2_INCLUDE_DIRS}")
|
||||
ENDIF (NOT GLIB2_FIND_QUIETLY)
|
||||
ELSE (GLIB2_FOUND)
|
||||
IF (GLIB2_FIND_REQUIRED)
|
||||
MESSAGE (SEND_ERROR "Could not find GLib2")
|
||||
ENDIF (GLIB2_FIND_REQUIRED)
|
||||
ENDIF (GLIB2_FOUND)
|
||||
|
||||
# show the GLIB2_INCLUDE_DIRS and GLIB2_LIBRARIES variables only in the advanced view
|
||||
MARK_AS_ADVANCED(GLIB2_INCLUDE_DIRS GLIB2_LIBRARIES)
|
||||
MARK_AS_ADVANCED(LIBICONV_INCLUDE_DIR LIBICONV_LIBRARY)
|
||||
MARK_AS_ADVANCED(LIBINTL_INCLUDE_DIR LIBINTL_LIBRARY)
|
||||
|
||||
ENDIF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS)
|
||||
|
||||
IF ( WIN32 )
|
||||
# include libiconv for win32
|
||||
IF ( NOT LIBICONV_FOUND )
|
||||
FIND_PATH(LIBICONV_INCLUDE_DIR iconv.h PATH_SUFFIXES glib-2.0)
|
||||
|
||||
FIND_LIBRARY(LIBICONV_LIBRARY NAMES iconv)
|
||||
|
||||
IF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
|
||||
SET (LIBICONV_FOUND TRUE)
|
||||
ENDIF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
|
||||
ENDIF ( NOT LIBICONV_FOUND )
|
||||
IF (LIBICONV_FOUND)
|
||||
SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY})
|
||||
SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR})
|
||||
ENDIF (LIBICONV_FOUND)
|
||||
ENDIF ( WIN32 )
|
||||
|
||||
IF ( GLIB2_FOUND )
|
||||
# Check if system has a newer version of glib
|
||||
# which supports g_regex_match_simple
|
||||
INCLUDE( CheckIncludeFiles )
|
||||
SET( CMAKE_REQUIRED_INCLUDES ${GLIB2_INCLUDE_DIRS} )
|
||||
CHECK_INCLUDE_FILES ( glib/gregex.h HAVE_GLIB_GREGEX_H )
|
||||
CHECK_INCLUDE_FILES ( glib/gchecksum.h HAVE_GLIB_GCHECKSUM_H )
|
||||
# Reset CMAKE_REQUIRED_INCLUDES
|
||||
SET( CMAKE_REQUIRED_INCLUDES "" )
|
||||
ENDIF( GLIB2_FOUND )
|
|
@ -0,0 +1,28 @@
|
|||
#
|
||||
# Try to find the wireshark library and its includes
|
||||
#
|
||||
# This snippet sets the following variables:
|
||||
# WIRESHARK_FOUND True if wireshark library got found
|
||||
# WIRESHARK_INCLUDE_DIRS Location of the wireshark headers
|
||||
# WIRESHARK_LIBRARIES List of libraries to use wireshark
|
||||
#
|
||||
# Copyright (c) 2011 Reinhold Kainhofer <reinhold@kainhofer.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
# wireshark does not install its library with pkg-config information,
|
||||
# so we need to manually find the libraries and headers
|
||||
|
||||
FIND_PATH( WIRESHARK_INCLUDE_DIRS epan/packet.h PATH_SUFFIXES wireshark )
|
||||
FIND_LIBRARY( WIRESHARK_LIBRARIES wireshark )
|
||||
|
||||
# Report results
|
||||
IF ( WIRESHARK_LIBRARIES AND WIRESHARK_INCLUDE_DIRS )
|
||||
SET( WIRESHARK_FOUND 1 )
|
||||
ELSE ( WIRESHARK_LIBRARIES AND WIRESHARK_INCLUDE_DIRS )
|
||||
MESSAGE( SEND_ERROR "Could NOT find the wireshark library and headers" )
|
||||
ENDIF ( WIRESHARK_LIBRARIES AND WIRESHARK_INCLUDE_DIRS )
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#
|
||||
# $Id: UseMakeDissectorReg.cmake 33616 2010-07-22 12:18:36Z stig $
|
||||
#
|
||||
MACRO(REGISTER_DISSECTOR_FILES _outputfile _registertype )
|
||||
# FIXME: Only the Python stuff has been implemented
|
||||
# Make this into a MACRO, to avoid duplication with plugins/.../
|
||||
#register.c: $(plugin_src) $(ALL_DISSECTORS_SRC) $(top_srcdir)/tools/make-dissector-reg \
|
||||
# $(top_srcdir)/tools/make-dissector-reg.py
|
||||
# @if test -n "$(PYTHON)"; then \
|
||||
# echo Making register.c with python ; \
|
||||
# $(PYTHON) $(top_srcdir)/tools/make-dissector-reg.py $(srcdir) \
|
||||
# dissectors $(ALL_DISSECTORS_SRC) ; \
|
||||
# else \
|
||||
# echo Making register.c with shell script ; \
|
||||
# $(top_srcdir)/tools/make-dissector-reg $(srcdir) \
|
||||
# dissectors $(plugin_src) $(ALL_DISSECTORS_SRC) ; \
|
||||
# fi
|
||||
set( _sources ${ARGN} )
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT
|
||||
${_outputfile}
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
${CMAKE_SOURCE_DIR}/tools/make-dissector-reg.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${_registertype}
|
||||
${_sources}
|
||||
DEPENDS
|
||||
${_sources}
|
||||
${CMAKE_SOURCE_DIR}/tools/make-dissector-reg
|
||||
${CMAKE_SOURCE_DIR}/tools/make-dissector-reg.py
|
||||
)
|
||||
ENDMACRO(REGISTER_DISSECTOR_FILES)
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
/* Included *after* config.h, in order to re-define these macros */
|
||||
|
||||
#ifdef PACKAGE
|
||||
#undef PACKAGE
|
||||
#endif
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "btbb"
|
||||
|
||||
|
||||
#ifdef VERSION
|
||||
#undef VERSION
|
||||
#endif
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.0.1"
|
||||
|
|
@ -0,0 +1,593 @@
|
|||
/* packet-btbb.c
|
||||
* Routines for Bluetooth baseband dissection
|
||||
* Copyright 2009, Michael Ossmann <mike@ossmann.com>
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#else
|
||||
#include <wireshark/config.h>
|
||||
#endif
|
||||
|
||||
#include <epan/packet.h>
|
||||
#include <epan/prefs.h>
|
||||
|
||||
/* function prototypes */
|
||||
void proto_reg_handoff_btbb(void);
|
||||
|
||||
/* initialize the protocol and registered fields */
|
||||
static int proto_btbb = -1;
|
||||
static int hf_btbb_meta = -1;
|
||||
static int hf_btbb_dir = -1;
|
||||
static int hf_btbb_clk = -1;
|
||||
static int hf_btbb_channel = -1;
|
||||
static int hf_btbb_addrbits = -1;
|
||||
static int hf_btbb_clkbits = -1;
|
||||
static int hf_btbb_pkthdr = -1;
|
||||
static int hf_btbb_ltaddr = -1;
|
||||
static int hf_btbb_type = -1;
|
||||
static int hf_btbb_flags = -1;
|
||||
static int hf_btbb_flow = -1;
|
||||
static int hf_btbb_arqn = -1;
|
||||
static int hf_btbb_seqn = -1;
|
||||
static int hf_btbb_hec = -1;
|
||||
static int hf_btbb_payload = -1;
|
||||
static int hf_btbb_pldhdr = -1;
|
||||
static int hf_btbb_llid = -1;
|
||||
static int hf_btbb_pldflow = -1;
|
||||
static int hf_btbb_length = -1;
|
||||
static int hf_btbb_pldbody = -1;
|
||||
static int hf_btbb_crc = -1;
|
||||
static int hf_btbb_fhs_parity = -1;
|
||||
static int hf_btbb_fhs_lap = -1;
|
||||
static int hf_btbb_fhs_eir = -1;
|
||||
static int hf_btbb_fhs_sr = -1;
|
||||
static int hf_btbb_fhs_uap = -1;
|
||||
static int hf_btbb_fhs_nap = -1;
|
||||
static int hf_btbb_fhs_class = -1;
|
||||
static int hf_btbb_fhs_ltaddr = -1;
|
||||
static int hf_btbb_fhs_clk = -1;
|
||||
static int hf_btbb_fhs_psmode = -1;
|
||||
|
||||
/* field values */
|
||||
static const true_false_string direction = {
|
||||
"Slave to Master",
|
||||
"Master to Slave"
|
||||
};
|
||||
|
||||
static const true_false_string clock_bits = {
|
||||
"27",
|
||||
"6"
|
||||
};
|
||||
|
||||
static const true_false_string address_bits = {
|
||||
"48 (NAP known)",
|
||||
"32 (NAP unknown)"
|
||||
};
|
||||
|
||||
static const value_string packet_types[] = {
|
||||
/* generic names for unknown logical transport */
|
||||
{ 0x0, "NULL" },
|
||||
{ 0x1, "POLL" },
|
||||
{ 0x2, "FHS" },
|
||||
{ 0x3, "DM1" },
|
||||
{ 0x4, "DH1/2-DH1" },
|
||||
{ 0x5, "HV1" },
|
||||
{ 0x6, "HV2/2-EV3" },
|
||||
{ 0x7, "HV3/EV3/3-EV3" },
|
||||
{ 0x8, "DV/3-DH1" },
|
||||
{ 0x9, "AUX1" },
|
||||
{ 0xa, "DM3/2-DH3" },
|
||||
{ 0xb, "DH3/3-DH3" },
|
||||
{ 0xc, "EV4/2-EV5" },
|
||||
{ 0xd, "EV5/3-EV5" },
|
||||
{ 0xe, "DM5/2-DH5" },
|
||||
{ 0xf, "DH5/3-DH5" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const value_string sr_modes[] = {
|
||||
{ 0x0, "R0" },
|
||||
{ 0x1, "R1" },
|
||||
{ 0x2, "R2" },
|
||||
{ 0x3, "Reserved" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const range_string ps_modes[] = {
|
||||
{ 0x0, 0x0, "Mandatory scan mode" },
|
||||
{ 0x1, 0x7, "Reserved" },
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static const value_string llid_codes[] = {
|
||||
{ 0x0, "undefined" },
|
||||
{ 0x1, "Continuation fragment of an L2CAP message (ACL-U)" },
|
||||
{ 0x2, "Start of an L2CAP message or no fragmentation (ACL-U)" },
|
||||
{ 0x3, "LMP message (ACL-C)" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* initialize the subtree pointers */
|
||||
static gint ett_btbb = -1;
|
||||
static gint ett_btbb_meta = -1;
|
||||
static gint ett_btbb_pkthdr = -1;
|
||||
static gint ett_btbb_flags = -1;
|
||||
static gint ett_btbb_payload = -1;
|
||||
static gint ett_btbb_pldhdr = -1;
|
||||
|
||||
/* subdissectors */
|
||||
static dissector_handle_t btbrlmp_handle = NULL;
|
||||
static dissector_handle_t btl2cap_handle = NULL;
|
||||
|
||||
/* packet header flags */
|
||||
static const int *flag_fields[] = {
|
||||
&hf_btbb_flow,
|
||||
&hf_btbb_arqn,
|
||||
&hf_btbb_seqn,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* one byte payload header */
|
||||
int
|
||||
dissect_payload_header1(proto_tree *tree, tvbuff_t *tvb, int offset)
|
||||
{
|
||||
proto_item *hdr_item;
|
||||
proto_tree *hdr_tree;
|
||||
|
||||
DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1);
|
||||
|
||||
hdr_item = proto_tree_add_item(tree, hf_btbb_pldhdr, tvb, offset, 1, ENC_NA);
|
||||
hdr_tree = proto_item_add_subtree(hdr_item, ett_btbb_pldhdr);
|
||||
|
||||
proto_tree_add_item(hdr_tree, hf_btbb_llid, tvb, offset, 1, ENC_NA);
|
||||
proto_tree_add_item(hdr_tree, hf_btbb_pldflow, tvb, offset, 1, ENC_NA);
|
||||
proto_tree_add_item(hdr_tree, hf_btbb_length, tvb, offset, 1, ENC_NA);
|
||||
|
||||
/* payload length */
|
||||
return tvb_get_guint8(tvb, offset) >> 3;
|
||||
}
|
||||
|
||||
void
|
||||
dissect_fhs(proto_tree *tree, tvbuff_t *tvb, int offset)
|
||||
{
|
||||
proto_item *fhs_item, *psmode_item;
|
||||
proto_tree *fhs_tree;
|
||||
const gchar *description;
|
||||
guint8 psmode;
|
||||
|
||||
DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) == 20);
|
||||
|
||||
fhs_item = proto_tree_add_item(tree, hf_btbb_payload, tvb, offset, -1, ENC_NA);
|
||||
fhs_tree = proto_item_add_subtree(fhs_item, ett_btbb_payload);
|
||||
|
||||
/* Use proto_tree_add_bits_item() to get around 32bit limit on bitmasks */
|
||||
proto_tree_add_bits_item(fhs_tree, hf_btbb_fhs_parity, tvb, offset*8, 34, ENC_LITTLE_ENDIAN);
|
||||
/* proto_tree_add_item(fhs_tree, hf_btbb_fhs_parity, tvb, offset, 5, ENC_LITTLE_ENDIAN); */
|
||||
offset += 4;
|
||||
|
||||
proto_tree_add_item(fhs_tree, hf_btbb_fhs_lap, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
||||
offset += 3;
|
||||
|
||||
proto_tree_add_item(fhs_tree, hf_btbb_fhs_eir, tvb, offset, 1, ENC_NA);
|
||||
/* skipping 1 undefined bit */
|
||||
proto_tree_add_item(fhs_tree, hf_btbb_fhs_sr, tvb, offset, 1, ENC_NA);
|
||||
/* skipping 2 reserved bits */
|
||||
offset += 1;
|
||||
|
||||
proto_tree_add_item(fhs_tree, hf_btbb_fhs_uap, tvb, offset, 1, ENC_NA);
|
||||
offset += 1;
|
||||
|
||||
proto_tree_add_item(fhs_tree, hf_btbb_fhs_nap, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
|
||||
proto_tree_add_item(fhs_tree, hf_btbb_fhs_class, tvb, offset, 3, ENC_LITTLE_ENDIAN);
|
||||
offset += 3;
|
||||
|
||||
proto_tree_add_item(fhs_tree, hf_btbb_fhs_ltaddr, tvb, offset, 1, ENC_NA);
|
||||
proto_tree_add_item(fhs_tree, hf_btbb_fhs_clk, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
||||
offset += 3;
|
||||
|
||||
psmode = tvb_get_guint8(tvb, offset);
|
||||
description = try_rval_to_str(psmode, ps_modes);
|
||||
psmode_item = proto_tree_add_item(fhs_tree, hf_btbb_fhs_psmode, tvb, offset, 1, ENC_NA);
|
||||
if (description)
|
||||
proto_item_append_text(psmode_item, " (%s)", description);
|
||||
offset += 1;
|
||||
|
||||
proto_tree_add_item(fhs_tree, hf_btbb_crc, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
void
|
||||
dissect_dm1(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset)
|
||||
{
|
||||
int len; /* payload length indicated by payload header */
|
||||
int llid; /* logical link id */
|
||||
int l2len; /* length indicated by l2cap header */
|
||||
proto_item *dm1_item;
|
||||
proto_tree *dm1_tree;
|
||||
tvbuff_t *pld_tvb;
|
||||
|
||||
/*
|
||||
* FIXME
|
||||
* I'm probably doing a terrible, terrible thing here, but it gets my
|
||||
* initial test cases working.
|
||||
*/
|
||||
guint16 fake_acl_data;
|
||||
|
||||
DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 3);
|
||||
|
||||
dm1_item = proto_tree_add_item(tree, hf_btbb_payload, tvb, offset, -1, ENC_NA);
|
||||
dm1_tree = proto_item_add_subtree(dm1_item, ett_btbb_payload);
|
||||
|
||||
len = dissect_payload_header1(dm1_tree, tvb, offset);
|
||||
llid = tvb_get_guint8(tvb, offset) & 0x3;
|
||||
offset += 1;
|
||||
|
||||
DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) == len + 2);
|
||||
|
||||
if (llid == 3 && btbrlmp_handle) {
|
||||
/* LMP */
|
||||
pld_tvb = tvb_new_subset(tvb, offset, len, len);
|
||||
call_dissector(btbrlmp_handle, pld_tvb, pinfo, dm1_tree);
|
||||
} else if (llid == 2 && btl2cap_handle) {
|
||||
/* unfragmented L2CAP or start of fragment */
|
||||
l2len = tvb_get_letohs(tvb, offset);
|
||||
if (l2len + 4 == len) {
|
||||
/* unfragmented */
|
||||
pinfo->private_data = &fake_acl_data;
|
||||
pld_tvb = tvb_new_subset(tvb, offset, len, len);
|
||||
call_dissector(btl2cap_handle, pld_tvb, pinfo, dm1_tree);
|
||||
} else {
|
||||
/* start of fragment */
|
||||
proto_tree_add_item(dm1_tree, hf_btbb_pldbody, tvb, offset, len, ENC_NA);
|
||||
}
|
||||
} else {
|
||||
proto_tree_add_item(dm1_tree, hf_btbb_pldbody, tvb, offset, len, ENC_NA);
|
||||
}
|
||||
offset += len;
|
||||
|
||||
proto_tree_add_item(dm1_tree, hf_btbb_crc, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
/* dissect a packet */
|
||||
static int
|
||||
dissect_btbb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
||||
{
|
||||
proto_item *btbb_item, *meta_item, *pkthdr_item;
|
||||
proto_tree *btbb_tree, *meta_tree, *pkthdr_tree;
|
||||
int offset;
|
||||
/* Avoid error: 'type' may be used uninitialized in this function */
|
||||
guint8 type = 0xff;
|
||||
const gchar *info;
|
||||
|
||||
/* sanity check: length */
|
||||
if (tvb_length(tvb) > 0 && tvb_length(tvb) < 9)
|
||||
/* bad length: look for a different dissector */
|
||||
return 0;
|
||||
|
||||
/* maybe should verify HEC */
|
||||
|
||||
/* make entries in protocol column and info column on summary display */
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Bluetooth");
|
||||
|
||||
if (tvb_length(tvb) == 0) {
|
||||
info = "ID";
|
||||
} else {
|
||||
type = (tvb_get_guint8(tvb, 6) >> 3) & 0x0f;
|
||||
info = val_to_str(type, packet_types, "Unknown type: 0x%x");
|
||||
}
|
||||
|
||||
col_clear(pinfo->cinfo, COL_INFO);
|
||||
col_add_str(pinfo->cinfo, COL_INFO, info);
|
||||
|
||||
/* see if we are being asked for details */
|
||||
if (tree) {
|
||||
|
||||
/* create display subtree for the protocol */
|
||||
offset = 0;
|
||||
btbb_item = proto_tree_add_item(tree, proto_btbb, tvb, offset, -1, ENC_NA);
|
||||
btbb_tree = proto_item_add_subtree(btbb_item, ett_btbb);
|
||||
|
||||
/* ID packets have no header, no payload */
|
||||
if (tvb_length(tvb) == 0)
|
||||
return 1;
|
||||
|
||||
/* meta data */
|
||||
meta_item = proto_tree_add_item(btbb_tree, hf_btbb_meta, tvb, offset, 3, ENC_NA);
|
||||
meta_tree = proto_item_add_subtree(meta_item, ett_btbb_meta);
|
||||
|
||||
proto_tree_add_item(meta_tree, hf_btbb_dir, tvb, offset, 1, ENC_NA);
|
||||
proto_tree_add_item(meta_tree, hf_btbb_clk, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
||||
offset += 4;
|
||||
|
||||
proto_tree_add_item(meta_tree, hf_btbb_channel, tvb, offset, 1, ENC_NA);
|
||||
offset += 1;
|
||||
|
||||
proto_tree_add_item(meta_tree, hf_btbb_clkbits, tvb, offset, 1, ENC_NA);
|
||||
proto_tree_add_item(meta_tree, hf_btbb_addrbits, tvb, offset, 1, ENC_NA);
|
||||
offset += 1;
|
||||
|
||||
/* packet header */
|
||||
pkthdr_item = proto_tree_add_item(btbb_tree, hf_btbb_pkthdr, tvb, offset, 3, ENC_NA);
|
||||
pkthdr_tree = proto_item_add_subtree(pkthdr_item, ett_btbb_pkthdr);
|
||||
|
||||
proto_tree_add_item(pkthdr_tree, hf_btbb_ltaddr, tvb, offset, 1, ENC_NA);
|
||||
proto_tree_add_item(pkthdr_tree, hf_btbb_type, tvb, offset, 1, ENC_NA);
|
||||
offset += 1;
|
||||
proto_tree_add_bitmask(pkthdr_tree, tvb, offset, hf_btbb_flags,
|
||||
ett_btbb_flags, flag_fields, ENC_NA);
|
||||
offset += 1;
|
||||
proto_tree_add_item(pkthdr_tree, hf_btbb_hec, tvb, offset, 1, ENC_NA);
|
||||
offset += 1;
|
||||
|
||||
/* payload */
|
||||
switch (type) {
|
||||
case 0x0: /* NULL */
|
||||
case 0x1: /* POLL */
|
||||
break;
|
||||
case 0x2: /* FHS */
|
||||
dissect_fhs(btbb_tree, tvb, offset);
|
||||
break;
|
||||
case 0x3: /* DM1 */
|
||||
dissect_dm1(btbb_tree, tvb, pinfo, offset);
|
||||
break;
|
||||
case 0x4: /* DH1/2-DH1 */
|
||||
dissect_dm1(btbb_tree, tvb, pinfo, offset);
|
||||
break;
|
||||
case 0x5: /* HV1 */
|
||||
case 0x6: /* HV2/2-EV3 */
|
||||
case 0x7: /* HV3/EV3/3-EV3 */
|
||||
case 0x8: /* DV/3-DH1 */
|
||||
case 0x9: /* AUX1 */
|
||||
case 0xa: /* DM3/2-DH3 */
|
||||
case 0xb: /* DH3/3-DH3 */
|
||||
case 0xc: /* EV4/2-EV5 */
|
||||
case 0xd: /* EV5/3-EV5 */
|
||||
case 0xe: /* DM5/2-DH5 */
|
||||
case 0xf: /* DH5/3-DH5 */
|
||||
proto_tree_add_item(btbb_tree, hf_btbb_payload, tvb, offset, -1, ENC_NA);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the amount of data this dissector was able to dissect */
|
||||
return tvb_length(tvb);
|
||||
}
|
||||
|
||||
/* register the protocol with Wireshark */
|
||||
void
|
||||
proto_register_btbb(void)
|
||||
{
|
||||
/* list of fields */
|
||||
static hf_register_info hf[] = {
|
||||
{ &hf_btbb_meta,
|
||||
{ "Meta Data", "btbb.meta",
|
||||
FT_NONE, BASE_NONE, NULL, 0x0,
|
||||
"Meta Data About the Packet", HFILL }
|
||||
},
|
||||
{ &hf_btbb_dir,
|
||||
{ "Direction", "btbb.dir",
|
||||
FT_BOOLEAN, 8, TFS(&direction), 0x01,
|
||||
"Direction of Transmission", HFILL }
|
||||
},
|
||||
{ &hf_btbb_clk,
|
||||
{ "CLK", "btbb.clk",
|
||||
FT_UINT32, BASE_HEX, NULL, 0x0,
|
||||
"Clock bits 1 through 27", HFILL }
|
||||
},
|
||||
{ &hf_btbb_channel,
|
||||
{ "Channel", "btbb.channel",
|
||||
FT_UINT8, BASE_DEC, NULL, 0x0,
|
||||
"Channel (0-78)", HFILL }
|
||||
},
|
||||
{ &hf_btbb_clkbits,
|
||||
{ "Known Clock Bits", "btbb.clkbits",
|
||||
FT_BOOLEAN, 8, TFS(&clock_bits), 0x01,
|
||||
"Number of Known Master CLK Bits (6 or 27)", HFILL }
|
||||
},
|
||||
{ &hf_btbb_addrbits,
|
||||
{ "Known Address Bits", "btbb.addrbits",
|
||||
FT_BOOLEAN, 8, TFS(&address_bits), 0x02,
|
||||
"Number of Known Bits of BD_ADDR (32 or 48)", HFILL }
|
||||
},
|
||||
{ &hf_btbb_pkthdr,
|
||||
{ "Packet Header", "btbb.pkthdr",
|
||||
FT_NONE, BASE_NONE, NULL, 0x0,
|
||||
"Bluetooth Baseband Packet Header", HFILL }
|
||||
},
|
||||
{ &hf_btbb_ltaddr,
|
||||
{ "LT_ADDR", "btbb.lt_addr",
|
||||
FT_UINT8, BASE_HEX, NULL, 0x07,
|
||||
"Logical Transport Address", HFILL }
|
||||
},
|
||||
{ &hf_btbb_type,
|
||||
{ "TYPE", "btbb.type",
|
||||
FT_UINT8, BASE_HEX, VALS(packet_types), 0x78,
|
||||
"Packet Type", HFILL }
|
||||
},
|
||||
{ &hf_btbb_flags,
|
||||
{ "Flags", "btbb.flags",
|
||||
FT_UINT8, BASE_HEX, NULL, 0x0,
|
||||
"Packet Header Flags", HFILL }
|
||||
},
|
||||
{ &hf_btbb_flow,
|
||||
{ "FLOW", "btbb.flow",
|
||||
FT_BOOLEAN, 8, NULL, 0x01,
|
||||
"Flow control indication", HFILL }
|
||||
},
|
||||
{ &hf_btbb_arqn,
|
||||
{ "ARQN", "btbb.arqn",
|
||||
FT_BOOLEAN, 8, NULL, 0x02,
|
||||
"Acknowledgment indication", HFILL }
|
||||
},
|
||||
{ &hf_btbb_seqn,
|
||||
{ "SEQN", "btbb.seqn",
|
||||
FT_BOOLEAN, 8, NULL, 0x04,
|
||||
"Sequence number", HFILL }
|
||||
},
|
||||
{ &hf_btbb_hec,
|
||||
{ "HEC", "btbb.lt_addr",
|
||||
FT_UINT8, BASE_HEX, NULL, 0x0,
|
||||
"Header Error Check", HFILL }
|
||||
},
|
||||
{ &hf_btbb_payload,
|
||||
{ "Payload", "btbb.payload",
|
||||
FT_NONE, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL }
|
||||
},
|
||||
{ &hf_btbb_llid,
|
||||
{ "LLID", "btbb.llid",
|
||||
FT_UINT8, BASE_HEX, VALS(llid_codes), 0x03,
|
||||
"Logical Link ID", HFILL }
|
||||
},
|
||||
{ &hf_btbb_pldflow,
|
||||
{ "Flow", "btbb.flow",
|
||||
FT_BOOLEAN, 8, NULL, 0x04,
|
||||
"Payload Flow indication", HFILL }
|
||||
},
|
||||
{ &hf_btbb_length,
|
||||
{ "Length", "btbb.length",
|
||||
FT_UINT8, BASE_DEC, NULL, 0xf8,
|
||||
"Payload Length", HFILL }
|
||||
},
|
||||
{ &hf_btbb_pldhdr,
|
||||
{ "Payload Header", "btbb.pldhdr",
|
||||
FT_NONE, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL }
|
||||
},
|
||||
{ &hf_btbb_pldbody,
|
||||
{ "Payload Body", "btbb.pldbody",
|
||||
FT_BYTES, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL }
|
||||
},
|
||||
{ &hf_btbb_crc,
|
||||
{ "CRC", "btbb.crc",
|
||||
FT_UINT16, BASE_HEX, NULL, 0x0,
|
||||
"Payload CRC", HFILL }
|
||||
},
|
||||
{ &hf_btbb_fhs_parity,
|
||||
{ "Parity", "btbb.parity",
|
||||
/* FIXME this doesn't work because bitmasks can only be 32 bits */
|
||||
FT_UINT64, BASE_HEX, NULL, /*0x00000003ffffffffULL,*/ 0x0,
|
||||
"LAP parity", HFILL }
|
||||
},
|
||||
{ &hf_btbb_fhs_lap,
|
||||
{ "LAP", "btbb.lap",
|
||||
FT_UINT24, BASE_HEX, NULL, 0x03fffffc,
|
||||
"Lower Address Part", HFILL }
|
||||
},
|
||||
{ &hf_btbb_fhs_eir,
|
||||
{ "EIR", "btbb.eir",
|
||||
FT_BOOLEAN, 8, NULL, 0x04,
|
||||
"Extended Inquiry Response packet may follow", HFILL }
|
||||
},
|
||||
{ &hf_btbb_fhs_sr,
|
||||
{ "SR", "btbb.sr",
|
||||
FT_UINT8, BASE_HEX, VALS(sr_modes), 0x30,
|
||||
"Scan Repetition", HFILL }
|
||||
},
|
||||
{ &hf_btbb_fhs_uap,
|
||||
{ "UAP", "btbb.uap",
|
||||
FT_UINT8, BASE_HEX, NULL, 0x0,
|
||||
"Upper Address Part", HFILL }
|
||||
},
|
||||
{ &hf_btbb_fhs_nap,
|
||||
{ "NAP", "btbb.nap",
|
||||
FT_UINT16, BASE_HEX, NULL, 0x0,
|
||||
"Non-Significant Address Part", HFILL }
|
||||
},
|
||||
{ &hf_btbb_fhs_class, /* FIXME break out further */
|
||||
{ "Class of Device", "btbb.class",
|
||||
FT_UINT24, BASE_HEX, NULL, 0x0,
|
||||
NULL, HFILL }
|
||||
},
|
||||
{ &hf_btbb_fhs_ltaddr,
|
||||
{ "LT_ADDR", "btbb.lt_addr",
|
||||
FT_UINT8, BASE_HEX, NULL, 0x07,
|
||||
"Logical Transport Address", HFILL }
|
||||
},
|
||||
{ &hf_btbb_fhs_clk,
|
||||
{ "CLK", "btbb.clk",
|
||||
FT_UINT32, BASE_HEX, NULL, 0x1ffffff8,
|
||||
"Clock bits 2 through 27", HFILL }
|
||||
},
|
||||
{ &hf_btbb_fhs_psmode,
|
||||
{ "Page Scan Mode", "btbb.psmode",
|
||||
FT_UINT8, BASE_HEX, NULL, 0xe0,
|
||||
NULL, HFILL }
|
||||
},
|
||||
};
|
||||
|
||||
/* protocol subtree arrays */
|
||||
static gint *ett[] = {
|
||||
&ett_btbb,
|
||||
&ett_btbb_meta,
|
||||
&ett_btbb_pkthdr,
|
||||
&ett_btbb_flags,
|
||||
&ett_btbb_payload,
|
||||
&ett_btbb_pldhdr,
|
||||
};
|
||||
|
||||
/* register the protocol name and description */
|
||||
proto_btbb = proto_register_protocol(
|
||||
"Bluetooth Baseband", /* full name */
|
||||
"BT Baseband", /* short name */
|
||||
"btbb" /* abbreviation (e.g. for filters) */
|
||||
);
|
||||
|
||||
/* register the header fields and subtrees used */
|
||||
proto_register_field_array(proto_btbb, hf, array_length(hf));
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
}
|
||||
|
||||
void
|
||||
proto_reg_handoff_btbb(void)
|
||||
{
|
||||
dissector_handle_t btbb_handle;
|
||||
|
||||
btbb_handle = new_create_dissector_handle(dissect_btbb, proto_btbb);
|
||||
/* hijacking this ethertype */
|
||||
dissector_add_uint("ethertype", 0xFFF0, btbb_handle);
|
||||
/* dissector_add_uint("wtap_encap", WTAP_ENCAP_BLUETOOTH_BASEBAND, btbb_handle); */
|
||||
|
||||
btbrlmp_handle = find_dissector("btbrlmp");
|
||||
btl2cap_handle = find_dissector("btl2cap");
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,34 @@
|
|||
#include "winver.h"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION @RC_MODULE_VERSION@
|
||||
PRODUCTVERSION @RC_VERSION@
|
||||
FILEFLAGSMASK 0x0L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "The Wireshark developer community, http://www.wireshark.org/\0"
|
||||
VALUE "FileDescription", "@PACKAGE@ dissector\0"
|
||||
VALUE "FileVersion", "@MODULE_VERSION@\0"
|
||||
VALUE "InternalName", "@PACKAGE@ @MODULE_VERSION@\0"
|
||||
VALUE "LegalCopyright", "Copyright © 1998 Gerald Combs <gerald@wireshark.org>, Gilbert Ramirez <gram@alumni.rice.edu> and others\0"
|
||||
VALUE "OriginalFilename", "@PLUGIN_NAME@.dll\0"
|
||||
VALUE "ProductName", "Wireshark\0"
|
||||
VALUE "ProductVersion", "@VERSION@\0"
|
||||
VALUE "Comments", "Build with @MSVC_VARIANT@\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
|
@ -0,0 +1,186 @@
|
|||
#! /bin/sh
|
||||
|
||||
#
|
||||
# $Id: make-dissector-reg 21716 2007-05-07 17:55:42Z gal $
|
||||
#
|
||||
|
||||
#
|
||||
# The first argument is the directory in which the source files live.
|
||||
#
|
||||
srcdir="$1"
|
||||
shift
|
||||
|
||||
#
|
||||
# The second argument is either "plugin" or "dissectors"; if it's
|
||||
# "plugin", we build a plugin.c for a plugin, and if it's
|
||||
# "dissectors", we build a register.c for libwireshark.
|
||||
#
|
||||
registertype="$1"
|
||||
shift
|
||||
if [ "$registertype" = plugin ]
|
||||
then
|
||||
outfile="plugin.c"
|
||||
elif [ "$registertype" = dissectors ]
|
||||
then
|
||||
outfile="register.c"
|
||||
else
|
||||
echo "Unknown output type '$registertype'" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# All subsequent arguments are the files to scan.
|
||||
#
|
||||
rm -f ${outfile}-tmp
|
||||
echo '/* Do not modify this file. */' >${outfile}-tmp
|
||||
echo '/* It is created automatically by the Makefile. */'>>${outfile}-tmp
|
||||
if [ "$registertype" = plugin ]
|
||||
then
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
#include "moduleinfo.h"
|
||||
|
||||
#ifndef ENABLE_STATIC
|
||||
G_MODULE_EXPORT const gchar version[] = VERSION;
|
||||
|
||||
/* Start the functions we need for the plugin stuff */
|
||||
|
||||
G_MODULE_EXPORT void
|
||||
plugin_register (void)
|
||||
{
|
||||
EOF
|
||||
#
|
||||
# Build code to call all the protocol registration routines.
|
||||
#
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^void proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
|
||||
else
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
#include "register.h"
|
||||
void
|
||||
register_all_protocols(register_cb cb, gpointer client_data)
|
||||
{
|
||||
EOF
|
||||
#
|
||||
# Build code to call all the protocol registration routines.
|
||||
#
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_REGISTER, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^void proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_REGISTER, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
|
||||
|
||||
fi
|
||||
echo '}' >>${outfile}-tmp
|
||||
|
||||
|
||||
#
|
||||
# Build code to call all the protocol handoff registration routines.
|
||||
#
|
||||
if [ "$registertype" = plugin ]
|
||||
then
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
G_MODULE_EXPORT void
|
||||
plugin_reg_handoff(void)
|
||||
{
|
||||
EOF
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^void proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
|
||||
else
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
void
|
||||
register_all_protocol_handoffs(register_cb cb, gpointer client_data)
|
||||
{
|
||||
EOF
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_HANDOFF, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^void proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_HANDOFF, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
|
||||
fi
|
||||
echo '}' >>${outfile}-tmp
|
||||
if [ "$registertype" = plugin ]
|
||||
then
|
||||
echo '#endif' >>${outfile}-tmp
|
||||
else
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
gulong register_count(void)
|
||||
{
|
||||
EOF
|
||||
proto_regs=`grep RA_REGISTER ${outfile}-tmp | wc -l`
|
||||
handoff_regs=`grep RA_HANDOFF ${outfile}-tmp | wc -l`
|
||||
echo " return $proto_regs + $handoff_regs;" >>${outfile}-tmp
|
||||
echo '}' >>${outfile}-tmp
|
||||
fi
|
||||
mv ${outfile}-tmp ${outfile}
|
|
@ -0,0 +1,311 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Looks for registration routines in the protocol dissectors,
|
||||
# and assembles C code to call all the routines.
|
||||
#
|
||||
# This is a Python version of the make-reg-dotc shell script.
|
||||
# Running the shell script on Win32 is very very slow because of
|
||||
# all the process-launching that goes on --- multiple greps and
|
||||
# seds for each input file. I wrote this python version so that
|
||||
# less processes would have to be started.
|
||||
#
|
||||
# $Id: make-dissector-reg.py 40736 2012-01-26 21:38:53Z gerald $
|
||||
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import pickle
|
||||
from stat import *
|
||||
|
||||
VERSION_KEY = '_VERSION'
|
||||
CUR_VERSION = '$Id: make-dissector-reg.py 40736 2012-01-26 21:38:53Z gerald $'
|
||||
|
||||
#
|
||||
# The first argument is the directory in which the source files live.
|
||||
#
|
||||
srcdir = sys.argv[1]
|
||||
|
||||
#
|
||||
# The second argument is either "plugin" or "dissectors"; if it's
|
||||
# "plugin", we build a plugin.c for a plugin, and if it's
|
||||
# "dissectors", we build a register.c for libwireshark.
|
||||
#
|
||||
registertype = sys.argv[2]
|
||||
if registertype == "plugin" or registertype == "plugin_wtap":
|
||||
tmp_filename = "plugin.c-tmp"
|
||||
final_filename = "plugin.c"
|
||||
cache_filename = None
|
||||
preamble = """\
|
||||
/*
|
||||
* Do not modify this file.
|
||||
*
|
||||
* It is created automatically by Makefile or Makefile.nmake.
|
||||
*/
|
||||
"""
|
||||
elif registertype == "dissectors":
|
||||
tmp_filename = "register.c-tmp"
|
||||
final_filename = "register.c"
|
||||
cache_filename = "register-cache.pkl"
|
||||
preamble = """\
|
||||
/*
|
||||
* Do not modify this file.
|
||||
*
|
||||
* It is created automatically by the "register.c" target in
|
||||
* epan/dissectors/Makefile or Makefile.nmake using information in
|
||||
* epan/dissectors/register-cache.pkl.
|
||||
*
|
||||
* You can force this file to be regenerated completely by deleting
|
||||
* it along with epan/dissectors/register-cache.pkl.
|
||||
*/
|
||||
"""
|
||||
else:
|
||||
print(("Unknown output type '%s'" % registertype))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
#
|
||||
# All subsequent arguments are the files to scan.
|
||||
#
|
||||
files = sys.argv[3:]
|
||||
|
||||
# Create the proper list of filenames
|
||||
filenames = []
|
||||
for file in files:
|
||||
if os.path.isfile(file):
|
||||
filenames.append(file)
|
||||
else:
|
||||
filenames.append(os.path.join(srcdir, file))
|
||||
|
||||
if len(filenames) < 1:
|
||||
print("No files found")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# Look through all files, applying the regex to each line.
|
||||
# If the pattern matches, save the "symbol" section to the
|
||||
# appropriate array.
|
||||
regs = {
|
||||
'proto_reg': [],
|
||||
'handoff_reg': [],
|
||||
'wtap_register': [],
|
||||
}
|
||||
|
||||
# For those that don't know Python, r"" indicates a raw string,
|
||||
# devoid of Python escapes.
|
||||
proto_regex0 = r"^(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||||
proto_regex1 = r"void\s+(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||||
|
||||
handoff_regex0 = r"^(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||||
handoff_regex1 = r"void\s+(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||||
|
||||
wtap_reg_regex0 = r"^(?P<symbol>wtap_register_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||||
wtap_reg_regex1 = r"void\s+(?P<symbol>wtap_register_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||||
|
||||
# This table drives the pattern-matching and symbol-harvesting
|
||||
patterns = [
|
||||
( 'proto_reg', re.compile(proto_regex0) ),
|
||||
( 'proto_reg', re.compile(proto_regex1) ),
|
||||
( 'handoff_reg', re.compile(handoff_regex0) ),
|
||||
( 'handoff_reg', re.compile(handoff_regex1) ),
|
||||
( 'wtap_register', re.compile(wtap_reg_regex0) ),
|
||||
( 'wtap_register', re.compile(wtap_reg_regex1) ),
|
||||
]
|
||||
|
||||
# Open our registration symbol cache
|
||||
cache = None
|
||||
if cache_filename:
|
||||
try:
|
||||
cache_file = open(cache_filename, 'rb')
|
||||
cache = pickle.load(cache_file)
|
||||
cache_file.close()
|
||||
if VERSION_KEY not in cache or cache[VERSION_KEY] != CUR_VERSION:
|
||||
cache = {VERSION_KEY: CUR_VERSION}
|
||||
except:
|
||||
cache = {VERSION_KEY: CUR_VERSION}
|
||||
|
||||
print(("Registering %d files, %d cached" % (len(filenames), len(list(cache.keys()))-1)))
|
||||
|
||||
# Grep
|
||||
cache_hits = 0
|
||||
cache_misses = 0
|
||||
for filename in filenames:
|
||||
file = open(filename)
|
||||
cur_mtime = os.fstat(file.fileno())[ST_MTIME]
|
||||
if cache and filename in cache:
|
||||
cdict = cache[filename]
|
||||
if cur_mtime == cdict['mtime']:
|
||||
cache_hits += 1
|
||||
# print "Pulling %s from cache" % (filename)
|
||||
regs['proto_reg'].extend(cdict['proto_reg'])
|
||||
regs['handoff_reg'].extend(cdict['handoff_reg'])
|
||||
regs['wtap_register'].extend(cdict['wtap_register'])
|
||||
file.close()
|
||||
continue
|
||||
# We don't have a cache entry
|
||||
if cache is not None:
|
||||
cache_misses += 1
|
||||
cache[filename] = {
|
||||
'mtime': cur_mtime,
|
||||
'proto_reg': [],
|
||||
'handoff_reg': [],
|
||||
'wtap_register': [],
|
||||
}
|
||||
# print "Searching %s" % (filename)
|
||||
for line in file.readlines():
|
||||
for action in patterns:
|
||||
regex = action[1]
|
||||
match = regex.search(line)
|
||||
if match:
|
||||
symbol = match.group("symbol")
|
||||
sym_type = action[0]
|
||||
regs[sym_type].append(symbol)
|
||||
if cache is not None:
|
||||
# print "Caching %s for %s: %s" % (sym_type, filename, symbol)
|
||||
cache[filename][sym_type].append(symbol)
|
||||
file.close()
|
||||
|
||||
|
||||
if cache is not None and cache_filename is not None:
|
||||
cache_file = open(cache_filename, 'wb')
|
||||
pickle.dump(cache, cache_file)
|
||||
cache_file.close()
|
||||
print(("Cache hits: %d, misses: %d" % (cache_hits, cache_misses)))
|
||||
|
||||
# Make sure we actually processed something
|
||||
if len(regs['proto_reg']) < 1:
|
||||
print("No protocol registrations found")
|
||||
sys.exit(1)
|
||||
|
||||
# Sort the lists to make them pretty
|
||||
regs['proto_reg'].sort()
|
||||
regs['handoff_reg'].sort()
|
||||
regs['wtap_register'].sort()
|
||||
|
||||
reg_code = open(tmp_filename, "w")
|
||||
|
||||
reg_code.write(preamble)
|
||||
|
||||
# Make the routine to register all protocols
|
||||
if registertype == "plugin" or registertype == "plugin_wtap":
|
||||
reg_code.write("""
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
#include "moduleinfo.h"
|
||||
|
||||
#ifndef ENABLE_STATIC
|
||||
G_MODULE_EXPORT const gchar version[] = VERSION;
|
||||
|
||||
/* Start the functions we need for the plugin stuff */
|
||||
|
||||
G_MODULE_EXPORT void
|
||||
plugin_register (void)
|
||||
{
|
||||
""");
|
||||
else:
|
||||
reg_code.write("""
|
||||
#include "register.h"
|
||||
void
|
||||
register_all_protocols(register_cb cb, gpointer client_data)
|
||||
{
|
||||
""");
|
||||
|
||||
for symbol in regs['proto_reg']:
|
||||
if registertype == "plugin" or registertype == "plugin_wtap":
|
||||
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
|
||||
else:
|
||||
line = " {extern void %s (void); if(cb) (*cb)(RA_REGISTER, \"%s\", client_data); %s ();}\n" % (symbol, symbol, symbol)
|
||||
reg_code.write(line)
|
||||
|
||||
reg_code.write("}\n")
|
||||
|
||||
|
||||
# Make the routine to register all protocol handoffs
|
||||
if registertype == "plugin" or registertype == "plugin_wtap":
|
||||
reg_code.write("""
|
||||
G_MODULE_EXPORT void
|
||||
plugin_reg_handoff(void)
|
||||
{
|
||||
""");
|
||||
else:
|
||||
reg_code.write("""
|
||||
void
|
||||
register_all_protocol_handoffs(register_cb cb, gpointer client_data)
|
||||
{
|
||||
""");
|
||||
|
||||
for symbol in regs['handoff_reg']:
|
||||
if registertype == "plugin" or registertype == "plugin_wtap":
|
||||
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
|
||||
else:
|
||||
line = " {extern void %s (void); if(cb) (*cb)(RA_HANDOFF, \"%s\", client_data); %s ();}\n" % (symbol, symbol, symbol)
|
||||
reg_code.write(line)
|
||||
|
||||
reg_code.write("}\n")
|
||||
|
||||
if registertype == "plugin":
|
||||
reg_code.write("#endif\n");
|
||||
elif registertype == "plugin_wtap":
|
||||
reg_code.write("""
|
||||
G_MODULE_EXPORT void
|
||||
register_wtap_module(void)
|
||||
{
|
||||
""");
|
||||
|
||||
for symbol in regs['wtap_register']:
|
||||
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
|
||||
reg_code.write(line)
|
||||
|
||||
reg_code.write("}\n");
|
||||
reg_code.write("#endif\n");
|
||||
else:
|
||||
reg_code.write("""
|
||||
static gulong proto_reg_count(void)
|
||||
{
|
||||
""");
|
||||
|
||||
line = " return %d;\n" % len(regs['proto_reg'])
|
||||
reg_code.write(line)
|
||||
|
||||
reg_code.write("""
|
||||
}
|
||||
""");
|
||||
reg_code.write("""
|
||||
static gulong handoff_reg_count(void)
|
||||
{
|
||||
""");
|
||||
|
||||
line = " return %d;\n" % len(regs['handoff_reg'])
|
||||
reg_code.write(line)
|
||||
|
||||
reg_code.write("""
|
||||
}
|
||||
""");
|
||||
reg_code.write("""
|
||||
gulong register_count(void)
|
||||
{
|
||||
""");
|
||||
|
||||
line = " return proto_reg_count() + handoff_reg_count();"
|
||||
reg_code.write(line)
|
||||
|
||||
reg_code.write("""
|
||||
}\n
|
||||
""");
|
||||
|
||||
|
||||
# Close the file
|
||||
reg_code.close()
|
||||
|
||||
# Remove the old final_file if it exists.
|
||||
try:
|
||||
os.stat(final_filename)
|
||||
os.remove(final_filename)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# Move from tmp file to final file
|
||||
os.rename(tmp_filename, final_filename)
|
|
@ -0,0 +1,3 @@
|
|||
Authors:
|
||||
Michael Ossmann <mike@ossmann.com>
|
||||
Dominic Spill <dominicgs@gmail.com>
|
|
@ -0,0 +1,86 @@
|
|||
#
|
||||
# Wireshark - Network traffic analyzer
|
||||
# By Gerald Combs <gerald@wireshark.org>
|
||||
# Copyright 1998 Gerald Combs
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
|
||||
project(btbredr-wireshark-plugin C)
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
set(CMAKE_BACKWARDS_COMPATIBILITY 2.6)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
|
||||
IF ( NOT CMAKE_INSTALL_LIBDIR )
|
||||
set(CMAKE_INSTALL_LIBDIR ~/.wireshark/plugins)
|
||||
ENDIF ( NOT CMAKE_INSTALL_LIBDIR )
|
||||
MESSAGE (STATUS "Plugin will be installed in: ${CMAKE_INSTALL_LIBDIR}")
|
||||
|
||||
INCLUDE(UseMakeDissectorReg)
|
||||
|
||||
set(GLIB2_MIN_VERSION 2.4.0)
|
||||
|
||||
find_package(GLIB2)
|
||||
include_directories (${GLIB2_INCLUDE_DIRS})
|
||||
|
||||
find_package(Wireshark)
|
||||
include_directories (${WIRESHARK_INCLUDE_DIRS})
|
||||
|
||||
set(LINK_MODE_LIB SHARED)
|
||||
set(LINK_MODE_MODULE MODULE)
|
||||
|
||||
|
||||
set(DISSECTOR_SRC
|
||||
packet-btbredr.c
|
||||
packet-btlmp.c
|
||||
)
|
||||
|
||||
set(PLUGIN_FILES
|
||||
plugin.c
|
||||
${DISSECTOR_SRC}
|
||||
)
|
||||
|
||||
set(CLEAN_FILES
|
||||
${PLUGIN_FILES}
|
||||
)
|
||||
|
||||
if (WERROR)
|
||||
set_source_files_properties(
|
||||
${CLEAN_FILES}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS -Werror
|
||||
)
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
register_dissector_files(plugin.c
|
||||
plugin
|
||||
${DISSECTOR_SRC}
|
||||
)
|
||||
|
||||
add_library(btbredr ${LINK_MODE_MODULE}
|
||||
${PLUGIN_FILES}
|
||||
)
|
||||
set_target_properties(btbredr PROPERTIES PREFIX "")
|
||||
set_target_properties(btbredr PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}")
|
||||
|
||||
target_link_libraries(btbredr wireshark)
|
||||
|
||||
install(TARGETS btbredr
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/ NAMELINK_SKIP
|
||||
)
|
||||
|
|
@ -0,0 +1,340 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,16 @@
|
|||
BTBB Basic and Enhanced Data Rate Wireshark plugin
|
||||
|
||||
This is the Bluetooth baseband plugin for Wireshark, it also includes an LMP
|
||||
level dissector.
|
||||
|
||||
To build this on Debian/Ubuntu/BackTrack linux distributions:
|
||||
sudo apt-get install wireshark-dev wireshark
|
||||
cd libbtbb/wireshark/plugins/btbredr/
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
make install
|
||||
|
||||
This will install to the .wireshark/ in your home directory. To override this
|
||||
set the DESTDIR environment variable when running cmake.
|
Binary file not shown.
|
@ -0,0 +1,22 @@
|
|||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,27 @@
|
|||
Copyright notice for the files copied from
|
||||
http://www.opensync.org/browser/branches/3rd-party-cmake-modules/modules
|
||||
|
||||
$Id: COPYING-CMAKE-SCRIPTS 34248 2010-09-25 15:38:12Z jmayer $
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue