├── VERSION ├── src ├── debian │ ├── compat │ ├── install │ ├── rules │ ├── control │ ├── postrm │ ├── changelog │ ├── copyright │ └── postinst ├── tools │ ├── version.h │ ├── additional │ │ ├── 55-USBProxy-dot11.rules │ │ ├── README.md │ │ ├── Makefile │ │ ├── dot11_test.c │ │ └── dot11_control.h │ ├── CMakeLists.txt │ └── git-version-gen.sh ├── lib │ ├── get_tid.c │ ├── get_tid.h │ ├── usbproxy.pc.in │ ├── FDInfo.h │ ├── HexString.h │ ├── Plugins.h │ ├── TRACE.h │ ├── InterfaceGroup.h │ ├── ConfigParser.h │ ├── USBString.h │ ├── Endpoint.h │ ├── RelayReader.h │ ├── HID.h │ ├── DeviceQualifier.h │ ├── PluginManager.h │ ├── PacketFilter.cpp │ ├── TCP_Helper.h │ ├── Packet.h │ ├── Proxy.h │ ├── Configuration.h │ ├── HID.cpp │ ├── RelayWriter.h │ ├── PacketFilter.h │ ├── HostProxy.h │ ├── EP_IO.h │ ├── Criteria.h │ ├── DefinitionErrors.h │ ├── DeviceProxy.h │ ├── Interface.h │ ├── FDInfo.c │ ├── SafeQueue.hpp │ ├── Criteria.cpp │ ├── Device.h │ ├── Manager.h │ ├── Endpoint.cpp │ ├── Injector.cpp │ ├── USBString.cpp │ ├── InterfaceGroup.cpp │ ├── CMakeLists.txt │ ├── PluginManager.cpp │ ├── Injector.h │ ├── ConfigParser.cpp │ └── RelayWriter.cpp ├── Plugins │ ├── CMakeLists.txt │ ├── Filters │ │ ├── PacketFilter_ROT13.h │ │ ├── PacketFilter_ZeroMQ.h │ │ ├── PacketFilter_Power.h │ │ ├── PacketFilter_StreamLog.h │ │ ├── PacketFilter_UDPHID.h │ │ ├── PacketFilter_KeyLogger.h │ │ ├── PacketFilter_ROT13.cpp │ │ ├── PacketFilter_Callback.h │ │ ├── PacketFilter_PcapLogger.h │ │ ├── PacketFilter_Power.cpp │ │ ├── PacketFilter_Callback.cpp │ │ ├── PacketFilter_ZeroMQ.cpp │ │ ├── CMakeLists.txt │ │ ├── PacketFilter_StreamLog.cpp │ │ ├── PacketFilter_UDPHID.cpp │ │ └── PacketFilter_MassStorage.h │ ├── Injectors │ │ ├── CMakeLists.txt │ │ ├── Injector_UDP.h │ │ ├── Injector_UDPHID.h │ │ ├── Injector_UDP.cpp │ │ └── Injector_UDPHID.cpp │ ├── Hosts │ │ ├── HostProxy_Null.h │ │ ├── CMakeLists.txt │ │ ├── HostProxy_TCP.h │ │ ├── HostProxy_GadgetFS.h │ │ ├── GadgetFS_helpers.h │ │ └── HostProxy_TCP.cpp │ └── Devices │ │ ├── DeviceProxy_Null.h │ │ ├── DeviceProxy_TCP.h │ │ ├── CMakeLists.txt │ │ ├── DeviceProxy_dot11.h │ │ ├── DeviceProxy_Loopback.h │ │ ├── DeviceProxy_Callback.h │ │ ├── DeviceProxy_LibUSB.h │ │ ├── Dot11_Interface.h │ │ ├── DeviceProxy_Callback.cpp │ │ └── DeviceProxy_TCP.cpp ├── greengrass │ ├── CMakeLists.txt │ └── main.cpp ├── cmake │ ├── modules │ │ ├── FindUSB1.cmake │ │ ├── Findlorcon.cmake │ │ └── FindUSBProxy.cmake │ └── cmake_uninstall.cmake.in └── CMakeLists.txt ├── CODEOWNERS ├── nodejs-client ├── .gitignore ├── package.json ├── index.js ├── delimiter_example.js └── package-lock.json ├── scripts ├── gdb_sudo.sh ├── sigkill.sh ├── sigterm.sh ├── install-libusb.sh ├── install.sh ├── usb-mitm.sh ├── install-dependencies.sh ├── usb-mitm-samsung.sh ├── install-msgpack.sh ├── install-from-release.sh └── install-zeromq.sh ├── docker-crosstool-ng-arm ├── .gitignore ├── README.md ├── docker-compose.yml ├── config │ └── raspberry_pi_3_b_plus.cmake.tc ├── fixes │ ├── project-config.jam │ └── 140-mpc.sh ├── docker │ ├── app.Dockerfile │ └── toolchain.Dockerfile └── build-binary.sh ├── aptly ├── .gitignore ├── .env.example ├── aptly.conf ├── Dockerfile └── build.sh ├── rpi-scripts ├── run.sh ├── all.sh ├── go.sh ├── extract.sh ├── link.sh ├── init.sh ├── install-aws-greengrass-sdk.sh ├── install-repo.sh └── install-all-dependencies.sh ├── .github ├── imgs │ ├── openkeychain.png │ └── project_logo.png ├── install-release-tools.sh ├── create-release.sh └── workflows │ ├── build-aptly.yaml │ └── build-container.yml ├── AUTHORS ├── .vscode ├── c_cpp_properties.json ├── tasks.json ├── settings.json └── launch.json ├── .devcontainer ├── assets │ └── armhf-cross-toolchain.cmake.tc └── devcontainer.json └── .gitignore /VERSION: -------------------------------------------------------------------------------- 1 | 0.1.0 -------------------------------------------------------------------------------- /src/debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @MartinLoeper -------------------------------------------------------------------------------- /src/debian/install: -------------------------------------------------------------------------------- 1 | usr/* usr/ -------------------------------------------------------------------------------- /nodejs-client/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /scripts/gdb_sudo.sh: -------------------------------------------------------------------------------- 1 | sudo /usr/bin/gdb "$@" 2 | -------------------------------------------------------------------------------- /src/tools/version.h: -------------------------------------------------------------------------------- 1 | #define VERSION "0.2" 2 | -------------------------------------------------------------------------------- /scripts/sigkill.sh: -------------------------------------------------------------------------------- 1 | sudo pkill -SIGKILL usb-mitm 2 | -------------------------------------------------------------------------------- /scripts/sigterm.sh: -------------------------------------------------------------------------------- 1 | sudo pkill -SIGTERM usb-mitm 2 | -------------------------------------------------------------------------------- /docker-crosstool-ng-arm/.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | usb-mitm.tar -------------------------------------------------------------------------------- /aptly/.gitignore: -------------------------------------------------------------------------------- 1 | public.asc 2 | private.asc 3 | .env 4 | key_passwd -------------------------------------------------------------------------------- /rpi-scripts/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo usb-mitm -v 045e -p 07f8 -n -------------------------------------------------------------------------------- /rpi-scripts/all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ./extract.sh && ./link.sh && ./go.sh -------------------------------------------------------------------------------- /scripts/install-libusb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo apt install libusb-1.0.0-dev -------------------------------------------------------------------------------- /scripts/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | (cd ./src/build && sudo make install) 4 | -------------------------------------------------------------------------------- /scripts/usb-mitm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo ./src/build/tools/usb-mitm -v 045e -p 07f8 -n 4 | -------------------------------------------------------------------------------- /aptly/.env.example: -------------------------------------------------------------------------------- 1 | AWS_ACCESS_KEY_ID= 2 | AWS_SECRET_ACCESS_KEY= 3 | GPG_KEY_ID= 4 | GPG_KEY_PASSWORD= -------------------------------------------------------------------------------- /rpi-scripts/go.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | LD_LIBRARY_PATH=/usr/local/lib/ ./staging/rootfs/usr/bin/usb-mitm 3 | -------------------------------------------------------------------------------- /.github/imgs/openkeychain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nesto-software/USBProxy/HEAD/.github/imgs/openkeychain.png -------------------------------------------------------------------------------- /.github/imgs/project_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nesto-software/USBProxy/HEAD/.github/imgs/project_logo.png -------------------------------------------------------------------------------- /rpi-scripts/extract.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm -Rf ./staging 3 | mkdir -p staging 4 | tar xf usb-mitm.tar -C ./staging 5 | -------------------------------------------------------------------------------- /scripts/install-dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo apt-get install -y libzmq3-dev libusb-1.0-0 libudev1 coreutils sed 4 | -------------------------------------------------------------------------------- /src/tools/additional/55-USBProxy-dot11.rules: -------------------------------------------------------------------------------- 1 | ATTRS{idVendor}=="ffff", ATTRS{idProduct}=="0005", MODE="0660", GROUP="plugdev" 2 | -------------------------------------------------------------------------------- /rpi-scripts/link.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | shopt -s globstar 4 | (cd staging/rootfs; rsync -r --relative --links ./usr/local/lib/** /) 5 | -------------------------------------------------------------------------------- /scripts/usb-mitm-samsung.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo ./src/build/tools/usb-mitm -v 04e8 -p 3461 -z -dd -l -w /home/pi/test.pcap 4 | 5 | 6 | -------------------------------------------------------------------------------- /rpi-scripts/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "dtoverlay=dwc2" | sudo tee -a /boot/config.txt 3 | echo "dwc2" | sudo tee -a /etc/modules 4 | sudo reboot -------------------------------------------------------------------------------- /.github/install-release-tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo apt-get install -y devscripts 3 | git clone https://github.com/fsaintjacques/semver-tool /tmp/semver 4 | (cd /tmp/semver && sudo make install) -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Authors: 2 | Dominic Spill 3 | Adam Stasiak 4 | 5 | Mike Kershaw / dragorn 6 | Martin Löper -------------------------------------------------------------------------------- /src/tools/additional/README.md: -------------------------------------------------------------------------------- 1 | Additional Tools 2 | ================ 3 | 4 | The files in this directory are used to provide proof of concept or simple 5 | tests for USBProxy plugins. They are not fully functional tools. 6 | -------------------------------------------------------------------------------- /src/tools/additional/Makefile: -------------------------------------------------------------------------------- 1 | 2 | dot11_test: dot11_control.c dot11_test.c 3 | gcc -g -I../../Plugins/Devices/ dot11_control.c dot11_test.c -o dot11_test -lusb-1.0 4 | 5 | clean: 6 | rm -f dot11_control.o dot11_test.o dot11_test 7 | 8 | -------------------------------------------------------------------------------- /src/lib/get_tid.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "get_tid.h" 9 | 10 | __pid_t gettid() { 11 | return (pid_t)syscall(__NR_gettid); 12 | } 13 | -------------------------------------------------------------------------------- /docker-crosstool-ng-arm/README.md: -------------------------------------------------------------------------------- 1 | # Cross-Compilation Docker Container for x64 to ARMv7 2 | This repo provides a Docker image which sets up a crosstool-ng toolchain and build a binary using it. 3 | The target binary is placed into `bin/` directory after running `build-binary.sh`. -------------------------------------------------------------------------------- /src/Plugins/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of USBProxy. 3 | # 4 | 5 | project(usbproxy_plugins C) 6 | set(PACKAGE usbproxy_plugins) 7 | 8 | add_subdirectory(Devices) 9 | add_subdirectory(Hosts) 10 | add_subdirectory(Filters) 11 | add_subdirectory(Injectors) 12 | -------------------------------------------------------------------------------- /docker-crosstool-ng-arm/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | services: 3 | webapp: 4 | build: 5 | context: . 6 | target: nesto-awslocalproxy-custom-build 7 | # uncomment to be able to jump into the container for debugging 8 | # command: tail -f /dev/null -------------------------------------------------------------------------------- /scripts/install-msgpack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo apt-get install libboost-all-dev 4 | sudo apt-get install doxygen 5 | git clone https://github.com/msgpack/msgpack-c.git /tmp/msgpack-c 6 | (cd /tmp/msgpack-c && git checkout cpp_master && cmake -DMSGPACK_CXX17=ON . && sudo make install) -------------------------------------------------------------------------------- /src/lib/get_tid.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_GET_TID_H 6 | #define USBPROXY_GET_TID_H 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | __pid_t gettid(); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif /* USBPROXY_GET_TID_H */ 19 | -------------------------------------------------------------------------------- /src/lib/usbproxy.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: USB Proxy Library 7 | Description: C++ Utility Library 8 | Version: @VERSION@ 9 | Cflags: -I${includedir}/ @USBPROXY_PC_CFLAGS@ 10 | Libs: -L${libdir} -lUSBProxy 11 | Libs.private: @USBPROXY_PC_LIBS@ 12 | -------------------------------------------------------------------------------- /src/lib/FDInfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_FDINFO_H 6 | #define USBPROXY_FDINFO_H 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | void showFDDetail( __s32 fd ); 13 | void showFDInfo(); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif /* USBPROXY_FDINFO_H */ 20 | -------------------------------------------------------------------------------- /rpi-scripts/install-aws-greengrass-sdk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | git clone https://github.com/aws/aws-greengrass-core-sdk-c.git /tmp/aws-sdk 4 | (cd /tmp/aws-sdk/ && git checkout a71613711438b48588e177f86ab322dd3992e780 && cd ./aws-greengrass-core-sdk-c && mkdir -p build && cd build && cmake $2 $3 .. && cmake $2 $3 --build . && sudo make install DESTDIR=$1) 5 | -------------------------------------------------------------------------------- /src/lib/HexString.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_HEXSTRING_H 6 | #define USBPROXY_HEXSTRING_H 7 | 8 | #define TABPADDING "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" 9 | char* hex_string_wide(const void* buf,int length,int width=32); 10 | char* hex_string(const void* buf,int length); 11 | 12 | #endif /* USBPROXY_HEXSTRING_H */ 13 | -------------------------------------------------------------------------------- /src/lib/Plugins.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_PLUGINS_H 6 | #define USBPROXY_PLUGINS_H 7 | 8 | #define PLUGIN_DEVICEPROXY (1<<1) 9 | #define PLUGIN_HOSTPROXY (1<<2) 10 | #define PLUGIN_FILTER (1<<3) 11 | #define PLUGIN_INJECTOR (1<<4) 12 | 13 | //FIXME: Generic factory to replace individual ones 14 | 15 | #endif /* USBPROXY_PLUGINS_H */ 16 | -------------------------------------------------------------------------------- /nodejs-client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "dependencies": { 11 | "msgpack5": "^5.0.0", 12 | "zeromq": "^6.0.0-beta.6" 13 | }, 14 | "author": "", 15 | "license": "ISC" 16 | } 17 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Linux", 5 | "includePath": [ 6 | "${workspaceFolder}/**" 7 | ], 8 | "defines": [], 9 | "compilerPath": "/usr/bin/gcc", 10 | "cStandard": "gnu17", 11 | "cppStandard": "gnu++17", 12 | "intelliSenseMode": "gcc-arm" 13 | } 14 | ], 15 | "version": 4 16 | } -------------------------------------------------------------------------------- /src/tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of USBProxy. 3 | # 4 | 5 | set(TOOL usb-mitm) 6 | 7 | include_directories(${libusbproxy_SOURCE_DIR}) 8 | LIST(APPEND TOOLS_LINK_LIBS USBProxy -pthread zmq) 9 | 10 | add_executable(${TOOL} ${TOOL}.cpp) 11 | set_source_files_properties(${TOOL}.cpp PROPERTIES COMPILE_FLAGS "-std=c++11 -pthread -Wall -I.") 12 | target_link_libraries(${TOOL} ${TOOLS_LINK_LIBS}) 13 | install(TARGETS ${TOOL} RUNTIME DESTINATION ${INSTALL_DEFAULT_BINDIR}) 14 | -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_ROT13.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_PACKETFILTER_ROT13_H_ 6 | #define USBPROXY_PACKETFILTER_ROT13_H_ 7 | 8 | #include "PacketFilter.h" 9 | 10 | class PacketFilter_ROT13: public PacketFilter { 11 | public: 12 | PacketFilter_ROT13(ConfigParser *cfg) {} 13 | virtual ~PacketFilter_ROT13() {} 14 | void filter_packet(Packet* packet); 15 | virtual char* toString() {return (char*)"ROT13 Filter";} 16 | }; 17 | 18 | #endif /* USBPROXY_PACKETFILTER_ROT13_H_ */ 19 | -------------------------------------------------------------------------------- /src/debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | %: 4 | dh $@ 5 | 6 | override_dh_auto_build: 7 | override_dh_auto_install: 8 | mkdir -p debian/tmp 9 | cp -r $(ROOT_FS)/usr debian/tmp/ 10 | 11 | override_dh_auto_configure: 12 | 13 | # because we skiip this step, we must figure out our shared library dependencies manually and write them into control file 14 | override_dh_shlibdeps: 15 | @echo "Skipping dh_shlibdeps because of cross-compilation" 16 | 17 | override_dh_strip: 18 | override_dh_installman: 19 | override_dh_usrlocal: 20 | override_dh_makeshlibs: -------------------------------------------------------------------------------- /src/lib/TRACE.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_TRACE_H_ 6 | #define USBPROXY_TRACE_H_ 7 | 8 | #include 9 | 10 | #define TRACE fprintf(stderr,"Trace: %s, line %d\n",__FILE__,__LINE__); 11 | #define TRACE1(X) fprintf(stderr,"Trace(%d): %s, line %d\n",X,__FILE__,__LINE__); 12 | #define TRACE2(X,Y) fprintf(stderr,"Trace(%d,%d): %s, line %d\n",X,Y,__FILE__,__LINE__); 13 | #define TRACE3(X,Y,Z) fprintf(stderr,"Trace(%d,%d,%d): %s, line %d\n",X,Y,Z,__FILE__,__LINE__); 14 | 15 | #endif /* USBPROXY_TRACE_H_ */ 16 | -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_ZeroMQ.h: -------------------------------------------------------------------------------- 1 | #ifndef PACKETFILTER_ZEROMQ_H_ 2 | #define PACKETFILTER_ZEROMQ_H_ 3 | 4 | #include 5 | 6 | #include "PacketFilter.h" 7 | 8 | class PacketFilter_ZeroMQ : public PacketFilter { 9 | public: 10 | PacketFilter_ZeroMQ(ConfigParser *cfg); 11 | ~PacketFilter_ZeroMQ(); 12 | void filter_packet(Packet* packet, zmq::socket_t *sock); 13 | void filter_setup_packet(SetupPacket* packet,bool direction); 14 | virtual char* toString() { return (char*)"ZeroMQ Filter"; } 15 | }; 16 | #endif /* PACKETFILTER_ZEROMQ_H_ */ 17 | -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_Power.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_PACKETFILTER_POWER_H 6 | #define USBPROXY_PACKETFILTER_POWER_H 7 | 8 | #include 9 | #include "PacketFilter.h" 10 | 11 | class PacketFilter_Power : public PacketFilter { 12 | 13 | public: 14 | PacketFilter_Power(ConfigParser *cfg); 15 | void filter_setup_packet(SetupPacket* packet, bool direction_in); 16 | virtual char* toString() {return (char*)"Force Self Powered Filter";} 17 | }; 18 | 19 | #endif /* USBPROXY_PACKETFILTER_POWER_H */ 20 | -------------------------------------------------------------------------------- /src/debian/control: -------------------------------------------------------------------------------- 1 | Source: nesto-usbproxy 2 | Section: net 3 | Priority: optional 4 | Maintainer: Martin Loeper 5 | Standards-Version: 2014-07-R1-git 6 | Build-Depends: libusb-1.0-0-dev, cmake 7 | Vcs-Git: https://github.com/nesto-software/USBProxy-legacy.git 8 | Vcs-Browser: https://github.com/nesto-software/USBProxy-legacy 9 | Homepage: https://github.com/nesto-software/USBProxy-legacy 10 | 11 | Package: nesto-usbproxy 12 | Architecture: armhf 13 | Depends: libzmq3-dev, libusb-1.0-0, libudev1, coreutils, sed 14 | Description: Enhanced USBProxy utility 15 | -------------------------------------------------------------------------------- /scripts/install-from-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | FILE=/tmp/nesto-usbproxy-latest.deb 5 | RELEASE=v0.1.0 6 | 7 | # install deps if not available 8 | bash -c "$(curl -fsSL https://raw.githubusercontent.com/nesto-software/USBProxy/master/scripts/install-dependencies.sh)" 9 | 10 | echo "Downloading .deb file from latest GitHub release..." 11 | curl -s https://api.github.com/repos/nesto-software/USBProxy/releases/tags/$RELEASE \ 12 | | grep "browser_download_url.*deb" \ 13 | | cut -d : -f 2,3 \ 14 | | tr -d \" \ 15 | | wget -qi - -O "$FILE" 16 | 17 | echo "Installing .deb file..." 18 | sudo dpkg -i "$FILE" 19 | -------------------------------------------------------------------------------- /.devcontainer/assets/armhf-cross-toolchain.cmake.tc: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME Linux) 2 | set(CMAKE_SYSTEM_PROCESSOR arm) 3 | 4 | set(CMAKE_SYSROOT /opt/crosstool-ng/x-tools/arm-unknown-linux-gnueabi/arm-unknown-linux-gnueabi/sysroot) 5 | 6 | set(tools /opt/crosstool-ng/x-tools/arm-unknown-linux-gnueabi) 7 | set(CMAKE_C_COMPILER ${tools}/bin/arm-unknown-linux-gnueabi-gcc) 8 | set(CMAKE_CXX_COMPILER ${tools}/bin/arm-unknown-linux-gnueabi-g++) 9 | 10 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 11 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 12 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 13 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # usb-mitm binary 2 | usb-mitm 3 | #object files 4 | *.o 5 | *.d 6 | *.so 7 | *.pyc 8 | #shell to move changes from usb-test 9 | merge.sh 10 | #eclipse stuff 11 | .project 12 | .cproject 13 | test/relaytest/relaytest 14 | typescript 15 | #vi(m) 16 | *.swp 17 | #cmake stuff 18 | CMakeFiles 19 | cmake_install.cmake 20 | cmake_uninstall.cmake 21 | CMakeCache.txt 22 | Makefile 23 | version.h 24 | version 25 | **/debian/*.log 26 | obj-x86_64-linux-gnu 27 | **/debian/*.substvars 28 | **/debian/usbproxy* 29 | **/debian/.debhelper 30 | 31 | # nesto-specific 32 | src/build 33 | cppzmq 34 | usb-mitm.tar 35 | src/lib/usbproxy.pc 36 | -------------------------------------------------------------------------------- /docker-crosstool-ng-arm/config/raspberry_pi_3_b_plus.cmake.tc: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME Linux) 2 | set(CMAKE_SYSTEM_PROCESSOR arm) 3 | 4 | set(CMAKE_SYSROOT /opt/crosstool-ng/x-tools/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot) 5 | 6 | set(tools /opt/crosstool-ng/x-tools/arm-rpi-linux-gnueabihf) 7 | set(CMAKE_C_COMPILER ${tools}/bin/arm-rpi-linux-gnueabihf-gcc) 8 | set(CMAKE_CXX_COMPILER ${tools}/bin/arm-rpi-linux-gnueabihf-g++) 9 | 10 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 11 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 12 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 13 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 14 | -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_StreamLog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef PACKETFILTER_STREAMLOG_H_ 6 | #define PACKETFILTER_STREAMLOG_H_ 7 | 8 | #include "PacketFilter.h" 9 | 10 | //writes all traffic to a stream 11 | class PacketFilter_StreamLog : public PacketFilter { 12 | private: 13 | FILE* file; 14 | public: 15 | PacketFilter_StreamLog(ConfigParser *cfg); 16 | void filter_packet(Packet* packet, zmq::socket_t *sock); 17 | void filter_setup_packet(SetupPacket* packet,bool direction); 18 | virtual char* toString() {return (char*)"Stream Log Filter";} 19 | }; 20 | #endif /* PACKETFILTER_STREAMLOG_H_ */ 21 | -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_UDPHID.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef PACKETFILTER_UDPHID_H_ 6 | #define PACKETFILTER_UDPHID_H_ 7 | 8 | #include "PacketFilter.h" 9 | #include "../Injectors/Injector_UDPHID.h" 10 | 11 | //writes all traffic to a stream 12 | class PacketFilter_UDPHID : public PacketFilter { 13 | private: 14 | __u8* reportBuffer; 15 | public: 16 | PacketFilter_UDPHID(ConfigParser *cfg); 17 | void filter_packet(Packet* packet); 18 | void filter_setup_packet(SetupPacket* packet,bool direction); 19 | virtual char* toString() {return (char*)"UDPHID Filter";} 20 | }; 21 | #endif /* PACKETFILTER_UDPHID_H_ */ 22 | -------------------------------------------------------------------------------- /scripts/install-zeromq.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # is following needed? 4 | #echo "deb http://download.opensuse.org/repositories/network:/messaging:/zeromq:/release-stable/Debian_9.0/ ./" >> /etc/apt/sources.list 5 | #wget https://download.opensuse.org/repositories/network:/messaging:/zeromq:/release-stable/Debian_9.0/Release.key -O- | sudo apt-key add 6 | #apt-get install libzmq3-dev 7 | 8 | git clone https://github.com/zeromq/libzmq.git /tmp/libzmq 9 | (cd /tmp/libzmq/ && /tmp/libzmq/autogen.sh; ./configure; make; sudo make install) 10 | 11 | git clone https://github.com/zeromq/cppzmq.git /tmp/cppzmq 12 | (cd /tmp/cppzmq && mkdir build && cd build && cmake .. && sudo make -j4 install) -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_KeyLogger.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_PACKETFILTER_KEYLOGGER_H_ 6 | #define USBPROXY_PACKETFILTER_KEYLOGGER_H_ 7 | 8 | #include 9 | #include "PacketFilter.h" 10 | 11 | class PacketFilter_KeyLogger : public PacketFilter { 12 | private: 13 | FILE* file; 14 | char lastReport[8]; 15 | void keyPressed(__u8 keyCode,__u8 mods); 16 | const char* keyMap[0x66]; 17 | const char* shiftKeyMap[0x66]; 18 | public: 19 | PacketFilter_KeyLogger(ConfigParser *cfg); 20 | void filter_packet(Packet* packet); 21 | virtual char* toString() {return (char*)"Key Logger Filter";} 22 | }; 23 | 24 | #endif /* USBPROXY_PACKETFILTER_KEYLOGGER_H_ */ 25 | -------------------------------------------------------------------------------- /src/greengrass/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # minimal CMakeLists.txt for the AWS Greengrass SDK for C 2 | cmake_minimum_required(VERSION 2.8) 3 | set(TOOL usb-mitm-gg) 4 | LIST(APPEND TOOLS_LINK_LIBS USBProxy -pthread zmq aws-greengrass-core-sdk-c) 5 | 6 | find_package(aws-greengrass-core-sdk-c REQUIRED) 7 | 8 | include_directories(${libusbproxy_SOURCE_DIR}) 9 | add_executable(${TOOL} main.cpp) 10 | target_link_libraries(${TOOL} ${TOOLS_LINK_LIBS}) 11 | target_compile_options(${TOOL} PRIVATE -Werror -Wall -Wextra -pedantic -std=c++11) 12 | 13 | install(TARGETS ${TOOL} RUNTIME DESTINATION ${INSTALL_DEFAULT_BINDIR}) 14 | 15 | # build the deployment package 16 | # the following is only working with: https://github.com/awslabs/aws-lambda-cpp 17 | #aws_lambda_package_target(${TOOL}) -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_ROT13.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include "PacketFilter_ROT13.h" 6 | 7 | void PacketFilter_ROT13::filter_packet(Packet* packet) { 8 | int i; 9 | for (i=2;i<8;i++) { 10 | if (packet->data[i]<=0x1d && packet->data[i]>=0x04) { 11 | if(packet->data[i]<=0x10) 12 | packet->data[i]=packet->data[i]+13; 13 | else 14 | packet->data[i]=packet->data[i]-13; 15 | } 16 | } 17 | } 18 | 19 | static PacketFilter_ROT13 *proxy; 20 | 21 | extern "C" { 22 | int plugin_type = PLUGIN_FILTER; 23 | 24 | PacketFilter * get_plugin(ConfigParser *cfg) { 25 | proxy = new PacketFilter_ROT13(cfg); 26 | return (PacketFilter *) proxy; 27 | } 28 | 29 | void destroy_plugin() { 30 | delete proxy; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Plugins/Injectors/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of USBProxy. 3 | # 4 | 5 | project(usbproxy_injectors C) 6 | set(PACKAGE usbproxy_injectors) 7 | 8 | LIST(APPEND PLUGINS Injector_UDP Injector_UDPHID) 9 | 10 | include_directories(${libusbproxy_SOURCE_DIR}) 11 | LIST(APPEND PLUGINS_LINK_LIBS USBProxy) 12 | 13 | foreach(plugin ${PLUGINS}) 14 | add_library(${plugin} SHARED ${plugin}.cpp) 15 | set_source_files_properties(${plugin}.cpp PROPERTIES COMPILE_FLAGS "-std=c++11 -pthread -Wall") 16 | set_target_properties(${plugin} PROPERTIES PREFIX "") 17 | target_link_libraries(${plugin} ${PLUGINS_LINK_LIBS}) 18 | install(TARGETS ${plugin} 19 | LIBRARY DESTINATION lib/USBProxy${LIB_SUFFIX} 20 | COMPONENT sharedlibs 21 | ) 22 | endforeach(plugin) 23 | -------------------------------------------------------------------------------- /src/Plugins/Injectors/Injector_UDP.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_INJECTORUDP_H 6 | #define USBPROXY_INJECTORUDP_H 7 | 8 | #include "Injector.h" 9 | #include 10 | #include 11 | 12 | #define UDP_BUFFER_SIZE 1472 13 | 14 | class Injector_UDP: public Injector { 15 | private: 16 | __u16 port; 17 | int sck; 18 | __u8* buf; 19 | struct pollfd spoll; 20 | 21 | protected: 22 | void start_injector(); 23 | void stop_injector(); 24 | int* get_pollable_fds(); 25 | void full_pipe(Packet* p); 26 | 27 | void get_packets(Packet** packet,SetupPacket** setup,int timeout=500); 28 | 29 | public: 30 | Injector_UDP(ConfigParser *cfg); 31 | virtual ~Injector_UDP(); 32 | }; 33 | 34 | #endif /* USBPROXY_INJECTORUDP_H */ 35 | -------------------------------------------------------------------------------- /src/debian/postrm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # postrm script for nesto-usbproxy 3 | 4 | set -e 5 | 6 | case "$1" in 7 | remove) 8 | sed '/dtoverlay=dwc2/d' /boot/config.txt > /boot/config.txt.bak 9 | sed '/dwc2/d' /etc/modules > /etc/modules.bak 10 | mv /etc/modules.bak /etc/modules 11 | mv /boot/config.txt.bak /boot/config.txt 12 | echo "Successfully set USB c to host mode again." 13 | ;; 14 | 15 | purge|upgrade|failed-upgrade|disappear|abort-install|abort-upgrade) 16 | 17 | ;; 18 | 19 | *) 20 | echo "postinst called with unknown argument \`$1'" >&2 21 | exit 0 22 | ;; 23 | esac 24 | 25 | # dh_installdeb will replace this with shell code automatically 26 | # generated by other debhelper scripts. 27 | 28 | #DEBHELPER# 29 | 30 | exit 0 -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_Callback.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef PACKETFILTER_CALLBACK_H_ 6 | #define PACKETFILTER_CALLBACK_H_ 7 | 8 | #include "PacketFilter.h" 9 | 10 | typedef void (*f_cb)(Packet*); 11 | typedef void (*f_cb_setup)(SetupPacket*,bool); 12 | 13 | //uses function pointers to filter packets 14 | class PacketFilter_Callback : public PacketFilter { 15 | private: 16 | f_cb cb; 17 | f_cb_setup cb_setup; 18 | public: 19 | PacketFilter_Callback(ConfigParser *cfg); 20 | PacketFilter_Callback(f_cb _cb, f_cb_setup _cb_setup); 21 | void filter_packet(Packet* packet); 22 | void filter_setup_packet(SetupPacket* packet,bool direction_out); 23 | virtual char* toString() {return (char*)"Filter";} 24 | 25 | }; 26 | 27 | #endif /* PACKETFILTER_CALLBACK_H_ */ 28 | -------------------------------------------------------------------------------- /src/Plugins/Injectors/Injector_UDPHID.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef INJECTORUDPHID_H_ 6 | #define INJECTORUDPHID_H_ 7 | 8 | #include "Injector.h" 9 | #include 10 | #include 11 | 12 | #define UDP_BUFFER_SIZE 1472 13 | 14 | class Injector_UDPHID: public Injector { 15 | private: 16 | __u16 port; 17 | int sck; 18 | __u8* buf; 19 | struct pollfd spoll; 20 | __u8 reportBuffer[20]; 21 | 22 | protected: 23 | void start_injector(); 24 | void stop_injector(); 25 | int* get_pollable_fds(); 26 | void full_pipe(Packet* p); 27 | 28 | void get_packets(Packet** packet,SetupPacket** setup,int timeout=500); 29 | 30 | public: 31 | Injector_UDPHID(ConfigParser *cfg); 32 | virtual ~Injector_UDPHID(); 33 | __u8* getReportBuffer() {return reportBuffer;} 34 | }; 35 | 36 | #endif /* INJECTORUDPHID_H_ */ 37 | -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_PcapLogger.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_PACKETFILTER_KEYLOGGER_H 6 | #define USBPROXY_PACKETFILTER_KEYLOGGER_H 7 | 8 | #include "PacketFilter.h" 9 | #include 10 | #include 11 | #include "pthread.h" 12 | 13 | class PacketFilter_PcapLogger : public PacketFilter { 14 | private: 15 | FILE *file; 16 | pcap_t *pcap_file; 17 | pcap_dumper_t *pcap_writer; 18 | pthread_mutex_t pcap_writer_mutex; 19 | __u64 pkt_count; 20 | 21 | public: 22 | PacketFilter_PcapLogger(ConfigParser *cfg); 23 | ~PacketFilter_PcapLogger(); 24 | void filter_setup_packet(SetupPacket* packet,bool direction_out); 25 | void filter_packet(Packet* packet, zmq::socket_t *sock); 26 | virtual char* toString() {return (char*)"Pcap Logging Filter";} 27 | }; 28 | 29 | #endif /* USBPROXY_PACKETFILTER_KEYLOGGER_H */ 30 | -------------------------------------------------------------------------------- /aptly/aptly.conf: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "rootDir": "/aptly", 4 | "downloadConcurrency": 4, 5 | "downloadSpeedLimit": 0, 6 | "architectures": [ 7 | "armhf" 8 | ], 9 | "dependencyFollowSuggests": false, 10 | "dependencyFollowRecommends": false, 11 | "dependencyFollowAllVariants": false, 12 | "dependencyFollowSource": false, 13 | "gpgDisableSign": false, 14 | "gpgDisableVerify": false, 15 | "downloadSourcePackages": false, 16 | "ppaDistributorID": "ubuntu", 17 | "ppaCodename": "", 18 | "S3PublishEndpoints": { 19 | "nesto-debian-repo-devel": { 20 | "region": "eu-central-1", 21 | "bucket": "nesto-debian-repo-devel", 22 | "endpoint": "", 23 | "prefix": "", 24 | "acl": "private", 25 | "storageClass": "", 26 | "encryptionMethod": "", 27 | "plusWorkaround": false, 28 | "disableMultiDel": false, 29 | "forceSigV2": false, 30 | "debug": false 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/lib/InterfaceGroup.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_INTERFACEGROUP_H 6 | #define USBPROXY_INTERFACEGROUP_H 7 | 8 | #include 9 | #include 10 | #include "DefinitionErrors.h" 11 | 12 | class Device; 13 | class Interface; 14 | 15 | class InterfaceGroup { 16 | private: 17 | __u8 number; 18 | __u8 alternateCount; 19 | Interface** interfaces; 20 | 21 | public: 22 | int activeAlternateIndex; 23 | 24 | InterfaceGroup(__u8 number); 25 | ~InterfaceGroup(); 26 | size_t get_full_descriptor_length(); 27 | void get_full_descriptor(__u8** p); 28 | void add_interface(Interface* interface); 29 | Interface* get_interface(__u8 alternate); 30 | void print(__u8 tabs=0); 31 | __u8 get_number(); 32 | __u8 get_alternate_count(); 33 | Interface* get_active_interface(); 34 | const definition_error is_defined(__u8 configId); 35 | }; 36 | 37 | #endif /* USBPROXY_INTERFACEGROUP_H */ 38 | -------------------------------------------------------------------------------- /nodejs-client/index.js: -------------------------------------------------------------------------------- 1 | const zmq = require("zeromq"); 2 | 3 | const sock = new zmq.Subscriber; 4 | 5 | (async function() { 6 | sock.connect("tcp://127.0.0.1:5678"); 7 | sock.subscribe(); 8 | console.log("Subscriber connected to port 5678"); 9 | let buf = []; 10 | let matched = 0; 11 | let desired = [0x1b, 0x6d]; // ESC/P cut sequence 12 | 13 | for await (const [msg] of sock) { 14 | for (const c of msg) { 15 | buf.push(c); 16 | console.log(c); 17 | const expected = desired[matched]; 18 | if (expected == c) { 19 | matched++; 20 | } else { 21 | matched = 0; 22 | } 23 | 24 | if (matched == desired.length) { 25 | console.log("CUT found. Receipt:\n"); 26 | console.log(buf.map(s => String.fromCharCode(s)).join("")); 27 | matched = 0; 28 | buf = []; 29 | } 30 | } 31 | } 32 | })(); 33 | -------------------------------------------------------------------------------- /src/debian/changelog: -------------------------------------------------------------------------------- 1 | nesto-usbproxy (0.1.0) main; urgency=medium 2 | 3 | * hotpluggin, mweal fixes, greengrass binary 4 | 5 | -- Martin Löper Tue, 27 Apr 2021 11:13:27 +0200 6 | 7 | nesto-usbproxy (0.0.4) main; urgency=medium 8 | 9 | * Link libzmq dynamically 10 | 11 | -- Martin Löper Mon, 15 Feb 2021 00:00:47 +0100 12 | 13 | nesto-usbproxy (0.0.3) main; urgency=medium 14 | 15 | * Test new release workflow 16 | 17 | -- Martin Löper Sun, 14 Feb 2021 02:09:38 +0100 18 | 19 | nesto-usbproxy (0.0.2) main; urgency=medium 20 | 21 | * Test the versioning and publishing of further images 22 | 23 | -- Martin Löper Mon, 08 Feb 2021 04:57:18 +0100 24 | 25 | nesto-usbproxy (0.0.1) main; urgency=low 26 | 27 | * Initial release 28 | 29 | -- Martin Loeper Tue, 02 Feb 2021 00:00:00 +0000 30 | -------------------------------------------------------------------------------- /src/lib/ConfigParser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_CONFIGPARSER_H 6 | #define USBPROXY_CONFIGPARSER_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class ConfigParser { 14 | private: 15 | std::map strings; 16 | std::map > vectors; 17 | std::map pointers; 18 | 19 | public: 20 | unsigned debugLevel; 21 | ConfigParser(); 22 | void parse_file(char* filename); 23 | 24 | void set(std::string key, std::string value); 25 | std::string get(const std::string& key); 26 | 27 | void add_to_vector(std::string key, std::string value); 28 | std::vector get_vector(std::string key); 29 | 30 | void add_pointer(std::string key, void *value); 31 | void *get_pointer(std::string key); 32 | 33 | void print_config(); 34 | }; 35 | 36 | #endif /* USBPROXY_CONFIGPARSER_H */ 37 | -------------------------------------------------------------------------------- /src/lib/USBString.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_USBSTRING_H_ 6 | #define USBPROXY_USBSTRING_H_ 7 | 8 | #include 9 | #include 10 | 11 | class DeviceProxy; 12 | 13 | class USBString { 14 | private: 15 | usb_string_descriptor* descriptor; 16 | __u16 languageId; 17 | __u8 index; 18 | 19 | public: 20 | USBString(DeviceProxy* proxy,__u8 _index,__u16 _languageId); 21 | USBString(const usb_string_descriptor* _descriptor,__u8 _index,__u16 _languageId); 22 | //create from ascii string 23 | USBString(const char* value,__u8 _index,__u16 _languageId); 24 | //create from unicode string 25 | USBString(const __u16* value,__u8 _index,__u16 _languageId); 26 | ~USBString(); 27 | const usb_string_descriptor* get_descriptor(); 28 | __u16 get_languageId(); 29 | __u8 get_index(); 30 | char* get_ascii(); 31 | __u8 get_char_count(); 32 | void append_char(__u16 u); 33 | }; 34 | 35 | 36 | #endif /* USBPROXY_USBSTRING_H_ */ 37 | -------------------------------------------------------------------------------- /src/Plugins/Hosts/HostProxy_Null.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_HOSTPROXYNULL_H 6 | #define USBPROXY_HOSTPROXYNULL_H 7 | 8 | #include "HostProxy.h" 9 | 10 | class HostProxy_Null: public HostProxy { 11 | private: 12 | bool connected=false; 13 | public: 14 | HostProxy_Null() {} 15 | virtual ~HostProxy_Null() {} 16 | 17 | int connect(Device* device) {connected=true;return 0;} 18 | void disconnect() {connected=false;} 19 | void reset() {} 20 | bool is_connected() {return connected;} 21 | 22 | int control_request(const usb_ctrlrequest *setup_packet, int *nbytes, __u8** dataptr) {setup_packet->bRequestType=0;return 0;} 23 | void send_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8* dataptr,int length) {} 24 | void receive_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8** dataptr, int* length) {*length=0;} 25 | 26 | const char* toString() {return (char*)"Null Host";} 27 | }; 28 | 29 | #endif /* USBPROXY_HOSTPROXYNULL_H */ 30 | -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_Power.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include "PacketFilter_Power.h" 6 | #include 7 | 8 | PacketFilter_Power::PacketFilter_Power(ConfigParser *cfg) { 9 | } 10 | 11 | void PacketFilter_Power::filter_setup_packet(SetupPacket* packet, bool direction_in) { 12 | struct usb_config_descriptor *config; 13 | 14 | if (direction_in 15 | && (packet->ctrl_req.bRequest == USB_REQ_GET_DESCRIPTOR) 16 | && (packet->ctrl_req.wValue == USB_DT_CONFIG)) { 17 | config = (struct usb_config_descriptor *) packet->data; 18 | config->bmAttributes = USB_CONFIG_ATT_ONE; 19 | config->bMaxPower = 0x32; /* 100mA */ 20 | } 21 | } 22 | 23 | static PacketFilter_Power *proxy; 24 | 25 | extern "C" { 26 | int plugin_type = PLUGIN_FILTER; 27 | 28 | PacketFilter * get_plugin(ConfigParser *cfg) { 29 | proxy = new PacketFilter_Power(cfg); 30 | return (PacketFilter *) proxy; 31 | } 32 | 33 | void destroy_plugin() { 34 | delete proxy; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /aptly/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian@sha256:7f2706b124ee835c3bcd7dc81d151d4f5eca3f4306c5af5c73848f5f89f10e0b as aptly_base 2 | 3 | RUN apt-get update && \ 4 | apt-get install gnupg=2.1.18-8~deb9u4 gnupg2 -y && \ 5 | apt-get clean 6 | 7 | RUN echo "deb http://repo.aptly.info/ squeeze main" > /etc/apt/sources.list.d/aptly.list && \ 8 | apt-key adv --keyserver pool.sks-keyservers.net --recv-keys ED75B5A4483DA07C && \ 9 | apt-get update && \ 10 | apt-get install aptly=1.4.0 ca-certificates=20200601~deb9u1 -y && \ 11 | apt-get clean 12 | 13 | ADD ./aptly/aptly.conf /etc/aptly.conf 14 | 15 | ENV APTLY_REPO nesto-pos-adapter-devel 16 | RUN aptly repo create $APTLY_REPO 17 | 18 | FROM aptly_base as aptly_local 19 | 20 | ADD ./docker-crosstool-ng-arm/bin/usbproxy/*.deb /root/usb-proxy/ 21 | RUN aptly repo add $APTLY_REPO /root/usb-proxy/nesto-usbproxy_*_armhf.deb 22 | 23 | ADD ./aptly/private.asc /root/usb-proxy/private.asc 24 | ADD ./aptly/public.asc /root/usb-proxy/public.asc 25 | 26 | RUN gpg --batch -v --import /root/usb-proxy/private.asc 27 | -------------------------------------------------------------------------------- /docker-crosstool-ng-arm/fixes/project-config.jam: -------------------------------------------------------------------------------- 1 | # Boost.Build Configuration 2 | # Automatically generated by bootstrap.sh 3 | 4 | import option ; 5 | import feature ; 6 | 7 | # Compiler configuration. This definition will be used unless 8 | # you already have defined some toolsets in your user-config.jam 9 | # file. 10 | if ! gcc in [ feature.values ] 11 | { 12 | using gcc : arm : arm-rpi-linux-gnueabihf-gcc ; 13 | } 14 | 15 | project : default-build gcc ; 16 | 17 | # List of --with- and --without- 18 | # options. If left empty, all libraries will be built. 19 | # Options specified on the command line completely 20 | # override this variable. 21 | libraries = ; 22 | 23 | # These settings are equivivalent to corresponding command-line 24 | # options. 25 | option.set prefix : /usr/local ; 26 | option.set exec-prefix : /usr/local ; 27 | option.set libdir : /usr/local/lib ; 28 | option.set includedir : /usr/local/include ; 29 | 30 | # Stop on first error 31 | option.set keep-going : false ; -------------------------------------------------------------------------------- /src/lib/Endpoint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_ENDPOINT_H 6 | #define USBPROXY_ENDPOINT_H 7 | 8 | #include 9 | #include 10 | #include "DefinitionErrors.h" 11 | 12 | class Interface; 13 | class DeviceProxy; 14 | 15 | class Endpoint { 16 | private: 17 | usb_endpoint_descriptor descriptor; 18 | Interface* interface; 19 | 20 | public: 21 | Endpoint(Interface* _interface,const __u8* p); 22 | Endpoint(Interface* _interface,const usb_endpoint_descriptor* _descriptor); 23 | Endpoint(Interface* _interface,__u8 bEndpointAddress,__u8 bmAttributes,__u16 wMaxPacketSize,__u8 bInterval); 24 | ~Endpoint(); 25 | const usb_endpoint_descriptor* get_descriptor(); 26 | size_t get_full_descriptor_length(); 27 | void get_full_descriptor(__u8** p); 28 | void print(__u8 tabs=0); 29 | const definition_error is_defined(__u8 configId,__u8 interfaceNum,__u8 interfaceAlternate); 30 | Interface* get_interface(); 31 | }; 32 | 33 | #endif /* USBPROXY_ENDPOINT_H */ 34 | -------------------------------------------------------------------------------- /.github/create-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # USAGE: ./create-release.sh (major|minor|patch) 4 | 5 | # HOWTO: merge all feature branches into dev first 6 | # run this script on dev branch 7 | # create a PR to merge dev into master (will create a new release) 8 | 9 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 10 | set -e 11 | 12 | echo "Please note: If you did not use this script before, please run ./install-release-tools.sh!" 13 | 14 | BUMP="${1:-patch}" 15 | VERSION=$(cat "${DIR}/../VERSION") 16 | NEW_VERSION=$(semver bump "$BUMP" "$VERSION") 17 | 18 | if [ -z "$DEBFULLNAME" ]; then 19 | export DEBFULLNAME=`git log -n 1 --pretty=format:%an` 20 | fi 21 | 22 | if [ -z "$DEBEMAIL" ]; then 23 | export DEBEMAIL=`git log -n 1 --pretty=format:%ae` 24 | fi 25 | 26 | 27 | (cd "${DIR}/../src" && dch -v ${NEW_VERSION} --distribution main --force-distribution) 28 | echo -n "$NEW_VERSION" > "${DIR}/../VERSION" 29 | 30 | echo "You are ready to commit the new version: git add -A && git commit -m \"chore: release v${NEW_VERSION}\"" -------------------------------------------------------------------------------- /src/lib/RelayReader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef RELAYREADER_H_ 6 | #define RELAYREADER_H_ 7 | 8 | #include 9 | 10 | #include 11 | 12 | class Proxy; 13 | class HostProxy; 14 | class Endpoint; 15 | class Manager; 16 | 17 | class RelayReader { 18 | private: 19 | std::atomic_bool _please_stop; 20 | PacketQueue* _sendQueue; 21 | PacketQueue* _recvQueue; 22 | Proxy* proxy; 23 | HostProxy* hostProxy; 24 | __u8 endpoint; 25 | __u8 attributes; 26 | __u16 maxPacketSize; 27 | Manager* manager; 28 | 29 | public: 30 | RelayReader(Endpoint* _endpoint,Proxy* _proxy, PacketQueue& sendQueue, Manager* _manager); 31 | RelayReader(Endpoint* _endpoint,HostProxy* _proxy, PacketQueue& sendQueue, PacketQueue& recvQueue, Manager* _manager); 32 | virtual ~RelayReader(); 33 | 34 | void relay_read(); 35 | void relay_read_setup(); 36 | 37 | void please_stop(void) { 38 | _please_stop = true; 39 | if (_recvQueue) 40 | _recvQueue->enqueue(PacketPtr()); 41 | } 42 | }; 43 | 44 | #endif /* RELAYREADER_H_ */ 45 | -------------------------------------------------------------------------------- /src/tools/git-version-gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | GVF=$1 4 | DEF_VER=v0.1-need_annotated_tag_or_version 5 | 6 | LF=' 7 | ' 8 | 9 | # First see if there is a version file (included in release tarballs), 10 | # then try git-describe, then default. 11 | if test -f $2 12 | then 13 | VN=$(cat $2) || VN="$DEF_VER" 14 | elif test -d $3/.git -o -f $3/.git && 15 | VN=$(git --git-dir=$3/.git describe --abbrev=4 HEAD 2>/dev/null) && 16 | #VN=$(git describe --tags --abbrev=4 HEAD 2>/dev/null) && 17 | case "$VN" in 18 | *$LF*) (exit 1) ;; 19 | v[0-9]*) 20 | git --git-dir=$3/.git update-index -q --refresh 21 | test -z "$(git --work-tree=$3 --git-dir=$3/.git diff-index --name-only HEAD --)" || 22 | VN="$VN-dirty" ;; 23 | esac 24 | then 25 | : #VN=$(echo "$VN" | sed -e 's/-/./g'); 26 | else 27 | VN="$DEF_VER" 28 | fi 29 | 30 | VN=$(expr "$VN" : v*'\(.*\)') 31 | 32 | if test -r $GVF 33 | then 34 | VC=$(sed -e 's/^#define VERSION "\(.*\)"/\1/' <$GVF) 35 | else 36 | VC=unset 37 | fi 38 | test "$VN" = "$VC" || { 39 | echo "#define VERSION \"$VN\"" >$GVF 40 | } 41 | 42 | -------------------------------------------------------------------------------- /src/lib/HID.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_HID_H 6 | #define USBPROXY_HID_H 7 | 8 | #include 9 | #include 10 | #include "DefinitionErrors.h" 11 | 12 | struct usb_hid_descriptor_record { 13 | __u8 bDescriptorType; 14 | __le16 wDescriptorLength; 15 | } __attribute__ ((packed)); 16 | 17 | struct usb_hid_descriptor { 18 | __u8 bLength; 19 | __u8 bDescriptorType; 20 | __le16 bcdHID; 21 | __u8 bCountryCode; 22 | __u8 bNumDescriptors; 23 | usb_hid_descriptor_record descriptors[1]; 24 | } __attribute__ ((packed)); 25 | 26 | class HID { 27 | private: 28 | usb_hid_descriptor* descriptor; 29 | 30 | public: 31 | HID(const __u8* p); 32 | HID(const usb_hid_descriptor* _descriptor); 33 | HID(__u16 bcdHID,__u8 bCountryCode,__u8 bNumDescriptors,usb_hid_descriptor_record* descriptors); 34 | ~HID(); 35 | const usb_hid_descriptor* get_descriptor(); 36 | size_t get_full_descriptor_length(); 37 | void get_full_descriptor(__u8** p); 38 | void print(__u8 tabs=0); 39 | const definition_error is_defined(); 40 | }; 41 | 42 | #endif /* USBPROXY_HID_H */ 43 | -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_Callback.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include "PacketFilter_Callback.h" 6 | 7 | PacketFilter_Callback::PacketFilter_Callback(ConfigParser *cfg) { 8 | cb = (f_cb) cfg->get_pointer("PacketFilter_Callback::filter_packet"); 9 | cb_setup = (f_cb_setup) cfg->get_pointer("PacketFilter_Callback::filter_setup_packet"); 10 | } 11 | 12 | PacketFilter_Callback::PacketFilter_Callback(f_cb _cb, f_cb_setup _cb_setup) { 13 | cb = _cb; 14 | cb_setup = _cb_setup; 15 | } 16 | 17 | void PacketFilter_Callback::filter_packet(Packet* packet) { 18 | if(cb) 19 | cb(packet); 20 | } 21 | 22 | void PacketFilter_Callback::filter_setup_packet(SetupPacket* packet,bool direction_out) { 23 | if (cb_setup) 24 | cb_setup(packet,direction_out); 25 | } 26 | 27 | static PacketFilter_Callback *proxy; 28 | 29 | extern "C" { 30 | int plugin_type = PLUGIN_FILTER; 31 | 32 | PacketFilter * get_plugin(ConfigParser *cfg) { 33 | proxy = new PacketFilter_Callback(cfg); 34 | return (PacketFilter *) proxy; 35 | } 36 | 37 | void destroy_plugin() { 38 | delete proxy; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Plugins/Devices/DeviceProxy_Null.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_DEVICEPROXYNULL_H 6 | #define USBPROXY_DEVICEPROXYNULL_H 7 | 8 | #include "DeviceProxy.h" 9 | 10 | class DeviceProxy_Null: public DeviceProxy { 11 | private: 12 | bool connected=false; 13 | public: 14 | DeviceProxy_Null() {} 15 | virtual ~DeviceProxy_Null(); 16 | 17 | virtual int connect() {connected=true;return 0;} 18 | virtual void disconnect() {connected=false;} 19 | virtual void reset() {} 20 | virtual bool is_connected() {return connected;} 21 | 22 | //this should be done synchronously 23 | virtual int control_request(const usb_ctrlrequest *setup_packet, int *nbytes, __u8* dataptr) {return 0;} 24 | virtual void send_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8* dataptr,int length) {} 25 | virtual void receive_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8** dataptr, int* length) {*length=0;} 26 | 27 | virtual __u8 get_address() {return 0;} 28 | virtual const char* toString() {return (char*)"Null Device";} 29 | 30 | }; 31 | 32 | #endif /* USBPROXY_DEVICEPROXYNULL_H */ 33 | -------------------------------------------------------------------------------- /src/lib/DeviceQualifier.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_DEVICEQUALIFIER_H 6 | #define USBPROXY_DEVICEQUALIFIER_H 7 | 8 | #include 9 | #include "DefinitionErrors.h" 10 | 11 | class Device; 12 | class Configuration; 13 | class DeviceProxy; 14 | 15 | class DeviceQualifier { 16 | private: 17 | usb_qualifier_descriptor descriptor; 18 | Configuration** configurations; 19 | Device* device; 20 | 21 | public: 22 | DeviceQualifier(Device* _device,DeviceProxy* _proxy); 23 | DeviceQualifier(Device* _device,const usb_qualifier_descriptor* _descriptor); 24 | DeviceQualifier(Device* _device,__le16 bcdUSB, __u8 bDeviceClass, __u8 bDeviceSubClass, __u8 bDeviceProtocol, __u8 bMaxPacketSize0, __u8 bNumConfigurations); 25 | ~DeviceQualifier(); 26 | const usb_qualifier_descriptor* get_descriptor(); 27 | void add_configuration(Configuration* config); 28 | Configuration* get_configuration(__u8 index); 29 | void print(__u8 tabs=0); 30 | void set_device(Device* _device); 31 | const definition_error is_defined(); 32 | }; 33 | 34 | #endif /* USBPROXY_DEVICEQUALIFIER_H */ 35 | -------------------------------------------------------------------------------- /src/lib/PluginManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_PLUGIN_MANAGER_H 6 | #define USBPROXY_PLUGIN_MANAGER_H 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | class DeviceProxy; 13 | class HostProxy; 14 | class PacketFilter; 15 | class Injector; 16 | class ConfigParser; 17 | 18 | /* Expand this list as needed */ 19 | enum plugin_manager_error { 20 | PLUGIN_MANAGER_SUCCESS = 0, 21 | PLUGIN_MANAGER_UNKNOWN_ERROR = 1, 22 | PLUGIN_MANAGER_CANNOT_FIND_FILE = 2 23 | }; 24 | 25 | class PluginManager 26 | { 27 | private: 28 | std::vector handleList; 29 | void *load_shared_lib(std::string plugin_name); 30 | 31 | public: 32 | /* These should have getter/setters */ 33 | DeviceProxy* device_proxy; 34 | HostProxy* host_proxy; 35 | std::vector filters; 36 | std::vector injectors; 37 | 38 | PluginManager(){}; 39 | int load_plugins(ConfigParser *cfg); 40 | void add_plugin(PacketFilter* plugin); 41 | void add_plugin(Injector* plugin); 42 | void destroy_plugins(); 43 | 44 | }; 45 | #endif /* USBPROXY_PLUGIN_MANAGER_H */ 46 | -------------------------------------------------------------------------------- /src/debian/copyright: -------------------------------------------------------------------------------- 1 | The USBProxy web site URL is https://github.com/dominicgs/USBProxy/ 2 | 3 | Except where otherwise noted in the source code, USBProxy is covered under 4 | the GNU General Public License (v2 or later). 5 | 6 | USBProxy is copyright (c) 2013-2014 Dominic Spill, Adam Stasiak 7 | 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License 10 | * as published by the Free Software Foundation; either version 2 11 | * of the License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 21 | 22 | On Debian systems the GNU GPL (v2) may be viewed in /usr/share/common-licenses/GPL-2. 23 | 24 | -------------------------------------------------------------------------------- /.github/workflows/build-aptly.yaml: -------------------------------------------------------------------------------- 1 | name: build-aptly 2 | on: 3 | push: 4 | paths: 5 | - 'aptly/Dockerfile' 6 | branches: master 7 | workflow_dispatch: 8 | 9 | jobs: 10 | build-aptly: 11 | name: Build Aptly Image 12 | runs-on: ubuntu-latest 13 | steps: 14 | - 15 | name: Set up Docker Buildx 16 | uses: docker/setup-buildx-action@v1 17 | 18 | - 19 | name: Login to Registry 20 | uses: docker/login-action@v1 21 | with: 22 | registry: ghcr.io 23 | username: ${{ github.repository_owner }} 24 | password: ${{ secrets.CR_PAT }} 25 | 26 | - 27 | name: Cache Docker layers 28 | uses: actions/cache@v2 29 | with: 30 | path: /tmp/.buildx-cache 31 | key: ${{ runner.os }}-buildx-${{ github.sha }} 32 | restore-keys: ${{ runner.os }}-buildx- 33 | 34 | - 35 | name: Build and push 36 | id: docker_build 37 | uses: docker/build-push-action@v2 38 | with: 39 | push: true 40 | tags: ghcr.io/${{ github.repository_owner }}/aptly:latest 41 | file: aptly/Dockerfile 42 | target: aptly_base -------------------------------------------------------------------------------- /.github/workflows/build-container.yml: -------------------------------------------------------------------------------- 1 | name: build-container 2 | on: 3 | push: 4 | paths: 5 | - '.devcontainer/**' 6 | - '.github/workflows/build-container.yml' 7 | branches: master 8 | workflow_dispatch: 9 | 10 | env: 11 | # used as the cross-toolchain release to be included into the image 12 | TOOLCHAIN_RELEASE: rpi-5.10.y 13 | 14 | jobs: 15 | build-container: 16 | runs-on: 'ubuntu-20.04' 17 | steps: 18 | - 19 | name: Login to Registry 20 | uses: docker/login-action@v1 21 | with: 22 | registry: ghcr.io 23 | username: ${{ github.repository_owner }} 24 | password: ${{ secrets.CR_PAT }} 25 | 26 | - name: Checkout 27 | uses: actions/checkout@v2 28 | with: 29 | submodules: recursive 30 | 31 | - 32 | name: Build and push 33 | id: docker_build 34 | uses: docker/build-push-action@v2 35 | with: 36 | push: true 37 | tags: ghcr.io/${{ github.repository_owner }}/usb-proxy-dev:latest,ghcr.io/${{ github.repository_owner }}/usb-proxy-dev:${{ env.TOOLCHAIN_RELEASE }} 38 | context: .devcontainer 39 | build-args: TOOLCHAIN_RELEASE=${{ env.TOOLCHAIN_RELEASE }} -------------------------------------------------------------------------------- /src/lib/PacketFilter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include 6 | #include "PacketFilter.h" 7 | #include "TRACE.h" 8 | 9 | void PacketFilter::set_packet_filter(__u8 header[8],__u8 mask[8]) { 10 | int i; 11 | packetHeaderMaskLength=1; 12 | for(i=0;i<8;i++) { 13 | if (mask[i]) {packetHeaderMaskLength=i;} 14 | } 15 | } 16 | 17 | bool PacketFilter::test_packet(const Packet* packet) { 18 | const __u8* data; 19 | if (packet->wLengthdata; 21 | int i; 22 | for(i=0;ictrl_req); 32 | int i; 33 | for(i=0;i 9 | #include 10 | #include 11 | 12 | class TCP_Helper { 13 | private: 14 | bool p_server; 15 | bool p_is_connected; 16 | __u8* ep_buf[32]; 17 | bool ep_connect[32]; 18 | int ep_socket[32]; 19 | int ep_listener[32]; 20 | struct pollfd spoll; 21 | char* p_address; 22 | int client_connect(int port,int timeout); 23 | int client_open_endpoints(__u8* eps,__u8 num_eps,int timeout); 24 | 25 | void server_listen(int port); 26 | int server_connect(int port,int timeout); 27 | int server_open_endpoints(__u8* eps,__u8 num_eps,int timeout); 28 | 29 | public: 30 | unsigned debugLevel; 31 | TCP_Helper(const char* address=NULL); 32 | virtual ~TCP_Helper(); 33 | 34 | int connect(int timeout); 35 | void disconnect(); 36 | int open_endpoints(__u8* eps,__u8 num_eps,int timeout); 37 | void reset(); 38 | bool is_connected(); 39 | 40 | void send_data(int ep,__u8* data,int length); 41 | void receive_data(int ep,__u8** data,int *length,int timeout); 42 | 43 | char* toString() {return (char *) "TCP network helper";} 44 | }; 45 | 46 | #endif /* USBPROXY_TCP_HELPER_H */ 47 | -------------------------------------------------------------------------------- /src/Plugins/Hosts/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of USBProxy. 3 | # 4 | 5 | project(usbproxy_hosts C) 6 | set(PACKAGE usbproxy_hosts) 7 | 8 | LIST(APPEND PLUGINS HostProxy_TCP) 9 | 10 | include_directories(${libusbproxy_SOURCE_DIR}) 11 | LIST(APPEND PLUGINS_LINK_LIBS USBProxy) 12 | 13 | foreach(plugin ${PLUGINS}) 14 | add_library(${plugin} SHARED ${plugin}.cpp) 15 | set_source_files_properties(${plugin}.cpp PROPERTIES COMPILE_FLAGS "-std=c++11 -pthread -Wall") 16 | set_target_properties(${plugin} PROPERTIES PREFIX "") 17 | target_link_libraries(${plugin} ${PLUGINS_LINK_LIBS}) 18 | install(TARGETS ${plugin} 19 | LIBRARY DESTINATION lib/USBProxy${LIB_SUFFIX} 20 | COMPONENT sharedlibs 21 | ) 22 | endforeach(plugin) 23 | 24 | # HostProxy_GadgetFS is a special case because of the helpers 25 | add_library(HostProxy_GadgetFS SHARED HostProxy_GadgetFS.cpp GadgetFS_helpers.c) 26 | set_target_properties(HostProxy_GadgetFS PROPERTIES PREFIX "") 27 | set_source_files_properties(HostProxy_GadgetFS.cpp PROPERTIES COMPILE_FLAGS "-std=c++11 -pthread -Wall") 28 | target_link_libraries(HostProxy_GadgetFS ${PLUGINS_LINK_LIBS}) 29 | install(TARGETS HostProxy_GadgetFS 30 | LIBRARY DESTINATION lib/USBProxy${LIB_SUFFIX} 31 | COMPONENT sharedlibs 32 | ) 33 | -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_ZeroMQ.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "HexString.h" 5 | #include "PacketFilter_ZeroMQ.h" 6 | 7 | struct ZMQ_MSG { 8 | std::vector<__u8> d; 9 | __u8 e; 10 | MSGPACK_DEFINE_MAP(d, e); 11 | }; 12 | 13 | PacketFilter_ZeroMQ::PacketFilter_ZeroMQ(ConfigParser *cfg) {} 14 | PacketFilter_ZeroMQ::~PacketFilter_ZeroMQ() {} 15 | 16 | void PacketFilter_ZeroMQ::filter_packet(Packet* packet, zmq::socket_t *sock) { 17 | struct ZMQ_MSG msg; 18 | msg.d = std::vector<__u8>(packet->data, packet->data + packet->wLength); 19 | msg.e = packet->bEndpoint; 20 | 21 | std::stringstream buffer; 22 | msgpack::pack(buffer, msg); 23 | buffer.seekg(0); 24 | std::string str(buffer.str()); 25 | 26 | (*sock).send(zmq::buffer(str), zmq::send_flags::dontwait); 27 | 28 | // TODO: is there something to clean up / free? 29 | } 30 | 31 | void PacketFilter_ZeroMQ::filter_setup_packet(SetupPacket* packet,bool direction) {} 32 | 33 | static PacketFilter_ZeroMQ *proxy; 34 | 35 | extern "C" { 36 | int plugin_type = PLUGIN_FILTER; 37 | 38 | PacketFilter * get_plugin(ConfigParser *cfg) { 39 | proxy = new PacketFilter_ZeroMQ(cfg); 40 | return (PacketFilter *) proxy; 41 | } 42 | 43 | void destroy_plugin() { 44 | delete proxy; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/lib/Packet.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_PACKET_H 6 | #define USBPROXY_PACKET_H 7 | 8 | #include // shared_ptr 9 | 10 | #include 11 | #include 12 | 13 | #include "SafeQueue.hpp" 14 | 15 | class Packet { 16 | public: 17 | __u8 bEndpoint; 18 | __u16 wLength; 19 | bool filter; 20 | bool transmit; 21 | __u8* data; 22 | 23 | Packet(__u8 _endpoint,__u8* _data,__u16 _length,bool _filter=true) : bEndpoint(_endpoint),wLength(_length),filter(_filter),transmit(true),data(_data) {} 24 | virtual ~Packet() {if (data) {free(data);data=NULL;}} 25 | }; 26 | typedef std::shared_ptr PacketPtr; 27 | typedef SafeQueue PacketQueue; 28 | 29 | class SetupPacket : public Packet { 30 | public: 31 | usb_ctrlrequest ctrl_req; 32 | int source; 33 | // TODO: share more fields with Packet 34 | bool filter_out; 35 | bool transmit_out; 36 | bool filter_in; 37 | bool transmit_in; 38 | 39 | SetupPacket(usb_ctrlrequest _ctrl_req,__u8* _data,bool _filter=true) 40 | : Packet(0, _data, 0, _filter) 41 | , ctrl_req(_ctrl_req) 42 | , source(0) 43 | , filter_out(_filter) 44 | , transmit_out(true) 45 | , filter_in(_filter) 46 | , transmit_in(true) 47 | {} 48 | }; 49 | 50 | #endif /* USBPROXY_PACKET_H */ 51 | -------------------------------------------------------------------------------- /src/Plugins/Filters/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of USBProxy. 3 | # 4 | 5 | project(usbproxy_filters C) 6 | set(PACKAGE usbproxy_filters) 7 | 8 | include_directories(${libusbproxy_SOURCE_DIR}) 9 | LIST(APPEND PLUGINS_LINK_LIBS USBProxy) 10 | 11 | LIST(APPEND PLUGINS PacketFilter_ZeroMQ PacketFilter_Callback PacketFilter_KeyLogger PacketFilter_ROT13 PacketFilter_UDPHID PacketFilter_MassStorage PacketFilter_Power PacketFilter_StreamLog) 12 | 13 | find_package(PCAP) 14 | 15 | if( ${PCAP_FOUND} ) 16 | LIST(APPEND PLUGINS PacketFilter_PcapLogger) 17 | include_directories(${PCAP_INCLUDE_DIRS}) 18 | LIST(APPEND PLUGINS_LINK_LIBS ${PCAP_LIBRARIES}) 19 | else( ${PCAP_FOUND} ) 20 | if( USE_PCAP AND NOT ${PCAP_FOUND} ) 21 | message( FATAL_ERROR 22 | "Cannot find libpcap, which is required for USE_PCAP") 23 | endif() 24 | endif( ${PCAP_FOUND} ) 25 | 26 | foreach(plugin ${PLUGINS}) 27 | add_library(${plugin} SHARED ${plugin}.cpp) 28 | set_source_files_properties(${plugin}.cpp PROPERTIES COMPILE_FLAGS "${CMAKE_CPP_FLAGS} -std=c++11 -pthread -Wall -fexceptions") 29 | set_target_properties(${plugin} PROPERTIES PREFIX "") 30 | target_link_libraries(${plugin} ${PLUGINS_LINK_LIBS}) 31 | install(TARGETS ${plugin} 32 | LIBRARY DESTINATION lib/USBProxy${LIB_SUFFIX} 33 | COMPONENT sharedlibs 34 | ) 35 | endforeach(plugin) 36 | -------------------------------------------------------------------------------- /src/debian/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # postinst script for nesto-usbproxy 3 | # 4 | # see: dh_installdeb(1) 5 | 6 | # summary of how this script can be called: 7 | # * 'configure' 8 | # * 'abort-upgrade' 9 | # * 'abort-remove' 'in-favour' 10 | # 11 | # * 'abort-deconfigure' 'in-favour' 12 | # 'removing' 13 | # 14 | # for details, see /usr/share/doc/packaging-manual/ 15 | 16 | echo $1 17 | case "$1" in 18 | configure) 19 | cat /boot/config.txt | grep -q dwc2 20 | rc=$? 21 | 22 | if [ $rc -ne 0 ]; then 23 | echo "dtoverlay=dwc2" | sudo tee -a /boot/config.txt 24 | echo "dwc2" | sudo tee -a /etc/modules 25 | 26 | echo "Changed USB c port to OTG client mode. Need a restart now." 27 | fi 28 | ;; 29 | 30 | abort-upgrade|abort-remove|abort-deconfigure) 31 | 32 | ;; 33 | 34 | *) 35 | echo "postinst called with unknown argument \`$1'" >&2 36 | exit 0 37 | ;; 38 | esac 39 | 40 | # dh_installdeb will replace this with shell code automatically 41 | # generated by other debhelper scripts. 42 | 43 | #DEBHELPER# 44 | 45 | exit 0 -------------------------------------------------------------------------------- /src/Plugins/Hosts/HostProxy_TCP.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_HOSTPROXY_TCP_H 6 | #define USBPROXY_HOSTPROXY_TCP_H 7 | 8 | #include "HostProxy.h" 9 | #include "TCP_Helper.h" 10 | 11 | class HostProxy_TCP: public HostProxy { 12 | private: 13 | bool p_is_connected; 14 | TCP_Helper* network; 15 | 16 | public: 17 | HostProxy_TCP(const char* address=NULL); 18 | HostProxy_TCP(ConfigParser *cfg); 19 | virtual ~HostProxy_TCP(); 20 | 21 | int connect(Device *device,int timeout=250); 22 | void disconnect(); 23 | void reset(); 24 | bool is_connected(); 25 | 26 | //CLEANUP is this the best way to indicate whether there was a request? 27 | //return 0 in usb_ctrlrequest->brequest if there is no request 28 | int control_request(usb_ctrlrequest *setup_packet, int *nbytes, __u8** dataptr, int timeout=500); 29 | void send_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8* dataptr,int length); 30 | bool send_wait_complete(__u8 endpoint, int timeout=500); 31 | void receive_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8** dataptr, int* length, int timeout=500); 32 | void control_ack(); 33 | void stall_ep(__u8 endpoint); 34 | 35 | void setConfig(Configuration* fs_cfg,Configuration* hs_cfg,bool hs); 36 | 37 | char* toString() {return (char *) "TCP host proxy";} 38 | }; 39 | 40 | #endif /* USBPROXY_HOSTPROXY_TCP_H */ 41 | -------------------------------------------------------------------------------- /src/lib/Proxy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_PROXY_H 6 | #define USBPROXY_PROXY_H 7 | 8 | #include "Plugins.h" 9 | #include 10 | #include 11 | #include "ConfigParser.h" 12 | 13 | class Configuration; 14 | 15 | class Proxy { 16 | public: 17 | static const __u8 plugin_type=0; 18 | 19 | Proxy() 20 | : debugLevel(0) 21 | {} 22 | Proxy(unsigned _debugLevel) 23 | : debugLevel(_debugLevel) 24 | {} 25 | 26 | virtual ~Proxy() {} 27 | 28 | virtual void send_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8* dataptr,int length)=0; 29 | virtual bool send_wait_complete(__u8 endpoint,int timeout=500) {return true;} 30 | virtual void receive_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8** dataptr, int* length,int timeout=500)=0; 31 | virtual void setConfig(Configuration* fs_cfg,Configuration* hs_cfg,bool hs)=0; 32 | virtual char* toString() {return NULL;} 33 | unsigned debugLevel; 34 | virtual void setNice(unsigned nice) {} 35 | 36 | private: 37 | /// \brief Disallow copying. 38 | /// 39 | /// This method is not implemented (besides beeing private). 40 | Proxy(const Proxy&); 41 | 42 | /// \brief Disallow assignment. 43 | /// 44 | /// This method is not implemented (besides beeing private). 45 | void operator= (const Proxy&); 46 | }; 47 | 48 | #endif /* USBPROXY_PROXY_H */ 49 | -------------------------------------------------------------------------------- /aptly/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # ARG: $1 (KEEP_BUILD_CONTAINER_RUNNING): set to 1 to build and jump into the container afterwards 3 | 4 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 5 | IMAGE_NAME=aptly:latest 6 | CONTAINER_NAME=aptly 7 | 8 | # load env vars to reference gpg key id 9 | source ./.env 10 | gpg --export --armor ${GPG_KEY_ID} > public.asc 11 | gpg --export-secret-key --armor ${GPG_KEY_ID} > private.asc 12 | 13 | echo "${GPG_KEY_PASSWORD}" > key_passwd 14 | 15 | docker build -t ${IMAGE_NAME} -f Dockerfile .. 16 | if [ $? -ne 0 ]; then 17 | echo -e "\nWe MUST abort because docker build already failed and no new image was created!\n" 18 | exit 1; 19 | fi 20 | 21 | if [ ! -z "$1" ] && [[ ( "$1" == 1 ) ]]; then 22 | echo -e "\nCommands to run in another shell:\n---------------------------------\nConnect: docker exec -it $CONTAINER_NAME bash\nKill: docker kill $CONTAINER_NAME\n" 23 | # -v "${DIR}/../docker-crosstool-ng-arm/bin/:/root/usb-proxy" 24 | docker run --rm -v "${DIR}/key_passwd:/root/usb-proxy/key_passwd" --env-file ./.env --name "${CONTAINER_NAME}" "${IMAGE_NAME}" tail -f /dev/null; exit 25 | fi 26 | 27 | # in order to publish to S3, please run "./build.sh 1" and then paste: 28 | # aptly publish repo -batch=true -passphrase-file="/root/usb-proxy/key_passwd" -gpg-key="92F91ABA4816493E" -component=local -distribution=unofficial nesto-pos-adapter-devel s3:nesto-debian-repo-devel: 29 | -------------------------------------------------------------------------------- /src/Plugins/Devices/DeviceProxy_TCP.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_DEVICEPROXY_TCP_H 6 | #define USBPROXY_DEVICEPROXY_TCP_H 7 | 8 | #include "DeviceProxy.h" 9 | #include "TCP_Helper.h" 10 | 11 | class DeviceProxy_TCP:public DeviceProxy { 12 | private: 13 | bool p_is_connected; 14 | TCP_Helper* network; 15 | 16 | public: 17 | DeviceProxy_TCP(const char* address=NULL); 18 | DeviceProxy_TCP(ConfigParser *cfg); 19 | ~DeviceProxy_TCP(); 20 | 21 | int connect(int timeout=250); 22 | void disconnect(); 23 | void reset(); 24 | bool is_connected(); 25 | bool is_highspeed(); 26 | 27 | int control_request(const usb_ctrlrequest *setup_packet, int *nbytes, __u8 *dataptr, int timeout=500); 28 | void send_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8* dataptr,int length); 29 | void receive_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8** dataptr, int* length,int timeout=500); 30 | 31 | void setConfig(Configuration* fs_cfg,Configuration* hs_cfg,bool hs); 32 | 33 | void set_endpoint_interface(__u8 endpoint, __u8 interface); 34 | void claim_interface(__u8 interface); 35 | void release_interface(__u8 interface); 36 | 37 | // modified 20141003 atsumi@aizulab.com 38 | void setEp2inf( __u8 *ep2inf_, __u8 *claimedInterface_) {}; 39 | __u8 get_address(); 40 | char* toString() {return (char *) "TCP device proxy";} 41 | }; 42 | 43 | #endif /* USBPROXY_DEVICEPROXY_TCP_H */ 44 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": [ 3 | { 4 | "label": "install", 5 | "type": "shell", 6 | "command": "${workspaceFolder}/scripts/install.sh" 7 | }, 8 | { 9 | "label": "sigterm", 10 | "type": "shell", 11 | "command": "${workspaceFolder}/scripts/sigterm.sh", 12 | "problemMatcher": [] 13 | }, 14 | { 15 | "label": "sigkill", 16 | "type": "shell", 17 | "command": "${workspaceFolder}/scripts/sigkill.sh", 18 | "problemMatcher": [] 19 | }, 20 | { 21 | "label": "prepare", 22 | "type": "shell", 23 | "command": "mkdir -p src/build" 24 | }, 25 | { 26 | "label": "all", 27 | "dependsOrder": "sequence", 28 | "dependsOn": [ 29 | "prepare", 30 | "cmake", 31 | "install" 32 | ] 33 | }, 34 | { 35 | "label": "cmake", 36 | "type": "shell", 37 | "options": { 38 | "cwd": "${workspaceRoot}/src/build" 39 | }, 40 | "command": "/usr/bin/cmake -Daws-greengrass-core-sdk-c_DIR=/usr/local/lib/ --build ${workspaceRoot}/src/build --config Debug --target all -- -j 6 ..", 41 | "problemMatcher": [] 42 | } 43 | ], 44 | "version": "2.0.0" 45 | } -------------------------------------------------------------------------------- /src/tools/additional/dot11_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Dominic Spill 3 | * Copyright 2014 Mike Kershaw / dragorn 4 | * 5 | * This file is part of USBProxy. 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; see the file COPYING. If not, write to 19 | * the Free Software Foundation, Inc., 51 Franklin Street, 20 | * Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #include "dot11_control.h" 24 | #include 25 | 26 | int main(int argc, char** argv) { 27 | char *x; 28 | struct libusb_device_handle *devh = find_dot11_device(); 29 | int timeout = 10; 30 | printf("Setting timeout=%d\n", timeout); 31 | cmd_set_timeout(devh, 10); 32 | printf("Timeout set\n"); 33 | timeout = cmd_get_timeout(devh); 34 | printf("Timeout=%d\n", timeout); 35 | x = cmd_get_capiface(devh); 36 | printf("Opened capture inteface (%s)\n", x); 37 | cmd_rx_data(devh); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_StreamLog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include "HexString.h" 6 | #include "PacketFilter_StreamLog.h" 7 | 8 | PacketFilter_StreamLog::PacketFilter_StreamLog(ConfigParser *cfg) { 9 | file = (FILE *) cfg->get_pointer("PacketFilter_StreamLog::file"); 10 | } 11 | 12 | void PacketFilter_StreamLog::filter_packet(Packet* packet, zmq::socket_t *sock) { 13 | char* hex=hex_string((void*)packet->data,packet->wLength); 14 | fprintf(file,"%02x[%d]: %s\n",packet->bEndpoint,packet->wLength,hex); 15 | free(hex); 16 | } 17 | void PacketFilter_StreamLog::filter_setup_packet(SetupPacket* packet,bool direction) { 18 | if (packet->ctrl_req.wLength && packet->data) { 19 | char* hex_setup=hex_string(&(packet->ctrl_req),sizeof(packet->ctrl_req)); 20 | char* hex_data=hex_string((void*)(packet->data),packet->ctrl_req.wLength); 21 | fprintf(file,"[%s]: %s\n",hex_setup,hex_data); 22 | free(hex_data); 23 | free(hex_setup); 24 | } else { 25 | char* hex_setup=hex_string(&(packet->ctrl_req),sizeof(packet->ctrl_req)); 26 | fprintf(file,"[%s]\n",hex_setup); 27 | free(hex_setup); 28 | } 29 | } 30 | 31 | static PacketFilter_StreamLog *proxy; 32 | 33 | extern "C" { 34 | int plugin_type = PLUGIN_FILTER; 35 | 36 | PacketFilter * get_plugin(ConfigParser *cfg) { 37 | proxy = new PacketFilter_StreamLog(cfg); 38 | return (PacketFilter *) proxy; 39 | } 40 | 41 | void destroy_plugin() { 42 | delete proxy; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/cmake/modules/FindUSB1.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find the freetype library 2 | # Once done this defines 3 | # 4 | # LIBUSB_FOUND - system has libusb 5 | # LIBUSB_INCLUDE_DIR - the libusb include directory 6 | # LIBUSB_LIBRARIES - Link these to use libusb 7 | 8 | # Copyright (c) 2006, 2008 Laurent Montel, 9 | # 10 | # Redistribution and use is allowed according to the terms of the BSD license. 11 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 12 | 13 | 14 | if (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) 15 | 16 | # in cache already 17 | set(LIBUSB_FOUND TRUE) 18 | 19 | else (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) 20 | IF (NOT WIN32) 21 | # use pkg-config to get the directories and then use these values 22 | # in the FIND_PATH() and FIND_LIBRARY() calls 23 | find_package(PkgConfig) 24 | pkg_check_modules(PC_LIBUSB libusb-1.0) 25 | ENDIF(NOT WIN32) 26 | 27 | FIND_PATH(LIBUSB_INCLUDE_DIR libusb.h 28 | PATHS ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDE_DIRS}) 29 | 30 | # note: use PC_LIBUSB_STATIC_LIBRARY_DIRS to link against static version! 31 | FIND_LIBRARY(LIBUSB_LIBRARIES NAMES usb-1.0 32 | PATHS ${PC_LIBUSB_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS}) 33 | 34 | include(FindPackageHandleStandardArgs) 35 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBUSB DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIR) 36 | 37 | MARK_AS_ADVANCED(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARIES) 38 | 39 | endif (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_UDPHID.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include "PacketFilter_UDPHID.h" 6 | 7 | PacketFilter_UDPHID::PacketFilter_UDPHID(ConfigParser *cfg) { 8 | this->interface.deviceClass=0xff; 9 | this->interface.subClass=0x5d; 10 | this->endpoint.address=0x80; 11 | this->endpoint.addressMask=0x80; 12 | this->packetHeaderMaskLength=2; 13 | this->packetHeader[0]=0; 14 | this->packetHeader[1]=20; 15 | this->packetHeaderMask[0]=0xff; 16 | this->packetHeaderMask[1]=0xff; 17 | this->packetHeaderSetupIn=false; 18 | this->packetHeaderSetupOut=false; 19 | Injector_UDPHID* injector = (Injector_UDPHID *) cfg->get_pointer("PacketFilter_UDPHID::injector"); 20 | reportBuffer=injector->getReportBuffer(); 21 | } 22 | 23 | void PacketFilter_UDPHID::filter_packet(Packet* packet) { 24 | int i; 25 | if (packet->wLength!=20) return; 26 | packet->data[2]=packet->data[2]|reportBuffer[2]; 27 | packet->data[3]=packet->data[3]|reportBuffer[3]; 28 | for (i=4;i<=13;i++) { 29 | if (reportBuffer[i]) packet->data[i]=reportBuffer[i]; 30 | } 31 | } 32 | void PacketFilter_UDPHID::filter_setup_packet(SetupPacket* packet,bool direction) { 33 | } 34 | 35 | static PacketFilter_UDPHID *proxy; 36 | 37 | extern "C" { 38 | int plugin_type = PLUGIN_FILTER; 39 | 40 | PacketFilter * get_plugin(ConfigParser *cfg) { 41 | proxy = new PacketFilter_UDPHID(cfg); 42 | return (PacketFilter *) proxy; 43 | } 44 | 45 | void destroy_plugin() { 46 | delete proxy; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/cmake/cmake_uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | # http://www.vtk.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F 2 | 3 | IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 4 | MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") 5 | ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 6 | 7 | FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) 8 | STRING(REGEX REPLACE "\n" ";" files "${files}") 9 | FOREACH(file ${files}) 10 | MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") 11 | IF(EXISTS "$ENV{DESTDIR}${file}") 12 | EXEC_PROGRAM( 13 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 14 | OUTPUT_VARIABLE rm_out 15 | RETURN_VALUE rm_retval 16 | ) 17 | IF(NOT "${rm_retval}" STREQUAL 0) 18 | MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") 19 | ENDIF(NOT "${rm_retval}" STREQUAL 0) 20 | ELSEIF(IS_SYMLINK "$ENV{DESTDIR}${file}") 21 | EXEC_PROGRAM( 22 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 23 | OUTPUT_VARIABLE rm_out 24 | RETURN_VALUE rm_retval 25 | ) 26 | IF(NOT "${rm_retval}" STREQUAL 0) 27 | MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") 28 | ENDIF(NOT "${rm_retval}" STREQUAL 0) 29 | ELSE(EXISTS "$ENV{DESTDIR}${file}") 30 | MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") 31 | ENDIF(EXISTS "$ENV{DESTDIR}${file}") 32 | ENDFOREACH(file) 33 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of USBProxy. 3 | # 4 | #top level cmake project for USBProxy lib, plugins, and commandline tool 5 | 6 | cmake_minimum_required(VERSION 2.8) 7 | set(MAJOR_VERSION 0) 8 | set(MINOR_VERSION 1) 9 | project(usbproxy_all) 10 | set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules) 11 | 12 | set(INSTALL_DEFAULT_BINDIR "bin" CACHE STRING "Appended to CMAKE_INSTALL_PREFIX") 13 | 14 | if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 15 | execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) 16 | if (GCC_VERSION VERSION_LESS 4.7) 17 | message(FATAL_ERROR 18 | "GCC version must be at least 4.7! \nTry: CC=gcc-4.7 CXX=g++-4.7 cmake") 19 | endif() 20 | endif() 21 | 22 | # Comment the following out for releases. 23 | set(CMAKE_C_FLAGS "$ENV{CFLAGS} -pthread -Wall") 24 | set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} $ENV{CPPFLAGS} -std=gnu++11 -pthread -pedantic -Wall -felide-constructors -fno-exceptions") 25 | set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -g -Wshadow -Wpointer-arith -Wcast-align -Wsign-compare -Wunused") 26 | 27 | add_subdirectory(lib) 28 | add_subdirectory(Plugins) 29 | add_subdirectory(tools) 30 | add_subdirectory(greengrass) 31 | 32 | # Create uninstall target 33 | configure_file( 34 | ${PROJECT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in 35 | ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 36 | @ONLY) 37 | 38 | add_custom_target(uninstall 39 | ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 40 | ) 41 | -------------------------------------------------------------------------------- /docker-crosstool-ng-arm/docker/app.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/nesto-software/nesto-usbproxy-deps:latest as nesto-custom-build 2 | 3 | ENV STAGING_DIR /usr/raspberry-build/staging 4 | ENV SYSROOT /opt/crosstool-ng/x-tools/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot 5 | ENV ROOT_FS /usr/raspberry-build/rootfs 6 | 7 | # checkout git repo for usb proxy project 8 | WORKDIR /root 9 | #RUN git clone https://github.com/nesto-software/USBProxy-legacy.git usbproxy 10 | COPY ./src ./usbproxy/src 11 | RUN cd ./usbproxy && mkdir -p src/build 12 | 13 | # build the executable for usb-mitm using the crosstool chain 14 | WORKDIR /root/usbproxy/src/build 15 | 16 | RUN LDFLAGS="-L${STAGING_DIR}/usr/local/lib" \ 17 | CFLAGS="-I${STAGING_DIR}/usr/local/include" \ 18 | CXXFLAGS=$CFLAGS \ 19 | PKG_CONFIG_PATH=$STAGING_DIR/usr/local/lib/pkgconfig \ 20 | cmake \ 21 | # note: following is needed to prefix pkg-config entries 22 | "-DCMAKE_PREFIX_PATH=$STAGING_DIR/usr/local" \ 23 | "-DCMAKE_FIND_ROOT_PATH=$STAGING_DIR" \ 24 | "-DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN_FILE" \ 25 | "-DCMAKE_INSTALL_PREFIX=/usr" \ 26 | "-DCMAKE_BUILD_TYPE=Release" \ 27 | "-DUSE_LIBUSB1=1" \ 28 | "-Daws-greengrass-core-sdk-c_DIR=/usr/local/lib/" \ 29 | .. 30 | 31 | RUN make 32 | 33 | # install the executable and its dependencies properly into rootfs 34 | RUN DESTDIR=${ROOT_FS} make install 35 | 36 | # build the debian package 37 | WORKDIR /root/usbproxy/src 38 | RUN dpkg-buildpackage -d -aarmhf -tarm-rpi-linux-gnueabihf 39 | 40 | WORKDIR /root/usbproxy -------------------------------------------------------------------------------- /src/lib/Configuration.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_CONFIGURATION_H 6 | #define USBPROXY_CONFIGURATION_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include "DefinitionErrors.h" 12 | 13 | class Device; 14 | class InterfaceGroup; 15 | class Interface; 16 | 17 | class DeviceProxy; 18 | class USBString; 19 | 20 | class Configuration { 21 | private: 22 | usb_config_descriptor descriptor; 23 | InterfaceGroup** interfaceGroups; 24 | Device* device; 25 | 26 | public: 27 | Configuration(Device* _device,DeviceProxy* proxy, int index,bool otherSpeed=false); 28 | Configuration(Device* _device,const usb_config_descriptor* _descriptor); 29 | Configuration(Device* _device,__u16 wTotalLength,__u8 bNumInterfaces,__u8 bConfigurationValue,__u8 iConfiguration,__u8 bmAttributes,__u8 bMaxPower,bool highSpeed=false); 30 | ~Configuration(); 31 | const usb_config_descriptor* get_descriptor(); 32 | __u8* get_full_descriptor(); 33 | size_t get_full_descriptor_length(); 34 | void add_interface(Interface* interface); 35 | Interface* get_interface_alternate(__u8 number,__u8 alternate); 36 | Interface* get_interface(__u8 number); 37 | void print(__u8 tabs=0,bool active=false); 38 | USBString* get_config_string(__u16 languageId=0); 39 | 40 | __u8 get_interface_alternate_count(__u8 number); 41 | bool is_highspeed(); 42 | const definition_error is_defined(bool highSpeed=false); 43 | Device* get_device(); 44 | }; 45 | #endif /* USBPROXY_CONFIGURATION_H */ 46 | -------------------------------------------------------------------------------- /rpi-scripts/install-repo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | echo "This script is intended to configure the debian repository for the USB Proxy project and install the latest binary." 5 | echo "" 6 | echo "Setting up the APT repository which is hosted on S3..." 7 | 8 | read -p 'AWS Access Key: ' 9 | echo ""; 10 | ACCESS_KEY_ID=${REPLY} 11 | 12 | read -s -p 'AWS Secret Access Key (hidden input): ' 13 | echo ""; 14 | SECRET_ACCESS_KEY=${REPLY} 15 | 16 | REGION=eu-central-1 17 | BUCKET=nesto-debian-repo-devel 18 | GPG_KEY_ID=92F91ABA4816493E 19 | PKG_NAME=nesto-usbproxy 20 | GPG_KEYSERVER=keys.openpgp.org 21 | 22 | echo "Installing tools which are needed by APT to access S3..." 23 | sudo apt-get update 24 | sudo apt-get install -y apt-transport-s3 25 | 26 | echo "Configuring the S3 transport for APT..." 27 | echo -e "AccessKeyId = '$ACCESS_KEY_ID'\nSecretAccessKey = '$SECRET_ACCESS_KEY'\nRegion = '$REGION'\nToken = ''" | sudo tee /etc/apt/s3auth.conf 28 | 29 | # note: please do not use nightly for production systems 30 | echo "deb [trusted=yes] s3://$BUCKET main aws" | sudo tee -a /etc/apt/sources.list 31 | echo "deb [trusted=yes] s3://$BUCKET nightly aws" | sudo tee -a /etc/apt/sources.list 32 | 33 | echo "Setting up APT keys for our S3 repo..." 34 | gpg --keyserver "$GPG_KEYSERVER" --receive-key "$GPG_KEY_ID" 35 | gpg --export --armor "$GPG_KEY_ID" | sudo apt-key add - 36 | 37 | echo "Updating the package list with the index from our S3 repo..." 38 | sudo apt-get update 39 | 40 | echo "Finally installing the latest version of our application..." 41 | sudo apt-get install -y $PKG_NAME -------------------------------------------------------------------------------- /src/Plugins/Filters/PacketFilter_MassStorage.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef PACKETFILTER_MASSSTORAGE_H 6 | #define PACKETFILTER_MASSSTORAGE_H 7 | 8 | #include "PacketFilter.h" 9 | #include "Injector.h" 10 | #include 11 | #include 12 | 13 | //writes all traffic to a stream 14 | class PacketFilter_MassStorage : public PacketFilter, public Injector { 15 | private: 16 | int state; 17 | char tag[4]; 18 | int pipe_fd[2]; /* [read, write] */ 19 | 20 | /* config flags */ 21 | bool block_writes; 22 | bool cache_blocks; 23 | bool inband_signalling; 24 | bool inband_block_writes; 25 | std::string unblock_password; 26 | std::string block_password; 27 | 28 | /* Block caching */ 29 | __u32 block_count; 30 | __u32 block_offset; 31 | __u32 base_address; 32 | std::map<__u32, __u8*> block_cache; 33 | void cache_read(__u32 address, __u8 *data); 34 | void cache_write(__u32 address, __u8 *data); 35 | void print_block_diff(__u8 *olddata, __u8 *newdata); 36 | char printable(__u8 in); 37 | 38 | /* In-Band Signalling */ 39 | void check_for_password(__u8 *data); 40 | 41 | public: 42 | PacketFilter_MassStorage(ConfigParser *cfg); 43 | ~PacketFilter_MassStorage(); 44 | 45 | /* Filter functions */ 46 | void filter_packet(Packet* packet); 47 | void queue_packet(); 48 | 49 | /* Injector functions */ 50 | void start_injector(); 51 | int *get_pollable_fds(); 52 | void stop_injector(); 53 | void get_packets(Packet** packet, SetupPacket** setup, int timeout); 54 | void full_pipe(Packet* p); 55 | }; 56 | 57 | #endif /* PACKETFILTER_MASSSTORAGE_H */ 58 | -------------------------------------------------------------------------------- /src/lib/HID.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "HID.h" 9 | #include "HexString.h" 10 | 11 | HID::HID(const __u8* p) { 12 | descriptor=(usb_hid_descriptor *)malloc(p[0]); 13 | memcpy(descriptor,p,p[0]); 14 | } 15 | 16 | HID::HID(const usb_hid_descriptor* _descriptor) { 17 | descriptor=(usb_hid_descriptor *)malloc(_descriptor->bLength); 18 | memcpy(descriptor,_descriptor,_descriptor->bLength); 19 | } 20 | 21 | HID::HID(__u16 bcdHID,__u8 bCountryCode,__u8 bNumDescriptors,usb_hid_descriptor_record* descriptors) { 22 | size_t bLength=6+bNumDescriptors*3; 23 | descriptor=(usb_hid_descriptor *)malloc(bLength); 24 | descriptor->bLength=bLength; 25 | descriptor->bDescriptorType=0x21; 26 | descriptor->bcdHID=bcdHID; 27 | descriptor->bCountryCode=bCountryCode; 28 | descriptor->bNumDescriptors=bNumDescriptors; 29 | if (bNumDescriptors) {memcpy(descriptor->descriptors,descriptors,bNumDescriptors*3);} 30 | } 31 | 32 | HID::~HID() { 33 | if (descriptor) { 34 | free(descriptor); 35 | descriptor=NULL; 36 | } 37 | } 38 | 39 | const usb_hid_descriptor* HID::get_descriptor() { 40 | return descriptor; 41 | } 42 | 43 | size_t HID::get_full_descriptor_length() { 44 | return descriptor->bLength; 45 | } 46 | 47 | void HID::get_full_descriptor(__u8** p) { 48 | memcpy(*p,descriptor,descriptor->bLength); 49 | *p=*p+descriptor->bLength; 50 | } 51 | 52 | void HID::print(__u8 tabs) { 53 | char* hex=hex_string((void*)descriptor,descriptor->bLength); 54 | printf("%.*sHID: %s\n",tabs,TABPADDING,hex); 55 | free(hex); 56 | } 57 | -------------------------------------------------------------------------------- /rpi-scripts/install-all-dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -o pipefail 4 | 5 | echo -e "[0/7] Updating package list\n" 6 | sudo apt-get update 7 | 8 | echo -e "[1/8] Installing cmake" 9 | sudo apt-get install -y cmake 10 | 11 | echo -e "[2/8] Installing libusb\n" 12 | sudo apt-get install -y libusb-1.0.0-dev 13 | 14 | echo -e "[3/8] Installing boost libs: chrono, timer, system\n" 15 | sudo apt-get install -y libboost-chrono-dev libboost-timer-dev libboost-system-dev 16 | 17 | echo -e "[4/8] Installing libzmq\n" 18 | sudo apt-get install -y libzmq3-dev 19 | 20 | echo -e "[5/8] Installing cppzmq\n" 21 | git clone https://github.com/zeromq/cppzmq.git /tmp/cppzmq || echo "Skipped clone." 22 | (cd /tmp/cppzmq && mkdir -p build && cd build && cmake -DCPPZMQ_BUILD_TESTS=off .. && sudo make -j4 install) 23 | 24 | echo -e "[6/8] Installing msgpack\n" 25 | git clone https://github.com/msgpack/msgpack-c.git /tmp/msgpack-c || echo "Skipped clone." 26 | (cd /tmp/msgpack-c && git checkout cpp_master && cmake -DMSGPACK_CXX17=ON . && sudo make install) 27 | 28 | echo -e "[7/8] Installing aws-greengrass-sdk\n" 29 | $(dirname "${BASH_SOURCE[0]}")/install-aws-greengrass-sdk.sh 30 | 31 | echo -e "[8/8] Put RPi USB into client mode" 32 | set +e 33 | set +o pipefail 34 | 35 | cat /boot/config.txt | grep -q dwc2 36 | rc=$? 37 | 38 | if [ $rc -ne 0 ]; then 39 | echo "dtoverlay=dwc2" | sudo tee -a /boot/config.txt 40 | echo "dwc2" | sudo tee -a /etc/modules 41 | 42 | echo "Changed USB c port to OTG client mode." 43 | fi 44 | 45 | echo -e "\nYou must restart the pi now for changes to usb mode to take effect!!! Use: 'sudo reboot now'\n" -------------------------------------------------------------------------------- /nodejs-client/delimiter_example.js: -------------------------------------------------------------------------------- 1 | const zmq = require("zeromq"); 2 | const msgpack = require('msgpack5')(); 3 | 4 | const sock = new zmq.Subscriber; 5 | 6 | (async function() { 7 | sock.connect("tcp://127.0.0.1:5678"); 8 | sock.subscribe(); 9 | console.log("Subscriber connected to port 5678"); 10 | let buf = []; 11 | let matched = 0; 12 | let desired = [0x1d, 0x56, 0x31]; // toshiba is set, epson would be: [0x1b, 0x6d] 13 | for await (const [msg] of sock) { 14 | for(const c of msg) { 15 | console.log(c); // uncomment if you do not know the sequence, otherwise nothing is shown 16 | buf.push(c); 17 | const expected = desired[matched]; 18 | if(expected == c) { 19 | matched++; 20 | } else { 21 | matched = 0; 22 | } 23 | 24 | if(matched == 2) { 25 | console.log("CUT found. Receipt:\n"); 26 | console.log(buf.map(s => String.fromCharCode(s)).join("")); 27 | matched = 0; 28 | buf = []; 29 | } 30 | //console.log(c.toString(16)); 31 | //console.log(c.toString()); 32 | //if(buf.length === 100) { 33 | //console.log(buf.map(s => s.toString(16))); 34 | //console.log(buf.map(s => String.fromCharCode(s)).join("")); 35 | //console.log(Buffer.from(buf)); 36 | //buf = []; 37 | //} 38 | } 39 | 40 | //console.log(buf.map(s => s.toString(16))); 41 | //console.log(buf.map(s => String.fromCharCode(s)).join("")); 42 | // const msg_decoded = msgpack.decode(msg); 43 | // console.log(msg_decoded.d); 44 | } 45 | })(); 46 | -------------------------------------------------------------------------------- /src/lib/RelayWriter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef RELAYWRITER_H_ 6 | #define RELAYWRITER_H_ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class PacketFilter; 14 | class Proxy; 15 | class DeviceProxy; 16 | class Endpoint; 17 | class Manager; 18 | 19 | class RelayWriter { 20 | private: 21 | std::atomic_bool _please_stop; 22 | //std::vector recvQueues; 23 | //std::vector sendQueues; 24 | PacketQueue* _recvQueue; 25 | PacketQueue* _sendQueue; 26 | //std::vector _sendQueues; 27 | 28 | __u8 endpoint; 29 | __u8 attributes; 30 | __u16 maxPacketSize; 31 | 32 | Proxy* proxy; 33 | DeviceProxy* deviceProxy; 34 | std::vector filters; 35 | Manager* manager; 36 | zmq::socket_t *sock; 37 | 38 | public: 39 | RelayWriter(Endpoint* _endpoint,Proxy* _proxy, PacketQueue& recvQueue); 40 | //RelayWriter(Endpoint* _endpoint,DeviceProxy* _deviceProxy,Manager* _manager,mqd_t _recvQueue,mqd_t _sendQueue); 41 | RelayWriter(Endpoint* _endpoint,DeviceProxy* _deviceProxy,Manager* _manager, PacketQueue& recvQueue, PacketQueue& sendQueue); 42 | virtual ~RelayWriter(); 43 | 44 | PacketQueue& get_recv_queue(void) { 45 | return *_recvQueue; 46 | } 47 | void add_filter(PacketFilter* filter); 48 | //void add_setup_queue(mqd_t recvQueue,mqd_t sendQueue); 49 | void set_send_queue(PacketQueue& sendQueue); 50 | 51 | void relay_write(); 52 | void relay_write_setup(); 53 | 54 | void please_stop(void) { 55 | _please_stop = true; 56 | if (_recvQueue) 57 | _recvQueue->enqueue(PacketPtr()); 58 | } 59 | }; 60 | 61 | #endif /* RELAYWRITER_H_ */ 62 | -------------------------------------------------------------------------------- /src/lib/PacketFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_PACKETFILTER_H 6 | #define USBPROXY_PACKETFILTER_H 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "Plugins.h" 13 | #include "Device.h" 14 | #include "Configuration.h" 15 | #include "Interface.h" 16 | #include "Endpoint.h" 17 | #include "Packet.h" 18 | #include "HexString.h" 19 | #include "Criteria.h" 20 | #include "ConfigParser.h" 21 | 22 | class PacketFilter { 23 | protected: 24 | __u8 packetHeader[8]; 25 | __u8 packetHeaderMask[8]; 26 | __u8 packetHeaderMaskLength; 27 | bool packetHeaderSetupOut; 28 | bool packetHeaderSetupIn; 29 | 30 | public: 31 | static const __u8 plugin_type=PLUGIN_FILTER; 32 | struct criteria_endpoint endpoint; 33 | struct criteria_interface interface; 34 | struct criteria_configuration configuration; 35 | struct criteria_device device; 36 | 37 | PacketFilter() { 38 | int i; 39 | for (i=0;i<8;i++) {packetHeader[i]=0;packetHeaderMask[i]=0;} 40 | packetHeaderMaskLength=0; 41 | packetHeaderSetupIn=true; 42 | packetHeaderSetupOut=true; 43 | } 44 | virtual ~PacketFilter() {}; 45 | 46 | virtual void filter_packet(Packet* packet, zmq::socket_t *sock) {} 47 | virtual void filter_setup_packet(SetupPacket* packet,bool direction_out) {} 48 | 49 | bool test_packet(const Packet* packet); 50 | bool test_setup_packet(const SetupPacket* packet,bool direction_out); 51 | void set_packet_filter(__u8 header[4],__u8 mask[4]); 52 | virtual char* toString() {return (char*)"Filter";} 53 | }; 54 | 55 | extern "C" { 56 | PacketFilter *get_packetfilter_plugin(); 57 | } 58 | #endif /* USBPROXY_PACKETFILTER_H */ 59 | -------------------------------------------------------------------------------- /src/lib/HostProxy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_HOSTPROXY_H 6 | #define USBPROXY_HOSTPROXY_H 7 | 8 | #include 9 | #include "Proxy.h" 10 | class Device; 11 | 12 | #define CONTROL_REQUEST_SETUP 1 13 | #define CONTROL_REQUEST_DISCONNECT 2 14 | #define CONTROL_REQUEST_CONNECT 3 15 | 16 | class HostProxy: public Proxy { 17 | public: 18 | static const __u8 plugin_type=PLUGIN_HOSTPROXY; 19 | 20 | HostProxy(const ConfigParser& cfg) 21 | : Proxy(cfg.debugLevel) 22 | {} 23 | HostProxy() 24 | {} 25 | virtual ~HostProxy() {} 26 | 27 | //return ETIMEDOUT if it times out 28 | virtual int connect(Device* device,int timeout=250)=0; 29 | virtual void disconnect()=0; 30 | virtual void reset()=0; 31 | virtual bool is_connected()=0; 32 | 33 | //return 0 in usb_ctrlrequest->brequest if there is no request 34 | virtual int control_request(usb_ctrlrequest *setup_packet, int *nbytes, __u8** dataptr,int timeout=500)=0; 35 | 36 | virtual void send_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8* dataptr,int length)=0; 37 | virtual bool send_wait_complete(__u8 endpoint,int timeout=500) {return true;} 38 | virtual void receive_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8** dataptr, int* length,int timeout=500)=0; 39 | virtual void setConfig(Configuration* fs_cfg,Configuration* hs_cfg,bool hs)=0; 40 | virtual char* toString() {return NULL;} 41 | 42 | virtual void control_ack()=0; 43 | virtual void stall_ep(__u8 endpoint)=0; 44 | virtual void disconnectEps() {} 45 | virtual void setNice(unsigned nice) {} 46 | }; 47 | 48 | extern "C" { 49 | HostProxy *get_hostproxy_plugin(ConfigParser *cfg); 50 | void destroy_plugin(); 51 | } 52 | #endif /* USBPROXY_HOSTPROXY_H */ 53 | -------------------------------------------------------------------------------- /src/cmake/modules/Findlorcon.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find the lorcon library 2 | # Once done this defines 3 | # 4 | # LORCON_FOUND - system has lorcon 5 | # LORCON_INCLUDE_DIR - the lorcon include directory 6 | # LORCON_LIBRARIES - Link these to use lorcon 7 | 8 | # Copyright (c) 2014 Dominic Spill 9 | # Copyright (c) 2013 Benjamin Vernoux 10 | # 11 | 12 | if (LORCON_INCLUDE_DIR AND LORCON_LIBRARIES) 13 | 14 | # in cache already 15 | set(LORCON_FOUND TRUE) 16 | 17 | else (LORCON_INCLUDE_DIR AND LORCON_LIBRARIES) 18 | IF (NOT WIN32) 19 | # use pkg-config to get the directories and then use these values 20 | # in the FIND_PATH() and FIND_LIBRARY() calls 21 | find_package(PkgConfig) 22 | pkg_check_modules(PC_LORCON QUIET lorcon) 23 | ENDIF(NOT WIN32) 24 | 25 | FIND_PATH(LORCON_INCLUDE_DIR 26 | NAMES lorcon2/lorcon.h 27 | HINTS $ENV{LORCON_DIR}/include ${PC_LORCON_INCLUDEDIR} 28 | PATHS /usr/local/include /usr/include 29 | /usr/include ${CMAKE_SOURCE_DIR}/../lib 30 | /opt/local/include/lorcon 31 | ${LORCON_INCLUDE_DIR} 32 | ) 33 | 34 | FIND_LIBRARY(LORCON_LIBRARIES 35 | NAMES orcon2 36 | HINTS $ENV{LORCON_DIR}/lib ${PC_LORCON_LIBDIR} 37 | PATHS /usr/local/lib /usr/lib /opt/local/lib ${PC_LORCON_LIBDIR} ${PC_LORCON_LIBRARY_DIRS} ${CMAKE_SOURCE_DIR}/../lib 38 | ) 39 | 40 | if(LORCON_INCLUDE_DIR) 41 | set(CMAKE_REQUIRED_INCLUDES ${LORCON_INCLUDE_DIR}) 42 | endif() 43 | 44 | if(LORCON_LIBRARIES) 45 | set(CMAKE_REQUIRED_LIBRARIES ${LORCON_LIBRARIES}) 46 | endif() 47 | 48 | include(FindPackageHandleStandardArgs) 49 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LORCON DEFAULT_MSG LORCON_LIBRARIES LORCON_INCLUDE_DIR) 50 | 51 | MARK_AS_ADVANCED(LORCON_INCLUDE_DIR LORCON_LIBRARIES) 52 | 53 | endif (LORCON_INCLUDE_DIR AND LORCON_LIBRARIES) -------------------------------------------------------------------------------- /src/lib/EP_IO.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef EP_IO_H_ 6 | #define EP_IO_H_ 7 | 8 | enum ep_io_action { 9 | EP_ACTION_FUNCTION=1, 10 | EP_ACTION_FD=2, 11 | EP_ACTION_AIO=3 12 | }; 13 | 14 | enum ep_io_notify { 15 | EP_NOTIFY_TIMEOUT=1, 16 | EP_NOTIFY_POLL=2, 17 | EP_NOTIFY_AIO=3 18 | }; 19 | 20 | struct ep_transfer_info { 21 | __u8 endpoint; 22 | __u8* data; 23 | int length; 24 | }; 25 | 26 | struct ep_setup_info { 27 | __u8 endpoint; 28 | __u8 attributes; 29 | __u16 maxPacketSize; 30 | }; 31 | 32 | class USBHostProxy; 33 | class USBDeviceProxy; 34 | 35 | struct ep_io_info { 36 | enum ep_io_action io_action; 37 | enum ep_io_notify io_notify; 38 | union { 39 | int fd; 40 | USBHostProxy* hostProxy; 41 | USBDeviceProxy* deviceProxy; 42 | }; 43 | }; 44 | 45 | //TODO the thinking here is we can call a host/device proxy with 46 | //virtual ep_io_info initialize_io(struct ep_setup_info ep_info)=0; 47 | //and it will indicate which monitoring method to use 48 | //EP_NOTIFY_TIMEOUT will call a function with a timeout 49 | //EP_NOTIFY_POLL will provide a pollable FD 50 | //EP_NOTIFY_AIO will wait on an async IO handle 51 | //when the EP is available we can use several different methods to actually accomplish the transfer 52 | //EP_ACTION_FUNCTION call the standar device/hostproxy function 53 | //EP_ACTION_FD standard direct read/write to the FD 54 | //EP_ACTION_AIO async direct read/write to the FD 55 | //EP_NOTIFY_TIMEOUT will require EP_ACTION_FUNCTION 56 | //EP_NOTIFY_POLL would probably do EP_ACTION_FD, 57 | //but could do EP_ACTION_FUNCTION (but we would need a new virtual member function in the base clasee to handle this) 58 | //EP_NOTIFY_AIO would probably go with //EP_ACTION_AIO but could use a function as above. 59 | 60 | 61 | #endif /* EP_IO_H_ */ 62 | -------------------------------------------------------------------------------- /src/Plugins/Devices/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of USBProxy. 3 | # 4 | 5 | project(usbproxy_devices C) 6 | set(PACKAGE usbproxy_devices) 7 | 8 | set(CMAKE_C_FLAGS "$ENV{CFLAGS} -pthread -Wall") 9 | set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} $ENV{CPPFLAGS} -std=gnu++11 -pthread -pedantic -Wall -felide-constructors -fno-exceptions") 10 | 11 | include_directories(${libusbproxy_SOURCE_DIR}) 12 | LIST(APPEND PLUGINS_LINK_LIBS USBProxy zmq) 13 | 14 | LIST(APPEND PLUGINS DeviceProxy_Loopback DeviceProxy_TCP DeviceProxy_Callback) 15 | 16 | find_package(USB1) 17 | 18 | if( ${LIBUSB_FOUND} ) 19 | LIST(APPEND PLUGINS DeviceProxy_LibUSB) 20 | include_directories(${LIBUSB_INCLUDE_DIR}) 21 | LIST(APPEND PLUGINS_LINK_LIBS ${LIBUSB_LIBRARIES}) 22 | else( ${LIBUSB_FOUND} ) 23 | if( USE_LIBUSB1 AND NOT ${LIBUSB_FOUND} ) 24 | message( FATAL_ERROR 25 | "Cannot find libUSB-1.0, which is required for USE_LIBUSB1") 26 | endif() 27 | endif( ${LIBUSB_FOUND} ) 28 | 29 | find_package(lorcon) 30 | 31 | if( ${LORCON_FOUND} ) 32 | LIST(APPEND PLUGINS DeviceProxy_dot11) 33 | include_directories(${LORCON_INCLUDE_DIR}) 34 | LIST(APPEND PLUGINS_LINK_LIBS ${LORCON_LIBRARIES}) 35 | else( ${LORCON_FOUND} ) 36 | if( USE_LORCON AND NOT ${LORCON_FOUND} ) 37 | message( FATAL_ERROR 38 | "Cannot find lorcon, which is required for USE_LORCON") 39 | endif() 40 | endif( ${LORCON_FOUND} ) 41 | 42 | foreach(plugin ${PLUGINS}) 43 | add_library(${plugin} SHARED ${plugin}.cpp) 44 | set_source_files_properties(${plugin}.cpp PROPERTIES COMPILE_FLAGS "${CMAKE_CPP_FLAGS}") 45 | set_target_properties(${plugin} PROPERTIES PREFIX "") 46 | target_link_libraries(${plugin} ${PLUGINS_LINK_LIBS}) 47 | install(TARGETS ${plugin} 48 | LIBRARY DESTINATION lib/USBProxy${LIB_SUFFIX} 49 | COMPONENT sharedlibs 50 | ) 51 | endforeach(plugin) 52 | -------------------------------------------------------------------------------- /src/Plugins/Devices/DeviceProxy_dot11.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_DEVICEPROXY_DOT11_H 6 | #define USBPROXY_DEVICEPROXY_DOT11_H 7 | 8 | #include "DeviceProxy.h" 9 | #include "Dot11_Interface.h" 10 | 11 | extern "C" { 12 | 13 | class Configuration; 14 | 15 | class DeviceProxy_dot11 : public DeviceProxy { 16 | private: 17 | bool p_is_connected; 18 | struct usb_device_descriptor dot11_device_descriptor; 19 | struct usb_config_descriptor dot11_config_descriptor; 20 | struct usb_interface_descriptor dot11_interface_descriptor; 21 | struct usb_endpoint_descriptor dot11_eps[2]; 22 | struct usb_string; 23 | std::string interface; 24 | /* Are we in monitor mode? */ 25 | bool monitor; 26 | 27 | public: 28 | DeviceProxy_dot11(ConfigParser *cfg); 29 | ~DeviceProxy_dot11(); 30 | 31 | int connect(int timeout=250); 32 | void disconnect(); 33 | void reset(); 34 | bool is_connected(); 35 | 36 | bool is_highspeed(); 37 | 38 | //return -1 to stall 39 | int control_request(const usb_ctrlrequest *setup_packet, int *nbytes, __u8* dataptr,int timeout=500); 40 | int vendor_request(const usb_ctrlrequest *setup_packet, int *nbytes, __u8* dataptr,int timeout=500); 41 | 42 | void send_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8* dataptr,int length); 43 | bool send_wait_complete(__u8 endpoint,int timeout=500) {return true;} 44 | void receive_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8** dataptr, int* length,int timeout=500); 45 | void setConfig(Configuration* fs_cfg,Configuration* hs_cfg,bool hs); 46 | char* toString() {return (char *) "Lookback device";} 47 | 48 | void claim_interface(__u8 interface); 49 | void release_interface(__u8 interface); 50 | 51 | __u8 get_address(); 52 | }; 53 | } /* extern C */ 54 | #endif /* USBPROXY_DEVICEPROXY_DOT11_H */ 55 | -------------------------------------------------------------------------------- /src/Plugins/Hosts/HostProxy_GadgetFS.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_HOSTPROXY_GADGETFS_H 6 | #define USBPROXY_HOSTPROXY_GADGETFS_H 7 | 8 | extern "C" { 9 | #include 10 | } 11 | #include "HostProxy.h" 12 | #include 13 | #include 14 | #include 15 | #include "TRACE.h" 16 | #include "errno.h" 17 | #include "aio.h" 18 | #include 19 | 20 | class HostProxy_GadgetFS: public HostProxy { 21 | private: 22 | bool p_is_connected; 23 | int p_device_file; 24 | const char* device_filename; 25 | struct aiocb* p_epin_async[16]; 26 | struct aiocb* p_epout_async[16]; 27 | bool p_epin_active[16]; 28 | 29 | char* descriptor; 30 | int descriptorLength; 31 | 32 | int reconnect(); 33 | int generate_descriptor(Device* device); 34 | 35 | usb_ctrlrequest lastControl; 36 | mutable std::mutex m; 37 | 38 | bool cancelAio(unsigned ep); 39 | void closeEP(uint8_t endpoint); 40 | 41 | public: 42 | HostProxy_GadgetFS(ConfigParser *cfg); 43 | virtual ~HostProxy_GadgetFS(); 44 | 45 | int connect(Device* device,int timeout=250); 46 | void disconnect(); 47 | void reset(); 48 | bool is_connected(); 49 | 50 | //return 0 in usb_ctrlrequest->brequest if there is no request 51 | int control_request(usb_ctrlrequest *setup_packet, int *nbytes, __u8** dataptr,int timeout=500); 52 | void send_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8* dataptr,int length); 53 | bool send_wait_complete(__u8 endpoint,int timeout=500); 54 | void receive_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8** dataptr, int* length,int timeout=500); 55 | void control_ack(); 56 | void stall_ep(__u8 endpoint); 57 | void setConfig(Configuration* fs_cfg,Configuration* hs_cfg,bool hs); 58 | void disconnectEps(); 59 | }; 60 | 61 | #endif /* USBPROXY_HOSTPROXY_GADGETFS_H */ 62 | -------------------------------------------------------------------------------- /src/lib/Criteria.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_CRITERIA_H 6 | #define USBPROXY_CRITERIA_H 7 | 8 | #include 9 | 10 | class Endpoint; 11 | class Interface; 12 | class Configuration; 13 | class Device; 14 | 15 | struct criteria_endpoint { 16 | __u8 address; 17 | __u8 addressMask; 18 | __u8 attributes; 19 | __u8 attributesMask; 20 | __u16 packetSizeMin; 21 | __u16 packetSizeMax; 22 | __u8 intervalMin; 23 | __u8 intervalMax; 24 | 25 | criteria_endpoint(): 26 | address(0), 27 | addressMask(0), 28 | attributes(0), 29 | attributesMask(0), 30 | packetSizeMin(0), 31 | packetSizeMax(65535), 32 | intervalMin(0), 33 | intervalMax(255) {} 34 | bool test(Endpoint* endpoint); 35 | }; 36 | 37 | 38 | struct criteria_interface { 39 | short number; 40 | short alternate; 41 | short deviceClass; 42 | short subClass; 43 | short protocol; 44 | 45 | criteria_interface(): 46 | number(-1), 47 | alternate(-1), 48 | deviceClass(-1), 49 | subClass(-1), 50 | protocol(-1) {} 51 | bool test(Interface* interface); 52 | }; 53 | 54 | struct criteria_configuration { 55 | short number; 56 | __u8 attributes; 57 | __u8 attributesMask; 58 | 59 | criteria_configuration(): 60 | number(-1), 61 | attributes(0), 62 | attributesMask(0) {} 63 | bool test(Configuration* configuration); 64 | }; 65 | 66 | 67 | struct criteria_device { 68 | short deviceClass; 69 | short subClass; 70 | short protocol; 71 | __u8 ep0packetSizeMin; 72 | __u8 ep0packetSizeMax; 73 | int vendor; 74 | int product; 75 | int release; 76 | 77 | criteria_device(): 78 | deviceClass(-1), 79 | subClass(-1), 80 | protocol(-1), 81 | ep0packetSizeMin(0), 82 | ep0packetSizeMax(255), 83 | vendor(-1), 84 | product(-1), 85 | release(-1) {} 86 | bool test(Device* device); 87 | }; 88 | #endif /* USBPROXY_CRITERIA_H */ 89 | -------------------------------------------------------------------------------- /src/Plugins/Devices/DeviceProxy_Loopback.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_DEVICEPROXY_LOOPBACK_H 6 | #define USBPROXY_DEVICEPROXY_LOOPBACK_H 7 | 8 | #include "DeviceProxy.h" 9 | 10 | class Configuration; 11 | 12 | struct pkt { 13 | int length; 14 | __u8 *data; 15 | 16 | pkt(): length(0),data(NULL) {} 17 | }; 18 | 19 | class DeviceProxy_Loopback : public DeviceProxy { 20 | private: 21 | bool p_is_connected; 22 | struct pkt *buffer; 23 | int head, tail; 24 | bool full; 25 | struct usb_device_descriptor loopback_device_descriptor; 26 | struct usb_config_descriptor loopback_config_descriptor; 27 | struct usb_interface_descriptor loopback_interface_descriptor; 28 | struct usb_endpoint_descriptor loopback_eps[2]; 29 | struct usb_string ; 30 | 31 | public: 32 | DeviceProxy_Loopback(int vendorId, int productId); 33 | DeviceProxy_Loopback(ConfigParser *cfg); 34 | ~DeviceProxy_Loopback(); 35 | 36 | int connect(int timeout=250); 37 | void disconnect(); 38 | void reset(); 39 | bool is_connected(); 40 | 41 | bool is_highspeed(); 42 | 43 | //return -1 to stall 44 | int control_request(const usb_ctrlrequest *setup_packet, int *nbytes, __u8* dataptr,int timeout=500); 45 | 46 | void send_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8* dataptr,int length); 47 | bool send_wait_complete(__u8 endpoint,int timeout=500) {return true;} 48 | void receive_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8** dataptr, int* length,int timeout=500); 49 | void setConfig(Configuration* fs_cfg,Configuration* hs_cfg,bool hs); 50 | char* toString() {return (char *) "Lookback device";} 51 | 52 | void set_endpoint_interface(__u8 endpoint, __u8 interface); 53 | void claim_interface(__u8 interface); 54 | void release_interface(__u8 interface); 55 | 56 | __u8 get_address(); 57 | }; 58 | 59 | #endif /* USBPROXY_DEVICEPROXY_LOOPBACK_H */ 60 | -------------------------------------------------------------------------------- /src/cmake/modules/FindUSBProxy.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find the usbproxy library 2 | # Once done this defines 3 | # 4 | # USBPROXY_FOUND - system has usbproxy 5 | # USBPROXY_INCLUDE_DIR - the usbproxy include directory 6 | # USBPROXY_LIBRARIES - Link these to use usbproxy 7 | 8 | # Copyright (c) 2014 Dominic Spill 9 | # Copyright (c) 2013 Benjamin Vernoux 10 | # 11 | 12 | 13 | if (USBPROXY_INCLUDE_DIR AND USBPROXY_LIBRARIES) 14 | 15 | # in cache already 16 | set(USBPROXY_FOUND TRUE) 17 | 18 | else (USBPROXY_INCLUDE_DIR AND USBPROXY_LIBRARIES) 19 | IF (NOT WIN32) 20 | # use pkg-config to get the directories and then use these values 21 | # in the FIND_PATH() and FIND_LIBRARY() calls 22 | find_package(PkgConfig) 23 | pkg_check_modules(PC_USBPROXY QUIET usbproxy) 24 | ENDIF(NOT WIN32) 25 | 26 | FIND_PATH(USBPROXY_INCLUDE_DIR 27 | NAMES DeviceProxy.h 28 | HINTS $ENV{USBPROXY_DIR}/include ${PC_USBPROXY_INCLUDEDIR} 29 | PATHS /usr/local/include /usr/include 30 | /usr/include ${CMAKE_SOURCE_DIR}/../lib 31 | /opt/local/include/usbproxy 32 | ${USBPROXY_INCLUDE_DIR} 33 | ) 34 | 35 | set(usbproxy_library_names USBProxy) 36 | 37 | FIND_LIBRARY(USBPROXY_LIBRARIES 38 | NAMES ${usbproxy_library_names} 39 | HINTS $ENV{USBPROXY_DIR}/lib ${PC_USBPROXY_LIBDIR} 40 | PATHS /usr/local/lib /usr/lib /opt/local/lib ${PC_USBPROXY_LIBDIR} ${PC_USBPROXY_LIBRARY_DIRS} ${CMAKE_SOURCE_DIR}/../lib 41 | ) 42 | 43 | if(USBPROXY_INCLUDE_DIR) 44 | set(CMAKE_REQUIRED_INCLUDES ${USBPROXY_INCLUDE_DIR}) 45 | endif() 46 | 47 | if(USBPROXY_LIBRARIES) 48 | set(CMAKE_REQUIRED_LIBRARIES ${USBPROXY_LIBRARIES}) 49 | endif() 50 | 51 | include(FindPackageHandleStandardArgs) 52 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(USBPROXY DEFAULT_MSG USBPROXY_LIBRARIES USBPROXY_INCLUDE_DIR) 53 | 54 | MARK_AS_ADVANCED(USBPROXY_INCLUDE_DIR USBPROXY_LIBRARIES) 55 | 56 | endif (USBPROXY_INCLUDE_DIR AND USBPROXY_LIBRARIES) -------------------------------------------------------------------------------- /src/tools/additional/dot11_control.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Dominic Spill 3 | * 4 | * This file is part of USBProcy. 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2, or (at your option) 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; see the file COPYING. If not, write to 18 | * the Free Software Foundation, Inc., 51 Franklin Street, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | #include "Dot11_Interface.h" 23 | #include 24 | 25 | struct libusb_device_handle* find_dot11_device(); 26 | 27 | int cmd_open_inject(struct libusb_device_handle* devh); 28 | int cmd_open_monitor(struct libusb_device_handle* devh); 29 | int cmd_open_injmon(struct libusb_device_handle* devh); 30 | 31 | int cmd_set_timeout(struct libusb_device_handle* devh, int timeout); 32 | int cmd_get_timeout(struct libusb_device_handle* devh); 33 | 34 | int cmd_set_datalink(struct libusb_device_handle* devh, int datalink); 35 | int cmd_get_datalink(struct libusb_device_handle* devh); 36 | 37 | int cmd_set_channel(struct libusb_device_handle* devh, int channel); 38 | int cmd_get_channel(struct libusb_device_handle* devh); 39 | 40 | int cmd_close_interface(struct libusb_device_handle* devh); 41 | 42 | char* cmd_get_capiface(struct libusb_device_handle* devh); 43 | 44 | int cmd_rx_data(struct libusb_device_handle* devh); 45 | /* To match lorcon without having to install it on the host system */ 46 | #define MAX_IFNAME_LEN 32 47 | 48 | -------------------------------------------------------------------------------- /src/lib/DefinitionErrors.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_DEFINITIONERRORS_H 6 | #define USBPROXY_DEFINITIONERRORS_H 7 | 8 | #include 9 | 10 | //0xff0000 object num2 11 | //0xff0000 object num 12 | //0xff00 object type 13 | //0xff error 14 | 15 | enum de_obj_type { 16 | DE_OBJ_NONE= 0x00, 17 | DE_OBJ_DEVICE= 0x01, 18 | DE_OBJ_CONFIG= 0x02, 19 | DE_OBJ_STRING= 0x03, 20 | DE_OBJ_INTERFACE= 0x04, 21 | DE_OBJ_ENDPOINT= 0x05, 22 | DE_OBJ_QUALIFIER= 0x06, 23 | DE_OBJ_OS_CONFIG= 0x07, 24 | DE_OBJ_INTERFACEGROUP= 0x84 25 | }; 26 | 27 | enum de_error { 28 | DE_ERR_NONE= 0x00, 29 | DE_ERR_INVALID_DESCRIPTOR= 0x01, //detail contains 1-based byte index of error 30 | DE_ERR_NULL_OBJECT= 0x02, //no detail 31 | DE_ERR_MISSING_LANGUAGE= 0x03, //detail conains missing languageId, configId contains the relevant stringId 32 | DE_ERR_MISPLACED_OBJECT= 0x04, //detail contains incorrect index 33 | DE_ERR_MISPLACED_IF_NUM= 0x05 //detail contains incorrect index 34 | }; 35 | 36 | struct definition_error { 37 | de_error error; 38 | __u16 error_detail; 39 | de_obj_type objectType; 40 | __u8 configId; //also holds stringid, high bit 1 for other speed configs 41 | __u8 interfaceNum; 42 | __u8 interfaceAlternate; 43 | __u8 endpointNum; 44 | definition_error() : 45 | error(DE_ERR_NONE), 46 | error_detail(0), 47 | objectType(DE_OBJ_NONE), 48 | configId(0), 49 | interfaceNum(0), 50 | interfaceAlternate(0), 51 | endpointNum(0) {} 52 | definition_error(de_error _error,__u16 _error_detail,de_obj_type _objectType, 53 | __u8 _configId=0,__u8 _interfaceNum=0,__u8 _interfaceAlternate=0,__u8 _endpointNum=0) : 54 | error(_error), 55 | error_detail(_error_detail), 56 | objectType(_objectType), 57 | configId(_configId), 58 | interfaceNum(_interfaceNum), 59 | interfaceAlternate(_interfaceAlternate), 60 | endpointNum(_endpointNum) {} 61 | }; 62 | 63 | #endif /* USBPROXY_DEFINITIONERRORS_H */ 64 | -------------------------------------------------------------------------------- /src/lib/DeviceProxy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_DEVICEPROXY_H 6 | #define USBPROXY_DEVICEPROXY_H 7 | 8 | #include 9 | #include "Proxy.h" 10 | #include 11 | 12 | class Configuration; 13 | 14 | class DeviceProxy : public Proxy { 15 | typedef std::function cbVV_t; 16 | 17 | private: 18 | virtual void disconnectCallback() {} 19 | 20 | public: 21 | 22 | static const __u8 plugin_type=PLUGIN_DEVICEPROXY; 23 | 24 | DeviceProxy(const ConfigParser& cfg) 25 | : Proxy(cfg.debugLevel) 26 | {} 27 | DeviceProxy() 28 | {} 29 | virtual ~DeviceProxy() {} 30 | 31 | //return ETIMEDOUT if it times out 32 | virtual int connect(int timeout=250)=0; 33 | virtual void disconnect()=0; 34 | virtual void reset()=0; 35 | virtual bool is_connected()=0; 36 | 37 | virtual bool is_highspeed()=0; 38 | 39 | //return -1 to stall 40 | virtual int control_request(const usb_ctrlrequest *setup_packet, int *nbytes, __u8* dataptr,int timeout=500)=0; 41 | 42 | virtual void send_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8* dataptr,int length)=0; 43 | virtual bool send_wait_complete(__u8 endpoint,int timeout=500) {return true;} 44 | virtual void receive_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8** dataptr, int* length,int timeout=500)=0; 45 | virtual void setConfig(Configuration* fs_cfg,Configuration* hs_cfg,bool hs)=0; 46 | virtual char* toString() {return NULL;} 47 | 48 | virtual void set_endpoint_interface(__u8 endpoint, __u8 interface)=0; 49 | virtual void claim_interface(__u8 interface)=0; 50 | virtual void release_interface(__u8 interface)=0; 51 | 52 | virtual __u8 get_address()=0; 53 | virtual void setNice(unsigned nice) {} 54 | cbVV_t disconnectNotifierCallback = nullptr; 55 | virtual void setDisconnectNotifierCallback(cbVV_t func) {disconnectNotifierCallback = func;} 56 | 57 | 58 | }; 59 | 60 | extern "C" { 61 | DeviceProxy *get_deviceproxy_plugin(ConfigParser *cfg); 62 | void destroy_plugin(); 63 | } 64 | #endif /* USBPROXY_DEVICEPROXY_H */ 65 | -------------------------------------------------------------------------------- /src/lib/Interface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_INTERFACE_H 6 | #define USBPROXY_INTERFACE_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include "DefinitionErrors.h" 12 | 13 | class DeviceProxy; 14 | class Device; 15 | class Configuration; 16 | class HID; 17 | class USBString; 18 | 19 | struct GenericDescriptor { 20 | __u8 bLength; 21 | __u8 bDescriptorType; 22 | __u8 bData[1]; 23 | } __attribute__ ((packed)); 24 | 25 | class Configuration; 26 | class Endpoint; 27 | class USBString; 28 | 29 | class Interface { 30 | private: 31 | usb_interface_descriptor descriptor; 32 | Endpoint** endpoints; 33 | Configuration* configuration; 34 | HID* hid_descriptor; 35 | GenericDescriptor** generic_descriptors; 36 | __u8 generic_descriptor_count; 37 | 38 | public: 39 | Interface(Configuration* _configuration,__u8** p,const __u8* e); 40 | Interface(Configuration* _configuration,const usb_interface_descriptor* _descriptor); 41 | Interface(Configuration* _configuration,__u8 bInterfaceNumber,__u8 bAlternateSetting,__u8 bNumEndpoints,__u8 bInterfaceClass,__u8 bInterfaceSubClass,__u8 bInterfaceProtocol,__u8 iInterface); 42 | ~Interface(); 43 | const usb_interface_descriptor* get_descriptor(); 44 | size_t get_full_descriptor_length(); 45 | void get_full_descriptor(__u8** p); 46 | void add_endpoint(Endpoint* endpoint); 47 | Endpoint* get_endpoint_by_idx(__u8 index); 48 | Endpoint* get_endpoint_by_address(__u8 address); 49 | __u8 get_endpoint_count(); 50 | void print(__u8 tabs=0,bool active=false); 51 | USBString* get_interface_string(__u16 languageId=0); 52 | const GenericDescriptor* get_generic_descriptor(__u8 index); 53 | __u8 get_generic_descriptor_count(); 54 | void add_generic_descriptor(GenericDescriptor* _gd); 55 | const definition_error is_defined(__u8 configId,__u8 interfaceNum); 56 | Configuration* get_configuration(); 57 | const bool has_HID(); 58 | size_t get_HID_descriptor_length(); 59 | }; 60 | 61 | #endif /* USBPROXY_INTERFACE_H */ 62 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cmake.sourceDirectory": "${workspaceFolder}/src", 3 | "cmake.buildDirectory": "${workspaceFolder}/src/build", 4 | "files.associations": { 5 | "sstream": "cpp", 6 | "array": "cpp", 7 | "string_view": "cpp", 8 | "new": "cpp", 9 | "iosfwd": "cpp", 10 | "atomic": "cpp", 11 | "*.tcc": "cpp", 12 | "bitset": "cpp", 13 | "cctype": "cpp", 14 | "chrono": "cpp", 15 | "clocale": "cpp", 16 | "cmath": "cpp", 17 | "complex": "cpp", 18 | "condition_variable": "cpp", 19 | "cstdarg": "cpp", 20 | "cstddef": "cpp", 21 | "cstdint": "cpp", 22 | "cstdio": "cpp", 23 | "cstdlib": "cpp", 24 | "cstring": "cpp", 25 | "ctime": "cpp", 26 | "cwchar": "cpp", 27 | "cwctype": "cpp", 28 | "deque": "cpp", 29 | "forward_list": "cpp", 30 | "list": "cpp", 31 | "unordered_map": "cpp", 32 | "unordered_set": "cpp", 33 | "vector": "cpp", 34 | "exception": "cpp", 35 | "algorithm": "cpp", 36 | "functional": "cpp", 37 | "iterator": "cpp", 38 | "map": "cpp", 39 | "memory": "cpp", 40 | "memory_resource": "cpp", 41 | "optional": "cpp", 42 | "ratio": "cpp", 43 | "set": "cpp", 44 | "string": "cpp", 45 | "system_error": "cpp", 46 | "tuple": "cpp", 47 | "type_traits": "cpp", 48 | "utility": "cpp", 49 | "fstream": "cpp", 50 | "future": "cpp", 51 | "initializer_list": "cpp", 52 | "iomanip": "cpp", 53 | "iostream": "cpp", 54 | "istream": "cpp", 55 | "limits": "cpp", 56 | "mutex": "cpp", 57 | "ostream": "cpp", 58 | "stdexcept": "cpp", 59 | "streambuf": "cpp", 60 | "thread": "cpp", 61 | "cfenv": "cpp", 62 | "cinttypes": "cpp", 63 | "typeindex": "cpp", 64 | "typeinfo": "cpp", 65 | "valarray": "cpp", 66 | "variant": "cpp" 67 | } 68 | } -------------------------------------------------------------------------------- /src/Plugins/Hosts/GadgetFS_helpers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Dominic Spill 3 | * Copyright 2013 Adam Stasiak 4 | * 5 | * Based on libusb-gadget - Copyright 2009 Daiki Ueno 6 | * 7 | * This file is part of USBProxy. 8 | * 9 | * This program is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation; either version 3, or (at your option) 12 | * any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; see the file COPYING. If not, write to 21 | * the Free Software Foundation, Inc., 51 Franklin Street, 22 | * Boston, MA 02110-1301, USA. 23 | * 24 | * GadgetFS_helpers.c 25 | * 26 | * Created on: Nov 24, 2013 27 | */ 28 | 29 | #ifndef USBPROXY_GADGETFS_HELPERS_H 30 | #define USBPROXY_GADGETFS_HELPERS_H 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | /* gadgetfs currently has no chunking (or O_DIRECT/zerocopy) support 37 | * to turn big requests into lots of smaller ones; so this is "small". 38 | */ 39 | #define USB_BUFSIZE (7 * 1024) 40 | 41 | /* open the appropriate gadget file on the GadgetFS filesystem */ 42 | int open_gadget(const char *); 43 | 44 | /* Find the appropriate gadget file on the GadgetFS filesystem */ 45 | const char * find_gadget_filename(); 46 | 47 | /* Find & open an endpoint file */ 48 | int open_endpoint(__u8 epAddress, const char * gadget_filename); 49 | 50 | /* Mount gadgetfs filesystem in a temporary directory */ 51 | int mount_gadget(); 52 | 53 | /* Unmount gadgetfs filesystem and remove temporary directory */ 54 | int unmount_gadget(); 55 | 56 | void clean_tmp(); 57 | 58 | #ifdef __cplusplus 59 | } // __cplusplus defined. 60 | #endif 61 | 62 | #endif /* USBPROXY_GADGETFS_HELPERS_H */ 63 | -------------------------------------------------------------------------------- /src/lib/FDInfo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "FDInfo.h" 11 | 12 | void showFDDetail( __s32 fd ) { 13 | char buf[256]; 14 | 15 | __s32 fd_flags = fcntl( fd, F_GETFD ); 16 | if ( fd_flags == -1 ) return; 17 | 18 | int fl_flags = fcntl( fd, F_GETFL ); 19 | if ( fl_flags == -1 ) return; 20 | 21 | char path[256]; 22 | snprintf( path, sizeof(path), "/proc/self/fd/%d", fd ); 23 | 24 | memset( &buf[0], 0, 256 ); 25 | ssize_t s = readlink( path, &buf[0], 256 ); 26 | if ( s == -1 ) 27 | { 28 | fprintf(stderr," (%s): not available\n",path); 29 | return; 30 | } 31 | fprintf(stderr,"%d (%s): ",fd,buf); 32 | 33 | if ( fd_flags & FD_CLOEXEC ) fprintf(stderr,"cloexec "); 34 | 35 | // file status 36 | if ( fl_flags & O_APPEND ) fprintf(stderr,"append "); 37 | if ( fl_flags & O_NONBLOCK ) fprintf(stderr,"nonblock "); 38 | 39 | // acc mode 40 | if ( fl_flags & O_RDONLY ) fprintf(stderr,"read-only "); 41 | if ( fl_flags & O_RDWR ) fprintf(stderr,"read-write "); 42 | if ( fl_flags & O_WRONLY ) fprintf(stderr,"write-only "); 43 | 44 | if ( fl_flags & O_DSYNC ) fprintf(stderr,"dsync "); 45 | if ( fl_flags & O_RSYNC ) fprintf(stderr,"rsync "); 46 | if ( fl_flags & O_SYNC ) fprintf(stderr,"sync "); 47 | 48 | struct flock fl; 49 | fl.l_type = F_WRLCK; 50 | fl.l_whence = 0; 51 | fl.l_start = 0; 52 | fl.l_len = 0; 53 | fcntl( fd, F_GETLK, &fl ); 54 | if ( fl.l_type != F_UNLCK ) 55 | { 56 | if ( fl.l_type == F_WRLCK ) 57 | fprintf(stderr,"write-locked"); 58 | else 59 | fprintf(stderr,"read-locked"); 60 | fprintf(stderr,"(pid:%d) ",fl.l_pid); 61 | } 62 | fprintf(stderr,"\n"); 63 | } 64 | 65 | void showFDInfo() { 66 | int numHandles = getdtablesize(); 67 | __s32 i; 68 | for ( i = 0; i < numHandles; i++ ) 69 | { 70 | __s32 fd_flags = fcntl( i, F_GETFD ); 71 | if ( fd_flags == -1 ) continue; 72 | showFDDetail(i); 73 | } 74 | } 75 | 76 | 77 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Install + Run", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/src/build/tools/usb-mitm", 12 | "args": [ 13 | // "-v", "045e", "-p", "07f8", "-z", "-l" 14 | "-v", "04e8", "-p", "3461", "-z", "-l" 15 | ], 16 | "stopAtEntry": false, 17 | "cwd": "${workspaceFolder}", 18 | "environment": [], 19 | "externalConsole": false, 20 | "MIMode": "gdb", 21 | "setupCommands": [ 22 | { 23 | "description": "Enable pretty-printing for gdb", 24 | "text": "-enable-pretty-printing", 25 | "ignoreFailures": true 26 | } 27 | ], 28 | "miDebuggerPath": "${workspaceFolder}/scripts/gdb_sudo.sh", 29 | "preLaunchTask": "install", 30 | }, 31 | { 32 | "name": "All", 33 | "type": "cppdbg", 34 | "request": "launch", 35 | "program": "${workspaceFolder}/src/build/tools/usb-mitm", 36 | "args": [ 37 | //"-v", "045e", "-p", "07f8", "-z" 38 | "-v", "04e8", "-p", "3461", "-z" 39 | ], 40 | "stopAtEntry": false, 41 | "cwd": "${workspaceFolder}", 42 | "environment": [], 43 | "externalConsole": false, 44 | "MIMode": "gdb", 45 | "setupCommands": [ 46 | { 47 | "description": "Enable pretty-printing for gdb", 48 | "text": "-enable-pretty-printing", 49 | "ignoreFailures": true 50 | } 51 | ], 52 | "miDebuggerPath": "${workspaceFolder}/scripts/gdb_sudo.sh", 53 | "preLaunchTask": "all", 54 | } 55 | ] 56 | } -------------------------------------------------------------------------------- /docker-crosstool-ng-arm/build-binary.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # ARG: $1 (KEEP_BUILD_CONTAINER_RUNNING): set to 1 to build and jump into the container afterwards 3 | # ARG: $2 (TRANSFER_TO_PI_SSH_KEYFILE_PATH): set to ssh key which is used to upload the artifact on a rpi 4 | 5 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 6 | 7 | # remove the local cmake build dir if there is any 8 | rm -Rf $DIR/../src/build 9 | 10 | # build the docker container - use the name which is also generated by docker-compose 11 | IMAGE_NAME=docker-crosstool-ng-arm_webapp:latest 12 | CONTAINER_NAME=crosstool-builder 13 | STAGING_DIR=/usr/raspberry-build/staging 14 | ROOTFS_DIR=/usr/raspberry-build/rootfs 15 | BINARY_PATH=STAGING_DIR/bin/usb-mitm 16 | 17 | # clear the binary output directory 18 | mkdir -p "${DIR}/bin" 19 | rm -Rf "${DIR}/bin/"* 20 | rm -f usb-mitm.tar 21 | 22 | docker build -t ${IMAGE_NAME} -f Dockerfile .. 23 | if [ $? -ne 0 ]; then 24 | echo -e "\nWe MUST abort because docker build already failed and no new image was created!\n" 25 | exit 1; 26 | fi 27 | 28 | # we must create a container first to copy a file from the image 29 | # see: https://stackoverflow.com/questions/25292198/docker-how-can-i-copy-a-file-from-an-image-to-a-host 30 | 31 | # use the following to debug the container after successful docker build 32 | if [ ! -z "$1" ] && [[ ( "$1" == 1 ) ]]; then 33 | echo -e "\nCommands to run in another shell:\n---------------------------------\nConnect: docker exec -it $CONTAINER_NAME bash\nKill: docker kill $CONTAINER_NAME\n" 34 | docker run --rm --name "${CONTAINER_NAME}" "${IMAGE_NAME}" tail -f /dev/null; exit 35 | else 36 | docker run -d --rm --name "${CONTAINER_NAME}" "${IMAGE_NAME}" sleep 120 || echo "You can ignore that error message if you are running this script multiple times." 37 | #docker cp "${CONTAINER_NAME}:${BINARY_PATH}" "bin/usb-mitm" 38 | #docker cp "${CONTAINER_NAME}:${ROOTFS_DIR}" "bin" 39 | docker cp "${CONTAINER_NAME}:/root/usbproxy/" "bin/" 40 | (cd bin; cp -r ../../nodejs-client nodejs-clients; tar cf ../usb-mitm.tar .;) 41 | docker kill "${CONTAINER_NAME}" 42 | fi 43 | 44 | if [ ! -z "$2" ]; then 45 | scp -i "$2" ./usb-mitm.tar pi@169.254.100.1:/home/pi/usb-mitm.tar 46 | fi -------------------------------------------------------------------------------- /src/lib/SafeQueue.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SAFE_QUEUE 2 | #define SAFE_QUEUE 3 | 4 | // Based on http://stackoverflow.com/questions/15278343/c11-thread-safe-queue 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define QUEUE_MAX 10000 13 | #define QUEUE_FULL_WARNING_THRESHOLD 1000 14 | #include 15 | 16 | template 17 | class SafeQueue 18 | { 19 | public: 20 | SafeQueue(void) 21 | : q() 22 | , qPriority() 23 | , m() 24 | , c() 25 | , destruct(0) 26 | {} 27 | 28 | ~SafeQueue(void) 29 | { 30 | destruct = true; 31 | c.notify_one(); 32 | std::this_thread::yield(); 33 | } 34 | 35 | void enqueue(T t) { 36 | std::lock_guard lock(m); 37 | if (!q.empty()) { 38 | auto size(q.size()); 39 | if (size >= QUEUE_MAX) 40 | return; 41 | if (size == QUEUE_MAX - QUEUE_FULL_WARNING_THRESHOLD) 42 | std::cerr << "Warning: queue fills up! Feel free to search the bug in either the driver or usbproxy.\n"; 43 | } 44 | q.push(t); 45 | c.notify_one(); 46 | } 47 | 48 | T dequeue(void) { 49 | std::unique_lock lock(m); 50 | while(q.empty() && qPriority.empty()) { 51 | c.wait(lock); 52 | if(destruct) 53 | { 54 | return nullptr; 55 | } 56 | } 57 | T val; 58 | if (!qPriority.empty()) { 59 | std::swap(qPriority.front(), val); 60 | qPriority.pop(); 61 | } else { 62 | std::swap(q.front(), val); 63 | q.pop(); 64 | } 65 | 66 | return val; 67 | } 68 | 69 | void enqueuePriority(T t) { 70 | std::lock_guard lock(m); 71 | if (!qPriority.empty()) { 72 | auto size(qPriority.size()); 73 | if (size >= QUEUE_MAX) 74 | return; 75 | if (size == QUEUE_MAX - QUEUE_FULL_WARNING_THRESHOLD) 76 | std::cerr << "Warning: queuePriority fills up! Feel free to search the bug in either the driver or usbproxy.\n"; 77 | } 78 | qPriority.push(t); 79 | c.notify_one(); 80 | } 81 | 82 | bool empty(void) {return q.empty() && qPriority.empty();} 83 | 84 | size_t size(void) {return q.size() + qPriority.size();} 85 | 86 | private: 87 | std::queue q, qPriority; 88 | mutable std::mutex m; 89 | std::condition_variable c; 90 | bool destruct; 91 | }; 92 | #endif 93 | -------------------------------------------------------------------------------- /src/lib/Criteria.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include "Criteria.h" 6 | 7 | #include "Device.h" 8 | #include "Configuration.h" 9 | #include "Interface.h" 10 | #include "Endpoint.h" 11 | 12 | bool criteria_endpoint::test(Endpoint* endpoint) { 13 | const usb_endpoint_descriptor* desc=endpoint->get_descriptor(); 14 | if ((addressMask&address)!=(addressMask&desc->bEndpointAddress)) {return false;} 15 | if ((attributesMask&attributes)!=(attributesMask&desc->bmAttributes)) {return false;} 16 | if (packetSizeMin>desc->wMaxPacketSize || packetSizeMaxwMaxPacketSize) {return false;} 17 | if (intervalMin>desc->bInterval || intervalMaxbInterval) {return false;} 18 | return true; 19 | } 20 | 21 | bool criteria_interface::test(Interface* interface) { 22 | const usb_interface_descriptor* desc=interface->get_descriptor(); 23 | if (number!=-1 && number!=desc->bInterfaceNumber) {return false;} 24 | if (alternate!=-1 && alternate!=desc->bAlternateSetting) {return false;} 25 | if (deviceClass!=-1 && deviceClass!=desc->bInterfaceClass) {return false;} 26 | if (subClass!=-1 && subClass!=desc->bInterfaceSubClass) {return false;} 27 | if (protocol!=-1 && protocol!=desc->bInterfaceProtocol) {return false;} 28 | return true; 29 | } 30 | bool criteria_configuration::test(Configuration* configuration) { 31 | const usb_config_descriptor* desc=configuration->get_descriptor(); 32 | if (number!=-1 && number!=desc->bConfigurationValue) {return false;} 33 | if ((attributesMask&attributes)!=(attributesMask&desc->bmAttributes)) {return false;} 34 | return true; 35 | } 36 | bool criteria_device::test(Device* device) { 37 | const usb_device_descriptor* desc=device->get_descriptor(); 38 | if (deviceClass!=-1 && deviceClass!=desc->bDeviceClass) {return false;} 39 | if (subClass!=-1 && subClass!=desc->bDeviceSubClass) {return false;} 40 | if (protocol!=-1 && protocol!=desc->bDeviceProtocol) {return false;} 41 | if (ep0packetSizeMin>desc->bMaxPacketSize0 || ep0packetSizeMaxbMaxPacketSize0) {return false;} 42 | if (vendor!=-1 && vendor!=desc->idVendor) {return false;} 43 | if (product!=-1 && product!=desc->idProduct) {return false;} 44 | if (release!=-1 && release!=desc->bcdDevice) {return false;} 45 | return true; 46 | } 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/Plugins/Devices/DeviceProxy_Callback.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_DEVICEPROXY_CALLBACK_H 6 | #define USBPROXY_DEVICEPROXY_CALLBACK_H 7 | 8 | #include "DeviceProxy.h" 9 | 10 | class Configuration; 11 | 12 | struct pkt { 13 | int length; 14 | __u8 *data; 15 | 16 | pkt(): length(0),data(NULL) {} 17 | }; 18 | 19 | typedef int (*f_connect)(int); 20 | typedef void (*f_disconnect)(void); 21 | typedef void (*f_reset)(void); 22 | typedef int (*f_control_request)(const usb_ctrlrequest*,int*,__u8*,int); 23 | typedef void (*f_send_data)(__u8,__u8,__u16,__u8*,int); 24 | typedef void (*f_receive_data)(__u8,__u8,__u16,__u8*,int*,int); 25 | typedef char* (*f_toString)(void); 26 | 27 | 28 | class DeviceProxy_Callback : public DeviceProxy { 29 | private: 30 | bool p_is_connected; 31 | struct usb_device_descriptor callback_device_descriptor; 32 | struct usb_config_descriptor callback_config_descriptor; 33 | struct usb_interface_descriptor callback_interface_descriptor; 34 | struct usb_endpoint_descriptor callback_eps[2]; 35 | struct usb_string ; 36 | 37 | f_connect connect_cb; 38 | f_disconnect disconnect_cb; 39 | f_reset reset_cb; 40 | f_control_request control_request_cb; 41 | f_send_data send_data_cb; 42 | f_receive_data receive_data_cb; 43 | f_toString toString_cb; 44 | 45 | public: 46 | DeviceProxy_Callback(ConfigParser *cfg); 47 | ~DeviceProxy_Callback(); 48 | 49 | int connect(int timeout=250); 50 | void disconnect(); 51 | void reset(); 52 | bool is_connected(); 53 | bool is_highspeed(); 54 | 55 | //return -1 to stall 56 | int control_request(const usb_ctrlrequest *setup_packet, int *nbytes, __u8* dataptr,int timeout=500); 57 | 58 | void send_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8* dataptr,int length); 59 | bool send_wait_complete(__u8 endpoint,int timeout=500) {return true;} 60 | void receive_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8** dataptr, int* length,int timeout=500); 61 | void setConfig(Configuration* fs_cfg,Configuration* hs_cfg,bool hs); 62 | char* toString(); 63 | 64 | void set_endpoint_interface(__u8 endpoint, __u8 interface); 65 | 66 | void claim_interface(__u8 interface); 67 | void release_interface(__u8 interface); 68 | 69 | __u8 get_address(); 70 | }; 71 | 72 | #endif /* USBPROXY_DEVICEPROXY_CALLBACK_H */ 73 | -------------------------------------------------------------------------------- /src/Plugins/Devices/DeviceProxy_LibUSB.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_DEVICEPROXY_LIBUSB_H 6 | #define USBPROXY_DEVICEPROXY_LIBUSB_H 7 | 8 | #ifndef LIBUSB_HOTPLUG_MATCH_ANY 9 | #define LIBUSB_HOTPLUG_MATCH_ANY -1 10 | #endif 11 | 12 | #include 13 | #include "DeviceProxy.h" 14 | 15 | #include 16 | 17 | class DeviceProxy_LibUSB: public DeviceProxy { 18 | private: 19 | libusb_context* context; 20 | libusb_hotplug_callback_handle callback_handle; 21 | libusb_device_handle* dev_handle; 22 | bool privateContext; 23 | bool privateDevice; 24 | int desired_vid; 25 | int desired_pid; 26 | bool desired_hubs; 27 | 28 | struct 29 | { 30 | uint8_t interface; 31 | bool defined; 32 | bool claimed; 33 | } epInterfaces[0x10]; 34 | 35 | bool endpoint_interface_claimed(uint8_t endpoint); 36 | unsigned nice; 37 | std::thread libusbThread; 38 | void libusbEventLoop(); 39 | 40 | public: 41 | DeviceProxy_LibUSB(int vendorId = LIBUSB_HOTPLUG_MATCH_ANY, int productId = LIBUSB_HOTPLUG_MATCH_ANY, 42 | bool includeHubs = false); 43 | DeviceProxy_LibUSB(ConfigParser *cfg); 44 | ~DeviceProxy_LibUSB(); 45 | 46 | int connect(int timeout = 250); 47 | int connect(int vendorId, int productId, bool includeHubs); 48 | int connect(libusb_device* dvc, libusb_context* _context = NULL); 49 | int connect(libusb_device_handle* devh, libusb_context* _context = NULL); 50 | void disconnect(); 51 | void reset(); 52 | bool is_connected(); 53 | bool is_highspeed(); 54 | 55 | int control_request(const usb_ctrlrequest *setup_packet, int *nbytes, uint8_t* dataptr, int timeout = 500); 56 | void send_data(uint8_t endpoint, uint8_t attributes, uint16_t maxPacketSize, uint8_t* dataptr, int length); 57 | void receive_data(uint8_t endpoint, uint8_t attributes, uint16_t maxPacketSize, uint8_t** dataptr, int* length, 58 | int timeout = 500); 59 | 60 | void setConfig(Configuration* fs_cfg, Configuration* hs_cfg, bool hs) { 61 | } 62 | 63 | void set_endpoint_interface(uint8_t endpoint, uint8_t interface); 64 | void claim_interface(uint8_t interface); 65 | void release_interface(uint8_t interface); 66 | 67 | uint8_t get_address(); 68 | char* toString(); 69 | void setNice(unsigned nice); 70 | bool please_stop; 71 | int rxAttempt = 0; 72 | }; 73 | 74 | #endif /* USBPROXY_DEVICEPROXY_LIBUSB_H */ 75 | -------------------------------------------------------------------------------- /src/Plugins/Devices/Dot11_Interface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_DOT11_INTERFACE_H 6 | #define USBPROXY_DOT11_INTERFACE_H 7 | 8 | #include 9 | 10 | enum dot11_usb_commands { 11 | DOT11_OPEN_INJECT = 0, 12 | DOT11_OPEN_MONITOR = 1, 13 | DOT11_OPEN_INJMON = 2, 14 | DOT11_GET_TIMEOUT = 3, 15 | DOT11_SET_TIMEOUT = 4, 16 | DOT11_GET_CAPIFACE = 5, 17 | DOT11_GET_DRIVER_NAME = 6, 18 | DOT11_CLOSE_INTERFACE = 7, 19 | DOT11_GET_DATALINK = 8, 20 | DOT11_SET_DATALINK = 9, 21 | DOT11_GET_CHANNEL = 10, 22 | DOT11_SET_CHANNEL = 11, 23 | DOT11_GET_HWMAC = 12, 24 | DOT11_SET_HWMAC = 13, 25 | DOT11_ADD_WEPKEY = 14, 26 | }; 27 | 28 | #define DOT11_VID 0xffff 29 | #define DOT11_PID 0x0005 30 | 31 | /* This struct will be sent at the start of a bulk trasnfer 32 | * followed by length bytes */ 33 | struct dot11_packet_header { 34 | int32_t tv_sec; 35 | int32_t tv_usec; 36 | int dlt; 37 | 38 | /* Channel we captured on or channel will tx on */ 39 | int channel; 40 | 41 | /* Length of components */ 42 | int length_capheader; 43 | int length_data; 44 | }; 45 | typedef struct dot11_packet_header dot11_packet_header_t; 46 | 47 | ///* Get a pcap_t */ 48 | //pcap_t *lorcon_get_pcap(lorcon_t *context); 49 | ///* Return pcap selectable FD */ 50 | //int lorcon_get_selectable_fd(lorcon_t *context); 51 | // 52 | ///* Fetch the next packet. This is available on all sources, including 53 | // * those which do not present a pcap interface */ 54 | //int lorcon_next_ex(lorcon_t *context, lorcon_packet_t **packet); 55 | // 56 | ///* Add a capture filter (if possible) using pcap bpf */ 57 | //int lorcon_set_filter(lorcon_t *context, const char *filter); 58 | // 59 | ///* Add a precompiled filter (again, using bpf) */ 60 | //int lorcon_set_compiled_filter(lorcon_t *context, struct bpf_program *filter); 61 | // 62 | ///* Pass through to pcap instance */ 63 | //int lorcon_loop(lorcon_t *context, int count, lorcon_handler callback, u_char *user); 64 | //int lorcon_dispatch(lorcon_t *context, int count, lorcon_handler callback, u_char *user); 65 | //void lorcon_breakloop(lorcon_t *context); 66 | // 67 | ///* Inject a packet */ 68 | //int lorcon_inject(lorcon_t *context, lorcon_packet_t *packet); 69 | // 70 | ///* Inject raw bytes */ 71 | //int lorcon_send_bytes(lorcon_t *context, int length, u_char *bytes); 72 | // 73 | //unsigned long int lorcon_get_version(); 74 | 75 | #endif /* USBPROXY_DOT11_INTERFACE_H */ 76 | -------------------------------------------------------------------------------- /src/lib/Device.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_DEVICE_H 6 | #define USBPROXY_DEVICE_H 7 | 8 | #include 9 | #include "DefinitionErrors.h" 10 | 11 | //CLEANUP error checking on malloc/calloc/realloc 12 | //CLEANUP leak checking on malloc/calloc/realloc 13 | //CLEANUP bound checking (or resize arrays) on add_*/get_* 14 | //CLEANUP handle control_request errors 15 | //CLEANUP null terminated arrays, vs ones where the count is stored vs ones where count is stored in descriptor, should some of these be changed to different types 16 | 17 | class Configuration; 18 | class DeviceQualifier; 19 | class USBString; 20 | class DeviceProxy; 21 | 22 | class Device { 23 | private: 24 | int hostAddress; 25 | int deviceAddress; 26 | usb_device_state hostState; 27 | usb_device_state deviceState; 28 | bool highspeed; 29 | 30 | int hostConfigurationIndex; 31 | int deviceConfigurationIndex; 32 | 33 | usb_device_descriptor descriptor; 34 | Configuration** configurations; 35 | //this is set up like strings[stringID][array of all languages] 36 | USBString ***strings; 37 | int maxStringIdx; 38 | DeviceProxy* proxy; 39 | void add_language(__u16); 40 | DeviceQualifier* qualifier; 41 | const definition_error is_string_defined(__u8 index); 42 | 43 | public: 44 | Device(DeviceProxy* _proxy); 45 | Device(const usb_device_descriptor* _descriptor); 46 | Device(__le16 bcdUSB, __u8 bDeviceClass, __u8 bDeviceSubClass, __u8 bDeviceProtocol, __u8 bMaxPacketSize0, __le16 idVendor, __le16 idProduct, __le16 bcdDevice, __u8 iManufacturer, __u8 iProduct, __u8 iSerialNumber, __u8 bNumConfigurations); 47 | ~Device(); 48 | const usb_device_descriptor* get_descriptor(); 49 | void add_configuration(Configuration* config); 50 | Configuration* get_configuration(__u8 index); 51 | void set_active_configuration(__u8 index); 52 | 53 | void print(__u8 tabs=0); 54 | void add_string(USBString* string); 55 | //adds via proxy 56 | void add_string(__u8 index,__u16 languageId); 57 | //adds for all languages 58 | void add_string(__u8 index); 59 | USBString* get_string(__u8 index,__u16 languageId); 60 | USBString* get_manufacturer_string(__u16 languageId=0); 61 | USBString* get_product_string(__u16 languageId=0); 62 | USBString* get_serial_string(__u16 languageId=0); 63 | __u16 get_language_by_index(__u8 index); 64 | int get_language_count(); 65 | Configuration* get_active_configuration(); 66 | DeviceQualifier* get_device_qualifier(); 67 | void set_device_qualifier(DeviceQualifier* _qualifier); 68 | bool is_highspeed(); 69 | const definition_error is_defined(); 70 | }; 71 | 72 | #endif /* USBPROXY_DEVICE_H */ 73 | -------------------------------------------------------------------------------- /src/greengrass/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "greengrasssdk.h" 3 | 4 | #include "Manager.h" 5 | #include "ConfigParser.h" 6 | #include 7 | #include 8 | 9 | Manager* manager; 10 | zmq::context_t *ctx = new zmq::context_t(); 11 | zmq::socket_t *frontend = new zmq::socket_t(*ctx, zmq::socket_type::xsub); 12 | zmq::socket_t *backend = new zmq::socket_t(*ctx, zmq::socket_type::xpub); 13 | static int done; 14 | 15 | void run_proxy(zmq::socket_t *frontend, zmq::socket_t *backend) { 16 | 17 | // proxy until context is destroyed, see: http://api.zeromq.org/3-2:zmq-proxy 18 | zmq::proxy(*frontend, *backend); 19 | } 20 | 21 | void handle_signal(int signum) 22 | { 23 | (void)signum; 24 | done = 1; 25 | } 26 | 27 | void handler(const gg_lambda_context *cxt) { 28 | (void)cxt; 29 | return; 30 | } 31 | 32 | int main() { 33 | gg_error err = GGE_SUCCESS; 34 | 35 | err = gg_global_init(0); 36 | if(err) { 37 | gg_log(GG_LOG_ERROR, "gg_global_init failed %d", err); 38 | return -1; 39 | } 40 | 41 | gg_runtime_start(handler, GG_RT_OPT_ASYNC); 42 | 43 | struct sigaction action; 44 | memset(&action, 0, sizeof(struct sigaction)); 45 | action.sa_handler = handle_signal; 46 | sigaction(SIGTERM, &action, NULL); 47 | sigaction(SIGINT, &action, NULL); 48 | 49 | const char* vendorId = std::getenv("VENDOR_ID"); 50 | const char* productId = std::getenv("PRODUCT_ID"); 51 | 52 | ConfigParser *cfg = new ConfigParser(); 53 | 54 | if (vendorId != NULL) { 55 | const std::string vendorIdStr = vendorId; 56 | cfg->set("vendorId", vendorIdStr); 57 | } 58 | 59 | if (productId != NULL) { 60 | const std::string productIdStr = productId; 61 | cfg->set("productId", productIdStr); 62 | } 63 | 64 | cfg->set("DeviceProxy", "DeviceProxy_LibUSB"); 65 | cfg->set("HostProxy", "HostProxy_GadgetFS"); 66 | cfg->set("DeviceProxy::nice", "50"); 67 | cfg->add_to_vector("Plugins", "PacketFilter_ZeroMQ"); 68 | 69 | (*frontend).bind("tcp://127.0.0.1:9999"); 70 | (*backend).bind("tcp://127.0.0.1:5678"); 71 | std::thread zmq_proxy = std::thread(run_proxy, std::ref(frontend), std::ref(backend)); 72 | 73 | int status; 74 | do { 75 | manager=new Manager(cfg); 76 | manager->load_plugins(cfg); 77 | cfg->print_config(); 78 | 79 | manager->start_control_relaying(); 80 | while ( ( status = manager->get_status()) == USBM_RELAYING) { 81 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 82 | } 83 | 84 | manager->stop_relaying(); 85 | manager->cleanup(); 86 | } while (!done && status == USBM_RESET); 87 | 88 | frontend->close(); 89 | backend->close(); 90 | zmq_proxy.join(); 91 | ctx->close(); 92 | delete(frontend); 93 | delete(backend); 94 | delete(manager); 95 | delete(ctx); 96 | 97 | return -1; 98 | } -------------------------------------------------------------------------------- /docker-crosstool-ng-arm/docker/toolchain.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:14.04.2 as crosstool-ng_install 2 | LABEL org.opencontainers.image.source https://github.com/nesto-software/USBProxy 3 | 4 | # from: https://github.com/amclain/docker-crosstool-ng/blob/master/Dockerfile 5 | # and: https://crosstool-ng.github.io/docs/install/ 6 | 7 | ENV CROSSTOOL crosstool-ng-1.24.0 8 | 9 | # Install system packages 10 | RUN apt-get -qq update 11 | RUN apt-get -y dist-upgrade 12 | RUN apt-get -y install wget curl 13 | RUN apt-get -y install git 14 | RUN apt-get -y install build-essential 15 | RUN apt-get -y install automake 16 | RUN apt-get -y install libtool 17 | RUN apt-get -y install gawk 18 | RUN apt-get -y install bison 19 | RUN apt-get -y install flex 20 | RUN apt-get -y install texinfo 21 | RUN apt-get -y install gperf 22 | RUN apt-get -y install libncurses5-dev 23 | RUN apt-get -y install libexpat1-dev 24 | RUN apt-get -y install subversion 25 | RUN apt-get -y install unzip 26 | RUN apt-get -y install help2man 27 | 28 | WORKDIR /opt 29 | 30 | # Install crosstool-ng 31 | RUN curl -s http://crosstool-ng.org/download/crosstool-ng/${CROSSTOOL}.tar.bz2 | tar -xj 32 | 33 | WORKDIR ${CROSSTOOL} 34 | RUN ./configure --prefix=/opt/crosstool-ng 35 | RUN make 36 | RUN make install 37 | ENV PATH="${PATH}:/opt/crosstool-ng/bin" 38 | 39 | WORKDIR / 40 | 41 | FROM crosstool-ng_install AS crosstool-ng_build-toolchain 42 | 43 | # choose correct triplet 44 | # see: https://wiki.osdev.org/Target_Triplet 45 | # raspberry arm versions (see: https://wiki.debian.org/RaspberryPi and https://www.raspbian.org/RaspbianFAQ "What compilation options should be set Raspbian code?") 46 | # - armhf for rev. 2 47 | # 48 | # cross compilers: 49 | # armhf: arm-linux-gnueabihf 50 | # we use the config from following snippet to create our own toolchain: 51 | # https://raw.githubusercontent.com/rvagg/rpi-newer-crosstools/master/x64-gcc-4.9.4-binutils-2.28.config 52 | ENV TOOLCHAIN arm-rpi-linux-gnueabihf 53 | 54 | WORKDIR /opt/crosstool-ng 55 | 56 | # Build ARM toolchain 57 | COPY ./docker-crosstool-ng-arm/config/arm.config .config 58 | 59 | # apply download server fix from https://github.com/pfalcon/esp-open-sdk/issues/306 60 | COPY "./docker-crosstool-ng-arm/fixes/140-mpc.sh" "/opt/crosstool-ng/lib/ct-ng.1.20.0/scripts/build/companion_libs/140-mpc.sh" 61 | 62 | # note: the following is needed because I copy-pasted the crosstool-ng config and updated the crosstool-ng version afterwards 63 | RUN ct-ng upgradeconfig 64 | 65 | # see: https://github.com/crosstool-ng/crosstool-ng/issues/1454#issuecomment-774962457 66 | RUN ct-ng source CT_ALLOW_BUILD_AS_ROOT_SURE=true 67 | 68 | # build the toolchain 69 | RUN ct-ng build CT_ALLOW_BUILD_AS_ROOT_SURE=true 70 | 71 | # add the toolchain to the path 72 | ENV PATH="${PATH}:/opt/crosstool-ng/x-tools/${TOOLCHAIN}/bin" 73 | 74 | WORKDIR / -------------------------------------------------------------------------------- /src/lib/Manager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_MANAGER_H 6 | #define USBPROXY_MANAGER_H 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "Packet.h" 14 | 15 | class PluginManager; 16 | class ConfigParser; 17 | 18 | class Injector; 19 | class RelayReader; 20 | class RelayWriter; 21 | 22 | class Device; 23 | class Endpoint; 24 | 25 | class DeviceProxy; 26 | class HostProxy; 27 | class PacketFilter; 28 | 29 | #define ALL_ENDPOINTS 0 30 | #define ALL_ENDPOINTS_EXCEPT_EP0 1 31 | 32 | enum Manager_status { 33 | USBM_IDLE=0, 34 | USBM_SETUP=1, 35 | USBM_RELAYING=2, 36 | USBM_STOPPING=3, 37 | USBM_SETUP_ABORT=4, 38 | USBM_RESET=5 39 | }; 40 | 41 | class Manager { 42 | private: 43 | Manager_status status; 44 | DeviceProxy* deviceProxy; 45 | HostProxy* hostProxy; 46 | PluginManager *plugin_manager; 47 | Device* device; 48 | 49 | PacketFilter** filters; 50 | __u8 filterCount; 51 | 52 | Injector** injectors; 53 | __u8 injectorCount; 54 | 55 | std::vector injectorThreads; 56 | 57 | Endpoint* in_endpoints[16]; 58 | PacketQueue* in_queues[16]; 59 | RelayReader* in_readers[16]; 60 | RelayWriter* in_writers[16]; 61 | std::thread in_readerThreads[16]; 62 | std::thread in_writerThreads[16]; 63 | 64 | Endpoint* out_endpoints[16]; 65 | PacketQueue* out_queues[16]; 66 | RelayReader* out_readers[16]; 67 | RelayWriter* out_writers[16]; 68 | std::thread out_readerThreads[16]; 69 | std::thread out_writerThreads[16]; 70 | PacketQueue _readersend; 71 | PacketQueue _writersend; 72 | 73 | void start_data_relaying(); 74 | unsigned _debug_level; 75 | 76 | ConfigParser *cfg_; 77 | uint8_t configurationNumber; 78 | 79 | public: 80 | Manager(ConfigParser *); 81 | virtual ~Manager(); 82 | 83 | void load_plugins(ConfigParser *cfg); 84 | 85 | void add_injector(Injector* _injector); 86 | void remove_injector(__u8 index,bool freeMemory=true); 87 | Injector* get_injector(__u8 index); 88 | __u8 get_injector_count(); 89 | 90 | void add_filter(PacketFilter* _filter); 91 | void remove_filter(__u8 index,bool freeMemory=true); 92 | PacketFilter* get_filter(__u8 index); 93 | __u8 get_filter_count(); 94 | 95 | void setConfig(__u8 index); 96 | 97 | enum Manager_status get_status() {return status;} 98 | void stopEps(unsigned start); 99 | 100 | // modified 20140924 atsumi@aizulab.com 101 | void set_status( Manager_status status_) { status = status_;} 102 | 103 | void start_control_relaying(); 104 | void stop_relaying(); 105 | void cleanup(); 106 | void hostDisconnectNotification(); 107 | void hostConnectNotification(); 108 | void deviceDisconnectNotification(); 109 | void setDeviceProxyNice(unsigned nice); 110 | }; 111 | 112 | #endif /* USBPROXY_MANAGER_H */ 113 | -------------------------------------------------------------------------------- /src/lib/Endpoint.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "DeviceProxy.h" 9 | #include "HexString.h" 10 | 11 | #include "Endpoint.h" 12 | #include "Interface.h" 13 | 14 | Endpoint::Endpoint(Interface* _interface,const __u8* p) { 15 | interface=_interface; 16 | memcpy(&descriptor,p,7); 17 | } 18 | 19 | Endpoint::Endpoint(Interface* _interface,const usb_endpoint_descriptor* _descriptor) { 20 | interface=_interface; 21 | descriptor=*_descriptor; 22 | } 23 | 24 | Endpoint::Endpoint(Interface* _interface,__u8 bEndpointAddress,__u8 bmAttributes,__u16 wMaxPacketSize,__u8 bInterval) { 25 | interface=_interface; 26 | descriptor.bLength=7; 27 | descriptor.bDescriptorType=USB_DT_ENDPOINT; 28 | descriptor.bEndpointAddress=bEndpointAddress; 29 | descriptor.bmAttributes=bmAttributes; 30 | descriptor.wMaxPacketSize=wMaxPacketSize; 31 | descriptor.bInterval=bInterval; 32 | } 33 | 34 | Endpoint::~Endpoint() { 35 | } 36 | 37 | const usb_endpoint_descriptor* Endpoint::get_descriptor() { 38 | return &descriptor; 39 | } 40 | 41 | size_t Endpoint::get_full_descriptor_length() { 42 | return descriptor.bLength; 43 | } 44 | 45 | void Endpoint::get_full_descriptor(__u8** p) { 46 | memcpy(*p,&descriptor,descriptor.bLength); 47 | *p=*p+descriptor.bLength; 48 | } 49 | 50 | void Endpoint::print(__u8 tabs) { 51 | char* hex=hex_string(&descriptor,descriptor.bLength); 52 | printf("%.*sEP(%02x): %s\n",tabs,TABPADDING,descriptor.bEndpointAddress,hex); 53 | free(hex); 54 | } 55 | 56 | const definition_error Endpoint::is_defined(__u8 configId,__u8 interfaceNum,__u8 interfaceAlternate) { 57 | if (descriptor.bLength!=7) {return definition_error(DE_ERR_INVALID_DESCRIPTOR,0x01, DE_OBJ_ENDPOINT,configId,interfaceNum,interfaceAlternate,descriptor.bEndpointAddress);} 58 | if (descriptor.bDescriptorType!=USB_DT_ENDPOINT) {return definition_error(DE_ERR_INVALID_DESCRIPTOR,0x02, DE_OBJ_ENDPOINT,configId,interfaceNum,interfaceAlternate,descriptor.bEndpointAddress);} 59 | if (descriptor.bEndpointAddress&0x70) {return definition_error(DE_ERR_INVALID_DESCRIPTOR,0x03, DE_OBJ_ENDPOINT,configId,interfaceNum,interfaceAlternate,descriptor.bEndpointAddress);} 60 | if ( (descriptor.bmAttributes&0xC0) || 61 | (((descriptor.bmAttributes&0x03)!=1) && (descriptor.bmAttributes&0xFC)) 62 | ) {return definition_error(DE_ERR_INVALID_DESCRIPTOR,0x04, DE_OBJ_ENDPOINT,configId,interfaceNum,interfaceAlternate,descriptor.bEndpointAddress);} 63 | //__u8 wMaxPacketSize 64 | if ( 65 | (((descriptor.bmAttributes&0x03)==1) && descriptor.bInterval!=1) || 66 | (((descriptor.bmAttributes&0x03)==3) && descriptor.bInterval==1) 67 | ) {return definition_error(DE_ERR_INVALID_DESCRIPTOR,0x05, DE_OBJ_ENDPOINT,configId,interfaceNum,interfaceAlternate,descriptor.bEndpointAddress);} 68 | return definition_error(); 69 | } 70 | 71 | Interface* Endpoint::get_interface() {return interface;} 72 | -------------------------------------------------------------------------------- /src/lib/Injector.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "get_tid.h" 9 | #include "TRACE.h" 10 | 11 | #include "Injector.h" 12 | 13 | #define SLEEP_US 1000 14 | 15 | Injector::Injector() 16 | : outPollIndex{}, 17 | inPollIndex{}, 18 | _please_stop(false), 19 | outQueues{}, 20 | inQueues{} 21 | {} 22 | 23 | void Injector::set_queue(__u8 epAddress, PacketQueue& queue) { 24 | if (epAddress&0x80) { 25 | inQueues[epAddress&0x0f] = &queue; 26 | } else { 27 | outQueues[epAddress&0x0f] = &queue; 28 | } 29 | } 30 | 31 | void Injector::listen() { 32 | bool idle; 33 | fprintf(stderr,"Starting injector thread (%ld) for [%s].\n",gettid(),this->toString()); 34 | start_injector(); 35 | Packet* packet; 36 | SetupPacket* setup; 37 | int* fdlist=get_pollable_fds(); 38 | int pollreadcount=0; 39 | int i=0; 40 | while(fdlist[i++]) {pollreadcount++;} 41 | struct pollfd* poll_list=(struct pollfd*)calloc(pollreadcount,sizeof(pollfd)); 42 | for (i=0;ienqueuePriority queues 59 | if (poll_list[i].revents & POLLIN) { 60 | get_packets(&packet,&setup,500); 61 | if (setup) { 62 | PacketQueue* queue=outQueues[0]; 63 | if (queue) { 64 | fprintf(stderr,"Injector send setup on %d\n",i); 65 | //queue->enqueue(setup); 66 | queue->enqueuePriority(std::make_shared(*setup)); 67 | setup->data = nullptr; 68 | delete setup; 69 | idle=false; 70 | } else { 71 | full_pipe(setup); 72 | idle=false; 73 | } 74 | setup=nullptr; 75 | } else if (packet) { 76 | __u8 epAddress=packet->bEndpoint; 77 | PacketQueue* queue =(epAddress&0x80)?inQueues[epAddress&0x0f]:outQueues[epAddress&0x0f]; 78 | if (queue) { //if queue defined for this EP, attempt to send 79 | //queue->enqueue(packet); 80 | queue->enqueuePriority(std::make_shared(*packet)); 81 | 82 | packet->data = nullptr; 83 | delete packet; 84 | } else { //kick packet back to injector 85 | full_pipe(packet); 86 | } 87 | packet = nullptr; 88 | idle=false; 89 | } 90 | } 91 | } 92 | } 93 | if (idle) sched_yield(); 94 | } 95 | free(poll_list); 96 | stop_injector(); 97 | fprintf(stderr,"Finished injector thread (%ld) for [%s].\n",gettid(),this->toString()); 98 | _please_stop = false; 99 | } 100 | -------------------------------------------------------------------------------- /docker-crosstool-ng-arm/fixes/140-mpc.sh: -------------------------------------------------------------------------------- 1 | # This file adds the functions to build the MPC library 2 | # Copyright 2009 Yann E. MORIN 3 | # Licensed under the GPL v2. See COPYING in the root of this package 4 | 5 | do_mpc_get() { :; } 6 | do_mpc_extract() { :; } 7 | do_mpc_for_build() { :; } 8 | do_mpc_for_host() { :; } 9 | 10 | # Overide functions depending on configuration 11 | if [ "${CT_MPC}" = "y" ]; then 12 | 13 | # Download MPC 14 | do_mpc_get() { 15 | CT_GetFile "mpc-${CT_MPC_VERSION}" .tar.gz \ 16 | https://ftp.gnu.org/gnu/mpc 17 | } 18 | 19 | # Extract MPC 20 | do_mpc_extract() { 21 | CT_Extract "mpc-${CT_MPC_VERSION}" 22 | CT_Patch "mpc" "${CT_MPC_VERSION}" 23 | } 24 | 25 | # Build MPC for running on build 26 | # - always build statically 27 | # - we do not have build-specific CFLAGS 28 | # - install in build-tools prefix 29 | do_mpc_for_build() { 30 | local -a mpc_opts 31 | 32 | case "${CT_TOOLCHAIN_TYPE}" in 33 | native|cross) return 0;; 34 | esac 35 | 36 | CT_DoStep INFO "Installing MPC for build" 37 | CT_mkdir_pushd "${CT_BUILD_DIR}/build-mpc-build-${CT_BUILD}" 38 | 39 | mpc_opts+=( "host=${CT_BUILD}" ) 40 | mpc_opts+=( "prefix=${CT_BUILDTOOLS_PREFIX_DIR}" ) 41 | mpc_opts+=( "cflags=${CT_CFLAGS_FOR_BUILD}" ) 42 | mpc_opts+=( "ldflags=${CT_LDFLAGS_FOR_BUILD}" ) 43 | do_mpc_backend "${mpc_opts[@]}" 44 | 45 | CT_Popd 46 | CT_EndStep 47 | } 48 | 49 | # Build MPC for running on host 50 | do_mpc_for_host() { 51 | local -a mpc_opts 52 | 53 | CT_DoStep INFO "Installing MPC for host" 54 | CT_mkdir_pushd "${CT_BUILD_DIR}/build-mpc-host-${CT_HOST}" 55 | 56 | mpc_opts+=( "host=${CT_HOST}" ) 57 | mpc_opts+=( "prefix=${CT_HOST_COMPLIBS_DIR}" ) 58 | mpc_opts+=( "cflags=${CT_CFLAGS_FOR_HOST}" ) 59 | mpc_opts+=( "ldflags=${CT_LDFLAGS_FOR_HOST}" ) 60 | do_mpc_backend "${mpc_opts[@]}" 61 | 62 | CT_Popd 63 | CT_EndStep 64 | } 65 | 66 | # Build MPC 67 | # Parameter : description : type : default 68 | # host : machine to run on : tuple : (none) 69 | # prefix : prefix to install into : dir : (none) 70 | # cflags : cflags to use : string : (empty) 71 | # ldflags : ldflags to use : string : (empty) 72 | do_mpc_backend() { 73 | local host 74 | local prefix 75 | local cflags 76 | local ldflags 77 | local arg 78 | 79 | for arg in "$@"; do 80 | eval "${arg// /\\ }" 81 | done 82 | 83 | CT_DoLog EXTRA "Configuring MPC" 84 | 85 | CT_DoExecLog CFG \ 86 | CFLAGS="${cflags}" \ 87 | LDFLAGS="${ldflags}" \ 88 | "${CT_SRC_DIR}/mpc-${CT_MPC_VERSION}/configure" \ 89 | --build=${CT_BUILD} \ 90 | --host=${host} \ 91 | --prefix="${prefix}" \ 92 | --with-gmp="${prefix}" \ 93 | --with-mpfr="${prefix}" \ 94 | --disable-shared \ 95 | --enable-static 96 | 97 | CT_DoLog EXTRA "Building MPC" 98 | CT_DoExecLog ALL make ${JOBSFLAGS} 99 | 100 | if [ "${CT_COMPLIBS_CHECK}" = "y" ]; then 101 | CT_DoLog EXTRA "Checking MPC" 102 | CT_DoExecLog ALL make ${JOBSFLAGS} -s check 103 | fi 104 | 105 | CT_DoLog EXTRA "Installing MPC" 106 | CT_DoExecLog ALL make install 107 | } 108 | 109 | fi # CT_MPC -------------------------------------------------------------------------------- /src/Plugins/Injectors/Injector_UDP.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "errno.h" 10 | #include "netinet/in.h" 11 | 12 | #include "Injector_UDP.h" 13 | #include "Packet.h" 14 | #include "HexString.h" 15 | 16 | Injector_UDP::Injector_UDP(ConfigParser *cfg) { 17 | std::string port_str = cfg->get("Injector_UDP::Port"); 18 | if(port_str == "") { 19 | fprintf(stderr, "Error: no port found for Injector_UDP\n"); 20 | return; 21 | } 22 | else 23 | port = std::stoi(port_str, nullptr, 10); 24 | 25 | sck=0; 26 | buf=NULL; 27 | spoll.events=POLLIN; 28 | } 29 | 30 | Injector_UDP::~Injector_UDP() { 31 | if (sck) {close(sck);sck=0;} 32 | if (buf) {free(buf);buf=NULL;} 33 | } 34 | 35 | void Injector_UDP::start_injector() { 36 | fprintf(stderr,"Opening injection UDP socket on port %d.\n",port); 37 | sck=socket(AF_INET,SOCK_DGRAM | SOCK_CLOEXEC,IPPROTO_UDP); 38 | spoll.fd=sck; 39 | if (sck<0) { 40 | fprintf(stderr,"Error creating socket.\n"); 41 | sck=0; 42 | } 43 | struct sockaddr_in addr; 44 | memset((char *)&addr,0,sizeof(addr)); 45 | addr.sin_family=AF_INET; 46 | addr.sin_addr.s_addr=htonl(INADDR_ANY); 47 | addr.sin_port=htons(port); 48 | if (bind(sck,(struct sockaddr*)&addr,sizeof(addr))<0) { 49 | fprintf(stderr,"Error binding to port %d.\n",port); 50 | sck=0; 51 | } 52 | //sized to handle ETHERNET less IP(20 byte)/UDP(8 byte) headers 53 | buf=(__u8*)malloc(UDP_BUFFER_SIZE); 54 | } 55 | 56 | int* Injector_UDP::get_pollable_fds() { 57 | int* tmp=(int*)calloc(2,sizeof(int)); 58 | tmp[0]=sck; 59 | return tmp; 60 | } 61 | 62 | void Injector_UDP::stop_injector() { 63 | if (sck) {close(sck);sck=0;} 64 | if (buf) {free(buf);buf=NULL;} 65 | } 66 | void Injector_UDP::get_packets(Packet** packet,SetupPacket** setup,int timeout) { 67 | *packet=NULL; 68 | *setup=NULL; 69 | 70 | if (!poll(&spoll, 1, timeout) || !(spoll.revents&POLLIN)) { 71 | return; 72 | } 73 | 74 | ssize_t len=recv(sck,buf,UDP_BUFFER_SIZE,0); 75 | if (len>0) { 76 | if (buf[0]) { 77 | __u16 usblen=buf[2]<<8 | buf[3]; 78 | __u8* usbbuf=(__u8*)malloc(usblen); 79 | memcpy(usbbuf,buf+4,usblen); 80 | *packet=new Packet(buf[0],usbbuf,usblen,buf[1]&0x01?false:true); 81 | (*packet)->transmit=buf[1]&0x02?false:true; 82 | return; 83 | } else { 84 | struct usb_ctrlrequest ctrl_req; 85 | memcpy(&ctrl_req,buf+3,8); 86 | if (ctrl_req.bRequestType&0x80) { 87 | *setup=new SetupPacket(ctrl_req,NULL,true); 88 | } else { 89 | __u8* usbbuf=(__u8*)malloc(ctrl_req.wLength); 90 | memcpy(usbbuf,buf+11,ctrl_req.wLength); 91 | *setup=new SetupPacket(ctrl_req,usbbuf,true); 92 | } 93 | (*setup)->filter_out = (buf[1] & 0x01) == 0x01 ? false : true; 94 | (*setup)->transmit_out = (buf[1] & 0x02) == 0x02 ? false : true; 95 | (*setup)->filter_in = (buf[1] & 0x04) == 0x04 ? false : true; 96 | (*setup)->transmit_in = (buf[1] & 0x08) == 0x08 ? false : true; 97 | return; 98 | } 99 | } 100 | if (len<0) { 101 | fprintf(stderr,"Socket read error [%s].\n",strerror(errno)); 102 | } 103 | return; 104 | } 105 | 106 | void Injector_UDP::full_pipe(Packet* p) {fprintf(stderr,"Packet returned due to full pipe & buffer\n");} 107 | 108 | static Injector_UDP *injector; 109 | 110 | extern "C" { 111 | int plugin_type = PLUGIN_INJECTOR; 112 | 113 | Injector * get_plugin(ConfigParser *cfg) { 114 | injector = new Injector_UDP(cfg); 115 | return (Injector *) injector; 116 | } 117 | 118 | void destroy_plugin() { 119 | delete injector; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/lib/USBString.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include "USBString.h" 11 | #include "DeviceProxy.h" 12 | 13 | USBString::USBString(DeviceProxy* proxy,__u8 _index,__u16 _languageId) { 14 | index=_index; 15 | languageId=_languageId; 16 | descriptor=(usb_string_descriptor *)malloc(8); 17 | usb_ctrlrequest setup_packet; 18 | setup_packet.bRequestType=USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; 19 | setup_packet.bRequest=USB_REQ_GET_DESCRIPTOR; 20 | setup_packet.wValue=USB_DT_STRING<<8|index; 21 | setup_packet.wIndex=languageId; 22 | setup_packet.wLength=8; 23 | int len=0; 24 | if (proxy->control_request(&setup_packet,&len,(__u8*)descriptor) < 0) { 25 | std::cerr << "Error sending control request!\n"; 26 | exit(1); 27 | } 28 | len=descriptor->bLength; 29 | descriptor=(usb_string_descriptor*)realloc(descriptor,len); 30 | if (len>8) { 31 | setup_packet.wLength=len; 32 | if (proxy->control_request(&setup_packet,&len,(__u8*)descriptor) < 0) { 33 | std::cerr << "Error sending control request!\n"; 34 | exit(1); 35 | } 36 | } 37 | } 38 | 39 | //create from descriptor 40 | USBString::USBString(const usb_string_descriptor* _descriptor,__u8 _index,__u16 _languageId) { 41 | int len=_descriptor->bLength; 42 | index=_index; 43 | languageId=_languageId; 44 | descriptor=(usb_string_descriptor *)malloc(len); 45 | memcpy(descriptor,_descriptor,len); 46 | } 47 | //create from ascii string 48 | USBString::USBString(const char* value,__u8 _index,__u16 _languageId) { 49 | int len=strlen(value); 50 | index=_index; 51 | languageId=_languageId; 52 | descriptor=(usb_string_descriptor *)calloc(len+1,2); 53 | descriptor->bLength=((len+1)<<1); 54 | descriptor->bDescriptorType=3; 55 | int i; 56 | for(i=0;iwData[i]=value[i]; 58 | } 59 | } 60 | 61 | //create from unicode-LE16 string 62 | USBString::USBString(const __u16* value,__u8 _index,__u16 _languageId) { 63 | index=_index; 64 | languageId=_languageId; 65 | const __u16* p=value; 66 | int len=0; 67 | while (*p++) {len++;} 68 | descriptor=(usb_string_descriptor *)calloc(len+1,2); 69 | descriptor->bLength=((len+1)<<1); 70 | descriptor->bDescriptorType=3; 71 | p=value; 72 | int i; 73 | for(i=0;iwData[i]=value[i]; 75 | } 76 | } 77 | 78 | USBString::~USBString() { 79 | if (descriptor) { 80 | free(descriptor); 81 | descriptor=NULL; 82 | } 83 | } 84 | 85 | char * USBString::get_ascii() { 86 | __u8 strlen=get_char_count(); 87 | char* buf=(char*)malloc(strlen+1); 88 | 89 | int len=((descriptor->bLength)>>1)-1; 90 | int i_uni; 91 | int i_asc; 92 | for (i_uni=0,i_asc=0;i_uniwData[i_uni]&0xff00) { 94 | buf[i_asc++]='?'; 95 | } else { 96 | buf[i_asc++]=descriptor->wData[i_uni]&0xff; 97 | } 98 | } 99 | buf[i_asc]=0; 100 | return buf; 101 | } 102 | 103 | const usb_string_descriptor* USBString::get_descriptor() {return descriptor;} 104 | 105 | __u16 USBString::get_languageId() {return languageId;} 106 | 107 | __u8 USBString::get_index() {return index;} 108 | 109 | __u8 USBString::get_char_count() {return ((descriptor->bLength)>>1)-1;} 110 | 111 | void USBString::append_char(__u16 u) { 112 | if (index!=0 || languageId!=0) {fprintf(stderr,"append_char() may only be called on the zero USBString.\n");return;} 113 | int len=(descriptor->bLength)+2; 114 | descriptor=(usb_string_descriptor*)realloc(descriptor,len); 115 | descriptor->bLength=len; 116 | descriptor->wData[(len>>1)-2]=u; 117 | } 118 | -------------------------------------------------------------------------------- /src/lib/InterfaceGroup.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "TRACE.h" 9 | #include "HexString.h" 10 | 11 | #include "InterfaceGroup.h" 12 | 13 | #include "Device.h" 14 | #include "Interface.h" 15 | 16 | InterfaceGroup::InterfaceGroup(__u8 _number) { 17 | number=_number; 18 | alternateCount=0; 19 | activeAlternateIndex=-1; 20 | interfaces=NULL; 21 | } 22 | InterfaceGroup::~InterfaceGroup() { 23 | if (interfaces) { 24 | int i; 25 | for(i=0;iget_full_descriptor_length(); 43 | } 44 | } 45 | return total; 46 | } 47 | 48 | void InterfaceGroup::get_full_descriptor(__u8** p) { 49 | int i; 50 | 51 | for(i=0;iget_full_descriptor(p); 55 | } 56 | } 57 | } 58 | 59 | void InterfaceGroup::add_interface(Interface* interface) { 60 | __u8 alternate=interface->get_descriptor()->bAlternateSetting; 61 | if (alternate>=alternateCount) { 62 | Interface** newInterfaces=(Interface **)calloc(alternate+1,sizeof(*interfaces)); 63 | if (alternateCount) { 64 | memcpy(newInterfaces,interfaces,sizeof(*interfaces)*alternateCount); 65 | free(interfaces); 66 | /* not needed interaces=NULL; */ 67 | } 68 | interfaces=newInterfaces; 69 | alternateCount=alternate+1; 70 | } else { 71 | if (interfaces[alternate]) {delete(interfaces[alternate]);/* not needed interfaces[alternate]=NULL;*/} 72 | } 73 | interfaces[alternate]=interface; 74 | } 75 | 76 | Interface* InterfaceGroup::get_interface(__u8 alternate) { 77 | if (alternate>=alternateCount || alternate<0) {return NULL;} 78 | return interfaces[alternate]; 79 | } 80 | 81 | void InterfaceGroup::print(__u8 tabs) { 82 | int i; 83 | printf("%.*sInterface(%d):\n",tabs,TABPADDING,number); 84 | for(i=0;iprint(tabs+1,i==activeAlternateIndex?true:false); 88 | } 89 | } 90 | } 91 | 92 | __u8 InterfaceGroup::get_number() { 93 | return number; 94 | } 95 | 96 | __u8 InterfaceGroup::get_alternate_count() { 97 | return alternateCount; 98 | } 99 | 100 | Interface* InterfaceGroup::get_active_interface() { 101 | if (activeAlternateIndex<0) {return NULL;} 102 | return get_interface(activeAlternateIndex); 103 | } 104 | 105 | const definition_error InterfaceGroup::is_defined(__u8 configId) { 106 | if (!alternateCount) {return definition_error(DE_ERR_NULL_OBJECT,0x0, DE_OBJ_INTERFACE,configId,number,0);} 107 | int i; 108 | for(i=0;iget_descriptor()->bInterfaceNumber!=number) {return definition_error(DE_ERR_MISPLACED_IF_NUM,interfaces[i]->get_descriptor()->bAlternateSetting, DE_OBJ_INTERFACE,configId,number,i);} 111 | if (interfaces[i]->get_descriptor()->bAlternateSetting!=i) {return definition_error(DE_ERR_MISPLACED_OBJECT,interfaces[i]->get_descriptor()->bAlternateSetting, DE_OBJ_INTERFACE,configId,number,i);} 112 | definition_error rc=interfaces[i]->is_defined(configId,number); 113 | if (rc.error) {return rc;} 114 | } 115 | return definition_error(); 116 | } 117 | -------------------------------------------------------------------------------- /src/lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of USBProxy. 3 | # 4 | 5 | project(libusbproxy C) 6 | set(PACKAGE libusbproxy) 7 | 8 | find_package(Threads REQUIRED) 9 | 10 | # Targets 11 | set(cpp_sources 12 | ${CMAKE_CURRENT_SOURCE_DIR}/ConfigParser.cpp 13 | ${CMAKE_CURRENT_SOURCE_DIR}/Criteria.cpp 14 | ${CMAKE_CURRENT_SOURCE_DIR}/DeviceQualifier.cpp 15 | ${CMAKE_CURRENT_SOURCE_DIR}/HexString.cpp 16 | ${CMAKE_CURRENT_SOURCE_DIR}/Interface.cpp 17 | ${CMAKE_CURRENT_SOURCE_DIR}/Manager.cpp 18 | ${CMAKE_CURRENT_SOURCE_DIR}/RelayReader.cpp 19 | ${CMAKE_CURRENT_SOURCE_DIR}/TCP_Helper.cpp 20 | ${CMAKE_CURRENT_SOURCE_DIR}/Configuration.cpp 21 | ${CMAKE_CURRENT_SOURCE_DIR}/Device.cpp 22 | ${CMAKE_CURRENT_SOURCE_DIR}/Endpoint.cpp 23 | ${CMAKE_CURRENT_SOURCE_DIR}/HID.cpp 24 | ${CMAKE_CURRENT_SOURCE_DIR}/InterfaceGroup.cpp 25 | ${CMAKE_CURRENT_SOURCE_DIR}/Injector.cpp 26 | ${CMAKE_CURRENT_SOURCE_DIR}/PacketFilter.cpp 27 | ${CMAKE_CURRENT_SOURCE_DIR}/PluginManager.cpp 28 | ${CMAKE_CURRENT_SOURCE_DIR}/RelayWriter.cpp 29 | ${CMAKE_CURRENT_SOURCE_DIR}/USBString.cpp 30 | CACHE INTERNAL "List of CPP sources") 31 | 32 | set(c_sources 33 | ${CMAKE_CURRENT_SOURCE_DIR}/FDInfo.c 34 | ${CMAKE_CURRENT_SOURCE_DIR}/get_tid.c 35 | CACHE INTERNAL "List of C sources") 36 | 37 | set(headers 38 | ${CMAKE_CURRENT_SOURCE_DIR}/ConfigParser.h 39 | ${CMAKE_CURRENT_SOURCE_DIR}/DefinitionErrors.h 40 | ${CMAKE_CURRENT_SOURCE_DIR}/DeviceQualifier.h 41 | ${CMAKE_CURRENT_SOURCE_DIR}/Injector.h 42 | ${CMAKE_CURRENT_SOURCE_DIR}/PacketFilter.h 43 | ${CMAKE_CURRENT_SOURCE_DIR}/PluginManager.h 44 | ${CMAKE_CURRENT_SOURCE_DIR}/TCP_Helper.h 45 | ${CMAKE_CURRENT_SOURCE_DIR}/Configuration.h 46 | ${CMAKE_CURRENT_SOURCE_DIR}/Device.h 47 | ${CMAKE_CURRENT_SOURCE_DIR}/Endpoint.h 48 | ${CMAKE_CURRENT_SOURCE_DIR}/HexString.h 49 | ${CMAKE_CURRENT_SOURCE_DIR}/Interface.h 50 | ${CMAKE_CURRENT_SOURCE_DIR}/Plugins.h 51 | ${CMAKE_CURRENT_SOURCE_DIR}/Criteria.h 52 | ${CMAKE_CURRENT_SOURCE_DIR}/DeviceProxy.h 53 | ${CMAKE_CURRENT_SOURCE_DIR}/get_tid.h 54 | ${CMAKE_CURRENT_SOURCE_DIR}/HostProxy.h 55 | ${CMAKE_CURRENT_SOURCE_DIR}/Manager.h 56 | ${CMAKE_CURRENT_SOURCE_DIR}/Packet.h 57 | ${CMAKE_CURRENT_SOURCE_DIR}/Proxy.h 58 | ${CMAKE_CURRENT_SOURCE_DIR}/USBString.h 59 | CACHE INTERNAL "List of headers") 60 | 61 | add_definitions( -DPLUGIN_PATH="${CMAKE_INSTALL_PREFIX}/lib/USBProxy/") 62 | 63 | # Dynamic library 64 | add_library(USBProxy SHARED ${cpp_sources} ${c_sources}) 65 | 66 | set_source_files_properties(${cpp_sources} PROPERTIES COMPILE_FLAGS "${CMAKE_CPP_FLAGS} -fexceptions") 67 | 68 | set_target_properties(USBProxy PROPERTIES VERSION ${MAJOR_VERSION}.${MINOR_VERSION} SOVERSION 0) 69 | 70 | target_link_libraries(USBProxy ${LIBUSBPROXY_LIBS} ${CMAKE_DL_LIBS} 71 | ${CMAKE_THREAD_LIBS_INIT} rt) 72 | 73 | install(TARGETS USBProxy 74 | LIBRARY DESTINATION lib${LIB_SUFFIX} 75 | COMPONENT sharedlibs 76 | ) 77 | install(FILES ${headers} 78 | DESTINATION include/USBProxy 79 | COMPONENT headers 80 | ) 81 | 82 | ######################################################################## 83 | # Create Pkg Config File (experimental) 84 | ######################################################################## 85 | FOREACH(inc ${LIBUSB_INCLUDE_DIR}) 86 | LIST(APPEND USBPROXY_PC_CFLAGS "-I${inc}") 87 | ENDFOREACH(inc) 88 | 89 | # use space-separation format for the pc file 90 | STRING(REPLACE ";" " " USBPROXY_PC_CFLAGS "${USBPROXY_PC_CFLAGS}") 91 | STRING(REPLACE ";" " " USBPROXY_PC_LIBS "${USBPROXY_PC_LIBS}") 92 | 93 | # unset these vars to avoid hard-coded paths to cross environment 94 | IF(CMAKE_CROSSCOMPILING) 95 | UNSET(USBPROXY_PC_CFLAGS) 96 | UNSET(USBPROXY_PC_LIBS) 97 | ENDIF(CMAKE_CROSSCOMPILING) 98 | 99 | set(prefix ${CMAKE_INSTALL_PREFIX}) 100 | set(exec_prefix \${prefix}) 101 | set(libdir \${exec_prefix}/lib) 102 | set(includedir \${prefix}/include) 103 | 104 | CONFIGURE_FILE( 105 | ${CMAKE_CURRENT_SOURCE_DIR}/usbproxy.pc.in 106 | ${CMAKE_CURRENT_BINARY_DIR}/usbproxy.pc 107 | @ONLY) 108 | 109 | INSTALL( 110 | FILES ${CMAKE_CURRENT_BINARY_DIR}/usbproxy.pc 111 | DESTINATION lib/pkgconfig 112 | ) 113 | -------------------------------------------------------------------------------- /src/Plugins/Devices/DeviceProxy_Callback.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include "DeviceProxy_Callback.h" 6 | #include 7 | #include 8 | #include 9 | #include "Packet.h" 10 | #include "HexString.h" 11 | #include "TRACE.h" 12 | #include "USBString.h" 13 | 14 | // Find the right place to pull this in from 15 | #define cpu_to_le16(x) (x) 16 | 17 | #define BUF_LEN 100 18 | 19 | DeviceProxy_Callback::DeviceProxy_Callback(ConfigParser *cfg) 20 | : DeviceProxy(*cfg) 21 | { 22 | void *vf = cfg->get_pointer("DeviceProxy_Callback::connect"); 23 | connect_cb = *reinterpret_cast(&vf); 24 | vf = cfg->get_pointer("DeviceProxy_Callback::disconnect"); 25 | disconnect_cb = *reinterpret_cast(&vf); 26 | vf = cfg->get_pointer("DeviceProxy_Callback::reset"); 27 | reset_cb = *reinterpret_cast(&vf); 28 | vf = cfg->get_pointer("DeviceProxy_Callback::control_request"); 29 | control_request_cb = *reinterpret_cast(&vf); 30 | vf = cfg->get_pointer("DeviceProxy_Callback::send_data"); 31 | send_data_cb = *reinterpret_cast(&vf); 32 | vf = cfg->get_pointer("DeviceProxy_Callback::receive_data"); 33 | receive_data_cb = *reinterpret_cast(&vf); 34 | vf = cfg->get_pointer("DeviceProxy_Callback::toString"); 35 | toString_cb = *reinterpret_cast(&vf); 36 | p_is_connected = false; 37 | } 38 | 39 | DeviceProxy_Callback::~DeviceProxy_Callback() { 40 | disconnect(); 41 | } 42 | 43 | int DeviceProxy_Callback::connect(int timeout) { 44 | int rv = 0; 45 | if(connect_cb) 46 | rv = connect_cb(timeout); 47 | if(rv == 0) 48 | p_is_connected = true; 49 | // No connect method - assume always connected 50 | return rv; 51 | } 52 | 53 | void DeviceProxy_Callback::disconnect() { 54 | if(disconnect_cb) 55 | disconnect_cb(); 56 | } 57 | 58 | void DeviceProxy_Callback::reset() { 59 | if(reset_cb) 60 | reset_cb(); 61 | } 62 | 63 | bool DeviceProxy_Callback::is_connected() { 64 | return p_is_connected; 65 | } 66 | 67 | bool DeviceProxy_Callback::is_highspeed() { 68 | return false; 69 | } 70 | 71 | int DeviceProxy_Callback::control_request(const usb_ctrlrequest* setup_packet, int* nbytes, __u8* dataptr, int timeout) { 72 | int rv = -1; 73 | if(control_request_cb) { 74 | rv = control_request_cb(setup_packet, nbytes, dataptr, timeout); 75 | int i; 76 | for(i=0; i<*nbytes; i++) { 77 | fprintf(stderr, "%02x ", (dataptr)[i]); 78 | } 79 | fprintf(stderr, "\n"); 80 | } 81 | return rv; 82 | } 83 | 84 | void DeviceProxy_Callback::send_data(__u8 endpoint,__u8 attributes, __u16 maxPacketSize, __u8* dataptr, int length) { 85 | if(send_data_cb) 86 | send_data_cb(endpoint, attributes, maxPacketSize, dataptr, length); 87 | } 88 | 89 | void DeviceProxy_Callback::receive_data(__u8 endpoint,__u8 attributes, __u16 maxPacketSize, __u8** dataptr, int* length, int timeout) { 90 | if(receive_data_cb) { 91 | *dataptr = (__u8*) malloc(maxPacketSize); 92 | receive_data_cb(endpoint, attributes, maxPacketSize, *dataptr, length, timeout); 93 | if(*length == 0) 94 | free(*dataptr); 95 | else { 96 | int i; 97 | for(i=0; i<*length; i++) { 98 | fprintf(stderr, "%02x ", (*dataptr)[i]); 99 | } 100 | fprintf(stderr, "\n"); 101 | } 102 | } 103 | 104 | } 105 | 106 | void DeviceProxy_Callback::setConfig(Configuration* fs_cfg, Configuration* hs_cfg, bool hs) { 107 | ; 108 | } 109 | 110 | void DeviceProxy_Callback::set_endpoint_interface(__u8 endpoint, __u8 interface) { 111 | 112 | } 113 | 114 | void DeviceProxy_Callback::claim_interface(__u8 interface) { 115 | ; 116 | } 117 | 118 | void DeviceProxy_Callback::release_interface(__u8 interface) { 119 | ; 120 | } 121 | 122 | __u8 DeviceProxy_Callback::get_address() { 123 | return 1; 124 | } 125 | 126 | char* DeviceProxy_Callback::toString() { 127 | if(toString_cb) 128 | return toString_cb(); 129 | else 130 | return (char *) "Callback device"; 131 | } 132 | 133 | static DeviceProxy_Callback *proxy; 134 | 135 | extern "C" { 136 | DeviceProxy * get_deviceproxy_plugin(ConfigParser *cfg) { 137 | proxy = new DeviceProxy_Callback(cfg); 138 | return (DeviceProxy *) proxy; 139 | } 140 | 141 | void destroy_plugin() { 142 | delete proxy; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/Plugins/Hosts/HostProxy_TCP.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "HexString.h" 9 | #include "TRACE.h" 10 | #include "HostProxy_TCP.h" 11 | 12 | #include "Configuration.h" 13 | #include "Interface.h" 14 | #include "Endpoint.h" 15 | 16 | HostProxy_TCP::HostProxy_TCP(const char* address) { 17 | network = new TCP_Helper(address); 18 | p_is_connected = false; 19 | } 20 | 21 | HostProxy_TCP::HostProxy_TCP(ConfigParser *cfg) 22 | : HostProxy(*cfg) 23 | { 24 | std::string address = cfg->get("HostProxy_TCP::TCPAddress"); 25 | network = new TCP_Helper(address.c_str()); 26 | if (network) 27 | network->debugLevel = debugLevel; 28 | p_is_connected = false; 29 | } 30 | 31 | HostProxy_TCP::~HostProxy_TCP() { 32 | if (network) { 33 | delete(network); 34 | network=NULL; 35 | } 36 | } 37 | 38 | int HostProxy_TCP::connect(Device* device,int timeout) { 39 | int rc=network->connect(timeout); 40 | p_is_connected=rc==0; 41 | return rc; 42 | } 43 | 44 | void HostProxy_TCP::disconnect() { 45 | p_is_connected = false; 46 | } 47 | 48 | void HostProxy_TCP::reset() { 49 | 50 | } 51 | 52 | bool HostProxy_TCP::is_connected() { 53 | return p_is_connected; 54 | } 55 | 56 | 57 | //return 0 in if there is no request, 1 otherwise 58 | int HostProxy_TCP::control_request(usb_ctrlrequest *setup_packet, int *nbytes, __u8** dataptr, int timeout) { 59 | int length=0; 60 | __u8* buf=NULL; 61 | network->receive_data(0,&buf,&length,timeout); 62 | if (!length) { 63 | setup_packet->bRequest=0; 64 | return 0; 65 | } 66 | 67 | memcpy(setup_packet,buf,8); 68 | if (!(setup_packet->bRequestType&0x80) && setup_packet->wLength) { 69 | *dataptr=(__u8*)malloc(length-8); 70 | memcpy(dataptr,buf+8,length-8); 71 | *nbytes=length-8; 72 | } else { 73 | *dataptr=NULL; 74 | *nbytes=0; 75 | } 76 | free(buf); 77 | 78 | if (debugLevel>1) { 79 | char* hex=hex_string((void*)setup_packet,sizeof(*setup_packet)); 80 | fprintf(stderr, "TCP< %s\n",hex); 81 | free(hex); 82 | } 83 | return 1; 84 | } 85 | 86 | void HostProxy_TCP::send_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8* dataptr,int length) { 87 | if (!endpoint) { 88 | __u8* buf=(__u8*)malloc(length+3); 89 | buf[0]=0; 90 | buf[1]=length>>8; 91 | buf[2]=length&0xff; 92 | memcpy(buf+3,dataptr,length); 93 | network->send_data(0,buf,length+3); 94 | free(buf); 95 | } else { 96 | network->send_data(endpoint,dataptr,length); 97 | } 98 | } 99 | 100 | bool HostProxy_TCP::send_wait_complete(__u8 endpoint,int timeout) { 101 | return true; 102 | } 103 | 104 | void HostProxy_TCP::receive_data(__u8 endpoint, __u8 attributes, __u16 maxPacketSize, __u8** dataptr, int* length, int timeout) { 105 | network->receive_data(endpoint,dataptr,length,timeout); 106 | } 107 | 108 | void HostProxy_TCP::control_ack() { 109 | __u8 val[]={0,0,0}; 110 | network->send_data(0,val,3); 111 | } 112 | 113 | void HostProxy_TCP::stall_ep(__u8 endpoint) { 114 | if (!endpoint) { 115 | __u8 val[]={1}; 116 | network->send_data(0,val,1); 117 | } 118 | //FINISH 119 | } 120 | 121 | void HostProxy_TCP::setConfig(Configuration* fs_cfg,Configuration* hs_cfg,bool hs) { 122 | fprintf(stderr,"TCPHP SetConfig\n"); 123 | int ifc_idx; 124 | __u8 ep_total=0; 125 | __u8 ifc_count=fs_cfg->get_descriptor()->bNumInterfaces; 126 | for (ifc_idx=0;ifc_idxget_interface(ifc_idx); 128 | ep_total+=ifc->get_endpoint_count(); 129 | } 130 | 131 | __u8* eps=(__u8*)malloc(ep_total); 132 | __u8 ep_total_idx=0; 133 | for (ifc_idx=0;ifc_idxget_interface(ifc_idx); 135 | __u8 ep_count=ifc->get_endpoint_count(); 136 | int ep_idx; 137 | for (ep_idx=0;ep_idxget_endpoint_by_idx(ep_idx)->get_descriptor(); 139 | eps[ep_total_idx++]=ep->bEndpointAddress; 140 | } 141 | } 142 | int rc=network->open_endpoints(eps,ep_total,250); 143 | while (rc>0) {rc=network->open_endpoints(eps,ep_total,250);putchar('.');fflush(stdout);} 144 | free(eps); 145 | } 146 | 147 | static HostProxy_TCP *proxy; 148 | 149 | extern "C" { 150 | HostProxy * get_hostproxy_plugin(ConfigParser *cfg) { 151 | proxy = new HostProxy_TCP(cfg); 152 | return (HostProxy *) proxy; 153 | } 154 | 155 | void destroy_plugin() { 156 | delete proxy; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/Plugins/Devices/DeviceProxy_TCP.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "TRACE.h" 9 | #include "HexString.h" 10 | #include "DeviceProxy_TCP.h" 11 | 12 | #include "Configuration.h" 13 | #include "Interface.h" 14 | #include "Endpoint.h" 15 | 16 | DeviceProxy_TCP::DeviceProxy_TCP(const char* address) { 17 | p_is_connected = false; 18 | } 19 | 20 | /* FIXME pull settings from config parser */ 21 | DeviceProxy_TCP::DeviceProxy_TCP(ConfigParser *cfg) 22 | : DeviceProxy(*cfg) 23 | { 24 | network = new TCP_Helper(NULL); 25 | if (network) 26 | network->debugLevel = debugLevel; 27 | p_is_connected = false; 28 | } 29 | 30 | DeviceProxy_TCP::~DeviceProxy_TCP() { 31 | if (network) { 32 | delete(network); 33 | network=NULL; 34 | } 35 | } 36 | 37 | /* Open a socket for EP0 - we don't know how many EPs we need yet */ 38 | int DeviceProxy_TCP::connect(int timeout) { 39 | int rc=network->connect(timeout); 40 | p_is_connected=rc==0; 41 | return rc; 42 | } 43 | 44 | void DeviceProxy_TCP::disconnect() { 45 | p_is_connected = false; 46 | } 47 | 48 | void DeviceProxy_TCP::reset() { 49 | //FINISH 50 | } 51 | 52 | bool DeviceProxy_TCP::is_connected() { 53 | return p_is_connected; 54 | } 55 | 56 | bool DeviceProxy_TCP::is_highspeed() { 57 | return false; 58 | } 59 | 60 | //return -1 to stall 61 | int DeviceProxy_TCP::control_request(const usb_ctrlrequest *setup_packet, int *nbytes, __u8 *dataptr, int timeout) { 62 | //FINISH 63 | if (debugLevel>1) { 64 | char* hex=hex_string((void*)setup_packet,sizeof(*setup_packet)); 65 | fprintf(stderr, "TCP> %s\n",hex); 66 | free(hex); 67 | } 68 | int length=8; 69 | length+=(setup_packet->bRequestType&0x80)?0:setup_packet->wLength; 70 | __u8* buf=(__u8*)malloc(length); 71 | memcpy(buf,setup_packet,8); 72 | if (!(setup_packet->bRequestType&0x80)) memcpy(buf+8,dataptr,setup_packet->wLength); 73 | network->send_data(0,buf,length); 74 | free(buf); 75 | buf=NULL; 76 | length=0; 77 | network->receive_data(0,&buf,&length,timeout); 78 | if (length==0 || buf[0]) {return -1;} 79 | __u16 usblen=buf[1]<<8 | buf[2]; 80 | *nbytes=(usblen>setup_packet->wLength)?setup_packet->wLength:usblen; 81 | if (debugLevel>1 && *nbytes) { 82 | char* hex=hex_string((void*)(buf+3),*nbytes); 83 | fprintf(stderr, "TCP> %s\n",hex); 84 | free(hex); 85 | } 86 | memcpy(dataptr,buf+3,*nbytes); 87 | free(buf); 88 | return 0; 89 | } 90 | 91 | void DeviceProxy_TCP::send_data(__u8 endpoint,__u8 attributes, __u16 maxPacketSize, __u8* dataptr, int length) { 92 | network->send_data(endpoint,dataptr,length); 93 | } 94 | 95 | void DeviceProxy_TCP::receive_data(__u8 endpoint,__u8 attributes, __u16 maxPacketSize, __u8** dataptr, int* length, int timeout) { 96 | network->receive_data(endpoint,dataptr,length,timeout); 97 | } 98 | 99 | void DeviceProxy_TCP::setConfig(Configuration* fs_cfg, Configuration* hs_cfg, bool hs) { 100 | fprintf(stderr,"TCPDP SetConfig\n"); 101 | int ifc_idx; 102 | __u8 ep_total=0; 103 | __u8 ifc_count=fs_cfg->get_descriptor()->bNumInterfaces; 104 | for (ifc_idx=0;ifc_idxget_interface(ifc_idx); 106 | ep_total+=ifc->get_endpoint_count(); 107 | } 108 | 109 | __u8* eps=(__u8*)malloc(ep_total); 110 | __u8 ep_total_idx=0; 111 | for (ifc_idx=0;ifc_idxget_interface(ifc_idx); 113 | __u8 ep_count=ifc->get_endpoint_count(); 114 | int ep_idx; 115 | for (ep_idx=0;ep_idxget_endpoint_by_idx(ep_idx)->get_descriptor(); 117 | eps[ep_total_idx++]=ep->bEndpointAddress; 118 | } 119 | } 120 | int rc=network->open_endpoints(eps,ep_total,250); 121 | TRACE1(rc) 122 | while (rc>0) {rc=network->open_endpoints(eps,ep_total,250);putchar('.');fflush(stdout);TRACE1(rc)} 123 | free(eps); 124 | } 125 | 126 | void DeviceProxy_TCP::set_endpoint_interface(__u8 endpoint, __u8 interface) { 127 | } 128 | 129 | void DeviceProxy_TCP::claim_interface(__u8 interface) {} 130 | 131 | void DeviceProxy_TCP::release_interface(__u8 interface) {} 132 | 133 | __u8 DeviceProxy_TCP::get_address() { 134 | return 1; 135 | } 136 | 137 | static DeviceProxy_TCP *proxy; 138 | 139 | extern "C" { 140 | DeviceProxy * get_deviceproxy_plugin(ConfigParser *cfg) { 141 | proxy = new DeviceProxy_TCP(cfg); 142 | return (DeviceProxy *) proxy; 143 | } 144 | 145 | void destroy_plugin() { 146 | delete proxy; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/Plugins/Injectors/Injector_UDPHID.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "errno.h" 10 | #include "netinet/in.h" 11 | 12 | #include "Injector_UDPHID.h" 13 | #include "Packet.h" 14 | #include "HexString.h" 15 | 16 | Injector_UDPHID::Injector_UDPHID(ConfigParser *cfg) { 17 | std::string port_str = cfg->get("Injector_UDPHID::port"); 18 | if(port_str == "") { 19 | fprintf(stderr, "Error: no port found for Injector_UDPHID\n"); 20 | return; 21 | } 22 | else 23 | port = std::stoi(port_str, nullptr, 10); 24 | 25 | sck=0; 26 | buf=NULL; 27 | spoll.events=POLLIN; 28 | this->interface.deviceClass=0xff; 29 | this->interface.subClass=0x5d; 30 | this->endpoint.address=0x80; 31 | this->endpoint.addressMask=0x80; 32 | reportBuffer[0]=0; 33 | reportBuffer[1]=0x14; 34 | reportBuffer[2]=0; 35 | reportBuffer[3]=0; 36 | reportBuffer[4]=0; 37 | reportBuffer[5]=0; 38 | reportBuffer[6]=0; 39 | reportBuffer[7]=0; 40 | reportBuffer[8]=0; 41 | reportBuffer[9]=0; 42 | reportBuffer[10]=0; 43 | reportBuffer[11]=0; 44 | reportBuffer[12]=0; 45 | reportBuffer[13]=0; 46 | reportBuffer[14]=0; 47 | reportBuffer[15]=0; 48 | reportBuffer[16]=0; 49 | reportBuffer[17]=0; 50 | reportBuffer[18]=0; 51 | reportBuffer[19]=0; 52 | cfg->add_pointer("PacketFilter_UDPHID::injector", this); 53 | } 54 | 55 | Injector_UDPHID::~Injector_UDPHID() { 56 | if (sck) {close(sck);sck=0;} 57 | if (buf) {free(buf);buf=NULL;} 58 | } 59 | 60 | void Injector_UDPHID::start_injector() { 61 | fprintf(stderr,"Opening injection UDP socket on port %d.\n",port); 62 | sck=socket(AF_INET,SOCK_DGRAM | SOCK_CLOEXEC,IPPROTO_UDP); 63 | spoll.fd=sck; 64 | if (sck<0) { 65 | fprintf(stderr,"Error creating socket.\n"); 66 | sck=0; 67 | } 68 | struct sockaddr_in addr; 69 | memset((char *)&addr,0,sizeof(addr)); 70 | addr.sin_family=AF_INET; 71 | addr.sin_addr.s_addr=htonl(INADDR_ANY); 72 | addr.sin_port=htons(port); 73 | if (bind(sck,(struct sockaddr*)&addr,sizeof(addr))<0) { 74 | fprintf(stderr,"Error binding to port %d.\n",port); 75 | sck=0; 76 | } 77 | //sized to handle ETHERNET less IP(20 byte)/UDP(8 byte) headers 78 | buf=(__u8*)malloc(UDP_BUFFER_SIZE); 79 | } 80 | 81 | int* Injector_UDPHID::get_pollable_fds() { 82 | int* tmp=(int*)calloc(2,sizeof(int)); 83 | tmp[0]=sck; 84 | return tmp; 85 | } 86 | 87 | void Injector_UDPHID::stop_injector() { 88 | if (sck) {close(sck);sck=0;} 89 | if (buf) {free(buf);buf=NULL;} 90 | } 91 | void Injector_UDPHID::get_packets(Packet** packet,SetupPacket** setup,int timeout) { 92 | *packet=NULL; 93 | *setup=NULL; 94 | 95 | if (!poll(&spoll, 1, timeout) || !(spoll.revents&POLLIN)) { 96 | return; 97 | } 98 | 99 | ssize_t len=recv(sck,buf,UDP_BUFFER_SIZE,0); 100 | if (len>0) { 101 | if (buf[0]) { 102 | __u16 usblen=buf[2]<<8 | buf[3]; 103 | __u8* usbbuf=(__u8*)malloc(usblen); 104 | memcpy(usbbuf,buf+4,usblen); 105 | *packet=new Packet(buf[0],usbbuf,usblen,buf[1]&0x01?false:true); 106 | (*packet)->transmit=buf[1]&0x02?false:true; 107 | if ((*packet)->wLength==20) { 108 | __u8* data=(*packet)->data; 109 | if (data[0]==0 && data[1]==20) {memcpy(reportBuffer+2,data+2,12);} 110 | } 111 | return; 112 | } else { 113 | struct usb_ctrlrequest ctrl_req; 114 | memcpy(&ctrl_req,buf+3,8); 115 | if (ctrl_req.bRequestType&0x80) { 116 | *setup=new SetupPacket(ctrl_req,NULL,true); 117 | } else { 118 | __u8* usbbuf=(__u8*)malloc(ctrl_req.wLength); 119 | memcpy(usbbuf,buf+11,ctrl_req.wLength); 120 | *setup=new SetupPacket(ctrl_req,usbbuf,true); 121 | } 122 | (*setup)->filter_out = (buf[1] & 0x01) == 0x01 ? false : true; 123 | (*setup)->transmit_out = (buf[1] & 0x02) == 0x02 ? false : true; 124 | (*setup)->filter_in = (buf[1] & 0x04) == 0x04 ? false : true; 125 | (*setup)->transmit_in = (buf[1] & 0x08) == 0x08 ? false : true; 126 | return; 127 | } 128 | } 129 | if (len<0) { 130 | fprintf(stderr,"Socket read error [%s].\n",strerror(errno)); 131 | } 132 | return; 133 | } 134 | 135 | void Injector_UDPHID::full_pipe(Packet* p) {fprintf(stderr,"Packet returned due to full pipe & buffer\n");} 136 | 137 | static Injector_UDPHID *injector; 138 | 139 | extern "C" { 140 | int plugin_type = PLUGIN_INJECTOR; 141 | 142 | Injector * get_plugin(ConfigParser *cfg) { 143 | injector = new Injector_UDPHID(cfg); 144 | return (Injector *) injector; 145 | } 146 | 147 | void destroy_plugin() { 148 | delete injector; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /nodejs-client/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-client", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "bl": { 8 | "version": "2.2.1", 9 | "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", 10 | "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", 11 | "requires": { 12 | "readable-stream": "^2.3.5", 13 | "safe-buffer": "^5.1.1" 14 | } 15 | }, 16 | "core-util-is": { 17 | "version": "1.0.2", 18 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 19 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 20 | }, 21 | "inherits": { 22 | "version": "2.0.4", 23 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 24 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 25 | }, 26 | "isarray": { 27 | "version": "1.0.0", 28 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 29 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 30 | }, 31 | "msgpack5": { 32 | "version": "5.0.0", 33 | "resolved": "https://registry.npmjs.org/msgpack5/-/msgpack5-5.0.0.tgz", 34 | "integrity": "sha512-oqVm0KrxGEBaMu/2Y5/pGy/FVCL7zvpL6uktSGlIMOZsfgx7kLA1WTDD9wG57ygeQWsMuLwusvN5bEX41gdHLg==", 35 | "requires": { 36 | "bl": "^2.0.1", 37 | "inherits": "^2.0.3", 38 | "readable-stream": "^2.3.6", 39 | "safe-buffer": "^5.1.2" 40 | } 41 | }, 42 | "node-gyp-build": { 43 | "version": "4.2.3", 44 | "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", 45 | "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==" 46 | }, 47 | "process-nextick-args": { 48 | "version": "2.0.1", 49 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 50 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 51 | }, 52 | "readable-stream": { 53 | "version": "2.3.7", 54 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 55 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 56 | "requires": { 57 | "core-util-is": "~1.0.0", 58 | "inherits": "~2.0.3", 59 | "isarray": "~1.0.0", 60 | "process-nextick-args": "~2.0.0", 61 | "safe-buffer": "~5.1.1", 62 | "string_decoder": "~1.1.1", 63 | "util-deprecate": "~1.0.1" 64 | }, 65 | "dependencies": { 66 | "safe-buffer": { 67 | "version": "5.1.2", 68 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 69 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 70 | } 71 | } 72 | }, 73 | "safe-buffer": { 74 | "version": "5.2.1", 75 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 76 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 77 | }, 78 | "string_decoder": { 79 | "version": "1.1.1", 80 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 81 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 82 | "requires": { 83 | "safe-buffer": "~5.1.0" 84 | }, 85 | "dependencies": { 86 | "safe-buffer": { 87 | "version": "5.1.2", 88 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 89 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 90 | } 91 | } 92 | }, 93 | "util-deprecate": { 94 | "version": "1.0.2", 95 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 96 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 97 | }, 98 | "zeromq": { 99 | "version": "6.0.0-beta.6", 100 | "resolved": "https://registry.npmjs.org/zeromq/-/zeromq-6.0.0-beta.6.tgz", 101 | "integrity": "sha512-wLf6M7pBHijl+BRltUL2VoDpgbQcOZetiX8UzycHL8CcYFxYnRrpoG5fi3UX3+Umavz1lk4/dGaQez8qiDgr/Q==", 102 | "requires": { 103 | "node-gyp-build": "^4.1.0" 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/lib/PluginManager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "Plugins.h" 10 | #include "PluginManager.h" 11 | #include "DeviceProxy.h" 12 | #include "HostProxy.h" 13 | #include "PacketFilter.h" 14 | #include "Injector.h" 15 | 16 | // FIXME: replace all of this repetative code with something based on Templates 17 | 18 | typedef DeviceProxy* (*device_plugin_getter)(ConfigParser *); 19 | typedef HostProxy* (*host_plugin_getter)(ConfigParser *); 20 | typedef PacketFilter* (*filter_plugin_getter)(ConfigParser *); 21 | typedef Injector* (*injector_plugin_getter)(ConfigParser *); 22 | 23 | void *PluginManager::load_shared_lib(std::string plugin_name) { 24 | std::string plugin_file = PLUGIN_PATH + plugin_name + ".so"; 25 | void* plugin_lib = dlopen(plugin_file.c_str(), RTLD_LAZY); 26 | if(!plugin_lib) 27 | fprintf(stderr, "error opening library %s\n", dlerror()); 28 | 29 | return plugin_lib; 30 | } 31 | 32 | int PluginManager::load_plugins(ConfigParser *cfg) 33 | { 34 | std::string plugin_file; 35 | void* plugin_func; 36 | PacketFilter *filter; 37 | fprintf(stderr, "Loading plugins from %s\n", PLUGIN_PATH); 38 | 39 | device_plugin_getter dp_ptr; 40 | host_plugin_getter hp_ptr; 41 | filter_plugin_getter f_ptr; 42 | injector_plugin_getter i_ptr; 43 | 44 | // Device Proxy 45 | void* dplugin_lib = load_shared_lib(cfg->get("DeviceProxy")); 46 | if(!dplugin_lib) 47 | return PLUGIN_MANAGER_CANNOT_FIND_FILE; 48 | plugin_func = dlsym(dplugin_lib, "get_deviceproxy_plugin"); 49 | if (!plugin_func) { 50 | dlclose(dplugin_lib); 51 | return PLUGIN_MANAGER_CANNOT_FIND_FILE; 52 | } 53 | handleList.push_back(plugin_func); 54 | dp_ptr = *reinterpret_cast(&plugin_func); 55 | device_proxy = (*(dp_ptr))(cfg); 56 | 57 | // Host Proxy 58 | void* hplugin_lib = load_shared_lib(cfg->get("HostProxy")); 59 | if(!hplugin_lib) 60 | return PLUGIN_MANAGER_CANNOT_FIND_FILE; 61 | plugin_func = dlsym(hplugin_lib, "get_hostproxy_plugin"); 62 | if (!plugin_func) { 63 | dlclose(hplugin_lib); 64 | return PLUGIN_MANAGER_CANNOT_FIND_FILE; 65 | } 66 | handleList.push_back(plugin_func); 67 | hp_ptr = *reinterpret_cast(&plugin_func); 68 | host_proxy = (*(hp_ptr))(cfg); 69 | 70 | // Plugins 71 | std::vector plugin_names=cfg->get_vector("Plugins"); 72 | for(std::vector::iterator it = plugin_names.begin(); 73 | it != plugin_names.end(); ++it) { 74 | void* plugin_lib = load_shared_lib(*it); 75 | if(plugin_lib==NULL) 76 | return PLUGIN_MANAGER_CANNOT_FIND_FILE; 77 | plugin_func = dlsym(plugin_lib, "plugin_type"); 78 | if (!plugin_func) { 79 | dlclose(plugin_lib); 80 | continue; 81 | } 82 | int plugin_type = *static_cast(plugin_func); 83 | 84 | switch (plugin_type) { 85 | case PLUGIN_FILTER: 86 | plugin_func = dlsym(plugin_lib, "get_plugin"); 87 | if (!plugin_func) { 88 | dlclose(plugin_lib); 89 | continue; 90 | } 91 | handleList.push_back(plugin_func); 92 | f_ptr = *reinterpret_cast(&plugin_func); 93 | filters.push_back((*(f_ptr))(cfg)); 94 | break; 95 | case PLUGIN_INJECTOR: 96 | plugin_func = dlsym(plugin_lib, "get_plugin"); 97 | if (!plugin_func) { 98 | dlclose(plugin_lib); 99 | continue; 100 | } 101 | handleList.push_back(plugin_func); 102 | i_ptr = *reinterpret_cast(&plugin_func); 103 | injectors.push_back((*(i_ptr))(cfg)); 104 | break; 105 | case (PLUGIN_FILTER|PLUGIN_INJECTOR): 106 | plugin_func = dlsym(plugin_lib, "get_plugin"); 107 | if (!plugin_func) { 108 | dlclose(plugin_lib); 109 | continue; 110 | } 111 | handleList.push_back(plugin_func); 112 | f_ptr = *reinterpret_cast(&plugin_func); 113 | filter = (*(f_ptr))(cfg); 114 | filters.push_back(filter); 115 | injectors.push_back(dynamic_cast(filter)); 116 | // this is a bit of a hack to solve double delete 117 | // on hotplug 118 | dynamic_cast(filter)->plugin_type=plugin_type; 119 | break; 120 | default: 121 | dlclose(plugin_lib); 122 | fprintf(stderr, "Invalid plugin type (%s)\n", (*it).c_str()); 123 | break; 124 | } 125 | } 126 | return PLUGIN_MANAGER_SUCCESS; 127 | } 128 | 129 | void PluginManager::add_plugin(PacketFilter* plugin) 130 | { 131 | filters.push_back(plugin); 132 | } 133 | 134 | void PluginManager::add_plugin(Injector* plugin) 135 | { 136 | injectors.push_back(plugin); 137 | } 138 | 139 | void PluginManager::destroy_plugins() 140 | { 141 | for(std::vector::iterator it = handleList.begin(); 142 | it != handleList.end(); ++it) 143 | { 144 | dlclose(*it); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/lib/Injector.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #ifndef USBPROXY_INJECTOR_H 6 | #define USBPROXY_INJECTOR_H 7 | 8 | #include 9 | #include 10 | 11 | #include "Plugins.h" 12 | #include "Packet.h" 13 | #include "Criteria.h" 14 | #include "ConfigParser.h" 15 | 16 | class Injector { 17 | private: 18 | 19 | 20 | int outPollIndex[16]; 21 | int inPollIndex[16]; 22 | std::atomic_bool _please_stop; 23 | 24 | protected: 25 | PacketQueue* outQueues[16]; 26 | PacketQueue* inQueues[16]; 27 | //--------------------------------------------------------------------- 28 | /// \brief gets new packets from injector pipe 29 | /// 30 | /// \param[out] packet pointer to data packet if present. nullptr if 31 | /// no data packet. 32 | /// \param[out] setup pointer to setup packet if present. nullptr if 33 | /// no setup packet. 34 | /// \param timeout timeout in ms to poll for new packet(s) 35 | /// 36 | /// \Note It is the responsibility of the calling routine to 37 | /// destroy the packet contents. 38 | /// \Note This is a legacy routine to support old injectors 39 | //--------------------------------------------------------------------- 40 | virtual void get_packets(Packet** packet, SetupPacket** setup, int timeout=500) {} 41 | //--------------------------------------------------------------------- 42 | //--------------------------------------------------------------------- 43 | virtual void start_injector() {} 44 | //--------------------------------------------------------------------- 45 | //--------------------------------------------------------------------- 46 | virtual void stop_injector() {} 47 | //--------------------------------------------------------------------- 48 | //--------------------------------------------------------------------- 49 | virtual void setup_ack() {} 50 | //--------------------------------------------------------------------- 51 | //--------------------------------------------------------------------- 52 | virtual void setup_stall() {} 53 | //--------------------------------------------------------------------- 54 | //--------------------------------------------------------------------- 55 | virtual void setup_data(__u8* buf, int length) {} 56 | //--------------------------------------------------------------------- 57 | /// \brief get pollable file descriptors(s) for injection pipe 58 | /// 59 | /// \return pointer to a zero terminated list of file descriptors used 60 | /// by get_packets(); 61 | /// /// \Note This is a legacy routine to support old injectors 62 | //--------------------------------------------------------------------- 63 | virtual int* get_pollable_fds() {return NULL;} 64 | //--------------------------------------------------------------------- 65 | //--------------------------------------------------------------------- 66 | virtual void full_pipe(SetupPacket* p) {} 67 | virtual void full_pipe(Packet* p) {} 68 | 69 | public: 70 | 71 | __u8 plugin_type=PLUGIN_INJECTOR; 72 | /// \brief endpoint filter 73 | struct criteria_endpoint endpoint; 74 | /// \brief interface filter 75 | struct criteria_interface interface; 76 | /// \brief configuration filter 77 | struct criteria_configuration configuration; 78 | /// \brief device filter 79 | struct criteria_device device; 80 | 81 | Injector(); 82 | virtual ~Injector() {} 83 | 84 | //--------------------------------------------------------------------- 85 | /// \brief used to notify the listen() task to exit 86 | //--------------------------------------------------------------------- 87 | void please_stop(void) { 88 | _please_stop = true; 89 | } 90 | 91 | //--------------------------------------------------------------------- 92 | //--------------------------------------------------------------------- 93 | void set_queue(__u8 epAddress, PacketQueue& queue); 94 | 95 | //--------------------------------------------------------------------- 96 | /// \brief main list loop 97 | /// 98 | /// This function is a task created by the Manager Class. 99 | /// The function polls for new packets to be injected from the injector 100 | /// pipe using get_packets. This is for support of legacy injector 101 | /// Pugins. Removing the pipes and directly injecting the data into the 102 | /// queue with outQueues[x].prioretyEnque dramatically (orders of 103 | /// magnitute) reduces the latencies in the system. 104 | //--------------------------------------------------------------------- 105 | virtual void listen(); 106 | 107 | //--------------------------------------------------------------------- 108 | //--------------------------------------------------------------------- 109 | virtual const char* toString() {return "Injector";} 110 | 111 | }; 112 | 113 | extern "C" { 114 | Injector *get_injector_plugin(); 115 | } 116 | #endif /* USBPROXY_INJECTOR_H */ 117 | -------------------------------------------------------------------------------- /src/lib/ConfigParser.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include "ConfigParser.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /* Taken from Kismet utils.cc */ 12 | std::string StrStrip(std::string in_str) { 13 | std::string temp; 14 | unsigned int start, end, x; 15 | 16 | start = 0; 17 | end = in_str.length(); 18 | 19 | if (in_str[0] == '\n') 20 | return ""; 21 | 22 | for (x = 0; x < in_str.length(); x++) { 23 | if (in_str[x] != ' ' && in_str[x] != '\t') { 24 | start = x; 25 | break; 26 | } 27 | } 28 | for (x = in_str.length(); x > 1; ) { 29 | x--; 30 | if (in_str[x] != ' ' && in_str[x] != '\t' && in_str[x] != '\n') { 31 | end = x; 32 | break; 33 | } 34 | } 35 | 36 | return in_str.substr(start, end-start+1); 37 | } 38 | 39 | ConfigParser::ConfigParser() 40 | : debugLevel(0) 41 | {} 42 | 43 | /* Very much inspired by Kismet's config parser */ 44 | void ConfigParser::parse_file(char* filename) { 45 | if(debugLevel) 46 | std::cerr << "Reading confilg file: " << filename << std::endl; 47 | 48 | std::ifstream configfile; 49 | configfile.open(filename, std::ifstream::in); 50 | if (!configfile) { 51 | std::cerr << "ERROR: Reading config file '" << filename << "': "; 52 | std::cerr << errno << " (" << strerror(errno) << ")" << std::endl; 53 | return; 54 | } 55 | 56 | std::string confline; 57 | while (!configfile.eof()) { 58 | std::getline(configfile, confline); 59 | 60 | std::string parsestr = StrStrip(confline); 61 | std::string key, value; 62 | 63 | if (parsestr.length() == 0) 64 | continue; 65 | if (parsestr[0] == '#') 66 | continue; 67 | 68 | unsigned int eq; 69 | if ((eq = parsestr.find("=")) > parsestr.length()) { 70 | key = parsestr; 71 | value = ""; 72 | } else { 73 | key = StrStrip(parsestr.substr(0, eq)); 74 | value = StrStrip(parsestr.substr(eq+1, parsestr.length())); 75 | set(key, value); 76 | } 77 | } 78 | configfile.close(); 79 | } 80 | 81 | void ConfigParser::set(std::string key, std::string value) { 82 | if(debugLevel) 83 | std::cerr << "CP: String " << key << " = " << value << std::endl; 84 | strings[key] = value; 85 | } 86 | 87 | std::string ConfigParser::get(const std::string& key) { 88 | auto cmitr = strings.find(key); 89 | // No such key 90 | if (cmitr == strings.end()) 91 | return ""; 92 | 93 | return cmitr->second; 94 | } 95 | 96 | void ConfigParser::add_to_vector(std::string key, std::string value) { 97 | if(debugLevel) 98 | std::cerr << "CP: Vector " << key << std::endl; 99 | std::map>::iterator vitr = vectors.find(key); 100 | // No such key 101 | if (vitr == vectors.end()) { 102 | std::vector vec; 103 | vec.push_back(value); 104 | vectors[key] = vec; 105 | } else 106 | vitr->second.push_back(value); 107 | } 108 | 109 | std::vector ConfigParser::get_vector(std::string key) { 110 | std::vector errvec; 111 | std::map>::iterator vitr = vectors.find(key); 112 | // No such key 113 | if (vitr == vectors.end()) 114 | return errvec; 115 | 116 | return vitr->second; 117 | } 118 | 119 | void ConfigParser::add_pointer(std::string key, void *value) { 120 | if(debugLevel) 121 | std::cerr << "CP: Pointer " << key << std::endl; 122 | pointers[key] = value; 123 | } 124 | 125 | void *ConfigParser::get_pointer(std::string key) { 126 | std::map::iterator pitr = pointers.find(key); 127 | // No such key 128 | if (pitr == pointers.end()) 129 | return NULL; 130 | 131 | return pitr->second; 132 | } 133 | 134 | /* Iterate over strings/vectors/pointers to print config */ 135 | void ConfigParser::print_config() { 136 | std::clog << "Printing Config data" << std::endl; 137 | std::clog << "\tStrings: " << strings.size() << std::endl; 138 | for(std::map::iterator it = strings.begin(); 139 | it != strings.end(); ++it) { 140 | std::clog << "\t\t" << it->first << ": " << it->second << std::endl; 141 | } 142 | 143 | std::clog << "\tVectors: " << vectors.size() << std::endl; 144 | for(std::map>::iterator it = vectors.begin(); 145 | it != vectors.end(); ++it) { 146 | std::clog << "\t\t" << it->first << ":\n"; 147 | for(std::vector::iterator itv = it->second.begin(); 148 | itv != it->second.end(); ++itv) { 149 | std::clog << "\t\t\t" << *itv << std::endl; 150 | } 151 | } 152 | 153 | std::clog << "\tPointer: " << pointers.size() << std::endl; 154 | for(std::map::iterator it = pointers.begin(); 155 | it != pointers.end(); ++it) { 156 | std::clog << "\t\t" << it->first << ": " << it->second << std::endl; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/lib/RelayWriter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of USBProxy. 3 | */ 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "get_tid.h" 18 | 19 | #include "Packet.h" 20 | #include "RelayWriter.h" 21 | 22 | #include "Endpoint.h" 23 | #include "Proxy.h" 24 | #include "DeviceProxy.h" 25 | #include "PacketFilter.h" 26 | #include "Manager.h" 27 | 28 | #define TRANSMIT_TIMEOUT_MS 500 29 | #define READ_TIMEOUT_MS 500 30 | 31 | extern zmq::context_t *ctx; 32 | 33 | RelayWriter::RelayWriter(Endpoint* _endpoint,Proxy* _proxy, PacketQueue& recvQueue) 34 | : _please_stop(false) 35 | , _recvQueue(&recvQueue) 36 | , _sendQueue(0) 37 | { 38 | 39 | endpoint=_endpoint->get_descriptor()->bEndpointAddress; 40 | attributes=_endpoint->get_descriptor()->bmAttributes; 41 | maxPacketSize=_endpoint->get_descriptor()->wMaxPacketSize; 42 | 43 | proxy=_proxy; 44 | deviceProxy=NULL; 45 | manager=NULL; 46 | 47 | sock = new zmq::socket_t(*ctx, zmq::socket_type::pub); 48 | (*sock).connect("tcp://127.0.0.1:9999"); 49 | } 50 | 51 | RelayWriter::RelayWriter(Endpoint* _endpoint,DeviceProxy* _deviceProxy,Manager* _manager, PacketQueue& recvQueue, PacketQueue& sendQueue) 52 | : _please_stop(false) 53 | , _recvQueue(&recvQueue) 54 | , _sendQueue(&sendQueue) 55 | { 56 | //_sendQueues.push_back(&sendQueue); 57 | 58 | endpoint=_endpoint->get_descriptor()->bEndpointAddress; 59 | attributes=_endpoint->get_descriptor()->bmAttributes; 60 | maxPacketSize=_endpoint->get_descriptor()->wMaxPacketSize; 61 | 62 | proxy=NULL; 63 | deviceProxy=_deviceProxy; 64 | manager=_manager; 65 | 66 | sock = new zmq::socket_t(*ctx, zmq::socket_type::pub); 67 | (*sock).connect("tcp://127.0.0.1:9999"); 68 | } 69 | 70 | RelayWriter::~RelayWriter() { 71 | filters.clear(); 72 | (*sock).close(); 73 | delete sock; 74 | } 75 | 76 | 77 | 78 | void RelayWriter::relay_write_setup() { 79 | if (!deviceProxy) { 80 | fprintf(stderr,"DeviceProxy not initialized for EP00 writer.\n"); 81 | return; 82 | } 83 | if (!_sendQueue) { 84 | fprintf(stderr,"outQueue not initialized for EP00 writer.\n"); 85 | return; 86 | } 87 | if (!_recvQueue) { 88 | fprintf(stderr,"inQueue not initialized for EP00 writer.\n"); 89 | return; 90 | } 91 | 92 | __u8 j; 93 | PacketPtr p; 94 | int length; 95 | usb_ctrlrequest ctrl_req; 96 | 97 | fprintf(stderr,"Starting setup writer thread (%ld) for EP%02x.\n",gettid(),endpoint); 98 | while (!_please_stop) { 99 | p = _recvQueue->dequeue(); 100 | 101 | if (_please_stop) 102 | break; 103 | if (!p) 104 | continue; 105 | SetupPacket* s = dynamic_cast(p.get()); 106 | if (!s) 107 | continue; 108 | //int sendQueue=events[i].data.u64&(__u64)0xffffffff; 109 | //s->source=sendQueue; TODO 110 | if (s->filter) { 111 | for(j=0; jfilter_out; j++) 112 | if (filters[j]->test_setup_packet(s, true)){ 113 | filters[j]->filter_setup_packet(s, true); 114 | } 115 | } 116 | ctrl_req=s->ctrl_req; 117 | if (!s->transmit_out || !s->transmit) 118 | continue; 119 | 120 | if (ctrl_req.bRequestType&0x80) { //device->host 121 | s->data=(__u8*)malloc(ctrl_req.wLength); 122 | s->transmit_in = (deviceProxy->control_request(&(s->ctrl_req), &length, s->data, TRANSMIT_TIMEOUT_MS) >= 0); 123 | j=0; 124 | s->ctrl_req.wLength=length; 125 | } else { //host->device 126 | length=ctrl_req.wLength; 127 | s->transmit_in = (deviceProxy->control_request(&(s->ctrl_req), &length, s->data, TRANSMIT_TIMEOUT_MS) >= 0); 128 | if (s->ctrl_req.bRequest == USB_REQ_SET_CONFIGURATION && s->ctrl_req.bRequestType == 0) { 129 | manager->setConfig(s->ctrl_req.wValue); 130 | } 131 | // msw -> why is this needed? 132 | s->ctrl_req.wLength=0; 133 | } 134 | if (s->filter) { 135 | for(;jfilter_in; j++) 136 | if (filters[j]->test_setup_packet(s, false)) 137 | filters[j]->filter_setup_packet(s, false); 138 | } 139 | _sendQueue->enqueue(p); 140 | } 141 | fprintf(stderr,"Finished setup writer thread (%ld) for EP%02x.\n",gettid(),endpoint); 142 | _please_stop = false; 143 | } 144 | 145 | void RelayWriter::relay_write() { 146 | if (!endpoint) { 147 | relay_write_setup(); 148 | return; 149 | } 150 | 151 | bool writing=false; 152 | PacketPtr p; 153 | 154 | fprintf(stderr,"Starting writer thread (%ld) for EP%02x.\n",gettid(),endpoint); 155 | while (!_please_stop) { 156 | if (!writing) { 157 | p = _recvQueue->dequeue(); 158 | if (_please_stop) 159 | { 160 | break; 161 | } 162 | if (!p) { 163 | continue; 164 | } 165 | 166 | if (p->filter) { 167 | for(size_t j=0; jtest_packet(p.get())) { 169 | filters[j]->filter_packet(p.get(), sock); 170 | } 171 | } 172 | } 173 | 174 | if (_please_stop) 175 | { 176 | break; 177 | } 178 | 179 | if (p->transmit) { 180 | proxy->send_data(endpoint,attributes,maxPacketSize,p->data,p->wLength); 181 | writing=true; 182 | } 183 | } else { 184 | writing=!(proxy->send_wait_complete(endpoint, READ_TIMEOUT_MS)); 185 | } 186 | } 187 | fprintf(stderr,"Finished writer thread (%ld) for EP%02x.\n",gettid(),endpoint); 188 | _please_stop = false; 189 | } 190 | 191 | void RelayWriter::add_filter(PacketFilter* filter) { 192 | filters.push_back(filter); 193 | } 194 | --------------------------------------------------------------------------------