├── .gitignore ├── .travis.yml ├── CHANGELOG ├── CONTRIBUTORS ├── LICENSE ├── README.md ├── doxygen.conf ├── examples └── c │ ├── ipv4 │ ├── CMakeLists.txt │ ├── build.sh │ └── example.c │ ├── ipv6 │ ├── CMakeLists.txt │ ├── build.sh │ └── example.c │ ├── tcp_ipv4 │ ├── CMakeLists.txt │ ├── build.sh │ └── example.c │ └── tcp_ipv6 │ ├── CMakeLists.txt │ ├── build.sh │ └── example.c └── src ├── CMakeLists.txt ├── CMakeLists.txt.a ├── CMakeLists.txt.so ├── build.sh ├── common.c ├── inc ├── common.h ├── ipv4defrag.h ├── ipv6defrag.h ├── libntoh.h ├── sfhash.h └── tcpreassembly.h ├── ipv4defrag.c ├── ipv6defrag.c ├── libntoh.c ├── ntoh.pc.in ├── sfhash.c └── tcpreassembly.c /.gitignore: -------------------------------------------------------------------------------- 1 | .cproject 2 | .project 3 | src/build 4 | examples/c/*/build 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | compiler: 4 | - gcc 5 | 6 | before_script: 7 | - cd src 8 | - mkdir build 9 | - cd build 10 | - cmake .. 11 | 12 | script: make 13 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | libntoh (0.4.1a) 2 | * Contributions made by: Eosis - https://github.com/Eosis 3 | * MAJOR: Fixed linked list problem seen if there was only one item in the list 4 | * MAJOR: Fixed problem caused by ipv4 hash collisions 5 | * 6 | * Contributions made by: di3online - https://github.com/di3online 7 | * MINOR: Modified DEFAULT_TCP_MAX_STREAMS to 4096 (connections) 8 | * MINOR: Optional connection timeout verification (for SYN , SYN + ACK and Established connections) 9 | * MINOR: Added shortcut to get packet origin (segment->origin = NTOH_SENT_BY_CLIENT || NTOH_SENT_BY_SERVER) 10 | * MINOR: compilation as static library 11 | * 12 | * Contributions made by: harjotgill - https://github.com/harjotgill 13 | * MEDIUM: Fixed issue caused when source and destination addresses are the same (localhost) 14 | * 15 | 16 | -- Chema Garcia (xx/xx/20xx) 17 | 18 | libntoh (0.4a) 19 | 20 | * Added DEFAULT_TIMEOUT_DELAY, delay value to check connections timeout 21 | * Replaced 'sleep' calls by 'poll' 22 | * Added some sanity checks of functions input 23 | * Added a function to get the tuple4 for an IPv4 flow 24 | * Added a function to get the tuple5 for an TCP/IPv4 stream 25 | * New field (protocol) added to identify TCP streams. ntoh_tcp_tuple4_t becomes ntoh_tcp_tuple5_t 26 | * Added a function to get the max. amount of IPv4 flows that can be stored (ntoh_ipv4_getsize) 27 | * Added a function to get the max. amount of TCP streams that can be stored (ntoh_tcp_getsize) 28 | * Added a flag to indicate we want to receive segments from a given peer 29 | * Fixed a MAJOR bug in TCP (avoided to correctly finish TCP streams) 30 | * Self implementation of hash tables (collision resolution by chaining) 31 | * Fixed a MAJOR bug in IPv4 defragmentation (deadlock) 32 | * Fixed a bug in IPv4 defragmentation when building the complete datagram (now using flow->total instead of flow->meat to allocate the memory. In some scenarios may cause segfault) 33 | 34 | -- Chema Garcia (xx/xx/20xx) 35 | 36 | libntoh (0.3a) 37 | 38 | * TCP reassembly has been totally rewritten 39 | * Added IPv4 defragmentation 40 | 41 | -- Chema Garcia (7/12/2011) 42 | 43 | libntoh (0.2a) 44 | 45 | * Directory tree restructured 46 | * Changelog added 47 | * Self implementation of linked lists (no glib-2.0 needed) 48 | * C files restructured 49 | * Added a function to get libntoh version 50 | * Some macros to get descriptions about errors,status,etc. are now exported C functions 51 | * ntohexample code updated 52 | * More comments added 53 | * Documentation regenerated 54 | * Added forgotten call to "shandler" in ntohexample 55 | * Added pkg-config compilation support 56 | 57 | -- Chema Garcia (14/11/2011) 58 | 59 | libntoh (0.1a) 60 | 61 | * First release 62 | 63 | -- Chema Garcia (7/11/2011) 64 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Eosis - https://github.com/Eosis 2 | di3online - https://github.com/di3online 3 | Harjot Gill - https://github.com/harjotgill 4 | ngo - https://github.com/ngo 5 | 6 | Thank you all guys! 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2012, Chema Garcia * 3 | * All rights reserved. * 4 | * * 5 | * Redistribution and use in source and binary forms, with or * 6 | * without modification, are permitted provided that the following * 7 | * conditions are met: * 8 | * * 9 | * * Redistributions of source code must retain the above * 10 | * copyright notice, this list of conditions and the following * 11 | * disclaimer. * 12 | * * 13 | * * Redistributions in binary form must reproduce the above * 14 | * copyright notice, this list of conditions and the following * 15 | * disclaimer in the documentation and/or other materials provided * 16 | * with the distribution. * 17 | * * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 28 | * POSSIBILITY OF SUCH DAMAGE. * 29 | ********************************************************************************/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![build status](https://travis-ci.org/sch3m4/libntoh.svg?branch=master) 2 | 3 | ### Introduction 4 | 5 | **What is libntoh?** 6 | 7 | Libntoh aims to be an user-friendly library to provide a easy way to perform defragmentation and reassembly of network/transport/(more?) protocols. 8 | 9 | 10 | **Why libntoh?** 11 | 12 | It's true there are some libraries which aims to do the same things (like libnids), but libntoh is intended to provide a flexible, thread-safe and highly configurable environment for the final user. And most of all, libntoh is released under Modified BSD License to avoid many license issues. 13 | 14 | 15 | **Which protocols does libntoh support?** 16 | 17 | Currently libntoh performs IPv4/IPv6 defragmentation and TCP reassembly over IPv4 and IPv6. 18 | 19 | ### Mailing List 20 | There is a mailing list for libntoh development issues: libntoh-dev@safetybits.net 21 | 22 | ### Getting the source 23 | 24 | $ git clone git://github.com/sch3m4/libntoh.git 25 | Cloning into 'libntoh'... 26 | remote: Counting objects: 962, done. 27 | remote: Total 962 (delta 0), reused 0 (delta 0), pack-reused 962 28 | Receiving objects: 100% (962/962), 1.01 MiB | 121.00 KiB/s, done. 29 | Resolving deltas: 100% (483/483), done. 30 | Checking connectivity... hecho. 31 | $ 32 | 33 | ### Dependencies 34 | 35 | To successfully compile libntoh you only need gcc, make, cmake, pkg-config and libpthread-dev. 36 | 37 | Debian-like OS: 38 | 39 | $ sudo apt-get install cmake libpthread-dev gcc make build-essential pkg-config 40 | 41 | If you want to generate the source code documentation, you will also need doxygen: 42 | 43 | $ sudo apt-get install doxygen 44 | 45 | Note: pkg-config isn't really needed but it helps. (See "ntohexample" compilation) 46 | 47 | 48 | You need CMake to compile libntoh and ntohexample. 49 | 50 | 51 | ### Compilation instructions 52 | 53 | $ cd libntoh/src 54 | ../src$ ./build.sh 55 | [i] pkg-config found: /usr/bin/pkg-config 56 | [i] cmake found: /usr/bin/cmake 57 | [i] make found: /usr/bin/make 58 | [i] PKG_CONFIG_PATH set to: /usr/local/lib/pkgconfig 59 | 60 | -- The C compiler identification is GNU 4.8.4 61 | -- The CXX compiler identification is GNU 4.8.4 62 | -- Check for working C compiler: /usr/bin/cc 63 | -- Check for working C compiler: /usr/bin/cc -- works 64 | -- Detecting C compiler ABI info 65 | -- Detecting C compiler ABI info - done 66 | -- Check for working CXX compiler: /usr/bin/c++ 67 | -- Check for working CXX compiler: /usr/bin/c++ -- works 68 | -- Detecting CXX compiler ABI info 69 | -- Detecting CXX compiler ABI info - done 70 | -- Looking for include file pthread.h 71 | -- Looking for include file pthread.h - found 72 | -- Looking for pthread_create 73 | -- Looking for pthread_create - not found 74 | -- Looking for pthread_create in pthreads 75 | -- Looking for pthread_create in pthreads - not found 76 | -- Looking for pthread_create in pthread 77 | -- Looking for pthread_create in pthread - found 78 | -- Found Threads: TRUE 79 | -- Configuring done 80 | -- Generating done 81 | -- Build files have been written to: /tmp/libntoh/src/build 82 | Scanning dependencies of target ntoh 83 | [ 16%] Building C object CMakeFiles/ntoh.dir/libntoh.c.o 84 | [ 33%] Building C object CMakeFiles/ntoh.dir/tcpreassembly.c.o 85 | [ 50%] Building C object CMakeFiles/ntoh.dir/ipv4defrag.c.o 86 | [ 66%] Building C object CMakeFiles/ntoh.dir/ipv6defrag.c.o 87 | [ 83%] Building C object CMakeFiles/ntoh.dir/common.c.o 88 | [100%] Building C object CMakeFiles/ntoh.dir/sfhash.c.o 89 | Linking C shared library libntoh.so 90 | [100%] Built target ntoh 91 | Do you want to perform the installation? [y/n]: y 92 | [sudo] password for chema: 93 | [100%] Built target ntoh 94 | Install the project... 95 | -- Install configuration: "Release" 96 | -- Installing: /usr/local/lib/libntoh.so 97 | -- Installing: /usr/local/include/libntoh/libntoh.h 98 | -- Installing: /usr/local/include/libntoh/tcpreassembly.h 99 | -- Installing: /usr/local/include/libntoh/sfhash.h 100 | -- Installing: /usr/local/include/libntoh/ipv4defrag.h 101 | -- Installing: /usr/local/include/libntoh/ipv6defrag.h 102 | -- Installing: /usr/local/include/libntoh/common.h 103 | -- Installing: /usr/local/lib/pkgconfig/ntoh.pc 104 | $ 105 | 106 | For a more detailed description refer to 107 | https://github.com/sch3m4/libntoh/wiki 108 | 109 | ### Libntoh Examples 110 | 111 | You can find a working source code example for each supported protocol in "examples" folder: 112 | 113 | libntoh$ ls examples/ -R 114 | examples/: 115 | c 116 | 117 | examples/c: 118 | ipv4 ipv6 tcp_ipv4 tcp_ipv6 119 | 120 | examples/c/ipv4: 121 | build.sh CMakeLists.txt example.c 122 | 123 | examples/c/ipv6: 124 | build.sh CMakeLists.txt example.c 125 | 126 | examples/c/tcp_ipv4: 127 | build.sh CMakeLists.txt example.c 128 | 129 | examples/c/tcp_ipv6: 130 | build.sh CMakeLists.txt example.c 131 | 132 | 133 | The default installation prefix for libntoh is "/usr/local", so if you plan to link against libntoh using pkg-config 134 | remember to add "/usr/local/lib/pkgconfig" to PKG_CONFIG_PATH: 135 | 136 | $ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig 137 | $ pkg-config --libs --cflags ntoh -I/usr/local/include/libntoh -L/usr/local/lib -lntoh 138 | 139 | On the other hand you can change the installation prefix by defining CMAKE_INSTALL_PREFIX: 140 | 141 | $ cmake ../ -DCMAKE_INSTALL_PREFIX=/usr 142 | 143 | So the new installation prefix will be "/usr" 144 | 145 | For more information, refer to the wiki page. 146 | 147 | ### TCP/IPv4 Example Output: 148 | 149 | $ sudo ./ntohexample 150 | ########################### 151 | # libntoh Example # 152 | # ----------------------- # 153 | # Written by Chema Garcia # 154 | # ----------------------- # 155 | # http://safetybits.net # 156 | # chema@safetybits.net # 157 | ########################### 158 | 159 | [i] libntoh version: 0.4a 160 | 161 | [+] Usage: ./ntohexample 162 | 163 | + Options: 164 | -i | --iface -----> Interface to read packets from 165 | -f | --file ------> File path to read packets from 166 | -F | --filter ----> Capture filter (default: "ip and tcp") 167 | -c | --client ----------> Receive client data only 168 | -s | --server ----------> Receive server data only 169 | 170 | $ sudo ./ntohexample -i eth0 -F "tcp and host 10.0.0.1 and port 22" 171 | 172 | ########################### 173 | # libntoh Example # 174 | # ----------------------- # 175 | # Written by Chema Garcia # 176 | # ----------------------- # 177 | # http://safetybits.net # 178 | # chema@safetybits.net # 179 | ########################### 180 | 181 | [i] libntoh version: 0.4a 182 | 183 | [i] Source: eth0 / Ethernet 184 | [i] Filter: tcp and host 10.0.0.1 and port 22 185 | [i] Receive data from client: Yes 186 | [i] Receive data from server: Yes 187 | [i] Max. TCP streams allowed: 1024 188 | [i] Max. IPv4 flows allowed: 1024 189 | 190 | 191 | [SYN Sent] 10.0.0.2:40819 (SYN Sent | Window: 233600) ---> 10.0.0.1:22 (Listen | Window: 0) 192 | 193 | [SYN Rcv] 10.0.0.1:22 (SYN Rcv | Window: 4194240) ---> 10.0.0.2:40819 (SYN Sent | Window: 233600) 194 | 195 | [Established] 10.0.0.2:40819 (Established | Window: 233600) ---> 10.0.0.1:22 (Established | Window: 4194240) 196 | 197 | [Established] 10.0.0.1:22 (Established | Window: 4194240) ---> 10.0.0.2:40819 (Established | Window: 233600) 198 | + Data segment | Bytes: 49 SEQ: 1 ACK: 1 Next SEQ: 50 199 | 200 | [Established] 10.0.0.2:40819 (Established | Window: 233600) ---> 10.0.0.1:22 (Established | Window: 4193384) 201 | + Data segment | Bytes: 32 SEQ: 1 ACK: 50 Next SEQ: 33 202 | 203 | [Established] 10.0.0.1:22 (Established | Window: 4194240) ---> 10.0.0.2:40819 (Established | Window: 233600) 204 | + Data segment | Bytes: 856 SEQ: 50 ACK: 33 Next SEQ: 906 205 | 206 | [Established] 10.0.0.2:40819 (Established | Window: 233600) ---> 10.0.0.1:22 (Established | Window: 4194240) 207 | + Data segment | Bytes: 1272 SEQ: 33 ACK: 906 Next SEQ: 1305 208 | 209 | [Established] 10.0.0.2:40819 (Established | Window: 233600) ---> 10.0.0.1:22 (Established | Window: 4193928) 210 | + Data segment | Bytes: 80 SEQ: 1305 ACK: 906 Next SEQ: 1385 211 | 212 | [Established] 10.0.0.1:22 (Established | Window: 4194240) ---> 10.0.0.2:40819 (Established | Window: 233600) 213 | + Data segment | Bytes: 312 SEQ: 906 ACK: 1385 Next SEQ: 1218 214 | 215 | [Established] 10.0.0.2:40819 (Established | Window: 233600) ---> 10.0.0.1:22 (Established | Window: 4194240) 216 | + Data segment | Bytes: 16 SEQ: 1385 ACK: 1218 Next SEQ: 1401 217 | 218 | [Established] 10.0.0.2:40819 (Established | Window: 233600) ---> 10.0.0.1:22 (Established | Window: 4194192) 219 | + Data segment | Bytes: 48 SEQ: 1401 ACK: 1218 Next SEQ: 1449 220 | 221 | [Established] 10.0.0.1:22 (Established | Window: 4194240) ---> 10.0.0.2:40819 (Established | Window: 233600) 222 | + Data segment | Bytes: 48 SEQ: 1218 ACK: 1449 Next SEQ: 1266 223 | 224 | [Established] 10.0.0.2:40819 (Established | Window: 233600) ---> 10.0.0.1:22 (Established | Window: 4194176) 225 | + Data segment | Bytes: 64 SEQ: 1449 ACK: 1266 Next SEQ: 1513 226 | 227 | [Established] 10.0.0.1:22 (Established | Window: 4194240) ---> 10.0.0.2:40819 (Established | Window: 233600) 228 | + Data segment | Bytes: 64 SEQ: 1266 ACK: 1513 Next SEQ: 1330 229 | 230 | [Established] 10.0.0.2:40819 (Established | Window: 233600) ---> 10.0.0.1:22 (Established | Window: 4193920) 231 | + Data segment | Bytes: 368 SEQ: 1513 ACK: 1330 Next SEQ: 1881 232 | 233 | [Established] 10.0.0.1:22 (Established | Window: 4194240) ---> 10.0.0.2:40819 (Established | Window: 233600) 234 | + Data segment | Bytes: 320 SEQ: 1330 ACK: 1881 Next SEQ: 1650 235 | 236 | [Established] 10.0.0.2:40819 (Established | Window: 233600) ---> 10.0.0.1:22 (Established | Window: 4194208) 237 | + Data segment | Bytes: 640 SEQ: 1881 ACK: 1650 Next SEQ: 2521 238 | 239 | [Established] 10.0.0.1:22 (Established | Window: 4194240) ---> 10.0.0.2:40819 (Established | Window: 233600) 240 | + Data segment | Bytes: 32 SEQ: 1650 ACK: 2521 Next SEQ: 1682 241 | 242 | [Established] 10.0.0.2:40819 (Established | Window: 233600) ---> 10.0.0.1:22 (Established | Window: 4194192) 243 | + Data segment | Bytes: 128 SEQ: 2521 ACK: 1682 Next SEQ: 2649 244 | 245 | [Established] 10.0.0.1:22 (Established | Window: 4194240) ---> 10.0.0.2:40819 (Established | Window: 233488) 246 | + Data segment | Bytes: 48 SEQ: 1682 ACK: 2649 Next SEQ: 1730 247 | 248 | [Established] 10.0.0.2:40819 (Established | Window: 233600) ---> 10.0.0.1:22 (Established | Window: 4194160) 249 | + Data segment | Bytes: 112 SEQ: 2649 ACK: 1730 Next SEQ: 2761 250 | 251 | [Established] 10.0.0.1:22 (Established | Window: 4194208) ---> 10.0.0.2:40819 (Established | Window: 233600) 252 | + Data segment | Bytes: 80 SEQ: 1730 ACK: 2761 Next SEQ: 1810 253 | 254 | [Established] 10.0.0.1:22 (Established | Window: 4194240) ---> 10.0.0.2:40819 (Established | Window: 233600) 255 | + Data segment | Bytes: 32 SEQ: 1810 ACK: 2761 Next SEQ: 1842 256 | 257 | [Established] 10.0.0.1:22 (Established | Window: 4194240) ---> 10.0.0.2:40819 (Established | Window: 233568) 258 | + Data segment | Bytes: 160 SEQ: 1842 ACK: 2761 Next SEQ: 2002 259 | 260 | [Established] 10.0.0.2:40819 (Established | Window: 233536) ---> 10.0.0.1:22 (Established | Window: 4194240) 261 | + Data segment | Bytes: 32 SEQ: 2761 ACK: 2002 Next SEQ: 2793 262 | 263 | [Established] 10.0.0.2:40819 (Established | Window: 233600) ---> 10.0.0.1:22 (Established | Window: 4194240) 264 | + Data segment | Bytes: 64 SEQ: 2793 ACK: 2002 Next SEQ: 2857 265 | 266 | [Closing] 10.0.0.2:40819 (Fin Wait1 | Window: 233600) ---> 10.0.0.1:22 (Close Wait | Window: 4194240) 267 | 268 | [Closing] 10.0.0.1:22 (Last ACK | Window: 4194240) ---> 10.0.0.2:40819 (Closing | Window: 233600) 269 | 270 | [Closed] 10.0.0.2:40819 (Time Wait | Window: 233600) ---> 10.0.0.1:22 (Closed | Window: 4194240) 271 | 272 | [+] Capture finished! 273 | $ 274 | -------------------------------------------------------------------------------- /doxygen.conf: -------------------------------------------------------------------------------- 1 | 2 | #--------------------------------------------------------------------------- 3 | # Project related configuration options 4 | #--------------------------------------------------------------------------- 5 | DOXYFILE_ENCODING = UTF-8 6 | PROJECT_NAME = libntoh 7 | PROJECT_NUMBER = 0.5a 8 | OUTPUT_DIRECTORY = doxygen 9 | CREATE_SUBDIRS = NO 10 | OUTPUT_LANGUAGE = English 11 | BRIEF_MEMBER_DESC = YES 12 | REPEAT_BRIEF = YES 13 | ABBREVIATE_BRIEF = "The $name class" \ 14 | "The $name widget" \ 15 | "The $name file" \ 16 | is \ 17 | provides \ 18 | specifies \ 19 | contains \ 20 | represents \ 21 | a \ 22 | an \ 23 | the 24 | ALWAYS_DETAILED_SEC = NO 25 | INLINE_INHERITED_MEMB = NO 26 | FULL_PATH_NAMES = YES 27 | STRIP_FROM_PATH = 28 | STRIP_FROM_INC_PATH = 29 | SHORT_NAMES = NO 30 | JAVADOC_AUTOBRIEF = NO 31 | QT_AUTOBRIEF = NO 32 | MULTILINE_CPP_IS_BRIEF = NO 33 | INHERIT_DOCS = YES 34 | SEPARATE_MEMBER_PAGES = NO 35 | TAB_SIZE = 8 36 | ALIASES = 37 | OPTIMIZE_OUTPUT_FOR_C = YES 38 | OPTIMIZE_OUTPUT_JAVA = NO 39 | OPTIMIZE_FOR_FORTRAN = NO 40 | OPTIMIZE_OUTPUT_VHDL = NO 41 | EXTENSION_MAPPING = 42 | BUILTIN_STL_SUPPORT = NO 43 | CPP_CLI_SUPPORT = NO 44 | SIP_SUPPORT = NO 45 | IDL_PROPERTY_SUPPORT = YES 46 | DISTRIBUTE_GROUP_DOC = NO 47 | SUBGROUPING = YES 48 | TYPEDEF_HIDES_STRUCT = YES 49 | SYMBOL_CACHE_SIZE = 0 50 | 51 | #--------------------------------------------------------------------------- 52 | # Build related configuration options 53 | #--------------------------------------------------------------------------- 54 | EXTRACT_ALL = YES 55 | EXTRACT_PRIVATE = NO 56 | EXTRACT_STATIC = NO 57 | EXTRACT_LOCAL_CLASSES = YES 58 | EXTRACT_LOCAL_METHODS = YES 59 | EXTRACT_ANON_NSPACES = NO 60 | HIDE_UNDOC_MEMBERS = NO 61 | HIDE_UNDOC_CLASSES = NO 62 | HIDE_FRIEND_COMPOUNDS = NO 63 | HIDE_IN_BODY_DOCS = NO 64 | INTERNAL_DOCS = NO 65 | CASE_SENSE_NAMES = YES 66 | HIDE_SCOPE_NAMES = NO 67 | SHOW_INCLUDE_FILES = YES 68 | FORCE_LOCAL_INCLUDES = YES 69 | INLINE_INFO = YES 70 | SORT_MEMBER_DOCS = YES 71 | SORT_BRIEF_DOCS = NO 72 | SORT_MEMBERS_CTORS_1ST = NO 73 | SORT_GROUP_NAMES = NO 74 | SORT_BY_SCOPE_NAME = NO 75 | GENERATE_TODOLIST = YES 76 | GENERATE_TESTLIST = YES 77 | GENERATE_BUGLIST = YES 78 | GENERATE_DEPRECATEDLIST= YES 79 | ENABLED_SECTIONS = 80 | MAX_INITIALIZER_LINES = 30 81 | SHOW_USED_FILES = YES 82 | SHOW_DIRECTORIES = YES 83 | SHOW_FILES = YES 84 | SHOW_NAMESPACES = YES 85 | FILE_VERSION_FILTER = 86 | LAYOUT_FILE = 87 | 88 | #--------------------------------------------------------------------------- 89 | # configuration options related to warning and progress messages 90 | #--------------------------------------------------------------------------- 91 | QUIET = NO 92 | WARNINGS = YES 93 | WARN_IF_UNDOCUMENTED = YES 94 | WARN_IF_DOC_ERROR = YES 95 | WARN_NO_PARAMDOC = NO 96 | WARN_FORMAT = "$file:$line: $text" 97 | WARN_LOGFILE = 98 | 99 | #--------------------------------------------------------------------------- 100 | # configuration options related to the input files 101 | #--------------------------------------------------------------------------- 102 | INPUT = libntoh 103 | INPUT_ENCODING = UTF-8 104 | FILE_PATTERNS = *.c *.h 105 | RECURSIVE = YES 106 | EXCLUDE = 107 | EXCLUDE_SYMLINKS = NO 108 | EXCLUDE_PATTERNS = 109 | EXCLUDE_SYMBOLS = 110 | EXAMPLE_PATH = 111 | EXAMPLE_PATTERNS = * 112 | EXAMPLE_RECURSIVE = NO 113 | IMAGE_PATH = 114 | INPUT_FILTER = 115 | FILTER_PATTERNS = 116 | FILTER_SOURCE_FILES = NO 117 | 118 | #--------------------------------------------------------------------------- 119 | # configuration options related to source browsing 120 | #--------------------------------------------------------------------------- 121 | SOURCE_BROWSER = YES 122 | INLINE_SOURCES = YES 123 | STRIP_CODE_COMMENTS = YES 124 | REFERENCED_BY_RELATION = YES 125 | REFERENCES_RELATION = YES 126 | REFERENCES_LINK_SOURCE = YES 127 | USE_HTAGS = YES 128 | VERBATIM_HEADERS = YES 129 | 130 | #--------------------------------------------------------------------------- 131 | # configuration options related to the alphabetical class index 132 | #--------------------------------------------------------------------------- 133 | ALPHABETICAL_INDEX = YES 134 | COLS_IN_ALPHA_INDEX = 5 135 | IGNORE_PREFIX = 136 | 137 | #--------------------------------------------------------------------------- 138 | # configuration options related to the HTML output 139 | #--------------------------------------------------------------------------- 140 | GENERATE_HTML = YES 141 | HTML_OUTPUT = html 142 | HTML_FILE_EXTENSION = .html 143 | HTML_HEADER = 144 | HTML_FOOTER = 145 | HTML_STYLESHEET = 146 | HTML_COLORSTYLE_HUE = 220 147 | HTML_COLORSTYLE_SAT = 100 148 | HTML_COLORSTYLE_GAMMA = 80 149 | HTML_TIMESTAMP = YES 150 | HTML_ALIGN_MEMBERS = YES 151 | HTML_DYNAMIC_SECTIONS = YES 152 | GENERATE_DOCSET = NO 153 | DOCSET_FEEDNAME = "Doxygen generated docs" 154 | DOCSET_BUNDLE_ID = org.doxygen.Project 155 | DOCSET_PUBLISHER_ID = org.doxygen.Publisher 156 | DOCSET_PUBLISHER_NAME = Publisher 157 | GENERATE_HTMLHELP = NO 158 | CHM_FILE = 159 | HHC_LOCATION = 160 | GENERATE_CHI = NO 161 | CHM_INDEX_ENCODING = 162 | BINARY_TOC = NO 163 | TOC_EXPAND = NO 164 | GENERATE_QHP = NO 165 | QCH_FILE = 166 | QHP_NAMESPACE = org.doxygen.Project 167 | QHP_VIRTUAL_FOLDER = doc 168 | QHP_CUST_FILTER_NAME = 169 | QHP_CUST_FILTER_ATTRS = 170 | QHP_SECT_FILTER_ATTRS = 171 | QHG_LOCATION = 172 | GENERATE_ECLIPSEHELP = NO 173 | ECLIPSE_DOC_ID = org.doxygen.Project 174 | DISABLE_INDEX = NO 175 | ENUM_VALUES_PER_LINE = 4 176 | GENERATE_TREEVIEW = NO 177 | USE_INLINE_TREES = NO 178 | TREEVIEW_WIDTH = 250 179 | EXT_LINKS_IN_WINDOW = NO 180 | FORMULA_FONTSIZE = 10 181 | FORMULA_TRANSPARENT = YES 182 | SEARCHENGINE = YES 183 | SERVER_BASED_SEARCH = NO 184 | 185 | #--------------------------------------------------------------------------- 186 | # configuration options related to the LaTeX output 187 | #--------------------------------------------------------------------------- 188 | GENERATE_LATEX = YES 189 | LATEX_OUTPUT = latex 190 | LATEX_CMD_NAME = latex 191 | MAKEINDEX_CMD_NAME = makeindex 192 | COMPACT_LATEX = NO 193 | PAPER_TYPE = a4 194 | EXTRA_PACKAGES = 195 | LATEX_HEADER = 196 | PDF_HYPERLINKS = YES 197 | USE_PDFLATEX = YES 198 | LATEX_BATCHMODE = NO 199 | LATEX_HIDE_INDICES = NO 200 | LATEX_SOURCE_CODE = YES 201 | 202 | #--------------------------------------------------------------------------- 203 | # configuration options related to the RTF output 204 | #--------------------------------------------------------------------------- 205 | GENERATE_RTF = NO 206 | RTF_OUTPUT = rtf 207 | COMPACT_RTF = NO 208 | RTF_HYPERLINKS = NO 209 | RTF_STYLESHEET_FILE = 210 | RTF_EXTENSIONS_FILE = 211 | 212 | #--------------------------------------------------------------------------- 213 | # configuration options related to the man page output 214 | #--------------------------------------------------------------------------- 215 | GENERATE_MAN = YES 216 | MAN_OUTPUT = man 217 | MAN_EXTENSION = .3 218 | MAN_LINKS = YES 219 | 220 | #--------------------------------------------------------------------------- 221 | # configuration options related to the XML output 222 | #--------------------------------------------------------------------------- 223 | GENERATE_XML = NO 224 | XML_OUTPUT = xml 225 | XML_SCHEMA = 226 | XML_DTD = 227 | XML_PROGRAMLISTING = YES 228 | 229 | #--------------------------------------------------------------------------- 230 | # configuration options for the AutoGen Definitions output 231 | #--------------------------------------------------------------------------- 232 | GENERATE_AUTOGEN_DEF = NO 233 | 234 | #--------------------------------------------------------------------------- 235 | # configuration options related to the Perl module output 236 | #--------------------------------------------------------------------------- 237 | GENERATE_PERLMOD = NO 238 | PERLMOD_LATEX = NO 239 | PERLMOD_PRETTY = YES 240 | PERLMOD_MAKEVAR_PREFIX = 241 | 242 | #--------------------------------------------------------------------------- 243 | # Configuration options related to the preprocessor 244 | #--------------------------------------------------------------------------- 245 | ENABLE_PREPROCESSING = YES 246 | MACRO_EXPANSION = NO 247 | EXPAND_ONLY_PREDEF = NO 248 | SEARCH_INCLUDES = YES 249 | INCLUDE_PATH = 250 | INCLUDE_FILE_PATTERNS = 251 | PREDEFINED = 252 | EXPAND_AS_DEFINED = 253 | SKIP_FUNCTION_MACROS = YES 254 | 255 | #--------------------------------------------------------------------------- 256 | # Configuration::additions related to external references 257 | #--------------------------------------------------------------------------- 258 | TAGFILES = 259 | GENERATE_TAGFILE = 260 | ALLEXTERNALS = NO 261 | EXTERNAL_GROUPS = YES 262 | PERL_PATH = /usr/bin/perl 263 | 264 | #--------------------------------------------------------------------------- 265 | # Configuration options related to the dot tool 266 | #--------------------------------------------------------------------------- 267 | CLASS_DIAGRAMS = YES 268 | MSCGEN_PATH = 269 | HIDE_UNDOC_RELATIONS = YES 270 | HAVE_DOT = YES 271 | DOT_NUM_THREADS = 0 272 | DOT_FONTNAME = FreeSans.ttf 273 | DOT_FONTSIZE = 10 274 | DOT_FONTPATH = 275 | CLASS_GRAPH = YES 276 | COLLABORATION_GRAPH = YES 277 | GROUP_GRAPHS = YES 278 | UML_LOOK = YES 279 | TEMPLATE_RELATIONS = NO 280 | INCLUDE_GRAPH = YES 281 | INCLUDED_BY_GRAPH = YES 282 | CALL_GRAPH = YES 283 | CALLER_GRAPH = YES 284 | GRAPHICAL_HIERARCHY = YES 285 | DIRECTORY_GRAPH = YES 286 | DOT_IMAGE_FORMAT = png 287 | DOT_PATH = 288 | DOTFILE_DIRS = 289 | DOT_GRAPH_MAX_NODES = 60 290 | MAX_DOT_GRAPH_DEPTH = 0 291 | DOT_TRANSPARENT = NO 292 | DOT_MULTI_TARGETS = NO 293 | GENERATE_LEGEND = YES 294 | DOT_CLEANUP = YES 295 | 296 | -------------------------------------------------------------------------------- /examples/c/ipv4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED ( VERSION 2.8 FATAL_ERROR ) 2 | PROJECT ( LIBNTOHEXAMPLE ) 3 | 4 | # find libpthread 5 | FIND_PACKAGE ( Threads REQUIRED ) 6 | 7 | # find pkg-config 8 | FIND_PACKAGE ( PkgConfig REQUIRED ) 9 | 10 | # find libntoh 11 | PKG_CHECK_MODULES ( NTOH REQUIRED ntoh ) 12 | INCLUDE_DIRECTORIES ( ${NTOH_INCLUDE_DIRS} ) 13 | LINK_DIRECTORIES ( ${NTOH_LIBRARY_DIRS} ) 14 | ADD_DEFINITIONS ( ${NTOH_CFLAGS} ) 15 | 16 | SET ( CMAKE_BUILD_TYPE Release ) 17 | 18 | # set source files and flags 19 | SET ( LIBNTOHEXAMPLE_SRCS example.c ) 20 | SET ( CMAKE_C_FLAGS "-Wall -Os -O2 -lpcap -g" ) 21 | 22 | # set target from source 23 | ADD_EXECUTABLE ( ntohexample ${LIBNTOHEXAMPLE_SRCS} ) 24 | TARGET_LINK_LIBRARIES ( ntohexample pcap ntoh ${CMAKE_THREAD_LIBS_INIT}) 25 | -------------------------------------------------------------------------------- /examples/c/ipv4/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # this scripts follows the steps that you 4 | # should follow to compile and link against libntoh: 5 | # 6 | # $ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig 7 | # $ pkg-config --libs --cflags libntoh 8 | # -I/usr/local/include/libntoh -L/usr/local/lib -lntoh 9 | 10 | pkgconfig=$(which pkg-config) 11 | cmake=$(which cmake) 12 | make=$(which make) 13 | pkgconfig_path='' 14 | libntoh_pcpath='/usr/local/lib/pkgconfig' 15 | build_dir='build' 16 | 17 | if [ -z "$pkgconfig" ] 18 | then 19 | echo "[w] pkg-config not found! Good luck compiling..." 20 | exit 1 21 | else 22 | echo "[i] pkg-config found: $pkgconfig" 23 | fi 24 | 25 | if [ -z "$cmake" ] 26 | then 27 | echo "[e] Cannot compile without cmake binary" 28 | exit 2 29 | else 30 | echo "[i] cmake found: $cmake" 31 | fi 32 | 33 | if [ -z "$make" ] 34 | then 35 | echo "[e] Cannot compile without make binary" 36 | exit 3 37 | else 38 | echo "[i] make found: $make" 39 | fi 40 | 41 | pkgconfig_path=$(echo $PKG_CONFIG_PATH) 42 | if [ -z "$pkgconfig_path" ] 43 | then 44 | pkgconfig_path="$libntoh_pcpath" 45 | else 46 | pkgconfig_path="$pkgconfig_path:$libntoh_pcpath" 47 | fi 48 | 49 | echo "[i] PKG_CONFIG_PATH set to: $pkgconfig_path" 50 | echo '' 51 | 52 | rm -rf $build_dir 2>/dev/null 53 | mkdir $build_dir 2>/dev/null 54 | cd $build_dir 55 | $cmake ../ 56 | $make 57 | 58 | unset pkgconfig_path build_dir cmake make pkgconfig libntoh_pcpath 59 | exit 0 60 | -------------------------------------------------------------------------------- /examples/c/ipv4/example.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2011, Chema Garcia * 3 | * All rights reserved. * 4 | * * 5 | * Redistribution and use in source and binary forms, with or * 6 | * without modification, are permitted provided that the following * 7 | * conditions are met: * 8 | * * 9 | * * Redistributions of source code must retain the above * 10 | * copyright notice, this list of conditions and the following * 11 | * disclaimer. * 12 | * * 13 | * * Redistributions in binary form must reproduce the above * 14 | * copyright notice, this list of conditions and the following * 15 | * disclaimer in the documentation and/or other materials provided * 16 | * with the distribution. * 17 | * * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 28 | * POSSIBILITY OF SUCH DAMAGE. * 29 | ********************************************************************************/ 30 | 31 | /* 32 | * This example save the data sent by each peer in a separated file called: [src_ip]:[src_port]-[dst_ip]:[dst_port] 33 | */ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #ifndef __FAVOR_BSD 43 | # define __FAVOR_BSD 44 | #endif 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | 51 | #include 52 | #include 53 | 54 | #define RECV_CLIENT 1 55 | #define RECV_SERVER 2 56 | 57 | /* capture handle */ 58 | pcap_t *handle = 0; 59 | pntoh_ipv4_session_t ipv4_session = 0; 60 | 61 | /** 62 | * @brief Exit function (closes the capture handle and releases all resource from libntoh) 63 | */ 64 | void shandler ( int sign ) 65 | { 66 | if ( sign != 0 ) 67 | signal ( sign , &shandler ); 68 | 69 | pcap_close( handle ); 70 | 71 | ntoh_exit(); 72 | 73 | fprintf( stderr, "\n\n[+] Capture finished!\n" ); 74 | exit( sign ); 75 | } 76 | 77 | /** 78 | * @brief Returns the name of a protocol 79 | */ 80 | inline char *get_proto_description ( unsigned short proto ) 81 | { 82 | switch ( proto ) 83 | { 84 | case IPPROTO_ICMP: 85 | return "ICMP"; 86 | 87 | case IPPROTO_TCP: 88 | return "TCP"; 89 | 90 | case IPPROTO_UDP: 91 | return "UDP"; 92 | 93 | case IPPROTO_IGMP: 94 | return "IGMP"; 95 | 96 | case IPPROTO_IPV6: 97 | return "IPv6"; 98 | 99 | case IPPROTO_FRAGMENT: 100 | return "IPv6 Fragment"; 101 | 102 | default: 103 | return "Undefined"; 104 | } 105 | } 106 | 107 | /** 108 | * @brief Sends a IPv4 fragment to libntoh 109 | */ 110 | void send_ipv4_fragment ( struct ip *iphdr , pipv4_dfcallback_t callback ) 111 | { 112 | ntoh_ipv4_tuple4_t ipt4; 113 | pntoh_ipv4_flow_t flow; 114 | int ret; 115 | unsigned int error; 116 | 117 | ntoh_ipv4_get_tuple4 ( iphdr , &ipt4 ); 118 | 119 | if ( !( flow = ntoh_ipv4_find_flow( ipv4_session , &ipt4 ) ) ) 120 | if ( ! (flow = ntoh_ipv4_new_flow( ipv4_session , &ipt4, callback, 0 , &error )) ) 121 | { 122 | fprintf ( stderr , "Error %d: %s" , error , ntoh_get_errdesc ( error ) ); 123 | return; 124 | } 125 | 126 | if ( ( ret = ntoh_ipv4_add_fragment( ipv4_session , flow, iphdr ) ) ) 127 | fprintf( stderr, "\n[e] Error %d adding IPv4: %s", ret, ntoh_get_retval_desc( ret ) ); 128 | 129 | return; 130 | } 131 | 132 | /* IPv4 Callback */ 133 | void ipv4_callback ( pntoh_ipv4_flow_t flow , pntoh_ipv4_tuple4_t tuple , unsigned char *data , size_t len , unsigned short reason ) 134 | { 135 | unsigned int i = 0; 136 | 137 | fprintf( stderr, "\n\n[i] Got an IPv4 datagram! (%s) %s --> ", ntoh_get_reason(reason) , inet_ntoa( *(struct in_addr*) &tuple->source ) ); 138 | fprintf( stderr, "%s | %zu/%zu bytes - Key: %04x - ID: %02x - Proto: %d (%s)\n\n", inet_ntoa( *(struct in_addr*) &tuple->destination ), len, flow->total , flow->key, ntohs( tuple->id ), tuple->protocol, get_proto_description( tuple->protocol ) ); 139 | 140 | for ( i = 0; i < flow->total ; i++ ) 141 | fprintf( stderr, "%02x ", data[i] ); 142 | 143 | fprintf( stderr, "\n" ); 144 | 145 | return; 146 | } 147 | 148 | int main ( int argc , char *argv[] ) 149 | { 150 | /* parameters parsing */ 151 | int c; 152 | 153 | /* pcap */ 154 | char errbuf[PCAP_ERRBUF_SIZE]; 155 | struct bpf_program fp; 156 | char filter_exp[] = "ip"; 157 | char *source = 0; 158 | char *filter = filter_exp; 159 | const unsigned char *packet = 0; 160 | struct pcap_pkthdr header; 161 | 162 | /* packet dissection */ 163 | struct ip *ip; 164 | unsigned int error; 165 | 166 | /* extra */ 167 | unsigned int ipf; 168 | 169 | fprintf( stderr, "\n###########################" ); 170 | fprintf( stderr, "\n# libntoh Example #" ); 171 | fprintf( stderr, "\n# ----------------------- #" ); 172 | fprintf( stderr, "\n# Written by Chema Garcia #" ); 173 | fprintf( stderr, "\n# ----------------------- #" ); 174 | fprintf( stderr, "\n# http://safetybits.net #" ); 175 | fprintf( stderr, "\n# chema@safetybits.net #" ); 176 | fprintf( stderr, "\n###########################\n" ); 177 | 178 | fprintf( stderr, "\n[i] libntoh version: %s\n", ntoh_version() ); 179 | 180 | if ( argc < 3 ) 181 | { 182 | fprintf( stderr, "\n[+] Usage: %s \n", argv[0] ); 183 | fprintf( stderr, "\n+ Options:" ); 184 | fprintf( stderr, "\n\t-i | --iface -----> Interface to read packets from" ); 185 | fprintf( stderr, "\n\t-f | --file ------> File path to read packets from" ); 186 | fprintf( stderr, "\n\t-F | --filter ----> Capture filter (default: \"ip\")\n\n" ); 187 | exit( 1 ); 188 | } 189 | 190 | /* check parameters */ 191 | while ( 1 ) 192 | { 193 | int option_index = 0; 194 | static struct option long_options[] = 195 | { 196 | { "iface" , 1 , 0 , 'i' } , 197 | { "file" , 1 , 0 , 'f' } , 198 | { 0 , 0 , 0 , 0 } }; 199 | 200 | if ( ( c = getopt_long( argc, argv, "i:f:F:", long_options, &option_index ) ) < 0 ) 201 | break; 202 | 203 | switch ( c ) 204 | { 205 | case 'i': 206 | source = optarg; 207 | handle = pcap_open_live( optarg, 65535, 1, 0, errbuf ); 208 | break; 209 | 210 | case 'f': 211 | source = optarg; 212 | handle = pcap_open_offline( optarg, errbuf ); 213 | break; 214 | 215 | case 'F': 216 | filter = optarg; 217 | break; 218 | 219 | } 220 | } 221 | 222 | if ( !handle ) 223 | { 224 | fprintf( stderr, "\n[e] Error loading %s: %s\n", source, errbuf ); 225 | exit( -1 ); 226 | } 227 | 228 | if ( pcap_compile( handle, &fp, filter, 0, 0 ) < 0 ) 229 | { 230 | fprintf( stderr, "\n[e] Error compiling filter \"%s\": %s\n\n", filter, pcap_geterr( handle ) ); 231 | pcap_close( handle ); 232 | exit( -2 ); 233 | } 234 | 235 | if ( pcap_setfilter( handle, &fp ) < 0 ) 236 | { 237 | fprintf( stderr, "\n[e] Cannot set filter \"%s\": %s\n\n", filter, pcap_geterr( handle ) ); 238 | pcap_close( handle ); 239 | exit( -3 ); 240 | } 241 | pcap_freecode( &fp ); 242 | 243 | /* verify datalink */ 244 | if ( pcap_datalink( handle ) != DLT_EN10MB ) 245 | { 246 | fprintf ( stderr , "\n[e] libntoh is independent from link layer, but this example only works with ethernet link layer\n"); 247 | pcap_close ( handle ); 248 | exit ( -4 ); 249 | } 250 | 251 | fprintf( stderr, "\n[i] Source: %s / %s", source, pcap_datalink_val_to_description( pcap_datalink( handle ) ) ); 252 | fprintf( stderr, "\n[i] Filter: %s", filter ); 253 | 254 | signal( SIGINT, &shandler ); 255 | signal( SIGTERM, &shandler ); 256 | 257 | /*******************************************/ 258 | /** libntoh initialization process starts **/ 259 | /*******************************************/ 260 | 261 | ntoh_init (); 262 | 263 | if ( ! (ipv4_session = ntoh_ipv4_new_session ( 0 , 0 , &error )) ) 264 | { 265 | fprintf ( stderr , "\n[e] Error %d creating IPv4 session: %s" , error , ntoh_get_errdesc ( error ) ); 266 | exit ( -6 ); 267 | } 268 | 269 | fprintf ( stderr , "\n[i] Max. IPv4 flows allowed: %d\n\n" , ntoh_ipv4_get_size ( ipv4_session ) ); 270 | 271 | /* capture starts */ 272 | while ( ( packet = pcap_next( handle, &header ) ) != 0 ) 273 | { 274 | /* get packet headers */ 275 | ip = (struct ip*) ( packet + sizeof ( struct ether_header ) ); 276 | if ( (ip->ip_hl * 4 ) < sizeof(struct ip) ) 277 | continue; 278 | 279 | /* it is an IPv4 fragment */ 280 | if ( NTOH_IPV4_IS_FRAGMENT(ip->ip_off) ) 281 | send_ipv4_fragment ( ip , &ipv4_callback ); 282 | } 283 | 284 | /* no flows left */ 285 | if ( ( ipf = ntoh_ipv4_count_flows ( ipv4_session ) ) > 0 ) 286 | { 287 | fprintf( stderr, "\n\n[+] There are currently %i IPv4 flow(s). You can wait them to get closed or press CTRL+C\n" , ipf ); 288 | pause(); 289 | } 290 | 291 | shandler( 0 ); 292 | 293 | //dummy return 294 | return 0; 295 | } 296 | -------------------------------------------------------------------------------- /examples/c/ipv6/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED ( VERSION 2.8 FATAL_ERROR ) 2 | PROJECT ( LIBNTOHEXAMPLE ) 3 | 4 | # find libpthread 5 | FIND_PACKAGE ( Threads REQUIRED ) 6 | 7 | # find pkg-config 8 | FIND_PACKAGE ( PkgConfig REQUIRED ) 9 | 10 | # find libntoh 11 | PKG_CHECK_MODULES ( NTOH REQUIRED ntoh ) 12 | INCLUDE_DIRECTORIES ( ${NTOH_INCLUDE_DIRS} ) 13 | LINK_DIRECTORIES ( ${NTOH_LIBRARY_DIRS} ) 14 | ADD_DEFINITIONS ( ${NTOH_CFLAGS} ) 15 | 16 | SET ( CMAKE_BUILD_TYPE Release ) 17 | 18 | # set source files and flags 19 | SET ( LIBNTOHEXAMPLE_SRCS example.c ) 20 | SET ( CMAKE_C_FLAGS "-Wall -Os -O2 -lpcap -g" ) 21 | 22 | # set target from source 23 | ADD_EXECUTABLE ( ntohexample ${LIBNTOHEXAMPLE_SRCS} ) 24 | TARGET_LINK_LIBRARIES ( ntohexample pcap ntoh ${CMAKE_THREAD_LIBS_INIT}) 25 | -------------------------------------------------------------------------------- /examples/c/ipv6/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # this scripts follows the steps that you 4 | # should follow to compile and link against libntoh: 5 | # 6 | # $ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig 7 | # $ pkg-config --libs --cflags libntoh 8 | # -I/usr/local/include/libntoh -L/usr/local/lib -lntoh 9 | 10 | pkgconfig=$(which pkg-config) 11 | cmake=$(which cmake) 12 | make=$(which make) 13 | pkgconfig_path='' 14 | libntoh_pcpath='/usr/local/lib/pkgconfig' 15 | build_dir='build' 16 | 17 | if [ -z "$pkgconfig" ] 18 | then 19 | echo "[w] pkg-config not found! Good luck compiling..." 20 | exit 1 21 | else 22 | echo "[i] pkg-config found: $pkgconfig" 23 | fi 24 | 25 | if [ -z "$cmake" ] 26 | then 27 | echo "[e] Cannot compile without cmake binary" 28 | exit 2 29 | else 30 | echo "[i] cmake found: $cmake" 31 | fi 32 | 33 | if [ -z "$make" ] 34 | then 35 | echo "[e] Cannot compile without make binary" 36 | exit 3 37 | else 38 | echo "[i] make found: $make" 39 | fi 40 | 41 | pkgconfig_path=$(echo $PKG_CONFIG_PATH) 42 | if [ -z "$pkgconfig_path" ] 43 | then 44 | pkgconfig_path="$libntoh_pcpath" 45 | else 46 | pkgconfig_path="$pkgconfig_path:$libntoh_pcpath" 47 | fi 48 | 49 | echo "[i] PKG_CONFIG_PATH set to: $pkgconfig_path" 50 | echo '' 51 | 52 | rm -rf $build_dir 2>/dev/null 53 | mkdir $build_dir 2>/dev/null 54 | cd $build_dir 55 | $cmake ../ 56 | $make 57 | 58 | unset pkgconfig_path build_dir cmake make pkgconfig libntoh_pcpath 59 | exit 0 60 | -------------------------------------------------------------------------------- /examples/c/ipv6/example.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2014, Chema Garcia * 3 | * All rights reserved. * 4 | * * 5 | * Redistribution and use in source and binary forms, with or * 6 | * without modification, are permitted provided that the following * 7 | * conditions are met: * 8 | * * 9 | * * Redistributions of source code must retain the above * 10 | * copyright notice, this list of conditions and the following * 11 | * disclaimer. * 12 | * * 13 | * * Redistributions in binary form must reproduce the above * 14 | * copyright notice, this list of conditions and the following * 15 | * disclaimer in the documentation and/or other materials provided * 16 | * with the distribution. * 17 | * * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 28 | * POSSIBILITY OF SUCH DAMAGE. * 29 | ********************************************************************************/ 30 | 31 | /* 32 | * This example defragments IPv6 datagrams and once it's completed shows the hex values of the final IPv6 header and data 33 | */ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #ifndef __FAVOR_BSD 48 | # define __FAVOR_BSD 49 | #endif 50 | 51 | #include 52 | #include 53 | #include 54 | #include 55 | 56 | #include 57 | #include 58 | 59 | #define RECV_CLIENT 1 60 | #define RECV_SERVER 2 61 | 62 | /* capture handle */ 63 | pcap_t *handle = 0; 64 | pntoh_ipv6_session_t ipv6_session = 0; 65 | unsigned short receive = 0; 66 | 67 | /** 68 | * @brief Exit function (closes the capture handle and releases all resource from libntoh) 69 | */ 70 | void shandler ( int sign ) 71 | { 72 | if ( sign != 0 ) 73 | signal ( sign , &shandler ); 74 | 75 | pcap_close( handle ); 76 | 77 | ntoh_exit(); 78 | 79 | fprintf( stderr, "\n\n[+] Capture finished!\n" ); 80 | exit( sign ); 81 | } 82 | 83 | /** 84 | * @brief Returns the name of a protocol 85 | */ 86 | inline char *get_proto_description ( unsigned short proto ) 87 | { 88 | switch ( proto ) 89 | { 90 | case IPPROTO_ICMP: 91 | return "ICMP"; 92 | 93 | case IPPROTO_TCP: 94 | return "TCP"; 95 | 96 | case IPPROTO_UDP: 97 | return "UDP"; 98 | 99 | case IPPROTO_IGMP: 100 | return "IGMP"; 101 | 102 | case IPPROTO_IPV6: 103 | return "IPv6"; 104 | 105 | case IPPROTO_FRAGMENT: 106 | return "IPv6 Fragment"; 107 | 108 | default: 109 | return "Undefined"; 110 | } 111 | } 112 | 113 | /** 114 | * @brief Sends a IPv6 fragment to libntoh 115 | */ 116 | void send_ipv6_fragment ( struct ip6_hdr *iphdr , pipv6_dfcallback_t callback ) 117 | { 118 | ntoh_ipv6_tuple4_t ipt4; 119 | pntoh_ipv6_flow_t flow; 120 | int ret; 121 | unsigned int error; 122 | 123 | ntoh_ipv6_get_tuple4 ( iphdr , &ipt4 ); 124 | 125 | if ( ! ( flow = ntoh_ipv6_find_flow( ipv6_session , &ipt4 ) ) ) 126 | if ( ! (flow = ntoh_ipv6_new_flow( ipv6_session , &ipt4, callback, 0 , &error )) ) 127 | { 128 | fprintf ( stderr , "\n[e] Error %d creating new IPv6 flow: %s" , error , ntoh_get_errdesc ( error ) ); 129 | return; 130 | } 131 | 132 | if ( ( ret = ntoh_ipv6_add_fragment( ipv6_session , flow, iphdr ) ) != NTOH_OK ) 133 | fprintf( stderr, "\n[e] Error %d adding IPv6: %s", ret, ntoh_get_retval_desc( ret ) ); 134 | 135 | return; 136 | } 137 | 138 | /* IPv6 Callback */ 139 | void ipv6_callback ( pntoh_ipv6_flow_t flow , pntoh_ipv6_tuple4_t tuple , unsigned char *data , size_t len , unsigned short reason ) 140 | { 141 | unsigned int i = 0; 142 | char src[INET6_ADDRSTRLEN] = {0}; 143 | char dst[INET6_ADDRSTRLEN] = {0}; 144 | 145 | inet_ntop ( AF_INET6 , (void*) &tuple->source , src , INET6_ADDRSTRLEN ); 146 | inet_ntop ( AF_INET6 , (void*) &tuple->destination , src , INET6_ADDRSTRLEN ); 147 | 148 | fprintf( stderr, "\n\n[i] Got an IPv6 datagram! (%s - %d) %s --> ", ntoh_get_reason(reason) , reason , src ); 149 | fprintf( stderr, "%s | %zu/%zu bytes - Key: %04x - ID: %02x - Proto: %d (%s)\n\n", dst , len, flow->total , flow->key, ntohs( tuple->id ), tuple->protocol, get_proto_description( tuple->protocol ) ); 150 | 151 | for ( i = 0; i < flow->total ; i++ ) 152 | fprintf( stderr, "%02x ", data[i] ); 153 | 154 | fprintf( stderr, "\n" ); 155 | 156 | return; 157 | } 158 | 159 | int main ( int argc , char *argv[] ) 160 | { 161 | /* parameters parsing */ 162 | int c; 163 | 164 | /* pcap */ 165 | char errbuf[PCAP_ERRBUF_SIZE]; 166 | struct bpf_program fp; 167 | char filter_exp[] = "ip6"; 168 | char *source = 0; 169 | char *filter = filter_exp; 170 | const unsigned char *packet = 0; 171 | struct pcap_pkthdr header; 172 | 173 | /* packet dissection */ 174 | struct ip6_hdr *ip; 175 | unsigned int error; 176 | 177 | /* extra */ 178 | unsigned int ipf; 179 | 180 | fprintf( stderr, "\n###########################" ); 181 | fprintf( stderr, "\n# libntoh Example #" ); 182 | fprintf( stderr, "\n# ----------------------- #" ); 183 | fprintf( stderr, "\n# Written by Chema Garcia #" ); 184 | fprintf( stderr, "\n# ----------------------- #" ); 185 | fprintf( stderr, "\n# http://safetybits.net #" ); 186 | fprintf( stderr, "\n# chema@safetybits.net #" ); 187 | fprintf( stderr, "\n###########################\n" ); 188 | 189 | fprintf( stderr, "\n[i] libntoh version: %s\n", ntoh_version() ); 190 | 191 | if ( argc < 3 ) 192 | { 193 | fprintf( stderr, "\n[+] Usage: %s \n", argv[0] ); 194 | fprintf( stderr, "\n+ Options:" ); 195 | fprintf( stderr, "\n\t-i | --iface -----> Interface to read packets from" ); 196 | fprintf( stderr, "\n\t-f | --file ------> File path to read packets from" ); 197 | fprintf( stderr, "\n\t-F | --filter ----> Capture filter (default \"ipv6\")" ); 198 | fprintf( stderr, "\n\t-c | --client ----------> Receive client data"); 199 | fprintf( stderr, "\n\t-s | --server ----------> Receive server data\n\n"); 200 | exit( 1 ); 201 | } 202 | 203 | /* check parameters */ 204 | while ( 1 ) 205 | { 206 | int option_index = 0; 207 | static struct option long_options[] = 208 | { 209 | { "iface" , 1 , 0 , 'i' } , 210 | { "file" , 1 , 0 , 'f' } , 211 | { "filter" , 1 , 0 , 'F' } , 212 | { "client" , 0 , 0 , 'c' }, 213 | { "server" , 0 , 0 , 's' }, 214 | { 0 , 0 , 0 , 0 } }; 215 | 216 | if ( ( c = getopt_long( argc, argv, "i:f:F:cs", long_options, &option_index ) ) < 0 ) 217 | break; 218 | 219 | switch ( c ) 220 | { 221 | case 'i': 222 | source = optarg; 223 | handle = pcap_open_live( optarg, 65535, 1, 0, errbuf ); 224 | break; 225 | 226 | case 'f': 227 | source = optarg; 228 | handle = pcap_open_offline( optarg, errbuf ); 229 | break; 230 | 231 | case 'F': 232 | filter = optarg; 233 | break; 234 | 235 | case 'c': 236 | receive |= RECV_CLIENT; 237 | break; 238 | 239 | case 's': 240 | receive |= RECV_SERVER; 241 | break; 242 | } 243 | } 244 | 245 | if ( !receive ) 246 | receive = (RECV_CLIENT | RECV_SERVER); 247 | 248 | if ( !handle ) 249 | { 250 | fprintf( stderr, "\n[e] Error loading %s: %s\n", source, errbuf ); 251 | exit( -1 ); 252 | } 253 | 254 | if ( pcap_compile( handle, &fp, filter, 0, 0 ) < 0 ) 255 | { 256 | fprintf( stderr, "\n[e] Error compiling filter \"%s\": %s\n\n", filter, pcap_geterr( handle ) ); 257 | pcap_close( handle ); 258 | exit( -2 ); 259 | } 260 | 261 | if ( pcap_setfilter( handle, &fp ) < 0 ) 262 | { 263 | fprintf( stderr, "\n[e] Cannot set filter \"%s\": %s\n\n", filter, pcap_geterr( handle ) ); 264 | pcap_close( handle ); 265 | exit( -3 ); 266 | } 267 | pcap_freecode( &fp ); 268 | 269 | /* verify datalink */ 270 | if ( pcap_datalink( handle ) != DLT_EN10MB ) 271 | { 272 | fprintf ( stderr , "\n[e] libntoh is independent from link layer, but this example only works with ethernet link layer\n"); 273 | pcap_close ( handle ); 274 | exit ( -4 ); 275 | } 276 | 277 | fprintf( stderr, "\n[i] Source: %s / %s", source, pcap_datalink_val_to_description( pcap_datalink( handle ) ) ); 278 | fprintf( stderr, "\n[i] Filter: %s", filter ); 279 | 280 | fprintf( stderr, "\n[i] Receive data from client: "); 281 | if ( receive & RECV_CLIENT ) 282 | fprintf( stderr , "Yes"); 283 | else 284 | fprintf( stderr , "No"); 285 | 286 | fprintf( stderr, "\n[i] Receive data from server: "); 287 | if ( receive & RECV_SERVER ) 288 | fprintf( stderr , "Yes"); 289 | else 290 | fprintf( stderr , "No"); 291 | 292 | signal( SIGINT, &shandler ); 293 | signal( SIGTERM, &shandler ); 294 | 295 | /*******************************************/ 296 | /** libntoh initialization process starts **/ 297 | /*******************************************/ 298 | 299 | ntoh_ipv6_init (); 300 | 301 | if ( ! (ipv6_session = ntoh_ipv6_new_session ( 0 , 0 , &error )) ) 302 | { 303 | fprintf ( stderr , "\n[e] Error %d creating IPv6 session: %s" , error , ntoh_get_errdesc ( error ) ); 304 | exit ( -6 ); 305 | } 306 | 307 | fprintf ( stderr , "\n[i] Max. IPv6 flows allowed: %d\n\n" , ntoh_ipv6_get_size ( ipv6_session ) ); 308 | 309 | /* capture starts */ 310 | while ( ( packet = pcap_next( handle, &header ) ) != 0 ) 311 | { 312 | /* get packet headers */ 313 | ip = (struct ip6_hdr*) ( packet + sizeof ( struct ether_header ) ); 314 | 315 | /* it is an IPv6 fragment */ 316 | if ( NTOH_IPV6_IS_FRAGMENT(ip) ) 317 | send_ipv6_fragment ( ip , &ipv6_callback ); 318 | } 319 | 320 | ipf = ntoh_ipv6_count_flows ( ipv6_session ); 321 | 322 | /* no streams left */ 323 | if ( ipf > 0 ) 324 | { 325 | fprintf( stderr, "\n\n[+] There are currently %i IPv6 flow(s). You can wait them to get closed or press CTRL+C\n" , ipf ); 326 | pause(); 327 | } 328 | 329 | shandler( 0 ); 330 | 331 | //dummy return 332 | return 0; 333 | } 334 | -------------------------------------------------------------------------------- /examples/c/tcp_ipv4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED ( VERSION 2.8 FATAL_ERROR ) 2 | PROJECT ( LIBNTOHEXAMPLE ) 3 | 4 | # find libpthread 5 | FIND_PACKAGE ( Threads REQUIRED ) 6 | 7 | # find pkg-config 8 | FIND_PACKAGE ( PkgConfig REQUIRED ) 9 | 10 | # find libntoh 11 | PKG_CHECK_MODULES ( NTOH REQUIRED ntoh ) 12 | INCLUDE_DIRECTORIES ( ${NTOH_INCLUDE_DIRS} ) 13 | LINK_DIRECTORIES ( ${NTOH_LIBRARY_DIRS} ) 14 | ADD_DEFINITIONS ( ${NTOH_CFLAGS} ) 15 | 16 | SET ( CMAKE_BUILD_TYPE Release ) 17 | 18 | # set source files and flags 19 | SET ( LIBNTOHEXAMPLE_SRCS example.c ) 20 | SET ( CMAKE_C_FLAGS "-Wall -Os -O2 -lpcap -g" ) 21 | 22 | # set target from source 23 | ADD_EXECUTABLE ( ntohexample ${LIBNTOHEXAMPLE_SRCS} ) 24 | TARGET_LINK_LIBRARIES ( ntohexample pcap ntoh ${CMAKE_THREAD_LIBS_INIT}) 25 | -------------------------------------------------------------------------------- /examples/c/tcp_ipv4/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # this scripts follows the steps that you 4 | # should follow to compile and link against libntoh: 5 | # 6 | # $ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig 7 | # $ pkg-config --libs --cflags libntoh 8 | # -I/usr/local/include/libntoh -L/usr/local/lib -lntoh 9 | 10 | pkgconfig=$(which pkg-config) 11 | cmake=$(which cmake) 12 | make=$(which make) 13 | pkgconfig_path='' 14 | libntoh_pcpath='/usr/local/lib/pkgconfig' 15 | build_dir='build' 16 | 17 | if [ -z "$pkgconfig" ] 18 | then 19 | echo "[w] pkg-config not found! Good luck compiling..." 20 | exit 1 21 | else 22 | echo "[i] pkg-config found: $pkgconfig" 23 | fi 24 | 25 | if [ -z "$cmake" ] 26 | then 27 | echo "[e] Cannot compile without cmake binary" 28 | exit 2 29 | else 30 | echo "[i] cmake found: $cmake" 31 | fi 32 | 33 | if [ -z "$make" ] 34 | then 35 | echo "[e] Cannot compile without make binary" 36 | exit 3 37 | else 38 | echo "[i] make found: $make" 39 | fi 40 | 41 | pkgconfig_path=$(echo $PKG_CONFIG_PATH) 42 | if [ -z "$pkgconfig_path" ] 43 | then 44 | pkgconfig_path="$libntoh_pcpath" 45 | else 46 | pkgconfig_path="$pkgconfig_path:$libntoh_pcpath" 47 | fi 48 | 49 | echo "[i] PKG_CONFIG_PATH set to: $pkgconfig_path" 50 | echo '' 51 | 52 | rm -rf $build_dir 2>/dev/null 53 | mkdir $build_dir 2>/dev/null 54 | cd $build_dir 55 | $cmake ../ 56 | $make 57 | 58 | unset pkgconfig_path build_dir cmake make pkgconfig libntoh_pcpath 59 | exit 0 60 | -------------------------------------------------------------------------------- /examples/c/tcp_ipv4/example.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2011, Chema Garcia * 3 | * All rights reserved. * 4 | * * 5 | * Redistribution and use in source and binary forms, with or * 6 | * without modification, are permitted provided that the following * 7 | * conditions are met: * 8 | * * 9 | * * Redistributions of source code must retain the above * 10 | * copyright notice, this list of conditions and the following * 11 | * disclaimer. * 12 | * * 13 | * * Redistributions in binary form must reproduce the above * 14 | * copyright notice, this list of conditions and the following * 15 | * disclaimer in the documentation and/or other materials provided * 16 | * with the distribution. * 17 | * * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 28 | * POSSIBILITY OF SUCH DAMAGE. * 29 | ********************************************************************************/ 30 | 31 | /* 32 | * This example save the data sent by each peer in a separated file called: [src_ip]:[src_port]-[dst_ip]:[dst_port] 33 | */ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #ifndef __FAVOR_BSD 48 | # define __FAVOR_BSD 49 | #endif 50 | 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | #include 58 | #include 59 | 60 | typedef struct 61 | { 62 | unsigned char *data; 63 | size_t data_len; 64 | char *path; 65 | } peer_info_t , *ppeer_info_t; 66 | 67 | #define RECV_CLIENT 1 68 | #define RECV_SERVER 2 69 | 70 | /* capture handle */ 71 | pcap_t *handle = 0; 72 | pntoh_tcp_session_t tcp_session = 0; 73 | pntoh_ipv4_session_t ipv4_session = 0; 74 | unsigned short receive = 0; 75 | 76 | /** 77 | * @brief Exit function (closes the capture handle and releases all resource from libntoh) 78 | */ 79 | void shandler ( int sign ) 80 | { 81 | if ( sign != 0 ) 82 | signal ( sign , &shandler ); 83 | 84 | pcap_close( handle ); 85 | 86 | ntoh_exit(); 87 | 88 | fprintf( stderr, "\n\n[+] Capture finished!\n" ); 89 | exit( sign ); 90 | } 91 | 92 | /** 93 | * @brief Returns a struct which stores some peer information 94 | */ 95 | ppeer_info_t get_peer_info ( unsigned char *payload , size_t payload_len , pntoh_tcp_tuple5_t tuple ) 96 | { 97 | ppeer_info_t ret = 0; 98 | size_t len = 0; 99 | char path[1024] = {0}; 100 | 101 | /* gets peer information */ 102 | ret = (ppeer_info_t) calloc ( 1 , sizeof ( peer_info_t ) ); 103 | ret->data_len = payload_len; 104 | ret->data = (unsigned char*) calloc ( ret->data_len , sizeof ( unsigned char ) ); 105 | memcpy ( ret->data , payload , ret->data_len ); 106 | 107 | snprintf ( path , sizeof(path) , "%s:%d-" , inet_ntoa ( *(struct in_addr*)&(tuple->source) ) , ntohs(tuple->sport) ); 108 | len = strlen(path); 109 | snprintf ( &path[len] , sizeof(path) - len, "%s:%d" , inet_ntoa ( *(struct in_addr*)&(tuple->destination) ) , ntohs(tuple->dport) ); 110 | 111 | ret->path = strndup ( path , sizeof(path) ); 112 | 113 | return ret; 114 | } 115 | 116 | /** 117 | * @brief Frees the ppeer_info_t struct 118 | */ 119 | void free_peer_info ( ppeer_info_t pinfo ) 120 | { 121 | /* free peer info data */ 122 | if ( ! pinfo ) 123 | return; 124 | 125 | free ( pinfo->data ); 126 | free ( pinfo->path ); 127 | free ( pinfo ); 128 | 129 | return; 130 | } 131 | 132 | /** 133 | * @brief Returns the name of a protocol 134 | */ 135 | inline char *get_proto_description ( unsigned short proto ) 136 | { 137 | switch ( proto ) 138 | { 139 | case IPPROTO_ICMP: 140 | return "ICMP"; 141 | 142 | case IPPROTO_TCP: 143 | return "TCP"; 144 | 145 | case IPPROTO_UDP: 146 | return "UDP"; 147 | 148 | case IPPROTO_IGMP: 149 | return "IGMP"; 150 | 151 | case IPPROTO_IPV6: 152 | return "IPv6"; 153 | 154 | case IPPROTO_FRAGMENT: 155 | return "IPv6 Fragment"; 156 | 157 | default: 158 | return "Undefined"; 159 | } 160 | } 161 | 162 | /** 163 | * @brief Writes the ppeer_info_t data field to disk 164 | */ 165 | void write_data ( ppeer_info_t info ) 166 | { 167 | int fd = 0; 168 | 169 | if ( !info ) 170 | return; 171 | 172 | if ( (fd = open ( info->path , O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW , S_IRWXU | S_IRWXG | S_IRWXO )) < 0 ) 173 | { 174 | fprintf ( stderr , "\n[e] Error %d writting data to \"%s\": %s" , errno , info->path , strerror( errno ) ); 175 | return; 176 | } 177 | 178 | write ( fd , info->data , info->data_len ); 179 | close ( fd ); 180 | 181 | return; 182 | } 183 | 184 | /** 185 | * @brief Send a TCP segment to libntoh 186 | */ 187 | void send_tcp_segment ( struct ip *iphdr , pntoh_tcp_callback_t callback ) 188 | { 189 | ppeer_info_t pinfo; 190 | ntoh_tcp_tuple5_t tcpt5; 191 | pntoh_tcp_stream_t stream; 192 | struct tcphdr *tcp; 193 | size_t size_ip; 194 | size_t total_len; 195 | size_t size_tcp; 196 | size_t size_payload; 197 | unsigned char *payload; 198 | int ret; 199 | unsigned int error; 200 | 201 | size_ip = iphdr->ip_hl * 4; 202 | total_len = ntohs( iphdr->ip_len ); 203 | 204 | tcp = (struct tcphdr*)((unsigned char*)iphdr + size_ip); 205 | if ( (size_tcp = tcp->th_off * 4) < sizeof(struct tcphdr) ) 206 | return; 207 | 208 | payload = (unsigned char *)iphdr + size_ip + size_tcp; 209 | size_payload = total_len - ( size_ip + size_tcp ); 210 | 211 | ntoh_tcp_get_tuple5 ( (void*)iphdr , tcp , &tcpt5 ); 212 | 213 | /* find the stream or creates a new one */ 214 | if ( !( stream = ntoh_tcp_find_stream( tcp_session , &tcpt5 ) ) ) 215 | if ( ! ( stream = ntoh_tcp_new_stream( tcp_session , &tcpt5, callback , 0 , &error , 1 , 1 ) ) ) 216 | { 217 | fprintf ( stderr , "\n[e] Error %d creating new stream: %s" , error , ntoh_get_errdesc ( error ) ); 218 | return; 219 | } 220 | 221 | if ( size_payload > 0 ) 222 | pinfo = get_peer_info ( payload , size_payload , &tcpt5 ); 223 | else 224 | pinfo = 0; 225 | 226 | /* add this segment to the stream */ 227 | switch ( ( ret = ntoh_tcp_add_segment( tcp_session , stream, (void*)iphdr, total_len, (void*)pinfo ) ) ) 228 | { 229 | case NTOH_OK: 230 | break; 231 | 232 | case NTOH_SYNCHRONIZING: 233 | free_peer_info ( pinfo ); 234 | break; 235 | 236 | default: 237 | fprintf( stderr, "\n[e] Error %d adding segment: %s", ret, ntoh_get_retval_desc( ret ) ); 238 | free_peer_info ( pinfo ); 239 | break; 240 | } 241 | 242 | return; 243 | } 244 | 245 | /** 246 | * @brief Sends a IPv4 fragment to libntoh 247 | */ 248 | void send_ipv4_fragment ( struct ip *iphdr , pipv4_dfcallback_t callback ) 249 | { 250 | ntoh_ipv4_tuple4_t ipt4; 251 | pntoh_ipv4_flow_t flow; 252 | int ret; 253 | unsigned int error; 254 | 255 | ntoh_ipv4_get_tuple4 ( iphdr , &ipt4 ); 256 | 257 | if ( !( flow = ntoh_ipv4_find_flow( ipv4_session , &ipt4 ) ) ) 258 | if ( ! (flow = ntoh_ipv4_new_flow( ipv4_session , &ipt4, callback, 0 , &error )) ) 259 | { 260 | fprintf ( stderr , "\n[e] Error %d creating new IPv4 flow: %s" , error , ntoh_get_errdesc ( error ) ); 261 | return; 262 | } 263 | 264 | if ( ( ret = ntoh_ipv4_add_fragment( ipv4_session , flow, iphdr ) ) ) 265 | fprintf( stderr, "\n[e] Error %d adding IPv4: %s", ret, ntoh_get_retval_desc( ret ) ); 266 | 267 | return; 268 | } 269 | 270 | /* TCP Callback */ 271 | void tcp_callback ( pntoh_tcp_stream_t stream , pntoh_tcp_peer_t orig , pntoh_tcp_peer_t dest , pntoh_tcp_segment_t seg , int reason , int extra ) 272 | { 273 | /* receive data only from the peer given by the user */ 274 | if ( receive == RECV_CLIENT && stream->server.receive ) 275 | { 276 | stream->server.receive = 0; 277 | return; 278 | }else if ( receive == RECV_SERVER && stream->client.receive ) 279 | { 280 | stream->client.receive = 0; 281 | return; 282 | } 283 | 284 | fprintf ( stderr , "\n[%s] %s:%d (%s | Window: %lu) ---> " , ntoh_tcp_get_status ( stream->status ) , inet_ntoa( *(struct in_addr*) &orig->addr ) , ntohs(orig->port) , ntoh_tcp_get_status ( orig->status ) , orig->totalwin ); 285 | fprintf ( stderr , "%s:%d (%s | Window: %lu)\n\t" , inet_ntoa( *(struct in_addr*) &dest->addr ) , ntohs(dest->port) , ntoh_tcp_get_status ( dest->status ) , dest->totalwin ); 286 | 287 | if ( seg != 0 ) 288 | fprintf ( stderr , "SEQ: %lu ACK: %lu Next SEQ: %lu" , seg->seq , seg->ack , orig->next_seq ); 289 | 290 | switch ( reason ) 291 | { 292 | /* Data segment */ 293 | case NTOH_REASON_DATA: 294 | fprintf ( stderr , " | Data segment | Bytes: %i" , seg->payload_len ); 295 | 296 | /* write data */ 297 | write_data( (ppeer_info_t) seg->user_data ); 298 | 299 | if ( extra != 0 ) 300 | fprintf ( stderr , " - %s" , ntoh_get_reason ( extra ) ); 301 | 302 | break; 303 | 304 | default: 305 | switch ( extra ) 306 | { 307 | case NTOH_REASON_MAX_SYN_RETRIES_REACHED: 308 | case NTOH_REASON_MAX_SYNACK_RETRIES_REACHED: 309 | case NTOH_REASON_HSFAILED: 310 | case NTOH_REASON_EXIT: 311 | case NTOH_REASON_TIMEDOUT: 312 | case NTOH_REASON_CLOSED: 313 | if ( extra == NTOH_REASON_CLOSED ) 314 | fprintf ( stderr , "\n\t+ Connection closed by %s (%s)" , stream->closedby == NTOH_CLOSEDBY_CLIENT ? "Client" : "Server" , inet_ntoa( *(struct in_addr*) &(stream->client.addr) ) ); 315 | else 316 | fprintf ( stderr , "\n\t+ %s/%s - %s" , ntoh_get_reason ( reason ) , ntoh_get_reason ( extra ) , ntoh_tcp_get_status ( stream->status ) ); 317 | 318 | break; 319 | 320 | default: 321 | break; 322 | } 323 | break; 324 | } 325 | 326 | if ( seg != 0 ) 327 | free_peer_info ( (ppeer_info_t) seg->user_data ); 328 | 329 | fprintf ( stderr , "\n" ); 330 | 331 | return; 332 | } 333 | 334 | /* IPv4 Callback */ 335 | void ipv4_callback ( pntoh_ipv4_flow_t flow , pntoh_ipv4_tuple4_t tuple , unsigned char *data , size_t len , unsigned short reason ) 336 | { 337 | unsigned int i = 0; 338 | 339 | fprintf( stderr, "\n\n[i] Got an IPv4 datagram! (%s) %s --> ", ntoh_get_reason(reason) , inet_ntoa( *(struct in_addr*) &tuple->source ) ); 340 | fprintf( stderr, "%s | %zu/%zu bytes - Key: %04x - ID: %02x - Proto: %d (%s)\n\n", inet_ntoa( *(struct in_addr*) &tuple->destination ), len, flow->total , flow->key, ntohs( tuple->id ), tuple->protocol, get_proto_description( tuple->protocol ) ); 341 | 342 | if ( tuple->protocol == IPPROTO_TCP ) 343 | send_tcp_segment ( (struct ip*) data , &tcp_callback ); 344 | else 345 | for ( i = 0; i < flow->total ; i++ ) 346 | fprintf( stderr, "%02x ", data[i] ); 347 | 348 | fprintf( stderr, "\n" ); 349 | 350 | return; 351 | } 352 | 353 | int main ( int argc , char *argv[] ) 354 | { 355 | /* parameters parsing */ 356 | int c; 357 | 358 | /* pcap */ 359 | char errbuf[PCAP_ERRBUF_SIZE]; 360 | struct bpf_program fp; 361 | char filter_exp[] = "ip and tcp"; 362 | char *source = 0; 363 | char *filter = filter_exp; 364 | const unsigned char *packet = 0; 365 | struct pcap_pkthdr header; 366 | 367 | /* packet dissection */ 368 | struct ip *ip; 369 | unsigned int error; 370 | 371 | /* extra */ 372 | unsigned int ipf,tcps; 373 | 374 | fprintf( stderr, "\n###########################" ); 375 | fprintf( stderr, "\n# libntoh Example #" ); 376 | fprintf( stderr, "\n# ----------------------- #" ); 377 | fprintf( stderr, "\n# Written by Chema Garcia #" ); 378 | fprintf( stderr, "\n# ----------------------- #" ); 379 | fprintf( stderr, "\n# http://safetybits.net #" ); 380 | fprintf( stderr, "\n# chema@safetybits.net #" ); 381 | fprintf( stderr, "\n###########################\n" ); 382 | 383 | fprintf( stderr, "\n[i] libntoh version: %s\n", ntoh_version() ); 384 | 385 | if ( argc < 3 ) 386 | { 387 | fprintf( stderr, "\n[+] Usage: %s \n", argv[0] ); 388 | fprintf( stderr, "\n+ Options:" ); 389 | fprintf( stderr, "\n\t-i | --iface -----> Interface to read packets from" ); 390 | fprintf( stderr, "\n\t-f | --file ------> File path to read packets from" ); 391 | fprintf( stderr, "\n\t-F | --filter ----> Capture filter (default: \"ip and tcp\")" ); 392 | fprintf( stderr, "\n\t-c | --client ----------> Receive client data"); 393 | fprintf( stderr, "\n\t-s | --server ----------> Receive server data\n\n"); 394 | exit( 1 ); 395 | } 396 | 397 | /* check parameters */ 398 | while ( 1 ) 399 | { 400 | int option_index = 0; 401 | static struct option long_options[] = 402 | { 403 | { "iface" , 1 , 0 , 'i' } , 404 | { "file" , 1 , 0 , 'f' } , 405 | { "filter" , 1 , 0 , 'F' } , 406 | { "client" , 0 , 0 , 'c' }, 407 | { "server" , 0 , 0 , 's' }, 408 | { 0 , 0 , 0 , 0 } }; 409 | 410 | if ( ( c = getopt_long( argc, argv, "i:f:F:cs", long_options, &option_index ) ) < 0 ) 411 | break; 412 | 413 | switch ( c ) 414 | { 415 | case 'i': 416 | source = optarg; 417 | handle = pcap_open_live( optarg, 65535, 1, 0, errbuf ); 418 | break; 419 | 420 | case 'f': 421 | source = optarg; 422 | handle = pcap_open_offline( optarg, errbuf ); 423 | break; 424 | 425 | case 'F': 426 | filter = optarg; 427 | break; 428 | 429 | case 'c': 430 | receive |= RECV_CLIENT; 431 | break; 432 | 433 | case 's': 434 | receive |= RECV_SERVER; 435 | break; 436 | } 437 | } 438 | 439 | if ( !receive ) 440 | receive = (RECV_CLIENT | RECV_SERVER); 441 | 442 | if ( !handle ) 443 | { 444 | fprintf( stderr, "\n[e] Error loading %s: %s\n", source, errbuf ); 445 | exit( -1 ); 446 | } 447 | 448 | if ( pcap_compile( handle, &fp, filter, 0, 0 ) < 0 ) 449 | { 450 | fprintf( stderr, "\n[e] Error compiling filter \"%s\": %s\n\n", filter, pcap_geterr( handle ) ); 451 | pcap_close( handle ); 452 | exit( -2 ); 453 | } 454 | 455 | if ( pcap_setfilter( handle, &fp ) < 0 ) 456 | { 457 | fprintf( stderr, "\n[e] Cannot set filter \"%s\": %s\n\n", filter, pcap_geterr( handle ) ); 458 | pcap_close( handle ); 459 | exit( -3 ); 460 | } 461 | pcap_freecode( &fp ); 462 | 463 | /* verify datalink */ 464 | if ( pcap_datalink( handle ) != DLT_EN10MB ) 465 | { 466 | fprintf ( stderr , "\n[e] libntoh is independent from link layer, but this example only works with ethernet link layer\n"); 467 | pcap_close ( handle ); 468 | exit ( -4 ); 469 | } 470 | 471 | fprintf( stderr, "\n[i] Source: %s / %s", source, pcap_datalink_val_to_description( pcap_datalink( handle ) ) ); 472 | fprintf( stderr, "\n[i] Filter: %s", filter ); 473 | 474 | fprintf( stderr, "\n[i] Receive data from client: "); 475 | if ( receive & RECV_CLIENT ) 476 | fprintf( stderr , "Yes"); 477 | else 478 | fprintf( stderr , "No"); 479 | 480 | fprintf( stderr, "\n[i] Receive data from server: "); 481 | if ( receive & RECV_SERVER ) 482 | fprintf( stderr , "Yes"); 483 | else 484 | fprintf( stderr , "No"); 485 | 486 | signal( SIGINT, &shandler ); 487 | signal( SIGTERM, &shandler ); 488 | 489 | /*******************************************/ 490 | /** libntoh initialization process starts **/ 491 | /*******************************************/ 492 | 493 | ntoh_init (); 494 | 495 | if ( ! (tcp_session = ntoh_tcp_new_session ( 0 , 0 , &error ) ) ) 496 | { 497 | fprintf ( stderr , "\n[e] Error %d creating TCP session: %s" , error , ntoh_get_errdesc ( error ) ); 498 | exit ( -5 ); 499 | } 500 | 501 | fprintf ( stderr , "\n[i] Max. TCP streams allowed: %d" , ntoh_tcp_get_size ( tcp_session ) ); 502 | 503 | if ( ! (ipv4_session = ntoh_ipv4_new_session ( 0 , 0 , &error )) ) 504 | { 505 | ntoh_tcp_free_session ( tcp_session ); 506 | fprintf ( stderr , "\n[e] Error %d creating IPv4 session: %s" , error , ntoh_get_errdesc ( error ) ); 507 | exit ( -6 ); 508 | } 509 | 510 | fprintf ( stderr , "\n[i] Max. IPv4 flows allowed: %d\n\n" , ntoh_ipv4_get_size ( ipv4_session ) ); 511 | 512 | /* capture starts */ 513 | while ( ( packet = pcap_next( handle, &header ) ) != 0 ) 514 | { 515 | /* get packet headers */ 516 | ip = (struct ip*) ( packet + sizeof ( struct ether_header ) ); 517 | if ( (ip->ip_hl * 4 ) < sizeof(struct ip) ) 518 | continue; 519 | 520 | /* it is an IPv4 fragment */ 521 | if ( NTOH_IPV4_IS_FRAGMENT(ip->ip_off) ) 522 | send_ipv4_fragment ( ip , &ipv4_callback ); 523 | /* or a TCP segment */ 524 | else if ( ip->ip_p == IPPROTO_TCP ) 525 | send_tcp_segment ( ip , &tcp_callback ); 526 | } 527 | 528 | tcps = ntoh_tcp_count_streams( tcp_session ); 529 | ipf = ntoh_ipv4_count_flows ( ipv4_session ); 530 | 531 | /* no streams left */ 532 | if ( ipf + tcps > 0 ) 533 | { 534 | fprintf( stderr, "\n\n[+] There are currently %i stored TCP stream(s) and %i IPv4 flow(s). You can wait them to get closed or press CTRL+C\n" , tcps , ipf ); 535 | pause(); 536 | } 537 | 538 | shandler( 0 ); 539 | 540 | //dummy return 541 | return 0; 542 | } 543 | -------------------------------------------------------------------------------- /examples/c/tcp_ipv6/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED ( VERSION 2.8 FATAL_ERROR ) 2 | PROJECT ( LIBNTOHEXAMPLE ) 3 | 4 | # find libpthread 5 | FIND_PACKAGE ( Threads REQUIRED ) 6 | 7 | # find pkg-config 8 | FIND_PACKAGE ( PkgConfig REQUIRED ) 9 | 10 | # find libntoh 11 | PKG_CHECK_MODULES ( NTOH REQUIRED ntoh ) 12 | INCLUDE_DIRECTORIES ( ${NTOH_INCLUDE_DIRS} ) 13 | LINK_DIRECTORIES ( ${NTOH_LIBRARY_DIRS} ) 14 | ADD_DEFINITIONS ( ${NTOH_CFLAGS} ) 15 | 16 | SET ( CMAKE_BUILD_TYPE Release ) 17 | 18 | # set source files and flags 19 | SET ( LIBNTOHEXAMPLE_SRCS example.c ) 20 | SET ( CMAKE_C_FLAGS "-Wall -Os -O2 -lpcap -g" ) 21 | 22 | # set target from source 23 | ADD_EXECUTABLE ( ntohexample ${LIBNTOHEXAMPLE_SRCS} ) 24 | TARGET_LINK_LIBRARIES ( ntohexample pcap ntoh ${CMAKE_THREAD_LIBS_INIT}) 25 | -------------------------------------------------------------------------------- /examples/c/tcp_ipv6/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # this scripts follows the steps that you 4 | # should follow to compile and link against libntoh: 5 | # 6 | # $ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig 7 | # $ pkg-config --libs --cflags libntoh 8 | # -I/usr/local/include/libntoh -L/usr/local/lib -lntoh 9 | 10 | pkgconfig=$(which pkg-config) 11 | cmake=$(which cmake) 12 | make=$(which make) 13 | pkgconfig_path='' 14 | libntoh_pcpath='/usr/local/lib/pkgconfig' 15 | build_dir='build' 16 | 17 | if [ -z "$pkgconfig" ] 18 | then 19 | echo "[w] pkg-config not found! Good luck compiling..." 20 | exit 1 21 | else 22 | echo "[i] pkg-config found: $pkgconfig" 23 | fi 24 | 25 | if [ -z "$cmake" ] 26 | then 27 | echo "[e] Cannot compile without cmake binary" 28 | exit 2 29 | else 30 | echo "[i] cmake found: $cmake" 31 | fi 32 | 33 | if [ -z "$make" ] 34 | then 35 | echo "[e] Cannot compile without make binary" 36 | exit 3 37 | else 38 | echo "[i] make found: $make" 39 | fi 40 | 41 | pkgconfig_path=$(echo $PKG_CONFIG_PATH) 42 | if [ -z "$pkgconfig_path" ] 43 | then 44 | pkgconfig_path="$libntoh_pcpath" 45 | else 46 | pkgconfig_path="$pkgconfig_path:$libntoh_pcpath" 47 | fi 48 | 49 | echo "[i] PKG_CONFIG_PATH set to: $pkgconfig_path" 50 | echo '' 51 | 52 | rm -rf $build_dir 2>/dev/null 53 | mkdir $build_dir 2>/dev/null 54 | cd $build_dir 55 | $cmake ../ 56 | $make 57 | 58 | unset pkgconfig_path build_dir cmake make pkgconfig libntoh_pcpath 59 | exit 0 60 | -------------------------------------------------------------------------------- /examples/c/tcp_ipv6/example.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2011, Chema Garcia * 3 | * All rights reserved. * 4 | * * 5 | * Redistribution and use in source and binary forms, with or * 6 | * without modification, are permitted provided that the following * 7 | * conditions are met: * 8 | * * 9 | * * Redistributions of source code must retain the above * 10 | * copyright notice, this list of conditions and the following * 11 | * disclaimer. * 12 | * * 13 | * * Redistributions in binary form must reproduce the above * 14 | * copyright notice, this list of conditions and the following * 15 | * disclaimer in the documentation and/or other materials provided * 16 | * with the distribution. * 17 | * * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 28 | * POSSIBILITY OF SUCH DAMAGE. * 29 | ********************************************************************************/ 30 | 31 | /* 32 | * This example save the data sent by each peer in a separated file called: [src_ip]:[src_port]-[dst_ip]:[dst_port] 33 | */ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #ifndef __FAVOR_BSD 48 | # define __FAVOR_BSD 49 | #endif 50 | 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | #include 58 | #include 59 | 60 | typedef struct 61 | { 62 | unsigned char *data; 63 | size_t data_len; 64 | char *path; 65 | } peer_info_t , *ppeer_info_t; 66 | 67 | #define RECV_CLIENT 1 68 | #define RECV_SERVER 2 69 | 70 | /* capture handle */ 71 | pcap_t *handle = 0; 72 | pntoh_tcp_session_t tcp_session = 0; 73 | pntoh_ipv6_session_t ipv6_session = 0; 74 | unsigned short receive = 0; 75 | 76 | /** 77 | * @brief Exit function (closes the capture handle and releases all resource from libntoh) 78 | */ 79 | void shandler ( int sign ) 80 | { 81 | if ( sign != 0 ) 82 | signal ( sign , &shandler ); 83 | 84 | pcap_close( handle ); 85 | 86 | ntoh_exit(); 87 | 88 | fprintf( stderr, "\n\n[+] Capture finished!\n" ); 89 | exit( sign ); 90 | } 91 | 92 | /** 93 | * @brief Returns a struct which stores some peer information 94 | */ 95 | ppeer_info_t get_peer_info ( unsigned char *payload , size_t payload_len , pntoh_tcp_tuple5_t tuple ) 96 | { 97 | ppeer_info_t ret = 0; 98 | size_t len = 0; 99 | char path[1024] = {0}; 100 | char src[INET6_ADDRSTRLEN] = {0}; 101 | char dst[INET6_ADDRSTRLEN] = {0}; 102 | 103 | inet_ntop ( AF_INET6 , (void*) &tuple->source , src , INET6_ADDRSTRLEN ); 104 | inet_ntop ( AF_INET6 , (void*) &tuple->destination , dst , INET6_ADDRSTRLEN ); 105 | 106 | /* gets peer information */ 107 | ret = (ppeer_info_t) calloc ( 1 , sizeof ( peer_info_t ) ); 108 | ret->data_len = payload_len; 109 | ret->data = (unsigned char*) calloc ( ret->data_len , sizeof ( unsigned char ) ); 110 | memcpy ( ret->data , payload , ret->data_len ); 111 | 112 | snprintf ( path , sizeof(path) , "%s:%d-" , src, ntohs(tuple->sport) ); 113 | len = strlen(path); 114 | snprintf ( &path[len] , sizeof(path) - len, "%s:%d" , dst , ntohs(tuple->dport) ); 115 | 116 | ret->path = strndup ( path , sizeof(path) ); 117 | 118 | return ret; 119 | } 120 | 121 | /** 122 | * @brief Frees the ppeer_info_t struct 123 | */ 124 | void free_peer_info ( ppeer_info_t pinfo ) 125 | { 126 | /* free peer info data */ 127 | if ( ! pinfo ) 128 | return; 129 | 130 | free ( pinfo->data ); 131 | free ( pinfo->path ); 132 | free ( pinfo ); 133 | 134 | return; 135 | } 136 | 137 | /** 138 | * @brief Returns the name of a protocol 139 | */ 140 | inline char *get_proto_description ( unsigned short proto ) 141 | { 142 | switch ( proto ) 143 | { 144 | case IPPROTO_ICMP: 145 | return "ICMP"; 146 | 147 | case IPPROTO_TCP: 148 | return "TCP"; 149 | 150 | case IPPROTO_UDP: 151 | return "UDP"; 152 | 153 | case IPPROTO_IGMP: 154 | return "IGMP"; 155 | 156 | case IPPROTO_IPV6: 157 | return "IPv6"; 158 | 159 | case IPPROTO_FRAGMENT: 160 | return "IPv6 Fragment"; 161 | 162 | default: 163 | return "Undefined"; 164 | } 165 | } 166 | 167 | /** 168 | * @brief Writes the ppeer_info_t data field to disk 169 | */ 170 | void write_data ( ppeer_info_t info ) 171 | { 172 | int fd = 0; 173 | 174 | if ( !info ) 175 | return; 176 | 177 | if ( (fd = open ( info->path , O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW , S_IRWXU | S_IRWXG | S_IRWXO )) < 0 ) 178 | { 179 | fprintf ( stderr , "\n[e] Error %d writting data to \"%s\": %s" , errno , info->path , strerror( errno ) ); 180 | return; 181 | } 182 | 183 | write ( fd , info->data , info->data_len ); 184 | close ( fd ); 185 | 186 | return; 187 | } 188 | 189 | /** 190 | * @brief Send a TCP segment to libntoh 191 | */ 192 | void send_tcp_segment ( struct ip6_hdr *iphdr , pntoh_tcp_callback_t callback ) 193 | { 194 | ppeer_info_t pinfo; 195 | ntoh_tcp_tuple5_t tcpt5; 196 | pntoh_tcp_stream_t stream; 197 | struct tcphdr *tcp; 198 | size_t size_ip; 199 | size_t total_len; 200 | size_t size_tcp; 201 | size_t size_payload; 202 | unsigned char *payload; 203 | int ret; 204 | unsigned int error; 205 | 206 | size_ip = sizeof ( struct ip6_hdr ); 207 | total_len = size_ip + ntohs( iphdr->ip6_plen ); 208 | 209 | tcp = (struct tcphdr*)((unsigned char*)iphdr + size_ip); 210 | if ( (size_tcp = tcp->th_off * 4) < sizeof(struct tcphdr) ) 211 | return; 212 | 213 | payload = (unsigned char *)iphdr + size_ip + size_tcp; 214 | size_payload = total_len - (size_ip + size_tcp); 215 | 216 | ntoh_tcp_get_tuple5 ( (void*)iphdr , tcp , &tcpt5 ); 217 | 218 | /* find the stream or creates a new one */ 219 | if ( !( stream = ntoh_tcp_find_stream( tcp_session , &tcpt5 ) ) ) 220 | { 221 | if ( ! ( stream = ntoh_tcp_new_stream( tcp_session , &tcpt5, callback , 0 , &error , 1 , 1 ) ) ) 222 | { 223 | fprintf ( stderr , "\n[e] Error %d creating new stream: %s" , error , ntoh_get_errdesc ( error ) ); 224 | return; 225 | } 226 | 227 | fprintf ( stderr , "\nStream Creado!"); 228 | } 229 | 230 | if ( size_payload > 0 ) 231 | pinfo = get_peer_info ( payload , size_payload , &tcpt5 ); 232 | else 233 | pinfo = 0; 234 | 235 | 236 | /* add this segment to the stream */ 237 | switch ( ( ret = ntoh_tcp_add_segment( tcp_session , stream, (void*)iphdr, total_len, (void*)pinfo ) ) ) 238 | { 239 | case NTOH_OK: 240 | break; 241 | 242 | case NTOH_SYNCHRONIZING: 243 | free_peer_info ( pinfo ); 244 | break; 245 | 246 | default: 247 | fprintf( stderr, "\n[e] Error %d adding segment: %s", ret, ntoh_get_retval_desc( ret ) ); 248 | free_peer_info ( pinfo ); 249 | break; 250 | } 251 | 252 | return; 253 | } 254 | 255 | /** 256 | * @brief Sends a IPv6 fragment to libntoh 257 | */ 258 | void send_ipv6_fragment ( struct ip6_hdr *iphdr , pipv6_dfcallback_t callback ) 259 | { 260 | ntoh_ipv6_tuple4_t ipt4; 261 | pntoh_ipv6_flow_t flow; 262 | int ret; 263 | unsigned int error; 264 | 265 | ntoh_ipv6_get_tuple4 ( iphdr , &ipt4 ); 266 | 267 | if ( !( flow = ntoh_ipv6_find_flow( ipv6_session , &ipt4 ) ) ) 268 | if ( ! (flow = ntoh_ipv6_new_flow( ipv6_session , &ipt4, callback, 0 , &error )) ) 269 | { 270 | fprintf ( stderr , "\n[e] Error %d creating new IPv4 flow: %s" , error , ntoh_get_errdesc ( error ) ); 271 | return; 272 | } 273 | 274 | if ( ( ret = ntoh_ipv6_add_fragment( ipv6_session , flow, iphdr ) ) ) 275 | fprintf( stderr, "\n[e] Error %d adding IPv6: %s", ret, ntoh_get_retval_desc( ret ) ); 276 | 277 | return; 278 | } 279 | 280 | /* TCP Callback */ 281 | void tcp_callback ( pntoh_tcp_stream_t stream , pntoh_tcp_peer_t orig , pntoh_tcp_peer_t dest , pntoh_tcp_segment_t seg , int reason , int extra ) 282 | { 283 | char src[INET6_ADDRSTRLEN] = {0}; 284 | char dst[INET6_ADDRSTRLEN] = {0}; 285 | 286 | inet_ntop ( AF_INET6 , (void*) &orig->addr , src , INET6_ADDRSTRLEN ); 287 | inet_ntop ( AF_INET6 , (void*) &dest->addr , dst , INET6_ADDRSTRLEN ); 288 | 289 | /* receive data only from the peer given by the user */ 290 | if ( receive == RECV_CLIENT && stream->server.receive ) 291 | { 292 | stream->server.receive = 0; 293 | return; 294 | }else if ( receive == RECV_SERVER && stream->client.receive ) 295 | { 296 | stream->client.receive = 0; 297 | return; 298 | } 299 | 300 | fprintf ( stderr , "\n[%s] %s:%d (%s | Window: %lu) ---> " , ntoh_tcp_get_status ( stream->status ) , src , ntohs(orig->port) , ntoh_tcp_get_status ( orig->status ) , orig->totalwin ); 301 | fprintf ( stderr , "%s:%d (%s | Window: %lu)\n\t" , dst , ntohs(dest->port) , ntoh_tcp_get_status ( dest->status ) , dest->totalwin ); 302 | 303 | if ( seg != 0 ) 304 | fprintf ( stderr , "SEQ: %lu ACK: %lu Next SEQ: %lu" , seg->seq , seg->ack , orig->next_seq ); 305 | 306 | switch ( reason ) 307 | { 308 | /* Data segment */ 309 | case NTOH_REASON_DATA: 310 | fprintf ( stderr , " | Data segment | Bytes: %i" , seg->payload_len ); 311 | 312 | /* write data */ 313 | write_data( (ppeer_info_t) seg->user_data ); 314 | 315 | if ( extra != 0 ) 316 | fprintf ( stderr , " - %s" , ntoh_get_reason ( extra ) ); 317 | 318 | break; 319 | 320 | default: 321 | switch ( extra ) 322 | { 323 | case NTOH_REASON_MAX_SYN_RETRIES_REACHED: 324 | case NTOH_REASON_MAX_SYNACK_RETRIES_REACHED: 325 | case NTOH_REASON_HSFAILED: 326 | case NTOH_REASON_EXIT: 327 | case NTOH_REASON_TIMEDOUT: 328 | case NTOH_REASON_CLOSED: 329 | inet_ntop ( AF_INET6 , (void*) &stream->client.addr , src , INET6_ADDRSTRLEN ); 330 | if ( extra == NTOH_REASON_CLOSED ) 331 | fprintf ( stderr , "\n\t+ Connection closed by %s (%s)" , stream->closedby == NTOH_CLOSEDBY_CLIENT ? "Client" : "Server" , src ); 332 | else 333 | fprintf ( stderr , "\n\t+ %s/%s - %s" , ntoh_get_reason ( reason ) , ntoh_get_reason ( extra ) , ntoh_tcp_get_status ( stream->status ) ); 334 | 335 | break; 336 | 337 | default: 338 | break; 339 | } 340 | 341 | break; 342 | } 343 | 344 | if ( seg != 0 ) 345 | free_peer_info ( (ppeer_info_t) seg->user_data ); 346 | 347 | fprintf ( stderr , "\n" ); 348 | 349 | return; 350 | } 351 | 352 | /* IPv6 Callback */ 353 | void ipv6_callback ( pntoh_ipv6_flow_t flow , pntoh_ipv6_tuple4_t tuple , unsigned char *data , size_t len , unsigned short reason ) 354 | { 355 | unsigned int i = 0; 356 | char src[INET6_ADDRSTRLEN] = {0}; 357 | char dst[INET6_ADDRSTRLEN] = {0}; 358 | 359 | inet_ntop ( AF_INET6 , (void*) &tuple->source , src , INET6_ADDRSTRLEN ); 360 | inet_ntop ( AF_INET6 , (void*) &tuple->destination , dst , INET6_ADDRSTRLEN ); 361 | 362 | fprintf( stderr, "\n\n[i] Got an IPv4 datagram! (%s - %d) %s --> ", ntoh_get_reason(reason) , reason , src ); 363 | fprintf( stderr, "%s | %zu/%zu bytes - Key: %04x - ID: %02x - Proto: %d (%s)\n\n", dst , len, flow->total , flow->key, ntohs( tuple->id ), tuple->protocol, get_proto_description( tuple->protocol ) ); 364 | 365 | if ( tuple->protocol == IPPROTO_TCP ) 366 | send_tcp_segment ( (struct ip6_hdr*) data , &tcp_callback ); 367 | else 368 | for ( i = 0; i < flow->total ; i++ ) 369 | fprintf( stderr, "%02x ", data[i] ); 370 | 371 | fprintf( stderr, "\n" ); 372 | 373 | return; 374 | } 375 | 376 | int main ( int argc , char *argv[] ) 377 | { 378 | /* parameters parsing */ 379 | int c; 380 | 381 | /* pcap */ 382 | char errbuf[PCAP_ERRBUF_SIZE]; 383 | struct bpf_program fp; 384 | char filter_exp[] = "ip6 and tcp"; 385 | char *source = 0; 386 | char *filter = filter_exp; 387 | const unsigned char *packet = 0; 388 | struct pcap_pkthdr header; 389 | 390 | /* packet dissection */ 391 | struct ip6_hdr *ip; 392 | unsigned int error; 393 | 394 | /* extra */ 395 | unsigned int ipf,tcps; 396 | 397 | fprintf( stderr, "\n###########################" ); 398 | fprintf( stderr, "\n# libntoh Example #" ); 399 | fprintf( stderr, "\n# ----------------------- #" ); 400 | fprintf( stderr, "\n# Written by Chema Garcia #" ); 401 | fprintf( stderr, "\n# ----------------------- #" ); 402 | fprintf( stderr, "\n# http://safetybits.net #" ); 403 | fprintf( stderr, "\n# chema@safetybits.net #" ); 404 | fprintf( stderr, "\n###########################\n" ); 405 | 406 | fprintf( stderr, "\n[i] libntoh version: %s\n", ntoh_version() ); 407 | 408 | if ( argc < 3 ) 409 | { 410 | fprintf( stderr, "\n[+] Usage: %s \n", argv[0] ); 411 | fprintf( stderr, "\n+ Options:" ); 412 | fprintf( stderr, "\n\t-i | --iface -----> Interface to read packets from" ); 413 | fprintf( stderr, "\n\t-f | --file ------> File path to read packets from" ); 414 | fprintf( stderr, "\n\t-F | --filter ----> Capture filter (default: \"ip6 and tcp\")" ); 415 | fprintf( stderr, "\n\t-c | --client ----------> Receive client data"); 416 | fprintf( stderr, "\n\t-s | --server ----------> Receive server data\n\n"); 417 | exit( 1 ); 418 | } 419 | 420 | /* check parameters */ 421 | while ( 1 ) 422 | { 423 | int option_index = 0; 424 | static struct option long_options[] = 425 | { 426 | { "iface" , 1 , 0 , 'i' } , 427 | { "file" , 1 , 0 , 'f' } , 428 | { "filter" , 1 , 0 , 'F' } , 429 | { "client" , 0 , 0 , 'c' }, 430 | { "server" , 0 , 0 , 's' }, 431 | { 0 , 0 , 0 , 0 } }; 432 | 433 | if ( ( c = getopt_long( argc, argv, "i:f:F:cs", long_options, &option_index ) ) < 0 ) 434 | break; 435 | 436 | switch ( c ) 437 | { 438 | case 'i': 439 | source = optarg; 440 | handle = pcap_open_live( optarg, 65535, 1, 0, errbuf ); 441 | break; 442 | 443 | case 'f': 444 | source = optarg; 445 | handle = pcap_open_offline( optarg, errbuf ); 446 | break; 447 | 448 | case 'F': 449 | filter = optarg; 450 | break; 451 | 452 | case 'c': 453 | receive |= RECV_CLIENT; 454 | break; 455 | 456 | case 's': 457 | receive |= RECV_SERVER; 458 | break; 459 | } 460 | } 461 | 462 | if ( !receive ) 463 | receive = (RECV_CLIENT | RECV_SERVER); 464 | 465 | if ( !handle ) 466 | { 467 | fprintf( stderr, "\n[e] Error loading %s: %s\n", source, errbuf ); 468 | exit( -1 ); 469 | } 470 | 471 | if ( pcap_compile( handle, &fp, filter, 0, 0 ) < 0 ) 472 | { 473 | fprintf( stderr, "\n[e] Error compiling filter \"%s\": %s\n\n", filter, pcap_geterr( handle ) ); 474 | pcap_close( handle ); 475 | exit( -2 ); 476 | } 477 | 478 | if ( pcap_setfilter( handle, &fp ) < 0 ) 479 | { 480 | fprintf( stderr, "\n[e] Cannot set filter \"%s\": %s\n\n", filter, pcap_geterr( handle ) ); 481 | pcap_close( handle ); 482 | exit( -3 ); 483 | } 484 | pcap_freecode( &fp ); 485 | 486 | /* verify datalink */ 487 | if ( pcap_datalink( handle ) != DLT_EN10MB ) 488 | { 489 | fprintf ( stderr , "\n[e] libntoh is independent from link layer, but this example only works with ethernet link layer\n"); 490 | pcap_close ( handle ); 491 | exit ( -4 ); 492 | } 493 | 494 | fprintf( stderr, "\n[i] Source: %s / %s", source, pcap_datalink_val_to_description( pcap_datalink( handle ) ) ); 495 | fprintf( stderr, "\n[i] Filter: %s", filter ); 496 | 497 | fprintf( stderr, "\n[i] Receive data from client: "); 498 | if ( receive & RECV_CLIENT ) 499 | fprintf( stderr , "Yes"); 500 | else 501 | fprintf( stderr , "No"); 502 | 503 | fprintf( stderr, "\n[i] Receive data from server: "); 504 | if ( receive & RECV_SERVER ) 505 | fprintf( stderr , "Yes"); 506 | else 507 | fprintf( stderr , "No"); 508 | 509 | signal( SIGINT, &shandler ); 510 | signal( SIGTERM, &shandler ); 511 | 512 | /*******************************************/ 513 | /** libntoh initialization process starts **/ 514 | /*******************************************/ 515 | 516 | ntoh_init (); 517 | 518 | if ( ! (tcp_session = ntoh_tcp_new_session ( 0 , 0 , &error ) ) ) 519 | { 520 | fprintf ( stderr , "\n[e] Error %d creating TCP session: %s" , error , ntoh_get_errdesc ( error ) ); 521 | exit ( -5 ); 522 | } 523 | 524 | fprintf ( stderr , "\n[i] Max. TCP streams allowed: %d" , ntoh_tcp_get_size ( tcp_session ) ); 525 | 526 | if ( ! (ipv6_session = ntoh_ipv6_new_session ( 0 , 0 , &error )) ) 527 | { 528 | ntoh_tcp_free_session ( tcp_session ); 529 | fprintf ( stderr , "\n[e] Error %d creating IPv4 session: %s" , error , ntoh_get_errdesc ( error ) ); 530 | exit ( -6 ); 531 | } 532 | 533 | fprintf ( stderr , "\n[i] Max. IPv6 flows allowed: %d\n\n" , ntoh_ipv6_get_size ( ipv6_session ) ); 534 | 535 | /* capture starts */ 536 | while ( ( packet = pcap_next( handle, &header ) ) != 0 ) 537 | { 538 | /* get packet headers */ 539 | ip = (struct ip6_hdr*) ( packet + sizeof ( struct ether_header ) ); 540 | 541 | /* it is an IPv4 fragment */ 542 | if ( NTOH_IPV6_IS_FRAGMENT(ip) ) 543 | send_ipv6_fragment ( ip , &ipv6_callback ); 544 | /* or a TCP segment */ 545 | else if ( ip->ip6_nxt == IPPROTO_TCP ) 546 | send_tcp_segment ( ip , &tcp_callback ); 547 | } 548 | 549 | tcps = ntoh_tcp_count_streams( tcp_session ); 550 | ipf = ntoh_ipv6_count_flows ( ipv6_session ); 551 | 552 | /* no streams left */ 553 | if ( ipf + tcps > 0 ) 554 | { 555 | fprintf( stderr, "\n\n[+] There are currently %i stored TCP stream(s) and %i IPv6 flow(s). You can wait them to get closed or press CTRL+C\n" , tcps , ipf ); 556 | pause(); 557 | } 558 | 559 | shandler( 0 ); 560 | 561 | //dummy return 562 | return 0; 563 | } 564 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED ( VERSION 2.8 FATAL_ERROR ) 2 | PROJECT ( LIBNTOH ) 3 | 4 | # set project version 5 | SET ( ${PROJECT_NAME}_MAJOR_VERSION "0" ) 6 | SET ( ${PROJECT_NAME}_MINOR_VERSION "5" ) 7 | SET ( ${PROJECT_NAME}_STATUS_VERSION "b" ) 8 | SET ( ${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_MAJOR_VERSION}.${${PROJECT_NAME}_MINOR_VERSION}${${PROJECT_NAME}_STATUS_VERSION}" ) 9 | # set project include dir. 10 | SET ( LIBNTOH_INC inc ) 11 | SET ( CMAKE_INCLUDE_PATH "/usr/include" ) 12 | # set build type 13 | SET ( CMAKE_BUILD_TYPE Release ) 14 | # set sources 15 | SET ( LIBNTOH_SRCS libntoh.c tcpreassembly.c ipv4defrag.c ipv6defrag.c common.c sfhash.c ) 16 | # set cflags 17 | SET ( CMAKE_C_FLAGS "-Wall -Os -O3 -pipe -fPIC" ) 18 | #SET ( CMAKE_C_FLAGS "-g -Wall -Os -O3 -pipe" ) // static: comment the line above and uncomment this one to compile as static library (contrib by Di3) 19 | # set output name 20 | SET ( OUTPUT_LIB ntoh ) 21 | # set interface files 22 | SET ( MODULE_NAME libntoh ) 23 | #SET ( INTERFACE_FILES libntoh.i tcpreassembly.i common.i sfhash.i ipv4defrag.i ) 24 | 25 | SET_SOURCE_FILES_PROPERTIES ( ${INTERFACE_FILES} PROPERTIES CPLUSCPLUS OFF ) 26 | 27 | 28 | # required libraries 29 | FIND_PACKAGE ( Threads REQUIRED ) 30 | 31 | # set include directories 32 | INCLUDE_DIRECTORIES ( ${LIBNTOH_INC} ) 33 | INCLUDE_DIRECTORIES ( ${CMAKE_CURRENT_SOURCE_DIR}) 34 | INCLUDE_DIRECTORIES ( ${CMAKE_INCLUDE_PATH}) 35 | 36 | # set target from source 37 | ADD_LIBRARY( ${OUTPUT_LIB} SHARED ${LIBNTOH_SRCS} ) 38 | #ADD_LIBRARY( ${OUTPUT_LIB} STATIC ${LIBNTOH_SRCS} ) // static: comment the line above and uncomment this one to compile as static library (contrib by Di3) 39 | 40 | # pkgconfig file 41 | CONFIGURE_FILE ( ntoh.pc.in ntoh.pc @ONLY ) 42 | 43 | # link against required libraries 44 | TARGET_LINK_LIBRARIES( ${OUTPUT_LIB} ${CMAKE_THREAD_LIBS_INIT}) 45 | 46 | ########################### 47 | # set install information # 48 | ########################### 49 | # library 50 | INSTALL ( TARGETS ${OUTPUT_LIB} LIBRARY DESTINATION lib ) 51 | #INSTALL ( TARGETS ${OUTPUT_LIB} ARCHIVE DESTINATION lib )// static: comment the line above and uncomment this one to compile as static library (contrib by Di3) 52 | # headers 53 | INSTALL ( FILES ${LIBNTOH_INC}/libntoh.h ${LIBNTOH_INC}/tcpreassembly.h ${LIBNTOH_INC}/sfhash.h ${LIBNTOH_INC}/ipv4defrag.h ${LIBNTOH_INC}/ipv6defrag.h ${LIBNTOH_INC}/common.h DESTINATION include/libntoh ) 54 | # pkconfig file 55 | INSTALL ( FILES ${CMAKE_CURRENT_BINARY_DIR}/ntoh.pc DESTINATION lib/pkgconfig) 56 | # swig 57 | 58 | -------------------------------------------------------------------------------- /src/CMakeLists.txt.a: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED ( VERSION 2.8 FATAL_ERROR ) 2 | PROJECT ( LIBNTOH ) 3 | 4 | # set project version 5 | SET ( ${PROJECT_NAME}_MAJOR_VERSION "0" ) 6 | SET ( ${PROJECT_NAME}_MINOR_VERSION "4" ) 7 | SET ( ${PROJECT_NAME}_STATUS_VERSION "a" ) 8 | SET ( ${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_MAJOR_VERSION}.${${PROJECT_NAME}_MINOR_VERSION}${${PROJECT_NAME}_STATUS_VERSION}" ) 9 | 10 | # set source files and flags 11 | SET ( LIBNTOH_SRCS libntoh.c tcpreassembly.c ipv4defrag.c common.c sfhash.c ) 12 | SET ( LIBNTOH_INC inc ) 13 | #SET ( CMAKE_C_FLAGS "-Wall -Os -O3 -pipe -fPIC" ) 14 | SET ( CMAKE_C_FLAGS "-g -Wall -Os -O3 -pipe" ) 15 | 16 | # set include directories 17 | INCLUDE_DIRECTORIES ( ${LIBNTOH_INC} ) 18 | 19 | SET ( CMAKE_INCLUDE_PATH "/usr/include" ) 20 | 21 | SET ( CMAKE_BUILD_TYPE Release ) 22 | 23 | # set output library name 24 | SET ( OUTPUT_LIB ntoh ) 25 | 26 | # set target from source 27 | #ADD_LIBRARY( ${OUTPUT_LIB} SHARED ${LIBNTOH_SRCS} ) 28 | ADD_LIBRARY( ${OUTPUT_LIB} STATIC ${LIBNTOH_SRCS} ) 29 | 30 | # pkgconfig file 31 | CONFIGURE_FILE ( ntoh.pc.in ntoh.pc @ONLY ) 32 | 33 | # link against required libraries 34 | FIND_PACKAGE ( Threads REQUIRED ) 35 | TARGET_LINK_LIBRARIES( ${OUTPUT_LIB} ${CMAKE_THREAD_LIBS_INIT}) 36 | 37 | ########################### 38 | # set install information # 39 | ########################### 40 | # library 41 | #INSTALL ( TARGETS ${OUTPUT_LIB} LIBRARY DESTINATION lib ) 42 | INSTALL ( TARGETS ${OUTPUT_LIB} ARCHIVE DESTINATION lib ) 43 | # headers 44 | INSTALL ( FILES ${LIBNTOH_INC}/libntoh.h ${LIBNTOH_INC}/tcpreassembly.h ${LIBNTOH_INC}/sfhash.h ${LIBNTOH_INC}/ipv4defrag.h ${LIBNTOH_INC}/common.h DESTINATION include/libntoh ) 45 | # pkconfig file 46 | INSTALL ( FILES ${CMAKE_CURRENT_BINARY_DIR}/ntoh.pc DESTINATION lib/pkgconfig) 47 | -------------------------------------------------------------------------------- /src/CMakeLists.txt.so: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED ( VERSION 2.8 FATAL_ERROR ) 2 | PROJECT ( LIBNTOH ) 3 | 4 | # set project version 5 | SET ( ${PROJECT_NAME}_MAJOR_VERSION "0" ) 6 | SET ( ${PROJECT_NAME}_MINOR_VERSION "4" ) 7 | SET ( ${PROJECT_NAME}_STATUS_VERSION "a" ) 8 | SET ( ${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_MAJOR_VERSION}.${${PROJECT_NAME}_MINOR_VERSION}${${PROJECT_NAME}_STATUS_VERSION}" ) 9 | 10 | # set source files and flags 11 | SET ( LIBNTOH_SRCS libntoh.c tcpreassembly.c ipv4defrag.c common.c sfhash.c ) 12 | SET ( LIBNTOH_INC inc ) 13 | SET ( CMAKE_C_FLAGS "-Wall -Os -O3 -pipe -fPIC" ) 14 | 15 | # set include directories 16 | INCLUDE_DIRECTORIES ( ${LIBNTOH_INC} ) 17 | 18 | SET ( CMAKE_INCLUDE_PATH "/usr/include" ) 19 | 20 | SET ( CMAKE_BUILD_TYPE Release ) 21 | 22 | # set output library name 23 | SET ( OUTPUT_LIB ntoh ) 24 | 25 | # set target from source 26 | ADD_LIBRARY( ${OUTPUT_LIB} SHARED ${LIBNTOH_SRCS} ) 27 | 28 | # pkgconfig file 29 | CONFIGURE_FILE ( ntoh.pc.in ntoh.pc @ONLY ) 30 | 31 | # link against required libraries 32 | FIND_PACKAGE ( Threads REQUIRED ) 33 | TARGET_LINK_LIBRARIES( ${OUTPUT_LIB} ${CMAKE_THREAD_LIBS_INIT}) 34 | 35 | ########################### 36 | # set install information # 37 | ########################### 38 | # library 39 | INSTALL ( TARGETS ${OUTPUT_LIB} LIBRARY DESTINATION lib ) 40 | # headers 41 | INSTALL ( FILES ${LIBNTOH_INC}/libntoh.h ${LIBNTOH_INC}/tcpreassembly.h ${LIBNTOH_INC}/sfhash.h ${LIBNTOH_INC}/ipv4defrag.h ${LIBNTOH_INC}/common.h DESTINATION include/libntoh ) 42 | # pkconfig file 43 | INSTALL ( FILES ${CMAKE_CURRENT_BINARY_DIR}/ntoh.pc DESTINATION lib/pkgconfig) 44 | -------------------------------------------------------------------------------- /src/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # this scripts follows the steps that you 4 | # should follow to compile and link against libntoh: 5 | # 6 | # $ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig 7 | # $ pkg-config --libs --cflags libntoh 8 | # -I/usr/local/include/libntoh -L/usr/local/lib -lntoh 9 | 10 | pkgconfig=$(which pkg-config) 11 | cmake=$(which cmake) 12 | make=$(which make) 13 | pkgconfig_path='' 14 | libntoh_pcpath='/usr/local/lib/pkgconfig' 15 | build_dir='build' 16 | 17 | if [ -z "$pkgconfig" ] 18 | then 19 | echo "[w] pkg-config not found! Good luck compiling..." 20 | exit 1 21 | else 22 | echo "[i] pkg-config found: $pkgconfig" 23 | fi 24 | 25 | if [ -z "$cmake" ] 26 | then 27 | echo "[e] Cannot compile without cmake binary" 28 | exit 2 29 | else 30 | echo "[i] cmake found: $cmake" 31 | fi 32 | 33 | if [ -z "$make" ] 34 | then 35 | echo "[e] Cannot compile without make binary" 36 | exit 3 37 | else 38 | echo "[i] make found: $make" 39 | fi 40 | 41 | pkgconfig_path=$(echo $PKG_CONFIG_PATH) 42 | if [ -z "$pkgconfig_path" ] 43 | then 44 | pkgconfig_path="$libntoh_pcpath" 45 | else 46 | pkgconfig_path="$pkgconfig_path:$libntoh_pcpath" 47 | fi 48 | 49 | echo "[i] PKG_CONFIG_PATH set to: $pkgconfig_path" 50 | echo '' 51 | 52 | rm -rf $build_dir 2>/dev/null 53 | mkdir $build_dir 2>/dev/null 54 | cd $build_dir 55 | $cmake ../ 56 | $make 57 | 58 | if [ $? -eq 0 ] 59 | then 60 | response='' 61 | while [ $(echo -n "$response" | grep -c "[yn]") -eq 0 ] 62 | do 63 | read -e -p "Do you want to perform the installation? [y/n]: " -i "y" response 64 | done 65 | 66 | if [ "$response" == "y" ] 67 | then 68 | command='make' 69 | if [ $UID -gt 0 ] 70 | then 71 | command="sudo $command" 72 | fi 73 | command="$command install" 74 | $command 75 | fi 76 | fi 77 | 78 | unset pkgconfig_path build_dir cmake make pkgconfig libntoh_pcpath 79 | exit 0 80 | -------------------------------------------------------------------------------- /src/common.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2012, Chema Garcia * 3 | * All rights reserved. * 4 | * * 5 | * Redistribution and use in source and binary forms, with or * 6 | * without modification, are permitted provided that the following * 7 | * conditions are met: * 8 | * * 9 | * * Redistributions of source code must retain the above * 10 | * copyright notice, this list of conditions and the following * 11 | * disclaimer. * 12 | * * 13 | * * Redistributions in binary form must reproduce the above * 14 | * copyright notice, this list of conditions and the following * 15 | * disclaimer in the documentation and/or other materials provided * 16 | * with the distribution. * 17 | * * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 28 | * POSSIBILITY OF SUCH DAMAGE. * 29 | ********************************************************************************/ 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | // Uniqueness test for IP fragments, using their tuples 36 | // @contrib: Eosis - https://github.com/Eosis 37 | /*_HIDDEN inline int ipv4_tuple4_equals_to(pntoh_ipv4_tuple4_t x, pntoh_ipv4_tuple4_t y) 38 | { 39 | if (x->source != y->source) 40 | return 0; 41 | 42 | if (x->destination != y->destination) 43 | return 0; 44 | 45 | if (x->protocol != y->protocol) 46 | return 0; 47 | 48 | if (x->id != y->id) 49 | return 0; 50 | 51 | return 1; 52 | }*/ 53 | 54 | /****************/ 55 | /** HASH TABLE **/ 56 | /****************/ 57 | /* map the hash table */ 58 | _HIDDEN phtable_t htable_map ( size_t size , fcmp_t *equal_func ) 59 | { 60 | phtable_t ret = 0; 61 | 62 | if ( !size ) 63 | return 0; 64 | 65 | ret = (phtable_t) calloc ( 1 , sizeof ( htable_t ) ); 66 | ret->table = (phtnode_t*) calloc ( size , sizeof ( phtnode_t ) ); 67 | ret->table_size = size; 68 | ret->equals = equal_func; 69 | 70 | return ret; 71 | } 72 | 73 | /* insert a pair key-value into the hash table */ 74 | _HIDDEN int htable_insert ( phtable_t ht , unsigned int key , void *val ) 75 | { 76 | phtnode_t node = 0; 77 | phtnode_t aux = 0; 78 | unsigned int index = 0; 79 | 80 | if ( !ht || !val ) 81 | return 0; 82 | 83 | node = (phtnode_t) calloc ( 1 , sizeof ( htnode_t ) ); 84 | node->key = key; 85 | node->val = val; 86 | 87 | index = key % ht->table_size; 88 | 89 | if ( ht->table[index] == NULL ) 90 | { 91 | ht->table[index] = node; 92 | return 1; 93 | } 94 | 95 | /* collision resolution by chaining */ 96 | aux = ht->table[index]; 97 | while ( aux->next != 0 ) 98 | aux = aux->next; 99 | 100 | aux->next = node; 101 | 102 | return 1; 103 | } 104 | 105 | /* returns the value associated to the given key */ 106 | _HIDDEN void *htable_find ( phtable_t ht , unsigned int key, void* ip_tuple4 ) 107 | { 108 | unsigned int index = 0; 109 | phtnode_t node = 0; 110 | 111 | if ( !ht ) 112 | return 0; 113 | 114 | index = key % ht->table_size; 115 | 116 | node = ht->table[index]; 117 | 118 | // @contrib: Eosis - https://github.com/Eosis 119 | if ( ip_tuple4 != 0 ) //if not null 120 | while( node != 0 && ! ht->equals ( ip_tuple4 , node->val ) ) //!(ipv4_tuple4_equals_to((pntoh_ipv4_tuple4_t)ip_tuple4, &(((pntoh_ipv4_flow_t)(node->val))->ident))) ) 121 | node = node->next; 122 | else 123 | while ( node != 0 && node->key != key ) 124 | node = node->next; 125 | 126 | if ( !node ) 127 | return 0; 128 | 129 | return node->val; 130 | } 131 | 132 | /* removes a key-value pair from the hash table */ 133 | _HIDDEN void *htable_remove ( phtable_t ht , unsigned int key, void* ip_tuple4 ) 134 | { 135 | unsigned int index = 0; 136 | phtnode_t node = 0; 137 | phtnode_t aux = 0; 138 | void *ret = 0; 139 | 140 | if ( !ht ) 141 | return 0; 142 | 143 | index = key % ht->table_size; 144 | node = ht->table[index]; 145 | 146 | if ( node->key == key ) 147 | ht->table[index] = node->next; 148 | else 149 | { 150 | while ( node->next != 0 && node->next->key != key ) 151 | node = node->next; 152 | 153 | // @contrib: Eosis - https://github.com/Eosis 154 | if (ip_tuple4 != 0 ) //if not null 155 | while( node->next != 0 && ! ht->equals ( ip_tuple4 , node->next->val ) ) //!(ipv4_tuple4_equals_to((pntoh_ipv4_tuple4_t)ip_tuple4, &(((pntoh_ipv4_flow_t)(node->next->val))->ident))) ) 156 | node = node->next; 157 | else 158 | while ( node->next != 0 && node->next->key != key ) 159 | node = node->next; 160 | 161 | if ( node->next != 0 ) 162 | { 163 | aux = node; 164 | node = node->next; 165 | aux->next = node->next; 166 | } 167 | } 168 | 169 | if ( !node ) 170 | return 0; 171 | 172 | ret = node->val; 173 | free ( node ); 174 | 175 | return ret; 176 | } 177 | 178 | /* count the key-value pairs in a hash table */ 179 | _HIDDEN unsigned int htable_count ( phtable_t ht ) 180 | { 181 | unsigned int i = 0; 182 | unsigned int ret = 0; 183 | phtnode_t aux = 0; 184 | 185 | if ( !ht ) 186 | return ret; 187 | 188 | for ( i = 0 ; i < ht->table_size ; i++ ) 189 | for ( aux = ht->table[i] ; aux != 0 ; ret++ , aux = aux->next ); 190 | 191 | return ret; 192 | } 193 | 194 | /* gets the first key in a hash table */ 195 | _HIDDEN unsigned int htable_first ( phtable_t ht ) 196 | { 197 | unsigned int ret = 0; 198 | unsigned int i = 0; 199 | 200 | if ( ! ht ) 201 | return ret; 202 | 203 | for ( i = 0 ; i < ht->table_size && ht->table[i] == 0 ; i++ ); 204 | 205 | if ( i < ht->table_size ) 206 | ret = ht->table[i]->key; 207 | 208 | return ret; 209 | } 210 | 211 | /* destroys entire hash table */ 212 | _HIDDEN void htable_destroy ( phtable_t *ht ) 213 | { 214 | unsigned int i = 0; 215 | phtnode_t aux = 0; 216 | 217 | if ( !ht || !(*ht) ) 218 | return; 219 | 220 | for ( i = 0 ; i < (*ht)->table_size ; i++ ) 221 | while ( (*ht)->table[i] != 0 ) 222 | { 223 | aux = (*ht)->table[i]->next; 224 | free ( (*ht)->table[i] ); 225 | (*ht)->table[i] = aux; 226 | } 227 | 228 | free ( (*ht)->table ); 229 | free ( *ht ); 230 | 231 | *ht = 0; 232 | 233 | return; 234 | } 235 | 236 | /********************/ 237 | /** ACCESS LOCKING **/ 238 | /********************/ 239 | _HIDDEN void lock_access ( pntoh_lock_t lock ) 240 | { 241 | pthread_mutex_lock( &lock->mutex ); 242 | 243 | while ( lock->use ) 244 | pthread_cond_wait( &lock->pcond, &lock->mutex ); 245 | 246 | lock->use = 1; 247 | 248 | pthread_mutex_unlock( &lock->mutex ); 249 | 250 | return; 251 | } 252 | 253 | _HIDDEN void unlock_access ( pntoh_lock_t lock ) 254 | { 255 | pthread_mutex_lock( &lock->mutex ); 256 | 257 | lock->use = 0; 258 | pthread_cond_signal( &lock->pcond ); 259 | 260 | pthread_mutex_unlock( &lock->mutex ); 261 | 262 | return; 263 | } 264 | 265 | _HIDDEN void free_lockaccess ( pntoh_lock_t lock ) 266 | { 267 | pthread_cond_destroy( &lock->pcond ); 268 | pthread_mutex_destroy( &lock->mutex ); 269 | 270 | return; 271 | } 272 | -------------------------------------------------------------------------------- /src/inc/common.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIBNTOH_COMMON_H__ 2 | # define __LIBNTOH_COMMON_H__ 3 | 4 | /******************************************************************************** 5 | * Copyright (c) 2012, Chema Garcia * 6 | * All rights reserved. * 7 | * * 8 | * Redistribution and use in source and binary forms, with or * 9 | * without modification, are permitted provided that the following * 10 | * conditions are met: * 11 | * * 12 | * * Redistributions of source code must retain the above * 13 | * copyright notice, this list of conditions and the following * 14 | * disclaimer. * 15 | * * 16 | * * Redistributions in binary form must reproduce the above * 17 | * copyright notice, this list of conditions and the following * 18 | * disclaimer in the documentation and/or other materials provided * 19 | * with the distribution. * 20 | * * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * 25 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 31 | * POSSIBILITY OF SUCH DAMAGE. * 32 | ********************************************************************************/ 33 | 34 | #ifndef _HIDDEN 35 | # define _HIDDEN __attribute__((visibility("hidden"))) 36 | #endif 37 | 38 | /* linked list */ 39 | typedef struct _hash_node_ 40 | { 41 | struct _hash_node_ *next; 42 | void *val; 43 | unsigned int key; 44 | } htnode_t , *phtnode_t; 45 | 46 | typedef unsigned short fcmp_t (void *a, void *b); 47 | 48 | /* hash table definition */ 49 | typedef struct 50 | { 51 | size_t table_size; 52 | phtnode_t *table; 53 | fcmp_t *equals; 54 | } htable_t , *phtable_t; 55 | 56 | /******************************************************************/ 57 | /** Hash Table implementation (collision resolution by chaining) **/ 58 | /******************************************************************/ 59 | phtable_t htable_map ( size_t size , fcmp_t *equal_func ); 60 | int htable_insert ( phtable_t ht , unsigned int key , void *val ); 61 | void *htable_find ( phtable_t ht , unsigned int key, void *ip_tuple4 ); 62 | void *htable_remove ( phtable_t ht , unsigned int key, void *ip_tuple4 ); 63 | unsigned int htable_count ( phtable_t ht ); 64 | unsigned int htable_first ( phtable_t ht ); 65 | void htable_destroy ( phtable_t *ht ); 66 | 67 | 68 | /** @brief Access locking **/ 69 | void lock_access ( pntoh_lock_t lock ); 70 | /** @brief Access unlocking **/ 71 | void unlock_access ( pntoh_lock_t lock ); 72 | void free_lockaccess ( pntoh_lock_t lock ); 73 | 74 | #endif /* __LIBNTOH_COMMON_H__ */ 75 | -------------------------------------------------------------------------------- /src/inc/ipv4defrag.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIBNTOH_IP4DF__ 2 | # define __LIBNTOH_IP4DF__ 3 | 4 | /******************************************************************************** 5 | * Copyright (c) 2012, Chema Garcia * 6 | * All rights reserved. * 7 | * * 8 | * Redistribution and use in source and binary forms, with or * 9 | * without modification, are permitted provided that the following * 10 | * conditions are met: * 11 | * * 12 | * * Redistributions of source code must retain the above * 13 | * copyright notice, this list of conditions and the following * 14 | * disclaimer. * 15 | * * 16 | * * Redistributions in binary form must reproduce the above * 17 | * copyright notice, this list of conditions and the following * 18 | * disclaimer in the documentation and/or other materials provided * 19 | * with the distribution. * 20 | * * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * 25 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 31 | * POSSIBILITY OF SUCH DAMAGE. * 32 | ********************************************************************************/ 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | /// macro to verify if an IP datagram is part of a fragmented datagram 39 | #define NTOH_IPV4_IS_FRAGMENT(off) ( ( (8*(ntohs(off) & 0x1FFF)) > 0 || (ntohs(off) & 0x2000) ) && !(ntohs(off) & 0x4000) ) 40 | 41 | /** @brief Struct to generate the flow key **/ 42 | typedef struct 43 | { 44 | /// source IP address 45 | unsigned int source; 46 | /// destination IP address 47 | unsigned int destination; 48 | /// Transport layer protocol 49 | unsigned char protocol; 50 | /// Identification 51 | unsigned short id; 52 | } ntoh_ipv4_tuple4_t, *pntoh_ipv4_tuple4_t; 53 | 54 | typedef unsigned int ntoh_ipv4_key_t; 55 | 56 | /** @brief Struct to store the information of each fragment */ 57 | typedef struct _ipv4_fragment_ 58 | { 59 | /// pointer to the next fragment 60 | struct _ipv4_fragment_ *next; 61 | /// fragment offset 62 | unsigned int offset; 63 | /// fragment data length 64 | unsigned int len; 65 | /// fragment data 66 | unsigned char *data; 67 | } ntoh_ipv4_fragment_t , *pntoh_ipv4_fragment_t; 68 | 69 | /** @brief Struct to store the information of each IPv4 flow */ 70 | typedef struct 71 | { 72 | /// flow identification data 73 | ntoh_ipv4_tuple4_t ident; 74 | /// flow key 75 | ntoh_ipv4_key_t key; 76 | /// fragments list 77 | pntoh_ipv4_fragment_t fragments; 78 | /// total amount of received data 79 | size_t meat; 80 | /// total amount of expected data 81 | size_t total; 82 | /// final fragment received? 83 | struct ip *final_iphdr; 84 | /// user defined function to receive defragmented packets 85 | void *function; 86 | /// last activity 87 | struct timeval last_activ; 88 | /// user-defined data 89 | void *udata; 90 | ntoh_lock_t lock; 91 | } ntoh_ipv4_flow_t, *pntoh_ipv4_flow_t; 92 | 93 | typedef htable_t ipv4_flows_table_t; 94 | typedef phtable_t pipv4_flows_table_t; 95 | 96 | /** @brief Structure to store global parameters */ 97 | typedef struct _ipv4_session_ 98 | { 99 | struct _ipv4_session_ *next; 100 | 101 | /// max. number of IP flows 102 | sem_t max_flows; 103 | sem_t max_fragments; 104 | /// hash table to store IP flows 105 | pipv4_flows_table_t flows; 106 | /// connection tables related 107 | pthread_t tID; 108 | ntoh_lock_t lock; 109 | }ntoh_ipv4_session_t , *pntoh_ipv4_session_t ; 110 | 111 | typedef struct 112 | { 113 | unsigned short init; 114 | pntoh_ipv4_session_t sessions_list; 115 | ntoh_lock_t lock; 116 | } ntoh_ipv4_params_t , *pntoh_ipv4_params_t; 117 | 118 | /// min. PMTU 119 | #ifndef MIN_IPV4_FRAGMENT_LENGTH 120 | # define MIN_IPV4_FRAGMENT_LENGTH 576 121 | #endif 122 | 123 | /// max. IPv4 datagram fragment length 124 | #ifndef MAX_IPV4_DATAGRAM_LENGTH 125 | # define MAX_IPV4_DATAGRAM_LENGTH 65535 126 | #endif 127 | 128 | /// IPv4 fragment timeout 129 | #ifndef DEFAULT_IPV4_FRAGMENT_TIMEOUT 130 | # define DEFAULT_IPV4_FRAGMENT_TIMEOUT 15 131 | #endif 132 | 133 | /// max. IPv4 allowed flows 134 | #ifndef DEFAULT_IPV4_MAX_FLOWS 135 | # define DEFAULT_IPV4_MAX_FLOWS 1024 136 | #endif 137 | 138 | /// max. IPv4 allowed fragments 139 | #ifndef DEFAULT_IPV4_MAX_FRAGMENTS 140 | # define DEFAULT_IPV4_MAX_FRAGMENTS ((12*1024*1024) / sizeof(ntoh_ipv4_fragment_t)) 141 | #endif 142 | 143 | typedef void(*pipv4_dfcallback_t) ( pntoh_ipv4_flow_t , pntoh_ipv4_tuple4_t , unsigned char* , size_t , unsigned short ); 144 | 145 | /** 146 | * @brief Initializes the IPv4 defragmentation 147 | */ 148 | void ntoh_ipv4_init ( void ); 149 | 150 | /** 151 | * @brief Flush all IPv4 sessions and release all resources 152 | */ 153 | void ntoh_ipv4_exit ( void ); 154 | 155 | /** 156 | * @brief Releases all resources used by an IPv4 session 157 | * @param session Session to be released 158 | */ 159 | void ntoh_ipv4_free_session ( pntoh_ipv4_session_t session ); 160 | 161 | /** 162 | * @brief Creates a new session with independent parameters to defragment IPv4 163 | * @param max_flows Max number of allowed flows in this session 164 | * @param max_mem Max. amount of memory used by the session 165 | * @param error Returned error code 166 | * @return A pointer to the new session or 0 when it fails 167 | */ 168 | pntoh_ipv4_session_t ntoh_ipv4_new_session ( unsigned int max_flows , unsigned long max_mem , unsigned int *error ); 169 | 170 | /** 171 | * @brief resizes the hash table of a given IPv4 session 172 | * @param IPv4 Session 173 | * @param size The new size of the hash table 174 | * @return NTOH_OK on success or the corresponding error code 175 | * 176 | **/ 177 | int ntoh_ipv4_resize_session ( pntoh_ipv4_session_t session , size_t size ); 178 | 179 | /** 180 | * @brief Finds an IP flow 181 | * @param tuple4 Flow information 182 | * @return Pointer to the flow on success or 0 when fails 183 | */ 184 | pntoh_ipv4_flow_t ntoh_ipv4_find_flow ( pntoh_ipv4_session_t session , pntoh_ipv4_tuple4_t tuple4 ); 185 | 186 | /** 187 | * @brief Adds a new IPv4 flow 188 | * @param tuple4 Flow information 189 | * @param function User defined function to receive defragmented datagrams 190 | * @param count_max Max. fragments allowed 191 | * @param udata User defined data associated with this flow 192 | * @param error Returned error code 193 | * @return A pointer to the new created flow 194 | */ 195 | pntoh_ipv4_flow_t ntoh_ipv4_new_flow ( pntoh_ipv4_session_t session , pntoh_ipv4_tuple4_t tuple4 , pipv4_dfcallback_t function , void *udata , unsigned int *error); 196 | 197 | /** 198 | * @brief Frees an IPv4 flow 199 | * @param session Pointer to the IPv4 session 200 | * @param flow IPv4 flow to be released 201 | * @param reason Value to be sent to the user-defined callback. Why has been freed the flow? 202 | */ 203 | void ntoh_ipv4_free_flow ( pntoh_ipv4_session_t session , pntoh_ipv4_flow_t *flow , unsigned short reason ); 204 | 205 | /** 206 | * @brief Adds a new IPv4 fragment to a given flow 207 | * @param session Pointer to the IPv4 session 208 | * @param flow Flow where the new fragment will be added 209 | * @param iphdr IPv4 Header of the fragment 210 | * @return NTOH_OK on success, or error code when it fails 211 | */ 212 | int ntoh_ipv4_add_fragment ( pntoh_ipv4_session_t session , pntoh_ipv4_flow_t flow , struct ip *iphdr ); 213 | 214 | /** 215 | * @brief Returns the total count of flows stored in the global hash table 216 | * @return Total count of stored flows 217 | */ 218 | unsigned int ntoh_ipv4_count_flows ( pntoh_ipv4_session_t session ); 219 | 220 | /** 221 | * @brief Gets the size of the flows table (max allowed flows) 222 | * @param session IPv4 Session 223 | * @return The max. amount of IPv4 flows that can be stored , or zero on error 224 | **/ 225 | unsigned int ntoh_ipv4_get_size ( pntoh_ipv4_session_t session ); 226 | 227 | /** 228 | * @brief Gets the tuple4 of a IPv4 flow 229 | * @param ip Pointer to the IPv4 header 230 | * @param tuple Pointer to the output tuple4 struct 231 | * @return NTOH_OK on success or the corresponding error code 232 | */ 233 | unsigned int ntoh_ipv4_get_tuple4 ( struct ip *ip , pntoh_ipv4_tuple4_t tuple ); 234 | 235 | #endif /* __LIBNTOH_IP4DF__ */ 236 | -------------------------------------------------------------------------------- /src/inc/ipv6defrag.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIBNTOH_IP6DF__ 2 | # define __LIBNTOH_IP6DF__ 3 | 4 | /******************************************************************************** 5 | * Copyright (c) 2012, Chema Garcia * 6 | * All rights reserved. * 7 | * * 8 | * Redistribution and use in source and binary forms, with or * 9 | * without modification, are permitted provided that the following * 10 | * conditions are met: * 11 | * * 12 | * * Redistributions of source code must retain the above * 13 | * copyright notice, this list of conditions and the following * 14 | * disclaimer. * 15 | * * 16 | * * Redistributions in binary form must reproduce the above * 17 | * copyright notice, this list of conditions and the following * 18 | * disclaimer in the documentation and/or other materials provided * 19 | * with the distribution. * 20 | * * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * 25 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 31 | * POSSIBILITY OF SUCH DAMAGE. * 32 | ********************************************************************************/ 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #define NTOH_IPV6_IS_FRAGMENT(val) (((struct ip6_hdr*)val)->ip6_nxt==IPPROTO_FRAGMENT && \ 39 | ( \ 40 | (ntohs(((struct ip6_frag *)((unsigned char*)val+sizeof(struct ip6_hdr)))->ip6f_offlg) & IP6F_OFF_MASK)>0 || \ 41 | (ntohs(((struct ip6_frag *)((unsigned char*)val+sizeof(struct ip6_hdr)))->ip6f_offlg & IP6F_MORE_FRAG)>0) \ 42 | )) 43 | 44 | /** @brief Struct to generate the flow key **/ 45 | typedef struct 46 | { 47 | /// source IP address 48 | unsigned char source[16]; 49 | /// destination IP address 50 | unsigned char destination[16]; 51 | /// Transport layer protocol 52 | unsigned char protocol; 53 | /// Identification 54 | unsigned int id; 55 | } ntoh_ipv6_tuple4_t, *pntoh_ipv6_tuple4_t; 56 | 57 | typedef unsigned int ntoh_ipv6_key_t; 58 | 59 | /** @brief Struct to store the information of each fragment */ 60 | typedef struct _ipv6_fragment_ 61 | { 62 | /// pointer to the next fragment 63 | struct _ipv6_fragment_ *next; 64 | /// fragment offset 65 | unsigned int offset; 66 | /// fragment data length 67 | unsigned int len; 68 | /// fragment data 69 | unsigned char *data; 70 | } ntoh_ipv6_fragment_t , *pntoh_ipv6_fragment_t; 71 | 72 | /** @brief Struct to store the information of each IPv6 flow */ 73 | typedef struct 74 | { 75 | /// flow identification data 76 | ntoh_ipv6_tuple4_t ident; 77 | /// flow key 78 | ntoh_ipv6_key_t key; 79 | /// fragments list 80 | pntoh_ipv6_fragment_t fragments; 81 | /// total amount of received data 82 | size_t meat; 83 | /// total amount of expected data 84 | size_t total; 85 | /// final fragment received? 86 | struct ip6_hdr *final_iphdr; 87 | /// user defined function to receive defragmented packets 88 | void *function; 89 | /// last activity 90 | struct timeval last_activ; 91 | /// user-defined data 92 | void *udata; 93 | ntoh_lock_t lock; 94 | } ntoh_ipv6_flow_t, *pntoh_ipv6_flow_t; 95 | 96 | typedef htable_t ipv6_flows_table_t; 97 | typedef phtable_t pipv6_flows_table_t; 98 | 99 | /** @brief Structure to store global parameters */ 100 | typedef struct _ipv6_session_ 101 | { 102 | struct _ipv6_session_ *next; 103 | 104 | /// max. number of IP flows 105 | sem_t max_flows; 106 | sem_t max_fragments; 107 | /// hash table to store IP flows 108 | pipv6_flows_table_t flows; 109 | /// connection tables related 110 | pthread_t tID; 111 | ntoh_lock_t lock; 112 | }ntoh_ipv6_session_t , *pntoh_ipv6_session_t; 113 | 114 | typedef struct 115 | { 116 | unsigned short init; 117 | pntoh_ipv6_session_t sessions_list; 118 | ntoh_lock_t lock; 119 | } ntoh_ipv6_params_t , *pntoh_ipv6_params_t; 120 | 121 | /// min. PMTU 122 | #ifndef MIN_IPV6_FRAGMENT_LENGTH 123 | # define MIN_IPV6_FRAGMENT_LENGTH 1280 124 | #endif 125 | 126 | /// max. IPv6 datagram fragment length 127 | #ifndef MAX_IPV6_DATAGRAM_LENGTH 128 | # define MAX_IPV6_DATAGRAM_LENGTH 4294967295UL // max size of jumbograms (using hop-by-hop options header) 129 | #endif 130 | 131 | /// IPv6 fragment timeout 132 | #ifndef DEFAULT_IPV6_FRAGMENT_TIMEOUT 133 | # define DEFAULT_IPV6_FRAGMENT_TIMEOUT 15 134 | #endif 135 | 136 | /// max. IPv6 allowed flows 137 | #ifndef DEFAULT_IPV6_MAX_FLOWS 138 | # define DEFAULT_IPV6_MAX_FLOWS 1024 139 | #endif 140 | 141 | /// max. IPv6 allowed fragments 142 | #ifndef DEFAULT_IPV6_MAX_FRAGMENTS 143 | # define DEFAULT_IPV6_MAX_FRAGMENTS ((12*1024*1024) / sizeof(ntoh_ipv6_fragment_t)) 144 | #endif 145 | 146 | typedef void(*pipv6_dfcallback_t) ( pntoh_ipv6_flow_t , pntoh_ipv6_tuple4_t , unsigned char* , size_t , unsigned short ); 147 | 148 | /** 149 | * @brief Initializes the IPv6 defragmentation 150 | */ 151 | void ntoh_ipv6_init ( void ); 152 | 153 | /** 154 | * @brief Flush all IPv6 sessions and release all resources 155 | */ 156 | void ntoh_ipv6_exit ( void ); 157 | 158 | /** 159 | * @brief Releases all resources used by an IPv6 session 160 | * @param session Session to be released 161 | */ 162 | void ntoh_ipv6_free_session ( pntoh_ipv6_session_t session ); 163 | 164 | /** 165 | * @brief Creates a new session with independent parameters to reassemble TCP segments 166 | * @param max_flows Max number of allowed flows in this session 167 | * @param max_mem Max. amount of memory used by the session 168 | * @param error Returned error code 169 | * @return A pointer to the new session or 0 when it fails 170 | */ 171 | pntoh_ipv6_session_t ntoh_ipv6_new_session ( unsigned int max_flows , unsigned long max_mem , unsigned int *error ); 172 | 173 | /** 174 | * @brief resizes the hash table of a given IPv4 session 175 | * @param IPv4 Session 176 | * @param size The new size of the hash table 177 | * @return NTOH_OK on success or the corresponding error code 178 | * 179 | **/ 180 | int ntoh_ipv6_resize_session ( pntoh_ipv6_session_t session , size_t size ); 181 | 182 | /** 183 | * @brief Finds an IP flow 184 | * @param tuple4 Flow information 185 | * @return Pointer to the flow on success or 0 when fails 186 | */ 187 | pntoh_ipv6_flow_t ntoh_ipv6_find_flow ( pntoh_ipv6_session_t session , pntoh_ipv6_tuple4_t tuple4 ); 188 | 189 | /** 190 | * @brief Adds a new IPv6 flow 191 | * @param tuple4 Flow information 192 | * @param function User defined function to receive defragmented datagrams 193 | * @param count_max Max. fragments allowed 194 | * @param udata User defined data associated with this flow 195 | * @return A pointer to the new created flow 196 | */ 197 | pntoh_ipv6_flow_t ntoh_ipv6_new_flow ( pntoh_ipv6_session_t session , pntoh_ipv6_tuple4_t tuple4 , pipv6_dfcallback_t function , void *udata , unsigned int *error); 198 | 199 | /** 200 | * @brief Frees an IPv6 flow 201 | * @param flow IPv6 flow to be freed 202 | * @param reason Why has been freed the flow? 203 | */ 204 | void ntoh_ipv6_free_flow ( pntoh_ipv6_session_t session , pntoh_ipv6_flow_t *flow , unsigned short reason ); 205 | 206 | /** 207 | * @brief Adds a new IPv6 fragment to a given flow 208 | * @param flow Flow where the new fragment will be added 209 | * @param iphdr IPv6 Header of the fragment 210 | * @return NTOH_OK on success, or error code when it fails 211 | */ 212 | int ntoh_ipv6_add_fragment ( pntoh_ipv6_session_t session , pntoh_ipv6_flow_t flow , struct ip6_hdr *iphdr ); 213 | 214 | /** 215 | * @brief Returns the total count of flows stored in the global hash table 216 | * @return Total count of stored flows 217 | */ 218 | unsigned int ntoh_ipv6_count_flows ( pntoh_ipv6_session_t session ); 219 | 220 | /** 221 | * @brief Gets the size of the flows table (max allowed flows) 222 | * @param session IPv6 Session 223 | * @return The max. amount of IPv6 flows that can be stored , or zero on error 224 | **/ 225 | unsigned int ntoh_ipv6_get_size ( pntoh_ipv6_session_t session ); 226 | 227 | /** 228 | * @brief Gets the tuple4 of a IPv6 flow 229 | * @param ip Pointer to the IPv6 header 230 | * @param tuple Pointer to the output tuple4 struct 231 | * @return NTOH_OK on success or the corresponding error code 232 | */ 233 | unsigned int ntoh_ipv6_get_tuple4 ( struct ip6_hdr *ip , pntoh_ipv6_tuple4_t tuple ); 234 | 235 | #endif /* __LIBNTOH_IP6DF__ */ 236 | -------------------------------------------------------------------------------- /src/inc/libntoh.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIBNTOH_H__ 2 | # define __LIBNTOH_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" 6 | { 7 | #endif 8 | 9 | /******************************************************************************** 10 | * Copyright (c) 2012, Chema Garcia * 11 | * All rights reserved. * 12 | * * 13 | * Redistribution and use in source and binary forms, with or * 14 | * without modification, are permitted provided that the following * 15 | * conditions are met: * 16 | * * 17 | * * Redistributions of source code must retain the above * 18 | * copyright notice, this list of conditions and the following * 19 | * disclaimer. * 20 | * * 21 | * * Redistributions in binary form must reproduce the above * 22 | * copyright notice, this list of conditions and the following * 23 | * disclaimer in the documentation and/or other materials provided * 24 | * with the distribution. * 25 | * * 26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 27 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * 30 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 36 | * POSSIBILITY OF SUCH DAMAGE. * 37 | ********************************************************************************/ 38 | 39 | #include 40 | #include 41 | 42 | /** @brief Common return values */ 43 | #define NTOH_OK 0 44 | 45 | /* IP defragmentation return values */ 46 | #define NTOH_IP_INCORRECT_FLOW -1 47 | #define NTOH_INCORRECT_LENGTH -2 48 | #define NTOH_INCORRECT_IP_HEADER -3 49 | #define NTOH_INCORRECT_IP_HEADER_LENGTH -4 50 | #define NTOH_NOT_IPV4 -5 51 | #define NTOH_IP_ADDRESSES_MISMATCH -6 52 | #define NTOH_NOT_AN_IP_FRAGMENT -7 53 | #define NTOH_TOO_LOW_IP_FRAGMENT_LENGTH -8 54 | #define NTOH_IP_FRAGMENT_OVERRUN -9 55 | #define NTOH_MAX_IP_FRAGMENTS_REACHED -10 56 | #define NTOH_NOT_ENOUGH_DATA -11 57 | #define NTOH_NOT_IPV6 -12 58 | 59 | /* TCP streams reassembly return values */ 60 | #define NTOH_INCORRECT_SESSION -13 61 | #define NTOH_INCORRECT_TCP_HEADER_LENGTH -14 62 | #define NTOH_TCP_PORTS_MISMATCH -15 63 | #define NTOH_INVALID_FLAGS -16 64 | #define NTOH_TOO_LOW_SEQ_NUMBER -17 65 | #define NTOH_TOO_LOW_ACK_NUMBER -18 66 | #define NTOH_PAWS_FAILED -19 67 | #define NTOH_HANDSHAKE_FAILED -20 68 | #define NTOH_MAX_SYN_RETRIES_REACHED -21 69 | #define NTOH_MAX_SYNACK_RETRIES_REACHED -22 70 | #define NTOH_NO_WINDOW_SPACE_LEFT -23 71 | #define NTOH_NOT_TCP -24 72 | #define NTOH_SYNCHRONIZING -25 73 | #define NTOH_NOT_INITIALIZED -26 74 | 75 | /* TCP streams reassembly notification cases values */ 76 | #define NTOH_REASON_HSFAILED 1 77 | #define NTOH_REASON_ESTABLISHED 2 78 | #define NTOH_REASON_DATA 3 79 | #define NTOH_REASON_CLOSED 4 80 | #define NTOH_REASON_TIMEDOUT 5 81 | #define NTOH_REASON_EXIT 6 82 | #define NTOH_REASON_OOO 7 83 | #define NTOH_REASON_SEGMENT_LOST 8 // @contrib: di3online - https://github.com/di3online 84 | #define NTOH_REASON_MAX_SYN_RETRIES_REACHED 9 85 | #define NTOH_REASON_MAX_SYNACK_RETRIES_REACHED 10 86 | #define NTOH_REASON_SYNC 11 87 | #define NTOH_REASON_NOWINDOW 12 88 | 89 | /* IP defragmentation notification cases values */ 90 | #define NTOH_REASON_DEFRAGMENTED_DATAGRAM 13 91 | #define NTOH_REASON_TIMEDOUT_FRAGMENTS 14 92 | 93 | /* API errors */ 94 | #define NTOH_ERROR_NOMEM 1 95 | #define NTOH_ERROR_NOSPACE 2 96 | #define NTOH_ERROR_NOKEY 3 97 | #define NTOH_ERROR_NOFUNCTION 4 98 | #define NTOH_ERROR_INVALID_TUPLE5 5 99 | #define NTOH_ERROR_PARAMS 6 100 | #define NTOH_ERROR_INIT 7 101 | 102 | typedef struct 103 | { 104 | pthread_mutex_t mutex; 105 | pthread_cond_t pcond; 106 | int use; 107 | } ntoh_lock_t , *pntoh_lock_t; 108 | 109 | /** @brief Header files */ 110 | #include "common.h" 111 | #include "ipv4defrag.h" 112 | #include "ipv6defrag.h" 113 | #include "tcpreassembly.h" 114 | 115 | /** 116 | * @brief Returns library version 117 | * @return The version of the library 118 | */ 119 | const char* ntoh_version ( void ); 120 | 121 | /** 122 | * @brief Returns the description string of ntoh_add_tcpsegment and ntoh_add_ipv4fragment 123 | * @param val Value returned by those functions 124 | * @return Description string or 0 if val is not found 125 | */ 126 | const char* ntoh_get_retval_desc ( int val ); 127 | 128 | /** 129 | * @brief Returns the description string about why a segment/fragment has been sent to the user 130 | * @param val 131 | * @return Description string or 0 if val is not found 132 | */ 133 | const char* ntoh_get_reason ( unsigned int val ); 134 | 135 | /** 136 | * @brief Returns the description of an error 137 | * @param val Error code 138 | * @returns Description string or 0 if val is not found 139 | */ 140 | const char* ntoh_get_errdesc ( unsigned int val ); 141 | 142 | /** 143 | * @brief Initializes the library (TCP and IPv4) 144 | */ 145 | void ntoh_init ( void ); 146 | 147 | /** 148 | * @brief Releases all resources 149 | */ 150 | void ntoh_exit ( void ); 151 | 152 | #ifdef __cplusplus 153 | } 154 | #endif 155 | 156 | #endif /*__LIBNTOH_H__ */ 157 | -------------------------------------------------------------------------------- /src/inc/sfhash.h: -------------------------------------------------------------------------------- 1 | #ifndef _LINUX_SFHASH_H 2 | #define _LINUX_SFHASH_H 3 | 4 | /* sfhash.h: SuperFastHash support. 5 | * 6 | * Copyright (C) 2004 by Paul Hsieh 7 | * 8 | * http://www.azillionmonkeys.com/qed/hash.html 9 | * 10 | */ 11 | 12 | unsigned int sfhash(const void * key, unsigned int len, unsigned int initval); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/inc/tcpreassembly.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIBNTOH_TCPRS_H__ 2 | # define __LIBNTOH_TCPRS_H__ 3 | 4 | /******************************************************************************** 5 | * Copyright (c) 2012, Chema Garcia * 6 | * All rights reserved. * 7 | * * 8 | * Redistribution and use in source and binary forms, with or * 9 | * without modification, are permitted provided that the following * 10 | * conditions are met: * 11 | * * 12 | * * Redistributions of source code must retain the above * 13 | * copyright notice, this list of conditions and the following * 14 | * disclaimer. * 15 | * * 16 | * * Redistributions in binary form must reproduce the above * 17 | * copyright notice, this list of conditions and the following * 18 | * disclaimer in the documentation and/or other materials provided * 19 | * with the distribution. * 20 | * * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * 25 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 31 | * POSSIBILITY OF SUCH DAMAGE. * 32 | ********************************************************************************/ 33 | 34 | #define __FAVOR_BSD 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include "sfhash.h" 43 | 44 | #ifndef IP6_ADDR_LEN 45 | # define IP6_ADDR_LEN 16 46 | #endif 47 | 48 | #ifndef IP4_ADDR_LEN 49 | # define IP4_ADDR_LEN 4 50 | #endif 51 | 52 | /** @brief connection status **/ 53 | enum _ntoh_tcp_status_ 54 | { 55 | NTOH_STATUS_CLOSED = 0, 56 | NTOH_STATUS_LISTEN, 57 | NTOH_STATUS_SYNSENT, 58 | NTOH_STATUS_SYNRCV, 59 | NTOH_STATUS_ESTABLISHED, 60 | NTOH_STATUS_CLOSING, 61 | NTOH_STATUS_CLOSEWAIT, 62 | NTOH_STATUS_FINWAIT1, 63 | NTOH_STATUS_FINWAIT2, 64 | NTOH_STATUS_LASTACK, 65 | NTOH_STATUS_TIMEWAIT 66 | }; 67 | 68 | /** @brief table to be resized **/ 69 | enum tcprs_resize_table 70 | { 71 | NTOH_RESIZE_STREAMS = 0, 72 | NTOH_RESIZE_TIMEWAIT 73 | }; 74 | 75 | /** @brief who closed the connection? **/ 76 | enum tcprs_who_closed 77 | { 78 | NTOH_CLOSEDBY_UNKNOWN = 0, 79 | NTOH_CLOSEDBY_CLIENT, 80 | NTOH_CLOSEDBY_SERVER 81 | }; 82 | 83 | // @contrib: di3online - https://github.com/di3online 84 | /** @brief who send the segment **/ 85 | enum tcprs_who_sent 86 | { 87 | NTOH_SENT_BY_CLIENT = 0, 88 | NTOH_SENT_BY_SERVER 89 | }; 90 | 91 | // @contrib: di3online - https://github.com/di3online 92 | /** @brief Control switch **/ 93 | enum check_timeout 94 | { 95 | NTOH_CHECK_TCP_SYNSENT_TIMEOUT = (1 << 0), 96 | NTOH_CHECK_TCP_SYNRCV_TIMEOUT = (1 << 1), 97 | NTOH_CHECK_TCP_ESTABLISHED_TIMEOUT = (1 << 2), 98 | NTOH_CHECK_TCP_FINWAIT2_TIMEOUT = (1 << 3), 99 | NTOH_CHECK_TCP_TIMEWAIT_TIMEOUT = (1 << 4), 100 | }; 101 | 102 | /** @brief key to identify connections **/ 103 | typedef unsigned int ntoh_tcp_key_t; 104 | 105 | /** @brief data to generate the connection key **/ 106 | typedef struct 107 | { 108 | ///source address 109 | unsigned int source[IP6_ADDR_LEN]; 110 | ///destination address 111 | unsigned int destination[IP6_ADDR_LEN]; 112 | ///source port 113 | unsigned short sport; 114 | ///destination port 115 | unsigned short dport; 116 | ///IP protocol version 4/6 117 | unsigned short protocol; 118 | } ntoh_tcp_tuple5_t, *pntoh_tcp_tuple5_t; 119 | 120 | /** @brief data sent to user-function **/ 121 | typedef struct _tcp_segment_ 122 | { 123 | struct _tcp_segment_ *next; 124 | ///SEQ number 125 | unsigned long seq; 126 | ///ACK number 127 | unsigned long ack; 128 | ///flags 129 | unsigned char flags; 130 | ///payload length 131 | unsigned int payload_len; 132 | ///segment origin 133 | unsigned short origin; 134 | ///TCP timestamp 135 | struct timeval tv; 136 | ///user provided data 137 | void *user_data; 138 | } ntoh_tcp_segment_t, *pntoh_tcp_segment_t; 139 | 140 | /** @brief peer information **/ 141 | typedef struct 142 | { 143 | ///IP address 144 | unsigned int addr[IP6_ADDR_LEN]; 145 | ///connection port 146 | unsigned short port; 147 | ///initial SEQ. number 148 | unsigned long isn; 149 | ///initial ACK. number 150 | unsigned long ian; 151 | ///NEXT SEQ. number 152 | unsigned long next_seq; 153 | ///TH_FIN | TH_RST sequence 154 | unsigned long final_seq; 155 | ///TCP window size 156 | unsigned int wsize; 157 | ///peer status 158 | unsigned int status; 159 | ///segments list 160 | pntoh_tcp_segment_t segments; 161 | ///Max. Segment Size 162 | unsigned int mss; 163 | ///Selective ACK. 164 | unsigned int sack; 165 | ///window scale factor 166 | unsigned int wscale; 167 | ///total window size 168 | unsigned long totalwin; 169 | ///last ts 170 | unsigned int lastts; 171 | ///send peer segments to user? 172 | unsigned short receive; 173 | } ntoh_tcp_peer_t, *pntoh_tcp_peer_t; 174 | 175 | /** @brief connection data **/ 176 | typedef struct _tcp_stream_ 177 | { 178 | struct _tcp_stream_ *next; 179 | 180 | ///data to generate the key to identify the connection 181 | ntoh_tcp_tuple5_t tuple; 182 | ///client data 183 | ntoh_tcp_peer_t client; 184 | ///server data 185 | ntoh_tcp_peer_t server; 186 | ///connection key 187 | ntoh_tcp_key_t key; 188 | ///connection status 189 | unsigned int status; 190 | ///who closed the connection 191 | unsigned short closedby; 192 | ///user-defined function to receive data 193 | void *function; 194 | ///last activity 195 | struct timeval last_activ; 196 | ///max. allowed SYN retries 197 | unsigned int syn_retries; 198 | ///max. allowed SYN/ACK retries 199 | unsigned int synack_retries; 200 | ///user-defined data linked to this stream 201 | void *udata; 202 | ntoh_lock_t lock; 203 | 204 | unsigned short enable_check_timeout; // @contrib: di3online - https://github.com/di3online 205 | unsigned short enable_check_nowindow; // @contrib: di3online - https://github.com/di3online 206 | } ntoh_tcp_stream_t, *pntoh_tcp_stream_t; 207 | 208 | typedef htable_t tcprs_streams_table_t; 209 | typedef phtable_t ptcprs_streams_table_t; 210 | 211 | /** @brief TCP session data **/ 212 | typedef struct _tcp_session_ 213 | { 214 | struct _tcp_session_ *next; 215 | 216 | /* max. streams */ 217 | sem_t max_streams; 218 | sem_t max_timewait; 219 | 220 | /* connections hash table */ 221 | ptcprs_streams_table_t streams; 222 | 223 | /* TIME-WAIT connections */ 224 | ptcprs_streams_table_t timewait; 225 | 226 | int rand; 227 | 228 | ntoh_lock_t lock; 229 | pthread_t tID; 230 | } ntoh_tcp_session_t , *pntoh_tcp_session_t; 231 | 232 | /** @brief structure to store the TCP sessions and the initialization status **/ 233 | typedef struct 234 | { 235 | /// is the library initialized? 236 | unsigned short init; 237 | /// TCP sessions list 238 | pntoh_tcp_session_t sessions_list; 239 | //// global mutex to create and free existing TCP sessions 240 | ntoh_lock_t lock; 241 | } ntoh_tcp_params_t , *pntoh_tcp_params_t; 242 | 243 | typedef void(*pntoh_tcp_callback_t) ( pntoh_tcp_stream_t , pntoh_tcp_peer_t , pntoh_tcp_peer_t , pntoh_tcp_segment_t , int, int ); 244 | 245 | /** @brief max allowed connections **/ 246 | #ifndef DEFAULT_TCP_MAX_STREAMS 247 | # define DEFAULT_TCP_MAX_STREAMS 4096 248 | #endif 249 | 250 | /** @brief max SYN retries **/ 251 | #ifndef DEFAULT_TCP_SYN_RETRIES 252 | # define DEFAULT_TCP_SYN_RETRIES 5 253 | #endif 254 | 255 | /** @brief max SYN/ACK retries **/ 256 | #ifndef DEFAULT_TCP_SYNACK_RETRIES 257 | # define DEFAULT_TCP_SYNACK_RETRIES 5 258 | #endif 259 | 260 | /** @brief SYN/ACK timeout **/ 261 | #ifndef DEFAULT_TCP_SYNSENT_TIMEOUT 262 | # define DEFAULT_TCP_SYNSENT_TIMEOUT 5 263 | #endif 264 | 265 | /** @brief ACK -> SYN timeout **/ 266 | #ifndef DEFAULT_TCP_SYNRCV_TIMEOUT 267 | # define DEFAULT_TCP_SYNRCV_TIMEOUT 5 268 | #endif 269 | 270 | /** @brief max. idle time for established connections **/ 271 | #ifndef DEFAULT_TCP_ESTABLISHED_TIMEOUT 272 | # define DEFAULT_TCP_ESTABLISHED_TIMEOUT 60 273 | #endif 274 | 275 | /** @brief max. idle time for "closed" connections **/ 276 | #ifndef DEFAULT_TCP_FINWAIT2_TIMEOUT 277 | # define DEFAULT_TCP_FINWAIT2_TIMEOUT 60 278 | #endif 279 | 280 | /** @brief Default timeout for TIMEWAIT tcp connections **/ 281 | #ifndef DEFAULT_TCP_TIMEWAIT_TIMEOUT 282 | # define DEFAULT_TCP_TIMEWAIT_TIMEOUT 2*DEFAULT_TCP_ESTABLISHED_TIMEOUT 283 | #endif 284 | 285 | /** @brief Macro to set the default TIMEWAIT for new connections **/ 286 | #ifndef DEFAULT_TCP_MAX_TIMEWAIT_STREAMS 287 | # define DEFAULT_TCP_MAX_TIMEWAIT_STREAMS(max) (max>0?max/3:DEFAULT_TCP_MAX_STREAMS/3) 288 | #endif 289 | 290 | /** @brief Delay to check session's streams timeout (ms) **/ 291 | #ifndef DEFAULT_TIMEOUT_DELAY 292 | # define DEFAULT_TIMEOUT_DELAY 3000 293 | #endif 294 | 295 | /** 296 | * @brief Initializes all needed resources for TCP reassembly 297 | */ 298 | void ntoh_tcp_init ( void ); 299 | 300 | /** 301 | * @brief Releases all resources used by TCP reassembly 302 | */ 303 | void ntoh_tcp_exit ( void ); 304 | 305 | /** 306 | * @brief Creates a new session with independent parameters to reassemble TCP segments 307 | * @param max_streams Max number of allowed streams in this session 308 | * @param max_timewait Max idle time fo TIME-WAIT connections (global) 309 | * @param error Returned error code 310 | * @return A pointer to the new session or 0 when it fails 311 | */ 312 | pntoh_tcp_session_t ntoh_tcp_new_session ( unsigned int max_streams , unsigned int max_timewait , unsigned int *error ); 313 | 314 | /** 315 | * @brief Releases all resources used by a session 316 | * @param session Session to be released 317 | */ 318 | void ntoh_tcp_free_session ( pntoh_tcp_session_t session ); 319 | 320 | /** 321 | * @brief Frees a given TCP stream 322 | * @param session Pointer to the session 323 | * @param stream Pointer to the stream 324 | * @param reason Value to be sent to the user defined function 325 | * @param extra Value to be sent to the user defined function 326 | */ 327 | void ntoh_tcp_free_stream ( pntoh_tcp_session_t session , pntoh_tcp_stream_t *stream , int reason , int extra ); 328 | 329 | /** 330 | * @brief Finds a TCP stream 331 | * @param session TCP Session 332 | * @param tuple5 Stream information 333 | * @return Pointer to the stream on success or 0 when fails 334 | */ 335 | pntoh_tcp_stream_t ntoh_tcp_find_stream ( pntoh_tcp_session_t session , pntoh_tcp_tuple5_t tuple5 ); 336 | 337 | /** 338 | * @brief Adds a new TCP stream 339 | * @param session TCP Session 340 | * @param tuple5 Stream information 341 | * @param function User defined function to receive the segments of this stream 342 | * @param udata User-defined data to be linked to the new stream 343 | * @param error Returned error code 344 | * @param enable_check_timeout enables/disables idle time verification for established connections // @contrib: di3online - https://github.com/di3online 345 | * @param enable_check_nowindow enables/disables TCP Window verification // @contrib: di3online - https://github.com/di3online 346 | * @return A pointer to the new stream on success or 0 when fails 347 | */ 348 | pntoh_tcp_stream_t ntoh_tcp_new_stream ( pntoh_tcp_session_t session , pntoh_tcp_tuple5_t tuple5 , pntoh_tcp_callback_t function , void *udata , unsigned int *error, unsigned short enable_check_timeout, unsigned short enable_check_nowindow ); 349 | 350 | /** 351 | * @brief Returns the total count of TCP streams stored in the global hash table 352 | * @param session TCP Session 353 | * @return Total count of stored streams 354 | */ 355 | unsigned int ntoh_tcp_count_streams ( pntoh_tcp_session_t session ); 356 | 357 | /** 358 | * @brief Adds a new segment to a given stream 359 | * @param session TCP Session 360 | * @param stream Pointer to the stream 361 | * @param ip_hdr IPv4/6 Header 362 | * @param len Total length of this segment 363 | * @param udata Used data associated with this segment 364 | * @return NTOH_OK on success or the corresponding error code 365 | */ 366 | int ntoh_tcp_add_segment ( pntoh_tcp_session_t session , pntoh_tcp_stream_t stream , void *ip , size_t len , void *udata ); 367 | 368 | /** 369 | * @brief Get the status string of a stream/peer 370 | * @param status Status id 371 | * @return Status string on success or 0 when fails 372 | */ 373 | const char *ntoh_tcp_get_status ( unsigned int status ); 374 | 375 | /** 376 | * @brief Gets the size of the sessions table (max allowed streams) 377 | * @param session TCP Session 378 | * @return The max. amount of TCP streams that can be stored , or zero on error 379 | **/ 380 | unsigned int ntoh_tcp_get_size ( pntoh_tcp_session_t session ); 381 | 382 | /** 383 | * @brief Gets the tuple5 of a TCP/IPv4 stream 384 | * @param ip Pointer to the IPv4/6 header 385 | * @param tcp Pointer to the TCP header 386 | * @param tuple Pointer to the output tuple5 struct 387 | * @return NTOH_OK on success or the corresponding error code 388 | */ 389 | unsigned int ntoh_tcp_get_tuple5 ( void *ip , struct tcphdr *tcp , pntoh_tcp_tuple5_t tuple ); 390 | 391 | /** 392 | * @brief Resizes the hash tables (streams | timewait) of a given TCP session 393 | * @param session TCP Session 394 | * @param table Table action (NTOH_RESIZE_STREAMS,NTOH_RESIZE_TIMEWAIT) 395 | * @param newsize The new size of the table 396 | * @return NTOH_OK on success or the corresponding error code 397 | * 398 | */ 399 | int ntoh_tcp_resize_session ( pntoh_tcp_session_t session , unsigned short table , size_t newsize ); 400 | 401 | #endif /* __LIBNTOH_TCPRS_H__ */ 402 | -------------------------------------------------------------------------------- /src/ipv4defrag.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2012, Chema Garcia * 3 | * All rights reserved. * 4 | * * 5 | * Redistribution and use in source and binary forms, with or * 6 | * without modification, are permitted provided that the following * 7 | * conditions are met: * 8 | * * 9 | * * Redistributions of source code must retain the above * 10 | * copyright notice, this list of conditions and the following * 11 | * disclaimer. * 12 | * * 13 | * * Redistributions in binary form must reproduce the above * 14 | * copyright notice, this list of conditions and the following * 15 | * disclaimer in the documentation and/or other materials provided * 16 | * with the distribution. * 17 | * * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 28 | * POSSIBILITY OF SUCH DAMAGE. * 29 | ********************************************************************************/ 30 | 31 | #define __FAVOR_BSD 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | static ntoh_ipv4_params_t params = { 0 , 0 }; 40 | 41 | #define NTOH_GET_IPV4_FRAGMENT_OFFSET(offset) (8*(ntohs(offset)&IP_OFFMASK)) 42 | #define IS_SET(a,b) (a & b) 43 | 44 | inline static ntoh_ipv4_key_t ip_get_hashkey ( pntoh_ipv4_tuple4_t tuple4 ) 45 | { 46 | ntoh_ipv4_key_t ret = 0; 47 | unsigned int hold = 0; 48 | 49 | if ( !tuple4 ) 50 | return ret; 51 | 52 | // @contrib: Eosis - https://github.com/Eosis 53 | ret = tuple4->source ^ tuple4->destination; 54 | ret ^= tuple4->id; 55 | hold = tuple4->protocol; 56 | hold = hold << 16; //skip the id bits 57 | ret ^= hold; 58 | 59 | return ret; 60 | } 61 | 62 | /** @brief API to get the size of the flows table (max allowed flows) **/ 63 | unsigned int ntoh_ipv4_get_size ( pntoh_ipv4_session_t session ) 64 | { 65 | unsigned int ret = 0; 66 | 67 | if ( !session ) 68 | return ret; 69 | 70 | lock_access ( & (session->lock) ); 71 | ret = session->flows->table_size; 72 | unlock_access ( & (session->lock) ); 73 | 74 | return ret; 75 | } 76 | 77 | /** @brief API to get a tuple4 **/ 78 | unsigned int ntoh_ipv4_get_tuple4 ( struct ip *ip , pntoh_ipv4_tuple4_t tuple ) 79 | { 80 | if ( !ip || !tuple ) 81 | return NTOH_ERROR_PARAMS; 82 | 83 | tuple->destination = ip->ip_dst.s_addr; 84 | tuple->source = ip->ip_src.s_addr; 85 | tuple->id = ip->ip_id; 86 | tuple->protocol = ip->ip_p; 87 | 88 | return NTOH_OK; 89 | } 90 | 91 | unsigned short ipv4_equal_tuple ( void *a , void *b ) 92 | { 93 | unsigned short ret = 0; 94 | 95 | if ( ! memcmp ( a , (void*)&((pntoh_ipv4_flow_t)b)->ident , sizeof ( ntoh_ipv4_tuple4_t) ) ) 96 | ret++; 97 | 98 | return ret; 99 | } 100 | 101 | pntoh_ipv4_flow_t ntoh_ipv4_find_flow ( pntoh_ipv4_session_t session , pntoh_ipv4_tuple4_t tuple4 ) 102 | { 103 | ntoh_ipv4_key_t key = 0; 104 | pntoh_ipv4_flow_t ret = 0; 105 | 106 | if ( !params.init || !session || !tuple4 ) 107 | return ret; 108 | 109 | key = ip_get_hashkey( tuple4 ); 110 | 111 | lock_access( &session->lock ); 112 | ret = htable_find ( session->flows , key, tuple4); 113 | 114 | unlock_access( &session->lock ); 115 | 116 | return ret; 117 | } 118 | 119 | pntoh_ipv4_flow_t ntoh_ipv4_new_flow ( pntoh_ipv4_session_t session , pntoh_ipv4_tuple4_t tuple4 , pipv4_dfcallback_t function , void *udata , unsigned int *error) 120 | { 121 | pntoh_ipv4_flow_t ret = 0; 122 | 123 | if ( error != 0 ) 124 | *error = 0; 125 | 126 | if ( !params.init ) 127 | { 128 | if ( error != 0 ) 129 | *error = NTOH_ERROR_INIT; 130 | return ret; 131 | } 132 | 133 | if ( !session || !tuple4 || !function ) 134 | { 135 | if ( error != 0 ) 136 | *error = NTOH_ERROR_PARAMS; 137 | return ret; 138 | } 139 | 140 | if ( sem_trywait( &session->max_flows ) != 0 ) 141 | { 142 | if ( error != 0 ) 143 | *error = NTOH_ERROR_NOSPACE; 144 | 145 | return ret; 146 | } 147 | 148 | if ( !( ret = (pntoh_ipv4_flow_t) calloc( 1, sizeof(ntoh_ipv4_flow_t) ) ) ) 149 | return ret; 150 | 151 | memcpy( &( ret->ident ), tuple4, sizeof(ntoh_ipv4_tuple4_t) ); 152 | ret->key = ip_get_hashkey( tuple4 ); 153 | 154 | gettimeofday( &ret->last_activ, 0 ); 155 | ret->function = (void*) function; 156 | ret->udata = udata; 157 | 158 | ret->lock.use = 0; 159 | pthread_mutex_init ( &ret->lock.mutex , 0 ); 160 | pthread_cond_init ( &ret->lock.pcond , 0 ); 161 | 162 | lock_access( &session->lock ); 163 | 164 | htable_insert ( session->flows , ret->key , ret ); 165 | 166 | unlock_access( &session->lock ); 167 | 168 | return ret; 169 | } 170 | 171 | /* insert a new fragment */ 172 | inline static pntoh_ipv4_fragment_t insert_fragment ( pntoh_ipv4_fragment_t list , pntoh_ipv4_fragment_t frag ) 173 | { 174 | pntoh_ipv4_fragment_t aux = list; 175 | 176 | if ( !aux ) 177 | return frag; 178 | 179 | if ( frag->offset > list->offset ) 180 | { 181 | frag->next = list; 182 | return frag; 183 | } 184 | 185 | /* finds the correct position for the new fragment */ 186 | /// Based on 4.3 BSD, we will give priority to fragments with lower offset to avoid teardrop attack 187 | for ( ; aux->next != 0 && frag->offset < aux->offset ; aux = aux->next ); 188 | 189 | if ( aux->next == 0 ) 190 | aux->next = frag; 191 | else{ 192 | frag->next = aux->next; 193 | aux->next = frag; 194 | } 195 | 196 | return list; 197 | } 198 | 199 | inline static unsigned short cksum(unsigned short *buf, int nwords) 200 | { 201 | unsigned long sum; 202 | 203 | for(sum=0; nwords>0; nwords--) 204 | sum += *buf++; 205 | 206 | sum = (sum >> 16) + (sum &0xffff); 207 | sum += (sum >> 16); 208 | 209 | return (unsigned short)(~sum); 210 | } 211 | 212 | 213 | /* build the complete datagram from all collected IPv4 fragments */ 214 | inline static unsigned char *build_datagram ( pntoh_ipv4_session_t session , pntoh_ipv4_flow_t flow ) 215 | { 216 | pntoh_ipv4_fragment_t tmp; 217 | pntoh_ipv4_fragment_t fragment; 218 | struct ip *iphdr; 219 | unsigned int offsethdr; 220 | unsigned char *ret; 221 | 222 | fragment = flow->fragments; 223 | iphdr = flow->final_iphdr; 224 | offsethdr = iphdr == 0 ? 0 : 4*iphdr->ip_hl; 225 | ret = (unsigned char*) calloc ( flow->total + offsethdr , sizeof ( unsigned char ) ); 226 | 227 | while ( fragment != 0 ) 228 | { 229 | memcpy ( &ret[offsethdr + fragment->offset] , fragment->data , fragment->len ); 230 | tmp = fragment; 231 | fragment = fragment->next; 232 | free ( tmp->data ); 233 | free ( tmp ); 234 | sem_post ( &session->max_fragments ); 235 | } 236 | flow->fragments = 0; 237 | 238 | /* fix ip header data */ 239 | if ( offsethdr > 0 ) 240 | { 241 | memcpy ( ret , iphdr , offsethdr ); 242 | iphdr = (struct ip*)ret; 243 | iphdr->ip_len = htons(flow->total); 244 | iphdr->ip_sum = 0; 245 | iphdr->ip_sum = cksum ( (unsigned short*) iphdr , (int)offsethdr ); 246 | free ( flow->final_iphdr ); 247 | 248 | flow->meat += offsethdr; 249 | flow->total += offsethdr; 250 | } 251 | 252 | return ret; 253 | } 254 | 255 | inline static void __ipv4_free_flow ( pntoh_ipv4_session_t session , pntoh_ipv4_flow_t *flow , unsigned short reason ) 256 | { 257 | unsigned char *buffer = 0; 258 | pntoh_ipv4_flow_t item = 0; 259 | 260 | if ( !flow || !(*flow) ) 261 | return; 262 | 263 | item = *flow; 264 | 265 | buffer = build_datagram ( session , item ); 266 | 267 | /* notify to the user */ 268 | ( (pipv4_dfcallback_t) item->function )( item, &item->ident, buffer , item->meat , reason ); 269 | free ( buffer ); 270 | 271 | htable_remove ( session->flows , item->key, &(item->ident) ); 272 | 273 | sem_post( &session->max_flows ); 274 | 275 | free_lockaccess ( &item->lock ); 276 | 277 | free( item ); 278 | 279 | *flow = 0; 280 | 281 | return; 282 | } 283 | 284 | void ntoh_ipv4_free_flow ( pntoh_ipv4_session_t session , pntoh_ipv4_flow_t *flow , unsigned short reason ) 285 | { 286 | if ( !params.init || !flow || !(*flow) ) 287 | return; 288 | 289 | lock_access( &session->lock ); 290 | 291 | lock_access ( &(*flow)->lock ); 292 | __ipv4_free_flow ( session , flow , reason ); 293 | 294 | unlock_access( &session->lock ); 295 | 296 | return; 297 | } 298 | 299 | int ntoh_ipv4_add_fragment ( pntoh_ipv4_session_t session , pntoh_ipv4_flow_t flow , struct ip *iphdr ) 300 | { 301 | size_t iphdr_len = 0; 302 | size_t len = 0; 303 | unsigned short offset = 0; 304 | unsigned short flags = 0; 305 | unsigned int data_len = 0; 306 | unsigned char *data = 0; 307 | int ret = NTOH_OK; 308 | pntoh_ipv4_fragment_t frag = 0; 309 | 310 | if ( !params.init ) 311 | return NTOH_NOT_INITIALIZED; 312 | 313 | if ( !session ) 314 | return NTOH_INCORRECT_SESSION; 315 | 316 | if ( !flow ) 317 | return NTOH_IP_INCORRECT_FLOW; 318 | 319 | if ( !iphdr ) 320 | return NTOH_INCORRECT_IP_HEADER; 321 | 322 | /* check if it is an IPv4 packet */ 323 | if ( iphdr->ip_v != 4 ) 324 | return NTOH_NOT_IPV4; 325 | 326 | /* get IP header and data length */ 327 | if ( ( iphdr_len = 4 * ( iphdr->ip_hl ) ) < sizeof(struct ip) ) 328 | return NTOH_INCORRECT_IP_HEADER_LENGTH; 329 | 330 | if ( ( len = ntohs ( iphdr->ip_len ) ) <= iphdr_len ) 331 | return NTOH_NOT_ENOUGH_DATA; 332 | 333 | data_len = len - iphdr_len; 334 | data = (unsigned char*) iphdr + iphdr_len; 335 | 336 | lock_access ( &flow->lock ); 337 | 338 | /* check if addresses matches */ 339 | if ( flow->ident.source != iphdr->ip_src.s_addr || flow->ident.destination != iphdr->ip_dst.s_addr ) 340 | { 341 | ret = NTOH_IP_ADDRESSES_MISMATCH; 342 | goto exitp; 343 | } 344 | 345 | flags = ntohs( iphdr->ip_off ); 346 | offset = NTOH_GET_IPV4_FRAGMENT_OFFSET(iphdr->ip_off); 347 | 348 | /* check if it is a fragment */ 349 | if ( !( IS_SET(flags,IP_MF) || offset > 0 ) || IS_SET(flags,IP_DF) ) 350 | { 351 | ret = NTOH_NOT_AN_IP_FRAGMENT; 352 | goto exitp; 353 | } 354 | 355 | /* checks if the fragment is hand crafted */ 356 | if ( IS_SET(flags,IP_MF) && data_len < MIN_IPV4_FRAGMENT_LENGTH ) 357 | { 358 | ret = NTOH_TOO_LOW_IP_FRAGMENT_LENGTH; 359 | goto exitp; 360 | } 361 | 362 | /* (1/2) checks if data length will overload max. amount of data allowed for an IPv4 datagram */ 363 | if ( flow->meat + data_len > MAX_IPV4_DATAGRAM_LENGTH ) 364 | { 365 | ret = NTOH_IP_FRAGMENT_OVERRUN; 366 | goto exitp; 367 | } 368 | 369 | /* (2/2) checks if data length will overload max. amount of data allowed for an IPv4 datagram */ 370 | if ( offset + data_len > MAX_IPV4_DATAGRAM_LENGTH ) 371 | { 372 | ret = NTOH_IP_FRAGMENT_OVERRUN; 373 | goto exitp; 374 | } 375 | 376 | sem_wait ( &session->max_fragments ); 377 | 378 | /* inserts the new fragment into the list */ 379 | frag = (pntoh_ipv4_fragment_t) calloc ( 1 , sizeof ( ntoh_ipv4_fragment_t ) ); 380 | frag->len = data_len; 381 | frag->offset = offset; 382 | frag->data = (unsigned char*) calloc ( data_len , sizeof ( unsigned char ) ); 383 | memcpy ( frag->data , data , data_len ); 384 | flow->fragments = insert_fragment ( flow->fragments , frag ); 385 | 386 | if ( flow->total < offset + data_len ) 387 | flow->total = offset + data_len; 388 | 389 | flow->meat += data_len; 390 | 391 | /* it is the final fragment */ 392 | if ( !IS_SET(flags,IP_MF) ) 393 | { 394 | flow->final_iphdr = (struct ip*) calloc ( iphdr_len , sizeof ( unsigned char ) ); 395 | memcpy ( flow->final_iphdr , iphdr , iphdr_len ); 396 | } 397 | 398 | /* if there are no holes */ 399 | if ( flow->final_iphdr != 0 && flow->total == flow->meat ) 400 | { 401 | 402 | lock_access ( &session->lock ); 403 | __ipv4_free_flow ( session , &flow , NTOH_REASON_DEFRAGMENTED_DATAGRAM ); 404 | unlock_access ( &session->lock ); 405 | }else 406 | gettimeofday( &flow->last_activ, 0 ); 407 | 408 | exitp: 409 | if ( flow != 0 ) 410 | unlock_access ( &flow->lock ); 411 | 412 | return ret; 413 | } 414 | 415 | unsigned int ntoh_ipv4_count_flows ( pntoh_ipv4_session_t session ) 416 | { 417 | unsigned int ret = 0; 418 | int count; 419 | 420 | if ( !params.init ) 421 | return ret; 422 | 423 | lock_access( ¶ms.lock ); 424 | 425 | sem_getvalue ( &session->max_flows , &count ); 426 | ret = session->flows->table_size - count; 427 | 428 | // ret = htable_count ( session->flows ); 429 | 430 | unlock_access( ¶ms.lock ); 431 | 432 | return ret; 433 | } 434 | 435 | inline static void ip_check_timeouts ( pntoh_ipv4_session_t session ) 436 | { 437 | struct timeval tv = { 0 , 0 }; 438 | pntoh_ipv4_flow_t item; 439 | unsigned int i = 0; 440 | phtnode_t node = 0; 441 | phtnode_t prev = 0; 442 | 443 | lock_access( &session->lock ); 444 | 445 | /* iterates between flows */ 446 | for ( i = 0 ; i < session->flows->table_size ; i++ ) 447 | { 448 | gettimeofday ( &tv , 0 ); 449 | node = prev = session->flows->table[i]; 450 | while ( node != 0 ) 451 | { 452 | item = (pntoh_ipv4_flow_t) node->val; 453 | 454 | /* timeout expired */ 455 | if ( DEFAULT_IPV4_FRAGMENT_TIMEOUT < tv.tv_sec - item->last_activ.tv_sec ) 456 | { 457 | lock_access ( &item->lock ); 458 | __ipv4_free_flow ( session , &item , NTOH_REASON_TIMEDOUT_FRAGMENTS ); 459 | if (node != prev) 460 | { 461 | node = prev; 462 | }else{ 463 | node = 0; 464 | } 465 | }else{ 466 | prev = node; 467 | node = node->next; 468 | } 469 | } 470 | } 471 | 472 | unlock_access( &session->lock ); 473 | 474 | return; 475 | } 476 | 477 | static void *timeouts_thread ( void *p ) 478 | { 479 | pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, 0 ); 480 | 481 | while ( 1 ) 482 | { 483 | ip_check_timeouts( (pntoh_ipv4_session_t) p ); 484 | pthread_testcancel(); 485 | sleep( 1 ); 486 | } 487 | 488 | pthread_exit( 0 ); 489 | //dummy return 490 | return 0; 491 | } 492 | 493 | pntoh_ipv4_session_t ntoh_ipv4_new_session ( unsigned int max_flows , unsigned long max_mem , unsigned int *error ) 494 | { 495 | pntoh_ipv4_session_t session; 496 | unsigned int max_fragments; 497 | 498 | if ( !max_flows ) 499 | max_flows = DEFAULT_IPV4_MAX_FLOWS; 500 | 501 | if ( ! (session = (pntoh_ipv4_session_t) calloc ( 1 , sizeof ( ntoh_ipv4_session_t ) )) ) 502 | { 503 | if ( error != 0 ) 504 | *error = NTOH_ERROR_NOMEM; 505 | return 0; 506 | } 507 | 508 | session->flows = htable_map (max_flows , &ipv4_equal_tuple ); 509 | sem_init ( &session->max_flows , 0 , max_flows ); 510 | session->lock.use = 0; 511 | pthread_mutex_init ( &session->lock.mutex , 0 ); 512 | pthread_cond_init ( &session->lock.pcond , 0 ); 513 | 514 | max_fragments = (int)(max_mem / sizeof ( ntoh_ipv4_fragment_t )); 515 | if ( !max_fragments ) 516 | max_fragments = DEFAULT_IPV4_MAX_FRAGMENTS; 517 | 518 | sem_init ( &session->max_fragments , 0 , max_fragments ); 519 | 520 | ntoh_ipv4_init(); 521 | 522 | lock_access ( ¶ms.lock ); 523 | 524 | if ( params.sessions_list != 0 ) 525 | session->next = params.sessions_list; 526 | params.sessions_list = session; 527 | 528 | unlock_access ( ¶ms.lock ); 529 | 530 | if ( error != 0 ) 531 | *error = NTOH_OK; 532 | 533 | pthread_create ( &session->tID , 0 , timeouts_thread , (void*) session ); 534 | 535 | return session; 536 | } 537 | 538 | inline static void __ipv4_free_session ( pntoh_ipv4_session_t session ) 539 | { 540 | ntoh_ipv4_key_t first = 0; 541 | pntoh_ipv4_session_t ptr = 0; 542 | pntoh_ipv4_flow_t item = 0; 543 | 544 | if ( !session ) 545 | return; 546 | 547 | if ( params.sessions_list == session ) 548 | params.sessions_list = session->next; 549 | else{ 550 | for ( ptr = params.sessions_list ; ptr != 0 && ptr->next != session ; ptr = ptr->next ); 551 | 552 | if ( ptr != 0 ) 553 | ptr->next = session->next; 554 | else 555 | return; 556 | } 557 | 558 | lock_access( &session->lock ); 559 | 560 | while ( ( first = htable_first ( session->flows ) ) != 0 ) 561 | { 562 | lock_access ( &item->lock ); 563 | __ipv4_free_flow ( session , &item , NTOH_REASON_EXIT ); 564 | } 565 | 566 | htable_destroy ( &(session->flows) ); 567 | 568 | pthread_cancel ( session->tID ); 569 | pthread_join ( session->tID , 0 ); 570 | sem_destroy ( &session->max_flows ); 571 | sem_destroy ( &session->max_fragments ); 572 | 573 | free_lockaccess ( &session->lock ); 574 | 575 | free ( session ); 576 | 577 | return; 578 | } 579 | 580 | void ntoh_ipv4_free_session ( pntoh_ipv4_session_t session ) 581 | { 582 | if ( !params.init || !session ) 583 | return; 584 | 585 | lock_access ( ¶ms.lock ); 586 | 587 | __ipv4_free_session ( session ); 588 | 589 | unlock_access ( ¶ms.lock ); 590 | 591 | return; 592 | } 593 | 594 | int ntoh_ipv4_resize_session ( pntoh_ipv4_session_t session , size_t newsize ) 595 | { 596 | pipv4_flows_table_t newht = 0 , curht = 0; 597 | pntoh_ipv4_flow_t item = 0; 598 | int current = 0; 599 | 600 | if ( ! session ) 601 | return NTOH_INCORRECT_SESSION; 602 | 603 | if ( ! newsize || newsize == session->flows->table_size ) 604 | return NTOH_OK; 605 | 606 | lock_access ( &session->lock ); 607 | 608 | curht = session->flows; 609 | 610 | // increase the size 611 | if ( newsize > curht->table_size ) 612 | newht = htable_map ( newsize , &ipv4_equal_tuple ); 613 | // decrease the size 614 | else 615 | { 616 | sem_getvalue ( &session->max_flows , ¤t ); 617 | if ( newsize < current ) 618 | { 619 | unlock_access ( &session->lock ); 620 | return NTOH_ERROR_NOSPACE; 621 | } 622 | } 623 | 624 | // moves all the flows to the new sessions table 625 | while ( ( current = htable_first ( curht ) ) != 0 ) 626 | { 627 | item = (pntoh_ipv4_flow_t) htable_remove ( curht , current , 0 ); 628 | htable_insert ( newht , current , item ); 629 | } 630 | htable_destroy ( &curht ); 631 | 632 | sem_init ( &session->max_flows , 0 , newsize ); 633 | session->flows = newht; 634 | 635 | unlock_access ( &session->lock ); 636 | 637 | return NTOH_OK; 638 | } 639 | 640 | void ntoh_ipv4_init ( void ) 641 | { 642 | if ( params.init ) 643 | return; 644 | 645 | params.lock.use = 0; 646 | pthread_mutex_init( ¶ms.lock.mutex, 0 ); 647 | pthread_cond_init( ¶ms.lock.pcond, 0 ); 648 | 649 | params.init = 1; 650 | return; 651 | } 652 | 653 | void ntoh_ipv4_exit ( void ) 654 | { 655 | if ( !params.init ) 656 | return; 657 | 658 | lock_access ( ¶ms.lock ); 659 | 660 | while ( params.sessions_list != 0 ) 661 | __ipv4_free_session ( params.sessions_list ); 662 | 663 | unlock_access ( ¶ms.lock ); 664 | 665 | free_lockaccess ( ¶ms.lock ); 666 | 667 | params.init = 0; 668 | 669 | return; 670 | } 671 | -------------------------------------------------------------------------------- /src/ipv6defrag.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2012, Chema Garcia * 3 | * All rights reserved. * 4 | * * 5 | * Redistribution and use in source and binary forms, with or * 6 | * without modification, are permitted provided that the following * 7 | * conditions are met: * 8 | * * 9 | * * Redistributions of source code must retain the above * 10 | * copyright notice, this list of conditions and the following * 11 | * disclaimer. * 12 | * * 13 | * * Redistributions in binary form must reproduce the above * 14 | * copyright notice, this list of conditions and the following * 15 | * disclaimer in the documentation and/or other materials provided * 16 | * with the distribution. * 17 | * * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 28 | * POSSIBILITY OF SUCH DAMAGE. * 29 | ********************************************************************************/ 30 | 31 | #define __FAVOR_BSD 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | 40 | static ntoh_ipv6_params_t params = { 0 , 0 }; 41 | 42 | #define NTOH_GET_IPV6_FRAGMENT_OFFSET(offset) (ntohs(offset)&~0x01) 43 | #define NTOH_GET_IPV6_MORE_FRAGMENTS(offset) ntohs(offset&IP6F_MORE_FRAG) 44 | #define IS_SET(a,b) (a & b) 45 | 46 | inline static ntoh_ipv6_key_t ip_get_hashkey ( pntoh_ipv6_tuple4_t tuple4 ) 47 | { 48 | unsigned char tmp[50] = {0}; 49 | ntoh_ipv6_key_t ret = 0; 50 | uint32_t i; 51 | 52 | if ( !tuple4 ) 53 | return ret; 54 | 55 | for ( i = 0 ; i < sizeof(tuple4->source) ; i++ ) 56 | { 57 | tmp[i] = tuple4->source[i]; 58 | tmp[sizeof(tuple4->source) + i ] = tuple4->destination[i]; 59 | } 60 | 61 | tmp[i] = tuple4->protocol; 62 | tmp[i+1] &= tuple4->id; 63 | 64 | // jenkins one-at-time hash algorithm 65 | for(ret = i = 0; i < sizeof(tmp) ; ++i) 66 | { 67 | ret += tmp[i]; 68 | ret += (ret << 10); 69 | ret ^= (ret >> 6); 70 | } 71 | 72 | ret += (ret << 3); 73 | ret ^= (ret >> 11); 74 | ret += (ret << 15); 75 | 76 | return ret; 77 | } 78 | 79 | /** @brief API to get the size of the flows table (max allowed flows) **/ 80 | unsigned int ntoh_ipv6_get_size ( pntoh_ipv6_session_t session ) 81 | { 82 | unsigned int ret = 0; 83 | 84 | if ( !session ) 85 | return ret; 86 | 87 | lock_access ( & (session->lock) ); 88 | ret = session->flows->table_size; 89 | unlock_access ( & (session->lock) ); 90 | 91 | return ret; 92 | } 93 | 94 | /** @brief API to get a tuple4 **/ 95 | unsigned int ntoh_ipv6_get_tuple4 ( struct ip6_hdr *ip , pntoh_ipv6_tuple4_t tuple ) 96 | { 97 | struct ip6_frag *frag; 98 | 99 | if ( !ip || !tuple ) 100 | return NTOH_ERROR_PARAMS; 101 | 102 | /** @todo: only checks the first header, should we verify them all? **/ 103 | if ( ip->ip6_nxt != IPPROTO_FRAGMENT ) 104 | return NTOH_NOT_AN_IP_FRAGMENT; 105 | 106 | memcpy ( (void*)tuple->source , (void*)&(ip->ip6_src) , sizeof ( tuple->source) ); 107 | memcpy ( (void*)tuple->destination , (void*)&(ip->ip6_dst) , sizeof ( tuple->destination) ); 108 | 109 | frag = (struct ip6_frag*)((unsigned char*)ip + sizeof ( struct ip6_hdr)); 110 | tuple->id = frag->ip6f_ident; // we dont care byte order (no ntoX needed) 111 | tuple->protocol = frag->ip6f_nxt; 112 | 113 | return NTOH_OK; 114 | } 115 | 116 | unsigned short ipv6_equal_tuple ( void *a , void *b ) 117 | { 118 | unsigned short ret = 0; 119 | 120 | if ( ! memcmp ( a , (void*)&((pntoh_ipv6_flow_t)b)->ident , sizeof ( ntoh_ipv6_tuple4_t) ) ) 121 | ret++; 122 | 123 | return ret; 124 | } 125 | 126 | pntoh_ipv6_flow_t ntoh_ipv6_find_flow ( pntoh_ipv6_session_t session , pntoh_ipv6_tuple4_t tuple4 ) 127 | { 128 | ntoh_ipv6_key_t key = 0; 129 | pntoh_ipv6_flow_t ret = 0; 130 | 131 | if ( !params.init || !session || !tuple4 ) 132 | return ret; 133 | 134 | key = ip_get_hashkey( tuple4 ); 135 | 136 | lock_access( &session->lock ); 137 | ret = htable_find ( session->flows , key, tuple4); 138 | 139 | unlock_access( &session->lock ); 140 | 141 | return ret; 142 | } 143 | 144 | pntoh_ipv6_flow_t ntoh_ipv6_new_flow ( pntoh_ipv6_session_t session , pntoh_ipv6_tuple4_t tuple4 , pipv6_dfcallback_t function , void *udata , unsigned int *error) 145 | { 146 | pntoh_ipv6_flow_t ret = 0; 147 | 148 | if ( error != 0 ) 149 | *error = 0; 150 | 151 | if ( !params.init ) 152 | { 153 | if ( error != 0 ) 154 | *error = NTOH_ERROR_INIT; 155 | return ret; 156 | } 157 | 158 | if ( !session || !tuple4 || !function ) 159 | { 160 | if ( error != 0 ) 161 | *error = NTOH_ERROR_PARAMS; 162 | return ret; 163 | } 164 | 165 | if ( sem_trywait( &session->max_flows ) != 0 ) 166 | { 167 | if ( error != 0 ) 168 | *error = NTOH_ERROR_NOSPACE; 169 | 170 | return ret; 171 | } 172 | 173 | if ( !( ret = (pntoh_ipv6_flow_t) calloc( 1, sizeof(ntoh_ipv6_flow_t) ) ) ) 174 | return ret; 175 | 176 | memcpy( &( ret->ident ), tuple4, sizeof(ntoh_ipv6_tuple4_t) ); 177 | ret->key = ip_get_hashkey( tuple4 ); 178 | 179 | gettimeofday( &ret->last_activ, 0 ); 180 | ret->function = (void*) function; 181 | ret->udata = udata; 182 | 183 | ret->lock.use = 0; 184 | pthread_mutex_init ( &ret->lock.mutex , 0 ); 185 | pthread_cond_init ( &ret->lock.pcond , 0 ); 186 | 187 | lock_access( &session->lock ); 188 | 189 | htable_insert ( session->flows , ret->key , ret ); 190 | 191 | unlock_access( &session->lock ); 192 | 193 | return ret; 194 | } 195 | 196 | /* insert a new fragment */ 197 | inline static pntoh_ipv6_fragment_t insert_fragment ( pntoh_ipv6_fragment_t list , pntoh_ipv6_fragment_t frag ) 198 | { 199 | pntoh_ipv6_fragment_t aux = list; 200 | 201 | if ( !aux ) 202 | return frag; 203 | 204 | if ( frag->offset > list->offset ) 205 | { 206 | frag->next = list; 207 | return frag; 208 | } 209 | 210 | /* finds the correct position for the new fragment */ 211 | /// Based on 4.3 BSD, we will give priority to fragments with lower offset to avoid teardrop attack 212 | for ( ; aux->next != 0 && frag->offset < aux->offset ; aux = aux->next ); 213 | 214 | if ( aux->next == 0 ) 215 | aux->next = frag; 216 | else{ 217 | frag->next = aux->next; 218 | aux->next = frag; 219 | } 220 | 221 | return list; 222 | } 223 | 224 | /* build the complete datagram from all collected IPv6 fragments */ 225 | inline static unsigned char *build_datagram ( pntoh_ipv6_session_t session , pntoh_ipv6_flow_t flow ) 226 | { 227 | pntoh_ipv6_fragment_t tmp; 228 | pntoh_ipv6_fragment_t fragment; 229 | struct ip6_hdr *iphdr; 230 | unsigned int offsethdr; 231 | unsigned char *ret; 232 | 233 | fragment = flow->fragments; 234 | iphdr = flow->final_iphdr; 235 | offsethdr = iphdr == 0 ? 0 : sizeof ( struct ip6_hdr ); 236 | ret = (unsigned char*) calloc ( flow->total + offsethdr , sizeof ( unsigned char ) ); 237 | 238 | while ( fragment != 0 ) 239 | { 240 | memcpy ( &ret[offsethdr + fragment->offset] , fragment->data , fragment->len ); 241 | tmp = fragment; 242 | fragment = fragment->next; 243 | free ( tmp->data ); 244 | free ( tmp ); 245 | sem_post ( &session->max_fragments ); 246 | } 247 | flow->fragments = 0; 248 | 249 | /* fix ip header data */ 250 | if ( offsethdr > 0 ) 251 | { 252 | memcpy ( ret , iphdr , offsethdr ); 253 | iphdr = (struct ip6_hdr*)ret; 254 | iphdr->ip6_plen = htons(flow->total); 255 | iphdr->ip6_nxt = flow->ident.protocol; 256 | free ( flow->final_iphdr ); 257 | flow->meat += offsethdr; 258 | flow->total += offsethdr; 259 | } 260 | 261 | return ret; 262 | } 263 | 264 | inline static void __ipv6_free_flow ( pntoh_ipv6_session_t session , pntoh_ipv6_flow_t *flow , unsigned short reason ) 265 | { 266 | unsigned char *buffer = 0; 267 | pntoh_ipv6_flow_t item = 0; 268 | 269 | if ( !flow || !(*flow) ) 270 | return; 271 | 272 | item = *flow; 273 | 274 | buffer = build_datagram ( session , item ); 275 | 276 | /* notify to the user */ 277 | ( (pipv6_dfcallback_t) item->function )( item, &item->ident, buffer , item->meat , reason ); 278 | free ( buffer ); 279 | 280 | htable_remove ( session->flows , item->key, &(item->ident) ); 281 | 282 | sem_post( &session->max_flows ); 283 | 284 | free_lockaccess ( &item->lock ); 285 | 286 | free( item ); 287 | 288 | *flow = 0; 289 | 290 | return; 291 | } 292 | 293 | void ntoh_ipv6_free_flow ( pntoh_ipv6_session_t session , pntoh_ipv6_flow_t *flow , unsigned short reason ) 294 | { 295 | if ( !params.init || !flow || !(*flow) ) 296 | return; 297 | 298 | lock_access( &session->lock ); 299 | 300 | lock_access ( &(*flow)->lock ); 301 | __ipv6_free_flow ( session , flow , reason ); 302 | 303 | unlock_access( &session->lock ); 304 | 305 | return; 306 | } 307 | 308 | int ntoh_ipv6_add_fragment ( pntoh_ipv6_session_t session , pntoh_ipv6_flow_t flow , struct ip6_hdr *iphdr ) 309 | { 310 | size_t iphdr_len = 0; 311 | unsigned short offset = 0; 312 | unsigned int data_len = 0; 313 | unsigned char *data = 0; 314 | int ret = NTOH_OK; 315 | pntoh_ipv6_fragment_t frag = 0; 316 | struct ip6_frag *frhdr = 0; 317 | size_t len = 0; 318 | 319 | if ( !params.init ) 320 | return NTOH_NOT_INITIALIZED; 321 | 322 | if ( !session ) 323 | return NTOH_INCORRECT_SESSION; 324 | 325 | if ( !flow ) 326 | return NTOH_IP_INCORRECT_FLOW; 327 | 328 | if ( !iphdr ) 329 | return NTOH_INCORRECT_IP_HEADER; 330 | 331 | /* too short length */ 332 | len = sizeof ( struct ip6_hdr ) + ntohs ( iphdr->ip6_plen ); 333 | if ( len <= sizeof(struct ip6_hdr) + sizeof ( struct ip6_frag ) ) 334 | return NTOH_INCORRECT_LENGTH; 335 | 336 | iphdr_len = sizeof ( struct ip6_hdr ); 337 | 338 | data_len = ntohs( iphdr->ip6_plen ) - sizeof ( struct ip6_frag ); 339 | data = (unsigned char*) iphdr + iphdr_len + sizeof ( struct ip6_frag ); 340 | 341 | /* check if it is an IPv6 packet */ 342 | if ( ((iphdr->ip6_vfc >> 4) & 0x0F) != 6 ) 343 | return NTOH_NOT_IPV6; 344 | 345 | lock_access ( &flow->lock ); 346 | 347 | /* check if addresses matches */ 348 | if ( memcmp ( flow->ident.source , (const void*)&(iphdr->ip6_src) , sizeof ( flow->ident.source )) != 0 || 349 | memcmp ( flow->ident.destination , (const void*)&(iphdr->ip6_dst) , sizeof ( flow->ident.destination )) != 0 ) 350 | { 351 | ret = NTOH_IP_ADDRESSES_MISMATCH; 352 | goto exitp; 353 | } 354 | 355 | /** @todo: only checks the first header, should we verify them all? **/ 356 | if ( iphdr->ip6_nxt != IPPROTO_FRAGMENT ) 357 | return NTOH_NOT_AN_IP_FRAGMENT; 358 | 359 | frhdr = (struct ip6_frag*)((unsigned char*)iphdr + sizeof ( struct ip6_hdr)); 360 | offset = NTOH_GET_IPV6_FRAGMENT_OFFSET(frhdr->ip6f_offlg); 361 | 362 | /* check if it is a fragment */ 363 | if ( !( NTOH_GET_IPV6_MORE_FRAGMENTS(frhdr->ip6f_offlg) || offset > 0 ) ) 364 | { 365 | ret = NTOH_NOT_AN_IP_FRAGMENT; 366 | goto exitp; 367 | } 368 | 369 | /* checks if the fragment is hand crafted */ 370 | if ( NTOH_GET_IPV6_MORE_FRAGMENTS(frhdr->ip6f_offlg) && data_len < MIN_IPV6_FRAGMENT_LENGTH ) 371 | { 372 | ret = NTOH_TOO_LOW_IP_FRAGMENT_LENGTH; 373 | goto exitp; 374 | } 375 | 376 | /* (1 / 2) checks if data length will overload max. amount of data allowed for an IPv6 datagram */ 377 | if ( flow->meat + data_len > MAX_IPV6_DATAGRAM_LENGTH ) 378 | { 379 | ret = NTOH_IP_FRAGMENT_OVERRUN; 380 | goto exitp; 381 | } 382 | 383 | /* (2 / 2) checks if data length will overload max. amount of data allowed for an IPv6 datagram */ 384 | if ( offset + data_len > MAX_IPV6_DATAGRAM_LENGTH ) 385 | { 386 | ret = NTOH_IP_FRAGMENT_OVERRUN; 387 | goto exitp; 388 | } 389 | 390 | sem_wait ( &session->max_fragments ); 391 | 392 | /* inserts the new fragment into the list */ 393 | frag = (pntoh_ipv6_fragment_t) calloc ( 1 , sizeof ( ntoh_ipv6_fragment_t ) ); 394 | frag->len = data_len; 395 | frag->offset = offset; 396 | frag->data = (unsigned char*) calloc ( data_len , sizeof ( unsigned char ) ); 397 | memcpy ( frag->data , data , data_len ); 398 | flow->fragments = insert_fragment ( flow->fragments , frag ); 399 | 400 | if ( flow->total < offset + data_len ) 401 | flow->total = offset + data_len; 402 | 403 | flow->meat += data_len; 404 | 405 | /* it is the final fragment? */ 406 | if ( ! NTOH_GET_IPV6_MORE_FRAGMENTS(frhdr->ip6f_offlg) ) 407 | { 408 | flow->final_iphdr = (struct ip6_hdr*) calloc ( iphdr_len , sizeof ( unsigned char ) ); 409 | memcpy ( flow->final_iphdr , iphdr , iphdr_len ); 410 | } 411 | 412 | /* if there are no holes */ 413 | if ( flow->final_iphdr != 0 && flow->total == flow->meat ) 414 | { 415 | lock_access ( &session->lock ); 416 | __ipv6_free_flow ( session , &flow , NTOH_REASON_DEFRAGMENTED_DATAGRAM ); 417 | unlock_access ( &session->lock ); 418 | }else 419 | gettimeofday( &flow->last_activ, 0 ); 420 | 421 | exitp: 422 | if ( flow != 0 ) 423 | unlock_access ( &flow->lock ); 424 | 425 | return ret; 426 | } 427 | 428 | unsigned int ntoh_ipv6_count_flows ( pntoh_ipv6_session_t session ) 429 | { 430 | unsigned int ret = 0; 431 | int count; 432 | 433 | if ( !params.init ) 434 | return ret; 435 | 436 | lock_access( ¶ms.lock ); 437 | 438 | sem_getvalue ( &session->max_flows , &count ); 439 | ret = session->flows->table_size - count; 440 | // ret = htable_count ( session->flows ); 441 | 442 | unlock_access( ¶ms.lock ); 443 | 444 | return ret; 445 | } 446 | 447 | inline static void ip_check_timeouts ( pntoh_ipv6_session_t session ) 448 | { 449 | struct timeval tv = { 0 , 0 }; 450 | pntoh_ipv6_flow_t item; 451 | unsigned int i = 0; 452 | phtnode_t node = 0; 453 | phtnode_t prev = 0; 454 | 455 | lock_access( &session->lock ); 456 | 457 | /* handly iterates between flows */ 458 | for ( i = 0 ; i < session->flows->table_size ; i++ ) 459 | { 460 | gettimeofday ( &tv , 0 ); 461 | node = prev = session->flows->table[i]; 462 | while ( node != 0 ) 463 | { 464 | item = (pntoh_ipv6_flow_t) node->val; 465 | 466 | /* timeout expired */ 467 | if ( DEFAULT_IPV6_FRAGMENT_TIMEOUT < tv.tv_sec - item->last_activ.tv_sec ) 468 | { 469 | lock_access ( &item->lock ); 470 | __ipv6_free_flow ( session , &item , NTOH_REASON_TIMEDOUT_FRAGMENTS ); 471 | if (node != prev) 472 | node = prev; 473 | else 474 | node = 0; 475 | }else{ 476 | prev = node; 477 | node = node->next; 478 | } 479 | } 480 | } 481 | 482 | unlock_access( &session->lock ); 483 | 484 | return; 485 | } 486 | 487 | static void *timeouts_thread ( void *p ) 488 | { 489 | pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, 0 ); 490 | 491 | while ( 1 ) 492 | { 493 | ip_check_timeouts( (pntoh_ipv6_session_t) p ); 494 | pthread_testcancel(); 495 | sleep( 1 ); 496 | } 497 | 498 | pthread_exit( 0 ); 499 | //dummy return 500 | return 0; 501 | } 502 | 503 | pntoh_ipv6_session_t ntoh_ipv6_new_session ( unsigned int max_flows , unsigned long max_mem , unsigned int *error ) 504 | { 505 | pntoh_ipv6_session_t session; 506 | unsigned int max_fragments; 507 | 508 | if ( !max_flows ) 509 | max_flows = DEFAULT_IPV6_MAX_FLOWS; 510 | 511 | if ( ! (session = (pntoh_ipv6_session_t) calloc ( 1 , sizeof ( ntoh_ipv6_session_t ) )) ) 512 | { 513 | if ( error != 0 ) 514 | *error = NTOH_ERROR_NOMEM; 515 | return 0; 516 | } 517 | 518 | session->flows = htable_map (max_flows , &ipv6_equal_tuple ); 519 | sem_init ( &session->max_flows , 0 , max_flows ); 520 | session->lock.use = 0; 521 | pthread_mutex_init ( &session->lock.mutex , 0 ); 522 | pthread_cond_init ( &session->lock.pcond , 0 ); 523 | 524 | max_fragments = (int)(max_mem / sizeof ( ntoh_ipv6_fragment_t )); 525 | if ( !max_fragments ) 526 | max_fragments = DEFAULT_IPV6_MAX_FRAGMENTS; 527 | 528 | sem_init ( &session->max_fragments , 0 , max_fragments ); 529 | 530 | ntoh_ipv6_init(); 531 | 532 | lock_access ( ¶ms.lock ); 533 | 534 | if ( params.sessions_list != 0 ) 535 | session->next = params.sessions_list; 536 | params.sessions_list = session; 537 | 538 | unlock_access ( ¶ms.lock ); 539 | 540 | if ( error != 0 ) 541 | *error = NTOH_OK; 542 | 543 | pthread_create ( &session->tID , 0 , timeouts_thread , (void*) session ); 544 | 545 | return session; 546 | } 547 | 548 | inline static void __ipv6_free_session ( pntoh_ipv6_session_t session ) 549 | { 550 | ntoh_ipv6_key_t first = 0; 551 | pntoh_ipv6_session_t ptr = 0; 552 | pntoh_ipv6_flow_t item = 0; 553 | 554 | if ( !session ) 555 | return; 556 | 557 | if ( params.sessions_list == session ) 558 | params.sessions_list = session->next; 559 | else{ 560 | for ( ptr = params.sessions_list ; ptr != 0 && ptr->next != session ; ptr = ptr->next ); 561 | 562 | if ( ptr != 0 ) 563 | ptr->next = session->next; 564 | else 565 | return; 566 | } 567 | 568 | lock_access( &session->lock ); 569 | 570 | while ( ( first = htable_first ( session->flows ) ) != 0 ) 571 | { 572 | lock_access ( &item->lock ); 573 | __ipv6_free_flow ( session , &item , NTOH_REASON_EXIT ); 574 | } 575 | 576 | htable_destroy ( &(session->flows) ); 577 | 578 | pthread_cancel ( session->tID ); 579 | pthread_join ( session->tID , 0 ); 580 | sem_destroy ( &session->max_flows ); 581 | sem_destroy ( &session->max_fragments ); 582 | 583 | free_lockaccess ( &session->lock ); 584 | 585 | free ( session ); 586 | 587 | return; 588 | } 589 | 590 | void ntoh_ipv6_free_session ( pntoh_ipv6_session_t session ) 591 | { 592 | if ( !params.init || !session ) 593 | return; 594 | 595 | lock_access ( ¶ms.lock ); 596 | 597 | __ipv6_free_session ( session ); 598 | 599 | unlock_access ( ¶ms.lock ); 600 | 601 | return; 602 | } 603 | 604 | int ntoh_ipv6_resize_session ( pntoh_ipv6_session_t session , size_t newsize ) 605 | { 606 | pipv6_flows_table_t newht = 0 , curht = 0; 607 | pntoh_ipv6_flow_t item = 0; 608 | int current = 0; 609 | 610 | if ( ! session ) 611 | return NTOH_INCORRECT_SESSION; 612 | 613 | if ( ! newsize || newsize == session->flows->table_size ) 614 | return NTOH_OK; 615 | 616 | lock_access ( &session->lock ); 617 | 618 | curht = session->flows; 619 | 620 | // increase the size 621 | if ( newsize > curht->table_size ) 622 | newht = htable_map ( newsize , &ipv6_equal_tuple ); 623 | // decrease the size 624 | else 625 | { 626 | sem_getvalue ( &session->max_flows , ¤t ); 627 | if ( newsize < current ) 628 | { 629 | unlock_access ( &session->lock ); 630 | return NTOH_ERROR_NOSPACE; 631 | } 632 | } 633 | 634 | // moves all the flows to the new sessions table 635 | while ( ( current = htable_first ( curht ) ) != 0 ) 636 | { 637 | item = (pntoh_ipv6_flow_t) htable_remove ( curht , current , 0 ); 638 | htable_insert ( newht , current , item ); 639 | } 640 | htable_destroy ( &curht ); 641 | 642 | sem_init ( &session->max_flows , 0 , newsize ); 643 | session->flows = newht; 644 | 645 | unlock_access ( &session->lock ); 646 | 647 | return NTOH_OK; 648 | } 649 | 650 | 651 | void ntoh_ipv6_init ( void ) 652 | { 653 | if ( params.init ) 654 | return; 655 | 656 | params.lock.use = 0; 657 | pthread_mutex_init( ¶ms.lock.mutex, 0 ); 658 | pthread_cond_init( ¶ms.lock.pcond, 0 ); 659 | 660 | params.init = 1; 661 | return; 662 | } 663 | 664 | void ntoh_ipv6_exit ( void ) 665 | { 666 | if ( !params.init ) 667 | return; 668 | 669 | lock_access ( ¶ms.lock ); 670 | 671 | while ( params.sessions_list != 0 ) 672 | __ipv6_free_session ( params.sessions_list ); 673 | 674 | unlock_access ( ¶ms.lock ); 675 | 676 | free_lockaccess ( ¶ms.lock ); 677 | 678 | params.init = 0; 679 | 680 | return; 681 | } 682 | -------------------------------------------------------------------------------- /src/libntoh.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2012, Chema Garcia * 3 | * All rights reserved. * 4 | * * 5 | * Redistribution and use in source and binary forms, with or * 6 | * without modification, are permitted provided that the following * 7 | * conditions are met: * 8 | * * 9 | * * Redistributions of source code must retain the above * 10 | * copyright notice, this list of conditions and the following * 11 | * disclaimer. * 12 | * * 13 | * * Redistributions in binary form must reproduce the above * 14 | * copyright notice, this list of conditions and the following * 15 | * disclaimer in the documentation and/or other materials provided * 16 | * with the distribution. * 17 | * * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 28 | * POSSIBILITY OF SUCH DAMAGE. * 29 | ********************************************************************************/ 30 | 31 | /** 32 | * @author Chema Garcia (aka sch3m4) 33 | * @mainpage https://github.com/sch3m4/libntoh/ 34 | * @version 0.4a 35 | */ 36 | 37 | #include 38 | 39 | #define VERSION "0.4a" 40 | 41 | static const char retval_descriptions[][48] = 42 | { 43 | /* ntoh_add_ipv(4|6)fragment */ 44 | "Success" , 45 | "Incorrect IP flow" , 46 | "Incorrect length" , 47 | "Incorrect IP header" , 48 | "Incorrect IP header length" , 49 | "Not an IPv4 datagram" , 50 | "IP addresses mismatch" , 51 | "Not an IPv4 fragment" , 52 | "Too small IP fragment", 53 | "Fragment overrun" , 54 | "Max. IP fragments reached" , 55 | "Not enough data", 56 | "Not an IPv6 fragment", 57 | 58 | /* ntoh_add_tcpsegment return values description */ 59 | "Incorrect session" , 60 | "Incorrect TCP header length" , 61 | "TCP ports mismatch", 62 | "Invalid flags" , 63 | "Too low seq. number" , 64 | "Too low ack. number" , 65 | "PAWS check failed", 66 | "TCP handshake failed" , 67 | "Max. SYN retries reached" , 68 | "Max. SYN/ACK retries reached" , 69 | "No TCP window space left", 70 | "Not a TCP segment", 71 | "Synchronizing connection", 72 | "Library not initialized" 73 | }; 74 | 75 | /** @brief reason description strings **/ 76 | static const char reason_descriptions[][30]= 77 | { 78 | /* TCP */ 79 | "Handshake failed" , 80 | "Established" , 81 | "Data" , 82 | "Closed" , 83 | "Timedout" , 84 | "Exiting" , 85 | "Out-Of-Order" , 86 | "Previous segment lost", // about 87 | "Max. SYN retries reached" , 88 | "Max. SYN/ACK retries reached" , 89 | "Synchronization", 90 | "No window space left", 91 | 92 | /* IP */ 93 | "Defragmented IP datagram", 94 | "Timeout expired" 95 | }; 96 | 97 | /* API errors */ 98 | static const char api_errors[][25] = { 99 | "No error", 100 | "Cannot allocate memory", 101 | "No space for add streams", 102 | "Null key", 103 | "Invalid function pointer", 104 | "Invalid tuple4 field(s)", 105 | "Invalid parameter(s)", 106 | "Library not initialized" 107 | }; 108 | 109 | const char* ntoh_version ( void ) 110 | { 111 | return (const char*) VERSION; 112 | } 113 | 114 | const char* ntoh_get_retval_desc ( int val ) 115 | { 116 | unsigned int pos = (unsigned int)(val * (-1)); 117 | 118 | if ( pos > (sizeof(retval_descriptions) / sizeof(*retval_descriptions) ) ) 119 | return 0; 120 | 121 | return retval_descriptions[pos]; 122 | } 123 | 124 | const char* ntoh_get_reason ( unsigned int val ) 125 | { 126 | if ( !val || val > (sizeof(reason_descriptions) / sizeof(*reason_descriptions)) ) 127 | return 0; 128 | 129 | return reason_descriptions[val - 1]; 130 | } 131 | 132 | const char* ntoh_get_errdesc ( unsigned int val ) 133 | { 134 | if ( val > (sizeof(api_errors) / sizeof(*api_errors)) ) 135 | return 0; 136 | 137 | return api_errors[val]; 138 | } 139 | 140 | void ntoh_init ( void ) 141 | { 142 | ntoh_tcp_init(); 143 | ntoh_ipv4_init(); 144 | ntoh_ipv6_init(); 145 | 146 | return; 147 | } 148 | 149 | void ntoh_exit ( void ) 150 | { 151 | ntoh_tcp_exit(); 152 | ntoh_ipv4_exit(); 153 | ntoh_ipv6_exit(); 154 | 155 | return; 156 | } 157 | -------------------------------------------------------------------------------- /src/ntoh.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | libdir=${prefix}/lib 3 | includedir=${prefix}/include 4 | 5 | Name: ntoh 6 | Description: C library to perform reassembly of network protocols 7 | Version: @LIBNTOH_VERSION@ 8 | Libs: -L${libdir} -l@OUTPUT_LIB@ 9 | Cflags: -I${includedir}/libntoh -------------------------------------------------------------------------------- /src/sfhash.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define get16bits(d) (*((const unsigned short *) (d))) 5 | 6 | /* The most generic version, hashes an arbitrary sequence 7 | * of bytes. No alignment or length assumptions are made about 8 | * the input key. 9 | */ 10 | _HIDDEN unsigned int sfhash(const void * key, unsigned int len, unsigned int initval) 11 | { 12 | const char *data = key; 13 | unsigned int hash = len + initval, tmp; 14 | int rem; 15 | 16 | if (len <= 0 || !data ) 17 | return 0; 18 | 19 | rem = len & 3; 20 | len >>= 2; 21 | 22 | /* Main loop */ 23 | for (; len > 0; len--) 24 | { 25 | /* Mix 32bit chunk of the data */ 26 | hash += get16bits(data); 27 | tmp = (get16bits(data+2) << 11) ^ hash; 28 | hash = (hash << 16) ^ tmp; 29 | data += 2*sizeof(unsigned short); 30 | hash += hash >> 11; 31 | } 32 | 33 | /* Handle end cases */ 34 | switch (rem) 35 | { 36 | case 3: hash += *((unsigned short *)data); 37 | hash ^= hash << 16; 38 | hash ^= data[sizeof(unsigned short)] << 18; 39 | hash += hash >> 11; 40 | break; 41 | 42 | case 2: hash += *((unsigned short *)data); 43 | hash ^= hash << 11; 44 | hash += hash >> 17; 45 | break; 46 | 47 | case 1: hash += *data; 48 | hash ^= hash << 10; 49 | hash += hash >> 1; 50 | break; 51 | } 52 | 53 | /* Force "avalanching" of final 127 bits */ 54 | hash ^= hash << 3; 55 | hash += hash >> 5; 56 | hash ^= hash << 2; 57 | hash += hash >> 15; 58 | hash ^= hash << 10; 59 | 60 | return hash; 61 | } 62 | --------------------------------------------------------------------------------