├── AUTHORS ├── COPYING ├── INSTALL ├── Makefile ├── README ├── README.md ├── ingress-qos.sh ├── ipt ├── Makefile └── libxt_ndpi.c ├── nDPI-patch └── src │ ├── include │ ├── ndpi_api.h │ ├── ndpi_define.h │ ├── ndpi_includes.h │ ├── ndpi_main.h │ ├── ndpi_typedefs.h │ └── ndpi_unix.h │ └── lib │ ├── ndpi_content_match.c.inc │ ├── ndpi_main.c │ ├── protocols │ ├── bittorrent.c │ ├── fiesta.c │ ├── ftp_control.c │ ├── git.c │ └── netflow.c │ └── third_party │ ├── include │ └── ndpi_patricia.h │ └── src │ ├── ahocorasick.c │ ├── ndpi_patricia.c │ ├── node.c │ └── sort.c ├── nDPI.tar.gz ├── ndpi.install ├── old ├── ipt │ ├── Makefile │ └── libxt_ndpi.c ├── kernel-patch │ ├── hack-conntrack-events.patch │ └── hack-conntrack-events.patch.old ├── nDPI.tar.gz └── src │ ├── Makefile │ ├── main.c │ └── xt_ndpi.h └── src ├── Makefile ├── main.c └── xt_ndpi.h /AUTHORS: -------------------------------------------------------------------------------- 1 | G. Elian Gidoni (base code author) 2 | Humberto Jucá 3 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | nDPI module INSTALL 2 | ---------------------- 3 | 4 | The install the modules follow these steps, always from the modules package 5 | root (i.e. where this file is located) 6 | 7 | - To compile the modules first type: 8 | 9 | NDPI_PATH=/home/foo/ndpi-x make 10 | 11 | Where, NDPI_PATH is the path to the original nDPI source code package 12 | (note that you have to extract it first). 13 | 14 | - Then, as root, type: 15 | 16 | make modules_install 17 | 18 | That would install the nDPI module for the given Linux kernel. 19 | 20 | - Finally, also as root, you should copy the iptables module into the 21 | corresponding directory. Usually this is "/lib/xtables" or 22 | "/usr/lib/xtables". 23 | 24 | cp ipt/libxt_ndpi.so /lib/xtables 25 | 26 | Now you can read the following section to learn how to use it. 27 | 28 | 29 | Module usage 30 | ------------ 31 | 32 | Once you have installed both modules ("libxt_ndpi.so" and "xt_ndpi.ko") 33 | you should type (as root): 34 | 35 | modprobe xt_ndpi 36 | 37 | If the module has been successfully loaded you shouldn't see any message. 38 | After loading the kernel module you can use iptables to add a rule. To see 39 | available protocols you can match for in every packet, type (as root): 40 | 41 | iptables -m ndpi --help 42 | 43 | Note that the list is long, you best try: "iptables -m ndpi --help | more" 44 | 45 | An example rule would be (as root): 46 | 47 | iptables -A OUTPUT -m ndpi --http -j REJECT 48 | 49 | This wouldn't allow any HTTP traffic that originates from the machine where the 50 | rule was added. 51 | 52 | In case you want to stop using the nDPI kernel module, first remove every 53 | iptables rule for nDPI and then type (as root): 54 | 55 | modprobe -r xt_ndpi 56 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | ifeq ($(strip $(NDPI_PATH)),) 3 | $(error NDPI_PATH required) 4 | endif 5 | $(MAKE) -C ipt 6 | $(MAKE) -C src 7 | modules_install: 8 | $(MAKE) -C src modules_install 9 | clean: 10 | $(MAKE) -C src clean 11 | $(MAKE) -C ipt clean 12 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This package is a GPL implementation of an iptables and netfilter module for 2 | nDPI integration into the Linux kernel. 3 | 4 | PayPal — The safer, easier way to pay online. 5 | 6 | 7 | The prerequisites are: 8 | 9 | - Tested on Ubuntu 14.04.1 LTS (Kernel 3.13.0-37-generic) 10 | - Following packages to compile kernel-modules: 11 | linux-headers 12 | iptables-dev >= version 1.4.21-1ubuntu1 13 | nDPI source package 14 | 15 | 16 | Compiled kernel features 17 | ------------------------ 18 | 19 | You do not need to do the below steps for Ubuntu 14.04.1 LTS 20 | 21 | In order to use nDPI as a kernel module notice that: 22 | 23 | - You should ENABLE Netfilter conntrack events (and also enable Advanced 24 | netfilter features to see it). 25 | 26 | In kernel 2.6.34 or greater its defined as: 27 | 28 | Connection tracking events 29 | Symbol: NF_CONNTRACK_EVENTS 30 | Location: 31 | -> Networking support 32 | -> Networking options 33 | -> Network packet filtering framework (Netfilter) 34 | -> Core Netfilter Configuration 35 | -> Netfilter connection tracking support 36 | 37 | In kernel 2.6.34 or greater its defined as: 38 | 39 | Connection tracking netlink interface 40 | Symbol: NF_CT_NETLINK 41 | Location: 42 | -> Networking support 43 | -> Networking options 44 | -> Network packet filtering framework (Netfilter) 45 | -> Core Netfilter Configuration 46 | -> Netfilter connection tracking support 47 | 48 | 49 | Once you have downloaded/installed each package and checked for the above 50 | kernel features you can read the INSTALL file. 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This package is a GPL implementation of an iptables and netfilter module for 2 | nDPI integration into the Linux kernel. 3 | 4 | PayPal — The safer, easier way to pay online. 5 | 6 | 7 | The prerequisites are: 8 | 9 | - Tested on Ubuntu 14.04.1 LTS (Kernel 3.13.0-37-generic) 10 | - Following packages to compile kernel-modules: 11 | linux-headers 12 | iptables-dev >= version 1.4.21-1ubuntu1 13 | nDPI source package 14 | 15 | 16 | Compiled kernel features 17 | ------------------------ 18 | 19 | You do not need to do the below steps for Ubuntu 14.04.1 LTS 20 | 21 | In order to use nDPI as a kernel module notice that: 22 | 23 | - You should ENABLE Netfilter conntrack events (and also enable Advanced 24 | netfilter features to see it). 25 | 26 | In kernel 2.6.34 or greater its defined as: 27 | 28 | Connection tracking events 29 | Symbol: NF_CONNTRACK_EVENTS 30 | Location: 31 | -> Networking support 32 | -> Networking options 33 | -> Network packet filtering framework (Netfilter) 34 | -> Core Netfilter Configuration 35 | -> Netfilter connection tracking support 36 | 37 | In kernel 2.6.34 or greater its defined as: 38 | 39 | Connection tracking netlink interface 40 | Symbol: NF_CT_NETLINK 41 | Location: 42 | -> Networking support 43 | -> Networking options 44 | -> Network packet filtering framework (Netfilter) 45 | -> Core Netfilter Configuration 46 | -> Netfilter connection tracking support 47 | 48 | 49 | Once you have downloaded/installed each package and checked for the above 50 | kernel features you can read the INSTALL file. 51 | -------------------------------------------------------------------------------- /ingress-qos.sh: -------------------------------------------------------------------------------- 1 | # Ubuntu steps - realease 14.04 2 | # 3 | # It's *default* in 15.x or greater Ubuntu realeases 4 | # 5 | # - Require kernel 4.2 for act_connmark 6 | # - Require iproute2 4.1.1 7 | # 8 | # 1. Update linux kernel 9 | # apt-get install linux-image-4.2.0-27-generic 10 | # apt-get install linux-headers-4.2.0-27 11 | # apt-get install linux-headers-4.2.0-27-generic 12 | # ln -sf /usr/src/linux-headers-4.2.0-27 /lib/modules/4.2.0-27-generic/build 13 | # 14 | # 2. Update iproute2 (4.1.1 version) 15 | # wget http://launchpadlibrarian.net/214987092/iproute2_4.1.1-1ubuntu1_amd64.deb 16 | # dpkg --install iproute2_4.1.1-1ubuntu1_amd64.deb 17 | # 18 | # 3. Rebuild ndpi-netfilter 19 | # 20 | 21 | # Using ifb interface to shape ingress flow 22 | modprobe ifb 23 | ifconfig ifb0 up 24 | 25 | # Root qdisc 26 | tc qdisc del dev ifb0 root 2> /dev/null 27 | tc qdisc del dev eth0 ingress 2>/dev/null 28 | /sbin/tc qdisc add dev eth0 ingress handle ffff: 29 | /sbin/tc qdisc add dev ifb0 root handle 101:0 htb default ffff 30 | 31 | # Interface rate 32 | /sbin/tc class add dev ifb0 parent 101:0 classid 101:1 htb rate 100Mbit 33 | 34 | # Default (101:ffff) and tcp traffic (101:2) 35 | /sbin/tc class add dev ifb0 parent 101:1 classid 101:ffff htb prio 4 rate 45Mbit ceil 98Mbit burst 20k cburst 20k 36 | /sbin/tc class add dev ifb0 parent 101:1 classid 101:2 htb prio 3 rate 25Mbit ceil 90Mbit burst 20k cburst 20k 37 | 38 | # Web traffic (101:3) and youtube (101:4) 39 | /sbin/tc class add dev ifb0 parent 101:1 classid 101:3 htb prio 2 rate 28Mbit ceil 90Mbit burst 20k cburst 20k 40 | /sbin/tc class add dev ifb0 parent 101:1 classid 101:4 htb prio 1 rate 2Mbit ceil 2Mbit burst 5k cburst 5k 41 | 42 | # Leaf qdisc 43 | /sbin/tc qdisc add dev ifb0 parent 101:ffff handle 803 pfifo 44 | /sbin/tc qdisc add dev ifb0 parent 101:2 handle 804 sfq divisor 256 45 | /sbin/tc qdisc add dev ifb0 parent 101:3 handle 805 sfq divisor 256 46 | /sbin/tc qdisc add dev ifb0 parent 101:4 handle 806 sfq divisor 256 47 | 48 | 49 | # Firewall marks 50 | # Flush mangle rules 51 | iptables -t mangle -F 52 | iptables -t mangle -X 53 | iptables -t mangle -N qosmark 54 | iptables -t mangle -A qosmark -j CONNMARK --restore-mark 55 | iptables -t mangle -A qosmark -m mark --mark 0x0 -j MARK --set-mark 0xffff 56 | iptables -t mangle -A qosmark -m mark --mark 0x104 -j RETURN 57 | iptables -t mangle -A qosmark -m connbytes --connbytes-dir both --connbytes-mode packets --connbytes 10 -j RETURN 58 | 59 | # - Tcp and web traffic 60 | iptables -t mangle -A qosmark -p tcp -j MARK --set-mark 0x102 61 | iptables -t mangle -A qosmark -m multiport -p tcp --sport 80,443,8080 -j MARK --set-mark 0x103 62 | iptables -t mangle -A qosmark -m multiport -p tcp --dport 80,443,8080 -j MARK --set-mark 0x103 63 | 64 | # - NDPI traffic 65 | iptables -t mangle -A qosmark -m ndpi --facebook -j MARK --set-mark 0x104 66 | iptables -t mangle -A qosmark -m ndpi --youtube -j MARK --set-mark 0x104 67 | 68 | 69 | # Mark rules 70 | iptables -t mangle -A PREROUTING -j qosmark 71 | iptables -t mangle -A POSTROUTING -j CONNMARK --save-mark 72 | iptables -t mangle -A OUTPUT -j qosmark 73 | 74 | 75 | # tc filters 76 | tc filter add dev ifb0 parent 101:0 protocol ip handle 0x102 fw flowid 101:2 77 | tc filter add dev ifb0 parent 101:0 protocol ip handle 0x103 fw flowid 101:3 78 | tc filter add dev ifb0 parent 101:0 protocol ip handle 0x104 fw flowid 101:4 79 | 80 | # mirroring eth0 packets to ifb interface (shape ingress flow) 81 | [ -f "/lib/modules/$(uname -r)/kernel/net/sched/act_connmark.ko" ] && cmd="action connmark" || cmd="action xt -j CONNMARK --restore-mark" 82 | tc filter add dev eth0 parent ffff: protocol all prio 1 u32 match u32 0 0 $cmd action mirred egress redirect dev ifb0 83 | 84 | #tc filter add dev eth0 parent ffff: protocol ip handle 0x104 fw action xt -j MARK --set-mark 0x104 action mirred egress redirect dev ifb0 85 | -------------------------------------------------------------------------------- /ipt/Makefile: -------------------------------------------------------------------------------- 1 | NDPI_PATH2 := ${NDPI_PATH}/src 2 | NDPI_SRC := ndpi_cpy 3 | NDPI_PRO := ${NDPI_SRC}/lib/protocols 4 | 5 | CFLAGS = -fPIC -I${NDPI_SRC}/include -I${NDPI_SRC}/lib -I../src -DOPENDPI_NETFILTER_MODULE -O2 -Wall -DNDPI_IPTABLES_EXT 6 | 7 | all: 8 | if test -d ${NDPI_SRC}; then \ 9 | cp ${NDPI_PATH2}/* ${NDPI_SRC} -R; \ 10 | else \ 11 | mkdir ${NDPI_SRC}; \ 12 | cp ${NDPI_PATH2}/* ${NDPI_SRC} -R; \ 13 | fi 14 | make libxt_ndpi.so 15 | rm -r ${NDPI_SRC} 16 | lib%.so: lib%.o 17 | $(CC) -shared -o $@ $^; 18 | lib%.o: lib%.c 19 | $(CC) ${CFLAGS} -D_INIT=lib$*_init -c -o $@ $<; 20 | clean: 21 | rm -rf libxt_ndpi.so ${NDPI_SRC} 22 | -------------------------------------------------------------------------------- /ipt/libxt_ndpi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libxt_ndpi.c 3 | * Copyright (C) 2010-2012 G. Elian Gidoni 4 | * 2012 Ed Wildgoose 5 | * 2014 Humberto Jucá 6 | * 7 | * This file is part of nDPI, an open source deep packet inspection 8 | * library based on the PACE technology by ipoque GmbH 9 | * 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License 12 | * as published by the Free Software Foundation; version 2 of the License. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | #include "xt_ndpi.h" 33 | 34 | static char *prot_long_str[] = { NDPI_PROTOCOL_LONG_STRING }; 35 | static char *prot_short_str[] = { NDPI_PROTOCOL_SHORT_STRING }; 36 | 37 | 38 | static void 39 | ndpi_mt4_save(const void *entry, const struct xt_entry_match *match) 40 | { 41 | const struct xt_ndpi_mtinfo *info = (const void *)match->data; 42 | int i; 43 | 44 | for (i = 1; i <= NDPI_LAST_NFPROTO; i++){ 45 | if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(info->flags, i) != 0){ 46 | printf(" --%s ", prot_short_str[i]); 47 | } 48 | } 49 | } 50 | 51 | 52 | static void 53 | ndpi_mt4_print(const void *entry, const struct xt_entry_match *match, 54 | int numeric) 55 | { 56 | const struct xt_ndpi_mtinfo *info = (const void *)match->data; 57 | int i; 58 | 59 | for (i = 1; i <= NDPI_LAST_NFPROTO; i++){ 60 | if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(info->flags, i) != 0){ 61 | printf("protocol %s ", prot_long_str[i]); 62 | } 63 | } 64 | } 65 | 66 | 67 | static int 68 | ndpi_mt4_parse(int c, char **argv, int invert, unsigned int *flags, 69 | const void *entry, struct xt_entry_match **match) 70 | { 71 | struct xt_ndpi_mtinfo *info = (void *)(*match)->data; 72 | 73 | if (c >= 0 && c <= NDPI_LAST_NFPROTO) { 74 | NDPI_ADD_PROTOCOL_TO_BITMASK(info->flags, c); 75 | *flags = 1; 76 | return true; 77 | } 78 | *flags = 0; 79 | return false; 80 | } 81 | 82 | #ifndef xtables_error 83 | #define xtables_error exit_error 84 | #endif 85 | 86 | static void 87 | ndpi_mt_check (unsigned int flags) 88 | { 89 | if (flags == 0){ 90 | xtables_error(PARAMETER_PROBLEM, "xt_ndpi: You need to " 91 | "specify at least one protocol"); 92 | } 93 | } 94 | 95 | 96 | static void 97 | ndpi_mt_help(void) 98 | { 99 | int i; 100 | 101 | printf("ndpi match options:\n"); 102 | for (i = 1; i <= NDPI_LAST_NFPROTO; i++){ 103 | printf("--%s Match for %s protocol packets.\n", 104 | prot_short_str[i], prot_long_str[i]); 105 | } 106 | } 107 | 108 | 109 | static void 110 | ndpi_mt_init (struct xt_entry_match *match) 111 | { 112 | struct xt_ndpi_mtinfo *info = (void *)match->data; 113 | /* inet_pton(PF_INET, "192.0.2.137", &info->dst.in); */ 114 | } 115 | 116 | 117 | static struct option ndpi_mt_opts[NDPI_LAST_NFPROTO+1]; 118 | 119 | static struct xtables_match 120 | ndpi_mt4_reg = { 121 | .version = XTABLES_VERSION, 122 | .name = "ndpi", 123 | .revision = 0, 124 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) 125 | .family = AF_INET, 126 | #else 127 | .family = NFPROTO_IPV4, 128 | #endif 129 | .size = XT_ALIGN(sizeof(struct xt_ndpi_mtinfo)), 130 | .userspacesize = XT_ALIGN(sizeof(struct xt_ndpi_mtinfo)), 131 | .help = ndpi_mt_help, 132 | .init = ndpi_mt_init, 133 | .parse = ndpi_mt4_parse, 134 | .final_check = ndpi_mt_check, 135 | .print = ndpi_mt4_print, 136 | .save = ndpi_mt4_save, 137 | .extra_opts = ndpi_mt_opts, 138 | }; 139 | 140 | void _init(void) 141 | { 142 | int i; 143 | 144 | for (i = 0; i < NDPI_LAST_NFPROTO; i++){ 145 | ndpi_mt_opts[i].name = prot_short_str[i+1]; 146 | ndpi_mt_opts[i].has_arg = false; 147 | ndpi_mt_opts[i].val = i+1; 148 | } 149 | ndpi_mt_opts[i].name = NULL; 150 | ndpi_mt_opts[i].flag = NULL; 151 | ndpi_mt_opts[i].has_arg = 0; 152 | ndpi_mt_opts[i].val = 0; 153 | 154 | xtables_register_match(&ndpi_mt4_reg); 155 | } 156 | -------------------------------------------------------------------------------- /nDPI-patch/src/include/ndpi_api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ndpi_api.h 3 | * 4 | * Copyright (C) 2011-16 - ntop.org 5 | * 6 | * This file is part of nDPI, an open source deep packet inspection 7 | * library based on the OpenDPI and PACE technology by ipoque GmbH 8 | * 9 | * nDPI is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * nDPI is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with nDPI. If not, see . 21 | * 22 | * Rev.1.1 23 | * 24 | */ 25 | 26 | 27 | #ifndef __NDPI_API_H__ 28 | #define __NDPI_API_H__ 29 | 30 | #include "ndpi_main.h" 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | #define NDPI_DETECTION_ONLY_IPV4 ( 1 << 0 ) 37 | #define NDPI_DETECTION_ONLY_IPV6 ( 1 << 1 ) 38 | 39 | #define ADD_TO_DETECTION_BITMASK 1 40 | #define NO_ADD_TO_DETECTION_BITMASK 0 41 | #define SAVE_DETECTION_BITMASK_AS_UNKNOWN 1 42 | #define NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN 0 43 | 44 | 45 | /** 46 | * Check if a string is encoded with punycode 47 | * ( https://tools.ietf.org/html/rfc3492 ) 48 | * 49 | * @par buff = pointer to the string to ckeck 50 | * @par len = len of the string 51 | * @return 1 if the string is punycoded; 52 | * else 0 53 | * 54 | */ 55 | int check_punycode_string(char * buff , int len); 56 | 57 | 58 | /** 59 | * Get the size of the flow struct 60 | * 61 | * @return the size of the flow struct 62 | * 63 | */ 64 | u_int32_t ndpi_detection_get_sizeof_ndpi_flow_struct(void); 65 | 66 | 67 | /** 68 | * Get the size of the id struct 69 | * 70 | * @return the size of the id struct 71 | * 72 | */ 73 | u_int32_t ndpi_detection_get_sizeof_ndpi_id_struct(void); 74 | 75 | 76 | /** 77 | * nDPI personal allocation and free functions 78 | **/ 79 | void * ndpi_malloc(size_t size); 80 | void * ndpi_calloc(unsigned long count, size_t size); 81 | void * ndpi_realloc(void *ptr, size_t old_size, size_t new_size); 82 | char * ndpi_strdup(const char *s); 83 | void ndpi_free(void *ptr); 84 | 85 | 86 | /** 87 | * Search the first occurrence of substring -find- in -s- 88 | * The search is limited to the first -slen- characters of the string 89 | * 90 | * @par s = string to parse 91 | * @par find = string to match with -s- 92 | * @par slen = max length to match between -s- and -find- 93 | * @return a pointer to the beginning of the located substring; 94 | * NULL if the substring is not found 95 | * 96 | */ 97 | char* ndpi_strnstr(const char *s, const char *find, size_t slen); 98 | 99 | 100 | /** 101 | * Returns the nDPI protocol id for IP-based protocol detection 102 | * 103 | * @par ndpi_struct = the struct created for the protocol detection 104 | * @par pin = IP host address (MUST BE in network byte order): 105 | * See man(7) ip for details 106 | * @return the nDPI protocol ID 107 | * 108 | */ 109 | u_int16_t ndpi_network_ptree_match(struct ndpi_detection_module_struct *ndpi_struct, struct in_addr *pin); 110 | 111 | 112 | /** 113 | * Init single protocol match 114 | * 115 | * @par ndpi_mod = the struct created for the protocol detection 116 | * @par match = the struct passed to match the protocol 117 | * 118 | */ 119 | void ndpi_init_protocol_match(struct ndpi_detection_module_struct *ndpi_mod, ndpi_protocol_match *match); 120 | 121 | /** 122 | * Returns a new initialized detection module 123 | * 124 | * @return the initialized detection module 125 | * 126 | */ 127 | struct ndpi_detection_module_struct *ndpi_init_detection_module(void); 128 | 129 | /** 130 | * Frees the memory allocated in the specified flow 131 | * 132 | * @par flow = the flow to deallocate 133 | * 134 | */ 135 | void ndpi_free_flow(struct ndpi_flow_struct *flow); 136 | 137 | 138 | /** 139 | * Enables cache support. 140 | * In nDPI is used for some protocol (i.e. Skype) 141 | * 142 | * @par ndpi_mod = the struct created for the protocol detection 143 | * @par host = string for the host name 144 | * @par port = unsigned int for the port number 145 | * 146 | */ 147 | void ndpi_enable_cache(struct ndpi_detection_module_struct *ndpi_mod, char* host, u_int port); 148 | 149 | 150 | /** 151 | * Destroys the detection module 152 | * 153 | * @par ndpi_struct = the struct to clearing for the detection module 154 | * 155 | */ 156 | void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_struct); 157 | 158 | 159 | /** 160 | * Sets a single protocol bitmask 161 | * This function does not increment the index of the callback_buffer 162 | * 163 | * @par label = string for the protocol name 164 | * @par ndpi_struct = the detection module 165 | * @par detection_bitmask = the protocol bitmask 166 | * @par idx = the index of the callback_buffer 167 | * @par func = function pointer of the protocol search 168 | * @par ndpi_selection_bitmask = the protocol selected bitmask 169 | * @par b_save_bitmask_unknow = if set as "true" save the detection bitmask as unknow 170 | * @par b_add_detection_bitmask = if set as "true" add the protocol bitmask to the detection bitmask 171 | * 172 | */ 173 | void ndpi_set_bitmask_protocol_detection(char *label, struct ndpi_detection_module_struct *ndpi_struct, 174 | const NDPI_PROTOCOL_BITMASK *detection_bitmask, 175 | const u_int32_t idx, 176 | u_int16_t ndpi_protocol_id, 177 | void (*func) (struct ndpi_detection_module_struct *, struct ndpi_flow_struct *flow), 178 | const NDPI_SELECTION_BITMASK_PROTOCOL_SIZE ndpi_selection_bitmask, 179 | u_int8_t b_save_bitmask_unknow, 180 | u_int8_t b_add_detection_bitmask); 181 | 182 | 183 | /** 184 | * Sets the protocol bitmask2 185 | * 186 | * @par ndpi_struct = the detection module 187 | * @par detection_bitmask = the protocol bitmask to set 188 | * 189 | */ 190 | void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *ndpi_struct, 191 | const NDPI_PROTOCOL_BITMASK * detection_bitmask); 192 | 193 | 194 | /** 195 | * Function to be called before we give up with detection for a given flow. 196 | * This function reduces the NDPI_UNKNOWN_PROTOCOL detection 197 | * 198 | * @par ndpi_struct = the detection module 199 | * @par flow = the flow given for the detection module 200 | * @return the detected protocol even if the flow is not completed; 201 | * 202 | */ 203 | ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_struct, 204 | struct ndpi_flow_struct *flow); 205 | 206 | 207 | /** 208 | * Processes one packet and returns the ID of the detected protocol. 209 | * This is the MAIN PACKET PROCESSING FUNCTION. 210 | * 211 | * @par ndpi_struct = the detection module 212 | * @par flow = pointer to the connection state machine 213 | * @par packet = unsigned char pointer to the Layer 3 (IP header) 214 | * @par packetlen = the length of the packet 215 | * @par current_tick = the current timestamp for the packet 216 | * @par src = pointer to the source subscriber state machine 217 | * @par dst = pointer to the destination subscriber state machine 218 | * @return the detected ID of the protocol 219 | * 220 | */ 221 | ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndpi_struct, 222 | struct ndpi_flow_struct *flow, 223 | const unsigned char *packet, 224 | const unsigned short packetlen, 225 | const u_int64_t current_tick, 226 | struct ndpi_id_struct *src, 227 | struct ndpi_id_struct *dst); 228 | 229 | 230 | /** 231 | * Processes one packet of L4 and returns the ID of the detected protocol. 232 | * L3 and L4 packet headers are passed in the arguments while payload 233 | * points to the L4 body. 234 | * This function mimics ndpi_detection_process_packet behaviour. 235 | * 236 | * @par ndpi_struct = the detection module 237 | * @par flow = pointer to the connection state machine 238 | * @par iph = IP packet header for IPv4 or NULL 239 | * @par iph6 = IP packet header for IPv6 or NULL 240 | * @par tcp = TCP packet header for TCP or NULL 241 | * @par udp = UDP packet header for UDP or NULL 242 | * @par src_to_dst_direction = order of src/dst state machines in a flow. 243 | * @par l4_proto = L4 protocol of the packet. 244 | * @par src = pointer to the source subscriber state machine 245 | * @par dst = pointer to the destination subscriber state machine 246 | * @par sport = source port of L4 packet, used for protocol guessing. 247 | * @par dport = destination port of L4 packet, used for protocol guessing. 248 | * @par current_tick_l = the current timestamp for the packet 249 | * @par payload = unsigned char pointer to the Layer 4 (TCP/UDP body) 250 | * @par payload_len = the length of the payload 251 | * @return the detected ID of the protocol 252 | * 253 | * NOTE: in a current implementation flow->src and flow->dst are swapped with 254 | * the src_to_dst_direction flag while ndpi_detection_process_packet does not swap 255 | * these values. 256 | * 257 | */ 258 | 259 | ndpi_protocol ndpi_l4_detection_process_packet(struct ndpi_detection_module_struct *ndpi_struct, 260 | struct ndpi_flow_struct *flow, 261 | const struct ndpi_iphdr *iph, 262 | struct ndpi_ipv6hdr *iph6, 263 | struct ndpi_tcphdr *tcp, 264 | struct ndpi_udphdr *udp, 265 | u_int8_t src_to_dst_direction, 266 | u_int8_t l4_proto, 267 | struct ndpi_id_struct *src, 268 | u_int16_t sport, 269 | struct ndpi_id_struct *dst, 270 | u_int16_t dport, 271 | const u_int64_t current_tick_l, 272 | u_int8_t *payload, u_int16_t payload_len); 273 | 274 | 275 | 276 | /** 277 | * Get the main protocol of the passed flows for the detected module 278 | * 279 | * 280 | * @par ndpi_struct = the detection module 281 | * @par flow = the flow given for the detection module 282 | * @return the ID of the master protocol detected 283 | * 284 | */ 285 | u_int16_t ndpi_get_flow_masterprotocol(struct ndpi_detection_module_struct *ndpi_struct, 286 | struct ndpi_flow_struct *flow); 287 | 288 | 289 | /** 290 | * Query the pointer to the layer 4 packet 291 | * 292 | * @par l3 = pointer to the layer 3 data 293 | * @par l3_len = length of the layer 3 data 294 | * @par l4_return = address to the pointer of the layer 4 data if return value == 0, else undefined 295 | * @par l4_len_return = length of the layer 4 data if return value == 0, else undefined 296 | * @par l4_protocol_return = protocol of the layer 4 data if return value == 0, undefined otherwise 297 | * @par flags = limit operation on ipv4 or ipv6 packets. Possible values: NDPI_DETECTION_ONLY_IPV4 - NDPI_DETECTION_ONLY_IPV6 - 0 (any) 298 | * @return 0 if layer 4 data could be found correctly; 299 | else != 0 300 | * 301 | */ 302 | u_int8_t ndpi_detection_get_l4(const u_int8_t *l3, u_int16_t l3_len, const u_int8_t **l4_return, u_int16_t *l4_len_return, 303 | u_int8_t *l4_protocol_return, u_int32_t flags); 304 | 305 | 306 | #if 0 307 | /** 308 | * returns true if the protocol history of the flow of the last packet given to the detection 309 | * contains the given protocol. 310 | * 311 | * @param ndpi_struct the detection module 312 | * @return 1 if protocol has been found, 0 otherwise 313 | * 314 | */ 315 | u_int8_t ndpi_detection_flow_protocol_history_contains_protocol(struct ndpi_detection_module_struct *ndpi_struct, 316 | struct ndpi_flow_struct *flow, 317 | u_int16_t protocol_id); 318 | #endif 319 | 320 | /** 321 | * Search and return the protocol based on matched ports 322 | * 323 | * @par ndpi_struct = the detection module 324 | * @par shost = source address in host byte order 325 | * @par sport = source port number 326 | * @par dhost = destination address in host byte order 327 | * @par dport = destination port number 328 | * @return the struct ndpi_protocol that match the port base protocol 329 | * 330 | */ 331 | ndpi_protocol ndpi_find_port_based_protocol(struct ndpi_detection_module_struct *ndpi_struct/* , u_int8_t proto */, 332 | u_int32_t shost, 333 | u_int16_t sport, 334 | u_int32_t dhost, 335 | u_int16_t dport); 336 | 337 | 338 | /** 339 | * Search and return the protocol guessed that is undetected 340 | * 341 | * @par ndpi_struct = the detection module 342 | * @par proto = the l4 protocol number 343 | * @par shost = source address in host byte order 344 | * @par sport = source port number 345 | * @par dhost = destination address in host byte order 346 | * @par dport = destination port number 347 | * @return the struct ndpi_protocol that match the port base protocol 348 | * 349 | */ 350 | ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct *ndpi_struct, 351 | u_int8_t proto, 352 | u_int32_t shost, 353 | u_int16_t sport, 354 | u_int32_t dhost, 355 | u_int16_t dport); 356 | 357 | 358 | /** 359 | * Check if the string passed match with a protocol 360 | * 361 | * @par ndpi_struct = the detection module 362 | * @par string_to_match = the string to match 363 | * @par string_to_match_len = the length of the string 364 | * @par is_host_match = value of the second field of struct ndpi_automa 365 | * @return the ID of the matched subprotocol 366 | * 367 | */ 368 | int ndpi_match_string_subprotocol(struct ndpi_detection_module_struct *ndpi_struct, 369 | char *string_to_match, 370 | u_int string_to_match_len, 371 | u_int8_t is_host_match); 372 | 373 | 374 | /** 375 | * Check if the host passed match with a protocol 376 | * 377 | * @par ndpi_struct = the detection module 378 | * @par flow = the flow where match the host 379 | * @par string_to_match = the string to match 380 | * @par string_to_match_len = the length of the string 381 | * @par master_protocol_id = value of the ID associated to the master protocol detected 382 | * @return the ID of the matched subprotocol 383 | * 384 | */ 385 | int ndpi_match_host_subprotocol(struct ndpi_detection_module_struct *ndpi_struct, 386 | struct ndpi_flow_struct *flow, 387 | char *string_to_match, 388 | u_int string_to_match_len, 389 | u_int16_t master_protocol_id); 390 | 391 | 392 | /** 393 | * Check if the string content passed match with a protocol 394 | * 395 | * @par ndpi_struct = the detection module 396 | * @par flow = the flow where match the host 397 | * @par string_to_match = the string to match 398 | * @par string_to_match_len = the length of the string 399 | * @par master_protocol_id = value of the ID associated to the master protocol detected 400 | * @return the ID of the matched subprotocol 401 | * 402 | */ 403 | int ndpi_match_content_subprotocol(struct ndpi_detection_module_struct *ndpi_struct, 404 | struct ndpi_flow_struct *flow, 405 | char *string_to_match, 406 | u_int string_to_match_len, 407 | u_int16_t master_protocol_id); 408 | 409 | 410 | /** 411 | * Check if the string -bigram_to_match- match with a bigram of -automa- 412 | * 413 | * @par ndpi_struct = the detection module 414 | * @par automa = the struct ndpi_automa for the bigram 415 | * @par bigram_to_match = the bigram string to match 416 | * @return 0 417 | * 418 | */ 419 | int ndpi_match_bigram(struct ndpi_detection_module_struct *ndpi_struct, 420 | ndpi_automa *automa, 421 | char *bigram_to_match); 422 | 423 | 424 | /** 425 | * Write the protocol name in the buffer -buf- as master_protocol.protocol 426 | * 427 | * @par ndpi_mod = the detection module 428 | * @par proto = the struct ndpi_protocol contain the protocols name 429 | * @par buf = the buffer to write the name of the protocols 430 | * @par buf_len = the length of the buffer 431 | * @return the buffer contains the master_protocol and protocol name 432 | * 433 | */ 434 | char* ndpi_protocol2name(struct ndpi_detection_module_struct *ndpi_mod, ndpi_protocol proto, char *buf, u_int buf_len); 435 | 436 | 437 | /** 438 | * Get the protocol name associated to the ID 439 | * 440 | * @par mod = the detection module 441 | * @par proto_id = the ID of the protocol 442 | * @return the buffer contains the master_protocol and protocol name 443 | * 444 | */ 445 | char* ndpi_get_proto_name(struct ndpi_detection_module_struct *mod, u_int16_t proto_id); 446 | 447 | 448 | /** 449 | * Return the protocol breed ID associated to the protocol 450 | * 451 | * @par ndpi_struct = the detection module 452 | * @par proto = the ID of the protocol 453 | * @return the breed ID associated to the protocol 454 | * 455 | */ 456 | ndpi_protocol_breed_t ndpi_get_proto_breed(struct ndpi_detection_module_struct *ndpi_struct, u_int16_t proto); 457 | 458 | 459 | /** 460 | * Return the string name of the protocol breed 461 | * 462 | * @par ndpi_struct = the detection module 463 | * @par breed_id = the breed ID associated to the protocol 464 | * @return the string name of the breed ID 465 | * 466 | */ 467 | char* ndpi_get_proto_breed_name(struct ndpi_detection_module_struct *ndpi_struct, ndpi_protocol_breed_t breed_id); 468 | 469 | 470 | /** 471 | * Return the ID of the protocol 472 | * 473 | * @par ndpi_mod = the detection module 474 | * @par proto = the ID of the protocol 475 | * @return the string name of the breed ID 476 | * 477 | */ 478 | int ndpi_get_protocol_id(struct ndpi_detection_module_struct *ndpi_mod, char *proto); 479 | 480 | 481 | /** 482 | * Write the list of the supported protocols 483 | * 484 | * @par ndpi_mod = the detection module 485 | */ 486 | void ndpi_dump_protocols(struct ndpi_detection_module_struct *mod); 487 | 488 | 489 | /** 490 | * Read a file and load the protocols 491 | * 492 | * Format: :,:,.....@ 493 | * 494 | * Example: 495 | * tcp:80,tcp:3128@HTTP 496 | * udp:139@NETBIOS 497 | * 498 | * @par ndpi_mod = the detection module 499 | * @par path = the path of the file 500 | * @return 0 if the file is loaded correctly; 501 | * -1 else 502 | * 503 | */ 504 | int ndpi_load_protocols_file(struct ndpi_detection_module_struct *ndpi_mod, char* path); 505 | 506 | 507 | /** 508 | * Get the total number of the supported protocols 509 | * 510 | * @par ndpi_mod = the detection module 511 | * @return the number of protocols 512 | * 513 | */ 514 | u_int ndpi_get_num_supported_protocols(struct ndpi_detection_module_struct *ndpi_mod); 515 | 516 | 517 | /** 518 | * Get the nDPI version release 519 | * 520 | * @return the NDPI_GIT_RELEASE 521 | * 522 | */ 523 | char* ndpi_revision(void); 524 | 525 | 526 | /** 527 | * Set the automa for the protocol search 528 | * 529 | * @par ndpi_struct = the detection module 530 | * @par automa = the automa to match 531 | * 532 | */ 533 | void ndpi_set_automa(struct ndpi_detection_module_struct *ndpi_struct, void* automa); 534 | 535 | 536 | #ifdef NDPI_PROTOCOL_HTTP 537 | /** 538 | * Retrieve information for HTTP flows 539 | * 540 | * @par ndpi_mod = the detection module 541 | * @par flow = the detected flow 542 | * @return the HTTP method information about the flow 543 | * 544 | */ 545 | ndpi_http_method ndpi_get_http_method(struct ndpi_detection_module_struct *ndpi_mod, struct ndpi_flow_struct *flow); 546 | 547 | 548 | /** 549 | * Get the HTTP url 550 | * 551 | * @par ndpi_mod = the detection module 552 | * @par flow = the detected flow 553 | * @return the HTTP method information about the flow 554 | * 555 | */ 556 | char* ndpi_get_http_url(struct ndpi_detection_module_struct *ndpi_mod, struct ndpi_flow_struct *flow); 557 | 558 | 559 | /** 560 | * Get the HTTP content-type 561 | * 562 | * @par ndpi_mod = the detection module 563 | * @par flow = the detected flow 564 | * @return the HTTP method information about the flow 565 | * 566 | */ 567 | char* ndpi_get_http_content_type(struct ndpi_detection_module_struct *ndpi_mod, struct ndpi_flow_struct *flow); 568 | #endif 569 | 570 | 571 | #ifdef NDPI_PROTOCOL_TOR 572 | /** 573 | * Check if the flow could be detected as TOR protocol 574 | * 575 | * @par ndpi_struct = the detection module 576 | * @par flow = the detected flow 577 | * @par certificate = the ssl certificate 578 | * @return 1 if the flow is TOR; 579 | * 0 else 580 | * 581 | */ 582 | int ndpi_is_ssl_tor(struct ndpi_detection_module_struct *ndpi_struct, 583 | struct ndpi_flow_struct *flow, char *certificate); 584 | #endif 585 | 586 | /* Wrappers functions */ 587 | /** 588 | * Init Aho-Corasick automata 589 | * 590 | * @return The requested automata, or NULL if an error occurred 591 | * 592 | */ 593 | void* ndpi_init_automa(void); 594 | 595 | 596 | /** 597 | * Free Aho-Corasick automata allocated with ndpi_init_automa(); 598 | * 599 | * @par The automata initialized with ndpi_init_automa(); 600 | * 601 | */ 602 | void ndpi_free_automa(void *_automa); 603 | 604 | 605 | /** 606 | * Add a string to match to an automata 607 | * 608 | * @par The automata initialized with ndpi_init_automa(); 609 | * @par The (sub)string to search 610 | * @return 0 in case of no error, or -1 if an error occurred. 611 | * 612 | */ 613 | int ndpi_add_string_to_automa(void *_automa, char *str); 614 | 615 | 616 | /** 617 | * Finalize the automa (necessary before start searching) 618 | * 619 | * @par The automata initialized with ndpi_init_automa(); 620 | * 621 | */ 622 | void ndpi_finalize_automa(void *_automa); 623 | 624 | 625 | /** 626 | * Add a string to match to an automata 627 | * 628 | * @par The automata initialized with ndpi_init_automa(); 629 | * @par The (sub)string to search 630 | * @return 0 in case of match, or -1 if no match, or -2 if an error occurred. 631 | * 632 | */ 633 | int ndpi_match_string(void *_automa, char *string_to_match); 634 | 635 | 636 | /* Utility functions to set ndpi malloc/free/print wrappers */ 637 | void set_ndpi_malloc(void* (*__ndpi_malloc)(size_t size)); 638 | void set_ndpi_free(void (*__ndpi_free)(void *ptr)); 639 | void set_ndpi_debug_function(ndpi_debug_function_ptr ndpi_debug_printf); 640 | 641 | #ifdef __cplusplus 642 | } 643 | #endif 644 | 645 | #endif /* __NDPI_API_H__ */ 646 | -------------------------------------------------------------------------------- /nDPI-patch/src/include/ndpi_define.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (C) 2011-16 - ntop.org 4 | * 5 | * This file is part of nDPI, an open source deep packet inspection 6 | * library based on the OpenDPI and PACE technology by ipoque GmbH 7 | * 8 | * nDPI is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * nDPI is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with nDPI. If not, see . 20 | * 21 | * Rev.1.1 22 | * 23 | */ 24 | 25 | #ifndef __NDPI_DEFINE_INCLUDE_FILE__ 26 | #define __NDPI_DEFINE_INCLUDE_FILE__ 27 | 28 | /* 29 | gcc -E -dM - < /dev/null |grep ENDIAN 30 | */ 31 | 32 | #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) 33 | #include 34 | #endif 35 | 36 | #ifdef __OpenBSD__ 37 | #include 38 | #define __BYTE_ORDER BYTE_ORDER 39 | #if BYTE_ORDER == LITTLE_ENDIAN 40 | #define __LITTLE_ENDIAN__ 41 | #else 42 | #define __BIG_ENDIAN__ 43 | #endif/* BYTE_ORDER */ 44 | #endif/* __OPENBSD__ */ 45 | 46 | 47 | #if 0 48 | #ifndef NDPI_ENABLE_DEBUG_MESSAGES 49 | #define NDPI_ENABLE_DEBUG_MESSAGES 50 | #endif 51 | #endif 52 | 53 | #ifndef __KERNEL__ 54 | #if __BYTE_ORDER == __LITTLE_ENDIAN 55 | #ifndef __LITTLE_ENDIAN__ 56 | #define __LITTLE_ENDIAN__ 57 | #endif 58 | #else 59 | #ifndef __BIG_ENDIAN__ 60 | #define __BIG_ENDIAN__ 61 | #endif 62 | #endif 63 | #endif 64 | 65 | #ifdef WIN32 66 | #ifndef __LITTLE_ENDIAN__ 67 | #define __LITTLE_ENDIAN__ 1 68 | #endif 69 | #endif 70 | 71 | #if !(defined(__LITTLE_ENDIAN__) || defined(__BIG_ENDIAN__)) 72 | #if defined(__mips__) 73 | #undef __LITTLE_ENDIAN__ 74 | #undef __LITTLE_ENDIAN 75 | #define __BIG_ENDIAN__ 76 | #endif 77 | 78 | /* Everything else */ 79 | #if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__)) 80 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 81 | #define __LITTLE_ENDIAN__ 82 | #else 83 | #define __BIG_ENDIAN__ 84 | #endif 85 | #endif 86 | 87 | #endif 88 | 89 | #define NDPI_USE_ASYMMETRIC_DETECTION 0 90 | #define NDPI_SELECTION_BITMASK_PROTOCOL_SIZE u_int32_t 91 | 92 | #define NDPI_SELECTION_BITMASK_PROTOCOL_IP (1<<0) 93 | #define NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP (1<<1) 94 | #define NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP (1<<2) 95 | #define NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP (1<<3) 96 | #define NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD (1<<4) 97 | #define NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION (1<<5) 98 | #define NDPI_SELECTION_BITMASK_PROTOCOL_IPV6 (1<<6) 99 | #define NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6 (1<<7) 100 | #define NDPI_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC (1<<8) 101 | /* now combined detections */ 102 | 103 | /* v4 */ 104 | #define NDPI_SELECTION_BITMASK_PROTOCOL_TCP (NDPI_SELECTION_BITMASK_PROTOCOL_IP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP) 105 | #define NDPI_SELECTION_BITMASK_PROTOCOL_UDP (NDPI_SELECTION_BITMASK_PROTOCOL_IP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP) 106 | #define NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP (NDPI_SELECTION_BITMASK_PROTOCOL_IP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP) 107 | 108 | /* v6 */ 109 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP (NDPI_SELECTION_BITMASK_PROTOCOL_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP) 110 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V6_UDP (NDPI_SELECTION_BITMASK_PROTOCOL_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP) 111 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_OR_UDP (NDPI_SELECTION_BITMASK_PROTOCOL_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP) 112 | 113 | /* v4 or v6 */ 114 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP (NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP) 115 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP (NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP) 116 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP (NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP) 117 | 118 | 119 | #define NDPI_SELECTION_BITMASK_PROTOCOL_TCP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 120 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 121 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 122 | 123 | /* does it make sense to talk about udp with payload ??? have you ever seen empty udp packets ? */ 124 | #define NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 125 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V6_UDP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_V6_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 126 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 127 | 128 | #define NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 129 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_OR_UDP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 130 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 131 | 132 | #define NDPI_SELECTION_BITMASK_PROTOCOL_TCP_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION) 133 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION) 134 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION) 135 | 136 | #define NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION) 137 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_OR_UDP_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION) 138 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION) 139 | 140 | #define NDPI_SELECTION_BITMASK_PROTOCOL_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 141 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 142 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 143 | 144 | #define NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 145 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 146 | #define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) 147 | 148 | /* safe src/dst protocol check macros... */ 149 | 150 | #define NDPI_SRC_HAS_PROTOCOL(src,protocol) ((src) != NULL && NDPI_COMPARE_PROTOCOL_TO_BITMASK((src)->detected_protocol_bitmask,(protocol)) != 0) 151 | 152 | #define NDPI_DST_HAS_PROTOCOL(dst,protocol) ((dst) != NULL && NDPI_COMPARE_PROTOCOL_TO_BITMASK((dst)->detected_protocol_bitmask,(protocol)) != 0) 153 | 154 | #define NDPI_SRC_OR_DST_HAS_PROTOCOL(src,dst,protocol) (NDPI_SRC_HAS_PROTOCOL(src,protocol) || NDPI_SRC_HAS_PROTOCOL(dst,protocol)) 155 | 156 | /** 157 | * convenience macro to check for excluded protocol 158 | * a protocol is excluded if the flow is known and either the protocol is not detected at all 159 | * or the excluded bitmask contains the protocol 160 | */ 161 | #define NDPI_FLOW_PROTOCOL_EXCLUDED(ndpi_struct,flow,protocol) ((flow) != NULL && \ 162 | ( NDPI_COMPARE_PROTOCOL_TO_BITMASK((ndpi_struct)->detection_bitmask, (protocol)) == 0 || \ 163 | NDPI_COMPARE_PROTOCOL_TO_BITMASK((flow)->excluded_protocol_bitmask, (protocol)) != 0 ) ) 164 | 165 | /* misc definitions */ 166 | #define NDPI_DEFAULT_MAX_TCP_RETRANSMISSION_WINDOW_SIZE 0x10000 167 | 168 | 169 | /* TODO: rebuild all memory areas to have a more aligned memory block here */ 170 | 171 | /* DEFINITION OF MAX LINE NUMBERS FOR line parse algorithm */ 172 | #define NDPI_MAX_PARSE_LINES_PER_PACKET 64 173 | 174 | #define MAX_PACKET_COUNTER 65000 175 | #define MAX_DEFAULT_PORTS 5 176 | 177 | #define NDPI_DIRECTCONNECT_CONNECTION_IP_TICK_TIMEOUT 600 178 | #define NDPI_IRC_CONNECTION_TIMEOUT 120 179 | #define NDPI_GNUTELLA_CONNECTION_TIMEOUT 60 180 | #define NDPI_BATTLEFIELD_CONNECTION_TIMEOUT 60 181 | #define NDPI_THUNDER_CONNECTION_TIMEOUT 30 182 | #define NDPI_RTSP_CONNECTION_TIMEOUT 5 183 | #define NDPI_TVANTS_CONNECTION_TIMEOUT 5 184 | #define NDPI_YAHOO_DETECT_HTTP_CONNECTIONS 1 185 | #define NDPI_YAHOO_LAN_VIDEO_TIMEOUT 30 186 | #define NDPI_ZATTOO_CONNECTION_TIMEOUT 120 187 | #define NDPI_ZATTOO_FLASH_TIMEOUT 5 188 | #define NDPI_JABBER_STUN_TIMEOUT 30 189 | #define NDPI_JABBER_FT_TIMEOUT 5 190 | #define NDPI_SOULSEEK_CONNECTION_IP_TICK_TIMEOUT 600 191 | 192 | #ifdef NDPI_ENABLE_DEBUG_MESSAGES 193 | 194 | #define NDPI_LOG(proto, mod, log_level, args...) \ 195 | { \ 196 | if(mod != NULL) { \ 197 | mod->ndpi_debug_print_file=__FILE__; \ 198 | mod->ndpi_debug_print_function=__FUNCTION__; \ 199 | mod->ndpi_debug_print_line=__LINE__; \ 200 | mod->ndpi_debug_printf(proto, mod, log_level, args); \ 201 | } \ 202 | } 203 | 204 | #else /* NDPI_ENABLE_DEBUG_MESSAGES */ 205 | 206 | #ifdef WIN32 207 | #define NDPI_LOG(...) {} 208 | #else 209 | #define NDPI_LOG(proto, mod, log_level, args...) {} 210 | #endif 211 | 212 | #endif /* NDPI_ENABLE_DEBUG_MESSAGES */ 213 | 214 | /** 215 | * macro for getting the string len of a static string 216 | * 217 | * use it instead of strlen to avoid runtime calculations 218 | */ 219 | #define NDPI_STATICSTRING_LEN( s ) ( sizeof( s ) - 1 ) 220 | 221 | /** macro to compare 2 IPv6 addresses with each other to identify the "smaller" IPv6 address */ 222 | #define NDPI_COMPARE_IPV6_ADDRESS_STRUCTS(x,y) \ 223 | ((((u_int64_t *)(x))[0]) < (((u_int64_t *)(y))[0]) || ( (((u_int64_t *)(x))[0]) == (((u_int64_t *)(y))[0]) && (((u_int64_t *)(x))[1]) < (((u_int64_t *)(y))[1])) ) 224 | 225 | #define NDPI_NUM_BITS 256 226 | 227 | #define NDPI_BITS /* 32 */ (sizeof(ndpi_ndpi_mask) * 8 /* number of bits in a byte */) /* bits per mask */ 228 | #define howmanybits(x, y) (((x)+((y)-1))/(y)) 229 | 230 | 231 | #define NDPI_SET(p, n) ((p)->fds_bits[(n)/NDPI_BITS] |= (1 << (((u_int32_t)n) % NDPI_BITS))) 232 | #define NDPI_CLR(p, n) ((p)->fds_bits[(n)/NDPI_BITS] &= ~(1 << (((u_int32_t)n) % NDPI_BITS))) 233 | #define NDPI_ISSET(p, n) ((p)->fds_bits[(n)/NDPI_BITS] & (1 << (((u_int32_t)n) % NDPI_BITS))) 234 | #define NDPI_ZERO(p) memset((char *)(p), 0, sizeof(*(p))) 235 | #define NDPI_ONE(p) memset((char *)(p), 0xFF, sizeof(*(p))) 236 | 237 | #define NDPI_NUM_FDS_BITS howmanybits(NDPI_NUM_BITS, NDPI_BITS) 238 | 239 | #define NDPI_PROTOCOL_BITMASK ndpi_protocol_bitmask_struct_t 240 | 241 | #define NDPI_BITMASK_ADD(a,b) NDPI_SET(&a,b) 242 | #define NDPI_BITMASK_DEL(a,b) NDPI_CLR(&a,b) 243 | #define NDPI_BITMASK_RESET(a) NDPI_ZERO(&a) 244 | #define NDPI_BITMASK_SET_ALL(a) NDPI_ONE(&a) 245 | #define NDPI_BITMASK_SET(a, b) { memcpy(&a, &b, sizeof(NDPI_PROTOCOL_BITMASK)); } 246 | 247 | /* this is a very very tricky macro *g*, 248 | * the compiler will remove all shifts here if the protocol is static... 249 | */ 250 | #define NDPI_ADD_PROTOCOL_TO_BITMASK(bmask,value) NDPI_SET(&bmask,value) 251 | #define NDPI_DEL_PROTOCOL_FROM_BITMASK(bmask,value) NDPI_CLR(&bmask,value) 252 | #define NDPI_COMPARE_PROTOCOL_TO_BITMASK(bmask,value) NDPI_ISSET(&bmask,value) 253 | 254 | #define NDPI_SAVE_AS_BITMASK(bmask,value) { NDPI_ZERO(&bmask) ; NDPI_ADD_PROTOCOL_TO_BITMASK(bmask, value); } 255 | 256 | 257 | #define ndpi_min(a,b) ((a < b) ? a : b) 258 | #define ndpi_max(a,b) ((a > b) ? a : b) 259 | 260 | #define NDPI_PARSE_PACKET_LINE_INFO(ndpi_struct,flow,packet) \ 261 | if (packet->packet_lines_parsed_complete != 1) { \ 262 | ndpi_parse_packet_line_info(ndpi_struct,flow); \ 263 | } \ 264 | 265 | #define NDPI_IPSEC_PROTOCOL_ESP 50 266 | #define NDPI_IPSEC_PROTOCOL_AH 51 267 | #define NDPI_GRE_PROTOCOL_TYPE 0x2F 268 | #define NDPI_ICMP_PROTOCOL_TYPE 0x01 269 | #define NDPI_IGMP_PROTOCOL_TYPE 0x02 270 | #define NDPI_EGP_PROTOCOL_TYPE 0x08 271 | #define NDPI_OSPF_PROTOCOL_TYPE 0x59 272 | #define NDPI_SCTP_PROTOCOL_TYPE 132 273 | #define NDPI_IPIP_PROTOCOL_TYPE 0x04 274 | #define NDPI_ICMPV6_PROTOCOL_TYPE 0x3a 275 | 276 | /* the get_uXX will return raw network packet bytes !! */ 277 | #define get_u_int8_t(X,O) (*(u_int8_t *)(((u_int8_t *)X) + O)) 278 | #define get_u_int16_t(X,O) (*(u_int16_t *)(((u_int8_t *)X) + O)) 279 | #define get_u_int32_t(X,O) (*(u_int32_t *)(((u_int8_t *)X) + O)) 280 | #define get_u_int64_t(X,O) (*(u_int64_t *)(((u_int8_t *)X) + O)) 281 | 282 | /* new definitions to get little endian from network bytes */ 283 | #define get_ul8(X,O) get_u_int8_t(X,O) 284 | 285 | 286 | #if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN) 287 | #define get_l16(X,O) get_u_int16_t(X,O) 288 | #define get_l32(X,O) get_u_int32_t(X,O) 289 | #elif defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) 290 | /* convert the bytes from big to little endian */ 291 | #ifndef __KERNEL__ 292 | # define get_l16(X,O) bswap_16(get_u_int16_t(X,O)) 293 | # define get_l32(X,O) bswap_32(get_u_int32_t(X,O)) 294 | #else 295 | # define get_l16(X,O) __cpu_to_le16(get_u_int16_t(X,O)) 296 | # define get_l32(X,O) __cpu_to_le32(get_u_int32_t(X,O)) 297 | #endif 298 | #else 299 | #error "__BYTE_ORDER MUST BE DEFINED !" 300 | #endif /* __BYTE_ORDER */ 301 | 302 | /* define memory callback function */ 303 | #define match_first_bytes(payload,st) (memcmp((payload),(st),(sizeof(st)-1))==0) 304 | 305 | #if defined(WIN32) && !defined(snprintf) 306 | #define snprintf _snprintf 307 | #endif 308 | 309 | #define NDPI_MAX_DNS_REQUESTS 16 310 | 311 | #endif /* __NDPI_DEFINE_INCLUDE_FILE__ */ 312 | -------------------------------------------------------------------------------- /nDPI-patch/src/include/ndpi_includes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ndpi_includes.h 3 | * 4 | * Copyright (C) 2011-16 - ntop.org 5 | * 6 | * This file is part of nDPI, an open source deep packet inspection 7 | * library based on the OpenDPI and PACE technology by ipoque GmbH 8 | * 9 | * nDPI is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * nDPI is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with nDPI. If not, see . 21 | * 22 | * Rev.1.1 23 | * 24 | */ 25 | 26 | #ifndef __NDPI_INCLUDES_H__ 27 | #define __NDPI_INCLUDES_H__ 28 | 29 | #ifndef __KERNEL__ 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #endif 38 | 39 | #ifdef WIN32 40 | #include "ndpi_win32.h" 41 | #else 42 | #ifndef __KERNEL__ 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #else 54 | #include 55 | #include 56 | #include 57 | #endif 58 | 59 | #if !defined __APPLE__ && !defined __FreeBSD__ && !defined __NetBSD__ && !defined __OpenBSD__ 60 | 61 | #ifndef __KERNEL__ 62 | #include 63 | #include 64 | #else 65 | #include 66 | #include 67 | #endif 68 | 69 | #if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ 70 | #include 71 | 72 | #if defined __NetBSD__ || defined __OpenBSD__ 73 | #include 74 | 75 | #ifdef __OpenBSD__ 76 | #include 77 | 78 | #endif 79 | #endif 80 | #endif 81 | #endif 82 | 83 | #endif /* Win32 */ 84 | 85 | #endif /* __NDPI_INCLUDES_H__ */ 86 | -------------------------------------------------------------------------------- /nDPI-patch/src/include/ndpi_main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ndpi_main.h 3 | * 4 | * Copyright (C) 2011-16 - ntop.org 5 | * 6 | * This file is part of nDPI, an open source deep packet inspection 7 | * library based on the OpenDPI and PACE technology by ipoque GmbH 8 | * 9 | * nDPI is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * nDPI is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with nDPI. If not, see . 21 | * 22 | * Rev.2 23 | * 24 | */ 25 | 26 | #ifndef __NDPI_MAIN_H__ 27 | #define __NDPI_MAIN_H__ 28 | 29 | /* 30 | #ifndef __KERNEL__ 31 | #include 32 | #include 33 | #include 34 | #include 35 | #ifndef WIN32 36 | #include 37 | #endif 38 | #include 39 | #include 40 | #endif 41 | 42 | #ifndef WIN32 43 | #ifndef __KERNEL__ 44 | #include 45 | #endif 46 | 47 | #ifndef __KERNEL__ 48 | #include 49 | #include 50 | #endif 51 | #endif 52 | */ 53 | 54 | #include "ndpi_includes.h" 55 | #include "ndpi_define.h" 56 | #include "ndpi_protocol_ids.h" 57 | #include "ndpi_typedefs.h" 58 | #include "ndpi_protocols.h" 59 | #include "ndpi_api.h" 60 | 61 | #ifdef __cplusplus 62 | extern "C" { 63 | #endif 64 | 65 | void *ndpi_tdelete(const void * __restrict, void ** __restrict, 66 | int (*)(const void *, const void *)); 67 | void *ndpi_tfind(const void *, void *, int (*)(const void *, const void *)); 68 | void *ndpi_tsearch(const void *, void**, int (*)(const void *, const void *)); 69 | void ndpi_twalk(const void *, void (*)(const void *, ndpi_VISIT, int, void*), void *user_data); 70 | void ndpi_tdestroy(void *vrootp, void (*freefct)(void *)); 71 | 72 | int NDPI_BITMASK_COMPARE(NDPI_PROTOCOL_BITMASK a, NDPI_PROTOCOL_BITMASK b); 73 | int NDPI_BITMASK_IS_EMPTY(NDPI_PROTOCOL_BITMASK a); 74 | void NDPI_DUMP_BITMASK(NDPI_PROTOCOL_BITMASK a); 75 | 76 | extern u_int8_t ndpi_net_match(u_int32_t ip_to_check, 77 | u_int32_t net, 78 | u_int32_t num_bits); 79 | 80 | extern u_int8_t ndpi_ips_match(u_int32_t src, u_int32_t dst, 81 | u_int32_t net, u_int32_t num_bits); 82 | 83 | u_int16_t ntohs_ndpi_bytestream_to_number(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read); 84 | 85 | u_int32_t ndpi_bytestream_to_number(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read); 86 | u_int64_t ndpi_bytestream_to_number64(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read); 87 | u_int32_t ndpi_bytestream_dec_or_hex_to_number(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read); 88 | u_int64_t ndpi_bytestream_dec_or_hex_to_number64(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read); 89 | u_int32_t ndpi_bytestream_to_ipv4(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read); 90 | 91 | 92 | void ndpi_set_detected_protocol(struct ndpi_detection_module_struct *ndpi_struct, 93 | struct ndpi_flow_struct *flow, 94 | u_int16_t upper_detected_protocol, 95 | u_int16_t lower_detected_protocol); 96 | 97 | extern void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); 98 | extern void ndpi_parse_packet_line_info_any(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); 99 | 100 | extern u_int16_t ndpi_check_for_email_address(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, u_int16_t counter); 101 | 102 | extern void ndpi_int_change_packet_protocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, 103 | u_int16_t upper_detected_protocol, 104 | u_int16_t lower_detected_protocol); 105 | extern void ndpi_int_change_protocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, 106 | u_int16_t upper_detected_protocol, 107 | u_int16_t lower_detected_protocol); 108 | extern void ndpi_set_proto_defaults(struct ndpi_detection_module_struct *ndpi_mod, ndpi_protocol_breed_t protoBreed, u_int16_t protoId, 109 | u_int16_t tcp_alias_protoId[2], u_int16_t udp_alias_protoId[2], char *protoName, 110 | ndpi_port_range *tcpDefPorts, ndpi_port_range *udpDefPorts); 111 | 112 | extern void ndpi_int_reset_packet_protocol(struct ndpi_packet_struct *packet); 113 | extern void ndpi_int_reset_protocol(struct ndpi_flow_struct *flow); 114 | 115 | extern int ndpi_packet_src_ip_eql(const struct ndpi_packet_struct *packet, const ndpi_ip_addr_t * ip); 116 | extern int ndpi_packet_dst_ip_eql(const struct ndpi_packet_struct *packet, const ndpi_ip_addr_t * ip); 117 | extern void ndpi_packet_src_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_addr_t * ip); 118 | extern void ndpi_packet_dst_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_addr_t * ip); 119 | 120 | extern char *ndpi_get_ip_string(struct ndpi_detection_module_struct *ndpi_struct, const ndpi_ip_addr_t * ip); 121 | extern char *ndpi_get_packet_src_ip_string(struct ndpi_detection_module_struct *ndpi_struct, const struct ndpi_packet_struct *packet); 122 | extern char* ndpi_get_proto_by_id(struct ndpi_detection_module_struct *ndpi_mod, u_int id); 123 | u_int16_t ndpi_get_proto_by_name(struct ndpi_detection_module_struct *ndpi_mod, const char *name); 124 | 125 | extern u_int16_t ndpi_guess_protocol_id(struct ndpi_detection_module_struct *ndpi_struct, 126 | u_int8_t proto, u_int16_t sport, u_int16_t dport, 127 | u_int8_t *user_defined_proto); 128 | 129 | extern u_int8_t ndpi_is_proto(ndpi_protocol p, u_int16_t proto); 130 | 131 | extern u_int16_t ndpi_get_lower_proto(ndpi_protocol p); 132 | extern int ndpi_get_protocol_id_master_proto(struct ndpi_detection_module_struct *ndpi_struct, u_int16_t protocol_id, 133 | u_int16_t** tcp_master_proto, 134 | u_int16_t** udp_master_proto); 135 | 136 | #ifdef NDPI_ENABLE_DEBUG_MESSAGES 137 | void ndpi_debug_get_last_log_function_line(struct ndpi_detection_module_struct *ndpi_struct, 138 | const char **file, const char **func, u_int32_t * line); 139 | #endif 140 | 141 | /** Checks when the @p payload starts with the string literal @p str. 142 | * When the string is larger than the payload, check fails. 143 | * @return non-zero if check succeeded 144 | */ 145 | int ndpi_match_prefix(const u_int8_t *payload, size_t payload_len, 146 | const char *str, size_t str_len); 147 | 148 | /* version of ndpi_match_prefix with string literal */ 149 | #define ndpi_match_strprefix(payload, payload_len, str) \ 150 | ndpi_match_prefix((payload), (payload_len), (str), (sizeof(str)-1)) 151 | 152 | #ifdef __cplusplus 153 | } 154 | #endif 155 | 156 | #endif /* __NDPI_MAIN_H__ */ 157 | -------------------------------------------------------------------------------- /nDPI-patch/src/include/ndpi_unix.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ndpi_unix.h 3 | * 4 | * Copyright (C) 2011-15 - ntop.org 5 | * 6 | * This file is part of nDPI, an open source deep packet inspection 7 | * library based on the OpenDPI and PACE technology by ipoque GmbH 8 | * 9 | * nDPI is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * nDPI is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with nDPI. If not, see . 21 | * 22 | * Rev.1.1 23 | * 24 | */ 25 | 26 | #ifndef __NDPI_UNIX_INCLUDE_FILE__ 27 | #define __NDPI_UNIX_INCLUDE_FILE__ 28 | 29 | #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) 30 | #include 31 | #if defined(__NetBSD__) || defined(__OpenBSD__) 32 | #include 33 | #if defined(__OpenBSD__) 34 | #include 35 | #endif 36 | #endif 37 | #endif 38 | 39 | #ifndef WIN32 40 | #ifndef __KERNEL__ 41 | 42 | #include 43 | #include 44 | #include 45 | #else 46 | #include 47 | #include 48 | #include 49 | #endif 50 | #endif 51 | 52 | #endif /* __NDPI_UNIX_INCLUDE_FILE__ */ 53 | -------------------------------------------------------------------------------- /nDPI-patch/src/lib/protocols/bittorrent.c: -------------------------------------------------------------------------------- 1 | /* 2 | * bittorrent.c 3 | * 4 | * Copyright (C) 2009-2011 by ipoque GmbH 5 | * Copyright (C) 2011-15 - ntop.org 6 | * 7 | * This file is part of nDPI, an open source deep packet inspection 8 | * library based on the OpenDPI and PACE technology by ipoque GmbH 9 | * 10 | * nDPI is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * nDPI is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Lesser General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with nDPI. If not, see . 22 | * 23 | * Rev.1.1 24 | * 25 | */ 26 | 27 | 28 | #include "ndpi_protocols.h" 29 | #ifdef NDPI_PROTOCOL_BITTORRENT 30 | #define NDPI_PROTOCOL_UNSAFE_DETECTION 0 31 | #define NDPI_PROTOCOL_SAFE_DETECTION 1 32 | 33 | #define NDPI_PROTOCOL_PLAIN_DETECTION 0 34 | #define NDPI_PROTOCOL_WEBSEED_DETECTION 2 35 | 36 | 37 | struct ndpi_utp_hdr { 38 | u_int8_t h_version:4, h_type:4, next_extension; 39 | u_int16_t connection_id; 40 | u_int32_t ts_usec, tdiff_usec, window_size; 41 | u_int16_t sequence_nr, ack_nr; 42 | }; 43 | 44 | static u_int8_t is_utp_pkt(const u_int8_t *payload, u_int payload_len) { 45 | struct ndpi_utp_hdr *h = (struct ndpi_utp_hdr*)payload; 46 | 47 | if(payload_len < sizeof(struct ndpi_utp_hdr)) return(0); 48 | if(h->h_version != 1) return(0); 49 | if(h->h_type > 4) return(0); 50 | if(h->next_extension > 2) return(0); 51 | if(ntohl(h->window_size) > 65565) return(0); 52 | 53 | return(1); 54 | } 55 | 56 | static void ndpi_add_connection_as_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, 57 | int bt_offset, int check_hash, 58 | const u_int8_t save_detection, const u_int8_t encrypted_connection) 59 | { 60 | if(check_hash) { 61 | const char *bt_hash = NULL; /* 20 bytes long */ 62 | const char *peer_id = NULL; /* 20 bytes long */ 63 | 64 | if(bt_offset == -1) { 65 | const char *bt_magic = ndpi_strnstr((const char *)flow->packet.payload, 66 | "BitTorrent protocol", flow->packet.payload_packet_len); 67 | 68 | if(bt_magic) 69 | bt_hash = &bt_magic[19], peer_id = &bt_magic[39]; 70 | } else 71 | bt_hash = (const char*)&flow->packet.payload[28], peer_id = (const char*)&flow->packet.payload[48]; 72 | 73 | if(bt_hash) memcpy(flow->bittorent_hash, bt_hash, 20); 74 | } 75 | 76 | ndpi_int_change_protocol(ndpi_struct, flow, NDPI_PROTOCOL_BITTORRENT, NDPI_PROTOCOL_UNKNOWN); 77 | } 78 | 79 | static u_int8_t ndpi_int_search_bittorrent_tcp_zero(struct ndpi_detection_module_struct 80 | *ndpi_struct, struct ndpi_flow_struct *flow) 81 | { 82 | struct ndpi_packet_struct *packet = &flow->packet; 83 | u_int16_t a = 0; 84 | 85 | if(packet->payload_packet_len == 1 && packet->payload[0] == 0x13) { 86 | /* reset stage back to 0 so we will see the next packet here too */ 87 | flow->bittorrent_stage = 0; 88 | return 0; 89 | } 90 | 91 | if(flow->packet_counter == 2 && packet->payload_packet_len > 20) { 92 | if(memcmp(&packet->payload[0], "BitTorrent protocol", 19) == 0) { 93 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, 94 | ndpi_struct, NDPI_LOG_TRACE, "BT: plain BitTorrent protocol detected\n"); 95 | ndpi_add_connection_as_bittorrent(ndpi_struct, flow, 19, 1, 96 | NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); 97 | return 1; 98 | } 99 | } 100 | 101 | if(packet->payload_packet_len > 20) { 102 | /* test for match 0x13+"BitTorrent protocol" */ 103 | if(packet->payload[0] == 0x13) { 104 | if(memcmp(&packet->payload[1], "BitTorrent protocol", 19) == 0) { 105 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "BT: plain BitTorrent protocol detected\n"); 106 | ndpi_add_connection_as_bittorrent(ndpi_struct, flow, 20, 1, 107 | NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); 108 | return 1; 109 | } 110 | } 111 | } 112 | 113 | if(packet->payload_packet_len > 23 && memcmp(packet->payload, "GET /webseed?info_hash=", 23) == 0) { 114 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, 115 | NDPI_LOG_TRACE, "BT: plain webseed BitTorrent protocol detected\n"); 116 | ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, 117 | NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION); 118 | return 1; 119 | } 120 | /* seen Azureus as server for webseed, possibly other servers existing, to implement */ 121 | /* is Server: hypertracker Bittorrent? */ 122 | /* no asymmetric detection possible for answer of pattern "GET /data?fid=". */ 123 | if(packet->payload_packet_len > 60 124 | && memcmp(packet->payload, "GET /data?fid=", 14) == 0 && memcmp(&packet->payload[54], "&size=", 6) == 0) { 125 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, 126 | NDPI_LOG_TRACE, "BT: plain Bitcomet persistent seed protocol detected\n"); 127 | ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, 128 | NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION); 129 | return 1; 130 | } 131 | 132 | 133 | if(packet->payload_packet_len > 90 && (memcmp(packet->payload, "GET ", 4) == 0 134 | || memcmp(packet->payload, "POST ", 5) == 0)) { 135 | const u_int8_t *ptr = &packet->payload[4]; 136 | u_int16_t len = packet->payload_packet_len - 4; 137 | 138 | 139 | /* parse complete get packet here into line structure elements */ 140 | ndpi_parse_packet_line_info(ndpi_struct, flow); 141 | /* answer to this pattern is HTTP....Server: hypertracker */ 142 | if(packet->user_agent_line.ptr != NULL 143 | && ((packet->user_agent_line.len > 8 && memcmp(packet->user_agent_line.ptr, "Azureus ", 8) == 0) 144 | || (packet->user_agent_line.len >= 10 && memcmp(packet->user_agent_line.ptr, "BitTorrent", 10) == 0) 145 | || (packet->user_agent_line.len >= 11 && memcmp(packet->user_agent_line.ptr, "BTWebClient", 11) == 0))) { 146 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, 147 | NDPI_LOG_TRACE, "Azureus /Bittorrent user agent line detected\n"); 148 | ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, 149 | NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION); 150 | return 1; 151 | } 152 | 153 | if(packet->user_agent_line.ptr != NULL 154 | && (packet->user_agent_line.len >= 9 && memcmp(packet->user_agent_line.ptr, "Shareaza ", 9) == 0) 155 | && (packet->parsed_lines > 8 && packet->line[8].ptr != 0 156 | && packet->line[8].len >= 9 && memcmp(packet->line[8].ptr, "X-Queue: ", 9) == 0)) { 157 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, 158 | NDPI_LOG_TRACE, "Bittorrent Shareaza detected.\n"); 159 | ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, 160 | NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION); 161 | return 1; 162 | } 163 | 164 | /* this is a self built client, not possible to catch asymmetrically */ 165 | if((packet->parsed_lines == 10 || (packet->parsed_lines == 11 && packet->line[11].len == 0)) 166 | && packet->user_agent_line.ptr != NULL 167 | && packet->user_agent_line.len > 12 168 | && memcmp(packet->user_agent_line.ptr, "Mozilla/4.0 ", 169 | 12) == 0 170 | && packet->host_line.ptr != NULL 171 | && packet->host_line.len >= 7 172 | && packet->line[2].ptr != NULL 173 | && packet->line[2].len > 14 174 | && memcmp(packet->line[2].ptr, "Keep-Alive: 300", 15) == 0 175 | && packet->line[3].ptr != NULL 176 | && packet->line[3].len > 21 177 | && memcmp(packet->line[3].ptr, "Connection: Keep-alive", 22) == 0 178 | && packet->line[4].ptr != NULL 179 | && packet->line[4].len > 10 180 | && (memcmp(packet->line[4].ptr, "Accpet: */*", 11) == 0 181 | || memcmp(packet->line[4].ptr, "Accept: */*", 11) == 0) 182 | 183 | && packet->line[5].ptr != NULL 184 | && packet->line[5].len > 12 185 | && memcmp(packet->line[5].ptr, "Range: bytes=", 13) == 0 186 | && packet->line[7].ptr != NULL 187 | && packet->line[7].len > 15 188 | && memcmp(packet->line[7].ptr, "Pragma: no-cache", 16) == 0 189 | && packet->line[8].ptr != NULL 190 | && packet->line[8].len > 22 && memcmp(packet->line[8].ptr, "Cache-Control: no-cache", 23) == 0) { 191 | 192 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "Bitcomet LTS detected\n"); 193 | ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, 194 | NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); 195 | return 1; 196 | } 197 | 198 | /* FlashGet pattern */ 199 | if(packet->parsed_lines == 8 200 | && packet->user_agent_line.ptr != NULL 201 | && packet->user_agent_line.len > (sizeof("Mozilla/4.0 (compatible; MSIE 6.0;") - 1) 202 | && memcmp(packet->user_agent_line.ptr, "Mozilla/4.0 (compatible; MSIE 6.0;", 203 | sizeof("Mozilla/4.0 (compatible; MSIE 6.0;") - 1) == 0 204 | && packet->host_line.ptr != NULL 205 | && packet->host_line.len >= 7 206 | && packet->line[2].ptr != NULL 207 | && packet->line[2].len == 11 208 | && memcmp(packet->line[2].ptr, "Accept: */*", 11) == 0 209 | && packet->line[3].ptr != NULL && packet->line[3].len >= (sizeof("Referer: ") - 1) 210 | && memcmp(packet->line[3].ptr, "Referer: ", sizeof("Referer: ") - 1) == 0 211 | && packet->line[5].ptr != NULL 212 | && packet->line[5].len > 13 213 | && memcmp(packet->line[5].ptr, "Range: bytes=", 13) == 0 214 | && packet->line[6].ptr != NULL 215 | && packet->line[6].len > 21 && memcmp(packet->line[6].ptr, "Connection: Keep-Alive", 22) == 0) { 216 | 217 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "FlashGet detected\n"); 218 | ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, 219 | NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); 220 | return 1; 221 | } 222 | 223 | if(packet->parsed_lines == 7 224 | && packet->user_agent_line.ptr != NULL 225 | && packet->user_agent_line.len > (sizeof("Mozilla/4.0 (compatible; MSIE 6.0;") - 1) 226 | && memcmp(packet->user_agent_line.ptr, "Mozilla/4.0 (compatible; MSIE 6.0;", 227 | sizeof("Mozilla/4.0 (compatible; MSIE 6.0;") - 1) == 0 228 | && packet->host_line.ptr != NULL 229 | && packet->host_line.len >= 7 230 | && packet->line[2].ptr != NULL 231 | && packet->line[2].len == 11 232 | && memcmp(packet->line[2].ptr, "Accept: */*", 11) == 0 233 | && packet->line[3].ptr != NULL && packet->line[3].len >= (sizeof("Referer: ") - 1) 234 | && memcmp(packet->line[3].ptr, "Referer: ", sizeof("Referer: ") - 1) == 0 235 | && packet->line[5].ptr != NULL 236 | && packet->line[5].len > 21 && memcmp(packet->line[5].ptr, "Connection: Keep-Alive", 22) == 0) { 237 | 238 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "FlashGet detected\n"); 239 | ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, 240 | NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); 241 | return 1; 242 | } 243 | 244 | /* answer to this pattern is not possible to implement asymmetrically */ 245 | while (1) { 246 | if(len < 50 || ptr[0] == 0x0d) { 247 | goto ndpi_end_bt_tracker_check; 248 | } 249 | if(memcmp(ptr, "info_hash=", 10) == 0) { 250 | break; 251 | } 252 | len--; 253 | ptr++; 254 | } 255 | 256 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, 257 | NDPI_LOG_TRACE, " BT stat: tracker info hash found\n"); 258 | 259 | /* len is > 50, so save operation here */ 260 | len -= 10; 261 | ptr += 10; 262 | 263 | /* parse bt hash */ 264 | for (a = 0; a < 20; a++) { 265 | if(len < 3) { 266 | goto ndpi_end_bt_tracker_check; 267 | } 268 | if(*ptr == '%') { 269 | u_int8_t x1 = 0xFF; 270 | u_int8_t x2 = 0xFF; 271 | 272 | 273 | if(ptr[1] >= '0' && ptr[1] <= '9') { 274 | x1 = ptr[1] - '0'; 275 | } 276 | if(ptr[1] >= 'a' && ptr[1] <= 'f') { 277 | x1 = 10 + ptr[1] - 'a'; 278 | } 279 | if(ptr[1] >= 'A' && ptr[1] <= 'F') { 280 | x1 = 10 + ptr[1] - 'A'; 281 | } 282 | 283 | if(ptr[2] >= '0' && ptr[2] <= '9') { 284 | x2 = ptr[2] - '0'; 285 | } 286 | if(ptr[2] >= 'a' && ptr[2] <= 'f') { 287 | x2 = 10 + ptr[2] - 'a'; 288 | } 289 | if(ptr[2] >= 'A' && ptr[2] <= 'F') { 290 | x2 = 10 + ptr[2] - 'A'; 291 | } 292 | 293 | if(x1 == 0xFF || x2 == 0xFF) { 294 | goto ndpi_end_bt_tracker_check; 295 | } 296 | ptr += 3; 297 | len -= 3; 298 | } else if(*ptr >= 32 && *ptr < 127) { 299 | ptr++; 300 | len--; 301 | } else { 302 | goto ndpi_end_bt_tracker_check; 303 | } 304 | } 305 | 306 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, 307 | NDPI_LOG_TRACE, " BT stat: tracker info hash parsed\n"); 308 | ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, 309 | NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); 310 | return 1; 311 | } 312 | 313 | ndpi_end_bt_tracker_check: 314 | 315 | if(packet->payload_packet_len == 80) { 316 | /* Warez 80 Bytes Packet 317 | * +----------------+---------------+-----------------+-----------------+ 318 | * |20 BytesPattern | 32 Bytes Value| 12 BytesPattern | 16 Bytes Data | 319 | * +----------------+---------------+-----------------+-----------------+ 320 | * 20 BytesPattern : 4c 00 00 00 ff ff ff ff 57 00 00 00 00 00 00 00 20 00 00 00 321 | * 12 BytesPattern : 28 23 00 00 01 00 00 00 10 00 00 00 322 | * */ 323 | static const char pattern_20_bytes[20] = { 0x4c, 0x00, 0x00, 0x00, 0xff, 324 | 0xff, 0xff, 0xff, 0x57, 0x00, 325 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00 326 | }; 327 | static const char pattern_12_bytes[12] = { 0x28, 0x23, 0x00, 0x00, 0x01, 328 | 0x00, 0x00, 0x00, 0x10, 0x00, 329 | 0x00, 0x00 330 | }; 331 | 332 | /* did not see this pattern anywhere */ 333 | if((memcmp(&packet->payload[0], pattern_20_bytes, 20) == 0) 334 | && (memcmp(&packet->payload[52], pattern_12_bytes, 12) == 0)) { 335 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, 336 | NDPI_LOG_TRACE, "BT: Warez - Plain BitTorrent protocol detected\n"); 337 | ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, 338 | NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); 339 | return 1; 340 | } 341 | } 342 | 343 | else if(packet->payload_packet_len > 50) { 344 | if(memcmp(packet->payload, "GET", 3) == 0) { 345 | 346 | ndpi_parse_packet_line_info(ndpi_struct, flow); 347 | /* haven't fount this pattern anywhere */ 348 | if(packet->host_line.ptr != NULL 349 | && packet->host_line.len >= 9 && memcmp(packet->host_line.ptr, "ip2p.com:", 9) == 0) { 350 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, 351 | ndpi_struct, NDPI_LOG_TRACE, 352 | "BT: Warez - Plain BitTorrent protocol detected due to Host: ip2p.com: pattern\n"); 353 | ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, 354 | NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION); 355 | return 1; 356 | } 357 | } 358 | } 359 | return 0; 360 | } 361 | 362 | 363 | /*Search for BitTorrent commands*/ 364 | static void ndpi_int_search_bittorrent_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) 365 | { 366 | struct ndpi_packet_struct *packet = &flow->packet; 367 | 368 | if(packet->payload_packet_len == 0) { 369 | return; 370 | } 371 | 372 | if(flow->bittorrent_stage == 0 && packet->payload_packet_len != 0) { 373 | /* exclude stage 0 detection from next run */ 374 | flow->bittorrent_stage = 1; 375 | if(ndpi_int_search_bittorrent_tcp_zero(ndpi_struct, flow) != 0) { 376 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_DEBUG, 377 | "stage 0 has detected something, returning\n"); 378 | return; 379 | } 380 | 381 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_DEBUG, 382 | "stage 0 has no direct detection, fall through\n"); 383 | } 384 | return; 385 | } 386 | 387 | void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) 388 | { 389 | struct ndpi_packet_struct *packet = &flow->packet; 390 | int no_bittorrent = 0; 391 | char *bt_proto = NULL; 392 | 393 | /* This is broadcast */ 394 | if(packet->iph 395 | && (((packet->iph->saddr == 0xFFFFFFFF) || (packet->iph->daddr == 0xFFFFFFFF)) 396 | || (packet->udp 397 | && ((ntohs(packet->udp->source) == 3544) /* teredo.c */ 398 | || (ntohs(packet->udp->dest) == 3544))))) { 399 | NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_BITTORRENT); 400 | return; 401 | } 402 | 403 | if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_BITTORRENT) { 404 | /* check for tcp retransmission here */ 405 | 406 | if((packet->tcp != NULL) 407 | && (packet->tcp_retransmission == 0 || packet->num_retried_bytes)) { 408 | ndpi_int_search_bittorrent_tcp(ndpi_struct, flow); 409 | } 410 | else if(packet->udp != NULL) { 411 | char *bt_search = "BT-SEARCH * HTTP/1.1\r\n"; 412 | 413 | if((ntohs(packet->udp->source) < 1024) 414 | || (ntohs(packet->udp->dest) < 1024) /* High ports only */) 415 | return; 416 | 417 | /* 418 | Check for uTP http://www.bittorrent.org/beps/bep_0029.html 419 | 420 | wireshark/epan/dissectors/packet-bt-utp.c 421 | */ 422 | 423 | if(packet->payload_packet_len >= 23 /* min header size */) { 424 | if(strncmp((const char*)packet->payload, bt_search, strlen(bt_search)) == 0) { 425 | ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, 426 | NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); 427 | return; 428 | } else { 429 | /* Check if this is protocol v0 */ 430 | u_int8_t v0_extension = packet->payload[17]; 431 | u_int8_t v0_flags = packet->payload[18]; 432 | 433 | /* Check if this is protocol v1 */ 434 | u_int8_t v1_version = packet->payload[0]; 435 | u_int8_t v1_extension = packet->payload[1]; 436 | u_int32_t v1_window_size = *((u_int32_t*)&packet->payload[12]); 437 | 438 | if(is_utp_pkt(packet->payload, packet->payload_packet_len)) 439 | goto bittorrent_found; 440 | else if((packet->payload[0]== 0x60) 441 | && (packet->payload[1]== 0x0) 442 | && (packet->payload[2]== 0x0) 443 | && (packet->payload[3]== 0x0) 444 | && (packet->payload[4]== 0x0)) { 445 | /* Heuristic */ 446 | bt_proto = ndpi_strnstr((const char *)&packet->payload[20], "BitTorrent protocol", packet->payload_packet_len-20); 447 | goto bittorrent_found; 448 | } else if(((v1_version & 0x0f) == 1) 449 | && ((v1_version >> 4) < 5 /* ST_NUM_STATES */) 450 | && (v1_extension < 3 /* EXT_NUM_EXT */) 451 | && (v1_window_size < 32768 /* 32k */) 452 | ) { 453 | bt_proto = ndpi_strnstr((const char *)&packet->payload[20], "BitTorrent protocol", packet->payload_packet_len-20); 454 | goto bittorrent_found; 455 | } else if((v0_flags < 6 /* ST_NUM_STATES */) && (v0_extension < 3 /* EXT_NUM_EXT */)) { 456 | u_int32_t ts = ntohl(*((u_int32_t*)&(packet->payload[4]))); 457 | u_int32_t now; 458 | 459 | #ifndef __KERNEL__ 460 | now = (u_int32_t)time(NULL); 461 | #else 462 | struct timespec t; 463 | 464 | getnstimeofday(&t); 465 | now = t.tv_sec; 466 | #endif 467 | 468 | if((ts < (now+86400)) && (ts > (now-86400))) { 469 | bt_proto = ndpi_strnstr((const char *)&packet->payload[20], "BitTorrent protocol", packet->payload_packet_len-20); 470 | goto bittorrent_found; 471 | } 472 | } 473 | } 474 | } 475 | 476 | flow->bittorrent_stage++; 477 | 478 | if(flow->bittorrent_stage < 10) { 479 | /* We have detected bittorrent but we need to wait until we get a hash */ 480 | 481 | if(packet->payload_packet_len > 19 /* min size */) { 482 | if(ndpi_strnstr((const char *)packet->payload, ":target20:", packet->payload_packet_len) 483 | || ndpi_strnstr((const char *)packet->payload, ":find_node1:", packet->payload_packet_len) 484 | || ndpi_strnstr((const char *)packet->payload, "d1:ad2:id20:", packet->payload_packet_len) 485 | || ndpi_strnstr((const char *)packet->payload, ":info_hash20:", packet->payload_packet_len) 486 | || ndpi_strnstr((const char *)packet->payload, ":filter64", packet->payload_packet_len) 487 | || ndpi_strnstr((const char *)packet->payload, "d1:rd2:id20:", packet->payload_packet_len) 488 | || (bt_proto = ndpi_strnstr((const char *)packet->payload, "BitTorrent protocol", packet->payload_packet_len)) 489 | ) { 490 | bittorrent_found: 491 | if(bt_proto && (packet->payload_packet_len > 47)) 492 | memcpy(flow->bittorent_hash, &bt_proto[27], 20); 493 | 494 | NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, 495 | ndpi_struct, NDPI_LOG_TRACE, "BT: plain BitTorrent protocol detected\n"); 496 | ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 0, 497 | NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); 498 | return; 499 | } 500 | } 501 | 502 | return; 503 | } 504 | 505 | NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_BITTORRENT); 506 | } 507 | } 508 | } 509 | 510 | 511 | void init_bittorrent_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask) 512 | { 513 | ndpi_set_bitmask_protocol_detection("BitTorrent", ndpi_struct, detection_bitmask, *id, 514 | NDPI_PROTOCOL_BITTORRENT, 515 | ndpi_search_bittorrent, 516 | NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP, 517 | SAVE_DETECTION_BITMASK_AS_UNKNOWN, 518 | ADD_TO_DETECTION_BITMASK); 519 | *id += 1; 520 | } 521 | 522 | #endif 523 | -------------------------------------------------------------------------------- /nDPI-patch/src/lib/protocols/fiesta.c: -------------------------------------------------------------------------------- 1 | /* 2 | * fiesta.c 3 | * 4 | * Copyright (C) 2009-2011 by ipoque GmbH 5 | * Copyright (C) 2011-15 - ntop.org 6 | * 7 | * This file is part of nDPI, an open source deep packet inspection 8 | * library based on the OpenDPI and PACE technology by ipoque GmbH 9 | * 10 | * nDPI is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * nDPI is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Lesser General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with nDPI. If not, see . 22 | * 23 | * Rev.1.1 24 | * 25 | */ 26 | 27 | /* include files */ 28 | #include "ndpi_protocols.h" 29 | #ifdef NDPI_PROTOCOL_FIESTA 30 | 31 | 32 | static void ndpi_int_fiesta_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) 33 | { 34 | ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_FIESTA, NDPI_PROTOCOL_UNKNOWN); 35 | } 36 | 37 | void ndpi_search_fiesta(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) 38 | { 39 | struct ndpi_packet_struct *packet = &flow->packet; 40 | 41 | // struct ndpi_id_struct *src=ndpi_struct->src; 42 | // struct ndpi_id_struct *dst=ndpi_struct->dst; 43 | 44 | NDPI_LOG(NDPI_PROTOCOL_FIESTA, ndpi_struct, NDPI_LOG_DEBUG, "search fiesta.\n"); 45 | 46 | if (flow->l4.tcp.fiesta_stage == 0 && packet->payload_packet_len == 5 47 | && get_u_int16_t(packet->payload, 0) == ntohs(0x0407) 48 | && (packet->payload[2] == 0x08) 49 | && (packet->payload[4] == 0x00 || packet->payload[4] == 0x01)) { 50 | 51 | NDPI_LOG(NDPI_PROTOCOL_FIESTA, ndpi_struct, NDPI_LOG_DEBUG, "maybe fiesta symmetric, first packet.\n"); 52 | flow->l4.tcp.fiesta_stage = 1 + packet->packet_direction; 53 | goto maybe_fiesta; 54 | } 55 | if (flow->l4.tcp.fiesta_stage == (2 - packet->packet_direction) 56 | && ((packet->payload_packet_len > 1 && packet->payload_packet_len - 1 == packet->payload[0]) 57 | || (packet->payload_packet_len > 3 && packet->payload[0] == 0 58 | && get_l16(packet->payload, 1) == packet->payload_packet_len - 3))) { 59 | NDPI_LOG(NDPI_PROTOCOL_FIESTA, ndpi_struct, NDPI_LOG_DEBUG, "Maybe fiesta.\n"); 60 | goto maybe_fiesta; 61 | } 62 | if (flow->l4.tcp.fiesta_stage == (1 + packet->packet_direction)) { 63 | if (packet->payload_packet_len == 4 && get_u_int32_t(packet->payload, 0) == htonl(0x03050c01)) { 64 | goto add_fiesta; 65 | } 66 | if (packet->payload_packet_len == 5 && get_u_int32_t(packet->payload, 0) == htonl(0x04030c01) 67 | && packet->payload[4] == 0) { 68 | goto add_fiesta; 69 | } 70 | if (packet->payload_packet_len == 6 && get_u_int32_t(packet->payload, 0) == htonl(0x050e080b)) { 71 | goto add_fiesta; 72 | } 73 | if (packet->payload_packet_len == 100 && packet->payload[0] == 0x63 && packet->payload[61] == 0x52 74 | && packet->payload[81] == 0x5a && get_u_int16_t(packet->payload, 1) == htons(0x3810) 75 | && get_u_int16_t(packet->payload, 62) == htons(0x6f75)) { 76 | goto add_fiesta; 77 | } 78 | if (packet->payload_packet_len > 3 && packet->payload_packet_len - 1 == packet->payload[0] 79 | && get_u_int16_t(packet->payload, 1) == htons(0x140c)) { 80 | goto add_fiesta; 81 | } 82 | } 83 | 84 | NDPI_LOG(NDPI_PROTOCOL_FIESTA, ndpi_struct, NDPI_LOG_DEBUG, "exclude fiesta.\n"); 85 | NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_FIESTA); 86 | return; 87 | 88 | maybe_fiesta: 89 | NDPI_LOG(NDPI_PROTOCOL_FIESTA, ndpi_struct, NDPI_LOG_DEBUG, "Stage is set to %d.\n", flow->l4.tcp.fiesta_stage); 90 | return; 91 | 92 | add_fiesta: 93 | NDPI_LOG(NDPI_PROTOCOL_FIESTA, ndpi_struct, NDPI_LOG_DEBUG, "detected fiesta.\n"); 94 | ndpi_int_fiesta_add_connection(ndpi_struct, flow); 95 | return; 96 | } 97 | 98 | 99 | void init_fiesta_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask) 100 | { 101 | ndpi_set_bitmask_protocol_detection("Fiesta", ndpi_struct, detection_bitmask, *id, 102 | NDPI_PROTOCOL_FIESTA, 103 | ndpi_search_fiesta, 104 | NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION, 105 | SAVE_DETECTION_BITMASK_AS_UNKNOWN, 106 | ADD_TO_DETECTION_BITMASK); 107 | 108 | *id += 1; 109 | } 110 | #endif 111 | -------------------------------------------------------------------------------- /nDPI-patch/src/lib/protocols/git.c: -------------------------------------------------------------------------------- 1 | /* 2 | * git.c 3 | * 4 | * Copyright (C) 2012-16 - ntop.org 5 | * 6 | * This module is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This module is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License. 17 | * If not, see . 18 | * 19 | * Rev.1 20 | * 21 | */ 22 | #ifndef __KERNEL__ 23 | #include 24 | #endif 25 | #include "ndpi_api.h" 26 | 27 | #ifdef NDPI_PROTOCOL_GIT 28 | 29 | #define GIT_PORT 9418 30 | 31 | #ifdef __KERNEL__ 32 | extern int atoi(const char *str); 33 | #endif 34 | 35 | void ndpi_search_git(struct ndpi_detection_module_struct *ndpi_struct, 36 | struct ndpi_flow_struct *flow) 37 | { 38 | struct ndpi_packet_struct * packet = &flow->packet; 39 | 40 | if((packet->tcp != NULL) && (packet->payload_packet_len > 4)) { 41 | if((ntohs(packet->tcp->source) == GIT_PORT) 42 | || (ntohs(packet->tcp->dest) == GIT_PORT)) { 43 | const u_int8_t * pp = packet->payload; 44 | u_int16_t payload_len = packet->payload_packet_len; 45 | u_int8_t found_git = 1; 46 | u_int16_t git_len = 0, offset = 0; 47 | 48 | while((offset+4) < payload_len) { 49 | char len[5]; 50 | u_int32_t git_pkt_len; 51 | 52 | memcpy(&len, &pp[offset], 4), len[4] = 0; 53 | git_pkt_len = atoi(len); 54 | 55 | if((payload_len < git_pkt_len) || (git_pkt_len == 0 /* Bad */)) { 56 | found_git = 0; 57 | break; 58 | } else 59 | offset += git_pkt_len, payload_len -= git_pkt_len; 60 | } 61 | 62 | if(found_git) { 63 | NDPI_LOG(NDPI_PROTOCOL_GIT, ndpi_struct, NDPI_LOG_DEBUG, "found Git.\n"); 64 | ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_GIT, NDPI_PROTOCOL_UNKNOWN); 65 | return; 66 | } 67 | } 68 | } 69 | 70 | NDPI_LOG(NDPI_PROTOCOL_GIT, ndpi_struct, NDPI_LOG_DEBUG, "exclude Git.\n"); 71 | NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_GIT); 72 | } 73 | 74 | 75 | /* ***************************************************************** */ 76 | 77 | 78 | void init_git_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, 79 | NDPI_PROTOCOL_BITMASK *detection_bitmask) 80 | { 81 | ndpi_set_bitmask_protocol_detection("Git", ndpi_struct, detection_bitmask, *id, 82 | NDPI_PROTOCOL_GIT, 83 | ndpi_search_git, 84 | NDPI_SELECTION_BITMASK_PROTOCOL_TCP_WITH_PAYLOAD, 85 | SAVE_DETECTION_BITMASK_AS_UNKNOWN, 86 | ADD_TO_DETECTION_BITMASK); 87 | 88 | *id += 1; 89 | } 90 | 91 | #endif /* NDPI_PROTOCOL_GIT */ 92 | -------------------------------------------------------------------------------- /nDPI-patch/src/lib/protocols/netflow.c: -------------------------------------------------------------------------------- 1 | /* 2 | * netflow.c 3 | * 4 | * Copyright (C) 2011-15 - ntop.org 5 | * 6 | * nDPI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * nDPI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with nDPI. If not, see . 18 | * 19 | * Rev.1.1 20 | * 21 | */ 22 | 23 | 24 | #include "ndpi_api.h" 25 | 26 | #ifdef NDPI_PROTOCOL_NETFLOW 27 | 28 | #ifndef __KERNEL__ 29 | #ifdef WIN32 30 | extern int gettimeofday(struct timeval * tp, struct timezone * tzp); 31 | #endif 32 | #define do_gettimeofday(a) gettimeofday(a, NULL) 33 | #endif 34 | 35 | struct flow_ver1_rec { 36 | u_int32_t srcaddr; /* Source IP Address */ 37 | u_int32_t dstaddr; /* Destination IP Address */ 38 | u_int32_t nexthop; /* Next hop router's IP Address */ 39 | u_int16_t input; /* Input interface index */ 40 | u_int16_t output; /* Output interface index */ 41 | u_int32_t dPkts; /* Packets sent in Duration */ 42 | u_int32_t dOctets; /* Octets sent in Duration */ 43 | u_int32_t first; /* SysUptime at start of flow */ 44 | u_int32_t last; /* and of last packet of the flow */ 45 | u_int16_t srcport; /* TCP/UDP source port number (.e.g, FTP, Telnet, etc.,or equivalent) */ 46 | u_int16_t dstport; /* TCP/UDP destination port number (.e.g, FTP, Telnet, etc.,or equivalent) */ 47 | u_int16_t pad; /* pad to word boundary */ 48 | u_int8_t proto; /* IP protocol, e.g., 6=TCP, 17=UDP, etc... */ 49 | u_int8_t tos; /* IP Type-of-Service */ 50 | u_int8_t pad2[7]; /* pad to word boundary */ 51 | }; 52 | 53 | struct flow_ver5_rec { 54 | u_int32_t srcaddr; /* Source IP Address */ 55 | u_int32_t dstaddr; /* Destination IP Address */ 56 | u_int32_t nexthop; /* Next hop router's IP Address */ 57 | u_int16_t input; /* Input interface index */ 58 | u_int16_t output; /* Output interface index */ 59 | u_int32_t dPkts; /* Packets sent in Duration (milliseconds between 1st 60 | & last packet in this flow)*/ 61 | u_int32_t dOctets; /* Octets sent in Duration (milliseconds between 1st 62 | & last packet in this flow)*/ 63 | u_int32_t first; /* SysUptime at start of flow */ 64 | u_int32_t last; /* and of last packet of the flow */ 65 | u_int16_t srcport; /* TCP/UDP source port number (.e.g, FTP, Telnet, etc.,or equivalent) */ 66 | u_int16_t dstport; /* TCP/UDP destination port number (.e.g, FTP, Telnet, etc.,or equivalent) */ 67 | u_int8_t pad1; /* pad to word boundary */ 68 | u_int8_t tcp_flags; /* Cumulative OR of tcp flags */ 69 | u_int8_t proto; /* IP protocol, e.g., 6=TCP, 17=UDP, etc... */ 70 | u_int8_t tos; /* IP Type-of-Service */ 71 | u_int16_t src_as; /* source peer/origin Autonomous System */ 72 | u_int16_t dst_as; /* dst peer/origin Autonomous System */ 73 | u_int8_t src_mask; /* source route's mask bits */ 74 | u_int8_t dst_mask; /* destination route's mask bits */ 75 | u_int16_t pad2; /* pad to word boundary */ 76 | }; 77 | 78 | struct flow_ver7_rec { 79 | u_int32_t srcaddr; /* Source IP Address */ 80 | u_int32_t dstaddr; /* Destination IP Address */ 81 | u_int32_t nexthop; /* Next hop router's IP Address */ 82 | u_int16_t input; /* Input interface index */ 83 | u_int16_t output; /* Output interface index */ 84 | u_int32_t dPkts; /* Packets sent in Duration */ 85 | u_int32_t dOctets; /* Octets sent in Duration */ 86 | u_int32_t first; /* SysUptime at start of flow */ 87 | u_int32_t last; /* and of last packet of the flow */ 88 | u_int16_t srcport; /* TCP/UDP source port number (.e.g, FTP, Telnet, etc.,or equivalent) */ 89 | u_int16_t dstport; /* TCP/UDP destination port number (.e.g, FTP, Telnet, etc.,or equivalent) */ 90 | u_int8_t flags; /* Shortcut mode(dest only,src only,full flows*/ 91 | u_int8_t tcp_flags; /* Cumulative OR of tcp flags */ 92 | u_int8_t proto; /* IP protocol, e.g., 6=TCP, 17=UDP, etc... */ 93 | u_int8_t tos; /* IP Type-of-Service */ 94 | u_int16_t dst_as; /* dst peer/origin Autonomous System */ 95 | u_int16_t src_as; /* source peer/origin Autonomous System */ 96 | u_int8_t dst_mask; /* destination route's mask bits */ 97 | u_int8_t src_mask; /* source route's mask bits */ 98 | u_int16_t pad2; /* pad to word boundary */ 99 | u_int32_t router_sc; /* Router which is shortcut by switch */ 100 | }; 101 | 102 | static void ndpi_check_netflow(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) 103 | { 104 | struct ndpi_packet_struct *packet = &flow->packet; 105 | // const u_int8_t *packet_payload = packet->payload; 106 | u_int32_t payload_len = packet->payload_packet_len; 107 | time_t now; 108 | struct timeval now_tv; 109 | 110 | if((packet->udp != NULL) && (payload_len >= 24)) { 111 | u_int16_t version = (packet->payload[0] << 8) + packet->payload[1], uptime_offset; 112 | u_int32_t when, *_when; 113 | u_int16_t n = (packet->payload[2] << 8) + packet->payload[3], expected_len = 0; 114 | 115 | switch(version) { 116 | case 1: 117 | case 5: 118 | case 7: 119 | case 9: 120 | if((n == 0) || (n > 30)) 121 | return; 122 | 123 | switch(version) { 124 | case 1: 125 | expected_len = n * sizeof(struct flow_ver1_rec) + 16 /* header */; 126 | break; 127 | case 5: 128 | expected_len = n * sizeof(struct flow_ver5_rec) + 24 /* header */; 129 | break; 130 | case 7: 131 | expected_len = n * sizeof(struct flow_ver7_rec) + 24 /* header */; 132 | break; 133 | case 9: 134 | /* We need to check the template */ 135 | break; 136 | } 137 | 138 | if((expected_len > 0) && (expected_len != payload_len)) { 139 | NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_NETFLOW); 140 | return; 141 | } 142 | 143 | uptime_offset = 8; 144 | break; 145 | case 10: /* IPFIX */ 146 | { 147 | u_int16_t ipfix_len = n; 148 | 149 | if(ipfix_len != payload_len) 150 | return; 151 | } 152 | uptime_offset = 4; 153 | break; 154 | default: 155 | return; 156 | } 157 | 158 | _when = (u_int32_t*)&packet->payload[uptime_offset]; /* Sysuptime */ 159 | when = ntohl(*_when); 160 | 161 | do_gettimeofday(&now_tv); 162 | now = now_tv.tv_sec; 163 | 164 | if(((version == 1) && (when == 0)) 165 | || ((when >= 946684800 /* 1/1/2000 */) && (when <= now))) { 166 | NDPI_LOG(NDPI_PROTOCOL_NETFLOW, ndpi_struct, NDPI_LOG_DEBUG, "Found netflow.\n"); 167 | ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_NETFLOW, NDPI_PROTOCOL_UNKNOWN); 168 | return; 169 | } 170 | } 171 | } 172 | 173 | void ndpi_search_netflow(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) 174 | { 175 | NDPI_LOG(NDPI_PROTOCOL_NETFLOW, ndpi_struct, NDPI_LOG_DEBUG, "netflow detection...\n"); 176 | ndpi_check_netflow(ndpi_struct, flow); 177 | } 178 | 179 | 180 | void init_netflow_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask) 181 | { 182 | ndpi_set_bitmask_protocol_detection("NetFlow", ndpi_struct, detection_bitmask, *id, 183 | NDPI_PROTOCOL_NETFLOW, 184 | ndpi_search_netflow, 185 | NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD, 186 | SAVE_DETECTION_BITMASK_AS_UNKNOWN, 187 | ADD_TO_DETECTION_BITMASK); 188 | 189 | *id += 1; 190 | } 191 | 192 | #endif 193 | -------------------------------------------------------------------------------- /nDPI-patch/src/lib/third_party/include/ndpi_patricia.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/betolj/ndpi-netfilter/4875069df027199698ba0b7c53541ae2a4e3ba00/nDPI-patch/src/lib/third_party/include/ndpi_patricia.h -------------------------------------------------------------------------------- /nDPI-patch/src/lib/third_party/src/ahocorasick.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ahocorasick.c: implementation of ahocorasick library's functions 3 | * This file is part of multifast. 4 | * 5 | * Rev.1.1 6 | * 7 | Copyright 2010-2012 Kamiar Kanani 8 | 9 | multifast is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | multifast is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with multifast. If not, see . 21 | */ 22 | 23 | #ifndef __KERNEL__ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #endif 29 | 30 | #include "ndpi_api.h" 31 | #include "ahocorasick.h" 32 | 33 | /* Allocation step for automata.all_nodes */ 34 | #define REALLOC_CHUNK_ALLNODES 200 35 | 36 | /* Private function prototype */ 37 | static void ac_automata_register_nodeptr 38 | (AC_AUTOMATA_t * thiz, AC_NODE_t * node); 39 | static void ac_automata_union_matchstrs 40 | (AC_NODE_t * node); 41 | static void ac_automata_set_failure 42 | (AC_AUTOMATA_t * thiz, AC_NODE_t * node, AC_ALPHABET_t * alphas); 43 | static void ac_automata_traverse_setfailure 44 | (AC_AUTOMATA_t * thiz, AC_NODE_t * node, AC_ALPHABET_t * alphas); 45 | 46 | 47 | /****************************************************************************** 48 | * FUNCTION: ac_automata_init 49 | * Initialize automata; allocate memories and set initial values 50 | * PARAMS: 51 | * MATCH_CALBACK mc: call-back function 52 | * the call-back function will be used to reach the caller on match occurrence 53 | ******************************************************************************/ 54 | AC_AUTOMATA_t * ac_automata_init (MATCH_CALBACK_f mc) 55 | { 56 | AC_AUTOMATA_t * thiz = (AC_AUTOMATA_t *)ndpi_malloc(sizeof(AC_AUTOMATA_t)); 57 | memset (thiz, 0, sizeof(AC_AUTOMATA_t)); 58 | thiz->root = node_create (); 59 | thiz->all_nodes_max = REALLOC_CHUNK_ALLNODES; 60 | thiz->all_nodes = (AC_NODE_t **) ndpi_malloc (thiz->all_nodes_max*sizeof(AC_NODE_t *)); 61 | thiz->match_callback = mc; 62 | ac_automata_register_nodeptr (thiz, thiz->root); 63 | ac_automata_reset (thiz); 64 | thiz->total_patterns = 0; 65 | thiz->automata_open = 1; 66 | return thiz; 67 | } 68 | 69 | /****************************************************************************** 70 | * FUNCTION: ac_automata_add 71 | * Adds pattern to the automata. 72 | * PARAMS: 73 | * AC_AUTOMATA_t * thiz: the pointer to the automata 74 | * AC_PATTERN_t * patt: the pointer to added pattern 75 | * RETUERN VALUE: AC_ERROR_t 76 | * the return value indicates the success or failure of adding action 77 | ******************************************************************************/ 78 | AC_ERROR_t ac_automata_add (AC_AUTOMATA_t * thiz, AC_PATTERN_t * patt) 79 | { 80 | unsigned int i; 81 | AC_NODE_t * n = thiz->root; 82 | AC_NODE_t * next; 83 | AC_ALPHABET_t alpha; 84 | 85 | if(!thiz->automata_open) 86 | return ACERR_AUTOMATA_CLOSED; 87 | 88 | if (!patt->length) 89 | return ACERR_ZERO_PATTERN; 90 | 91 | if (patt->length > AC_PATTRN_MAX_LENGTH) 92 | return ACERR_LONG_PATTERN; 93 | 94 | for (i=0; ilength; i++) 95 | { 96 | alpha = patt->astring[i]; 97 | if ((next = node_find_next(n, alpha))) 98 | { 99 | n = next; 100 | continue; 101 | } 102 | else 103 | { 104 | next = node_create_next(n, alpha); 105 | next->depth = n->depth + 1; 106 | n = next; 107 | ac_automata_register_nodeptr(thiz, n); 108 | } 109 | } 110 | 111 | if(n->final) 112 | return ACERR_DUPLICATE_PATTERN; 113 | 114 | n->final = 1; 115 | node_register_matchstr(n, patt); 116 | thiz->total_patterns++; 117 | 118 | return ACERR_SUCCESS; 119 | } 120 | 121 | /****************************************************************************** 122 | * FUNCTION: ac_automata_finalize 123 | * Locate the failure node for all nodes and collect all matched pattern for 124 | * every node. it also sorts outgoing edges of node, so binary search could be 125 | * performed on them. after calling this function the automate literally will 126 | * be finalized and you can not add new patterns to the automate. 127 | * PARAMS: 128 | * AC_AUTOMATA_t * thiz: the pointer to the automata 129 | ******************************************************************************/ 130 | void ac_automata_finalize (AC_AUTOMATA_t * thiz) 131 | { 132 | unsigned int i; 133 | AC_ALPHABET_t *alphas; 134 | AC_NODE_t * node; 135 | 136 | if((alphas = ndpi_malloc(AC_PATTRN_MAX_LENGTH)) != NULL) { 137 | ac_automata_traverse_setfailure (thiz, thiz->root, alphas); 138 | 139 | for (i=0; i < thiz->all_nodes_num; i++) 140 | { 141 | node = thiz->all_nodes[i]; 142 | ac_automata_union_matchstrs (node); 143 | node_sort_edges (node); 144 | } 145 | thiz->automata_open = 0; /* do not accept patterns any more */ 146 | ndpi_free(alphas); 147 | } 148 | } 149 | 150 | /****************************************************************************** 151 | * FUNCTION: ac_automata_search 152 | * Search in the input text using the given automata. on match event it will 153 | * call the call-back function. and the call-back function in turn after doing 154 | * its job, will return an integer value to ac_automata_search(). 0 value means 155 | * continue search, and non-0 value means stop search and return to the caller. 156 | * PARAMS: 157 | * AC_AUTOMATA_t * thiz: the pointer to the automata 158 | * AC_TEXT_t * txt: the input text that must be searched 159 | * void * param: this parameter will be send to call-back function. it is 160 | * useful for sending parameter to call-back function from caller function. 161 | * RETURN VALUE: 162 | * -1: failed call; automata is not finalized 163 | * 0: success; continue searching; call-back sent me a 0 value 164 | * 1: success; stop searching; call-back sent me a non-0 value 165 | ******************************************************************************/ 166 | int ac_automata_search (AC_AUTOMATA_t * thiz, AC_TEXT_t * txt, void * param) 167 | { 168 | unsigned long position; 169 | AC_NODE_t *curr; 170 | AC_NODE_t *next; 171 | 172 | if(thiz->automata_open) 173 | /* you must call ac_automata_locate_failure() first */ 174 | return -1; 175 | 176 | position = 0; 177 | curr = thiz->current_node; 178 | 179 | /* This is the main search loop. 180 | * it must be keep as lightweight as possible. */ 181 | while (position < txt->length) 182 | { 183 | if(!(next = node_findbs_next(curr, txt->astring[position]))) 184 | { 185 | if(curr->failure_node /* we are not in the root node */) 186 | curr = curr->failure_node; 187 | else 188 | position++; 189 | } 190 | else 191 | { 192 | curr = next; 193 | position++; 194 | } 195 | 196 | if(curr->final && next) 197 | /* We check 'next' to find out if we came here after a alphabet 198 | * transition or due to a fail. in second case we should not report 199 | * matching because it was reported in previous node */ 200 | { 201 | thiz->match.position = position + thiz->base_position; 202 | thiz->match.match_num = curr->matched_patterns_num; 203 | thiz->match.patterns = curr->matched_patterns; 204 | /* we found a match! do call-back */ 205 | if (thiz->match_callback(&thiz->match, param)) 206 | return 1; 207 | } 208 | } 209 | 210 | /* save status variables */ 211 | thiz->current_node = curr; 212 | thiz->base_position += position; 213 | return 0; 214 | } 215 | 216 | /****************************************************************************** 217 | * FUNCTION: ac_automata_reset 218 | * reset the automata and make it ready for doing new search on a new text. 219 | * when you finished with the input text, you must reset automata state for 220 | * new input, otherwise it will not work. 221 | * PARAMS: 222 | * AC_AUTOMATA_t * thiz: the pointer to the automata 223 | ******************************************************************************/ 224 | void ac_automata_reset (AC_AUTOMATA_t * thiz) 225 | { 226 | thiz->current_node = thiz->root; 227 | thiz->base_position = 0; 228 | } 229 | 230 | /****************************************************************************** 231 | * FUNCTION: ac_automata_release 232 | * Release all allocated memories to the automata 233 | * PARAMS: 234 | * AC_AUTOMATA_t * thiz: the pointer to the automata 235 | ******************************************************************************/ 236 | void ac_automata_release (AC_AUTOMATA_t * thiz) 237 | { 238 | unsigned int i; 239 | AC_NODE_t * n; 240 | 241 | for (i=0; i < thiz->all_nodes_num; i++) 242 | { 243 | n = thiz->all_nodes[i]; 244 | node_release(n); 245 | } 246 | ndpi_free(thiz->all_nodes); 247 | ndpi_free(thiz); 248 | } 249 | 250 | #ifndef __KERNEL__ 251 | /****************************************************************************** 252 | * FUNCTION: ac_automata_display 253 | * Prints the automata to output in human readable form. it is useful for 254 | * debugging purpose. 255 | * PARAMS: 256 | * AC_AUTOMATA_t * thiz: the pointer to the automata 257 | * char repcast: 'n': print AC_REP_t as number, 's': print AC_REP_t as string 258 | ******************************************************************************/ 259 | void ac_automata_display (AC_AUTOMATA_t * thiz, char repcast) 260 | { 261 | unsigned int i, j; 262 | AC_NODE_t * n; 263 | struct edge * e; 264 | AC_PATTERN_t sid; 265 | 266 | printf("---------------------------------\n"); 267 | 268 | for (i=0; iall_nodes_num; i++) 269 | { 270 | n = thiz->all_nodes[i]; 271 | printf("NODE(%3d)/----fail----> NODE(%3d)\n", 272 | n->id, (n->failure_node)?n->failure_node->id:1); 273 | for (j=0; joutgoing_degree; j++) 274 | { 275 | e = &n->outgoing[j]; 276 | printf(" |----("); 277 | if(isgraph(e->alpha)) 278 | printf("%c)---", e->alpha); 279 | else 280 | printf("0x%x)", e->alpha); 281 | printf("--> NODE(%3d)\n", e->next->id); 282 | } 283 | if (n->matched_patterns_num) { 284 | printf("Accepted patterns: {"); 285 | for (j=0; jmatched_patterns_num; j++) 286 | { 287 | sid = n->matched_patterns[j]; 288 | if(j) printf(", "); 289 | switch (repcast) 290 | { 291 | case 'n': 292 | printf("%ld", sid.rep.number); 293 | break; 294 | case 's': 295 | printf("%s", sid.rep.stringy); 296 | break; 297 | } 298 | } 299 | printf("}\n"); 300 | } 301 | printf("---------------------------------\n"); 302 | } 303 | } 304 | #endif /* __KERNEL__ */ 305 | 306 | /****************************************************************************** 307 | * FUNCTION: ac_automata_register_nodeptr 308 | * Adds the node pointer to all_nodes. 309 | ******************************************************************************/ 310 | static void ac_automata_register_nodeptr (AC_AUTOMATA_t * thiz, AC_NODE_t * node) 311 | { 312 | if(thiz->all_nodes_num >= thiz->all_nodes_max) 313 | { 314 | thiz->all_nodes = ndpi_realloc(thiz->all_nodes, 315 | thiz->all_nodes_max*sizeof(AC_NODE_t *), 316 | (REALLOC_CHUNK_ALLNODES+thiz->all_nodes_max)*sizeof(AC_NODE_t *) 317 | ); 318 | thiz->all_nodes_max += REALLOC_CHUNK_ALLNODES; 319 | } 320 | thiz->all_nodes[thiz->all_nodes_num++] = node; 321 | } 322 | 323 | /****************************************************************************** 324 | * FUNCTION: ac_automata_union_matchstrs 325 | * Collect accepted patterns of the node. the accepted patterns consist of the 326 | * node's own accepted pattern plus accepted patterns of its failure node. 327 | ******************************************************************************/ 328 | static void ac_automata_union_matchstrs (AC_NODE_t * node) 329 | { 330 | unsigned int i; 331 | AC_NODE_t * m = node; 332 | 333 | while ((m = m->failure_node)) 334 | { 335 | for (i=0; i < m->matched_patterns_num; i++) 336 | node_register_matchstr(node, &(m->matched_patterns[i])); 337 | 338 | if (m->final) 339 | node->final = 1; 340 | } 341 | // TODO : sort matched_patterns? is that necessary? I don't think so. 342 | } 343 | 344 | /****************************************************************************** 345 | * FUNCTION: ac_automata_set_failure 346 | * find failure node for the given node. 347 | ******************************************************************************/ 348 | static void ac_automata_set_failure 349 | (AC_AUTOMATA_t * thiz, AC_NODE_t * node, AC_ALPHABET_t * alphas) 350 | { 351 | unsigned int i, j; 352 | AC_NODE_t * m; 353 | 354 | for (i=1; i < node->depth; i++) 355 | { 356 | m = thiz->root; 357 | for (j=i; j < node->depth && m; j++) 358 | m = node_find_next (m, alphas[j]); 359 | if (m) 360 | { 361 | node->failure_node = m; 362 | break; 363 | } 364 | } 365 | if (!node->failure_node) 366 | node->failure_node = thiz->root; 367 | } 368 | 369 | /****************************************************************************** 370 | * FUNCTION: ac_automata_traverse_setfailure 371 | * Traverse all automata nodes using DFS (Depth First Search), meanwhile it set 372 | * the failure node for every node it passes through. this function must be 373 | * called after adding last pattern to automata. i.e. after calling this you 374 | * can not add further pattern to automata. 375 | ******************************************************************************/ 376 | static void ac_automata_traverse_setfailure 377 | (AC_AUTOMATA_t * thiz, AC_NODE_t * node, AC_ALPHABET_t * alphas) 378 | { 379 | unsigned int i; 380 | AC_NODE_t * next; 381 | 382 | for (i=0; i < node->outgoing_degree; i++) 383 | { 384 | alphas[node->depth] = node->outgoing[i].alpha; 385 | next = node->outgoing[i].next; 386 | 387 | /* At every node look for its failure node */ 388 | ac_automata_set_failure (thiz, next, alphas); 389 | 390 | /* Recursively call itself to traverse all nodes */ 391 | ac_automata_traverse_setfailure (thiz, next, alphas); 392 | } 393 | } 394 | -------------------------------------------------------------------------------- /nDPI-patch/src/lib/third_party/src/node.c: -------------------------------------------------------------------------------- 1 | /* 2 | * node.c: implementation of automata node 3 | * This file is part of multifast. 4 | * 5 | * Rev.1.1 6 | * 7 | Copyright 2010-2012 Kamiar Kanani 8 | 9 | multifast is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | multifast is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with multifast. If not, see . 21 | 22 | */ 23 | 24 | #ifndef __KERNEL__ 25 | #include 26 | #include 27 | #include 28 | #endif 29 | 30 | #include "ndpi_api.h" 31 | #include "../include/node.h" 32 | #include "sort.h" 33 | 34 | /* reallocation step for AC_NODE_t.matched_patterns */ 35 | #define REALLOC_CHUNK_MATCHSTR 8 36 | 37 | /* reallocation step for AC_NODE_t.outgoing array */ 38 | #define REALLOC_CHUNK_OUTGOING 8 39 | /* TODO: For different depth of node, number of outgoing edges differs 40 | considerably, It is efficient to use different chunk size for 41 | different depths */ 42 | 43 | /* Private function prototype */ 44 | void node_init (AC_NODE_t * thiz); 45 | int node_edge_compare (const void * l, const void * r); 46 | int node_has_matchstr (AC_NODE_t * thiz, AC_PATTERN_t * newstr); 47 | 48 | 49 | /****************************************************************************** 50 | * FUNCTION: node_create 51 | * Create the node 52 | ******************************************************************************/ 53 | AC_NODE_t * node_create(void) 54 | { 55 | AC_NODE_t * thiz = (AC_NODE_t *) ndpi_malloc (sizeof(AC_NODE_t)); 56 | node_init(thiz); 57 | node_assign_id(thiz); 58 | return thiz; 59 | } 60 | 61 | /****************************************************************************** 62 | * FUNCTION: node_init 63 | * Initialize node 64 | ******************************************************************************/ 65 | void node_init(AC_NODE_t * thiz) 66 | { 67 | memset(thiz, 0, sizeof(AC_NODE_t)); 68 | 69 | thiz->outgoing_max = REALLOC_CHUNK_OUTGOING; 70 | thiz->outgoing = (struct edge *) ndpi_malloc 71 | (thiz->outgoing_max*sizeof(struct edge)); 72 | 73 | thiz->matched_patterns_max = REALLOC_CHUNK_MATCHSTR; 74 | thiz->matched_patterns = (AC_PATTERN_t *) ndpi_malloc 75 | (thiz->matched_patterns_max*sizeof(AC_PATTERN_t)); 76 | } 77 | 78 | /****************************************************************************** 79 | * FUNCTION: node_release 80 | * Release node 81 | ******************************************************************************/ 82 | void node_release(AC_NODE_t * thiz) 83 | { 84 | ndpi_free(thiz->matched_patterns); 85 | ndpi_free(thiz->outgoing); 86 | ndpi_free(thiz); 87 | } 88 | 89 | /****************************************************************************** 90 | * FUNCTION: node_find_next 91 | * Find out the next node for a given Alpha to move. this function is used in 92 | * the pre-processing stage in which edge array is not sorted. so it uses 93 | * linear search. 94 | ******************************************************************************/ 95 | AC_NODE_t * node_find_next(AC_NODE_t * thiz, AC_ALPHABET_t alpha) 96 | { 97 | int i; 98 | 99 | for (i=0; i < thiz->outgoing_degree; i++) 100 | { 101 | if(thiz->outgoing[i].alpha == alpha) 102 | return (thiz->outgoing[i].next); 103 | } 104 | return NULL; 105 | } 106 | 107 | /****************************************************************************** 108 | * FUNCTION: node_findbs_next 109 | * Find out the next node for a given Alpha. this function is used after the 110 | * pre-processing stage in which we sort edges. so it uses Binary Search. 111 | ******************************************************************************/ 112 | AC_NODE_t * node_findbs_next (AC_NODE_t * thiz, AC_ALPHABET_t alpha) 113 | { 114 | int min, max, mid; 115 | AC_ALPHABET_t amid; 116 | 117 | min = 0; 118 | max = thiz->outgoing_degree - 1; 119 | 120 | while (min <= max) 121 | { 122 | mid = (min+max) >> 1; 123 | amid = thiz->outgoing[mid].alpha; 124 | if (alpha > amid) 125 | min = mid + 1; 126 | else if (alpha < amid) 127 | max = mid - 1; 128 | else 129 | return (thiz->outgoing[mid].next); 130 | } 131 | return NULL; 132 | } 133 | 134 | /****************************************************************************** 135 | * FUNCTION: node_has_matchstr 136 | * Determine if a final node contains a pattern in its accepted pattern list 137 | * or not. return values: 1 = it has, 0 = it hasn't 138 | ******************************************************************************/ 139 | int node_has_matchstr (AC_NODE_t * thiz, AC_PATTERN_t * newstr) 140 | { 141 | int i, j; 142 | AC_PATTERN_t * str; 143 | 144 | for (i=0; i < thiz->matched_patterns_num; i++) 145 | { 146 | str = &thiz->matched_patterns[i]; 147 | 148 | if (str->length != newstr->length) 149 | continue; 150 | 151 | for (j=0; j<(int)str->length; j++) 152 | if(str->astring[j] != newstr->astring[j]) 153 | continue; 154 | 155 | if (j == str->length) 156 | return 1; 157 | } 158 | return 0; 159 | } 160 | 161 | /****************************************************************************** 162 | * FUNCTION: node_create_next 163 | * Create the next node for the given alpha. 164 | ******************************************************************************/ 165 | AC_NODE_t * node_create_next (AC_NODE_t * thiz, AC_ALPHABET_t alpha) 166 | { 167 | AC_NODE_t * next; 168 | next = node_find_next (thiz, alpha); 169 | if (next) 170 | /* The edge already exists */ 171 | return NULL; 172 | /* Otherwise register new edge */ 173 | next = node_create (); 174 | node_register_outgoing(thiz, next, alpha); 175 | 176 | return next; 177 | } 178 | 179 | /****************************************************************************** 180 | * FUNCTION: node_register_matchstr 181 | * Adds the pattern to the list of accepted pattern. 182 | ******************************************************************************/ 183 | void node_register_matchstr (AC_NODE_t * thiz, AC_PATTERN_t * str) 184 | { 185 | /* Check if the new pattern already exists in the node list */ 186 | if (node_has_matchstr(thiz, str)) 187 | return; 188 | 189 | /* Manage memory */ 190 | if (thiz->matched_patterns_num >= thiz->matched_patterns_max) 191 | { 192 | thiz->matched_patterns = (AC_PATTERN_t *) ndpi_realloc 193 | (thiz->matched_patterns, thiz->matched_patterns_max*sizeof(AC_PATTERN_t), 194 | (REALLOC_CHUNK_MATCHSTR+thiz->matched_patterns_max)*sizeof(AC_PATTERN_t)); 195 | 196 | thiz->matched_patterns_max += REALLOC_CHUNK_MATCHSTR; 197 | } 198 | 199 | thiz->matched_patterns[thiz->matched_patterns_num].astring = str->astring; 200 | thiz->matched_patterns[thiz->matched_patterns_num].length = str->length; 201 | thiz->matched_patterns[thiz->matched_patterns_num].rep = str->rep; 202 | thiz->matched_patterns_num++; 203 | } 204 | 205 | /****************************************************************************** 206 | * FUNCTION: node_register_outgoing 207 | * Establish an edge between two nodes 208 | ******************************************************************************/ 209 | void node_register_outgoing 210 | (AC_NODE_t * thiz, AC_NODE_t * next, AC_ALPHABET_t alpha) 211 | { 212 | if(thiz->outgoing_degree >= thiz->outgoing_max) 213 | { 214 | thiz->outgoing = (struct edge *) ndpi_realloc 215 | (thiz->outgoing, thiz->outgoing_max*sizeof(struct edge), 216 | (REALLOC_CHUNK_OUTGOING+thiz->outgoing_max)*sizeof(struct edge)); 217 | thiz->outgoing_max += REALLOC_CHUNK_OUTGOING; 218 | } 219 | 220 | thiz->outgoing[thiz->outgoing_degree].alpha = alpha; 221 | thiz->outgoing[thiz->outgoing_degree++].next = next; 222 | } 223 | 224 | /****************************************************************************** 225 | * FUNCTION: node_assign_id 226 | * assign a unique ID to the node (used for debugging purpose). 227 | ******************************************************************************/ 228 | void node_assign_id (AC_NODE_t * thiz) 229 | { 230 | static int unique_id = 1; 231 | thiz->id = unique_id ++; 232 | } 233 | 234 | /****************************************************************************** 235 | * FUNCTION: node_edge_compare 236 | * Comparison function for qsort. see man qsort. 237 | ******************************************************************************/ 238 | int node_edge_compare (const void * l, const void * r) 239 | { 240 | /* According to man page: 241 | * The comparison function must return an integer less than, equal to, or 242 | * greater than zero if the first argument is considered to be 243 | * respectively less than, equal to, or greater than the second. if two 244 | * members compare as equal, their order in the sorted array is undefined. 245 | * 246 | * NOTE: Because edge alphabets are unique in every node we ignore 247 | * equivalence case. 248 | **/ 249 | if ( ((struct edge *)l)->alpha >= ((struct edge *)r)->alpha ) 250 | return 1; 251 | else 252 | return -1; 253 | } 254 | 255 | /****************************************************************************** 256 | * FUNCTION: node_sort_edges 257 | * sorts edges alphabets. 258 | ******************************************************************************/ 259 | void node_sort_edges (AC_NODE_t * thiz) 260 | { 261 | sort ((void *)thiz->outgoing, thiz->outgoing_degree, sizeof(struct edge), node_edge_compare, NULL); 262 | } 263 | -------------------------------------------------------------------------------- /nDPI-patch/src/lib/third_party/src/sort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A fast, small, non-recursive O(nlog n) sort for the Linux kernel 3 | * 4 | * Jan 23 2005 Matt Mackall 5 | * 6 | * Rev.1.1 7 | */ 8 | 9 | #ifdef __KERNEL__ 10 | #include 11 | #else 12 | #ifdef WIN32 13 | #include 14 | typedef uint32_t u_int32_t; 15 | #endif 16 | 17 | #include 18 | #include 19 | #include 20 | #endif 21 | 22 | /* This is a function ported from the Linux kernel lib/sort.c */ 23 | 24 | static void u_int32_t_swap(void *a, void *b, int size) 25 | { 26 | u_int32_t t = *(u_int32_t *)a; 27 | *(u_int32_t *)a = *(u_int32_t *)b; 28 | *(u_int32_t *)b = t; 29 | } 30 | 31 | static void generic_swap(void *_a, void *_b, int size) 32 | { 33 | char t; 34 | char *a = (char*)_a; 35 | char *b = (char*)_b; 36 | 37 | do { 38 | t = *a; 39 | *a++ = *b; 40 | *b++ = t; 41 | } while (--size > 0); 42 | } 43 | 44 | /** 45 | * sort - sort an array of elements 46 | * @base: pointer to data to sort 47 | * @num: number of elements 48 | * @size: size of each element 49 | * @cmp_func: pointer to comparison function 50 | * @swap_func: pointer to swap function or NULL 51 | * 52 | * This function does a heapsort on the given array. You may provide a 53 | * swap_func function optimized to your element type. 54 | * 55 | * Sorting time is O(n log n) both on average and worst-case. While 56 | * qsort is about 20% faster on average, it suffers from exploitable 57 | * O(n*n) worst-case behavior and extra memory requirements that make 58 | * it less suitable for kernel use. 59 | */ 60 | 61 | void sort(void *_base, size_t num, size_t size, 62 | int (*cmp_func)(const void *, const void *), 63 | void (*swap_func)(void *, void *, int size)) 64 | { 65 | /* pre-scale counters for performance */ 66 | int i = (num/2 - 1) * size, n = num * size, c, r; 67 | char *base = (char*)_base; 68 | 69 | if (!swap_func) 70 | swap_func = (size == 4 ? u_int32_t_swap : generic_swap); 71 | 72 | /* heapify */ 73 | for ( ; i >= 0; i -= size) { 74 | for (r = i; r * 2 + size < n; r = c) { 75 | c = r * 2 + size; 76 | if (c < n - size && 77 | cmp_func(base + c, base + c + size) < 0) 78 | c += size; 79 | if (cmp_func(base + r, base + c) >= 0) 80 | break; 81 | swap_func(base + r, base + c, size); 82 | } 83 | } 84 | 85 | /* sort */ 86 | for (i = n - size; i > 0; i -= size) { 87 | swap_func(base, base + i, size); 88 | for (r = 0; r * 2 + size < i; r = c) { 89 | c = r * 2 + size; 90 | if (c < i - size && 91 | cmp_func(base + c, base + c + size) < 0) 92 | c += size; 93 | if (cmp_func(base + r, base + c) >= 0) 94 | break; 95 | swap_func(base + r, base + c, size); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /nDPI.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/betolj/ndpi-netfilter/4875069df027199698ba0b7c53541ae2a4e3ba00/nDPI.tar.gz -------------------------------------------------------------------------------- /ndpi.install: -------------------------------------------------------------------------------- 1 | # 2 | # Steps to build ndpi-netfilter on Ubuntu/Debian 3 | # 4 | # - Now, WORKS with nf_conntrack_netlink too 5 | # 6 | 7 | 1. Install kernel sources 8 | apt-get install linux-source 9 | 10 | 11 | # With Build dir /usr/src/ndpi-netfilter 12 | 2. Install nDPI and ndpi-netfilter 13 | apt-get install libtool 14 | apt-get install autoconf 15 | apt-get install pkg-config 16 | apt-get install subversion 17 | apt-get install libpcap-dev 18 | apt-get install iptables-dev 19 | cd /usr/src/ndpi-netfilter 20 | tar xvfz nDPI.tar.gz 21 | cd nDPI 22 | ./autogen.sh 23 | #./configure –with-pic 24 | make 25 | make install 26 | 27 | cd .. 28 | NDPI_PATH=/usr/src/ndpi-netfilter/nDPI make 29 | make modules_install 30 | cp /usr/src/ndpi-netfilter/ipt/libxt_ndpi.so /lib/xtables/ 31 | 32 | 33 | 3. Firewall rules example 34 | - You can use a full detection engine with "--dpi_check" option (any flows): 35 | # dpi_check without a firewall target 36 | iptables -t mangle -A PREROUTING -m ndpi --dpi_check 37 | iptables -t mangle -A POSTROUTING -m ndpi --dpi_check 38 | 39 | iptables -A INPUT -m ndpi --youtube -j DROP 40 | iptables -A OUTPUT -m ndpi --facebook -j DROP 41 | 42 | 43 | - Or make a manual flow detection 44 | iptables -A INPUT -m ndpi --ftp -j DROP 45 | iptables -A OUTPUT -m ndpi --ftp -j DROP 46 | 47 | -------------------------------------------------------------------------------- /old/ipt/Makefile: -------------------------------------------------------------------------------- 1 | NDPI_PATH2 := ${NDPI_PATH}/src 2 | NDPI_SRC := ndpi_cpy 3 | NDPI_PRO := ${NDPI_SRC}/lib/protocols 4 | 5 | CFLAGS = -fPIC -I${NDPI_SRC}/include -I${NDPI_SRC}/lib -I../src -DOPENDPI_NETFILTER_MODULE -O2 -Wall -DNDPI_IPTABLES_EXT 6 | 7 | all: 8 | if test -d ${NDPI_SRC}; then \ 9 | cp ${NDPI_PATH2}/* ${NDPI_SRC} -R; \ 10 | else \ 11 | mkdir ${NDPI_SRC}; \ 12 | cp ${NDPI_PATH2}/* ${NDPI_SRC} -R; \ 13 | fi 14 | make libxt_ndpi.so 15 | rm -r ${NDPI_SRC} 16 | lib%.so: lib%.o 17 | $(CC) -shared -o $@ $^; 18 | lib%.o: lib%.c 19 | $(CC) ${CFLAGS} -D_INIT=lib$*_init -c -o $@ $<; 20 | clean: 21 | rm -rf libxt_ndpi.so ${NDPI_SRC} 22 | -------------------------------------------------------------------------------- /old/ipt/libxt_ndpi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libxt_ndpi.c 3 | * Copyright (C) 2010-2012 G. Elian Gidoni 4 | * 2012 Ed Wildgoose 5 | * 2014 Humberto Jucá 6 | * 7 | * This file is part of nDPI, an open source deep packet inspection 8 | * library based on the PACE technology by ipoque GmbH 9 | * 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License 12 | * as published by the Free Software Foundation; version 2 of the License. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | #include "xt_ndpi.h" 33 | 34 | static char *prot_long_str[] = { NDPI_PROTOCOL_LONG_STRING }; 35 | static char *prot_short_str[] = { NDPI_PROTOCOL_SHORT_STRING }; 36 | 37 | 38 | static void 39 | ndpi_mt4_save(const void *entry, const struct xt_entry_match *match) 40 | { 41 | const struct xt_ndpi_mtinfo *info = (const void *)match->data; 42 | int i; 43 | 44 | for (i = 1; i <= NDPI_LAST_NFPROTO; i++){ 45 | if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(info->flags, i) != 0){ 46 | printf("--%s ", prot_short_str[i]); 47 | } 48 | } 49 | } 50 | 51 | 52 | static void 53 | ndpi_mt4_print(const void *entry, const struct xt_entry_match *match, 54 | int numeric) 55 | { 56 | const struct xt_ndpi_mtinfo *info = (const void *)match->data; 57 | int i; 58 | 59 | for (i = 1; i <= NDPI_LAST_NFPROTO; i++){ 60 | if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(info->flags, i) != 0){ 61 | printf("protocol %s ", prot_long_str[i]); 62 | } 63 | } 64 | } 65 | 66 | 67 | static int 68 | ndpi_mt4_parse(int c, char **argv, int invert, unsigned int *flags, 69 | const void *entry, struct xt_entry_match **match) 70 | { 71 | struct xt_ndpi_mtinfo *info = (void *)(*match)->data; 72 | 73 | if (c >= 0 && c <= NDPI_LAST_IMPLEMENTED_PROTOCOL) { 74 | NDPI_ADD_PROTOCOL_TO_BITMASK(info->flags, c); 75 | *flags = 1; 76 | return true; 77 | } 78 | *flags = 0; 79 | return false; 80 | } 81 | 82 | #ifndef xtables_error 83 | #define xtables_error exit_error 84 | #endif 85 | 86 | static void 87 | ndpi_mt_check (unsigned int flags) 88 | { 89 | if (flags == 0){ 90 | xtables_error(PARAMETER_PROBLEM, "xt_ndpi: You need to " 91 | "specify at least one protocol"); 92 | } 93 | } 94 | 95 | 96 | static void 97 | ndpi_mt_help(void) 98 | { 99 | int i; 100 | 101 | printf("ndpi match options:\n"); 102 | for (i = 1; i <= NDPI_LAST_NFPROTO; i++){ 103 | printf("--%s Match for %s protocol packets.\n", 104 | prot_short_str[i], prot_long_str[i]); 105 | } 106 | } 107 | 108 | 109 | static void 110 | ndpi_mt_init (struct xt_entry_match *match) 111 | { 112 | struct xt_ndpi_mtinfo *info = (void *)match->data; 113 | /* inet_pton(PF_INET, "192.0.2.137", &info->dst.in); */ 114 | } 115 | 116 | 117 | static struct option ndpi_mt_opts[NDPI_LAST_NFPROTO+1]; 118 | 119 | static struct xtables_match 120 | ndpi_mt4_reg = { 121 | .version = XTABLES_VERSION, 122 | .name = "ndpi", 123 | .revision = 0, 124 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) 125 | .family = AF_INET, 126 | #else 127 | .family = NFPROTO_IPV4, 128 | #endif 129 | .size = XT_ALIGN(sizeof(struct xt_ndpi_mtinfo)), 130 | .userspacesize = XT_ALIGN(sizeof(struct xt_ndpi_mtinfo)), 131 | .help = ndpi_mt_help, 132 | .init = ndpi_mt_init, 133 | .parse = ndpi_mt4_parse, 134 | .final_check = ndpi_mt_check, 135 | .print = ndpi_mt4_print, 136 | .save = ndpi_mt4_save, 137 | .extra_opts = ndpi_mt_opts, 138 | }; 139 | 140 | void _init(void) 141 | { 142 | int i; 143 | 144 | for (i = 0; i < NDPI_LAST_NFPROTO; i++){ 145 | ndpi_mt_opts[i].name = prot_short_str[i+1]; 146 | ndpi_mt_opts[i].has_arg = false; 147 | ndpi_mt_opts[i].val = i+1; 148 | } 149 | ndpi_mt_opts[i].name = NULL; 150 | ndpi_mt_opts[i].flag = NULL; 151 | ndpi_mt_opts[i].has_arg = 0; 152 | ndpi_mt_opts[i].val = 0; 153 | 154 | xtables_register_match(&ndpi_mt4_reg); 155 | } 156 | -------------------------------------------------------------------------------- /old/kernel-patch/hack-conntrack-events.patch: -------------------------------------------------------------------------------- 1 | diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h 2 | --- a/include/net/netfilter/nf_conntrack_ecache.h 3 | +++ b/include/net/netfilter/nf_conntrack_ecache.h 4 | @@ -79,7 +79,8 @@ nf_conntrack_event_cache(enum ip_conntra 5 | struct net *net = nf_ct_net(ct); 6 | struct nf_conntrack_ecache *e; 7 | 8 | - if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) 9 | + if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb) 10 | + && !rcu_access_pointer(net->ct.nf_conntrack_event_cb_2)) 11 | return; 12 | 13 | e = nf_ct_ecache_find(ct); 14 | @@ -98,11 +99,14 @@ nf_conntrack_eventmask_report(unsigned i 15 | int ret = 0; 16 | struct net *net = nf_ct_net(ct); 17 | struct nf_ct_event_notifier *notify; 18 | + struct nf_ct_event_notifier *notify_2; 19 | struct nf_conntrack_ecache *e; 20 | 21 | rcu_read_lock(); 22 | + /* Incredibly nasty duplication in order to hack second event */ 23 | notify = rcu_dereference(net->ct.nf_conntrack_event_cb); 24 | - if (notify == NULL) 25 | + notify_2 = rcu_dereference(net->ct.nf_conntrack_event_cb_2); 26 | + if ((notify == NULL) && (notify_2 == NULL)) 27 | goto out_unlock; 28 | 29 | e = nf_ct_ecache_find(ct); 30 | @@ -121,7 +125,8 @@ nf_conntrack_eventmask_report(unsigned i 31 | if (!((eventmask | missed) & e->ctmask)) 32 | goto out_unlock; 33 | 34 | - ret = notify->fcn(eventmask | missed, &item); 35 | + ret = min( notify ? notify->fcn(eventmask | missed, &item) : 0, 36 | + notify_2 ? notify_2->fcn(eventmask | missed, &item) : 0 ); 37 | if (unlikely(ret < 0 || missed)) { 38 | spin_lock_bh(&ct->lock); 39 | if (ret < 0) { 40 | diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h 41 | --- a/include/net/netns/conntrack.h 42 | +++ b/include/net/netns/conntrack.h 43 | @@ -73,6 +73,7 @@ struct netns_ct { 44 | struct hlist_nulls_head dying; 45 | struct ip_conntrack_stat __percpu *stat; 46 | struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb; 47 | + struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb_2; 48 | struct nf_exp_event_notifier __rcu *nf_expect_event_cb; 49 | int sysctl_events; 50 | unsigned int sysctl_events_retry_timeout; 51 | diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c 52 | --- a/net/netfilter/nf_conntrack_ecache.c 53 | +++ b/net/netfilter/nf_conntrack_ecache.c 54 | @@ -33,14 +33,17 @@ void nf_ct_deliver_cached_events(struct 55 | { 56 | struct net *net = nf_ct_net(ct); 57 | unsigned long events, missed; 58 | + /* Incredibly nasty duplication in order to hack second event */ 59 | struct nf_ct_event_notifier *notify; 60 | + struct nf_ct_event_notifier *notify_2; 61 | struct nf_conntrack_ecache *e; 62 | struct nf_ct_event item; 63 | int ret; 64 | 65 | rcu_read_lock(); 66 | notify = rcu_dereference(net->ct.nf_conntrack_event_cb); 67 | - if (notify == NULL) 68 | + notify_2 = rcu_dereference(net->ct.nf_conntrack_event_cb_2); 69 | + if ( (notify == NULL) && (notify_2 == NULL) ) 70 | goto out_unlock; 71 | 72 | e = nf_ct_ecache_find(ct); 73 | @@ -64,7 +67,8 @@ void nf_ct_deliver_cached_events(struct 74 | item.pid = 0; 75 | item.report = 0; 76 | 77 | - ret = notify->fcn(events | missed, &item); 78 | + ret = min( notify ? notify->fcn(events | missed, &item) : 0, 79 | + notify_2 ? notify_2->fcn(events | missed, &item) : 0); 80 | 81 | if (likely(ret >= 0 && !missed)) 82 | goto out_unlock; 83 | @@ -86,15 +90,21 @@ int nf_conntrack_register_notifier(struc 84 | { 85 | int ret; 86 | struct nf_ct_event_notifier *notify; 87 | + struct nf_ct_event_notifier *notify_2; 88 | 89 | mutex_lock(&nf_ct_ecache_mutex); 90 | notify = rcu_dereference_protected(net->ct.nf_conntrack_event_cb, 91 | lockdep_is_held(&nf_ct_ecache_mutex)); 92 | - if (notify != NULL) { 93 | + notify_2 = rcu_dereference_protected(net->ct.nf_conntrack_event_cb_2, 94 | + lockdep_is_held(&nf_ct_ecache_mutex)); 95 | + if ( (notify != NULL) && (notify_2 != NULL) ) { 96 | ret = -EBUSY; 97 | goto out_unlock; 98 | } 99 | - rcu_assign_pointer(net->ct.nf_conntrack_event_cb, new); 100 | + if (notify == NULL) 101 | + rcu_assign_pointer(net->ct.nf_conntrack_event_cb, new); 102 | + else 103 | + rcu_assign_pointer(net->ct.nf_conntrack_event_cb_2, new); 104 | ret = 0; 105 | 106 | out_unlock: 107 | @@ -107,12 +117,18 @@ void nf_conntrack_unregister_notifier(st 108 | struct nf_ct_event_notifier *new) 109 | { 110 | struct nf_ct_event_notifier *notify; 111 | + struct nf_ct_event_notifier *notify_2; 112 | 113 | mutex_lock(&nf_ct_ecache_mutex); 114 | notify = rcu_dereference_protected(net->ct.nf_conntrack_event_cb, 115 | lockdep_is_held(&nf_ct_ecache_mutex)); 116 | - BUG_ON(notify != new); 117 | - RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL); 118 | + notify_2 = rcu_dereference_protected(net->ct.nf_conntrack_event_cb_2, 119 | + lockdep_is_held(&nf_ct_ecache_mutex)); 120 | + BUG_ON((notify != new) || (notify_2 != new)); 121 | + if (notify == new) 122 | + RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL); 123 | + else 124 | + RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb_2, NULL); 125 | mutex_unlock(&nf_ct_ecache_mutex); 126 | } 127 | EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); 128 | -------------------------------------------------------------------------------- /old/kernel-patch/hack-conntrack-events.patch.old: -------------------------------------------------------------------------------- 1 | commit 0bff241af47f293d27b908ab82a4e2ec5d62385f 2 | Author: Ed W 3 | Date: Wed Oct 24 23:11:44 2012 +0100 4 | 5 | incredibly nasty hack for nDPI + conntrack/netlink 6 | 7 | In recent kernels, only one listener can register for 8 | notification of conntrack events. This is done for 9 | performance reasons and no other in kernel module cares. 10 | This incredibly nasty hack allows a second listener to 11 | register for conntrack notifications. 12 | 13 | Use at your peril. No warranty included... 14 | 15 | diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h 16 | index a88fb69..d39af41 100644 17 | --- a/include/net/netfilter/nf_conntrack_ecache.h 18 | +++ b/include/net/netfilter/nf_conntrack_ecache.h 19 | @@ -78,7 +78,8 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) 20 | struct net *net = nf_ct_net(ct); 21 | struct nf_conntrack_ecache *e; 22 | 23 | - if (net->ct.nf_conntrack_event_cb == NULL) 24 | + if ( (net->ct.nf_conntrack_event_cb == NULL) && 25 | + (net->ct.nf_conntrack_event_cb_2 == NULL) ) 26 | return; 27 | 28 | e = nf_ct_ecache_find(ct); 29 | @@ -97,11 +98,14 @@ nf_conntrack_eventmask_report(unsigned int eventmask, 30 | int ret = 0; 31 | struct net *net = nf_ct_net(ct); 32 | struct nf_ct_event_notifier *notify; 33 | + struct nf_ct_event_notifier *notify_2; 34 | struct nf_conntrack_ecache *e; 35 | 36 | rcu_read_lock(); 37 | + /* Incredibly nasty duplication in order to hack second event */ 38 | notify = rcu_dereference(net->ct.nf_conntrack_event_cb); 39 | - if (notify == NULL) 40 | + notify_2 = rcu_dereference(net->ct.nf_conntrack_event_cb_2); 41 | + if ((notify == NULL) && (notify_2 == NULL)) 42 | goto out_unlock; 43 | 44 | e = nf_ct_ecache_find(ct); 45 | @@ -120,7 +124,8 @@ nf_conntrack_eventmask_report(unsigned int eventmask, 46 | if (!((eventmask | missed) & e->ctmask)) 47 | goto out_unlock; 48 | 49 | - ret = notify->fcn(eventmask | missed, &item); 50 | + ret = min( notify ? notify->fcn(eventmask | missed, &item) : 0, 51 | + notify_2 ? notify_2->fcn(eventmask | missed, &item) : 0 ); 52 | if (unlikely(ret < 0 || missed)) { 53 | spin_lock_bh(&ct->lock); 54 | if (ret < 0) { 55 | diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h 56 | index 7a911ec..24a78d3 100644 57 | --- a/include/net/netns/conntrack.h 58 | +++ b/include/net/netns/conntrack.h 59 | @@ -19,6 +19,7 @@ struct netns_ct { 60 | struct hlist_nulls_head dying; 61 | struct ip_conntrack_stat __percpu *stat; 62 | struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb; 63 | + struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb_2; 64 | struct nf_exp_event_notifier __rcu *nf_expect_event_cb; 65 | int sysctl_events; 66 | unsigned int sysctl_events_retry_timeout; 67 | diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c 68 | index 14af632..9535ab7 100644 69 | --- a/net/netfilter/nf_conntrack_ecache.c 70 | +++ b/net/netfilter/nf_conntrack_ecache.c 71 | @@ -33,12 +33,15 @@ void nf_ct_deliver_cached_events(struct nf_conn *ct) 72 | { 73 | struct net *net = nf_ct_net(ct); 74 | unsigned long events; 75 | + /* Incredibly nasty duplication in order to hack second event */ 76 | struct nf_ct_event_notifier *notify; 77 | + struct nf_ct_event_notifier *notify_2; 78 | struct nf_conntrack_ecache *e; 79 | 80 | rcu_read_lock(); 81 | notify = rcu_dereference(net->ct.nf_conntrack_event_cb); 82 | - if (notify == NULL) 83 | + notify_2 = rcu_dereference(net->ct.nf_conntrack_event_cb_2); 84 | + if ( (notify == NULL) && (notify_2 == NULL) ) 85 | goto out_unlock; 86 | 87 | e = nf_ct_ecache_find(ct); 88 | @@ -62,7 +65,8 @@ void nf_ct_deliver_cached_events(struct nf_conn *ct) 89 | if (!((events | missed) & e->ctmask)) 90 | goto out_unlock; 91 | 92 | - ret = notify->fcn(events | missed, &item); 93 | + ret = min( notify ? notify->fcn(events | missed, &item) : 0, 94 | + notify_2 ? notify_2->fcn(events | missed, &item) : 0); 95 | if (unlikely(ret < 0 || missed)) { 96 | spin_lock_bh(&ct->lock); 97 | if (ret < 0) 98 | @@ -83,15 +87,21 @@ int nf_conntrack_register_notifier(struct net *net, 99 | { 100 | int ret = 0; 101 | struct nf_ct_event_notifier *notify; 102 | + struct nf_ct_event_notifier *notify_2; 103 | 104 | mutex_lock(&nf_ct_ecache_mutex); 105 | notify = rcu_dereference_protected(net->ct.nf_conntrack_event_cb, 106 | lockdep_is_held(&nf_ct_ecache_mutex)); 107 | - if (notify != NULL) { 108 | + notify_2 = rcu_dereference_protected(net->ct.nf_conntrack_event_cb_2, 109 | + lockdep_is_held(&nf_ct_ecache_mutex)); 110 | + if ( (notify != NULL) && (notify_2 != NULL) ) { 111 | ret = -EBUSY; 112 | goto out_unlock; 113 | } 114 | - rcu_assign_pointer(net->ct.nf_conntrack_event_cb, new); 115 | + if (notify == NULL) 116 | + rcu_assign_pointer(net->ct.nf_conntrack_event_cb, new); 117 | + else 118 | + rcu_assign_pointer(net->ct.nf_conntrack_event_cb_2, new); 119 | mutex_unlock(&nf_ct_ecache_mutex); 120 | return ret; 121 | 122 | @@ -105,12 +115,18 @@ void nf_conntrack_unregister_notifier(struct net *net, 123 | struct nf_ct_event_notifier *new) 124 | { 125 | struct nf_ct_event_notifier *notify; 126 | + struct nf_ct_event_notifier *notify_2; 127 | 128 | mutex_lock(&nf_ct_ecache_mutex); 129 | notify = rcu_dereference_protected(net->ct.nf_conntrack_event_cb, 130 | lockdep_is_held(&nf_ct_ecache_mutex)); 131 | - BUG_ON(notify != new); 132 | - RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL); 133 | + notify_2 = rcu_dereference_protected(net->ct.nf_conntrack_event_cb_2, 134 | + lockdep_is_held(&nf_ct_ecache_mutex)); 135 | + BUG_ON((notify != new) || (notify_2 != new)); 136 | + if (notify == new) 137 | + RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL); 138 | + else 139 | + RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb_2, NULL); 140 | mutex_unlock(&nf_ct_ecache_mutex); 141 | } 142 | EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); 143 | -------------------------------------------------------------------------------- /old/nDPI.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/betolj/ndpi-netfilter/4875069df027199698ba0b7c53541ae2a4e3ba00/old/nDPI.tar.gz -------------------------------------------------------------------------------- /old/src/Makefile: -------------------------------------------------------------------------------- 1 | NDPI_PATH2 := ${NDPI_PATH}/src 2 | NDPI_SRC := ndpi_cpy 3 | NDPI_PRO := ${NDPI_SRC}/lib/protocols 4 | 5 | ccflags-y += -I${src}/${NDPI_SRC}/include -I${src}/${NDPI_SRC}/lib -DOPENDPI_NETFILTER_MODULE -DNDPI_IPTABLES_EXT 6 | 7 | MODULES_DIR := /lib/modules/$(shell uname -r) 8 | KERNEL_DIR ?= ${MODULES_DIR}/build 9 | 10 | obj-m := xt_ndpi.o 11 | xt_ndpi-y := main.o \ 12 | ${NDPI_SRC}/lib/ndpi_main.o \ 13 | ${NDPI_SRC}/lib/ahocorasick.o \ 14 | ${NDPI_SRC}/lib/node.o \ 15 | ${NDPI_SRC}/lib/sort.o \ 16 | ${NDPI_PRO}/afp.o \ 17 | ${NDPI_PRO}/aimini.o \ 18 | ${NDPI_PRO}/applejuice.o \ 19 | ${NDPI_PRO}/armagetron.o \ 20 | ${NDPI_PRO}/battlefield.o \ 21 | ${NDPI_PRO}/bgp.o \ 22 | ${NDPI_PRO}/bittorrent.o \ 23 | ${NDPI_PRO}/citrix.o \ 24 | ${NDPI_PRO}/ciscovpn.o \ 25 | ${NDPI_PRO}/corba.o \ 26 | ${NDPI_PRO}/crossfire.o \ 27 | ${NDPI_PRO}/dcerpc.o \ 28 | ${NDPI_PRO}/dhcp.o \ 29 | ${NDPI_PRO}/dhcpv6.o \ 30 | ${NDPI_PRO}/directconnect.o \ 31 | ${NDPI_PRO}/directdownloadlink.o \ 32 | ${NDPI_PRO}/dns.o \ 33 | ${NDPI_PRO}/dofus.o \ 34 | ${NDPI_PRO}/dropbox.o \ 35 | ${NDPI_PRO}/edonkey.o \ 36 | ${NDPI_PRO}/gtp.o \ 37 | ${NDPI_PRO}/lotus_notes.o \ 38 | ${NDPI_PRO}/fasttrack.o \ 39 | ${NDPI_PRO}/fiesta.o \ 40 | ${NDPI_PRO}/filetopia.o \ 41 | ${NDPI_PRO}/florensia.o \ 42 | ${NDPI_PRO}/ftp_control.o \ 43 | ${NDPI_PRO}/ftp_data.o \ 44 | ${NDPI_PRO}/gnutella.o \ 45 | ${NDPI_PRO}/guildwars.o \ 46 | ${NDPI_PRO}/halflife2_and_mods.o \ 47 | ${NDPI_PRO}/h323.o \ 48 | ${NDPI_PRO}/http.o \ 49 | ${NDPI_PRO}/http_activesync.o \ 50 | ${NDPI_PRO}/iax.o \ 51 | ${NDPI_PRO}/icecast.o \ 52 | ${NDPI_PRO}/imesh.o \ 53 | ${NDPI_PRO}/ipp.o \ 54 | ${NDPI_PRO}/irc.o \ 55 | ${NDPI_PRO}/jabber.o \ 56 | ${NDPI_PRO}/kerberos.o \ 57 | ${NDPI_PRO}/kontiki.o \ 58 | ${NDPI_PRO}/ldap.o \ 59 | ${NDPI_PRO}/mail_imap.o \ 60 | ${NDPI_PRO}/mail_pop.o \ 61 | ${NDPI_PRO}/mail_smtp.o \ 62 | ${NDPI_PRO}/maplestory.o \ 63 | ${NDPI_PRO}/mdns.o \ 64 | ${NDPI_PRO}/meebo.o \ 65 | ${NDPI_PRO}/mgcp.o \ 66 | ${NDPI_PRO}/mms.o \ 67 | ${NDPI_PRO}/msn.o \ 68 | ${NDPI_PRO}/mssql.o \ 69 | ${NDPI_PRO}/mysql.o \ 70 | ${NDPI_PRO}/whoisdas.o \ 71 | ${NDPI_PRO}/netbios.o \ 72 | ${NDPI_PRO}/netflow.o \ 73 | ${NDPI_PRO}/nfs.o \ 74 | ${NDPI_PRO}/noe.o \ 75 | ${NDPI_PRO}/non_tcp_udp.o \ 76 | ${NDPI_PRO}/ntp.o \ 77 | ${NDPI_PRO}/openft.o \ 78 | ${NDPI_PRO}/openvpn.o \ 79 | ${NDPI_PRO}/oracle.o \ 80 | ${NDPI_PRO}/oscar.o \ 81 | ${NDPI_PRO}/pando.o \ 82 | ${NDPI_PRO}/pcanywhere.o \ 83 | ${NDPI_PRO}/postgres.o \ 84 | ${NDPI_PRO}/pplive.o \ 85 | ${NDPI_PRO}/ppstream.o \ 86 | ${NDPI_PRO}/pptp.o \ 87 | ${NDPI_PRO}/twitter.o \ 88 | ${NDPI_PRO}/qq.o \ 89 | ${NDPI_PRO}/quake.o \ 90 | ${NDPI_PRO}/quic.o \ 91 | ${NDPI_PRO}/radius.o \ 92 | ${NDPI_PRO}/rdp.o \ 93 | ${NDPI_PRO}/rtp.o \ 94 | ${NDPI_PRO}/rtsp.o \ 95 | ${NDPI_PRO}/rtmp.o \ 96 | ${NDPI_PRO}/rtcp.o \ 97 | ${NDPI_PRO}/rsync.o \ 98 | ${NDPI_PRO}/sflow.o \ 99 | ${NDPI_PRO}/shoutcast.o \ 100 | ${NDPI_PRO}/sip.o \ 101 | ${NDPI_PRO}/zeromq.o \ 102 | ${NDPI_PRO}/skinny.o \ 103 | ${NDPI_PRO}/skype.o \ 104 | ${NDPI_PRO}/smb.o \ 105 | ${NDPI_PRO}/snmp.o \ 106 | ${NDPI_PRO}/socrates.o \ 107 | ${NDPI_PRO}/socks4.o \ 108 | ${NDPI_PRO}/socks5.o \ 109 | ${NDPI_PRO}/sopcast.o \ 110 | ${NDPI_PRO}/soulseek.o \ 111 | ${NDPI_PRO}/spotify.o \ 112 | ${NDPI_PRO}/ssdp.o \ 113 | ${NDPI_PRO}/ssh.o \ 114 | ${NDPI_PRO}/ssl.o \ 115 | ${NDPI_PRO}/stealthnet.o \ 116 | ${NDPI_PRO}/steam.o \ 117 | ${NDPI_PRO}/stun.o \ 118 | ${NDPI_PRO}/syslog.o \ 119 | ${NDPI_PRO}/tcp_udp.o \ 120 | ${NDPI_PRO}/tds.o \ 121 | ${NDPI_PRO}/teamviewer.o \ 122 | ${NDPI_PRO}/telegram.o \ 123 | ${NDPI_PRO}/telnet.o \ 124 | ${NDPI_PRO}/teamspeak.o \ 125 | ${NDPI_PRO}/tftp.o \ 126 | ${NDPI_PRO}/thunder.o \ 127 | ${NDPI_PRO}/tvants.o \ 128 | ${NDPI_PRO}/tvuplayer.o \ 129 | ${NDPI_PRO}/tor.o \ 130 | ${NDPI_PRO}/usenet.o \ 131 | ${NDPI_PRO}/veohtv.o \ 132 | ${NDPI_PRO}/viber.o \ 133 | ${NDPI_PRO}/vmware.o \ 134 | ${NDPI_PRO}/vnc.o \ 135 | ${NDPI_PRO}/warcraft3.o \ 136 | ${NDPI_PRO}/winmx.o \ 137 | ${NDPI_PRO}/world_of_kung_fu.o \ 138 | ${NDPI_PRO}/world_of_warcraft.o \ 139 | ${NDPI_PRO}/xbox.o \ 140 | ${NDPI_PRO}/xdmcp.o \ 141 | ${NDPI_PRO}/yahoo.o \ 142 | ${NDPI_PRO}/megaco.o \ 143 | ${NDPI_PRO}/redis_net.o \ 144 | ${NDPI_PRO}/vhua.o \ 145 | ${NDPI_PRO}/ayiya.o \ 146 | ${NDPI_PRO}/zattoo.o 147 | 148 | all: 149 | if test -d ${NDPI_SRC}; then \ 150 | cp ${NDPI_PATH2}/* ${NDPI_SRC} -R; \ 151 | else \ 152 | mkdir ${NDPI_SRC}; \ 153 | cp ${NDPI_PATH2}/* ${NDPI_SRC} -R; \ 154 | fi 155 | cp ${NDPI_SRC}/lib/third_party/src/*.c ${NDPI_SRC}/lib -R; 156 | cp ${NDPI_SRC}/lib/third_party/include/*.h ${NDPI_SRC}/lib -R; 157 | cp ${NDPI_SRC}/lib/third_party/include/*.h ${NDPI_SRC}/include -R; 158 | sed -i "s/^\s*void ndpi_free_flow/\/\/void ndpi_free_flow/" ${NDPI_SRC}/include/ndpi_api.h; 159 | make -C ${KERNEL_DIR} M=$$PWD; 160 | rm -r ${NDPI_SRC} 161 | modules: 162 | make -C ${KERNEL_DIR} M=$$PWD $@; 163 | modules_install: 164 | make -C ${KERNEL_DIR} M=$$PWD $@; 165 | depmod -a; 166 | clean: 167 | make -C ${KERNEL_DIR} M=$$PWD $@; 168 | rm -rf modules.order ${NDPI_SRC} 169 | -------------------------------------------------------------------------------- /old/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c 3 | * Copyright (C) 2010-2012 G. Elian Gidoni 4 | * 2012 Ed Wildgoose 5 | * 2014 Humberto Jucá 6 | * 7 | * This file is part of nDPI, an open source deep packet inspection 8 | * library based on the PACE technology by ipoque GmbH 9 | * 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License 12 | * as published by the Free Software Foundation; version 2 of the License. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include 39 | #include 40 | 41 | #include "ndpi_main.h" 42 | #include "xt_ndpi.h" 43 | 44 | 45 | /* flow tracking */ 46 | struct osdpi_flow_node { 47 | struct rb_node node; 48 | struct nf_conn * ct; 49 | u_int64_t ndpi_timeout; // detection timeout - detection 30s / connection 180s 50 | /* mark if done detecting flow proto - no more tries */ 51 | u8 detection_completed; 52 | /* result only, not used for flow identification */ 53 | u32 detected_protocol; 54 | /* last pointer assigned at run time */ 55 | struct ndpi_flow_struct *ndpi_flow; 56 | }; 57 | 58 | /* id tracking */ 59 | struct osdpi_id_node { 60 | struct rb_node node; 61 | struct kref refcnt; 62 | union nf_inet_addr ip; 63 | /* last pointer assigned at run time */ 64 | struct ndpi_id_struct *ndpi_id; 65 | }; 66 | 67 | 68 | u64 gc_interval_timeout = 0; 69 | static u32 size_id_struct = 0; 70 | static u32 size_flow_struct = 0; 71 | 72 | static struct rb_root osdpi_flow_root = RB_ROOT; 73 | static struct rb_root osdpi_id_root = RB_ROOT; 74 | 75 | static struct kmem_cache *osdpi_flow_cache __read_mostly; 76 | static struct kmem_cache *osdpi_id_cache __read_mostly; 77 | 78 | static NDPI_PROTOCOL_BITMASK protocols_bitmask; 79 | static atomic_t protocols_cnt[NDPI_LAST_IMPLEMENTED_PROTOCOL]; 80 | static u8 nfndpi_protocols_http[NDPI_LAST_IMPLEMENTED_PROTOCOL]; 81 | 82 | DEFINE_SPINLOCK(flow_lock); 83 | DEFINE_SPINLOCK(id_lock); 84 | DEFINE_SPINLOCK(ipq_lock); 85 | DEFINE_SPINLOCK(gc_lock); 86 | 87 | 88 | /* detection */ 89 | static struct ndpi_detection_module_struct *ndpi_struct = NULL; 90 | static u32 detection_tick_resolution = 1000; 91 | 92 | /* debug functions */ 93 | 94 | static void debug_printf(u32 protocol, void *id_struct, 95 | ndpi_log_level_t log_level, const char *format, ...) 96 | { 97 | /* do nothing */ 98 | 99 | va_list args; 100 | va_start(args, format); 101 | switch (log_level) 102 | { 103 | case NDPI_LOG_ERROR: 104 | vprintk(format, args); 105 | break; 106 | case NDPI_LOG_TRACE: 107 | vprintk(format, args); 108 | break; 109 | 110 | case NDPI_LOG_DEBUG: 111 | vprintk(format, args); 112 | break; 113 | } 114 | va_end(args); 115 | } 116 | 117 | 118 | static void *malloc_wrapper(unsigned long size) 119 | { 120 | return kmalloc(size, GFP_KERNEL); 121 | } 122 | 123 | 124 | static void free_wrapper(void *freeable) 125 | { 126 | kfree(freeable); 127 | } 128 | 129 | 130 | static struct osdpi_flow_node * 131 | ndpi_flow_search(struct rb_root *root, struct nf_conn *ct) 132 | { 133 | struct osdpi_flow_node *data; 134 | struct rb_node *node = root->rb_node; 135 | 136 | while (node) { 137 | data = rb_entry(node, struct osdpi_flow_node, node); 138 | 139 | if (ct < data->ct) 140 | node = node->rb_left; 141 | else if (ct > data->ct) 142 | node = node->rb_right; 143 | else 144 | return data; 145 | } 146 | 147 | return NULL; 148 | } 149 | 150 | 151 | static int 152 | ndpi_flow_insert(struct rb_root *root, struct osdpi_flow_node *data) 153 | { 154 | struct osdpi_flow_node *this; 155 | struct rb_node **new = &(root->rb_node), *parent = NULL; 156 | 157 | while (*new) { 158 | this = rb_entry(*new, struct osdpi_flow_node, node); 159 | 160 | parent = *new; 161 | if (data->ct < this->ct) 162 | new = &((*new)->rb_left); 163 | else if (data->ct > this->ct) 164 | new = &((*new)->rb_right); 165 | else 166 | return 0; 167 | } 168 | rb_link_node(&data->node, parent, new); 169 | rb_insert_color(&data->node, root); 170 | 171 | return 1; 172 | } 173 | 174 | 175 | static struct osdpi_id_node * 176 | ndpi_id_search(struct rb_root *root, union nf_inet_addr *ip) 177 | { 178 | int res; 179 | struct osdpi_id_node *data; 180 | struct rb_node *node = root->rb_node; 181 | 182 | while (node) { 183 | data = rb_entry(node, struct osdpi_id_node, node); 184 | res = memcmp(ip, &data->ip, sizeof(union nf_inet_addr)); 185 | 186 | if (res < 0) 187 | node = node->rb_left; 188 | else if (res > 0) 189 | node = node->rb_right; 190 | else 191 | return data; 192 | } 193 | 194 | return NULL; 195 | } 196 | 197 | 198 | static int 199 | ndpi_id_insert(struct rb_root *root, struct osdpi_id_node *data) 200 | { 201 | int res; 202 | struct osdpi_id_node *this; 203 | struct rb_node **new = &(root->rb_node), *parent = NULL; 204 | 205 | while (*new) { 206 | this = rb_entry(*new, struct osdpi_id_node, node); 207 | res = memcmp(&data->ip, &this->ip, sizeof(union nf_inet_addr)); 208 | 209 | parent = *new; 210 | if (res < 0) 211 | new = &((*new)->rb_left); 212 | else if (res > 0) 213 | new = &((*new)->rb_right); 214 | else 215 | return 0; 216 | } 217 | 218 | rb_link_node(&data->node, parent, new); 219 | rb_insert_color(&data->node, root); 220 | 221 | return 1; 222 | } 223 | 224 | 225 | static void 226 | ndpi_id_release(struct kref *kref) 227 | { 228 | struct osdpi_id_node * id; 229 | 230 | id = container_of (kref, struct osdpi_id_node, refcnt); 231 | rb_erase(&id->node, &osdpi_id_root); 232 | kmem_cache_free (osdpi_id_cache, id); 233 | //kfree(id); 234 | } 235 | 236 | 237 | static struct osdpi_flow_node * 238 | ndpi_alloc_flow (struct nf_conn * ct) 239 | { 240 | struct osdpi_flow_node *flow; 241 | 242 | flow = kmem_cache_zalloc (osdpi_flow_cache, GFP_ATOMIC); 243 | //flow = kzalloc(sizeof(struct ndpi_flow_struct *) + size_flow_struct, GFP_KERNEL); 244 | 245 | if (flow == NULL) { 246 | pr_err("xt_ndpi: couldn't allocate new flow.\n"); 247 | return NULL; 248 | } 249 | else { 250 | flow->ct = ct; 251 | flow->ndpi_flow = (struct ndpi_flow_struct *) 252 | ((char*)&flow->ndpi_flow+sizeof(flow->ndpi_flow)); 253 | ndpi_flow_insert (&osdpi_flow_root, flow); 254 | } 255 | 256 | return flow; 257 | } 258 | 259 | static void 260 | nfndpi_free_flow (struct nf_conn * ct, struct osdpi_flow_node * auxflow) 261 | { 262 | struct osdpi_flow_node * flow; 263 | 264 | spin_lock_bh (&flow_lock); 265 | if (auxflow == NULL) 266 | flow = ndpi_flow_search (&osdpi_flow_root, ct); 267 | else 268 | flow = auxflow; 269 | 270 | if (flow != NULL){ 271 | rb_erase (&flow->node, &osdpi_flow_root); 272 | kmem_cache_free (osdpi_flow_cache, flow); 273 | //kfree (flow); 274 | } 275 | spin_unlock_bh (&flow_lock); 276 | } 277 | 278 | 279 | static struct osdpi_id_node * 280 | ndpi_alloc_id (union nf_inet_addr * ip) 281 | { 282 | struct osdpi_id_node *id; 283 | 284 | id = kmem_cache_zalloc (osdpi_id_cache, GFP_ATOMIC); 285 | //id = kzalloc(sizeof(struct ndpi_id_struct *) + size_id_struct, GFP_KERNEL); 286 | 287 | if (id == NULL){ 288 | pr_err("xt_ndpi: couldn't allocate new id.\n"); 289 | return NULL; 290 | } 291 | else { 292 | memcpy(&id->ip, ip, sizeof(union nf_inet_addr)); 293 | id->ndpi_id = (struct ndpi_id_struct *) 294 | ((char*)&id->ndpi_id+sizeof(id->ndpi_id)); 295 | kref_init (&id->refcnt); 296 | ndpi_id_insert (&osdpi_id_root, id); 297 | } 298 | 299 | return id; 300 | } 301 | 302 | 303 | static void 304 | nfndpi_free_id (union nf_inet_addr * ip) 305 | { 306 | struct osdpi_id_node *id; 307 | 308 | spin_lock_bh (&id_lock); 309 | id = ndpi_id_search (&osdpi_id_root, ip); 310 | if (id != NULL) 311 | kref_put (&id->refcnt, ndpi_id_release); 312 | spin_unlock_bh (&id_lock); 313 | } 314 | 315 | 316 | static void 317 | ndpi_enable_protocols (const struct xt_ndpi_mtinfo*info) 318 | { 319 | int i; 320 | 321 | for (i = 1; i <= NDPI_LAST_IMPLEMENTED_PROTOCOL; i++){ 322 | if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(info->flags, i) != 0){ 323 | spin_lock_bh (&ipq_lock); 324 | 325 | //Force http or ssl detection for webserver host requests 326 | if (nfndpi_protocols_http[i]) { 327 | NDPI_ADD_PROTOCOL_TO_BITMASK(protocols_bitmask, NDPI_PROTOCOL_DNS); 328 | NDPI_ADD_PROTOCOL_TO_BITMASK(protocols_bitmask, NDPI_PROTOCOL_HTTP); 329 | NDPI_ADD_PROTOCOL_TO_BITMASK(protocols_bitmask, NDPI_PROTOCOL_SSL); 330 | } 331 | atomic_inc(&protocols_cnt[i-1]); 332 | NDPI_ADD_PROTOCOL_TO_BITMASK(protocols_bitmask, i); 333 | ndpi_set_protocol_detection_bitmask2 334 | (ndpi_struct,&protocols_bitmask); 335 | 336 | spin_unlock_bh (&ipq_lock); 337 | } 338 | } 339 | } 340 | 341 | 342 | static void 343 | ndpi_disable_protocols (const struct xt_ndpi_mtinfo*info) 344 | { 345 | int i; 346 | 347 | for (i = 1; i <= NDPI_LAST_IMPLEMENTED_PROTOCOL; i++){ 348 | if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(info->flags, i) != 0){ 349 | spin_lock_bh (&ipq_lock); 350 | if (atomic_dec_and_test(&protocols_cnt[i-1])){ 351 | NDPI_DEL_PROTOCOL_FROM_BITMASK(protocols_bitmask, i); 352 | ndpi_set_protocol_detection_bitmask2 353 | (ndpi_struct, &protocols_bitmask); 354 | } 355 | spin_unlock_bh (&ipq_lock); 356 | } 357 | } 358 | } 359 | 360 | 361 | static void ndpi_kill_flow(struct nf_conn * ct, union nf_inet_addr *ipsrc, union nf_inet_addr *ipdst) { 362 | nfndpi_free_id (ipsrc); 363 | nfndpi_free_id (ipdst); 364 | nfndpi_free_flow(ct, NULL); 365 | } 366 | 367 | 368 | static void ndpi_gc_flow(void) 369 | { 370 | struct nf_conn * ct; 371 | struct rb_node * next; 372 | struct osdpi_flow_node *flow; 373 | union nf_inet_addr *ipdst; 374 | 375 | u64 t1; 376 | struct timeval tv; 377 | 378 | do_gettimeofday(&tv); 379 | t1 = (uint64_t) tv.tv_sec; 380 | 381 | spin_lock_bh (&gc_lock); 382 | //pr_info ("xt_ndpi: call garbage collector.\n"); 383 | next = rb_first(&osdpi_flow_root); 384 | while (next){ 385 | flow = rb_entry(next, struct osdpi_flow_node, node); 386 | next = rb_next(&flow->node); 387 | if (flow && (t1 - flow->ndpi_timeout > 180)) { 388 | ct = flow->ct; 389 | ipdst = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3; 390 | //pr_info ("xt_ndpi: deleted by garbage collector - proto %d - dst %pI4\n", ipdst, flow->detected_protocol); 391 | 392 | nfndpi_free_id (&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3); 393 | nfndpi_free_id (ipdst); 394 | nfndpi_free_flow(ct, flow); 395 | } 396 | } 397 | spin_unlock_bh (&gc_lock); 398 | } 399 | 400 | 401 | static u32 402 | ndpi_process_packet(struct nf_conn * ct, const uint64_t time, 403 | const struct iphdr *iph, uint16_t ipsize, const struct tcphdr *tcph) 404 | { 405 | u32 proto = NDPI_PROTOCOL_UNKNOWN; 406 | union nf_inet_addr *ipsrc, *ipdst; 407 | struct osdpi_id_node *src, *dst; 408 | struct osdpi_flow_node *flow; 409 | 410 | u8 exist_flow=0; 411 | u64 t1; 412 | struct timeval tv; 413 | 414 | ipsrc = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3; 415 | ipdst = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3; 416 | 417 | spin_lock_bh (&flow_lock); 418 | flow = ndpi_flow_search (&osdpi_flow_root, ct); 419 | 420 | if (iph->protocol == IPPROTO_TCP) { 421 | if (tcph->syn) { 422 | spin_unlock_bh (&flow_lock); 423 | return proto; 424 | } 425 | else if ((tcph->fin || tcph->rst) && flow != NULL) { 426 | spin_unlock_bh (&flow_lock); 427 | ndpi_kill_flow(ct, ipsrc, ipdst); 428 | return proto; 429 | } 430 | } 431 | else if (iph->protocol == IPPROTO_ICMP) { 432 | spin_unlock_bh (&flow_lock); 433 | return NDPI_PROTOCOL_IP_ICMP; 434 | } 435 | else { 436 | if (nf_ct_is_dying(ct)) { 437 | spin_unlock_bh (&flow_lock); 438 | ndpi_kill_flow(ct, ipsrc, ipdst); 439 | return proto; 440 | } 441 | } 442 | 443 | do_gettimeofday(&tv); 444 | t1 = (uint64_t) tv.tv_sec; 445 | 446 | if (flow == NULL) { 447 | if (!gc_interval_timeout) gc_interval_timeout = t1; 448 | else { 449 | if (t1 - gc_interval_timeout > 59) { 450 | spin_unlock_bh (&flow_lock); 451 | ndpi_gc_flow(); 452 | gc_interval_timeout = t1; 453 | spin_lock_bh (&flow_lock); 454 | } 455 | } 456 | 457 | flow = ndpi_alloc_flow(ct); 458 | if (flow == NULL) { 459 | spin_unlock_bh (&flow_lock); 460 | return NDPI_PROTOCOL_UNKNOWN; 461 | } 462 | else { 463 | /* Include flow timeouts */ 464 | flow->ndpi_timeout = t1; // 30s for DPI timeout and 180 for connection 465 | flow->detected_protocol = NDPI_PROTOCOL_UNKNOWN; 466 | flow->detection_completed = 0; 467 | } 468 | } 469 | else { 470 | /* Update timeouts */ 471 | exist_flow=1; 472 | if (flow->detected_protocol) { 473 | proto = flow->detected_protocol; 474 | flow->ndpi_timeout = t1; 475 | //pr_info ("xt_ndpi: flow detected. %d\n", flow->detected_protocol); 476 | spin_unlock_bh (&flow_lock); 477 | return proto; 478 | } 479 | else if (!flow->detected_protocol && (t1 - flow->ndpi_timeout > 30)) { 480 | //pr_info ("xt_ndpi: expired.\n"); 481 | spin_unlock_bh (&flow_lock); 482 | return NDPI_PROTOCOL_UNKNOWN; 483 | 484 | } 485 | } 486 | 487 | /* Invalid DPI flow */ 488 | if (flow->ndpi_flow == NULL) { 489 | spin_unlock_bh (&flow_lock); 490 | ndpi_kill_flow(ct, ipsrc, ipdst); 491 | return proto; 492 | } 493 | 494 | flow->ndpi_timeout = t1; 495 | spin_unlock_bh (&flow_lock); 496 | 497 | 498 | spin_lock_bh (&id_lock); 499 | src = ndpi_id_search (&osdpi_id_root, ipsrc); 500 | if (src == NULL) { 501 | src = ndpi_alloc_id(ipsrc); 502 | if (src == NULL) { 503 | spin_unlock_bh (&id_lock); 504 | return proto; 505 | } 506 | } 507 | else if (!exist_flow) kref_get (&src->refcnt); 508 | 509 | dst = ndpi_id_search (&osdpi_id_root, ipdst); 510 | if (dst == NULL) { 511 | dst = ndpi_alloc_id(ipdst); 512 | if (dst == NULL) { 513 | spin_unlock_bh (&id_lock); 514 | return proto; 515 | } 516 | } 517 | else if (!exist_flow) kref_get (&dst->refcnt); 518 | spin_unlock_bh (&id_lock); 519 | 520 | 521 | /* here the actual detection is performed */ 522 | spin_lock_bh (&ipq_lock); 523 | proto = ndpi_detection_process_packet(ndpi_struct,flow->ndpi_flow, 524 | (uint8_t *) iph, ipsize, time, 525 | src->ndpi_id, dst->ndpi_id); 526 | 527 | /* set detected protocol */ 528 | flow->detected_protocol = proto; 529 | if (proto > NDPI_LAST_IMPLEMENTED_PROTOCOL) 530 | proto = NDPI_PROTOCOL_UNKNOWN; 531 | else { 532 | if (flow->detected_protocol != NDPI_PROTOCOL_UNKNOWN) { 533 | //pr_info ("xt_ndpi: proto detected. %d\n", flow->detected_protocol); 534 | if (flow->ndpi_flow->no_cache_protocol) 535 | ndpi_kill_flow(ct, ipsrc, ipdst); 536 | else { 537 | /* update timeouts */ 538 | flow->ndpi_timeout = t1; 539 | flow->detection_completed = 1; 540 | 541 | /* reset detection */ 542 | if (flow->ndpi_flow) memset(flow->ndpi_flow, 0, sizeof(*(flow->ndpi_flow))); 543 | } 544 | } 545 | } 546 | spin_unlock_bh (&ipq_lock); 547 | 548 | return proto; 549 | } 550 | 551 | 552 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) 553 | static bool 554 | ndpi_mt (const struct sk_buff *skb, 555 | const struct net_device *in, 556 | const struct net_device *out, 557 | const struct xt_match *match, 558 | const void *matchinfo, 559 | int offset, 560 | unsigned int protoff, 561 | bool *hotdrop) 562 | 563 | #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) 564 | static bool 565 | ndpi_mt(const struct sk_buff *skb, const struct xt_match_param *par) 566 | #else 567 | static bool 568 | ndpi_mt(const struct sk_buff *skb, struct xt_action_param *par) 569 | #endif 570 | { 571 | u32 proto = NDPI_PROTOCOL_UNKNOWN; 572 | u64 time; 573 | 574 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) 575 | const struct xt_ndpi_mtinfo *info = matchinfo; 576 | #else 577 | const struct xt_ndpi_mtinfo *info = par->matchinfo; 578 | #endif 579 | 580 | enum ip_conntrack_info ctinfo; 581 | struct nf_conn * ct; 582 | struct timeval tv; 583 | struct sk_buff *linearized_skb = NULL; 584 | const struct sk_buff *skb_use = NULL; 585 | 586 | const struct iphdr *ip; 587 | const struct tcphdr *tcph; 588 | 589 | if (skb_is_nonlinear(skb)){ 590 | linearized_skb = skb_copy(skb, GFP_ATOMIC); 591 | if (linearized_skb == NULL) { 592 | pr_info ("xt_ndpi: linearization failed.\n"); 593 | return false; 594 | } 595 | skb_use = linearized_skb; 596 | } else { 597 | skb_use = skb; 598 | } 599 | 600 | 601 | ct = nf_ct_get (skb_use, &ctinfo); 602 | if (ct == NULL){ 603 | if(linearized_skb != NULL) 604 | kfree_skb(linearized_skb); 605 | 606 | return false; 607 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) 608 | } else if (nf_ct_is_untracked(skb)){ 609 | #else 610 | } else if (nf_ct_is_untracked(ct)){ 611 | #endif 612 | pr_info ("xt_ndpi: ignoring untracked sk_buff.\n"); 613 | return false; 614 | } 615 | 616 | 617 | /* process the packet */ 618 | ip = ip_hdr(skb_use); 619 | tcph = (const void *)ip + ip_hdrlen(skb_use); 620 | 621 | do_gettimeofday(&tv); 622 | time = ((uint64_t) tv.tv_sec) * detection_tick_resolution + 623 | tv.tv_usec / (1000000 / detection_tick_resolution); 624 | 625 | /* reset for new packets and solve ct collisions */ 626 | if (ctinfo == IP_CT_NEW) 627 | ndpi_kill_flow(ct, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3); 628 | 629 | proto = ndpi_process_packet(ct, time, ip_hdr(skb_use), skb_use->len, tcph); 630 | 631 | 632 | if(linearized_skb != NULL) 633 | kfree_skb(linearized_skb); 634 | 635 | if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(info->flags,proto) != 0) { 636 | if(par->hotdrop) 637 | ndpi_kill_flow(ct, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3); 638 | return true; 639 | } 640 | 641 | return false; 642 | } 643 | 644 | 645 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) 646 | static bool 647 | ndpi_mt_check(const char *tablename, 648 | const void *ip, 649 | const struct xt_match *match, 650 | void *matchinfo, 651 | unsigned int hook_mask) 652 | 653 | { 654 | const struct xt_ndpi_mtinfo *info = matchinfo; 655 | 656 | 657 | if (NDPI_BITMASK_IS_ZERO(info->flags)) { 658 | pr_info("None selected protocol.\n"); 659 | return -EINVAL; 660 | } 661 | 662 | ndpi_enable_protocols (info); 663 | 664 | return nf_ct_l3proto_try_module_get (match->family) == 0; 665 | } 666 | 667 | #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) 668 | static bool 669 | ndpi_mt_check(const struct xt_mtchk_param *par) 670 | { 671 | const struct xt_ndpi_mtinfo *info = par->matchinfo; 672 | 673 | if (NDPI_BITMASK_IS_ZERO(info->flags)) { 674 | pr_info("None selected protocol.\n"); 675 | return -EINVAL; 676 | } 677 | 678 | ndpi_enable_protocols (info); 679 | 680 | return nf_ct_l3proto_try_module_get (par->family) == 0; 681 | } 682 | #else 683 | static int 684 | ndpi_mt_check(const struct xt_mtchk_param *par) 685 | { 686 | const struct xt_ndpi_mtinfo *info = par->matchinfo; 687 | 688 | if (NDPI_BITMASK_IS_ZERO(info->flags)) { 689 | pr_info("None selected protocol.\n"); 690 | return -EINVAL; 691 | } 692 | 693 | ndpi_enable_protocols (info); 694 | 695 | return nf_ct_l3proto_try_module_get (par->family); 696 | } 697 | #endif 698 | 699 | 700 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) 701 | static void 702 | ndpi_mt_destroy (const struct xt_match *match, void *matchinfo) 703 | { 704 | const struct xt_ndpi_mtinfo *info = matchinfo; 705 | 706 | ndpi_disable_protocols (info); 707 | nf_ct_l3proto_module_put (match->family); 708 | } 709 | 710 | #else 711 | static void 712 | ndpi_mt_destroy (const struct xt_mtdtor_param *par) 713 | { 714 | const struct xt_ndpi_mtinfo *info = par->matchinfo; 715 | 716 | ndpi_disable_protocols (info); 717 | nf_ct_l3proto_module_put (par->family); 718 | } 719 | 720 | #endif 721 | 722 | 723 | 724 | static void ndpi_cleanup(void) 725 | { 726 | struct rb_node * next; 727 | struct osdpi_id_node *id; 728 | struct osdpi_flow_node *flow; 729 | 730 | ndpi_exit_detection_module(ndpi_struct, free_wrapper); 731 | 732 | /* free all objects before destroying caches */ 733 | next = rb_first(&osdpi_flow_root); 734 | while (next){ 735 | flow = rb_entry(next, struct osdpi_flow_node, node); 736 | next = rb_next(&flow->node); 737 | 738 | rb_erase(&flow->node, &osdpi_flow_root); 739 | kmem_cache_free (osdpi_flow_cache, flow); 740 | } 741 | kmem_cache_destroy (osdpi_flow_cache); 742 | 743 | next = rb_first(&osdpi_id_root); 744 | while (next){ 745 | id = rb_entry(next, struct osdpi_id_node, node); 746 | next = rb_next(&id->node); 747 | rb_erase(&id->node, &osdpi_id_root); 748 | kmem_cache_free (osdpi_id_cache, id); 749 | } 750 | kmem_cache_destroy (osdpi_id_cache); 751 | } 752 | 753 | 754 | static struct xt_match 755 | ndpi_mt_reg __read_mostly = { 756 | .name = "ndpi", 757 | .revision = 0, 758 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) 759 | .family = AF_INET, 760 | #else 761 | .family = NFPROTO_IPV4, 762 | #endif 763 | .match = ndpi_mt, 764 | .checkentry = ndpi_mt_check, 765 | .destroy = ndpi_mt_destroy, 766 | .matchsize = sizeof(struct xt_ndpi_mtinfo), 767 | .me = THIS_MODULE, 768 | }; 769 | 770 | 771 | static int __init ndpi_mt_init(void) 772 | { 773 | int ret=-ENOMEM, i; 774 | 775 | pr_info("xt_ndpi 2.0 (nDPI wrapper module).\n"); 776 | 777 | /* init global detection structure */ 778 | ndpi_struct = ndpi_init_detection_module(detection_tick_resolution, 779 | malloc_wrapper, free_wrapper, debug_printf); 780 | 781 | if (ndpi_struct == NULL) { 782 | pr_err("xt_ndpi: global structure initialization failed.\n"); 783 | ret = -ENOMEM; 784 | goto err_out; 785 | } 786 | 787 | for (i = 0; i <= NDPI_LAST_IMPLEMENTED_PROTOCOL; i++){ 788 | atomic_set (&protocols_cnt[i], 0); 789 | 790 | // Set HTTP based protocols 791 | if ((i > 118 && i < 127) || (i > 139 && i < 146) || (i > 175 && i < 182 ) || i == 70 || i == 133) nfndpi_protocols_http[i]=1; 792 | else nfndpi_protocols_http[i]=0; 793 | } 794 | 795 | /* disable all protocols */ 796 | NDPI_BITMASK_RESET(protocols_bitmask); 797 | ndpi_set_protocol_detection_bitmask2(ndpi_struct, &protocols_bitmask); 798 | 799 | /* allocate memory for id and flow tracking */ 800 | size_id_struct = ndpi_detection_get_sizeof_ndpi_id_struct(); 801 | size_flow_struct = ndpi_detection_get_sizeof_ndpi_flow_struct(); 802 | 803 | 804 | osdpi_flow_cache = kmem_cache_create("xt_ndpi_flows", 805 | sizeof(struct osdpi_flow_node) + 806 | size_flow_struct, 807 | 0, 0, NULL); 808 | 809 | if (!osdpi_flow_cache){ 810 | pr_err("xt_ndpi: error creating flow cache.\n"); 811 | ret = -ENOMEM; 812 | goto err_ipq; 813 | } 814 | 815 | osdpi_id_cache = kmem_cache_create("xt_ndpi_ids", 816 | sizeof(struct osdpi_id_node) + 817 | size_id_struct, 818 | 0, 0, NULL); 819 | if (!osdpi_id_cache){ 820 | pr_err("xt_ndpi: error creating ids cache.\n"); 821 | ret = -ENOMEM; 822 | goto err_flow; 823 | } 824 | 825 | ret = xt_register_match(&ndpi_mt_reg); 826 | if (ret != 0){ 827 | pr_err("xt_ndpi: error registering ndpi match.\n"); 828 | ndpi_cleanup(); 829 | } 830 | 831 | return ret; 832 | 833 | err_flow: 834 | kmem_cache_destroy (osdpi_flow_cache); 835 | err_ipq: 836 | ndpi_exit_detection_module(ndpi_struct, free_wrapper); 837 | err_out: 838 | return ret; 839 | } 840 | 841 | 842 | static void __exit ndpi_mt_exit(void) 843 | { 844 | pr_info("xt_ndpi 2.0 unload.\n"); 845 | 846 | xt_unregister_match(&ndpi_mt_reg); 847 | ndpi_cleanup(); 848 | } 849 | 850 | 851 | module_init(ndpi_mt_init); 852 | module_exit(ndpi_mt_exit); 853 | 854 | MODULE_LICENSE("GPL"); 855 | MODULE_AUTHOR("G. Elian Gidoni "); 856 | MODULE_AUTHOR("Humberto Juca "); 857 | MODULE_DESCRIPTION("nDPI wrapper"); 858 | MODULE_ALIAS("ipt_ndpi"); 859 | -------------------------------------------------------------------------------- /old/src/xt_ndpi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * xt_ndpi.h 3 | * Copyright (C) 2010-2012 G. Elian Gidoni 4 | * 2012 Ed Wildgoose 5 | * 2014 Humberto Jucá 6 | * 7 | * This file is part of nDPI, an open source deep packet inspection 8 | * library based on the PACE technology by ipoque GmbH 9 | * 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License 12 | * as published by the Free Software Foundation; version 2 of the License. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 | */ 23 | 24 | #ifndef _LINUX_NETFILTER_XT_NDPI_H 25 | #define _LINUX_NETFILTER_XT_NDPI_H 1 26 | 27 | #include 28 | #include "ndpi_main.h" 29 | 30 | #ifndef NDPI_BITMASK_IS_ZERO 31 | #define NDPI_BITMASK_IS_ZERO(a) NDPI_BITMASK_IS_EMPTY(a) 32 | #endif 33 | 34 | struct xt_ndpi_mtinfo { 35 | NDPI_PROTOCOL_BITMASK flags; 36 | }; 37 | 38 | /* /usr/src/nDPI/src/include/ndpi_protocol_ids.h */ 39 | #ifndef NDPI_PROTOCOL_LONG_STRING 40 | #define NDPI_PROTOCOL_LONG_STRING "Unknown","FTP_CONTROL","MAIL_POP","MAIL_SMTP","MAIL_IMAP","DNS","IPP","HTTP","MDNS","NTP",\ 41 | "NETBIOS","NFS","SSDP","BGP","SNMP","XDMCP","SMB","SYSLOG","DHCP","POSTGRES","MYSQL","TDS","DIRECT_DOWNLOAD_LINK","MAIL_POPS",\ 42 | "APPLEJUICE","DIRECTCONNECT","SOCRATES","WINMX","VMWARE","MAIL_SMTPS",\ 43 | "FILETOPIA","IMESH","KONTIKI","OPENFT","FASTTRACK","GNUTELLA","EDONKEY","BITTORRENT",\ 44 | "EPP","AVI","FLASH","OGG","MPEG","QUICKTIME","REALMEDIA","WINDOWSMEDIA","MMS","XBOX","QQ","MOVE","RTSP","MAIL_IMAPS","ICECAST",\ 45 | "PPLIVE","PPSTREAM","ZATTOO","SHOUTCAST","SOPCAST","TVANTS","TVUPLAYER","HTTP_APPLICATION_VEOHTV","QQLIVE","THUNDER","SOULSEEK",\ 46 | "SSL_NO_CERT","IRC","AYIYA","UNENCRYPED_JABBER","MSN","OSCAR","YAHOO","BATTLEFIELD","QUAKE","VRRP","STEAM","HALFLIFE2",\ 47 | "WORLDOFWARCRAFT","TELNET","STUN","IPSEC","GRE","ICMP","IGMP","EGP","SCTP","OSPF","IP_IN_IP","RTP","RDP","VNC","PCANYWHERE",\ 48 | "SSL","SSH","USENET","MGCP","IAX","TFTP","AFP","STEALTHNET","AIMINI","SIP","TRUPHONE","ICMPV6","DHCPV6","ARMAGETRON",\ 49 | "CROSSFIRE","DOFUS","FIESTA","FLORENSIA","GUILDWARS","HTTP_APPLICATION_ACTIVESYNC","KERBEROS","LDAP","MAPLESTORY","MSSQL",\ 50 | "PPTP","WARCRAFT3","WORLD_OF_KUNG_FU","MEEBO","FACEBOOK","TWITTER","DROPBOX","GMAIL","GOOGLE_MAPS","YOUTUBE","SKYPE","GOOGLE",\ 51 | "DCERPC","NETFLOW","SFLOW","HTTP_CONNECT","HTTP_PROXY","CITRIX","NETFLIX","LASTFM","GROOVESHARK",\ 52 | "SKYFILE_PREPAID","SKYFILE_RUDICS","SKYFILE_POSTPAID","CITRIX_ONLINE","APPLE","WEBEX","WHATSAPP","APPLE_ICLOUD","VIBER",\ 53 | "APPLE_ITUNES","RADIUS","WINDOWS_UPDATE","TEAMVIEWER","TUENTI","LOTUS_NOTES","SAP","GTP","UPNP","LLMNR","REMOTE_SCAN","SPOTIFY",\ 54 | "WEBM","H323","OPENVPN","NOE","CISCOVPN","TEAMSPEAK","TOR","SKINNY","RTCP","RSYNC","ORACLE","CORBA","UBUNTUONE","WHOIS_DAS",\ 55 | "COLLECTD","SOCKS5","SOCKS4","RTMP","FTP_DATA","WIKIPEDIA","ZMQ","AMAZON","EBAY","CNN","MEGACO","REDIS","PANDO","VHUA","TELEGRAM",\ 56 | "VEVO","PANDORA","QUIC","WHATSAPP_VOICE","CHECK" 57 | #endif 58 | 59 | #ifndef NDPI_PROTOCOL_SHORT_STRING 60 | #define NDPI_PROTOCOL_SHORT_STRING "unknown","ftp","pop","smtp","imap","dns","ipp","http","mdns","ntp",\ 61 | "netbios","nfs","ssdp","bgp","snmp","xdmcp","smb","syslog","dhcp","postgres","mysql","tds","directdownload","pops",\ 62 | "applejuice","directconnect","socrates","winmx","vmware","smtps",\ 63 | "filetopia","imesh","kontiki","openft","fasttrack","gnutella","edonkey","bittorrent",\ 64 | "epp","avi","flash","ogg","mpeg","quicktime","realmedia","windowsmedia","mms","xbox","qq","move","rtsp","imaps","icecast",\ 65 | "pplive","ppstream","zattoo","shoutcast","sopcast","tvants","tvuplayer","http_application_veohtv","qqlive","thunder","soulseek",\ 66 | "ssl_no_cert","irc","ayiya","unencryped_jabber","msn","oscar","yahoo","battlefield","quake","vrrp","steam","halflife2",\ 67 | "worldofwarcraft","telnet","stun","ipsec","gre","icmp","igmp","egp","sctp","ospf","ipip","rtp","rdp","vnc","pcanywhere",\ 68 | "ssl","ssh","usenet","mgcp","iax","tftp","afp","stealthnet","aimini","sip","truphone","icmpv6","dhcpv6","armagetron",\ 69 | "crossfire","dofus","fiesta","florensia","guildwars","http_application_activesync","kerberos","ldap","maplestory","mssql",\ 70 | "pptp","warcraft3","world_of_kung_fu","meebo","facebook","twitter","dropbox","gmail","google_maps","youtube","skype","google",\ 71 | "dcerpc","netflow","sflow","http_connect","http_proxy","citrix","netflix","lastfm","grooveshark",\ 72 | "skyfile_prepaid","skyfile_rudics","skyfile_postpaid","citrix_online","apple","webex","whatsapp","apple_icloud","viber",\ 73 | "apple_itunes","radius","windows_update","teamviewer","tuenti","lotusnotes","sap","gtp","upnp","llmnr","remotescan","spotify",\ 74 | "webm","h323","openvpn","noe","ciscovpn","teamspeak","tor","skinny","rtcp","rsync","oracle","corba","ubuntuone","whois_das",\ 75 | "collectd","socks5","socks4","rtmp","ftpdata","wikipedia","zmq","amazon","ebay","cnn","megaco","redis","pando","vhua","telegram",\ 76 | "vevo","pandora","quic","whatsapp_voice","dpi_check" 77 | #endif 78 | 79 | #ifndef NDPI_LAST_NFPROTO 80 | #define NDPI_LAST_NFPROTO NDPI_LAST_IMPLEMENTED_PROTOCOL + 1 81 | #endif 82 | 83 | #endif /* _LINUX_NETFILTER_XT_NDPI_H */ 84 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | NDPI_PATH2 := ${NDPI_PATH}/src 2 | NDPI_SRC := ndpi_cpy 3 | NDPI_PRO := ${NDPI_SRC}/lib/protocols 4 | 5 | ccflags-y += -I${src}/${NDPI_SRC}/include -I${src}/${NDPI_SRC}/lib -DOPENDPI_NETFILTER_MODULE -DNDPI_IPTABLES_EXT 6 | 7 | MODULES_DIR := /lib/modules/$(shell uname -r) 8 | KERNEL_DIR ?= ${MODULES_DIR}/build 9 | 10 | obj-m := xt_ndpi.o 11 | xt_ndpi-y := main.o \ 12 | ${NDPI_SRC}/lib/ndpi_main.o \ 13 | ${NDPI_SRC}/lib/ahocorasick.o \ 14 | ${NDPI_SRC}/lib/node.o \ 15 | ${NDPI_SRC}/lib/sort.o \ 16 | ${NDPI_PRO}/afp.o \ 17 | ${NDPI_PRO}/aimini.o \ 18 | ${NDPI_PRO}/applejuice.o \ 19 | ${NDPI_PRO}/armagetron.o \ 20 | ${NDPI_PRO}/battlefield.o \ 21 | ${NDPI_PRO}/bgp.o \ 22 | ${NDPI_PRO}/bittorrent.o \ 23 | ${NDPI_PRO}/citrix.o \ 24 | ${NDPI_PRO}/ciscovpn.o \ 25 | ${NDPI_PRO}/corba.o \ 26 | ${NDPI_PRO}/crossfire.o \ 27 | ${NDPI_PRO}/dcerpc.o \ 28 | ${NDPI_PRO}/dhcp.o \ 29 | ${NDPI_PRO}/dhcpv6.o \ 30 | ${NDPI_PRO}/directconnect.o \ 31 | ${NDPI_PRO}/directdownloadlink.o \ 32 | ${NDPI_PRO}/dns.o \ 33 | ${NDPI_PRO}/dofus.o \ 34 | ${NDPI_PRO}/drda.o \ 35 | ${NDPI_PRO}/dropbox.o \ 36 | ${NDPI_PRO}/edonkey.o \ 37 | ${NDPI_PRO}/git.o \ 38 | ${NDPI_PRO}/gtp.o \ 39 | ${NDPI_PRO}/lotus_notes.o \ 40 | ${NDPI_PRO}/fasttrack.o \ 41 | ${NDPI_PRO}/fiesta.o \ 42 | ${NDPI_PRO}/filetopia.o \ 43 | ${NDPI_PRO}/florensia.o \ 44 | ${NDPI_PRO}/ftp_control.o \ 45 | ${NDPI_PRO}/ftp_data.o \ 46 | ${NDPI_PRO}/gnutella.o \ 47 | ${NDPI_PRO}/guildwars.o \ 48 | ${NDPI_PRO}/hangout.o \ 49 | ${NDPI_PRO}/halflife2_and_mods.o \ 50 | ${NDPI_PRO}/h323.o \ 51 | ${NDPI_PRO}/http.o \ 52 | ${NDPI_PRO}/http_activesync.o \ 53 | ${NDPI_PRO}/iax.o \ 54 | ${NDPI_PRO}/icecast.o \ 55 | ${NDPI_PRO}/ipp.o \ 56 | ${NDPI_PRO}/irc.o \ 57 | ${NDPI_PRO}/jabber.o \ 58 | ${NDPI_PRO}/kerberos.o \ 59 | ${NDPI_PRO}/kontiki.o \ 60 | ${NDPI_PRO}/ldap.o \ 61 | ${NDPI_PRO}/mail_imap.o \ 62 | ${NDPI_PRO}/mail_pop.o \ 63 | ${NDPI_PRO}/mail_smtp.o \ 64 | ${NDPI_PRO}/maplestory.o \ 65 | ${NDPI_PRO}/mdns.o \ 66 | ${NDPI_PRO}/mgcp.o \ 67 | ${NDPI_PRO}/mms.o \ 68 | ${NDPI_PRO}/msn.o \ 69 | ${NDPI_PRO}/mssql_tds.o \ 70 | ${NDPI_PRO}/mysql.o \ 71 | ${NDPI_PRO}/whoisdas.o \ 72 | ${NDPI_PRO}/netbios.o \ 73 | ${NDPI_PRO}/netflow.o \ 74 | ${NDPI_PRO}/nfs.o \ 75 | ${NDPI_PRO}/noe.o \ 76 | ${NDPI_PRO}/non_tcp_udp.o \ 77 | ${NDPI_PRO}/ntp.o \ 78 | ${NDPI_PRO}/openft.o \ 79 | ${NDPI_PRO}/openvpn.o \ 80 | ${NDPI_PRO}/oracle.o \ 81 | ${NDPI_PRO}/oscar.o \ 82 | ${NDPI_PRO}/pando.o \ 83 | ${NDPI_PRO}/pcanywhere.o \ 84 | ${NDPI_PRO}/postgres.o \ 85 | ${NDPI_PRO}/pplive.o \ 86 | ${NDPI_PRO}/ppstream.o \ 87 | ${NDPI_PRO}/pptp.o \ 88 | ${NDPI_PRO}/qq.o \ 89 | ${NDPI_PRO}/quake.o \ 90 | ${NDPI_PRO}/quic.o \ 91 | ${NDPI_PRO}/eaq.o \ 92 | ${NDPI_PRO}/kakaotalk_voice.o \ 93 | ${NDPI_PRO}/mpegts.o \ 94 | ${NDPI_PRO}/starcraft.o \ 95 | ${NDPI_PRO}/teredo.o \ 96 | ${NDPI_PRO}/hep.o \ 97 | ${NDPI_PRO}/ubntac2.o \ 98 | ${NDPI_PRO}/radius.o \ 99 | ${NDPI_PRO}/rdp.o \ 100 | ${NDPI_PRO}/rtp.o \ 101 | ${NDPI_PRO}/rtsp.o \ 102 | ${NDPI_PRO}/rtmp.o \ 103 | ${NDPI_PRO}/rtcp.o \ 104 | ${NDPI_PRO}/rsync.o \ 105 | ${NDPI_PRO}/sflow.o \ 106 | ${NDPI_PRO}/shoutcast.o \ 107 | ${NDPI_PRO}/sip.o \ 108 | ${NDPI_PRO}/zeromq.o \ 109 | ${NDPI_PRO}/skinny.o \ 110 | ${NDPI_PRO}/skype.o \ 111 | ${NDPI_PRO}/smb.o \ 112 | ${NDPI_PRO}/snmp.o \ 113 | ${NDPI_PRO}/coap.o \ 114 | ${NDPI_PRO}/socrates.o \ 115 | ${NDPI_PRO}/socks45.o \ 116 | ${NDPI_PRO}/sopcast.o \ 117 | ${NDPI_PRO}/soulseek.o \ 118 | ${NDPI_PRO}/spotify.o \ 119 | ${NDPI_PRO}/ssdp.o \ 120 | ${NDPI_PRO}/ssh.o \ 121 | ${NDPI_PRO}/ssl.o \ 122 | ${NDPI_PRO}/stealthnet.o \ 123 | ${NDPI_PRO}/steam.o \ 124 | ${NDPI_PRO}/stun.o \ 125 | ${NDPI_PRO}/syslog.o \ 126 | ${NDPI_PRO}/tcp_udp.o \ 127 | ${NDPI_PRO}/teamviewer.o \ 128 | ${NDPI_PRO}/telegram.o \ 129 | ${NDPI_PRO}/telnet.o \ 130 | ${NDPI_PRO}/teamspeak.o \ 131 | ${NDPI_PRO}/tftp.o \ 132 | ${NDPI_PRO}/thunder.o \ 133 | ${NDPI_PRO}/tvants.o \ 134 | ${NDPI_PRO}/tvuplayer.o \ 135 | ${NDPI_PRO}/tor.o \ 136 | ${NDPI_PRO}/usenet.o \ 137 | ${NDPI_PRO}/viber.o \ 138 | ${NDPI_PRO}/vmware.o \ 139 | ${NDPI_PRO}/vnc.o \ 140 | ${NDPI_PRO}/warcraft3.o \ 141 | ${NDPI_PRO}/world_of_kung_fu.o \ 142 | ${NDPI_PRO}/world_of_warcraft.o \ 143 | ${NDPI_PRO}/xbox.o \ 144 | ${NDPI_PRO}/xdmcp.o \ 145 | ${NDPI_PRO}/yahoo.o \ 146 | ${NDPI_PRO}/megaco.o \ 147 | ${NDPI_PRO}/redis_net.o \ 148 | ${NDPI_PRO}/vhua.o \ 149 | ${NDPI_PRO}/ayiya.o \ 150 | ${NDPI_PRO}/zattoo.o \ 151 | ${NDPI_PRO}/rx.o \ 152 | ${NDPI_PRO}/mqtt.o 153 | 154 | all: 155 | if test -d ${NDPI_SRC}; then \ 156 | cp ${NDPI_PATH2}/* ${NDPI_SRC} -R; \ 157 | else \ 158 | mkdir ${NDPI_SRC}; \ 159 | cp ${NDPI_PATH2}/* ${NDPI_SRC} -R; \ 160 | fi 161 | cp ${NDPI_SRC}/../../nDPI-patch/src/* ${NDPI_SRC}/ -R; 162 | cp ${NDPI_SRC}/lib/third_party/src/*.c ${NDPI_SRC}/lib -R; 163 | cp ${NDPI_SRC}/lib/third_party/include/*.h ${NDPI_SRC}/lib -R; 164 | cp ${NDPI_SRC}/lib/third_party/include/*.h ${NDPI_SRC}/include -R; 165 | sed -i "s/^\s*void ndpi_free_flow/\/\/void ndpi_free_flow/" ${NDPI_SRC}/include/ndpi_api.h; 166 | make -C ${KERNEL_DIR} M=$$PWD; 167 | rm -r ${NDPI_SRC} 168 | modules: 169 | make -C ${KERNEL_DIR} M=$$PWD $@; 170 | modules_install: 171 | make -C ${KERNEL_DIR} M=$$PWD $@; 172 | depmod -a; 173 | clean: 174 | make -C ${KERNEL_DIR} M=$$PWD $@; 175 | rm -rf modules.order ${NDPI_SRC} 176 | -------------------------------------------------------------------------------- /src/xt_ndpi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * xt_ndpi.h 3 | * Copyright (C) 2010-2012 G. Elian Gidoni 4 | * 2012 Ed Wildgoose 5 | * 2014 Humberto Jucá 6 | * 7 | * This file is part of nDPI, an open source deep packet inspection 8 | * library based on the PACE technology by ipoque GmbH 9 | * 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License 12 | * as published by the Free Software Foundation; version 2 of the License. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 | */ 23 | 24 | #ifndef _LINUX_NETFILTER_XT_NDPI_H 25 | #define _LINUX_NETFILTER_XT_NDPI_H 1 26 | 27 | #include 28 | #include "ndpi_main.h" 29 | 30 | #ifndef NDPI_BITMASK_IS_ZERO 31 | #define NDPI_BITMASK_IS_ZERO(a) NDPI_BITMASK_IS_EMPTY(a) 32 | #endif 33 | 34 | struct xt_ndpi_mtinfo { 35 | NDPI_PROTOCOL_BITMASK flags; 36 | }; 37 | 38 | /* /usr/src/nDPI/src/include/ndpi_protocol_ids.h 39 | - protocols summ per line: 9, 23, 29, 37, 52, 63, 75, 90, 104, 114, 126, 135, 144, 156, 170, 185, 197, 208, 214 40 | */ 41 | #ifndef NDPI_PROTOCOL_LONG_STRING 42 | #define NDPI_PROTOCOL_LONG_STRING "Unknown","FTP_CONTROL","MAIL_POP","MAIL_SMTP","MAIL_IMAP","DNS","IPP","HTTP","MDNS","NTP",\ 43 | "NETBIOS","NFS","SSDP","BGP","SNMP","XDMCP","SMB","SYSLOG","DHCP","POSTGRES","MYSQL","HOTMAIL","DIRECT_DOWNLOAD_LINK","MAIL_POPS",\ 44 | "APPLEJUICE","DIRECTCONNECT","SOCRATES","COAP","VMWARE","MAIL_SMTPS",\ 45 | "FILETOPIA","UBNTAC2","KONTIKI","OPENFT","FASTTRACK","GNUTELLA","EDONKEY","BITTORRENT",\ 46 | "EPP","AVI","FLASH","OGG","MPEG","QUICKTIME","REALMEDIA","WINDOWSMEDIA","MMS","XBOX","QQ","MOVE","RTSP","MAIL_IMAPS","ICECAST",\ 47 | "PPLIVE","PPSTREAM","ZATTOO","SHOUTCAST","SOPCAST","TVANTS","TVUPLAYER","HTTP_DOWNLOAD","QQLIVE","THUNDER","SOULSEEK",\ 48 | "SSL_NO_CERT","IRC","AYIYA","UNENCRYPED_JABBER","MSN","OSCAR","YAHOO","BATTLEFIELD","QUAKE","VRRP","STEAM","HALFLIFE2",\ 49 | "WORLDOFWARCRAFT","TELNET","STUN","IPSEC","GRE","ICMP","IGMP","EGP","SCTP","OSPF","IP_IN_IP","RTP","RDP","VNC","PCANYWHERE",\ 50 | "SSL","SSH","USENET","MGCP","IAX","TFTP","AFP","STEALTHNET","AIMINI","SIP","TRUPHONE","ICMPV6","DHCPV6","ARMAGETRON",\ 51 | "CROSSFIRE","DOFUS","FIESTA","FLORENSIA","GUILDWARS","HTTP_APPLICATION_ACTIVESYNC","KERBEROS","LDAP","MAPLESTORY","MSSQL_TDS",\ 52 | "PPTP","WARCRAFT3","WORLD_OF_KUNG_FU","SLACK","FACEBOOK","TWITTER","DROPBOX","GMAIL","GOOGLE_MAPS","YOUTUBE","SKYPE","GOOGLE",\ 53 | "DCERPC","NETFLOW","SFLOW","HTTP_CONNECT","HTTP_PROXY","CITRIX","NETFLIX","LASTFM","WAZE",\ 54 | "SKYFILE_PREPAID","SKYFILE_RUDICS","SKYFILE_POSTPAID","CITRIX_ONLINE","APPLE","WEBEX","WHATSAPP","APPLE_ICLOUD","VIBER",\ 55 | "APPLE_ITUNES","RADIUS","WINDOWS_UPDATE","TEAMVIEWER","TUENTI","LOTUS_NOTES","SAP","GTP","UPNP","LLMNR","REMOTE_SCAN","SPOTIFY",\ 56 | "WEBM","H323","OPENVPN","NOE","CISCOVPN","TEAMSPEAK","TOR","SKINNY","RTCP","RSYNC","ORACLE","CORBA","UBUNTUONE","WHOIS_DAS",\ 57 | "COLLECTD","SOCKS","MS_LYNC","RTMP","FTP_DATA","WIKIPEDIA","ZMQ","AMAZON","EBAY","CNN","MEGACO","REDIS","PANDO","VHUA","TELEGRAM",\ 58 | "VEVO","PANDORA","QUIC","WHATSAPP_VOICE","EAQ","GIT","DRDA","KAKAOTALK","KAKAOTALK_VOICE","TWITCH","QUICKPLAY","OPENDNS",\ 59 | "MPEGTS","SNAPCHAT","DEEZER","INSTAGRAM","MICROSOFT","HOTSPOT_SHIELD","OCS","OFFICE_365","CLOUDFLARE","MS_ONE_DRIVE","MQTT",\ 60 | "RX","SINA","STARCRAFT","TEREDO","HEP","HANGOUT","CHECK" 61 | #endif 62 | 63 | #ifndef NDPI_PROTOCOL_SHORT_STRING 64 | #define NDPI_PROTOCOL_SHORT_STRING "unknown","ftp","pop","smtp","imap","dns","ipp","http","mdns","ntp",\ 65 | "netbios","nfs","ssdp","bgp","snmp","xdmcp","smb","syslog","dhcp","postgres","mysql","hotmail","directdownload","pops",\ 66 | "applejuice","directconnect","socrates","coap","vmware","smtps",\ 67 | "filetopia","ubntac2","kontiki","openft","fasttrack","gnutella","edonkey","bittorrent",\ 68 | "epp","avi","flash","ogg","mpeg","quicktime","realmedia","windowsmedia","mms","xbox","qq","move","rtsp","imaps","icecast",\ 69 | "pplive","ppstream","zattoo","shoutcast","sopcast","tvants","tvuplayer","http_download","qqlive","thunder","soulseek",\ 70 | "ssl_no_cert","irc","ayiya","unencryped_jabber","msn","oscar","yahoo","battlefield","quake","vrrp","steam","halflife2",\ 71 | "worldofwarcraft","telnet","stun","ipsec","gre","icmp","igmp","egp","sctp","ospf","ipip","rtp","rdp","vnc","pcanywhere",\ 72 | "ssl","ssh","usenet","mgcp","iax","tftp","afp","stealthnet","aimini","sip","truphone","icmpv6","dhcpv6","armagetron",\ 73 | "crossfire","dofus","fiesta","florensia","guildwars","http_application_activesync","kerberos","ldap","maplestory","mssql",\ 74 | "pptp","warcraft3","world_of_kung_fu","slack","facebook","twitter","dropbox","gmail","google_maps","youtube","skype","google",\ 75 | "dcerpc","netflow","sflow","http_connect","http_proxy","citrix","netflix","lastfm","waze",\ 76 | "skyfile_prepaid","skyfile_rudics","skyfile_postpaid","citrix_online","apple","webex","whatsapp","apple_icloud","viber",\ 77 | "apple_itunes","radius","windows_update","teamviewer","tuenti","lotusnotes","sap","gtp","upnp","llmnr","remotescan","spotify",\ 78 | "webm","h323","openvpn","noe","ciscovpn","teamspeak","tor","skinny","rtcp","rsync","oracle","corba","ubuntuone","whois_das",\ 79 | "collectd","socks","ms_lync","rtmp","ftpdata","wikipedia","zmq","amazon","ebay","cnn","megaco","redis","pando","vhua","telegram",\ 80 | "vevo","pandora","quic","whatsapp_voice","eaq","git","drda","kakaotalk","kakaotalk_voice","twitch","quickplay","opendns",\ 81 | "mpegts","snapchat","deezer","instagram","microsoft","hotspot_shield","ocs","office_365","cloudflare","ms_one_drive","mqtt",\ 82 | "rx","sina","starcraft","teredo","hep","hangout","dpi_check" 83 | #endif 84 | 85 | #ifndef NDPI_LAST_NFPROTO 86 | #define NDPI_LAST_NFPROTO NDPI_LAST_IMPLEMENTED_PROTOCOL + 1 87 | #endif 88 | 89 | #endif /* _LINUX_NETFILTER_XT_NDPI_H */ 90 | --------------------------------------------------------------------------------