netsniff-ng-0.5.7/0000775000175000017500000000000011773367375014116 5ustar bordaniebordanienetsniff-ng-0.5.7/src/0000775000175000017500000000000011773367375014705 5ustar bordaniebordanienetsniff-ng-0.5.7/scripts/0000775000175000017500000000000011773367375015605 5ustar bordaniebordanienetsniff-ng-0.5.7/contrib/0000775000175000017500000000000011773367375015556 5ustar bordaniebordanienetsniff-ng-0.5.7/Documentation/0000775000175000017500000000000011773367375016727 5ustar bordaniebordanienetsniff-ng-0.5.7/src/trafgen/0000775000175000017500000000000011773367375016333 5ustar bordaniebordanienetsniff-ng-0.5.7/src/test/0000775000175000017500000000000011773367375015664 5ustar bordaniebordanienetsniff-ng-0.5.7/src/netsniff-ng/0000775000175000017500000000000011773367375017123 5ustar bordaniebordanienetsniff-ng-0.5.7/src/ifpps/0000775000175000017500000000000011773367375016026 5ustar bordaniebordanienetsniff-ng-0.5.7/src/flowtop/0000775000175000017500000000000011773367375016377 5ustar bordaniebordanienetsniff-ng-0.5.7/src/examples/0000775000175000017500000000000011773367375016523 5ustar bordaniebordanienetsniff-ng-0.5.7/src/curvetun/0000775000175000017500000000000011773367375016560 5ustar bordaniebordanienetsniff-ng-0.5.7/src/conf/0000775000175000017500000000000011773367375015632 5ustar bordaniebordanienetsniff-ng-0.5.7/src/cmake/0000775000175000017500000000000011773367375015765 5ustar bordaniebordanienetsniff-ng-0.5.7/src/bpfc/0000775000175000017500000000000011773367375015617 5ustar bordaniebordanienetsniff-ng-0.5.7/src/ashunt/0000775000175000017500000000000011773367375016207 5ustar bordaniebordanienetsniff-ng-0.5.7/contrib/patches/0000775000175000017500000000000011773367375017205 5ustar bordaniebordanienetsniff-ng-0.5.7/contrib/nacl/0000775000175000017500000000000011773367375016473 5ustar bordaniebordanienetsniff-ng-0.5.7/contrib/html/0000775000175000017500000000000011773367375016522 5ustar bordaniebordanienetsniff-ng-0.5.7/contrib/art/0000775000175000017500000000000011773367375016344 5ustar bordaniebordanienetsniff-ng-0.5.7/Documentation/RelNotes/0000775000175000017500000000000011773367375020462 5ustar bordaniebordanienetsniff-ng-0.5.7/src/examples/trafgen/0000775000175000017500000000000011773367375020151 5ustar bordaniebordanienetsniff-ng-0.5.7/src/examples/pcap/0000775000175000017500000000000011773367375017446 5ustar bordaniebordanienetsniff-ng-0.5.7/src/examples/bpfc/0000775000175000017500000000000011773367375017435 5ustar bordaniebordanienetsniff-ng-0.5.7/src/cmake/modules/0000775000175000017500000000000011773367375017435 5ustar bordaniebordanienetsniff-ng-0.5.7/contrib/html/img/0000775000175000017500000000000011773367375017276 5ustar bordaniebordanienetsniff-ng-0.5.7/src/examples/pcap/ipv6_hdr_ext/0000775000175000017500000000000011773367375022047 5ustar bordaniebordanienetsniff-ng-0.5.7/src/examples/pcap/icmpv6/0000775000175000017500000000000011773367375020652 5ustar bordaniebordanienetsniff-ng-0.5.7/src/examples/pcap/802.1ad/0000775000175000017500000000000011773367375020423 5ustar bordaniebordanienetsniff-ng-0.5.7/src/examples/pcap/802.11/0000775000175000017500000000000011773367375020177 5ustar bordaniebordanienetsniff-ng-0.5.7/src/examples/bpfc/opcodes/0000775000175000017500000000000011773367375021071 5ustar bordaniebordanienetsniff-ng-0.5.7/src/examples/bpfc/high-level/0000775000175000017500000000000011773367375021461 5ustar bordaniebordanienetsniff-ng-0.5.7/VERSION0000664000175000017500000000000611773367375015162 0ustar bordaniebordanie0.5.7 netsniff-ng-0.5.7/REPORTING-BUGS0000664000175000017500000000033311773367375016147 0ustar bordaniebordanieFor reporting bugs, either send a mail to one of the following email addresses , or visit our bug-tracker, which is reachable via: http://bugs.netsniff-ng.org/ netsniff-ng-0.5.7/README0000664000175000017500000000613711773367375015005 0ustar bordaniebordanie////////////////////////////////////////////////////////////////////////////// netsniff-ng - the packet sniffing beast \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ . . /( )\ .' {______} '. \ ^, ,^ / netsniff-ng is a free, performant |'O\ /O'| _.<0101011>-- Linux network analyzer and > `' '` < / networking toolkit. ) ,.==., ( | (|/--~~--\|)-' Release: 2012-06-29 / ( ___ Web: http://netsniff-ng.org \__.=|___E The gain of performance is reached by zero-copy mechanisms, so that on packet reception and transmission the kernel does not need to copy packets from kernel space to user space and vice versa. For this purpose, the netsniff-ng toolkit [1] is libpcap independent, but nevertheless supports the pcap file format for capturing, replaying and performing offline-analysis of pcap dumps. Furthermore, we are focussing on building a robust and clean analyzer and utilities that complete netsniff-ng as a support for network development, debugging or network reconnaissance. (Note: libpcap starting from 1.0.0 now also supports zero-copy, but for capturing only) The netsniff-ng toolkit currently consists of the following utilities: * netsniff-ng: a zero-copy analyzer, pcap capturing and replaying tool * trafgen: a high performance zero-copy network packet generator * ifpps: a top-like kernel networking and system statistics tool * curvetun: a lightweight curve25519-based multiuser IP tunnel * ashunt: an autonomous system trace route and ISP testing utility * flowtop: a top-like netfilter connection tracking tool * bpfc: a tiny Berkeley Packet Filter compiler supporting Linux extensions Have a look at the Documentation/ folder for further information. The netsniff-ng toolkit is an Open Source project covered by the GNU General Public License. For any questions or feedback about netsniff-ng you are welcome to leave us a message to or to our mailing list at (Note: you have to register first). This project is purely non-commercial and will always stay that way! The current project status can be considered as "working". In general, all tools have been tested by us to a great extend including their command-line options. In fact, many of our tools are used in production systems. However, we give no guarantee that our tools are free of bugs! If you spot some issues, contact us as described in REPORTING-BUGS. Also, have a look at our FAQ [2] for answering your questions. Furthermore, we have a development blog [3] where we sometimes drop some interesting things or news for the outside world! A public repository of the old stable releases can be found here [4]. Happy packet hacking! [1] http://netsniff-ng.org/ [2] http://netsniff-ng.org/faq.html [3] http://dev.netsniff-ng.org/ [4] http://pub.netsniff-ng.org/ netsniff-ng-0.5.7/INSTALL0000664000175000017500000000712111773367375015150 0ustar bordaniebordanieCurrently only operating systems running on Linux kernels with CONFIG_PACKET_MMAP enabled. This feature can be found even back to the days of 2.4 kernels. Most operating systems ship pre-compiled kernels that have this config option enabled and even the latest kernel versions got rid of this option and have this functionality already built-in. However, we recommend a kernel >= 2.6.31, because the TX_RING is officially integrated since then. netsniff-ng has been successfully tested on x86 and x86_64. Please drop us a short mail, if it runs successfully on hardware other than that. What libraries / tools are required? - glibc (all) - cmake (all) - libpthread (curvetun, netsniff-ng, flowtop) - libncurses (ifpps, flowtop) - libGeoIP and its database (ashunt, flowtop) - flex, bison (bpfc, trafgen) - ntpd [or equivalent] (curvetun) - libnacl (curvetun) - libnetfilter-conntrack (flowtop) - liburcu (flowtop) - libcli (trafgen) - libnl (netsniff-ng, trafgen) It is common, that these libraries are shipped as distribution packages for an easy installation. We try to keep this as minimal as possible. For downloading the latest GeoIP database, you can use the script that is located at scripts/geoip-database-update. The installation process done by cmake is fairly simple: $ cd netsniff-ng/src/ $ mkdir build $ cd build $ cmake .. $ make # make install Man pages are generated out of the corresponding source files by cmake. They are written in POD format as a C header comment within those files. For this, you need the tool pod2man which is distributed with Perl and should therefore be available on most systems. To uninstall, simply remove all files refered in install_manifest.txt For bpfc, we also have a Vim syntax highlighting file. Have a look at scripts/bpf.vim for installation instructions. In order to build curvetun, libnacl must be built first. A helper script called build_nacl.sh is there to facilitate this process. If you want to build NaCl in the directory ~/nacl, the script should be called this way: $ cd src/curvetun $ ./build_nacl.sh ~/nacl This gives an initial output such as "Building NaCl for arch amd64 on host fuuubar (grab a coffee, this takes a while) ...". If the automatically detected architecture (such as amd64) is not the one you intend to compile for, then edit the (cc="gcc") variable within the build_nacl.sh script to your cross compiler. If NaCl already has been built on the target, it is quicker to use nacl_path.sh this way: $ cd src/curvetun $ ./nacl_path.sh ~/nacl/build/include/x86 ~/nacl/build/lib/x86 When done, netsniff-ng build infrastructure will read nacl_path.cmake to get the needed paths to NaCl. For using TUN/TAP devices as a user, e.g. create a file called src/50-tuntap.rules in /etc/udev/rules.d/ with: KERNEL=="tun", NAME="net/%k", GROUP="netdev", MODE="0660", OPTIONS+="ignore_remove" and restart the udev daemon. Add yourself to the "netdev" group. NOTES If you are a package distribution maintainer, have a look at the patch set under contrib/patches which makes packaging a little easier for you. The following warnings can be seen when compiling bpfc with flex 2.5.35 and bison 2.4.1: - redundant redeclaration of ‘isatty’ - cannot optimize loop, the loop counter may overflow Those two warnings occur on generated C code produced by flex and bison and there is no possibility on our side to fix them. Similar to that, gcc will throw a warning on strchr(3) which is a false positive (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36513) from glibc: - warning: logical ‘&&’ with non-zero constant will always evaluate as true netsniff-ng-0.5.7/COPYING0000664000175000017500000004405411773367375015160 0ustar bordaniebordanie Note that the only valid version of the GPL as far as this project is concerned is _this_ particular version of the license (i.e. v2, not v2.2 or v3.x or whatever), unless explicitly otherwise stated. Daniel Borkmann ----------------------------------------------------------------------------- Copyright (C) 2009-2012 Daniel Borkmann, Emmanuel Roullit and contributors GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. netsniff-ng-0.5.7/AUTHORS0000664000175000017500000000025011773367375015163 0ustar bordaniebordanieDaniel Borkmann Emmanuel Roullit Markus Amend Christoph Jaeger netsniff-ng-0.5.7/.mailmap0000664000175000017500000000137011773367375015540 0ustar bordaniebordanie# # This list is used by git-shortlog to fix a few botched name translations # in the git archive, either because the author's full name was messed up # and/or not always written the same way, making contributions from the # same person appearing not to be so. # Daniel Borkmann Daniel Borkmann Daniel Borkmann Daniel Borkmann Daniel Borkmann root Emmanuel Roullit Emmanuel Roullit Markus Amend Christoph Jaeger Christoph Jaeger Stefan Seering netsniff-ng-0.5.7/.gitignore0000664000175000017500000000113211773367375016103 0ustar bordaniebordanie# Editor crap (emacs, vim, ...) *.swp *.orig \#*\# .\#* .*.sw[a-z] *.un~ # Hidden files, general things .* *~ # Compiled object files *.slo *.lo *.o # Compiled dynamic libraries *.so # Compiled static libraries *.lai *.la *.a # Build and testing folders src/build/ src/test/fuzzing/ # LaTeX documentation files *.acn *.acr *.alg *.aux *.bbl *.blg *.dvi *.fdb_latexmk *.glg *.glo *.gls *.idx *.ilg *.ind *.ist *.lof *.log *.lot *.maf *.mtc *.mtc0 *.nav *.nlo *.out *.pdfsync *.ps *.snm *.synctex.gz *.toc *.vrb *.xdy # Other documentation ignores *.md *.ps # Excluded from ignorance !.gitignore netsniff-ng-0.5.7/.gitattributes0000664000175000017500000000015111773367375017006 0ustar bordaniebordanie* whitespace=!indent,trail,space *.[ch] whitespace=indent,trail,space *.sh whitespace=indent,trail,space netsniff-ng-0.5.7/src/xutils.h0000664000175000017500000001113311773367375016405 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Copyright 2009, 2010 Emmanuel Roullit. * Subject to the GPL, version 2. */ #ifndef XSYS_H #define XSYS_H #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include "die.h" #include "built_in.h" extern int af_socket(int af); extern int pf_socket(void); extern int wireless_bitrate(const char *ifname); extern int adjust_dbm_level(int in_dbm, int dbm_val); extern int wireless_sigqual(const char *ifname, struct iw_statistics *stats); extern int wireless_rangemax_sigqual(const char *ifname); extern int ethtool_bitrate(const char *ifname); extern int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf); extern int device_bitrate(const char *ifname); extern int device_mtu(const char *ifname); extern int device_address(const char *ifname, int af, struct sockaddr_storage *ss); extern int device_irq_number(const char *ifname); extern int device_bind_irq_to_cpu(int irq, int cpu); extern void sock_print_net_stats(int sock, unsigned long skipped); extern int device_ifindex(const char *ifname); extern short device_get_flags(const char *ifname); extern void device_set_flags(const char *ifname, const short flags); extern int set_nonblocking(int fd); extern int set_nonblocking_sloppy(int fd); extern int set_reuseaddr(int fd); extern void set_tcp_cork(int fd); extern void set_tcp_uncork(int fd); extern void set_udp_cork(int fd); extern void set_udp_uncork(int fd); extern void set_sock_cork(int fd, int udp); extern void set_sock_uncork(int fd, int udp); extern void set_tcp_nodelay(int fd); extern void set_socket_keepalive(int fd); extern int set_ipv6_only(int fd); extern void set_mtu_disc_dont(int fd); extern void register_signal(int signal, void (*handler)(int)); extern void register_signal_f(int signal, void (*handler)(int), int flags); extern int get_tty_size(void); extern void check_for_root_maybe_die(void); extern short enter_promiscuous_mode(char *ifname); extern void leave_promiscuous_mode(char *ifname, short oldflags); extern int device_up(char *ifname); extern int device_running(char *ifname); extern int device_up_and_running(char *ifname); extern int poll_error_maybe_die(int sock, struct pollfd *pfd); extern void set_epoll_descriptor(int fd_epoll, int action, int fd_toadd, int events); extern int set_epoll_descriptor2(int fd_epoll, int action, int fd_toadd, int events); extern int set_cpu_affinity(char *str, int inverted); extern int set_proc_prio(int prio); extern int set_sched_status(int policy, int priority); extern void ioprio_print(void); extern void set_ioprio_rt(void); extern void set_ioprio_be(void); extern void xusleep(const struct timespec *ts_delay); extern void xusleep2(long usecs); extern int xnanosleep(double seconds); extern int set_timeout(struct timeval *timeval, unsigned int msec); extern size_t strlcpy(char *dest, const char *src, size_t size); extern int slprintf(char *dst, size_t size, const char *fmt, ...); extern noinline void *xmemset(void *s, int c, size_t n); extern char *getuint(char *in, uint32_t *out); extern char *strtrim_right(register char *p, register char c); extern char *strtrim_left(register char *p, register char c); static inline int get_default_sched_policy(void) { return SCHED_FIFO; } static inline int get_default_sched_prio(void) { return sched_get_priority_max(get_default_sched_policy()); } static inline int get_number_cpus(void) { return sysconf(_SC_NPROCESSORS_CONF); } static inline int get_number_cpus_online(void) { return sysconf(_SC_NPROCESSORS_ONLN); } static inline int get_default_proc_prio(void) { return -20; } static inline struct timeval tv_subtract(struct timeval time1, struct timeval time2) { /* time1 - time2 */ struct timeval result; if ((time1.tv_sec < time2.tv_sec) || ((time1.tv_sec == time2.tv_sec) && (time1.tv_usec <= time2.tv_usec))) { result.tv_sec = result.tv_usec = 0; } else { result.tv_sec = time1.tv_sec - time2.tv_sec; if (time1.tv_usec < time2.tv_usec) { result.tv_usec = time1.tv_usec + 1000000L - time2.tv_usec; result.tv_sec--; } else { result.tv_usec = time1.tv_usec - time2.tv_usec; } } return result; } static inline char *skips(char *p) { return strtrim_left(p, ' '); } static inline char *skipchar(char *in, char c) { if (*in != c) panic("Syntax error!\n"); return ++in; } #endif /* XSYS_H */ netsniff-ng-0.5.7/src/xutils.c0000664000175000017500000004403011773367375016402 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Copyright 2009, 2010 Emmanuel Roullit. * Copyright 2010 Marek Polacek. * Subject to the GPL, version 2. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Kernel < 2.6.26 */ #include #include #include /* Kernel < 2.6.26 */ #include #include #include #include #include #include "die.h" #include "xutils.h" #include "ring.h" #include "tprintf.h" #include "built_in.h" #define IOPRIO_CLASS_SHIFT 13 enum { ioprio_class_none, ioprio_class_rt, ioprio_class_be, ioprio_class_idle, }; enum { ioprio_who_process = 1, ioprio_who_pgrp, ioprio_who_user, }; static const char *const to_prio[] = { "none", "realtime", "best-effort", "idle", }; int af_socket(int af) { int sock; if (unlikely(af != AF_INET && af != AF_INET6)) { whine("Wrong AF socket type! Falling back to AF_INET\n"); af = AF_INET; } sock = socket(af, SOCK_DGRAM, 0); if (unlikely(sock < 0)) panic("Creation AF socket failed!\n"); return sock; } int pf_socket(void) { int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (unlikely(sock < 0)) panic("Creation of PF socket failed!\n"); return sock; } void set_udp_cork(int fd) { int state = 1; setsockopt(fd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state)); } void set_udp_uncork(int fd) { int state = 0; setsockopt(fd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state)); } void set_tcp_cork(int fd) { int state = 1; setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state)); } void set_tcp_uncork(int fd) { int state = 0; setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state)); } void set_sock_cork(int fd, int udp) { if (!!udp) set_udp_cork(fd); else set_tcp_cork(fd); } void set_sock_uncork(int fd, int udp) { if (!!udp) set_udp_uncork(fd); else set_tcp_uncork(fd); } int set_nonblocking(int fd) { int ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK); if (unlikely(ret < 0)) panic("Cannot fcntl!\n"); return 0; } int set_nonblocking_sloppy(int fd) { return fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK); } void set_socket_keepalive(int fd) { int one = 1; setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one)); } void set_tcp_nodelay(int fd) { int one = 1; setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); } int set_ipv6_only(int fd) { int one = 1; return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); } int set_reuseaddr(int fd) { int ret, one = 1; ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (one)); if (unlikely(ret < 0)) panic("Cannot reuse addr!\n"); return 0; } void set_mtu_disc_dont(int fd) { int mtu = IP_PMTUDISC_DONT; setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu)); } void set_epoll_descriptor(int fd_epoll, int action, int fd_toadd, int events) { int ret; struct epoll_event ev; memset(&ev, 0, sizeof(ev)); ev.events = events; ev.data.fd = fd_toadd; ret = epoll_ctl(fd_epoll, action, fd_toadd, &ev); if (ret < 0) panic("Cannot add socket for epoll!\n"); } int set_epoll_descriptor2(int fd_epoll, int action, int fd_toadd, int events) { struct epoll_event ev; memset(&ev, 0, sizeof(ev)); ev.events = events; ev.data.fd = fd_toadd; return epoll_ctl(fd_epoll, action, fd_toadd, &ev); } int wireless_bitrate(const char *ifname) { int sock, ret, rate_in_mbit; struct iwreq iwr; sock = af_socket(AF_INET); memset(&iwr, 0, sizeof(iwr)); strlcpy(iwr.ifr_name, ifname, IFNAMSIZ); ret = ioctl(sock, SIOCGIWRATE, &iwr); if (!ret) rate_in_mbit = iwr.u.bitrate.value / 1000000; else rate_in_mbit = 0; close(sock); return rate_in_mbit; } int adjust_dbm_level(int in_dbm, int dbm_val) { if (!in_dbm) return dbm_val; return dbm_val - 0x100; } int wireless_sigqual(const char *ifname, struct iw_statistics *stats) { int ret, sock; struct iwreq iwr; sock = af_socket(AF_INET); memset(&iwr, 0, sizeof(iwr)); strlcpy(iwr.ifr_name, ifname, IFNAMSIZ); iwr.u.data.pointer = (caddr_t) stats; iwr.u.data.length = sizeof(*stats); iwr.u.data.flags = 1; ret = ioctl(sock, SIOCGIWSTATS, &iwr); close(sock); return ret; } int wireless_rangemax_sigqual(const char *ifname) { int ret, sock, sigqual; struct iwreq iwr; struct iw_range iwrange; sock = af_socket(AF_INET); memset(&iwrange, 0, sizeof(iwrange)); memset(&iwr, 0, sizeof(iwr)); strlcpy(iwr.ifr_name, ifname, IFNAMSIZ); iwr.u.data.pointer = (caddr_t) &iwrange; iwr.u.data.length = sizeof(iwrange); iwr.u.data.flags = 0; ret = ioctl(sock, SIOCGIWRANGE, &iwr); if (!ret) sigqual = iwrange.max_qual.qual; else sigqual = 0; close(sock); return sigqual; } int ethtool_bitrate(const char *ifname) { int ret, sock, bitrate; struct ifreq ifr; struct ethtool_cmd ecmd; sock = af_socket(AF_INET); memset(&ecmd, 0, sizeof(ecmd)); memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); ecmd.cmd = ETHTOOL_GSET; ifr.ifr_data = (char *) &ecmd; ret = ioctl(sock, SIOCETHTOOL, &ifr); if (ret) { bitrate = 0; goto out; } switch (ecmd.speed) { case SPEED_10: case SPEED_100: case SPEED_1000: case SPEED_10000: bitrate = ecmd.speed; break; default: bitrate = 0; break; }; out: close(sock); return bitrate; } int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf) { int ret, sock; struct ifreq ifr; sock = af_socket(AF_INET); memset(drvinf, 0, sizeof(*drvinf)); memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); drvinf->cmd = ETHTOOL_GDRVINFO; ifr.ifr_data = (char *) drvinf; ret = ioctl(sock, SIOCETHTOOL, &ifr); close(sock); return ret; } int device_bitrate(const char *ifname) { int speed_c, speed_w; speed_c = ethtool_bitrate(ifname); speed_w = wireless_bitrate(ifname); return (speed_c == 0 ? speed_w : speed_c); } int device_ifindex(const char *ifname) { int ret, sock, index; struct ifreq ifr; if (!strncmp("any", ifname, strlen("any"))) return 0; sock = af_socket(AF_INET); memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); ret = ioctl(sock, SIOCGIFINDEX, &ifr); if (!ret) index = ifr.ifr_ifindex; else index = -1; close(sock); return index; } int device_address(const char *ifname, int af, struct sockaddr_storage *ss) { int ret, sock; struct ifreq ifr; if (!ss) return -EINVAL; if (!strncmp("any", ifname, strlen("any"))) return -EINVAL; sock = af_socket(af); memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); ifr.ifr_addr.sa_family = af; ret = ioctl(sock, SIOCGIFADDR, &ifr); if (!ret) memcpy(ss, &ifr.ifr_addr, sizeof(ifr.ifr_addr)); close(sock); return ret; } int device_mtu(const char *ifname) { int ret, sock, mtu; struct ifreq ifr; sock = af_socket(AF_INET); memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); ret = ioctl(sock, SIOCGIFMTU, &ifr); if (!ret) mtu = ifr.ifr_mtu; else mtu = 0; close(sock); return mtu; } short device_get_flags(const char *ifname) { /* Really, it's short! Look at struct ifreq */ short flags; int ret, sock; struct ifreq ifr; sock = af_socket(AF_INET); memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); ret = ioctl(sock, SIOCGIFFLAGS, &ifr); if (!ret) flags = ifr.ifr_flags; else flags = 0; close(sock); return flags; } void device_set_flags(const char *ifname, const short flags) { int ret, sock; struct ifreq ifr; sock = af_socket(AF_INET); memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); ifr.ifr_flags = flags; ret = ioctl(sock, SIOCSIFFLAGS, &ifr); if (ret < 0) panic("Cannot set NIC flags!\n"); close(sock); } int device_irq_number(const char *ifname) { /* * Since fetching IRQ numbers from SIOCGIFMAP is deprecated and not * supported anymore, we need to grab them from procfs */ int irq = 0; char *buffp; char buff[512]; char sysname[512]; if (!strncmp("lo", ifname, strlen("lo"))) return 0; FILE *fp = fopen("/proc/interrupts", "r"); if (!fp) { whine("Cannot open /proc/interrupts!\n"); return -ENOENT; } memset(buff, 0, sizeof(buff)); while (fgets(buff, sizeof(buff), fp) != NULL) { buff[sizeof(buff) - 1] = 0; if (strstr(buff, ifname) == NULL) continue; buffp = buff; while (*buffp != ':') buffp++; *buffp = 0; irq = atoi(buff); memset(buff, 0, sizeof(buff)); } fclose(fp); if (irq != 0) return irq; /* * Try sysfs as fallback. Probably wireless devices will be found * here. We return silently if it fails ... */ slprintf(sysname, sizeof(sysname), "/sys/class/net/%s/device/irq", ifname); fp = fopen(sysname, "r"); if (!fp) return -ENOENT; memset(buff, 0, sizeof(buff)); if(fgets(buff, sizeof(buff), fp) != NULL) { buff[sizeof(buff) - 1] = 0; irq = atoi(buff); } fclose(fp); return irq; } int device_bind_irq_to_cpu(int irq, int cpu) { int ret; char buff[256]; char file[256]; /* Note: first CPU begins with CPU 0 */ if (irq < 0 || cpu < 0) return -EINVAL; memset(file, 0, sizeof(file)); memset(buff, 0, sizeof(buff)); /* smp_affinity starts counting with CPU 1, 2, ... */ cpu = cpu + 1; sprintf(file, "/proc/irq/%d/smp_affinity", irq); FILE *fp = fopen(file, "w"); if (!fp) { whine("Cannot open file %s!\n", file); return -ENOENT; } sprintf(buff, "%d", cpu); ret = fwrite(buff, sizeof(buff), 1, fp); fclose(fp); return (ret > 0 ? 0 : ret); } void sock_print_net_stats(int sock, unsigned long skipped) { int ret; struct tpacket_stats kstats; socklen_t slen = sizeof(kstats); memset(&kstats, 0, sizeof(kstats)); ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen); if (ret > -1) { printf("\r%12ld frames incoming\n", 1UL * kstats.tp_packets); printf("\r%12ld frames passed filter\n", 1UL * kstats.tp_packets - kstats.tp_drops - skipped); printf("\r%12ld frames failed filter (out of space)\n", 1UL * kstats.tp_drops + skipped); if (kstats.tp_packets > 0) printf("\r%12.4f%% frame droprate\n", 1.f * kstats.tp_drops / kstats.tp_packets * 100.f); } } void register_signal(int signal, void (*handler)(int)) { sigset_t block_mask; struct sigaction saction; sigfillset(&block_mask); saction.sa_handler = handler; saction.sa_mask = block_mask; saction.sa_flags = SA_RESTART; sigaction(signal, &saction, NULL); } void register_signal_f(int signal, void (*handler)(int), int flags) { sigset_t block_mask; struct sigaction saction; sigfillset(&block_mask); saction.sa_handler = handler; saction.sa_mask = block_mask; saction.sa_flags = flags; sigaction(signal, &saction, NULL); } int get_tty_size(void) { #ifdef TIOCGSIZE struct ttysize ts = {0}; int ret = ioctl(0, TIOCGSIZE, &ts); return (ret == 0 ? ts.ts_cols : DEFAULT_TTY_SIZE); #elif defined(TIOCGWINSZ) struct winsize ts; memset(&ts, 0, sizeof(ts)); int ret = ioctl(0, TIOCGWINSZ, &ts); return (ret == 0 ? ts.ws_col : DEFAULT_TTY_SIZE); #else return DEFAULT_TTY_SIZE; #endif } void check_for_root_maybe_die(void) { if (geteuid() != 0 || geteuid() != getuid()) panic("Uhhuh, not root?!\n"); } short enter_promiscuous_mode(char *ifname) { short ifflags; if (!strncmp("any", ifname, strlen("any"))) return 0; ifflags = device_get_flags(ifname); device_set_flags(ifname, ifflags | IFF_PROMISC); return ifflags; } void leave_promiscuous_mode(char *ifname, short oldflags) { if (!strncmp("any", ifname, strlen("any"))) return; device_set_flags(ifname, oldflags); } int device_up(char *ifname) { if (!ifname) return -EINVAL; if (!strncmp("any", ifname, strlen("any"))) return 1; return (device_get_flags(ifname) & IFF_UP) == IFF_UP; } int device_running(char *ifname) { if (!ifname) return -EINVAL; if (!strncmp("any", ifname, strlen("any"))) return 1; return (device_get_flags(ifname) & IFF_RUNNING) == IFF_RUNNING; } int device_up_and_running(char *ifname) { if (!ifname) return -EINVAL; if (!strncmp("any", ifname, strlen("any"))) return 1; return (device_get_flags(ifname) & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING); } int poll_error_maybe_die(int sock, struct pollfd *pfd) { if ((pfd->revents & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL)) == 0) return POLL_NEXT_PKT; if (pfd->revents & (POLLHUP | POLLRDHUP)) panic("Hangup on socket occured!\n"); if (pfd->revents & POLLERR) { int tmp; errno = 0; if (recv(sock, &tmp, sizeof(tmp), MSG_PEEK) >= 0) return POLL_NEXT_PKT; if (errno == ENETDOWN) panic("Interface went down!\n"); return POLL_MOVE_OUT; } if (pfd->revents & POLLNVAL) { whine("Invalid polling request on socket!\n"); return POLL_MOVE_OUT; } return POLL_NEXT_PKT; } static inline char *next_token(char *q, int sep) { if (q) q = strchr(q, sep); /* * glibc defines this as a macro and gcc throws a false * positive ``logical ‘&&’ with non-zero constant will * always evaluate as true'' in older versions. See: * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36513 */ if (q) q++; return q; } int set_cpu_affinity(char *str, int inverted) { int ret, i, cpus; char *p, *q; cpu_set_t cpu_bitmask; q = str; cpus = get_number_cpus(); CPU_ZERO(&cpu_bitmask); for (i = 0; inverted && i < cpus; ++i) CPU_SET(i, &cpu_bitmask); while (p = q, q = next_token(q, ','), p) { unsigned int a; /* Beginning of range */ unsigned int b; /* End of range */ unsigned int s; /* Stride */ char *c1, *c2; if (sscanf(p, "%u", &a) < 1) return -EINVAL; b = a; s = 1; c1 = next_token(p, '-'); c2 = next_token(p, ','); if (c1 != NULL && (c2 == NULL || c1 < c2)) { if (sscanf(c1, "%u", &b) < 1) return -EINVAL; c1 = next_token(c1, ':'); if (c1 != NULL && (c2 == NULL || c1 < c2)) if (sscanf(c1, "%u", &s) < 1) return -EINVAL; } if (!(a <= b)) return -EINVAL; while (a <= b) { if (inverted) CPU_CLR(a, &cpu_bitmask); else CPU_SET(a, &cpu_bitmask); a += s; } } ret = sched_setaffinity(getpid(), sizeof(cpu_bitmask), &cpu_bitmask); if (ret) panic("Can't set this cpu affinity!\n"); return 0; } int set_proc_prio(int priority) { /* * setpriority() is clever, even if you put a nice value which * is out of range it corrects it to the closest valid nice value */ int ret = setpriority(PRIO_PROCESS, getpid(), priority); if (ret) panic("Can't set nice val to %i!\n", priority); return 0; } int set_sched_status(int policy, int priority) { int ret, min_prio, max_prio; struct sched_param sp; max_prio = sched_get_priority_max(policy); min_prio = sched_get_priority_min(policy); if (max_prio == -1 || min_prio == -1) whine("Cannot determine scheduler prio limits!\n"); else if (priority < min_prio) priority = min_prio; else if (priority > max_prio) priority = max_prio; memset(&sp, 0, sizeof(sp)); sp.sched_priority = priority; ret = sched_setscheduler(getpid(), policy, &sp); if (ret) { whine("Cannot set scheduler policy!\n"); return -EINVAL; } ret = sched_setparam(getpid(), &sp); if (ret) { whine("Cannot set scheduler prio!\n"); return -EINVAL; } return 0; } static inline int ioprio_set(int which, int who, int ioprio) { return syscall(SYS_ioprio_set, which, who, ioprio); } static inline int ioprio_get(int which, int who) { return syscall(SYS_ioprio_get, which, who); } static void ioprio_setpid(pid_t pid, int ioprio, int ioclass) { int ret = ioprio_set(ioprio_who_process, pid, ioprio | ioclass << IOPRIO_CLASS_SHIFT); if (ret < 0) panic("Failed to set io prio for pid!\n"); } void ioprio_print(void) { int ioprio = ioprio_get(ioprio_who_process, getpid()); if (ioprio < 0) panic("Failed to fetch io prio for pid!\n"); else { int ioclass = ioprio >> IOPRIO_CLASS_SHIFT; if (ioclass != ioprio_class_idle) { ioprio &= 0xff; printf("%s: prio %d\n", to_prio[ioclass], ioprio); } else printf("%s\n", to_prio[ioclass]); } } void set_ioprio_rt(void) { ioprio_setpid(getpid(), 4, ioprio_class_rt); } void set_ioprio_be(void) { ioprio_setpid(getpid(), 4, ioprio_class_be); } int set_timeout(struct timeval *timeval, unsigned int msec) { if (msec == 0) return -EINVAL; timeval->tv_sec = 0; timeval->tv_usec = 0; if (msec < 1000) { timeval->tv_usec = msec * 1000; return 0; } timeval->tv_sec = (long) (msec / 1000); timeval->tv_usec = (long) ((msec - (timeval->tv_sec * 1000)) * 1000); return 0; } size_t strlcpy(char *dest, const char *src, size_t size) { size_t ret = strlen(src); if (size) { size_t len = (ret >= size) ? size - 1 : ret; memcpy(dest, src, len); dest[len] = '\0'; } return ret; } int slprintf(char *dst, size_t size, const char *fmt, ...) { int ret; va_list ap; va_start(ap, fmt); ret = vsnprintf(dst, size, fmt, ap); dst[size - 1] = '\0'; va_end(ap); return ret; } noinline void *xmemset(void *s, int c, size_t n) { size_t i; uint8_t *ptr = s; for (i = 0; i < n; ++i) ptr[i] = (uint8_t) c; return ptr; } char *getuint(char *in, uint32_t *out) { char *pt = in, tmp; char *endptr = NULL; while (*in && (isdigit(*in) || isxdigit(*in) || *in == 'x')) in++; if (!*in) panic("Syntax error!\n"); errno = 0; tmp = *in; *in = 0; *out = strtoul(pt, &endptr, 0); if ((endptr != NULL && *endptr != '\0') || errno != 0) { panic("Syntax error!\n"); } *in = tmp; return in; } char *strtrim_right(register char *p, register char c) { register char *end; register int len; len = strlen(p); while (*p && len) { end = p + len - 1; if (c == *end) *end = 0; else break; len = strlen(p); } return p; } char *strtrim_left(register char *p, register char c) { register int len; len = strlen(p); while (*p && len--) { if (c == *p) p++; else break; } return p; } netsniff-ng-0.5.7/src/xmalloc.h0000664000175000017500000000212411773367375016514 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #ifndef XMALLOC_H #define XMALLOC_H #include #include "built_in.h" #include "die.h" extern __hidden void *xmalloc(size_t size); extern __hidden void *xzmalloc(size_t size); extern __hidden void *xmallocz(size_t size); extern __hidden void *xmalloc_aligned(size_t size, size_t alignment); extern __hidden void *xzmalloc_aligned(size_t size, size_t alignment); extern __hidden void *xmemdupz(const void *data, size_t len); extern __hidden void *xrealloc(void *ptr, size_t nmemb, size_t size); extern __hidden void xfree_func(void *ptr); extern __hidden char *xstrdup(const char *str); extern __hidden char *xstrndup(const char *str, size_t size); extern __hidden int xdup(int fd); #define xfree(ptr) \ do { \ if (unlikely((ptr) == NULL)) \ panic("xfree: NULL pointer given as argument\n"); \ free((ptr)); \ (ptr) = NULL; \ } while (0) #endif /* XMALLOC_H */ netsniff-ng-0.5.7/src/xmalloc.c0000664000175000017500000000524011773367375016511 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010, 2011, 2012 Daniel Borkmann. * Subject to the GPL, version 2. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "xmalloc.h" #include "xutils.h" #include "built_in.h" #include "die.h" __hidden void *xmalloc(size_t size) { void *ptr; if (unlikely(size == 0)) panic("xmalloc: zero size\n"); ptr = malloc(size); if (unlikely(ptr == NULL)) panic("xmalloc: out of memory (allocating %zu bytes)\n", size); return ptr; } __hidden void *xzmalloc(size_t size) { void *ptr = xmalloc(size); memset(ptr, 0, size); return ptr; } __hidden void *xmalloc_aligned(size_t size, size_t alignment) { int ret; void *ptr; if (unlikely(size == 0)) panic("xmalloc_aligned: zero size\n"); ret = posix_memalign(&ptr, alignment, size); if (unlikely(ret != 0)) panic("xmalloc_aligned: out of memory (allocating %zu " "bytes)\n", size); return ptr; } __hidden void *xzmalloc_aligned(size_t size, size_t alignment) { void *ptr = xmalloc_aligned(size, alignment); memset(ptr, 0, size); return ptr; } __hidden void *xmallocz(size_t size) { void *ptr; if (unlikely(size + 1 < size)) panic("xmallocz: data too large to fit into virtual " "memory space\n"); ptr = xmalloc(size + 1); ((char*) ptr)[size] = 0; return ptr; } __hidden void *xmemdupz(const void *data, size_t len) { return memcpy(xmallocz(len), data, len); } __hidden void *xrealloc(void *ptr, size_t nmemb, size_t size) { void *new_ptr; size_t new_size = nmemb * size; if (unlikely(new_size == 0)) panic("xrealloc: zero size\n"); if (unlikely(((size_t) ~0) / nmemb < size)) panic("xrealloc: nmemb * size > SIZE_T_MAX\n"); if (ptr == NULL) new_ptr = malloc(new_size); else new_ptr = realloc(ptr, new_size); if (unlikely(new_ptr == NULL)) panic("xrealloc: out of memory (new_size %zu bytes)\n", new_size); return new_ptr; } __hidden void xfree_func(void *ptr) { if (unlikely(ptr == NULL)) panic("xfree: NULL pointer given as argument\n"); free(ptr); } __hidden char *xstrdup(const char *str) { size_t len; char *cp; len = strlen(str) + 1; cp = xmalloc(len); strlcpy(cp, str, len); return cp; } __hidden char *xstrndup(const char *str, size_t size) { size_t len; char *cp; len = strlen(str) + 1; if (size < len) len = size; cp = xmalloc(len); strlcpy(cp, str, len); return cp; } __hidden int xdup(int fd) { int ret = dup(fd); if (unlikely(ret < 0)) panic("xdup: dup failed\n"); return ret; } netsniff-ng-0.5.7/src/xio.h0000664000175000017500000000140611773367375015656 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #ifndef XIO_H #define XIO_H extern int open_or_die(const char *file, int flags); extern int open_or_die_m(const char *file, int flags, mode_t mode); extern void create_or_die(const char *file, mode_t mode); extern int tun_open_or_die(char *name, int type); extern void pipe_or_die(int pipefd[2], int flags); extern ssize_t read_or_die(int fd, void *buf, size_t count); extern ssize_t write_or_die(int fd, const void *buf, size_t count); extern ssize_t read_exact(int fd, void *buf, size_t len, int mayexit); extern ssize_t write_exact(int fd, void *buf, size_t len, int mayexit); #endif /* XIO_H */ netsniff-ng-0.5.7/src/xio.c0000664000175000017500000000557611773367375015665 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "die.h" #include "xio.h" #include "xutils.h" int open_or_die(const char *file, int flags) { int ret = open(file, flags); if (ret < 0) panic("Cannot open file!\n"); return ret; } int open_or_die_m(const char *file, int flags, mode_t mode) { int ret = open(file, flags, mode); if (ret < 0) panic("Cannot open or create file!"); return ret; } void create_or_die(const char *file, mode_t mode) { int fd = open_or_die_m(file, O_WRONLY | O_CREAT, mode); close(fd); } void pipe_or_die(int pipefd[2], int flags) { int ret = pipe2(pipefd, flags); if (ret < 0) panic("Cannot create pipe2 event fd!\n"); } int tun_open_or_die(char *name, int type) { int fd, ret; short flags; struct ifreq ifr; if (!name) panic("No name provided for tundev!\n"); fd = open_or_die("/dev/net/tun", O_RDWR); memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = type; strlcpy(ifr.ifr_name, name, IFNAMSIZ); ret = ioctl(fd, TUNSETIFF, &ifr); if (ret < 0) panic("ioctl screwed up!\n"); ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); if (ret < 0) panic("fctnl screwed up!\n"); flags = device_get_flags(name); flags |= IFF_UP | IFF_RUNNING; device_set_flags(name, flags); return fd; } ssize_t read_or_die(int fd, void *buf, size_t len) { ssize_t ret = read(fd, buf, len); if (ret < 0) { if (errno == EPIPE) die(); panic("Cannot read from descriptor!\n"); } return ret; } ssize_t write_or_die(int fd, const void *buf, size_t len) { ssize_t ret = write(fd, buf, len); if (ret < 0) { if (errno == EPIPE) die(); panic("Cannot write to descriptor!"); } return ret; } extern volatile sig_atomic_t sigint; ssize_t read_exact(int fd, void *buf, size_t len, int mayexit) { register ssize_t num = 0, written; while (len > 0 && !sigint) { if ((written = read(fd, buf, len)) < 0) { if (errno == EAGAIN && num > 0) continue; if (mayexit) return -1; else continue; } if (!written) return 0; len -= written; buf += written; num += written; } return num; } ssize_t write_exact(int fd, void *buf, size_t len, int mayexit) { register ssize_t num = 0, written; while (len > 0 && !sigint) { if ((written = write(fd, buf, len)) < 0) { if (errno == EAGAIN && num > 0) continue; if (mayexit) return -1; else continue; } if (!written) return 0; len -= written; buf += written; num += written; } return num; } netsniff-ng-0.5.7/src/trie.h0000664000175000017500000000124311773367375016021 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2011 Daniel Borkmann. * Subject to the GPL, version 2. */ #ifndef TRIE_H #define TRIE_H #include extern void trie_addr_lookup(char *buff, size_t len, int ipv4, int *fd, struct sockaddr_storage *addr, size_t *alen); extern int trie_addr_maybe_update(char *buff, size_t len, int ipv4, int fd, struct sockaddr_storage *addr, size_t alen); extern void trie_addr_remove(int fd); extern void trie_addr_remove_addr(struct sockaddr_storage *addr, size_t alen); extern void trie_init(void); extern void trie_cleanup(void); #endif /* TRIE_H */ netsniff-ng-0.5.7/src/trie.c0000664000175000017500000000663311773367375016024 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2011 Daniel Borkmann. * Subject to the GPL, version 2. */ #include #include #include #include #include "patricia.h" #include "locking.h" #include "trie.h" struct ipv4hdr { #if defined(__LITTLE_ENDIAN_BITFIELD) __extension__ uint8_t h_ihl:4, h_version:4; #elif defined (__BIG_ENDIAN_BITFIELD) __extension__ uint8_t h_version:4, h_ihl:4; #else # error "Please fix " #endif uint8_t h_tos; uint16_t h_tot_len; uint16_t h_id; uint16_t h_frag_off; uint8_t h_ttl; uint8_t h_protocol; uint16_t h_check; uint32_t h_saddr; uint32_t h_daddr; } __attribute__((packed)); struct ipv6hdr { #if defined(__LITTLE_ENDIAN_BITFIELD) __extension__ uint8_t priority:4, version:4; #elif defined(__BIG_ENDIAN_BITFIELD) __extension__ uint8_t version:4, priority:4; #else # error "Please fix " #endif uint8_t flow_lbl[3]; uint16_t payload_len; uint8_t nexthdr; uint8_t hop_limit; struct in6_addr saddr; struct in6_addr daddr; } __attribute__((packed)); static struct patricia_node *tree = NULL; static struct rwlock tree_lock; void trie_addr_lookup(char *buff, size_t len, int ipv4, int *fd, struct sockaddr_storage *addr, size_t *alen) { void *data; size_t dlen; struct ipv4hdr *hdr4 = (void *) buff; struct ipv6hdr *hdr6 = (void *) buff; data = ipv4 ? (void *) &hdr4->h_daddr : (void *) &hdr6->daddr; dlen = ipv4 ? sizeof(hdr4->h_daddr) : sizeof(hdr6->daddr); if (unlikely((ipv4 && ((struct ipv4hdr *) buff)->h_version != 4) || (!ipv4 && ((struct ipv6hdr *) buff)->version != 6))) { memset(addr, 0, sizeof(*addr)); (*alen) = 0; (*fd) = -1; return; } /* Always happens on the dst address */ rwlock_rd_lock(&tree_lock); (*fd) = ptree_search_data_exact(data, dlen, addr, alen, tree); rwlock_unlock(&tree_lock); } int trie_addr_maybe_update(char *buff, size_t len, int ipv4, int fd, struct sockaddr_storage *addr, size_t alen) { int ret; void *data; size_t dlen; struct ipv4hdr *hdr4 = (void *) buff; struct ipv6hdr *hdr6 = (void *) buff; data = ipv4 ? (void *) &hdr4->h_saddr : (void *) &hdr6->saddr; dlen = ipv4 ? sizeof(hdr4->h_saddr) : sizeof(hdr6->saddr); if (unlikely((ipv4 && ((struct ipv4hdr *) buff)->h_version != 4) || (!ipv4 && ((struct ipv6hdr *) buff)->version != 6))) return -1; /* Always happens on the src address */ rwlock_wr_lock(&tree_lock); ret = ptree_maybe_add_entry(data, dlen, fd, addr, alen, &tree); rwlock_unlock(&tree_lock); return ret; } void trie_addr_remove(int fd) { int found = 1; struct patricia_node *n = NULL; rwlock_wr_lock(&tree_lock); while (found) { ptree_get_key(fd, tree, &n); if (n) { ptree_del_entry(n->key, n->klen, &tree); n = NULL; } else found = 0; } rwlock_unlock(&tree_lock); } void trie_addr_remove_addr(struct sockaddr_storage *addr, size_t alen) { int found = 1; struct patricia_node *n = NULL; rwlock_wr_lock(&tree_lock); while (found) { ptree_get_key_addr(addr, alen, tree, &n); if (n) { ptree_del_entry(n->key, n->klen, &tree); n = NULL; } else found = 0; } rwlock_unlock(&tree_lock); } void trie_init(void) { rwlock_init(&tree_lock); } void trie_cleanup(void) { rwlock_wr_lock(&tree_lock); ptree_free(tree); rwlock_unlock(&tree_lock); rwlock_destroy(&tree_lock); } netsniff-ng-0.5.7/src/trafgen_parser.y0000664000175000017500000002207211773367375020104 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2012 Daniel Borkmann , * Swiss federal institute of technology (ETH Zurich) * Subject to the GPL, version 2. */ %{ #include #include #include #include #include #include "xmalloc.h" #include "trafgen_parser.tab.h" #include "trafgen_conf.h" #include "built_in.h" #include "die.h" #include "mtrand.h" #define YYERROR_VERBOSE 0 #define YYDEBUG 0 #define YYENABLE_NLS 1 #define YYLTYPE_IS_TRIVIAL 1 #define ENABLE_NLS 1 extern FILE *yyin; extern int yylex(void); extern void yyerror(const char *); extern int yylineno; extern char *yytext; extern struct packet *packets; extern unsigned int packets_len; #define packets_last (packets_len - 1) #define payload_last (packets[packets_last].len - 1) extern struct packet_dynamics *packet_dyns; extern unsigned int packet_dyn_len; #define packetds_last (packet_dyn_len - 1) #define packetds_c_last (packet_dyns[packetds_last].counter_len - 1) #define packetds_r_last (packet_dyns[packetds_last].randomizer_len - 1) static int dfunc_note_flag = 0; static void give_note_dynamic(void) { if (!dfunc_note_flag) { printf("Note: dynamic elements like drnd, dinc, ddec and " "others make trafgen slower!\n"); dfunc_note_flag = 1; } } static inline void init_new_packet_slot(struct packet *slot) { slot->payload = NULL; slot->len = 0; } static inline void init_new_counter_slot(struct packet_dynamics *slot) { slot->counter = NULL; slot->counter_len = 0; } static inline void init_new_randomizer_slot(struct packet_dynamics *slot) { slot->randomizer = NULL; slot->randomizer_len = 0; } static void realloc_packet(void) { packets_len++; packets = xrealloc(packets, 1, packets_len * sizeof(*packets)); init_new_packet_slot(&packets[packets_last]); packet_dyn_len++; packet_dyns = xrealloc(packet_dyns, 1, packet_dyn_len * sizeof(*packet_dyns)); init_new_counter_slot(&packet_dyns[packetds_last]); init_new_randomizer_slot(&packet_dyns[packetds_last]); } static void set_byte(uint8_t val) { packets[packets_last].len++; packets[packets_last].payload = xrealloc(packets[packets_last].payload, 1, packets[packets_last].len); packets[packets_last].payload[payload_last] = val; } static void set_fill(uint8_t val, size_t len) { int i; packets[packets_last].len += len; packets[packets_last].payload = xrealloc(packets[packets_last].payload, 1, packets[packets_last].len); for (i = 0; i < len; ++i) packets[packets_last].payload[payload_last - i] = val; } static void set_rnd(size_t len) { int i; packets[packets_last].len += len; packets[packets_last].payload = xrealloc(packets[packets_last].payload, 1, packets[packets_last].len); for (i = 0; i < len; ++i) packets[packets_last].payload[payload_last - i] = (uint8_t) mt_rand_int32(); } static void set_seqinc(uint8_t start, size_t len, uint8_t stepping) { int i; packets[packets_last].len += len; packets[packets_last].payload = xrealloc(packets[packets_last].payload, 1, packets[packets_last].len); for (i = 0; i < len; ++i) { int off = len - 1 - i; packets[packets_last].payload[payload_last - off] = start; start += stepping; } } static void set_seqdec(uint8_t start, size_t len, uint8_t stepping) { int i; packets[packets_last].len += len; packets[packets_last].payload = xrealloc(packets[packets_last].payload, 1, packets[packets_last].len); for (i = 0; i < len; ++i) { int off = len - 1 - i; packets[packets_last].payload[payload_last - off] = start; start -= stepping; } } static inline void setup_new_counter(struct counter *counter, uint8_t start, uint8_t stop, uint8_t stepping, int type) { counter->min = start; counter->max = stop; counter->inc = stepping; counter->val = (type == TYPE_INC) ? start : stop; counter->off = payload_last; counter->type = type; } static inline void setup_new_randomizer(struct randomizer *randomizer) { randomizer->val = (uint8_t) mt_rand_int32(); randomizer->off = payload_last; } static void set_drnd(void) { give_note_dynamic(); packets[packets_last].len++; packets[packets_last].payload = xrealloc(packets[packets_last].payload, 1, packets[packets_last].len); packet_dyns[packetds_last].randomizer_len++; packet_dyns[packetds_last].randomizer = xrealloc(packet_dyns[packetds_last].randomizer, 1, packet_dyns[packetds_last].randomizer_len * sizeof(struct randomizer)); setup_new_randomizer(&packet_dyns[packetds_last]. randomizer[packetds_r_last]); } static void set_dincdec(uint8_t start, uint8_t stop, uint8_t stepping, int type) { give_note_dynamic(); packets[packets_last].len++; packets[packets_last].payload = xrealloc(packets[packets_last].payload, 1, packets[packets_last].len); packet_dyns[packetds_last].counter_len++; packet_dyns[packetds_last].counter = xrealloc(packet_dyns[packetds_last].counter, 1, packet_dyns[packetds_last].counter_len * sizeof(struct counter)); setup_new_counter(&packet_dyns[packetds_last].counter[packetds_c_last], start, stop, stepping, type); } %} %union { long int number; } %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE %token K_NEWL %token ',' '{' '}' '(' ')' '[' ']' %token number_hex number_dec number_ascii number_bin number_oct %type number_hex number_dec number_ascii number_bin number_oct number %% packets : { } | packets packet { } | packets inline_comment { } | packets white { } ; inline_comment : K_COMMENT { } ; packet : '{' delimiter payload delimiter '}' { realloc_packet(); } ; payload : elem { } | payload elem_delimiter { } ; white : white K_WHITE { } | white K_NEWL { } | K_WHITE { } | K_NEWL { } ; delimiter : ',' { } | white { } | ',' white { } ; elem_delimiter : delimiter elem { } ; number : number_dec { $$ = $1; } | number_hex { $$ = $1; } | number_ascii { $$ = $1; } | number_bin { $$ = $1; } | number_oct { $$ = $1; } ; fill : K_FILL '(' number delimiter number ')' { set_fill($3, $5); } ; rnd : K_RND '(' number ')' { set_rnd($3); } ; seqinc : K_SEQINC '(' number delimiter number ')' { set_seqinc($3, $5, 1); } | K_SEQINC '(' number delimiter number delimiter number ')' { set_seqinc($3, $5, $7); } ; seqdec : K_SEQDEC '(' number delimiter number ')' { set_seqdec($3, $5, 1); } | K_SEQDEC '(' number delimiter number delimiter number ')' { set_seqdec($3, $5, $7); } ; drnd : K_DRND '(' ')' { set_drnd(); } | K_DRND '(' number ')' { int i, max = $3; for (i = 0; i < max; ++i) set_drnd(); } ; dinc : K_DINC '(' number delimiter number ')' { set_dincdec($3, $5, 1, TYPE_INC); } | K_DINC '(' number delimiter number delimiter number ')' { set_dincdec($3, $5, $7, TYPE_INC); } ; ddec : K_DDEC '(' number delimiter number ')' { set_dincdec($3, $5, 1, TYPE_DEC); } | K_DDEC '(' number delimiter number delimiter number ')' { set_dincdec($3, $5, $7, TYPE_DEC); } ; elem : number { set_byte((uint8_t) $1); } | fill { } | rnd { } | drnd { } | seqinc { } | seqdec { } | dinc { } | ddec { } | inline_comment { } ; %% static void finalize_packet(void) { /* XXX hack ... we allocated one packet pointer too much */ packets_len--; packet_dyn_len--; } static void dump_conf(void) { size_t i, j; for (i = 0; i < packets_len; ++i) { printf("[%zu] pkt\n", i); printf(" len %zu cnts %zu rnds %zu\n", packets[i].len, packet_dyns[i].counter_len, packet_dyns[i].randomizer_len); printf(" payload "); for (j = 0; j < packets[i].len; ++j) printf("%02x ", packets[i].payload[j]); printf("\n"); for (j = 0; j < packet_dyns[i].counter_len; ++j) printf(" cnt%zu [%u,%u], inc %u, off %ld type %s\n", j, packet_dyns[i].counter[j].min, packet_dyns[i].counter[j].max, packet_dyns[i].counter[j].inc, packet_dyns[i].counter[j].off, packet_dyns[i].counter[j].type == TYPE_INC ? "inc" : "dec"); for (j = 0; j < packet_dyns[i].randomizer_len; ++j) printf(" rnd%zu off %ld\n", j, packet_dyns[i].randomizer[j].off); } } void cleanup_packets(void) { int i; for (i = 0; i < packets_len; ++i) { if (packets[i].len > 0) xfree(packets[i].payload); } if (packets_len > 0) xfree(packets); for (i = 0; i < packet_dyn_len; ++i) { if (packet_dyns[i].counter_len > 0) xfree(packet_dyns[i].counter); if (packet_dyns[i].randomizer_len > 0) xfree(packet_dyns[i].randomizer); } if (packet_dyn_len > 0) xfree(packet_dyns); } int compile_packets(char *file, int verbose) { mt_init_by_seed_time(); yyin = fopen(file, "r"); if (!yyin) panic("Cannot open file!\n"); realloc_packet(); yyparse(); finalize_packet(); if (verbose) { dump_conf(); } else { int i; size_t total_len = 0; printf("%u packets to schedule\n", packets_len); for (i = 0; i < packets_len; ++i) total_len += packets[i].len; printf("%zu bytes in total\n", total_len); } fclose(yyin); return 0; } void yyerror(const char *err) { panic("Syntax error at line %d: '%s'! %s!\n", yylineno, yytext, err); } netsniff-ng-0.5.7/src/trafgen_lexer.l0000664000175000017500000000357211773367375017716 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2012 Daniel Borkmann , * Swiss federal institute of technology (ETH Zurich) * Subject to the GPL, version 2. */ %{ #include #include #include #include #include "trafgen_parser.tab.h" #include "xmalloc.h" extern void yyerror(const char *); %} %option align %option nounput %option noyywrap %option noreject %option 8bit %option caseless %option noinput %option nodefault digit [0-9] digit_s [1-9] digit_n [0] bindigit [0-1] bindigit_b [b] hex [a-fA-F0-9] hex_x [x] number_dec {digit_n}|{digit_s}{digit}* number_oct {digit_n}{digit}+ number_hex {digit_n}{hex_x}{hex}+ number_bin {digit_n}{bindigit_b}{bindigit}+ number_ascii [a-zA-Z] %% "fill" { return K_FILL; } "rnd" { return K_RND; } "drnd" { return K_DRND; } "dinc" { return K_DINC; } "ddec" { return K_DDEC; } "seqinc" { return K_SEQINC; } "seqdec" { return K_SEQDEC; } "{" { return '{'; } "}" { return '}'; } "(" { return '('; } ")" { return ')'; } "[" { return '['; } "]" { return ']'; } "," { return ','; } "\n" { yylineno++; return K_NEWL; } [ \t\r]+ { return K_WHITE; } "/*"([^\*]|\*[^/])*"*/" { return K_COMMENT; } {number_hex} { yylval.number = strtoul(yytext, NULL, 16); return number_hex; } {number_dec} { yylval.number = strtol(yytext, NULL, 10); return number_dec; } {number_oct} { yylval.number = strtol(yytext, NULL, 8); return number_oct; } {number_bin} { yylval.number = strtol(yytext + 2, NULL, 2); return number_bin; } {number_ascii} { yylval.number = (uint8_t) (*yytext); return number_ascii; } "'"."'" { yylval.number = (uint8_t) (*(yytext + 1)); return number_ascii; } ";"[^\n]* {/* NOP */} "#"[^\n]* {/* NOP */} . { printf("Unknown character '%s'", yytext); yyerror("lex Unknown character"); } %% netsniff-ng-0.5.7/src/trafgen_conf.h0000664000175000017500000000152311773367375017512 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #ifndef TRAFGEN_CONF #define TRAFGEN_CONF #include #include #include #define TYPE_INC 0 #define TYPE_DEC 1 struct mode; struct counter { int type; uint8_t min; uint8_t max; uint8_t inc; uint8_t val; off_t off; }; struct randomizer { uint8_t val; off_t off; }; struct packet { uint8_t *payload; size_t len; }; struct packet_dynamics { struct counter *counter; size_t counter_len; struct randomizer *randomizer; size_t randomizer_len; }; extern int compile_packets(char *file, int verbose); extern void cleanup_packets(void); extern int main_loop_interactive(struct mode *mode, char *confname); #endif /* TRAFGEN_CONF */ netsniff-ng-0.5.7/src/trafgen_cli.c0000664000175000017500000000045411773367375017331 0ustar bordaniebordanie#include #include "trafgen_conf.h" int main_loop_interactive(struct mode *mode, char *confname) { struct cli_def *cli; cli = cli_init(); cli_set_banner(cli, "trafgen interactive mode"); cli_set_hostname(cli, "txfnode"); // cli_telnet_protocol(cli, 1); cli_done(cli); return 0; } netsniff-ng-0.5.7/src/trafgen.c0000664000175000017500000004641611773367375016512 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2011 Daniel Borkmann , * Swiss federal institute of technology (ETH Zurich) * Subject to the GPL, version 2. * * A high-performance network traffic generator that uses the zero-copy * kernelspace TX_RING for network I/O. On comodity Gigabit hardware up * to 1,488,095 pps 64 Byte pps have been achieved with 2 trafgen instances * bound to different CPUs from the userspace and turned off pause frames, * ask Ronald from NST (Network Security Toolkit) for more details. ;-) * So, this line-rate result is the very same as pktgen from kernelspace! * * Who can now hold the fords when the King of the Nine Riders comes? And * other armies will come. I am too late. All is lost. I tarried on the * way. All is lost. Even if my errand is performed, no one will ever * know. There will be no one I can tell. It will be in vain. * * -- The Lord of the Rings, Frodo thinking, * Chapter 'The Stairs of Cirith Ungol'. */ /* =head1 NAME trafgen - a high-performance zero-copy network packet generator =head1 SYNOPSIS trafgen [-d|--dev ][-c|--conf ][-J|--jumbo-support] [-x|--interactive][-n|--num ][-r|--rand][-t|--gap ] [-S|--ring-size ][-k|--kernel-pull ][-b|--bind-cpu ] [-B|--unbind-cpu ][-H|--prio-high][-Q|--notouch-irq][-v|--version] [-h|--help] =head1 DESCRIPTION A high-performance network traffic generator that uses the zero-copy TX_RING for network I/O. For instance, on comodity Gigabit hardware up to 1,488,095 pps 64 Byte pps have been achieved with trafgen. =head1 OPTIONS =over =item trafgen --dev eth0 --conf trafgen.txf --bind-cpu 0 Use packet configuration trafgen.txf, eth0 as transmission device and CPU0 for binding the process. =back =head1 OPTIONS =over =item -h|--help Print help text and lists all options. =item -v|--version Print version. =item -d|--dev Device for transmission i.e., eth0. =item -c|--conf Path to packet configuration file. =item -x|--interactive Start trafgen in interactive mode. =item -J|--jumbo-support Support for 64KB Super Jumbo Frames =item -n|--num Number of packets to generate before exiting. 0 means forever until SIGINT. =item -r|--rand Randomize packet selection process instead of round-robin. =item -t|--gap Interpacket gap in microseconds. =item -S|--ring-size Manually set ring size to : mmap space in KB/MB/GB. =item -k|--kernel-pull Kernel pull from user interval in microseconds. Default value is 10 microseconds. =item -b|--bind-cpu Bind to specific CPU (or CPU-range). =item -B|--unbind-cpu Forbid to use specific CPU (or CPU-range). =item -H|--prio-high Make this high priority process. =item -Q|--notouch-irq Do not touch IRQ CPU affinity of NIC. =back =head1 EXAMPLES =over =item Generate traffic defined in trafgen.txf on eth0 using CPU 0 trafgen --dev eth0 --conf trafgen.txf --bind-cpu 0 =item Generate traffic on eth0 using CPU 0, wait 100 us between packets trafgen --dev eth0 --conf trafgen.txf --bind-cpu 0 --gap 100 =item Generate 100,000 packet on eth0 using CPU 0 trafgen --dev eth0 --conf trafgen.txf --bind-cpu 0 --num 100000 =back =head1 AUTHOR Written by Daniel Borkmann =head1 DOCUMENTATION Documentation by Emmanuel Roullit =head1 BUGS Please report bugs to =cut */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "xmalloc.h" #include "die.h" #include "mac80211.h" #include "xutils.h" #include "xio.h" #include "trafgen_conf.h" #include "tprintf.h" #include "mtrand.h" #include "ring_tx.h" struct stats { unsigned long tx_bytes; unsigned long tx_packets; }; struct mode { #define CPU_UNKNOWN -1 #define CPU_NOTOUCH -2 struct stats stats; char *device; char *device_trans; int cpu; int rand; int rfraw; unsigned long kpull; /* 0 for automatic, > 0 for manual */ unsigned int reserve_size; int jumbo_support; int verbose; unsigned long num; unsigned long gap; }; static int sock; static struct itimerval itimer; static unsigned long interval = TX_KERNEL_PULL_INT; sig_atomic_t sigint = 0; struct packet *packets = NULL; unsigned int packets_len = 0; struct packet_dynamics *packet_dyns = NULL; unsigned int packet_dyn_len = 0; static const char *short_options = "d:c:n:t:vJhS:HQb:B:rk:xi:o:VR"; static struct option long_options[] = { {"dev", required_argument, 0, 'd'}, {"out", required_argument, 0, 'o'}, {"in", required_argument, 0, 'i'}, {"conf", required_argument, 0, 'c'}, {"num", required_argument, 0, 'n'}, {"gap", required_argument, 0, 't'}, {"ring-size", required_argument, 0, 'S'}, {"bind-cpu", required_argument, 0, 'b'}, {"unbind-cpu", required_argument, 0, 'B'}, {"kernel-pull", required_argument, 0, 'k'}, {"jumbo-support", no_argument, 0, 'J'}, {"rfraw", no_argument, 0, 'R'}, {"interactive", no_argument, 0, 'x'}, {"rand", no_argument, 0, 'r'}, {"prio-high", no_argument, 0, 'H'}, {"notouch-irq", no_argument, 0, 'Q'}, {"verbose", no_argument, 0, 'V'}, {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; static void signal_handler(int number) { switch (number) { case SIGINT: sigint = 1; break; case SIGHUP: default: break; } } static void timer_elapsed(int number) { itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = interval; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = interval; pull_and_flush_tx_ring(sock); setitimer(ITIMER_REAL, &itimer, NULL); } static void header(void) { printf("%s%s%s\n", colorize_start(bold), "trafgen " VERSION_STRING, colorize_end()); } static void help(void) { printf("\ntrafgen %s, high-perf zero-copy network packet generator\n", VERSION_STRING); printf("http://www.netsniff-ng.org\n\n"); printf("Usage: trafgen [options]\n"); printf("Options:\n"); /* printf(" -o|-d|--out|--dev Networking Device i.e., eth0 or pcap\n"); */ printf(" -o|-d|--out|--dev Networking Device i.e., eth0\n"); printf(" -i|-c|--in|--conf Packet configuration file\n"); /* printf(" -x|--interactive Start trafgen in interactive server mode\n"); */ printf(" -J|--jumbo-support Support for 64KB Super Jumbo Frames\n"); printf(" Default TX slot: 2048Byte\n"); printf(" -R|--rfraw Inject raw 802.11 frames\n"); printf(" -n|--num Number of packets until exit\n"); printf(" `-- 0 Loop until interrupt (default)\n"); printf(" `- n Send n packets and done\n"); printf(" -r|--rand Randomize packet selection process\n"); printf(" Instead of a round robin selection\n"); printf(" -t|--gap Interpacket gap in us (approx)\n"); printf(" -S|--ring-size Manually set ring size to :\n"); printf(" mmap space in KB/MB/GB, e.g. \'10MB\'\n"); printf(" -k|--kernel-pull Kernel pull from user interval in us\n"); printf(" Default is 10us where the TX_RING\n"); printf(" is populated with payload from uspace\n"); printf(" -b|--bind-cpu Bind to specific CPU (or CPU-range)\n"); printf(" -B|--unbind-cpu Forbid to use specific CPU (or CPU-range)\n"); printf(" -H|--prio-high Make this high priority process\n"); printf(" -Q|--notouch-irq Do not touch IRQ CPU affinity of NIC\n"); printf(" -v|--version Show version\n"); printf(" -h|--help Guess what?!\n"); printf("\n"); printf("Examples:\n"); printf(" See trafgen.txf for configuration file examples.\n"); printf(" trafgen --dev eth0 --conf trafgen.txf --bind-cpu 0\n"); printf(" trafgen --dev wlan0 --rfraw --conf beacon-test.txf --bind-cpu 0\n"); printf(" trafgen --out eth0 --in trafgen.txf --bind-cpu 0\n"); /* printf(" trafgen --out test.pcap --in trafgen.txf --bind-cpu 0\n"); */ printf(" trafgen --dev eth0 --conf trafgen.txf --rand --gap 1000\n"); printf(" trafgen --dev eth0 --conf trafgen.txf --bind-cpu 0 --num 10 --rand\n"); /* printf(" trafgen --interactive\n"); printf(" trafgen --interactive --dev mgmt0 (only start server on mgmt0)\n"); printf(" trafgen --interactive --conf trafgen-cli.batch\n");*/ printf("\n"); printf("Note:\n"); printf(" This tool is targeted for network developers! You should\n"); printf(" be aware of what you are doing and what these options above\n"); printf(" mean! Only use this tool in an isolated LAN that you own!\n"); printf("\n"); printf("Please report bugs to \n"); printf("Copyright (C) 2011-2012 Daniel Borkmann ,\n"); printf("Swiss federal institute of technology (ETH Zurich)\n"); printf("License: GNU GPL version 2\n"); printf("This is free software: you are free to change and redistribute it.\n"); printf("There is NO WARRANTY, to the extent permitted by law.\n\n"); die(); } static void version(void) { printf("\ntrafgen %s, high-perf zero-copy network packet generator\n", VERSION_STRING); printf("http://www.netsniff-ng.org\n\n"); printf("Please report bugs to \n"); printf("Copyright (C) 2011-2012 Daniel Borkmann ,\n"); printf("Swiss federal institute of technology (ETH Zurich)\n"); printf("License: GNU GPL version 2\n"); printf("This is free software: you are free to change and redistribute it.\n"); printf("There is NO WARRANTY, to the extent permitted by law.\n\n"); die(); } static inline void apply_counter(int i) { int j; for (j = 0; j < packet_dyns[i].counter_len; ++j) { uint8_t val; struct counter *counter = &packet_dyns[i].counter[j]; val = counter->val; val -= counter->min; if (counter->type == TYPE_INC) val = (val + counter->inc) % (counter->max - counter->min + 1); else val = (val - counter->inc) % (counter->min - counter->max + 1); val += counter->min; counter->val = val; packets[i].payload[counter->off] = val; } } static inline void apply_randomizer(int i) { int j; for (j = 0; j < packet_dyns[i].randomizer_len; ++j) { uint8_t val = (uint8_t) mt_rand_int32(); struct randomizer *randomizer = &packet_dyns[i].randomizer[j]; randomizer->val = val; packets[i].payload[randomizer->off] = val; } } static void tx_precheck(struct mode *mode) { int i, mtu; if (!mode) panic("Panic over invalid args for TX trigger!\n"); if (packets_len == 0 || packets_len != packet_dyn_len) panic("Panic over invalid args for TX trigger!\n"); if (!mode->rfraw && !device_up_and_running(mode->device)) panic("Device not up and running!\n"); mtu = device_mtu(mode->device); for (i = 0; i < packets_len; ++i) { if (packets[i].len > mtu + 14) panic("Device MTU < than your packet size!\n"); if (packets[i].len <= 14) panic("Device packet size too short!\n"); } } static void tx_slowpath_or_die(struct mode *mode) { int ifindex, ret; unsigned int i; struct sockaddr_ll s_addr; unsigned long num = 1; struct timeval start, end, diff; tx_precheck(mode); sock = pf_socket(); if (mode->rfraw) { mode->device_trans = xstrdup(mode->device); xfree(mode->device); enter_rfmon_mac80211(mode->device_trans, &mode->device); } ifindex = device_ifindex(mode->device); if (mode->num > 0) num = mode->num; if (mode->rand) printf("Note: randomizes output makes trafgen slower!\n"); printf("MD: TX slowpath %s %luus", mode->rand ? "RND" : "RR", mode->gap); if (mode->rfraw) printf(" 802.11 raw via %s", mode->device); printf("\n\n"); printf("Running! Hang up with ^C!\n\n"); fmemset(&s_addr, 0, sizeof(s_addr)); s_addr.sll_family = PF_PACKET; s_addr.sll_halen = ETH_ALEN; s_addr.sll_ifindex = ifindex; i = 0; gettimeofday(&start, NULL); while (likely(sigint == 0) && likely(num > 0)) { apply_counter(i); apply_randomizer(i); ret = sendto(sock, packets[i].payload, packets[i].len, 0, (struct sockaddr *) &s_addr, sizeof(s_addr)); if (ret < 0) whine("sendto error!\n"); mode->stats.tx_bytes += packets[i].len; mode->stats.tx_packets++; if (mode->rand) { i = mt_rand_int32() % packets_len; } else { i++; atomic_cmp_swp(&i, packets_len, 0); } if (mode->num > 0) num--; usleep(mode->gap); } gettimeofday(&end, NULL); diff = tv_subtract(end, start); if (mode->rfraw) leave_rfmon_mac80211(mode->device_trans, mode->device); close(sock); fflush(stdout); printf("\n"); printf("\r%12lu frames outgoing\n", mode->stats.tx_packets); printf("\r%12lu bytes outgoing\n", mode->stats.tx_bytes); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); } static void tx_fastpath_or_die(struct mode *mode) { int irq, ifindex; unsigned int i, size, it = 0; unsigned long num = 1; uint8_t *out = NULL; struct ring tx_ring; struct frame_map *hdr; struct timeval start, end, diff; tx_precheck(mode); sock = pf_socket(); fmemset(&tx_ring, 0, sizeof(tx_ring)); if (mode->rfraw) { mode->device_trans = xstrdup(mode->device); xfree(mode->device); enter_rfmon_mac80211(mode->device_trans, &mode->device); } ifindex = device_ifindex(mode->device); size = ring_size(mode->device, mode->reserve_size); set_packet_loss_discard(sock); setup_tx_ring_layout(sock, &tx_ring, size, mode->jumbo_support); create_tx_ring(sock, &tx_ring); mmap_tx_ring(sock, &tx_ring); alloc_tx_ring_frames(&tx_ring); bind_tx_ring(sock, &tx_ring, ifindex); if (mode->cpu >= 0 && ifindex > 0) { irq = device_irq_number(mode->device); device_bind_irq_to_cpu(mode->cpu, irq); printf("IRQ: %s:%d > CPU%d\n", mode->device, irq, mode->cpu); } if (mode->kpull) interval = mode->kpull; if (mode->num > 0) num = mode->num; if (mode->rand) printf("Note: randomizes output makes trafgen slower!\n"); printf("MD: TX fastpath %s %luus", mode->rand ? "RND" : "RR", interval); if (mode->rfraw) printf(" 802.11 raw via %s", mode->device); printf("\n\n"); printf("Running! Hang up with ^C!\n\n"); itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = interval; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = interval; setitimer(ITIMER_REAL, &itimer, NULL); i = 0; gettimeofday(&start, NULL); while (likely(sigint == 0) && likely(num > 0)) { while (user_may_pull_from_tx(tx_ring.frames[it].iov_base) && likely(num > 0)) { hdr = tx_ring.frames[it].iov_base; /* Kernel assumes: data = ph.raw + po->tp_hdrlen - * sizeof(struct sockaddr_ll); */ out = ((uint8_t *) hdr) + TPACKET_HDRLEN - sizeof(struct sockaddr_ll); hdr->tp_h.tp_snaplen = packets[i].len; hdr->tp_h.tp_len = packets[i].len; apply_counter(i); apply_randomizer(i); fmemcpy(out, packets[i].payload, packets[i].len); mode->stats.tx_bytes += packets[i].len; mode->stats.tx_packets++; if (mode->rand) { i = mt_rand_int32() % packets_len; } else { i++; atomic_cmp_swp(&i, packets_len, 0); } kernel_may_pull_from_tx(&hdr->tp_h); next_slot_prewr(&it, &tx_ring); if (mode->num > 0) num--; if (unlikely(sigint == 1)) break; } } gettimeofday(&end, NULL); diff = tv_subtract(end, start); destroy_tx_ring(sock, &tx_ring); if (mode->rfraw) leave_rfmon_mac80211(mode->device_trans, mode->device); close(sock); fflush(stdout); printf("\n"); printf("\r%12lu frames outgoing\n", mode->stats.tx_packets); printf("\r%12lu bytes outgoing\n", mode->stats.tx_bytes); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); } static void main_loop(struct mode *mode, char *confname) { compile_packets(confname, mode->verbose); if (mode->gap > 0) tx_slowpath_or_die(mode); else tx_fastpath_or_die(mode); cleanup_packets(); } int main(int argc, char **argv) { int c, opt_index, i, j, interactive = 0; char *confname = NULL, *ptr; bool prio_high = false; struct mode mode; check_for_root_maybe_die(); fmemset(&mode, 0, sizeof(mode)); mode.cpu = CPU_UNKNOWN; mode.gap = 0; mode.num = 0; while ((c = getopt_long(argc, argv, short_options, long_options, &opt_index)) != EOF) { switch (c) { case 'h': help(); break; case 'v': version(); break; case 'V': mode.verbose = 1; break; case 'd': case 'o': mode.device = xstrndup(optarg, IFNAMSIZ); break; case 'x': interactive = 1; break; case 'r': mode.rand = 1; break; case 'R': mode.rfraw = 1; break; case 'J': mode.jumbo_support = 1; break; case 'c': case 'i': confname = xstrdup(optarg); break; case 'k': mode.kpull = atol(optarg); break; case 'n': mode.num = atol(optarg); break; case 't': mode.gap = atol(optarg); break; case 'S': ptr = optarg; mode.reserve_size = 0; for (j = i = strlen(optarg); i > 0; --i) { if (!isdigit(optarg[j - i])) break; ptr++; } if (!strncmp(ptr, "KB", strlen("KB"))) mode.reserve_size = 1 << 10; else if (!strncmp(ptr, "MB", strlen("MB"))) mode.reserve_size = 1 << 20; else if (!strncmp(ptr, "GB", strlen("GB"))) mode.reserve_size = 1 << 30; else panic("Syntax error in ring size param!\n"); *ptr = 0; mode.reserve_size *= atoi(optarg); break; case 'b': set_cpu_affinity(optarg, 0); /* Take the first CPU for rebinding the IRQ */ if (mode.cpu != CPU_NOTOUCH) mode.cpu = atoi(optarg); break; case 'B': set_cpu_affinity(optarg, 1); break; case 'H': prio_high = true; break; case 'Q': mode.cpu = CPU_NOTOUCH; break; case '?': switch (optopt) { case 'd': case 'c': case 'n': case 'S': case 'b': case 'o': case 'i': case 'k': case 'B': case 't': panic("Option -%c requires an argument!\n", optopt); default: if (isprint(optopt)) whine("Unknown option character " "`0x%X\'!\n", optopt); die(); } default: break; } } if (!interactive && argc < 5) help(); if (interactive && argc < 2) help(); if (!interactive && mode.device == NULL) panic("No networking device given!\n"); if (!interactive && confname == NULL) panic("No configuration file given!\n"); if (!interactive && device_mtu(mode.device) == 0) panic("This is no networking device!\n"); if (!interactive && !mode.rfraw && device_up_and_running(mode.device) == 0) panic("Networking device not running!\n"); register_signal(SIGINT, signal_handler); register_signal(SIGHUP, signal_handler); register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); header(); if (prio_high == true) { set_proc_prio(get_default_proc_prio()); set_sched_status(get_default_sched_policy(), get_default_sched_prio()); } if (interactive) main_loop_interactive(&mode, confname); else main_loop(&mode, confname); if (mode.device) xfree(mode.device); if (mode.device_trans) xfree(mode.device_trans); if (confname) xfree(confname); return 0; } netsniff-ng-0.5.7/src/tprintf.h0000664000175000017500000000235611773367375016552 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #ifndef TPRINTF_H #define TPRINTF_H #define DEFAULT_TTY_SIZE 80 extern void tprintf_init(void); extern void tprintf(char *msg, ...); extern void tprintf_flush(void); extern void tprintf_cleanup(void); #define __reset "0" #define __bold "1" #define __black "30" #define __red "31" #define __green "32" #define __yellow "33" #define __blue "34" #define __magenta "35" #define __cyan "36" #define __white "37" #define __on_black "40" #define __on_red "41" #define __on_green "42" #define __on_yellow "43" #define __on_blue "44" #define __on_magenta "45" #define __on_cyan "46" #define __on_white "47" #define colorize_start(fore) "\033[" __##fore "m" #define colorize_start_full(fore, back) "\033[" __##fore ";" __on_##back "m" #define colorize_end() "\033[" __reset "m" #define colorize_str(fore, text) \ colorize_start(fore) text colorize_end() #define colorize_full_str(fore, back, text) \ colorize_start_full(fore, back) text colorize_end() #endif /* TPRINTF_H */ netsniff-ng-0.5.7/src/tprintf.c0000664000175000017500000000443511773367375016545 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #define _BSD_SOURCE #include #include #include "xutils.h" #include "tprintf.h" #include "die.h" #include "locking.h" #include "built_in.h" #define term_trailing_size 5 #define term_starting_size 3 #define term_curr_size (get_tty_size() - term_trailing_size) static char buffer[1024]; static volatile size_t buffer_use = 0; static struct spinlock buffer_lock; static inline void __tprintf_flush_newline(void) { int i; fputc('\n', stdout); for (i = 0; i < term_starting_size; ++i) fputc(' ', stdout); } static inline int __tprintf_flush_skip(char *buffer, int i, size_t max) { int val = buffer[i]; if (val == ' ' || val == ',') return 1; return 0; } static void __tprintf_flush(void) { int i; static ssize_t line_count = 0; size_t term_len = term_curr_size; for (i = 0; i < buffer_use; ++i) { if (buffer[i] == '\n') { term_len = term_curr_size; line_count = -1; } if (line_count == term_len) { __tprintf_flush_newline(); line_count = term_starting_size; while (i < buffer_use && __tprintf_flush_skip(buffer, i, buffer_use)) i++; } fputc(buffer[i], stdout); line_count++; } fflush(stdout); access_once(buffer_use) = 0; } void tprintf_flush(void) { spinlock_lock(&buffer_lock); __tprintf_flush(); spinlock_unlock(&buffer_lock); } void tprintf_init(void) { spinlock_init(&buffer_lock); } void tprintf_cleanup(void) { tprintf_flush(); spinlock_destroy(&buffer_lock); } void tprintf(char *msg, ...) { ssize_t ret; ssize_t avail; va_list vl; spinlock_lock(&buffer_lock); avail = sizeof(buffer) - buffer_use; bug_on(avail < 0); va_start(vl, msg); ret = vsnprintf(buffer + buffer_use, avail, msg, vl); va_end(vl); if (ret < 0) panic("vsnprintf screwed up in tprintf!\n"); if (ret > sizeof(buffer)) panic("No mem in tprintf left!\n"); if (ret >= avail) { __tprintf_flush(); avail = sizeof(buffer) - buffer_use; bug_on(avail < 0); va_start(vl, msg); ret = vsnprintf(buffer + buffer_use, avail, msg, vl); va_end(vl); if (ret < 0) panic("vsnprintf screwed up in tprintf!\n"); } buffer_use += ret; spinlock_unlock(&buffer_lock); } netsniff-ng-0.5.7/src/stun.c0000664000175000017500000001017711773367375016050 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2011 Daniel Borkmann. * Subject to the GPL, version 2. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "xmalloc.h" #include "xutils.h" #include "die.h" extern int print_stun_probe(char *server, int sport, int tport); #define BINDING_REQUEST 0x0001 #define BINDING_RESPONSE 0x0101 #define MAPPED_ADDRESS 0x0001 #define TIMEOUT 5000 #define REQUEST_LEN 20 #define ID_COOKIE_FIELD htonl(((int) 'a' << 24) + \ ((int) 'c' << 16) + \ ((int) 'd' << 8) + \ (int) 'c') struct stun_header { uint16_t type; uint16_t len; uint32_t magic_cookie; uint32_t transid[3]; }; struct stun_attrib { uint16_t type; uint16_t len; uint8_t *value; }; struct stun_mapped_addr { uint8_t none; uint8_t family; uint16_t port; uint32_t ip; }; static int stun_test(const char *server_ip, int server_port, int tun_port) { int ret, sock, set = 1; uint8_t pkt[256]; uint8_t rpkt[256]; size_t len, off, max; struct in_addr in; struct timeval timeout; struct stun_header *hdr, *rhdr; struct stun_attrib *attr; struct stun_mapped_addr *addr; struct sockaddr_in saddr, daddr; fd_set fdset; if (!server_ip) return -EINVAL; sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock < 0) panic("Cannot obtain socket!\n"); ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &set, sizeof(set)); if (ret) panic("Cannot set socket option!\n"); saddr.sin_family = PF_INET; saddr.sin_port = htons(tun_port); saddr.sin_addr.s_addr = INADDR_ANY; ret = bind(sock, (struct sockaddr *) &saddr, sizeof(saddr)); if (ret) panic("Cannot bind udp socket!\n"); len = REQUEST_LEN; hdr = (struct stun_header *) pkt; hdr->type = htons(BINDING_REQUEST); hdr->len = 0; hdr->magic_cookie = ID_COOKIE_FIELD; hdr->transid[0] = htonl(rand()); hdr->transid[1] = htonl(rand()); hdr->transid[2] = htonl(rand()); daddr.sin_family = PF_INET; daddr.sin_port = htons(server_port); daddr.sin_addr.s_addr = inet_addr(server_ip); ret = sendto(sock, pkt, len, 0, (struct sockaddr *) &daddr, sizeof(daddr)); if (ret != len) { whine("Error sending request (%s)!\n", strerror(errno)); return -EIO; } set_timeout(&timeout, TIMEOUT); FD_ZERO(&fdset); FD_SET(sock, &fdset); ret = select(sock + 1, &fdset, NULL, NULL, &timeout); if (ret <= 0) { whine("STUN server timeout!\n"); return -EIO; } memset(rpkt, 0, sizeof(rpkt)); len = read(sock, rpkt, sizeof(rpkt)); close(sock); if (len < REQUEST_LEN) { whine("Bad STUN response (%s)!\n", strerror(errno)); return -EIO; } rhdr = (struct stun_header *) rpkt; if (ntohs(rhdr->type) != BINDING_RESPONSE) { whine("Wrong STUN response type!\n"); return -EIO; } if (rhdr->len == 0) { whine("No attributes in STUN response!\n"); return -EIO; } if (rhdr->magic_cookie != hdr->magic_cookie || rhdr->transid[0] != hdr->transid[0] || rhdr->transid[1] != hdr->transid[1] || rhdr->transid[2] != hdr->transid[2]) { whine("Got wrong STUN transaction id!\n"); return -EIO; } off = REQUEST_LEN; max = ntohs(rhdr->len) + REQUEST_LEN; while (off + 8 < max) { attr = (struct stun_attrib *) (rpkt + off); if (ntohs(attr->type) != MAPPED_ADDRESS) goto next; addr = (struct stun_mapped_addr *) (rpkt + off + 4); if (addr->family != 0x1) break; in.s_addr = addr->ip; printf("Public mapping %s:%u!\n", inet_ntoa(in), ntohs(addr->port)); break; next: off += 4; off += ntohs(attr->len); } return 0; } int print_stun_probe(char *server, int sport, int tport) { char *address; struct hostent *hp; printf("STUN on %s:%u\n", server, sport); srand(time(NULL)); hp = gethostbyname(server); if (!hp) return -EIO; address = inet_ntoa(*(struct in_addr *) hp->h_addr_list[0]); return stun_test(address, sport, tport); } netsniff-ng-0.5.7/src/ring_tx.h0000664000175000017500000000223111773367375016526 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #ifndef TX_RING_H #define TX_RING_H #include "ring.h" #include "built_in.h" /* Give userland 10 us time to push packets to the ring */ #define TX_KERNEL_PULL_INT 10 extern void destroy_tx_ring(int sock, struct ring *ring); extern void create_tx_ring(int sock, struct ring *ring); extern void mmap_tx_ring(int sock, struct ring *ring); extern void alloc_tx_ring_frames(struct ring *ring); extern void bind_tx_ring(int sock, struct ring *ring, int ifindex); extern void setup_tx_ring_layout(int sock, struct ring *ring, unsigned int size, int jumbo_support); extern void set_packet_loss_discard(int sock); static inline int user_may_pull_from_tx(struct tpacket_hdr *hdr) { return ((hdr->tp_status & TP_STATUS_AVAILABLE) == TP_STATUS_AVAILABLE); } static inline void kernel_may_pull_from_tx(struct tpacket_hdr *hdr) { hdr->tp_status = TP_STATUS_SEND_REQUEST; } static inline int pull_and_flush_tx_ring(int sock) { return sendto(sock, NULL, 0, MSG_DONTWAIT, NULL, 0); } #endif /* TX_RING_H */ netsniff-ng-0.5.7/src/ring_tx.c0000664000175000017500000000703411773367375016527 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Copyright 2009, 2010 Emmanuel Roullit. * Subject to the GPL, version 2. */ #include #include #include #include #include #include #include #include #include #include "die.h" #include "xmalloc.h" #include "ring_tx.h" #include "built_in.h" void set_packet_loss_discard(int sock) { int ret, discard = 1; ret = setsockopt(sock, SOL_PACKET, PACKET_LOSS, (void *) &discard, sizeof(discard)); if (ret < 0) panic("setsockopt: cannot set packet loss"); } void destroy_tx_ring(int sock, struct ring *ring) { fmemset(&ring->layout, 0, sizeof(ring->layout)); setsockopt(sock, SOL_PACKET, PACKET_TX_RING, &ring->layout, sizeof(ring->layout)); munmap(ring->mm_space, ring->mm_len); ring->mm_len = 0; xfree(ring->frames); } void setup_tx_ring_layout(int sock, struct ring *ring, unsigned int size, int jumbo_support) { fmemset(&ring->layout, 0, sizeof(ring->layout)); ring->layout.tp_block_size = (jumbo_support ? getpagesize() << 4 : getpagesize() << 2); ring->layout.tp_frame_size = (jumbo_support ? TPACKET_ALIGNMENT << 12 : TPACKET_ALIGNMENT << 7); ring->layout.tp_block_nr = size / ring->layout.tp_block_size; ring->layout.tp_frame_nr = ring->layout.tp_block_size / ring->layout.tp_frame_size * ring->layout.tp_block_nr; bug_on(ring->layout.tp_block_size < ring->layout.tp_frame_size); bug_on((ring->layout.tp_block_size % ring->layout.tp_frame_size) != 0); bug_on((ring->layout.tp_block_size % getpagesize()) != 0); } void create_tx_ring(int sock, struct ring *ring) { int ret; retry: ret = setsockopt(sock, SOL_PACKET, PACKET_TX_RING, &ring->layout, sizeof(ring->layout)); if (errno == ENOMEM && ring->layout.tp_block_nr > 1) { ring->layout.tp_block_nr >>= 1; ring->layout.tp_frame_nr = ring->layout.tp_block_size / ring->layout.tp_frame_size * ring->layout.tp_block_nr; goto retry; } if (ret < 0) panic("Cannot allocate TX_RING!\n"); ring->mm_len = ring->layout.tp_block_size * ring->layout.tp_block_nr; printf("TX: %.2f MiB, %u Frames, each %u Byte allocated\n", 1.f * ring->mm_len / (1 << 20), ring->layout.tp_frame_nr, ring->layout.tp_frame_size); } void mmap_tx_ring(int sock, struct ring *ring) { ring->mm_space = mmap(0, ring->mm_len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, sock, 0); if (ring->mm_space == MAP_FAILED) { destroy_tx_ring(sock, ring); panic("Cannot mmap TX_RING!\n"); } } void alloc_tx_ring_frames(struct ring *ring) { int i; size_t len = ring->layout.tp_frame_nr * sizeof(*ring->frames); ring->frames = xmalloc_aligned(len, CO_CACHE_LINE_SIZE); fmemset(ring->frames, 0, len); for (i = 0; i < ring->layout.tp_frame_nr; ++i) { ring->frames[i].iov_len = ring->layout.tp_frame_size; ring->frames[i].iov_base = ring->mm_space + (i * ring->layout.tp_frame_size); } } void bind_tx_ring(int sock, struct ring *ring, int ifindex) { int ret; fmemset(&ring->s_ll, 0, sizeof(ring->s_ll)); ring->s_ll.sll_family = AF_PACKET; ring->s_ll.sll_protocol = htons(ETH_P_ALL); ring->s_ll.sll_ifindex = ifindex; ring->s_ll.sll_hatype = 0; ring->s_ll.sll_halen = 0; ring->s_ll.sll_pkttype = 0; ret = bind(sock, (struct sockaddr *) &ring->s_ll, sizeof(ring->s_ll)); if (ret < 0) { destroy_tx_ring(sock, ring); panic("Cannot bind TX_RING!\n"); } } netsniff-ng-0.5.7/src/ring_rx.h0000664000175000017500000000162211773367375016527 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #ifndef RX_RING_H #define RX_RING_H #include "ring.h" #include "built_in.h" extern void destroy_rx_ring(int sock, struct ring *ring); extern void create_rx_ring(int sock, struct ring *ring); extern void mmap_rx_ring(int sock, struct ring *ring); extern void alloc_rx_ring_frames(struct ring *ring); extern void bind_rx_ring(int sock, struct ring *ring, int ifindex); extern void setup_rx_ring_layout(int sock, struct ring *ring, unsigned int size, int jumbo_support); static inline int user_may_pull_from_rx(struct tpacket_hdr *hdr) { return ((hdr->tp_status & TP_STATUS_USER) == TP_STATUS_USER); } static inline void kernel_may_pull_from_rx(struct tpacket_hdr *hdr) { hdr->tp_status = TP_STATUS_KERNEL; } #endif /* RX_RING_H */ netsniff-ng-0.5.7/src/ring_rx.c0000664000175000017500000000671011773367375016525 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #include #include #include #include #include #include #include #include #include #include "xmalloc.h" #include "die.h" #include "ring_rx.h" #include "built_in.h" void destroy_rx_ring(int sock, struct ring *ring) { fmemset(&ring->layout, 0, sizeof(ring->layout)); setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &ring->layout, sizeof(ring->layout)); munmap(ring->mm_space, ring->mm_len); ring->mm_len = 0; xfree(ring->frames); } void setup_rx_ring_layout(int sock, struct ring *ring, unsigned int size, int jumbo_support) { fmemset(&ring->layout, 0, sizeof(ring->layout)); ring->layout.tp_block_size = (jumbo_support ? getpagesize() << 4 : getpagesize() << 2); ring->layout.tp_frame_size = (jumbo_support ? TPACKET_ALIGNMENT << 12 : TPACKET_ALIGNMENT << 7); ring->layout.tp_block_nr = size / ring->layout.tp_block_size; ring->layout.tp_frame_nr = ring->layout.tp_block_size / ring->layout.tp_frame_size * ring->layout.tp_block_nr; bug_on(ring->layout.tp_block_size < ring->layout.tp_frame_size); bug_on((ring->layout.tp_block_size % ring->layout.tp_frame_size) != 0); bug_on((ring->layout.tp_block_size % getpagesize()) != 0); } void create_rx_ring(int sock, struct ring *ring) { int ret; retry: ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &ring->layout, sizeof(ring->layout)); if (errno == ENOMEM && ring->layout.tp_block_nr > 1) { ring->layout.tp_block_nr >>= 1; ring->layout.tp_frame_nr = ring->layout.tp_block_size / ring->layout.tp_frame_size * ring->layout.tp_block_nr; goto retry; } if (ret < 0) panic("Cannot allocate RX_RING!\n"); ring->mm_len = ring->layout.tp_block_size * ring->layout.tp_block_nr; printf("RX: %.2f MiB, %u Frames, each %u Byte allocated\n", 1.f * ring->mm_len / (1 << 20), ring->layout.tp_frame_nr, ring->layout.tp_frame_size); } void mmap_rx_ring(int sock, struct ring *ring) { ring->mm_space = mmap(0, ring->mm_len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, sock, 0); if (ring->mm_space == MAP_FAILED) { destroy_rx_ring(sock, ring); panic("Cannot mmap RX_RING!\n"); } } void alloc_rx_ring_frames(struct ring *ring) { int i; size_t len = ring->layout.tp_frame_nr * sizeof(*ring->frames); ring->frames = xmalloc_aligned(len, CO_CACHE_LINE_SIZE); fmemset(ring->frames, 0, len); for (i = 0; i < ring->layout.tp_frame_nr; ++i) { ring->frames[i].iov_len = ring->layout.tp_frame_size; ring->frames[i].iov_base = ring->mm_space + (i * ring->layout.tp_frame_size); } } void bind_rx_ring(int sock, struct ring *ring, int ifindex) { int ret; /* * The RX_RING registers itself to the networking stack with * dev_add_pack(), so we have one single RX_RING for all devs * otherwise you'll get the packet twice. */ fmemset(&ring->s_ll, 0, sizeof(ring->s_ll)); ring->s_ll.sll_family = AF_PACKET; ring->s_ll.sll_protocol = htons(ETH_P_ALL); ring->s_ll.sll_ifindex = ifindex; ring->s_ll.sll_hatype = 0; ring->s_ll.sll_halen = 0; ring->s_ll.sll_pkttype = 0; ret = bind(sock, (struct sockaddr *) &ring->s_ll, sizeof(ring->s_ll)); if (ret < 0) { destroy_rx_ring(sock, ring); panic("Cannot bind RX_RING!\n"); } } netsniff-ng-0.5.7/src/ring.h0000664000175000017500000001036411773367375016021 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #ifndef RING_H #define RING_H /* * "I love the smell of 10GbE in the morning. Smells like ... victory." * - W. Richard Stevens, "Secret Teachings of the UNIX Environment" */ #include #include #include #include #include #include #include #include #include #include "xutils.h" #include "built_in.h" #include "mtrand.h" #include "die.h" #ifndef PACKET_FANOUT # define PACKET_FANOUT 18 # define PACKET_FANOUT_POLICY_HASH 0 # define PACKET_FANOUT_POLICY_LB 1 # define PACKET_FANOUT_POLICY_DEFAULT PACKET_FANOUT_HASH #endif struct frame_map { struct tpacket_hdr tp_h __aligned_tpacket; struct sockaddr_ll s_ll __aligned_tpacket; }; struct ring { struct iovec *frames __cacheline_aligned; uint8_t *mm_space __cacheline_aligned; size_t mm_len; struct tpacket_req layout; struct sockaddr_ll s_ll; }; static inline void next_slot(unsigned int *it, struct ring *ring) { (*it)++; atomic_cmp_swp(it, ring->layout.tp_frame_nr, 0); } static inline void next_slot_prerd(unsigned int *it, struct ring *ring) { (*it)++; atomic_cmp_swp(it, ring->layout.tp_frame_nr, 0); prefetch_rd_hi(ring->frames[*it].iov_base); } static inline void next_slot_prewr(unsigned int *it, struct ring *ring) { (*it)++; atomic_cmp_swp(it, ring->layout.tp_frame_nr, 0); prefetch_wr_hi(ring->frames[*it].iov_base); } static inline void next_rnd_slot(unsigned int *it, struct ring *ring) { *it = mt_rand_int32() % ring->layout.tp_frame_nr; } #define RING_SIZE_FALLBACK (1 << 26) static inline unsigned int ring_size(char *ifname, unsigned int size) { if (size > 0) return size; /* * Device bitrate in bytes times two as ring size. * Fallback => ~ 64,00 MB * 10 MBit => ~ 2,38 MB * 54 MBit => ~ 12,88 MB * 100 MBit => ~ 23,84 MB * 300 MBit => ~ 71,52 MB * 1.000 MBit => ~ 238,42 MB * 10.000 MBit => ~ 2.384.18 MB */ size = device_bitrate(ifname); size = (size * 1000000) / 8; size = size * 2; if (size == 0) size = RING_SIZE_FALLBACK; return round_up_cacheline(size); } enum ring_mode { RING_MODE_EGRESS, RING_MODE_INGRESS, }; static inline unsigned int ring_frame_size(struct ring *ring) { return ring->layout.tp_frame_size; } static inline void tpacket_hdr_clone(struct tpacket_hdr *thdrd, struct tpacket_hdr *thdrs) { thdrd->tp_sec = thdrs->tp_sec; thdrd->tp_usec = thdrs->tp_usec; thdrd->tp_snaplen = thdrs->tp_snaplen; thdrd->tp_len = thdrs->tp_len; } #ifndef POLLRDNORM # define POLLRDNORM 0x0040 #endif #ifndef POLLWRNORM # define POLLWRNORM 0x0100 #endif #ifndef POLLRDHUP # define POLLRDHUP 0x2000 #endif #define POLL_NEXT_PKT 0 #define POLL_MOVE_OUT 1 static inline void prepare_polling(int sock, struct pollfd *pfd) { memset(pfd, 0, sizeof(*pfd)); pfd->fd = sock; pfd->revents = 0; pfd->events = POLLIN | POLLRDNORM | POLLERR; } static inline void set_sockopt_fanout(int sock, unsigned int fanout_id, unsigned int fanout_type) { unsigned int fanout_arg = (fanout_id | (fanout_type << 16)); int ret = setsockopt(sock, SOL_PACKET, PACKET_FANOUT, &fanout_arg, sizeof(fanout_arg)); if (ret) panic("No packet fanout support!\n"); } #if defined(__WITH_HARDWARE_TIMESTAMPING) # include static inline void set_sockopt_hwtimestamp(int sock, const char *dev) { int timesource, ret; struct hwtstamp_config hwconfig; struct ifreq ifr; memset(&hwconfig, 0, sizeof(hwconfig)); hwconfig.tx_type = HWTSTAMP_TX_ON; hwconfig.rx_filter = HWTSTAMP_FILTER_ALL; memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); ifr.ifr_data = &hwconfig; ret = ioctl(sock, SIOCSHWTSTAMP, &ifr); if (ret < 0) return; timesource = SOF_TIMESTAMPING_RAW_HARDWARE; ret = setsockopt(sock, SOL_PACKET, PACKET_TIMESTAMP, ×ource, sizeof(timesource)); if (ret) panic("Cannot set timestamping!\n"); } #else static inline void set_sockopt_hwtimestamp(int sock, const char *dev) { return; } #endif /* defined(__WITH_HARDWARE_TIMESTAMPING) */ #endif /* RING_H */ netsniff-ng-0.5.7/src/protos.h0000664000175000017500000000210711773367375016404 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #ifndef PROTOS_H #define PROTOS_H #include "proto.h" extern struct protocol arp_ops; extern struct protocol ethernet_ops; extern struct protocol icmpv4_ops; extern struct protocol icmpv6_ops; extern struct protocol igmp_ops; extern struct protocol ip_auth_ops; extern struct protocol ip_esp_ops; extern struct protocol ipv4_ops; extern struct protocol ipv6_ops; extern struct protocol ipv6_dest_opts_ops; extern struct protocol ipv6_fragm_ops; extern struct protocol ipv6_hop_by_hop_ops; extern struct protocol ipv6_in_ipv4_ops; extern struct protocol ipv6_mobility_ops; extern struct protocol ipv6_no_next_header_ops; extern struct protocol ipv6_routing_ops; extern struct protocol none_ops; extern struct protocol tcp_ops; extern struct protocol udp_ops; extern struct protocol vlan_ops; extern struct protocol ieee80211_ops; extern struct protocol QinQ_ops; extern struct protocol mpls_uc_ops; #endif /* PROTOS_H */ netsniff-ng-0.5.7/src/proto_vlan_q_in_q.c0000664000175000017500000000251411773367375020564 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright 2012 Markus Amend , Deutsche Flugsicherung GmbH * Subject to the GPL, version 2. * * http://www.ieee802.org/1/pages/802.1ad.html */ #include #include #include /* for ntohs() */ #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "built_in.h" #include "pkt_buff.h" struct QinQhdr { uint16_t TCI; uint16_t TPID; } __packed; static void QinQ_full(struct pkt_buff *pkt) { uint16_t tci; struct QinQhdr *QinQ = (struct QinQhdr *) pkt_pull(pkt, sizeof(*QinQ)); if (QinQ == NULL) return; tci = ntohs(QinQ->TCI); tprintf(" [ VLAN QinQ "); tprintf("Prio (%d), ", (tci & 0xE000) >> 13); tprintf("DEI (%d), ", (tci & 0x1000) >> 12); tprintf("ID (%d), ", (tci & 0x0FFF)); tprintf("Proto (0x%.4x)", ntohs(QinQ->TPID)); tprintf(" ]\n"); pkt_set_proto(pkt, ð_lay2, ntohs(QinQ->TPID)); } static void QinQ_less(struct pkt_buff *pkt) { uint16_t tci; struct QinQhdr *QinQ = (struct QinQhdr *) pkt_pull(pkt, sizeof(*QinQ)); if (QinQ == NULL) return; tci = ntohs(QinQ->TCI); tprintf(" VLAN%d", (tci & 0x0FFF)); pkt_set_proto(pkt, ð_lay2, ntohs(QinQ->TPID)); } struct protocol QinQ_ops = { .key = 0x88a8, .print_full = QinQ_full, .print_less = QinQ_less, }; EXPORT_SYMBOL(QinQ_ops); netsniff-ng-0.5.7/src/proto_vlan.c0000664000175000017500000000262411773367375017240 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Copyright 2010 Emmanuel Roullit. * Subject to the GPL, version 2. */ #include #include #include /* for ntohs() */ #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "pkt_buff.h" struct vlanhdr { uint16_t h_vlan_TCI; uint16_t h_vlan_encapsulated_proto; } __attribute__((packed)); static void vlan(struct pkt_buff *pkt) { uint16_t tci; struct vlanhdr *vlan = (struct vlanhdr *) pkt_pull(pkt, sizeof(*vlan)); if (vlan == NULL) return; tci = ntohs(vlan->h_vlan_TCI); tprintf(" [ VLAN "); tprintf("Prio (%d), ", (tci & 0xE000) >> 13); tprintf("CFI (%d), ", (tci & 0x1000) >> 12); tprintf("ID (%d), ", (tci & 0x0FFF)); tprintf("Proto (0x%.4x)", ntohs(vlan->h_vlan_encapsulated_proto)); tprintf(" ]\n"); pkt_set_proto(pkt, ð_lay2, ntohs(vlan->h_vlan_encapsulated_proto)); } static void vlan_less(struct pkt_buff *pkt) { uint16_t tci; struct vlanhdr *vlan = (struct vlanhdr *) pkt_pull(pkt, sizeof(*vlan)); if (vlan == NULL) return; tci = ntohs(vlan->h_vlan_TCI); tprintf(" VLAN%d", (tci & 0x0FFF)); pkt_set_proto(pkt, ð_lay2, ntohs(vlan->h_vlan_encapsulated_proto)); } struct protocol vlan_ops = { .key = 0x8100, .print_full = vlan, .print_less = vlan_less, }; EXPORT_SYMBOL(vlan_ops); netsniff-ng-0.5.7/src/proto_udp.c0000664000175000017500000000377411773367375017077 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #include #include #include /* for ntohs() */ #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "pkt_buff.h" struct udphdr { uint16_t source; uint16_t dest; uint16_t len; uint16_t check; } __attribute__((packed)); static void udp(struct pkt_buff *pkt) { struct udphdr *udp = (struct udphdr *) pkt_pull(pkt, sizeof(*udp)); ssize_t len; uint16_t src, dest; char *src_name, *dest_name; if (udp == NULL) return; len = ntohs(udp->len) - sizeof(*udp); src = ntohs(udp->source); dest = ntohs(udp->dest); src_name = lookup_port_udp(src); dest_name = lookup_port_udp(dest); tprintf(" [ UDP "); tprintf("Port (%u", src); if (src_name) tprintf(" (%s%s%s)", colorize_start(bold), src_name, colorize_end()); tprintf(" => %u", dest); if (dest_name) tprintf(" (%s%s%s)", colorize_start(bold), dest_name, colorize_end()); tprintf("), "); if(len > pkt_len(pkt) || len < 0){ tprintf("Len (%u) %s, ", ntohs(udp->len), colorize_start_full(black, red) "invalid" colorize_end()); } tprintf("Len (%u Bytes, %u Bytes Data), ", ntohs(udp->len), len); tprintf("CSum (0x%.4x)", ntohs(udp->check)); tprintf(" ]\n"); } static void udp_less(struct pkt_buff *pkt) { struct udphdr *udp = (struct udphdr *) pkt_pull(pkt, sizeof(*udp)); uint16_t src, dest; char *src_name, *dest_name; if (udp == NULL) return; src = ntohs(udp->source); dest = ntohs(udp->dest); src_name = lookup_port_udp(src); dest_name = lookup_port_udp(dest); tprintf(" UDP %u", src); if(src_name) tprintf("(%s%s%s)", colorize_start(bold), src_name, colorize_end()); tprintf("/%u", dest); if (dest_name) tprintf("(%s%s%s)", colorize_start(bold), dest_name, colorize_end()); } struct protocol udp_ops = { .key = 0x11, .print_full = udp, .print_less = udp_less, }; EXPORT_SYMBOL(udp_ops); netsniff-ng-0.5.7/src/proto_tcp.c0000664000175000017500000000651011773367375017064 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #include #include #include #include /* for ntohs() */ #include #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "built_in.h" #include "pkt_buff.h" struct tcphdr { uint16_t source; uint16_t dest; uint32_t seq; uint32_t ack_seq; #if defined(__LITTLE_ENDIAN_BITFIELD) __extension__ uint16_t res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1; #elif defined(__BIG_ENDIAN_BITFIELD) __extension__ uint16_t doff:4, res1:4, cwr:1, ece:1, urg:1, ack:1, psh:1, rst:1, syn:1, fin:1; #else # error "Adjust your defines" #endif uint16_t window; uint16_t check; uint16_t urg_ptr; } __attribute__((packed)); static void tcp(struct pkt_buff *pkt) { struct tcphdr *tcp = (struct tcphdr *) pkt_pull(pkt, sizeof(*tcp)); uint16_t src, dest; char *src_name, *dest_name; if (tcp == NULL) return; src = ntohs(tcp->source); dest = ntohs(tcp->dest); src_name = lookup_port_tcp(src); dest_name = lookup_port_tcp(dest); tprintf(" [ TCP "); tprintf("Port (%u", src); if (src_name) tprintf(" (%s%s%s)", colorize_start(bold), src_name, colorize_end()); tprintf(" => %u", dest); if (dest_name) tprintf(" (%s%s%s)", colorize_start(bold), dest_name, colorize_end()); tprintf("), "); tprintf("SN (0x%x), ", ntohl(tcp->seq)); tprintf("AN (0x%x), ", ntohl(tcp->ack_seq)); tprintf("DataOff (%u), ", tcp->doff); tprintf("Res (%u), ", tcp->res1); tprintf("Flags ("); if (tcp->fin) tprintf("FIN "); if (tcp->syn) tprintf("SYN "); if (tcp->rst) tprintf("RST "); if (tcp->psh) tprintf("PSH "); if (tcp->ack) tprintf("ACK "); if (tcp->urg) tprintf("URG "); if (tcp->ece) tprintf("ECE "); if (tcp->cwr) tprintf("CWR "); tprintf("), "); tprintf("Window (%u), ", ntohs(tcp->window)); tprintf("CSum (0x%.4x), ", ntohs(tcp->check)); tprintf("UrgPtr (%u)", ntohs(tcp->urg_ptr)); tprintf(" ]\n"); } static void tcp_less(struct pkt_buff *pkt) { struct tcphdr *tcp = (struct tcphdr *) pkt_pull(pkt, sizeof(*tcp)); uint16_t src, dest; char *src_name, *dest_name; if (tcp == NULL) return; src = ntohs(tcp->source); dest = ntohs(tcp->dest); src_name = lookup_port_tcp(src); dest_name = lookup_port_tcp(dest); tprintf(" TCP %u", src); if(src_name) tprintf("(%s%s%s)", colorize_start(bold), src_name, colorize_end()); tprintf("/%u", dest); if(dest_name) tprintf("(%s%s%s)", colorize_start(bold), dest_name, colorize_end()); tprintf(" F%s",colorize_start(bold)); if (tcp->fin) tprintf(" FIN"); if (tcp->syn) tprintf(" SYN"); if (tcp->rst) tprintf(" RST"); if (tcp->psh) tprintf(" PSH"); if (tcp->ack) tprintf(" ACK"); if (tcp->urg) tprintf(" URG"); if (tcp->ece) tprintf(" ECE"); if (tcp->cwr) tprintf(" CWR"); tprintf("%s Win %u S/A 0x%x/0x%x", colorize_end(), ntohs(tcp->window), ntohl(tcp->seq), ntohl(tcp->ack_seq)); } struct protocol tcp_ops = { .key = 0x06, .print_full = tcp, .print_less = tcp_less, }; EXPORT_SYMBOL(tcp_ops); netsniff-ng-0.5.7/src/proto_none.c0000664000175000017500000000246211773367375017237 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #include #include #include #include "proto.h" #include "protos.h" #include "pkt_buff.h" void empty(struct pkt_buff *pkt) {} static void _hex(uint8_t *ptr, size_t len) { if (!len) return; tprintf(" [ hex "); for (; ptr && len-- > 0; ptr++) tprintf(" %.2x", *ptr); tprintf(" ]\n"); } void hex(struct pkt_buff *pkt) { size_t len = pkt_len(pkt); if (!len) return; _hex(pkt_pull(pkt, len), len); tprintf("\n"); } static void _ascii(uint8_t *ptr, size_t len) { if (!len) return; tprintf(" [ chr "); for (; ptr && len-- > 0; ptr++) tprintf("%c", isprint(*ptr) ? *ptr : '.'); tprintf(" ]\n"); } void ascii(struct pkt_buff *pkt) { size_t len = pkt_len(pkt); if (!len) return; _ascii(pkt_pull(pkt, len), len); tprintf("\n"); } void hex_ascii(struct pkt_buff *pkt) { size_t len = pkt_len(pkt); uint8_t *ptr = pkt_pull(pkt, len); if (len) { _ascii(ptr, len); _hex(ptr, len); } tprintf("\n"); } static void none_less(struct pkt_buff *pkt) { tprintf("\n"); } struct protocol none_ops = { .key = 0x01, .print_full = hex_ascii, .print_less = none_less, }; EXPORT_SYMBOL(none_ops); netsniff-ng-0.5.7/src/proto_mpls_unicast.c0000664000175000017500000000416411773367375021002 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright 2012 Markus Amend , Deutsche Flugsicherung GmbH * Subject to the GPL, version 2. * * http://tools.ietf.org/html/rfc3032 */ #include #include #include /* for ntohs() */ #include #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "built_in.h" #include "pkt_buff.h" struct mpls_uchdr { uint32_t mpls_uc_hdr; } __packed; static int mpls_uc_next_proto(struct pkt_buff *pkt) { uint8_t proto; uint16_t key = 0; if (pkt_len(pkt)) proto = *(pkt->data); else return -EIO; /* FIXME: Right now only test for IP Version field */ switch (proto >> 4) { case 4: key = 0x0800; /* IPv4*/ break; case 6: key = 0x86DD; /* IPv6*/ break; default: /* Nothing detected ... */ return -ENOENT; } return key; } static void mpls_uc_full(struct pkt_buff *pkt) { int next; uint32_t mpls_uc_data; struct mpls_uchdr *mpls_uc; uint8_t s = 0; do { mpls_uc = (struct mpls_uchdr *) pkt_pull(pkt, sizeof(*mpls_uc)); if (mpls_uc == NULL) return; mpls_uc_data = ntohl(mpls_uc->mpls_uc_hdr); s = (mpls_uc_data >> 8) & 0x1; tprintf(" [ MPLS "); tprintf("Label (%u), ", mpls_uc_data >> 12); tprintf("Exp (%u), ", (mpls_uc_data >> 9) & 0x7); tprintf("S (%u), ", s); tprintf("TTL (%u)", (mpls_uc_data & 0xFF)); tprintf(" ]\n"); } while (!s); next = mpls_uc_next_proto(pkt); if (next < 0) return; pkt_set_proto(pkt, ð_lay2, (uint16_t) next); } static void mpls_uc_less(struct pkt_buff *pkt) { int next; uint32_t mpls_uc_data; struct mpls_uchdr *mpls_uc; uint8_t s = 0; do { mpls_uc = (struct mpls_uchdr *) pkt_pull(pkt, sizeof(*mpls_uc)); if (mpls_uc == NULL) return; mpls_uc_data = ntohl(mpls_uc->mpls_uc_hdr); s = (mpls_uc_data >> 8) & 0x1; tprintf(" MPLS/%u", mpls_uc_data >> 12); } while (!s); next = mpls_uc_next_proto(pkt); if (next < 0) return; pkt_set_proto(pkt, ð_lay2, (uint16_t) next); } struct protocol mpls_uc_ops = { .key = 0x8847, .print_full = mpls_uc_full, .print_less = mpls_uc_less, }; EXPORT_SYMBOL(mpls_uc_ops); netsniff-ng-0.5.7/src/proto_ipv6_routing.c0000664000175000017500000000771711773367375020743 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright 2012 Markus Amend , Deutsche Flugsicherung GmbH * Subject to the GPL, version 2. * * IPv6 Routing Header described in RFC2460 */ #include #include #include /* for ntohs() and "struct in6_addr" */ #include /* for inet_ntop() */ #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "built_in.h" #include "pkt_buff.h" #define ROUTING_HEADER_TYPE_0 0x00 struct routinghdr { uint8_t h_next_header; uint8_t h_hdr_ext_len; uint8_t h_routing_type; uint8_t h_segments_left; } __packed; struct routinghdr_0 { uint32_t reserved; uint32_t addresses[0]; } __packed; static void dissect_routinghdr_type_0(struct pkt_buff *pkt, ssize_t *data_len, int less) { uint8_t num_addr; char address[INET6_ADDRSTRLEN]; struct in6_addr *addr; struct routinghdr_0 *routing_0; routing_0 = (struct routinghdr_0 *) pkt_pull(pkt, sizeof(*routing_0)); *data_len -= sizeof(*routing_0); if (routing_0 == NULL || *data_len > pkt_len(pkt) || *data_len < 0) return; if (less) { tprintf("Addresses (%u)", *data_len / sizeof(struct in6_addr)); return; } tprintf("Res (0x%x)", routing_0->reserved); num_addr = *data_len / sizeof(*addr); while (num_addr--) { addr = (struct in6_addr *) pkt_pull(pkt, sizeof(*addr)); *data_len -= sizeof(*addr); if (addr == NULL || *data_len > pkt_len(pkt) || *data_len < 0) return; tprintf("\n\t Address: %s", inet_ntop(AF_INET6, addr, address, sizeof(address))); } } static inline void dissect_routinghdr_type_0_norm(struct pkt_buff *pkt, ssize_t *data_len) { dissect_routinghdr_type_0(pkt, data_len, 0); } static inline void dissect_routinghdr_type_0_less(struct pkt_buff *pkt, ssize_t *data_len) { dissect_routinghdr_type_0(pkt, data_len, 1); } static void routing(struct pkt_buff *pkt) { uint16_t hdr_ext_len; ssize_t data_len; struct routinghdr *routing; routing = (struct routinghdr *) pkt_pull(pkt, sizeof(*routing)); if (routing == NULL) return; /* Total Header Length in Bytes */ hdr_ext_len = (routing->h_hdr_ext_len + 1) * 8; /* Data length in Bytes */ data_len = hdr_ext_len - sizeof(*routing); tprintf("\t [ Routing "); tprintf("NextHdr (%u), ", routing->h_next_header); if (data_len > pkt_len(pkt) || data_len < 0){ tprintf("HdrExtLen (%u, %u Bytes %s), ", routing->h_hdr_ext_len, hdr_ext_len, colorize_start_full(black, red) "invalid" colorize_end()); return; } tprintf("HdrExtLen (%u, %u Bytes), ", routing->h_hdr_ext_len, hdr_ext_len); tprintf("Type (%u), ", routing->h_routing_type); tprintf("Left (%u), ", routing->h_segments_left); switch (routing->h_routing_type) { case ROUTING_HEADER_TYPE_0: dissect_routinghdr_type_0_norm(pkt, &data_len); break; default: tprintf("Type %u is unknown", routing->h_routing_type); } tprintf(" ]\n"); if (data_len > pkt_len(pkt) || data_len < 0) return; pkt_pull(pkt, data_len); pkt_set_proto(pkt, ð_lay3, routing->h_next_header); } static void routing_less(struct pkt_buff *pkt) { uint16_t hdr_ext_len; ssize_t data_len; struct routinghdr *routing; routing = (struct routinghdr *) pkt_pull(pkt, sizeof(*routing)); if (routing == NULL) return; /* Total Header Length in Bytes */ hdr_ext_len = (routing->h_hdr_ext_len + 1) * 8; /* Data length in Bytes */ data_len = hdr_ext_len - sizeof(*routing); if (data_len > pkt_len(pkt) || data_len < 0) return; tprintf(" Routing "); switch (routing->h_routing_type) { case ROUTING_HEADER_TYPE_0: dissect_routinghdr_type_0_less(pkt, &data_len); break; default: tprintf("Type %u is unknown", routing->h_routing_type); } if (data_len > pkt_len(pkt) || data_len < 0) return; pkt_pull(pkt, data_len); pkt_set_proto(pkt, ð_lay3, routing->h_next_header); } struct protocol ipv6_routing_ops = { .key = 0x2B, .print_full = routing, .print_less = routing_less, }; EXPORT_SYMBOL(ipv6_routing_ops); netsniff-ng-0.5.7/src/proto_ipv6_no_nxt_hdr.c0000664000175000017500000000217011773367375021402 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright 2012 Markus Amend , Deutsche Flugsicherung GmbH * Subject to the GPL, version 2. * * IPv6 No Next Header described in RFC2460 */ #include #include #include /* for ntohs() */ #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "built_in.h" static void no_next_header(struct pkt_buff *pkt) { /* * The value 59 in the Next Header field of an IPv6 header or any * extension header indicates that there is nothing following that * header. If the Payload Length field of the IPv6 header indicates the * presence of octets past the end of a header whose Next Header field * contains 59, those octets must be ignored, and passed on unchanged if * the packet is forwarded. */ tprintf(" [ No Next Header"); tprintf(" ]\n"); } static void no_next_header_less(struct pkt_buff *pkt) { tprintf(" No Next Header"); } struct protocol ipv6_no_next_header_ops = { .key = 0x3B, .print_full = no_next_header, .print_less = no_next_header_less, }; EXPORT_SYMBOL(ipv6_no_next_header_ops); netsniff-ng-0.5.7/src/proto_ipv6_mobility_hdr.c0000664000175000017500000002040711773367375021730 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright 2012 Markus Amend , Deutsche Flugsicherung GmbH * Subject to the GPL, version 2. * * IPv6 Mobility Header described in RFC6275 */ #include #include #include /* for ntohs() */ #include #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "built_in.h" #include "pkt_buff.h" #define BINDING_REFRESH_REQUEST_MESSAGE 0x00 #define HOME_TEST_INIT_MESSAGE 0x01 #define CARE_OF_TEST_INIT_MESSAGE 0x02 #define HOME_TEST_MESSAGE 0x03 #define CARE_OF_TEST_MESSAGE 0x04 #define BINDING_UPDATE_MESSAGE 0x05 #define BINDING_ACKNOWLEDGEMENT_MESSAGE 0x06 #define BINDING_ERROR_MESSAGE 0x07 struct mobilityhdr { uint8_t payload_proto; uint8_t hdr_len; uint8_t MH_type; uint8_t reserved; uint16_t chksum; uint8_t msgdata[0]; } __packed; struct bin_refr_req_msg { uint16_t reserved; uint8_t mobility_opt[0]; } __packed; /* for 0x01 and 0x02 */ struct tst_init_msg { uint16_t reserved; uint64_t init_cookie; uint8_t mobility_opt[0]; } __packed; /* for 0x03 and 0x04 */ struct tst_msg { uint16_t nonce_index; uint64_t init_cookie; uint64_t keygen_token; uint8_t mobility_opt[0]; } __packed; struct bind_upd_msg { uint16_t sequence; uint16_t ahlk_res; uint16_t lifetime; uint8_t mobility_opt[0]; } __packed; struct bind_ack_msg { uint8_t status; uint8_t k_res; uint16_t sequence; uint16_t lifetime; uint8_t mobility_opt[0]; } __packed; struct bind_err_msg { uint8_t status; uint8_t res; uint64_t home_addr; uint8_t mobility_opt[0]; } __packed; static void dissect_mobility_options(struct pkt_buff *pkt, ssize_t *message_data_len) { /* Have to been upgraded. * http://tools.ietf.org/html/rfc6275#section-6.2.1 */ if (*message_data_len) tprintf("MH Option(s) recognized "); /* If adding dissector reduce message_data_len for each using of * pkt_pull to the same size. */ } static void dissect_mobilityhdr_type_0(struct pkt_buff *pkt, ssize_t *message_data_len) { struct bin_refr_req_msg *type_0; type_0 = (struct bin_refr_req_msg *) pkt_pull(pkt, sizeof(*type_0)); *message_data_len -= sizeof(*type_0); if (type_0 == NULL || *message_data_len > pkt_len(pkt) || *message_data_len < 0) return; dissect_mobility_options(pkt, message_data_len); } static void dissect_mobilityhdr_type_1_2(struct pkt_buff *pkt, ssize_t *message_data_len) { struct tst_init_msg *type_1_2; type_1_2 = (struct tst_init_msg *) pkt_pull(pkt, sizeof(*type_1_2)); *message_data_len -= sizeof(*type_1_2); if (type_1_2 == NULL || *message_data_len > pkt_len(pkt) || *message_data_len < 0) return; tprintf("Init Cookie (0x%x)", ntohll(type_1_2->init_cookie)); dissect_mobility_options(pkt, message_data_len); } static void dissect_mobilityhdr_type_3_4(struct pkt_buff *pkt, ssize_t *message_data_len) { struct tst_msg *type_3_4; type_3_4 = (struct tst_msg *) pkt_pull(pkt, sizeof(*type_3_4)); *message_data_len -= sizeof(*type_3_4); if (type_3_4 == NULL || *message_data_len > pkt_len(pkt) || *message_data_len < 0) return; tprintf("HN Index (%u) ", ntohs(type_3_4->nonce_index)); tprintf("Init Cookie (0x%x) ", ntohll(type_3_4->init_cookie)); tprintf("Keygen Token (0x%x)", ntohll(type_3_4->keygen_token)); dissect_mobility_options(pkt, message_data_len); } static void dissect_mobilityhdr_type_5(struct pkt_buff *pkt, ssize_t *message_data_len) { struct bind_upd_msg *type_5; type_5 = (struct bind_upd_msg *) pkt_pull(pkt, sizeof(*type_5)); *message_data_len -= sizeof(*type_5); if (type_5 == NULL || *message_data_len > pkt_len(pkt) || *message_data_len < 0) return; tprintf("Sequence (0x%x) ", ntohs(type_5->sequence)); tprintf("A|H|L|K (0x%x) ", ntohs(type_5->ahlk_res) >> 12); tprintf("Lifetime (%us)", ntohs(type_5->lifetime) * 4); dissect_mobility_options(pkt, message_data_len); } static void dissect_mobilityhdr_type_6(struct pkt_buff *pkt, ssize_t *message_data_len) { struct bind_ack_msg *type_6; type_6 = (struct bind_ack_msg *) pkt_pull(pkt, sizeof(*type_6)); *message_data_len -= sizeof(*type_6); if (type_6 == NULL || *message_data_len > pkt_len(pkt) || *message_data_len < 0) return; tprintf("Status (0x%x) ", type_6->status); tprintf("K (%u) ", type_6->k_res >> 7); tprintf("Sequence (0x%x)", ntohs(type_6->sequence)); tprintf("Lifetime (%us)", ntohs(type_6->lifetime) * 4); dissect_mobility_options(pkt, message_data_len); } static void dissect_mobilityhdr_type_7(struct pkt_buff *pkt, ssize_t *message_data_len) { char address[INET6_ADDRSTRLEN]; uint64_t addr; struct bind_err_msg *type_7; type_7 = (struct bind_err_msg *) pkt_pull(pkt, sizeof(*type_7)); *message_data_len -= sizeof(*type_7); addr = ntohll(type_7->home_addr); if (type_7 == NULL || *message_data_len > pkt_len(pkt) || *message_data_len < 0) return; tprintf("Status (0x%x) ", type_7->status); tprintf("Home Addr (%s)", inet_ntop(AF_INET6, &addr, address, sizeof(address))); dissect_mobility_options(pkt, message_data_len); } static void get_mh_type(struct pkt_buff *pkt, ssize_t *message_data_len, uint8_t *mh_type) { switch (*mh_type) { case BINDING_REFRESH_REQUEST_MESSAGE: tprintf("Binding Refresh Request Message "); dissect_mobilityhdr_type_0(pkt, message_data_len); break; case HOME_TEST_INIT_MESSAGE: tprintf("Home Test Init Message "); dissect_mobilityhdr_type_1_2(pkt, message_data_len); break; case CARE_OF_TEST_INIT_MESSAGE: tprintf("Care-of Test Init Message "); dissect_mobilityhdr_type_1_2(pkt, message_data_len); break; case HOME_TEST_MESSAGE: tprintf("Binding Refresh Request Message "); dissect_mobilityhdr_type_3_4(pkt, message_data_len); break; case CARE_OF_TEST_MESSAGE: tprintf("Binding Refresh Request Message "); dissect_mobilityhdr_type_3_4(pkt, message_data_len); break; case BINDING_UPDATE_MESSAGE: tprintf("Binding Refresh Request Message "); dissect_mobilityhdr_type_5(pkt, message_data_len); break; case BINDING_ACKNOWLEDGEMENT_MESSAGE: tprintf("Binding Refresh Request Message "); dissect_mobilityhdr_type_6(pkt, message_data_len); break; case BINDING_ERROR_MESSAGE: tprintf("Binding Refresh Request Message "); dissect_mobilityhdr_type_7(pkt, message_data_len); break; default: tprintf("Type %u is unknown. Error", *mh_type); } } static void mobility(struct pkt_buff *pkt) { uint16_t hdr_ext_len; ssize_t message_data_len; struct mobilityhdr *mobility; mobility = (struct mobilityhdr *) pkt_pull(pkt, sizeof(*mobility)); if (mobility == NULL) return; /* Total Header Length in Bytes */ hdr_ext_len = (mobility->hdr_len + 1) * 8; /* Total Message Data length in Bytes*/ message_data_len = (hdr_ext_len - sizeof(*mobility)); tprintf("\t [ Mobility "); tprintf("NextHdr (%u), ", mobility->payload_proto); if (message_data_len > pkt_len(pkt) || message_data_len < 0){ tprintf("HdrExtLen (%u, %u Bytes %s), ", mobility->hdr_len, hdr_ext_len, colorize_start_full(black, red) "invalid" colorize_end()); return; } tprintf("HdrExtLen (%u, %u Bytes), ", mobility->hdr_len, hdr_ext_len); tprintf("MH Type (%u), ", mobility->MH_type); tprintf("Res (0x%x), ", mobility->reserved); tprintf("Chks (0x%x), ", ntohs(mobility->chksum)); tprintf("MH Data "); get_mh_type(pkt, &message_data_len, &mobility->MH_type); tprintf(" ]\n"); if (message_data_len > pkt_len(pkt) || message_data_len < 0) return; pkt_pull(pkt, message_data_len); pkt_set_proto(pkt, ð_lay3, mobility->payload_proto); } static void mobility_less(struct pkt_buff *pkt) { uint16_t hdr_ext_len; ssize_t message_data_len; struct mobilityhdr *mobility; mobility = (struct mobilityhdr *) pkt_pull(pkt, sizeof(*mobility)); if (mobility == NULL) return; /* Total Header Length in Bytes */ hdr_ext_len = (mobility->hdr_len + 1) * 8; /* Total Message Data length in Bytes*/ message_data_len = (hdr_ext_len - sizeof(*mobility)); if (message_data_len > pkt_len(pkt) || message_data_len < 0) return; tprintf(" Mobility Type (%u), ", mobility->MH_type); pkt_pull(pkt, message_data_len); pkt_set_proto(pkt, ð_lay3, mobility->payload_proto); } struct protocol ipv6_mobility_ops = { .key = 0x87, .print_full = mobility, .print_less = mobility_less, }; EXPORT_SYMBOL(ipv6_mobility_ops); netsniff-ng-0.5.7/src/proto_ipv6_in_ipv4.c0000664000175000017500000000115311773367375020610 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright 2012 Markus Amend , Deutsche Flugsicherung GmbH * Subject to the GPL, version 2. * * IPv6 in IPv4 encapsulation described in RFC3056 */ #include #include #include /* for ntohs() */ #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "built_in.h" extern void ipv6(struct pkt_buff *pkt); extern void ipv6_less(struct pkt_buff *pkt); struct protocol ipv6_in_ipv4_ops = { .key = 0x29, .print_full = ipv6, .print_less = ipv6_less, }; EXPORT_SYMBOL(ipv6_in_ipv4_ops); netsniff-ng-0.5.7/src/proto_ipv6_hop_by_hop.c0000664000175000017500000000463011773367375021371 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright 2012 Markus Amend , Deutsche Flugsicherung GmbH * Subject to the GPL, version 2. * * IPv6 Hop-By-Hop Header described in RFC2460 */ #include #include #include /* for ntohs() */ #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "built_in.h" #include "pkt_buff.h" struct hop_by_hophdr { uint8_t h_next_header; uint8_t hdr_len; } __packed; static void dissect_opt_hop (struct pkt_buff *pkt, ssize_t *opt_len) { /* Have to been upgraded. * http://tools.ietf.org/html/rfc2460#section-4.2 * Look also for proto_ipv6_dest_opts.h, it needs * dissect_opt(), too. */ if (*opt_len) tprintf(", Option(s) recognized "); /* If adding dissector reduce opt_len for each using of pkt_pull * to the same size. */ } static void hop_by_hop(struct pkt_buff *pkt) { uint16_t hdr_ext_len; ssize_t opt_len; struct hop_by_hophdr *hop_ops; hop_ops = (struct hop_by_hophdr *) pkt_pull(pkt, sizeof(*hop_ops)); if (hop_ops == NULL) return; /* Total Header Length in Bytes */ hdr_ext_len = (hop_ops->hdr_len + 1) * 8; /* Options length in Bytes */ opt_len = hdr_ext_len - sizeof(*hop_ops); tprintf("\t [ Hop-by-Hop Options "); tprintf("NextHdr (%u), ", hop_ops->h_next_header); if (opt_len > pkt_len(pkt) || opt_len < 0){ tprintf("HdrExtLen (%u, %u Bytes, %s)", hop_ops->hdr_len, hdr_ext_len, colorize_start_full(black, red) "invalid" colorize_end()); return; } tprintf("HdrExtLen (%u, %u Bytes)", hop_ops->hdr_len, hdr_ext_len); dissect_opt_hop(pkt, &opt_len); tprintf(" ]\n"); pkt_pull(pkt, opt_len); pkt_set_proto(pkt, ð_lay3, hop_ops->h_next_header); } static void hop_by_hop_less(struct pkt_buff *pkt) { uint16_t hdr_ext_len; ssize_t opt_len; struct hop_by_hophdr *hop_ops; hop_ops = (struct hop_by_hophdr *) pkt_pull(pkt, sizeof(*hop_ops)); if (hop_ops == NULL) return; /* Total Header Length in Bytes */ hdr_ext_len = (hop_ops->hdr_len + 1) * 8; /* Options length in Bytes */ opt_len = hdr_ext_len - sizeof(*hop_ops); if (opt_len > pkt_len(pkt) || opt_len < 0) return; tprintf(" Hop Ops"); pkt_pull(pkt, opt_len); pkt_set_proto(pkt, ð_lay3, hop_ops->h_next_header); } struct protocol ipv6_hop_by_hop_ops = { .key = 0x0, .print_full = hop_by_hop, .print_less = hop_by_hop_less, }; EXPORT_SYMBOL(ipv6_hop_by_hop_ops); netsniff-ng-0.5.7/src/proto_ipv6_fragm.c0000664000175000017500000000333711773367375020342 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright 2012 Markus Amend , Deutsche Flugsicherung GmbH * Subject to the GPL, version 2. * * IPv6 Fragmentation Header described in RFC2460 */ #include #include #include /* for ntohs() */ #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "built_in.h" #include "pkt_buff.h" struct fragmhdr { uint8_t h_fragm_next_header; uint8_t h_fragm_reserved; uint16_t h_fragm_off_res_M; uint32_t h_fragm_identification; } __packed; static void fragm(struct pkt_buff *pkt) { uint16_t off_res_M; struct fragmhdr *fragm_ops; fragm_ops = (struct fragmhdr *) pkt_pull(pkt, sizeof(*fragm_ops)); if (fragm_ops == NULL) return; off_res_M = ntohs(fragm_ops->h_fragm_off_res_M); tprintf("\t [ Fragment "); tprintf("NextHdr (%u), ", fragm_ops->h_fragm_next_header); tprintf("Reserved (%u), ", fragm_ops->h_fragm_reserved); tprintf("Offset (%u), ", off_res_M >> 3); tprintf("Res (%u), ", (off_res_M >> 1) & 0x3); tprintf("M flag (%u), ", off_res_M & 0x1); tprintf("Identification (%u)", ntohl(fragm_ops->h_fragm_identification)); tprintf(" ]\n"); pkt_set_proto(pkt, ð_lay3, fragm_ops->h_fragm_next_header); } static void fragm_less(struct pkt_buff *pkt) { uint16_t off_res_M; struct fragmhdr *fragm_ops; fragm_ops = (struct fragmhdr *) pkt_pull(pkt, sizeof(*fragm_ops)); if (fragm_ops == NULL) return; off_res_M = ntohs(fragm_ops->h_fragm_off_res_M); tprintf(" FragmOffs %u", off_res_M >> 3); pkt_set_proto(pkt, ð_lay3, fragm_ops->h_fragm_next_header); } struct protocol ipv6_fragm_ops = { .key = 0x2C, .print_full = fragm, .print_less = fragm_less, }; EXPORT_SYMBOL(ipv6_fragm_ops); netsniff-ng-0.5.7/src/proto_ipv6_dest_opts.c0000664000175000017500000000465511773367375021256 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright 2012 Markus Amend , Deutsche Flugsicherung GmbH * Subject to the GPL, version 2. * * IPv6 Destination Options Header described in RFC2460 */ #include #include #include /* for ntohs() */ #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "built_in.h" #include "pkt_buff.h" struct dest_optshdr { uint8_t h_next_header; uint8_t hdr_len; } __packed; static void dissect_opt_dest(struct pkt_buff *pkt, ssize_t *opt_len) { /* Have to been upgraded. * http://tools.ietf.org/html/rfc2460#section-4.2 * Look also for proto_ipv6_hop_by_hop.h, it needs * dissect_opt(), too. */ if (*opt_len) tprintf(", Option(s) recognized "); /* If adding dissector reduce opt_len for each using of pkt_pull * to the same size. */ } static void dest_opts(struct pkt_buff *pkt) { uint16_t hdr_ext_len; ssize_t opt_len; struct dest_optshdr *dest_ops; dest_ops = (struct dest_optshdr *) pkt_pull(pkt, sizeof(*dest_ops)); if (dest_ops == NULL) return; /* Total Header Length in Bytes */ hdr_ext_len = (dest_ops->hdr_len + 1) * 8; /* Options length in Bytes */ opt_len = hdr_ext_len - sizeof(*dest_ops); tprintf("\t [ Destination Options "); tprintf("NextHdr (%u), ", dest_ops->h_next_header); if (opt_len > pkt_len(pkt) || opt_len < 0) { tprintf("HdrExtLen (%u, %u Bytes, %s)", dest_ops->hdr_len, hdr_ext_len, colorize_start_full(black, red) "invalid" colorize_end()); return; } tprintf("HdrExtLen (%u, %u Bytes)", dest_ops->hdr_len, hdr_ext_len); dissect_opt_dest(pkt, &opt_len); tprintf(" ]\n"); pkt_pull(pkt, opt_len); pkt_set_proto(pkt, ð_lay3, dest_ops->h_next_header); } static void dest_opts_less(struct pkt_buff *pkt) { uint16_t hdr_ext_len; ssize_t opt_len; struct dest_optshdr *dest_ops; dest_ops = (struct dest_optshdr *) pkt_pull(pkt, sizeof(*dest_ops)); if (dest_ops == NULL) return; /* Total Header Length in Bytes */ hdr_ext_len = (dest_ops->hdr_len + 1) * 8; /* Options length in Bytes */ opt_len = hdr_ext_len - sizeof(*dest_ops); if (opt_len > pkt_len(pkt) || opt_len < 0) return; tprintf(" Dest Ops"); pkt_pull(pkt, opt_len); pkt_set_proto(pkt, ð_lay3, dest_ops->h_next_header); } struct protocol ipv6_dest_opts_ops = { .key = 0x3C, .print_full = dest_opts, .print_less = dest_opts_less, }; EXPORT_SYMBOL(ipv6_dest_opts_ops); netsniff-ng-0.5.7/src/proto_ipv6.c0000664000175000017500000000505611773367375017166 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Copyright 2010 Emmanuel Roullit. * Subject to the GPL, version 2. */ #include #include #include /* for ntohs() */ #include /* for inet_ntop() */ #include #include "proto.h" #include "protos.h" #include "csum.h" #include "dissector_eth.h" #include "pkt_buff.h" #include "built_in.h" /* * IPv6 fixed header * * BEWARE, it is incorrect. The first 4 bits of flow_lbl * are glued to priority now, forming "class". */ struct ipv6hdr { #if defined(__LITTLE_ENDIAN_BITFIELD) __extension__ uint8_t priority:4, version:4; #elif defined(__BIG_ENDIAN_BITFIELD) __extension__ uint8_t version:4, priority:4; #else # error "Please fix " #endif uint8_t flow_lbl[3]; uint16_t payload_len; uint8_t nexthdr; uint8_t hop_limit; struct in6_addr saddr; struct in6_addr daddr; } __packed; extern void ipv6(struct pkt_buff *pkt); extern void ipv6_less(struct pkt_buff *pkt); void ipv6(struct pkt_buff *pkt) { uint8_t traffic_class; uint32_t flow_label; char src_ip[INET6_ADDRSTRLEN]; char dst_ip[INET6_ADDRSTRLEN]; struct ipv6hdr *ip = (struct ipv6hdr *) pkt_pull(pkt, sizeof(*ip)); if (ip == NULL) return; traffic_class = (ip->priority << 4) | ((ip->flow_lbl[0] & 0xF0) >> 4); flow_label = ((ip->flow_lbl[0] & 0x0F) << 8) | (ip->flow_lbl[1] << 4) | ip->flow_lbl[2]; inet_ntop(AF_INET6, &ip->saddr, src_ip, sizeof(src_ip)); inet_ntop(AF_INET6, &ip->daddr, dst_ip, sizeof(dst_ip)); tprintf(" [ IPv6 "); tprintf("Addr (%s => %s), ", src_ip, dst_ip); tprintf("Version (%u), ", ip->version); tprintf("TrafficClass (%u), ", traffic_class); tprintf("FlowLabel (%u), ", flow_label); tprintf("Len (%u), ", ntohs(ip->payload_len)); tprintf("NextHdr (%u), ", ip->nexthdr); tprintf("HopLimit (%u)", ip->hop_limit); tprintf(" ]\n"); pkt_set_proto(pkt, ð_lay3, ip->nexthdr); } void ipv6_less(struct pkt_buff *pkt) { char src_ip[INET6_ADDRSTRLEN]; char dst_ip[INET6_ADDRSTRLEN]; struct ipv6hdr *ip = (struct ipv6hdr *) pkt_pull(pkt, sizeof(*ip)); if (ip == NULL) return; inet_ntop(AF_INET6, &ip->saddr, src_ip, sizeof(src_ip)); inet_ntop(AF_INET6, &ip->daddr, dst_ip, sizeof(dst_ip)); tprintf(" %s/%s Len %u", src_ip, dst_ip, ntohs(ip->payload_len)); pkt_set_proto(pkt, ð_lay3, ip->nexthdr); } struct protocol ipv6_ops = { .key = 0x86DD, .print_full = ipv6, .print_less = ipv6_less, }; EXPORT_SYMBOL(ipv6_ops); netsniff-ng-0.5.7/src/proto_ipv4.c0000664000175000017500000001250411773367375017160 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann . * Copyright (C) 2009, 2010 Daniel Borkmann * Copyright (C) 2012 Christoph Jaeger * Subject to the GPL, version 2. */ #include #include #include /* for ntohs() */ #include /* for inet_ntop() */ #include #include "proto.h" #include "protos.h" #include "csum.h" #include "dissector_eth.h" #include "pkt_buff.h" #include "built_in.h" struct ipv4hdr { #if defined(__LITTLE_ENDIAN_BITFIELD) __extension__ uint8_t h_ihl:4, h_version:4; #elif defined (__BIG_ENDIAN_BITFIELD) __extension__ uint8_t h_version:4, h_ihl:4; #else # error "Please fix " #endif uint8_t h_tos; uint16_t h_tot_len; uint16_t h_id; uint16_t h_frag_off; uint8_t h_ttl; uint8_t h_protocol; uint16_t h_check; uint32_t h_saddr; uint32_t h_daddr; } __packed; #define FRAG_OFF_RESERVED_FLAG(x) ((x) & 0x8000) #define FRAG_OFF_NO_FRAGMENT_FLAG(x) ((x) & 0x4000) #define FRAG_OFF_MORE_FRAGMENT_FLAG(x) ((x) & 0x2000) #define FRAG_OFF_FRAGMENT_OFFSET(x) ((x) & 0x1fff) /* IP Option Numbers (http://www.iana.org/assignments/ip-parameters) */ #define IP_OPT_EOOL 0x00 #define IP_OPT_NOP 0x01 #define IP_OPT_COPIED_FLAG(x) ((x) & 0x80) #define IP_OPT_CLASS(x) (((x) & 0x60) >> 5) #define IP_OPT_NUMBER(x) ((x) & 0x1F) static void ipv4(struct pkt_buff *pkt) { uint16_t csum, frag_off, h_tot_len; char src_ip[INET_ADDRSTRLEN]; char dst_ip[INET_ADDRSTRLEN]; struct ipv4hdr *ip = (struct ipv4hdr *) pkt_pull(pkt, sizeof(*ip)); uint8_t *opt, *trailer; unsigned int trailer_len = 0; ssize_t opts_len, opt_len; if (!ip) return; frag_off = ntohs(ip->h_frag_off); h_tot_len = ntohs(ip->h_tot_len); csum = calc_csum(ip, ip->h_ihl * 4, 0); inet_ntop(AF_INET, &ip->h_saddr, src_ip, sizeof(src_ip)); inet_ntop(AF_INET, &ip->h_daddr, dst_ip, sizeof(dst_ip)); if ((pkt_len(pkt) + sizeof(*ip)) > h_tot_len) { trailer_len = pkt_len(pkt) + sizeof(*ip) - h_tot_len; trailer = pkt->data + h_tot_len + trailer_len; } if (trailer_len) { tprintf(" [ Eth trailer "); while (trailer_len--) { tprintf("%x", *(trailer - trailer_len)); } tprintf(" ]\n"); } tprintf(" [ IPv4 "); tprintf("Addr (%s => %s), ", src_ip, dst_ip); tprintf("Proto (%u), ", ip->h_protocol); tprintf("TTL (%u), ", ip->h_ttl); tprintf("TOS (%u), ", ip->h_tos); tprintf("Ver (%u), ", ip->h_version); tprintf("IHL (%u), ", ip->h_ihl); tprintf("Tlen (%u), ", ntohs(ip->h_tot_len)); tprintf("ID (%u), ", ntohs(ip->h_id)); tprintf("Res (%u), NoFrag (%u), MoreFrag (%u), FragOff (%u), ", FRAG_OFF_RESERVED_FLAG(frag_off) ? 1 : 0, FRAG_OFF_NO_FRAGMENT_FLAG(frag_off) ? 1 : 0, FRAG_OFF_MORE_FRAGMENT_FLAG(frag_off) ? 1 : 0, FRAG_OFF_FRAGMENT_OFFSET(frag_off)); tprintf("CSum (0x%.4x) is %s", ntohs(ip->h_check), csum ? colorize_start_full(black, red) "bogus (!)" colorize_end() : "ok"); if (csum) tprintf("%s should be 0x%.4x%s", colorize_start_full(black, red), csum_expected(ip->h_check, csum), colorize_end()); tprintf(" ]\n"); opts_len = max((uint8_t) ip->h_ihl, sizeof(*ip) / sizeof(uint32_t)) * sizeof(uint32_t) - sizeof(*ip); for (opt = pkt_pull(pkt, opts_len); opt && opts_len > 0; opt++) { tprintf(" [ Option Copied (%u), Class (%u), Number (%u)", IP_OPT_COPIED_FLAG(*opt) ? 1 : 0, IP_OPT_CLASS(*opt), IP_OPT_NUMBER(*opt)); switch (*opt) { case IP_OPT_EOOL: case IP_OPT_NOP: tprintf(" ]\n"); opts_len--; break; default: /* * Assuming that EOOL and NOP are the only single-byte * options, treat all other options as variable in * length with a minimum of 2. * * TODO: option length might be incorrect in malformed packets, * check and handle that */ opt_len = *(++opt); if (opt_len > opts_len) { tprintf(", Len (%u, invalid) ]\n", opt_len); goto out; } else tprintf(", Len (%u) ]\n", opt_len); opts_len -= opt_len; tprintf(" [ Data hex "); for (opt_len -= 2; opt_len > 0; opt_len--) tprintf(" %.2x", *(++opt)); tprintf(" ]\n"); break; } } out: /* cut off everything that is not part of IPv4 payload */ /* XXX there could still be an Ethernet trailer included or others */ pkt_trim(pkt, pkt_len(pkt) - min(pkt_len(pkt), (ntohs(ip->h_tot_len) - ip->h_ihl * sizeof(uint32_t)))); pkt_set_proto(pkt, ð_lay3, ip->h_protocol); } static void ipv4_less(struct pkt_buff *pkt) { char src_ip[INET_ADDRSTRLEN]; char dst_ip[INET_ADDRSTRLEN]; struct ipv4hdr *ip = (struct ipv4hdr *) pkt_pull(pkt, sizeof(*ip)); if (!ip) return; inet_ntop(AF_INET, &ip->h_saddr, src_ip, sizeof(src_ip)); inet_ntop(AF_INET, &ip->h_daddr, dst_ip, sizeof(dst_ip)); tprintf(" %s/%s Len %u", src_ip, dst_ip, ntohs(ip->h_tot_len)); /* cut off IP options and everything that is not part of IPv4 payload */ pkt_pull(pkt, max((uint8_t) ip->h_ihl, sizeof(*ip) / sizeof(uint32_t)) * sizeof(uint32_t) - sizeof(*ip)); /* XXX there coul still be an Ethernet trailer included or others */ #if 0 pkt_trim(pkt, pkt_len(pkt) - min(pkt_len(pkt), (ntohs(ip->h_tot_len) - ip->h_ihl * sizeof(uint32_t)))); #endif pkt_set_proto(pkt, ð_lay3, ip->h_protocol); } struct protocol ipv4_ops = { .key = 0x0800, .print_full = ipv4, .print_less = ipv4_less, }; EXPORT_SYMBOL(ipv4_ops); netsniff-ng-0.5.7/src/proto_ip_esp.c0000664000175000017500000000211011773367375017545 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright 2012 Markus Amend , Deutsche Flugsicherung GmbH * Subject to the GPL, version 2. * * Encapsulating Security Payload described in RFC4303 */ #include #include #include /* for ntohs() */ #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "built_in.h" #include "pkt_buff.h" struct esp_hdr { uint32_t h_spi; uint32_t h_sn; } __packed; static void esp(struct pkt_buff *pkt) { struct esp_hdr *esp_ops; esp_ops = (struct esp_hdr *) pkt_pull(pkt, sizeof(*esp_ops)); if (esp_ops == NULL) return; tprintf(" [ ESP "); tprintf("SPI (0x%x), ", ntohl(esp_ops->h_spi)); tprintf("SN (0x%x)", ntohl(esp_ops->h_sn)); tprintf(" ]\n"); } static void esp_less(struct pkt_buff *pkt) { struct esp_hdr *esp_ops; esp_ops = (struct esp_hdr *) pkt_pull(pkt, sizeof(*esp_ops)); if (esp_ops == NULL) return; tprintf(" ESP"); } struct protocol ip_esp_ops = { .key = 0x32, .print_full = esp, .print_less = esp_less, }; EXPORT_SYMBOL(ip_esp_ops); netsniff-ng-0.5.7/src/proto_ip_authentication_hdr.c0000664000175000017500000000423711773367375022646 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright 2012 Markus Amend , Deutsche Flugsicherung GmbH * Subject to the GPL, version 2. * * IP Authentication Header described in RFC4302 */ #include #include #include /* for ntohs() */ #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "built_in.h" #include "pkt_buff.h" struct auth_hdr { uint8_t h_next_header; uint8_t h_payload_len; uint16_t h_reserved; uint32_t h_spi; uint32_t h_snf; } __packed; static void auth_hdr(struct pkt_buff *pkt) { ssize_t hdr_len; struct auth_hdr *auth_ops; auth_ops = (struct auth_hdr *) pkt_pull(pkt, sizeof(*auth_ops)); if (auth_ops == NULL) return; hdr_len = (auth_ops->h_payload_len * 4) + 8; tprintf(" [ Authentication Header "); tprintf("NextHdr (%u), ", auth_ops->h_next_header); if (hdr_len > pkt_len(pkt) || hdr_len < 0){ tprintf("HdrLen (%u, %u Bytes %s), ", auth_ops->h_payload_len, hdr_len, colorize_start_full(black, red) "invalid" colorize_end()); return; } tprintf("HdrLen (%u, %u Bytes), ",auth_ops->h_payload_len, hdr_len); tprintf("Reserved (0x%x), ", ntohs(auth_ops->h_reserved)); /* TODO * Upgrade for Extended (64-bit) Sequence Number * http://tools.ietf.org/html/rfc4302#section-2.5.1 */ tprintf("SPI (0x%x), ", ntohl(auth_ops->h_spi)); tprintf("SNF (0x%x), ", ntohl(auth_ops->h_snf)); tprintf("ICV 0x"); for (size_t i = sizeof(struct auth_hdr); i < hdr_len; i++) tprintf("%02x", *pkt_pull(pkt, 1)); tprintf(" ]\n"); pkt_set_proto(pkt, ð_lay3, auth_ops->h_next_header); } static void auth_hdr_less(struct pkt_buff *pkt) { ssize_t hdr_len; struct auth_hdr *auth_ops; auth_ops = (struct auth_hdr *) pkt_pull(pkt, sizeof(*auth_ops)); if (auth_ops == NULL) return; hdr_len = (auth_ops->h_payload_len * 4) + 8; if (hdr_len > pkt_len(pkt) || hdr_len < 0) return; tprintf(" AH"); pkt_pull(pkt, hdr_len - sizeof(*auth_ops)); pkt_set_proto(pkt, ð_lay3, auth_ops->h_next_header); } struct protocol ip_auth_ops = { .key = 0x33, .print_full = auth_hdr, .print_less = auth_hdr_less, }; EXPORT_SYMBOL(ip_auth_ops); netsniff-ng-0.5.7/src/proto_igmp.c0000664000175000017500000003550711773367375017242 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright (C) 2012 Christoph Jaeger * Subject to the GPL, version 2. */ #include #include #include #include "proto.h" #include "protos.h" #include "csum.h" #include "dissector_eth.h" #include "built_in.h" #include "pkt_buff.h" /* IGMPv0 (RFC-988) */ struct igmp_v0_msg { uint8_t type; uint8_t code; uint16_t checksum; uint32_t identifier; uint32_t group_address; uint64_t access_key; } __packed; /* igmp_v0_msg.type */ #define IGMP_V0_CREATE_GROUP_REQUEST 0x01 #define IGMP_V0_CREATE_GROUP_REPLY 0x02 #define IGMP_V0_JOIN_GROUP_REQUEST 0x03 #define IGMP_V0_JOIN_GROUP_REPLY 0x04 #define IGMP_V0_LEAVE_GROUP_REQUEST 0x05 #define IGMP_V0_LEAVE_GROUP_REPLY 0x06 #define IGMP_V0_CONFIRM_GROUP_REQUEST 0x07 #define IGMP_V0_CONFIRM_GROUP_REPLY 0x08 /* IGMPv1 (RFC-1054/RFC-1112, obsoletes RFC-988) */ struct igmp_v1_msg { union { uint8_t version__type; struct { #if defined(__LITTLE_ENDIAN_BITFIELD) uint8_t type :4, version :4; #elif defined(__BIG_ENDIAN_BITFIELD) uint8_t version :4, type :4; #else # error "Please fix " #endif }; }; uint8_t unused; /* always zero */ uint16_t checksum; uint32_t group_address; } __attribute__((packed)); /* igmp_v1_msg.version__type (!) */ /* IGMP_V1_MEMBERSHIP_QUERY 0x11 */ #define IGMP_V1_MEMBERSHIP_REPORT 0x12 /* IGMPv2 (RFC-2236) */ struct igmp_v2_msg { uint8_t type; uint8_t max_resp_time; uint16_t checksum; uint32_t group_address; } __attribute__((packed)); /* igmp_v2_msg.type */ /* IGMP_V2_MEMBERSHIP_QUERY 0x11 */ #define IGMP_V2_MEMBERSHIP_REPORT 0x16 #define IGMP_V2_LEAVE_GROUP 0x17 /* * RGMP (RFC-3488) * The RGMP message format resembles the IGMPv2 message format. All RGMP * messages are sent with TTL 1, to destination address 224.0.0.25. */ #define RGMP_LEAVE_GROUP 0xFC #define RGMP_JOIN_GROUP 0xFD #define RGMP_BYE 0xFE #define RGMP_HELLO 0xFF /* IGMPv3 (RFC-3376) */ struct igmp_v3_group_record { uint8_t record_type; uint8_t aux_data_len; /* always zero */ uint16_t number_of_sources; uint32_t multicast_address; uint32_t source_addresses[0]; /* auxiliary data (IGMPv3 does not define any) */ } __attribute__((packed)); /* igmp_v3_group_record.record_type */ #define IGMP_V3_MODE_IS_INCLUDE 1 #define IGMP_V3_MODE_IS_EXCLUDE 2 #define IGMP_V3_CHANGE_TO_INCLUDE_MODE 3 #define IGMP_V3_CHANGE_TO_EXCLUDE_MODE 4 #define IGMP_V3_ALLOW_NEW_SOURCES 5 #define IGMP_V3_BLOCK_OLD_SOURCES 6 struct igmp_v3_membership_report { uint8_t type; uint8_t reserved1; uint16_t checksum; uint16_t reserved2; uint16_t number_of_group_records; struct igmp_v3_group_record group_records[0]; } __attribute__((packed)); struct igmp_v3_membership_query { uint8_t type; uint8_t max_resp_code; uint16_t checksum; uint32_t group_address; #if defined(__LITTLE_ENDIAN_BITFIELD) uint8_t qrv :3, s_flag :1, :4; #elif defined(__BIG_ENDIAN_BITFIELD) uint8_t :4, s_flag :1, qrv :3; #else # error "Please fix " #endif uint8_t qqic; uint16_t number_of_sources; uint32_t source_addresses[0]; } __attribute__((packed)); #define IGMP_MEMBERSHIP_QUERY 0x11 /* v1/v2/v3 */ #define IGMP_V3_MEMBERSHIP_REPORT 0x22 #define EXP(x) (((x) & 0x70) >> 4) #define MANT(x) ((x) & 0x0F) #define DECODE_MAX_RESP_CODE(x) ((x) < 128 ? (x) : (MANT(x) | 0x10) << (EXP(x) + 3)) #define DECODE_QQIC(x) ((x) < 128 ? (x) : (MANT(x) | 0x10) << (EXP(x) + 3)) static char *friendly_msg_type_name(uint8_t msg_type) { switch (msg_type) { case IGMP_V0_CREATE_GROUP_REQUEST: return "Create Group Request"; case IGMP_V0_CREATE_GROUP_REPLY: return "Create Group Reply"; case IGMP_V0_JOIN_GROUP_REQUEST: return "Join Group Request"; case IGMP_V0_JOIN_GROUP_REPLY: return "Join Group Reply"; case IGMP_V0_LEAVE_GROUP_REQUEST: return "Leave Group Request"; case IGMP_V0_LEAVE_GROUP_REPLY: return "Leave Group Reply"; case IGMP_V0_CONFIRM_GROUP_REQUEST: return "Confirm Group Request"; case IGMP_V0_CONFIRM_GROUP_REPLY: return "Confirm Group Reply"; case IGMP_MEMBERSHIP_QUERY: return "Membership Query"; case IGMP_V1_MEMBERSHIP_REPORT: case IGMP_V2_MEMBERSHIP_REPORT: case IGMP_V3_MEMBERSHIP_REPORT: return "Membership Report"; case IGMP_V2_LEAVE_GROUP: return "Leave Group"; case RGMP_HELLO: return "Hello"; case RGMP_BYE: return "Bye"; case RGMP_JOIN_GROUP: return "Join Group"; case RGMP_LEAVE_GROUP: return "Leave Group"; default: return NULL; } } #define PRINT_FRIENDLY_NAMED_MSG_TYPE(type) \ do { \ if (friendly_msg_type_name(type)) \ tprintf(" Type (0x%.2x, %s)", type, \ friendly_msg_type_name(type)); \ else \ tprintf(" Type (0x%.2x)", type); \ } while (0) static char *friendly_group_rec_type_name(uint8_t rec_type) { switch (rec_type) { case IGMP_V3_MODE_IS_INCLUDE: return "Mode Is Include"; case IGMP_V3_MODE_IS_EXCLUDE: return "Mode Is Exclude"; case IGMP_V3_CHANGE_TO_INCLUDE_MODE: return "Change To Include Mode"; case IGMP_V3_CHANGE_TO_EXCLUDE_MODE: return "Change To Exclude Mode"; case IGMP_V3_ALLOW_NEW_SOURCES: return "Allow New Sources"; case IGMP_V3_BLOCK_OLD_SOURCES: return "Block Old Sources"; default: return NULL; } } static void dissect_igmp_v0(struct pkt_buff *pkt) { char addr[INET_ADDRSTRLEN]; uint16_t csum; static const char *reply_codes[] = { "Request Granted", "Request Denied, No Resources", "Request Denied, Invalid Code", "Request Denied, Invalid Group Address", "Request Denied, Invalid Access Key" }; struct igmp_v0_msg *msg = (struct igmp_v0_msg *) pkt_pull(pkt, sizeof(*msg)); if (msg == NULL) return; tprintf(" [ IGMPv0"); PRINT_FRIENDLY_NAMED_MSG_TYPE(msg->type); switch (msg->type) { case IGMP_V0_CREATE_GROUP_REQUEST: switch (msg->code) { case 0: tprintf(", Code (%u, %s)", msg->code, "Public"); break; case 1: tprintf(", Code (%u, %s)", msg->code, "Private"); break; default: tprintf(", Code (%u)", msg->code); } break; case IGMP_V0_CREATE_GROUP_REPLY: case IGMP_V0_JOIN_GROUP_REPLY: case IGMP_V0_LEAVE_GROUP_REPLY: case IGMP_V0_CONFIRM_GROUP_REPLY: if (msg->code < 5) tprintf(", Code (%u, %s)", msg->code, reply_codes[msg->code]); else tprintf(", Code (%u, Request Pending, Retry In %u Seconds)", msg->code, msg->code); break; default: tprintf(", Code (%u)", msg->code); } csum = calc_csum(msg, sizeof(*msg) + pkt_len(pkt), 0); tprintf(", CSum (0x%.4x) is %s", ntohs(msg->checksum), csum ? colorize_start_full(black, red) "bogus (!)" colorize_end() : "ok"); if (csum) tprintf(" - %s should be %x%s", colorize_start_full(black, red), csum_expected(msg->checksum, csum), colorize_end()); tprintf(", Id (%u)", ntohs(msg->identifier)); inet_ntop(AF_INET, &msg->group_address, addr, sizeof(addr)); tprintf(", Group Addr (%s)", addr); tprintf(", Access Key (0x%.16x)", msg->access_key); tprintf(" ]\n"); } static void dissect_igmp_v1(struct pkt_buff *pkt) { char addr[INET_ADDRSTRLEN]; uint16_t csum; struct igmp_v1_msg *msg = (struct igmp_v1_msg *) pkt_pull(pkt, sizeof(*msg)); if (msg == NULL) return; tprintf(" [ IGMPv1"); PRINT_FRIENDLY_NAMED_MSG_TYPE(msg->version__type); csum = calc_csum(msg, sizeof(*msg) + pkt_len(pkt), 0); tprintf(", CSum (0x%.4x) is %s", ntohs(msg->checksum), csum ? colorize_start_full(black, red) "bogus (!)" colorize_end() : "ok"); if (csum) tprintf(" - %s should be %x%s", colorize_start_full(black, red), csum_expected(msg->checksum, csum), colorize_end()); inet_ntop(AF_INET, &msg->group_address, addr, sizeof(addr)); tprintf(", Group Addr (%s)", addr); tprintf(" ]\n"); } static void dissect_igmp_v2(struct pkt_buff *pkt) { char addr[INET_ADDRSTRLEN]; uint16_t csum; struct igmp_v2_msg *msg = (struct igmp_v2_msg *) pkt_pull(pkt, sizeof(*msg)); if (msg == NULL) return; switch (msg->type) { case RGMP_HELLO: case RGMP_BYE: case RGMP_JOIN_GROUP: case RGMP_LEAVE_GROUP: tprintf(" [ IGMPv2 (RGMP)"); break; default: tprintf(" [ IGMPv2"); break; } PRINT_FRIENDLY_NAMED_MSG_TYPE(msg->type); tprintf(", Max Resp Time (%u)", msg->max_resp_time); csum = calc_csum(msg, sizeof(*msg) + pkt_len(pkt), 0); tprintf(", CSum (0x%.4x) is %s", ntohs(msg->checksum), csum ? colorize_start_full(black, red) "bogus (!)" colorize_end() : "ok"); if (csum) tprintf(" - %s should be %x%s", colorize_start_full(black, red), csum_expected(msg->checksum, csum), colorize_end()); inet_ntop(AF_INET, &msg->group_address, addr, sizeof(addr)); tprintf(", Group Addr (%s)", addr); tprintf(" ]\n"); } static void dissect_igmp_v3_membership_query(struct pkt_buff *pkt) { char addr[INET_ADDRSTRLEN]; size_t n; uint16_t csum; uint32_t *src_addr; struct igmp_v3_membership_query *msg = (struct igmp_v3_membership_query *) pkt_pull(pkt, sizeof(*msg)); if (msg == NULL) return; tprintf(" [ IGMPv3"); PRINT_FRIENDLY_NAMED_MSG_TYPE(msg->type); tprintf(", Max Resp Code (0x%.2x => %u)", msg->max_resp_code, DECODE_MAX_RESP_CODE(msg->max_resp_code)); csum = calc_csum(msg, sizeof(*msg) + pkt_len(pkt), 0); tprintf(", CSum (0x%.4x) is %s", ntohs(msg->checksum), csum ? colorize_start_full(black, red) "bogus (!)" colorize_end() : "ok"); if (csum) tprintf(" - %s should be %x%s", colorize_start_full(black, red), csum_expected(msg->checksum, csum), colorize_end()); inet_ntop(AF_INET, &msg->group_address, addr, sizeof(addr)); /* S Flag (Suppress Router-Side Processing) */ tprintf(", Suppress (%u)", msg->s_flag ? 1 : 0); /* QRV (Querier's Robustness Variable) */ tprintf(", QRV (%u)", msg->qrv); /* QQIC (Querier's Query Interval Code) */ tprintf(", QQIC (0x%.2x => %u)", msg->qqic, DECODE_QQIC(msg->qqic)); tprintf(", Group Addr (%s)", addr); n = ntohs(msg->number_of_sources); tprintf(", Num Src (%u)", n); if (n--) { src_addr = (uint32_t *) pkt_pull(pkt, sizeof(*src_addr)); if (src_addr != NULL) { inet_ntop(AF_INET, src_addr, addr, sizeof(addr)); tprintf(", Src Addr (%s", addr); while (n--) { src_addr = (uint32_t *) pkt_pull(pkt, sizeof(*src_addr)); if (src_addr != NULL) break; inet_ntop(AF_INET, src_addr, addr, sizeof(addr)); tprintf(", %s", addr); } tprintf(")"); } } tprintf(" ]\n"); } static void dissect_igmp_v3_membership_report(struct pkt_buff *pkt) { char addr[INET_ADDRSTRLEN]; size_t m, n; uint16_t csum; uint32_t *src_addr; struct igmp_v3_group_record *rec; struct igmp_v3_membership_report *msg = (struct igmp_v3_membership_report *) pkt_pull(pkt, sizeof(*msg)); if (msg == NULL) return; tprintf(" [ IGMPv3"); PRINT_FRIENDLY_NAMED_MSG_TYPE(msg->type); csum = calc_csum(msg, sizeof(*msg) + pkt_len(pkt), 0); tprintf(", CSum (0x%.4x) is %s", ntohs(msg->checksum), csum ? colorize_start_full(black, red) "bogus (!)" colorize_end() : "ok"); if (csum) tprintf(" - %s should be %x%s", colorize_start_full(black, red), csum_expected(msg->checksum, csum), colorize_end()); m = ntohs(msg->number_of_group_records); tprintf(", Num Group Rec (%u)", m); tprintf(" ]\n"); while (m--) { rec = (struct igmp_v3_group_record *) pkt_pull(pkt, sizeof(*rec)); if (rec == NULL) break; tprintf(" [ Group Record"); if (friendly_group_rec_type_name(rec->record_type)) tprintf(" Type (%u, %s)", rec->record_type, friendly_group_rec_type_name(rec->record_type)); else tprintf(" Type (%u)", rec->record_type); n = ntohs(rec->number_of_sources); tprintf(", Num Src (%u)", n); inet_ntop(AF_INET, &rec->multicast_address, addr, sizeof(addr)); tprintf(", Multicast Addr (%s)", addr); if (n--) { src_addr = (uint32_t *) pkt_pull(pkt, sizeof(*src_addr)); if (src_addr != NULL) { inet_ntop(AF_INET, src_addr, addr, sizeof(addr)); tprintf(", Src Addr (%s", addr); while (n--) { src_addr = (uint32_t *) pkt_pull(pkt, sizeof(*src_addr)); if (src_addr != NULL) break; inet_ntop(AF_INET, src_addr, addr, sizeof(addr)); tprintf(", %s", addr); } tprintf(")"); } } tprintf(" ]\n"); } tprintf("\n"); } static void igmp(struct pkt_buff *pkt) { switch (*pkt_peek(pkt)) { case IGMP_V0_CREATE_GROUP_REQUEST: case IGMP_V0_CREATE_GROUP_REPLY: case IGMP_V0_JOIN_GROUP_REQUEST: case IGMP_V0_JOIN_GROUP_REPLY: case IGMP_V0_LEAVE_GROUP_REQUEST: case IGMP_V0_LEAVE_GROUP_REPLY: case IGMP_V0_CONFIRM_GROUP_REQUEST: case IGMP_V0_CONFIRM_GROUP_REPLY: if (pkt_len(pkt) == sizeof(struct igmp_v0_msg)) dissect_igmp_v0(pkt); break; case IGMP_MEMBERSHIP_QUERY: /* v1/v2/v3 */ if (pkt_len(pkt) >= sizeof(struct igmp_v3_membership_query)) dissect_igmp_v3_membership_query(pkt); else if (pkt_len(pkt) == sizeof(struct igmp_v2_msg) && *(pkt_peek(pkt) + 1)) dissect_igmp_v2(pkt); else if (pkt_len(pkt) == sizeof(struct igmp_v1_msg)) dissect_igmp_v1(pkt); break; case IGMP_V1_MEMBERSHIP_REPORT: if (pkt_len(pkt) == sizeof(struct igmp_v1_msg)) dissect_igmp_v1(pkt); break; case RGMP_HELLO: case RGMP_BYE: case RGMP_JOIN_GROUP: case RGMP_LEAVE_GROUP: case IGMP_V2_MEMBERSHIP_REPORT: case IGMP_V2_LEAVE_GROUP: if (pkt_len(pkt) == sizeof(struct igmp_v2_msg)) dissect_igmp_v2(pkt); break; case IGMP_V3_MEMBERSHIP_REPORT: if (pkt_len(pkt) >= sizeof(struct igmp_v3_membership_report)) dissect_igmp_v3_membership_report(pkt); break; } } static void igmp_less(struct pkt_buff *pkt) { int version = -1; switch (*pkt_peek(pkt)) { case IGMP_V0_CREATE_GROUP_REQUEST: case IGMP_V0_CREATE_GROUP_REPLY: case IGMP_V0_JOIN_GROUP_REQUEST: case IGMP_V0_JOIN_GROUP_REPLY: case IGMP_V0_LEAVE_GROUP_REQUEST: case IGMP_V0_LEAVE_GROUP_REPLY: case IGMP_V0_CONFIRM_GROUP_REQUEST: case IGMP_V0_CONFIRM_GROUP_REPLY: if (pkt_len(pkt) == sizeof(struct igmp_v0_msg)) version = 0; break; case IGMP_MEMBERSHIP_QUERY: /* v1/v2/v3 */ if (pkt_len(pkt) >= sizeof(struct igmp_v3_membership_query)) version = 3; else if (pkt_len(pkt) == sizeof(struct igmp_v2_msg) && *(pkt_peek(pkt) + 1)) version = 2; else if (pkt_len(pkt) == sizeof(struct igmp_v1_msg)) version = 1; break; case IGMP_V1_MEMBERSHIP_REPORT: if (pkt_len(pkt) == sizeof(struct igmp_v1_msg)) version = 1; break; case RGMP_HELLO: case RGMP_BYE: case RGMP_JOIN_GROUP: case RGMP_LEAVE_GROUP: case IGMP_V2_MEMBERSHIP_REPORT: case IGMP_V2_LEAVE_GROUP: if (pkt_len(pkt) == sizeof(struct igmp_v2_msg)) version = 2; break; case IGMP_V3_MEMBERSHIP_REPORT: if (pkt_len(pkt) >= sizeof(struct igmp_v3_membership_report)) version = 3; break; } if (version < 0 || version > 3) return; switch (*pkt_peek(pkt)) { case RGMP_HELLO: case RGMP_BYE: case RGMP_JOIN_GROUP: case RGMP_LEAVE_GROUP: tprintf(" IGMPv2 (RGMP)"); break; default: tprintf(" IGMPv%u", version); break; } PRINT_FRIENDLY_NAMED_MSG_TYPE(*pkt_peek(pkt)); } struct protocol igmp_ops = { .key = 0x02, .print_full = igmp, .print_less = igmp_less, }; EXPORT_SYMBOL(igmp_ops); netsniff-ng-0.5.7/src/proto_icmpv6.c0000664000175000017500000011761611773367375017514 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright 2012 Markus Amend , Deutsche Flugsicherung GmbH * Subject to the GPL, version 2. * * ICMPv6 described in RFC4443, RFC2710, RFC4861, RFC2894, * RFC4620, RFC3122, RFC3810, RFC3775, RFC3971, RFC4065 * RFC4286 * Look also for an good overview: * http://www.iana.org/assignments/icmpv6-parameters */ #include #include #include #include #include #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "pkt_buff.h" #include "built_in.h" #define icmpv6_code_range_valid(code, sarr) ((code) < array_size((sarr))) struct icmpv6_general_hdr { uint8_t h_type; uint8_t h_code; uint16_t h_chksum; } __packed; /* for type 0x01 and 0x03 */ struct icmpv6_type_1_3 { uint32_t unused; uint8_t invoking_pkt[0]; } __packed; struct icmpv6_type_2 { uint32_t MTU; uint8_t invoking_pkt[0]; } __packed; struct icmpv6_type_4 { uint32_t pointer; uint8_t invoking_pkt[0]; } __packed; struct icmpv6_type_128_129 { uint16_t id; uint16_t sn; uint8_t data[0]; } __packed; /* MLDv1 msg */ struct icmpv6_type_130_131_132 { uint16_t maxrespdel; uint16_t res; struct in6_addr ipv6_addr; } __packed; /* end MLDv1 msg */ struct icmpv6_type_130_mldv2 { uint8_t resv_S_QRV; uint8_t QQIC; uint16_t nr_src; struct in6_addr ipv6_addr[0]; } __packed; /* Neighbor Discovery msg */ struct icmpv6_type_133_141_142 { uint32_t res; uint8_t ops[0]; } __packed; struct icmpv6_type_134 { uint8_t cur_hop_limit; uint8_t m_o_res; uint16_t router_lifetime; uint32_t reachable_time; uint32_t retrans_timer; uint8_t ops[0]; } __packed; struct icmpv6_type_135 { uint32_t res; struct in6_addr ipv6_addr; uint8_t ops[0]; } __packed; struct icmpv6_type_136 { uint32_t r_s_o_res; struct in6_addr ipv6_addr; uint8_t ops[0]; } __packed; struct icmpv6_type_137 { uint32_t res; struct in6_addr ipv6_targ_addr; struct in6_addr ipv6_dest_addr; uint8_t ops[0]; } __packed; struct icmpv6_neighb_disc_ops_general { uint8_t type; uint8_t len; uint8_t ops[0]; } __packed; struct icmpv6_neighb_disc_ops_type_1_2 { uint8_t link_lay_addr[0]; } __packed; struct icmpv6_neighb_disc_ops_type_3 { uint8_t prefix_len; uint8_t l_a_res1; uint32_t valid_lifetime; uint32_t preferred_lifetime; uint32_t res2; struct in6_addr prefix; } __packed; struct icmpv6_neighb_disc_ops_type_4 { uint16_t res1; uint32_t res2; uint8_t ip_hdr_data[0]; } __packed; struct icmpv6_neighb_disc_ops_type_5 { uint16_t res1; uint32_t MTU; } __packed; struct icmpv6_neighb_disc_ops_type_9_10 { uint16_t res1; uint32_t res2; uint8_t ip_hdr_data[0]; } __packed; struct icmpv6_neighb_disc_ops_type_15 { uint8_t name_type; size_t pad_len; char name[0]; uint8_t pad[0]; } __packed; struct icmpv6_neighb_disc_ops_type_16 { uint8_t cert_type; uint8_t res; uint8_t cert[0]; uint8_t pad[0]; } __packed; struct icmpv6_neighb_disc_ops_type_17 { uint8_t opt_code; uint8_t prefix_len; uint8_t data[0]; } __packed; struct icmpv6_neighb_disc_ops_type_17_1 { uint32_t res; struct in6_addr ipv6_addr; } __packed; struct icmpv6_neighb_disc_ops_type_17_2 { struct in6_addr ipv6_addr; } __packed; struct icmpv6_neighb_disc_ops_type_19 { uint8_t opt_code; uint8_t lla[0]; } __packed; /* end Neighbor Discovery msg */ struct icmpv6_type_138 { uint32_t seq_nr; uint8_t seg_nr; uint8_t flags; uint16_t maxdelay; uint32_t res; } __packed; /* Node Information Queries */ struct icmpv6_type_139_140 { uint16_t qtype; uint16_t flags; uint64_t nonce; uint8_t data[0]; } __packed; /* end Node Information Queries */ /* MLDv2 report */ struct icmpv6_type_143 { uint16_t res; uint16_t nr_rec; uint8_t addr_rec[0]; } __packed; struct icmpv6_mldv2_addr_rec { uint8_t rec_type; uint8_t aux_data_len; uint16_t nr_src; struct in6_addr multic_addr; struct in6_addr src_addr[0]; } __packed; /* end MLDv2 report */ /* ICMP Mobility Support */ struct icmpv6_type_144_146 { uint16_t id; uint16_t res; } __packed; struct icmpv6_type_145 { uint16_t id; uint16_t res; struct in6_addr home_agent_addr[0]; } __packed; struct icmpv6_type_147 { uint16_t id; uint16_t m_o_res; uint8_t ops[0]; } __packed; /* end ICMP Mobility Support */ /* SEcure Neighbor Discovery */ struct icmpv6_type_148 { uint16_t id; uint16_t comp; uint8_t ops[0]; } __packed; struct icmpv6_type_149 { uint16_t id; uint16_t all_comp; uint16_t comp; uint16_t res; uint8_t ops[0]; } __packed; /* end SEcure Neighbor Discovery */ struct icmpv6_type_150 { union { uint32_t subtype_res; struct { #if defined(__LITTLE_ENDIAN_BITFIELD) uint32_t res :24, subtype :8; #elif defined(__BIG_ENDIAN_BITFIELD) uint32_t subtype :8, res :24; #else # error "Please fix " #endif }; }; uint8_t ops[0]; } __packed; /* Multicast Router Discovery */ struct icmpv6_type_151 { uint16_t query_intv; uint16_t rob_var; } __packed; struct icmpv6_type_152 { uint8_t null[0]; } __packed; struct icmpv6_type_153 { uint8_t null[0]; } __packed; /* end Multicast Router Discovery */ struct icmpv6_type_154 { uint8_t subtype; uint8_t res; uint16_t id; uint8_t ops[0]; } __packed; static int8_t print_ipv6_addr_list(struct pkt_buff *pkt, uint8_t nr_addr) { char address[INET6_ADDRSTRLEN]; struct in6_addr *addr; while (nr_addr--) { addr = (struct in6_addr *) pkt_pull(pkt, sizeof(*addr)); if (addr == NULL) return 0; tprintf("\n\t Address: %s", inet_ntop(AF_INET6, addr, address, sizeof(address))); } return 1; } static const char *icmpv6_mcast_rec_types[] = { "MODE_IS_INCLUDE", "MODE_IS_EXCLUDE", "CHANGE_TO_INCLUDE_MODE", "CHANGE_TO_EXCLUDE_MODE", "ALLOW_NEW_SOURCES", "BLOCK_OLD_SOURCES", }; static int8_t dissect_icmpv6_mcast_rec(struct pkt_buff *pkt, uint16_t nr_rec) { uint16_t nr_src, aux_data_len_bytes; char address[INET6_ADDRSTRLEN]; struct icmpv6_mldv2_addr_rec *addr_rec; while (nr_rec--) { addr_rec = (struct icmpv6_mldv2_addr_rec *) pkt_pull(pkt,sizeof(*addr_rec)); if (addr_rec == NULL) return 0; aux_data_len_bytes = addr_rec->aux_data_len * 4; nr_src = ntohs(addr_rec->nr_src); tprintf(", Rec Type %s (%u)", icmpv6_code_range_valid(addr_rec->rec_type - 1, icmpv6_mcast_rec_types) ? icmpv6_mcast_rec_types[addr_rec->rec_type - 1] : "Unknown", addr_rec->rec_type); if (aux_data_len_bytes > pkt_len(pkt)) { tprintf(", Aux Data Len (%u, %u bytes) %s", addr_rec->aux_data_len, aux_data_len_bytes, colorize_start_full(black, red) "invalid" colorize_end()); return 0; } tprintf(", Aux Data Len (%u, %u bytes)",addr_rec->aux_data_len, aux_data_len_bytes); tprintf(", Nr. of Sources (%u)",nr_src); tprintf(", Address: %s", inet_ntop(AF_INET6, &addr_rec->multic_addr, address, sizeof(address))); if(!print_ipv6_addr_list(pkt, nr_src)) return 0; if (aux_data_len_bytes > pkt_len(pkt)) { tprintf("\nAux Data Len %s", colorize_start_full(black, red) "invalid" colorize_end()); return 0; } tprintf(", Aux Data: "); while (aux_data_len_bytes--) { tprintf("%x", *pkt_pull(pkt,1)); } } return 1; } static int8_t dissect_neighb_disc_ops_1(struct pkt_buff *pkt, ssize_t len) { struct icmpv6_neighb_disc_ops_type_1_2 *icmp_neighb_disc_1; icmp_neighb_disc_1 = (struct icmpv6_neighb_disc_ops_type_1_2 *) pkt_pull(pkt,sizeof(*icmp_neighb_disc_1)); if (icmp_neighb_disc_1 == NULL) return 0; len -= sizeof(*icmp_neighb_disc_1); if (len < 0) return 0; tprintf("Address 0x"); while(len--){ tprintf("%x", *pkt_pull(pkt,1)); } return 1; } static int8_t dissect_neighb_disc_ops_2(struct pkt_buff *pkt, ssize_t len) { return dissect_neighb_disc_ops_1(pkt, len); } static int8_t dissect_neighb_disc_ops_3(struct pkt_buff *pkt, ssize_t len) { char address[INET6_ADDRSTRLEN]; struct icmpv6_neighb_disc_ops_type_3 *icmp_neighb_disc_3; icmp_neighb_disc_3 = (struct icmpv6_neighb_disc_ops_type_3 *) pkt_pull(pkt,sizeof(*icmp_neighb_disc_3)); if (icmp_neighb_disc_3 == NULL) return 0; len -= sizeof(*icmp_neighb_disc_3); if (len < 0) return 0; tprintf("Prefix Len (%u) ",icmp_neighb_disc_3->prefix_len); tprintf("L (%u) A (%u) Res1 (0x%x) ",icmp_neighb_disc_3->l_a_res1 >> 7, (icmp_neighb_disc_3->l_a_res1 >> 7) & 0x1, icmp_neighb_disc_3->l_a_res1 & 0x3F); tprintf("Valid Lifetime (%us) ", ntohl(icmp_neighb_disc_3->valid_lifetime)); tprintf("Preferred Lifetime (%us) ", ntohl(icmp_neighb_disc_3->preferred_lifetime)); tprintf("Reserved2 (0x%x) ", ntohl(icmp_neighb_disc_3->res2)); tprintf("Prefix: %s ", inet_ntop(AF_INET6,&icmp_neighb_disc_3->prefix, address, sizeof(address))); return 1; } static int8_t dissect_neighb_disc_ops_4(struct pkt_buff *pkt, ssize_t len) { struct icmpv6_neighb_disc_ops_type_4 *icmp_neighb_disc_4; icmp_neighb_disc_4 = (struct icmpv6_neighb_disc_ops_type_4 *) pkt_pull(pkt,sizeof(*icmp_neighb_disc_4)); if (icmp_neighb_disc_4 == NULL) return 0; len -= sizeof(*icmp_neighb_disc_4); if (len < 0) return 0; tprintf("Reserved 1 (0x%x) ", ntohs(icmp_neighb_disc_4->res1)); tprintf("Reserved 2 (0x%x) ", ntohl(icmp_neighb_disc_4->res2)); tprintf("IP header + data "); while (len--) { tprintf("%x", *pkt_pull(pkt,1)); } return 1; } static int8_t dissect_neighb_disc_ops_5(struct pkt_buff *pkt, ssize_t len) { struct icmpv6_neighb_disc_ops_type_5 *icmp_neighb_disc_5; icmp_neighb_disc_5 = (struct icmpv6_neighb_disc_ops_type_5 *) pkt_pull(pkt,sizeof(*icmp_neighb_disc_5)); if (icmp_neighb_disc_5 == NULL) return 0; len -= sizeof(*icmp_neighb_disc_5); if (len < 0) return 0; tprintf("Reserved (0x%x) ", ntohs(icmp_neighb_disc_5->res1)); tprintf("MTU (%u)", ntohl(icmp_neighb_disc_5->MTU)); return 1; } static int8_t dissect_neighb_disc_ops_9(struct pkt_buff *pkt, ssize_t len) { struct icmpv6_neighb_disc_ops_type_9_10 *icmp_neighb_disc_9; icmp_neighb_disc_9 = (struct icmpv6_neighb_disc_ops_type_9_10 *) pkt_pull(pkt,sizeof(*icmp_neighb_disc_9)); if (icmp_neighb_disc_9 == NULL) return 0; len -= sizeof(*icmp_neighb_disc_9); if (len < 0) return 0; tprintf("Reserved 1 (0x%x) ", ntohs(icmp_neighb_disc_9->res1)); tprintf("Reserved 2 (0x%x) ", ntohl(icmp_neighb_disc_9->res2)); return print_ipv6_addr_list(pkt, len / sizeof(struct in6_addr)); } static int8_t dissect_neighb_disc_ops_10(struct pkt_buff *pkt, ssize_t len) { return dissect_neighb_disc_ops_9(pkt, len); } static const char *icmpv6_neighb_disc_ops_15_name[] = { "DER Encoded X.501 Name", "FQDN", }; static int8_t dissect_neighb_disc_ops_15(struct pkt_buff *pkt, ssize_t len) { size_t pad_len; ssize_t name_len; struct icmpv6_neighb_disc_ops_type_15 *icmp_neighb_disc_15; icmp_neighb_disc_15 = (struct icmpv6_neighb_disc_ops_type_15 *) pkt_pull(pkt,sizeof(*icmp_neighb_disc_15)); if (icmp_neighb_disc_15 == NULL) return 0; len -= sizeof(*icmp_neighb_disc_15); if (len < 0) return 0; pad_len = icmp_neighb_disc_15->pad_len; tprintf("Name Type %s (%u) ", icmpv6_code_range_valid(icmp_neighb_disc_15->name_type - 1, icmpv6_neighb_disc_ops_15_name) ? icmpv6_neighb_disc_ops_15_name[ icmp_neighb_disc_15->name_type - 1] : "Unknown", icmp_neighb_disc_15->name_type); if (pad_len > len) { tprintf("Pad Len (%u, invalid)\n%s", pad_len, colorize_start_full(black, red) "Skip Option" colorize_end()); pkt_pull(pkt, len); return 1; } else tprintf("Pad Len (%u) ", pad_len); name_len = len - pad_len; tprintf("Name ("); while (name_len--) { tprintf("%c", *pkt_pull(pkt,1)); } tprintf(") "); tprintf("Padding ("); while (pad_len--) { tprintf("%x", *pkt_pull(pkt,1)); } tprintf(")"); return 1; } static const char *icmpv6_neighb_disc_ops_16_cert[] = { "X.509v3 Certificate", }; static int8_t dissect_neighb_disc_ops_16(struct pkt_buff *pkt, ssize_t len) { struct icmpv6_neighb_disc_ops_type_16 *icmp_neighb_disc_16; icmp_neighb_disc_16 = (struct icmpv6_neighb_disc_ops_type_16 *) pkt_pull(pkt,sizeof(*icmp_neighb_disc_16)); if (icmp_neighb_disc_16 == NULL) return 0; len -= sizeof(*icmp_neighb_disc_16); if (len < 0) return 0; tprintf("Cert Type %s (%u) ", icmpv6_code_range_valid(icmp_neighb_disc_16->cert_type - 1, icmpv6_neighb_disc_ops_16_cert) ? icmpv6_neighb_disc_ops_16_cert[ icmp_neighb_disc_16->cert_type - 1] : "Unknown", icmp_neighb_disc_16->cert_type); tprintf("Res (0x%x) ", icmp_neighb_disc_16->res); tprintf("Certificate + Padding ("); while (len--) { tprintf("%x", *pkt_pull(pkt,1)); } tprintf(") "); return 1; } static const char *icmpv6_neighb_disc_ops_17_codes[] = { "Old Care-of Address", "New Care-of Address", "NAR's IP address", "NAR's Prefix", }; static int8_t dissect_neighb_disc_ops_17(struct pkt_buff *pkt, ssize_t len) { char address[INET6_ADDRSTRLEN]; struct icmpv6_neighb_disc_ops_type_17 *icmp_neighb_disc_17; icmp_neighb_disc_17 = (struct icmpv6_neighb_disc_ops_type_17 *) pkt_pull(pkt,sizeof(*icmp_neighb_disc_17)); if (icmp_neighb_disc_17 == NULL) return 0; len -= sizeof(*icmp_neighb_disc_17); if (len < 0) return 0; tprintf("Opt Code %s (%u) ", icmpv6_code_range_valid(icmp_neighb_disc_17->opt_code - 1, icmpv6_neighb_disc_ops_17_codes) ? icmpv6_neighb_disc_ops_17_codes[ icmp_neighb_disc_17->opt_code - 1] : "Unknown", icmp_neighb_disc_17->opt_code); tprintf("Prefix Len (%u) ", icmp_neighb_disc_17->prefix_len); if (len == sizeof(struct icmpv6_neighb_disc_ops_type_17_1)) { struct icmpv6_neighb_disc_ops_type_17_1 *icmp_neighb_disc_17_1; icmp_neighb_disc_17_1 = (struct icmpv6_neighb_disc_ops_type_17_1 *) pkt_pull(pkt,sizeof(*icmp_neighb_disc_17_1)); if (icmp_neighb_disc_17_1 == NULL) return 0; len -= sizeof(*icmp_neighb_disc_17_1); if (len < 0) return 0; tprintf("Res (0x%x) ",icmp_neighb_disc_17_1->res); tprintf("Addr: %s ", inet_ntop(AF_INET6,&icmp_neighb_disc_17_1->ipv6_addr, address, sizeof(address))); } else if (len == sizeof(struct icmpv6_neighb_disc_ops_type_17_2)) { struct icmpv6_neighb_disc_ops_type_17_2 *icmp_neighb_disc_17_2; icmp_neighb_disc_17_2 = (struct icmpv6_neighb_disc_ops_type_17_2 *) pkt_pull(pkt,sizeof(*icmp_neighb_disc_17_2)); if (icmp_neighb_disc_17_2 == NULL) return 0; len -= sizeof(*icmp_neighb_disc_17_2); if (len < 0) return 0; tprintf("Addr: %s ", inet_ntop(AF_INET6,&icmp_neighb_disc_17_2->ipv6_addr, address, sizeof(address))); } else { tprintf("%s (", colorize_start_full(black, red) "Error Wrong Length. Skip Option" colorize_end()); while (len--) { tprintf("%x", *pkt_pull(pkt,1)); } tprintf(") "); } return 1; } static const char *icmpv6_neighb_disc_ops_19_codes[] = { "Wildcard requesting resolution for all nearby access points", "Link-Layer Address of the New Access Point", "Link-Layer Address of the MN", "Link-Layer Address of the NAR", "Link-Layer Address of the source of RtSolPr or PrRtAdv \ message", "The access point identified by the LLA belongs to the \ current interface of the router", "No prefix information available for the access point \ identified by the LLA", "No fast handover support available for the access point \ identified by the LLA", }; static int8_t dissect_neighb_disc_ops_19(struct pkt_buff *pkt, ssize_t len) { struct icmpv6_neighb_disc_ops_type_19 *icmp_neighb_disc_19; icmp_neighb_disc_19 = (struct icmpv6_neighb_disc_ops_type_19 *) pkt_pull(pkt,sizeof(*icmp_neighb_disc_19)); if (icmp_neighb_disc_19 == NULL) return 0; len -= sizeof(*icmp_neighb_disc_19); if (len < 0) return 0; tprintf("Opt Code %s (%u) ", icmpv6_code_range_valid(icmp_neighb_disc_19->opt_code, icmpv6_neighb_disc_ops_19_codes) ? icmpv6_neighb_disc_ops_19_codes[ icmp_neighb_disc_19->opt_code] : "Unknown", icmp_neighb_disc_19->opt_code); tprintf("LLA ("); while(len--){ tprintf("%x", *pkt_pull(pkt,1)); } tprintf(") "); return 1; } static inline char *icmpv6_neighb_disc_ops(uint8_t code) { switch (code) { case 1: return "Source Link-Layer Address"; case 2: return "Target Link-Layer Address"; case 3: return "Prefix Information"; case 4: return "Redirected Header"; case 5: return "MTU"; case 6: return "NBMA Shortcut Limit Option"; case 7: return "Advertisement Interval Option"; case 8: return "Home Agent Information Option"; case 9: return "Source Address List"; case 10: return "Target Address List"; case 11: return "CGA option"; case 12: return "RSA Signature option"; case 13: return "Timestamp option"; case 14: return "Nonce option"; case 15: return "Trust Anchor option"; case 16: return "Certificate option"; case 17: return "IP Address/Prefix Option"; case 18: return "New Router Prefix Information Option"; case 19: return "Link-layer Address Option"; case 20: return "Neighbor Advertisement Acknowledgment Option"; case 23: return "Prefix Information"; case 24: return "Redirected Header"; case 25: return "MTU"; case 26: return "NBMA Shortcut Limit Option"; case 27: return "Advertisement Interval Option"; case 28: return "Home Agent Information Option"; case 29: return "Source Address List"; case 30: return "Target Address List"; case 31: return "DNS Search List Option"; case 32: return "Proxy Signature (PS)"; case 138: return "CARD Request option"; case 139: return "CARD Reply option"; case 253: return "RFC3692-style Experiment 1"; case 254: return "RFC3692-style Experiment 2"; } return NULL; }; static int8_t dissect_neighb_disc_ops(struct pkt_buff *pkt) { size_t pad_bytes; uint16_t ops_total_len; ssize_t ops_payl_len; struct icmpv6_neighb_disc_ops_general *icmp_neighb_disc; while(pkt_len(pkt)) { icmp_neighb_disc = (struct icmpv6_neighb_disc_ops_general *) pkt_pull(pkt,sizeof(*icmp_neighb_disc)); if (icmp_neighb_disc == NULL) return 0; ops_total_len = icmp_neighb_disc->len * 8; pad_bytes = (size_t) (ops_total_len % 8); ops_payl_len = ops_total_len - sizeof(*icmp_neighb_disc) - pad_bytes; tprintf("\n\tOption %s (%u) ", icmpv6_neighb_disc_ops(icmp_neighb_disc->type) ? icmpv6_neighb_disc_ops(icmp_neighb_disc->type) : "Type Unknown", icmp_neighb_disc->type); if (ops_payl_len > pkt_len(pkt) || ops_payl_len < 0) { tprintf("Length (%u, %u bytes, %s%s%s) ", icmp_neighb_disc->len, ops_total_len, colorize_start_full(black, red), "invalid", colorize_end()); return 0; } tprintf("Length (%u, %u bytes) ",icmp_neighb_disc->len, ops_total_len); switch (icmp_neighb_disc->type) { case 1: if (!dissect_neighb_disc_ops_1(pkt, ops_payl_len)) return 0; break; case 2: if (!dissect_neighb_disc_ops_2(pkt, ops_payl_len)) return 0; break; case 3: if (!dissect_neighb_disc_ops_3(pkt, ops_payl_len)) return 0; break; case 4: if (!dissect_neighb_disc_ops_4(pkt, ops_payl_len)) return 0; break; case 5: if (!dissect_neighb_disc_ops_5(pkt, ops_payl_len)) return 0; break; /* Type 9 and 10 defined in * http://tools.ietf.org/html/rfc3122#section-3.1 */ case 9: if (!dissect_neighb_disc_ops_9(pkt, ops_payl_len)) return 0; break; case 10: if (!dissect_neighb_disc_ops_10(pkt, ops_payl_len)) return 0; break; /* Type 15 and 16 defined in * http://tools.ietf.org/html/rfc3971#section-6.4.3 * http://tools.ietf.org/html/rfc3971#section-6.4.4 */ case 15: if (!dissect_neighb_disc_ops_15(pkt, ops_payl_len)) return 0; break; case 16: if (!dissect_neighb_disc_ops_16(pkt, ops_payl_len)) return 0; break; /* Type 17 and 19 defined in * http://tools.ietf.org/html/rfc5568#section-6.4 */ case 17: if (!dissect_neighb_disc_ops_17(pkt, ops_payl_len)) return 0; break; case 19: if (!dissect_neighb_disc_ops_19(pkt, ops_payl_len)) return 0; break; default: pkt_pull(pkt, ops_payl_len); } /* Skip Padding Bytes */ if (pad_bytes > pkt_len(pkt)) { tprintf(" %s",colorize_start_full(black, red) "Invalid Padding" colorize_end()); return 0; } pkt_pull(pkt, pad_bytes); } return 1; } static const char *icmpv6_type_1_codes[] = { "No route to destination", "Communication with destination administratively prohibited", "Beyond scope of source address", "Address unreachable", "Port unreachable", "Source address failed ingress/egress policy", "Reject route to destination", "Error in Source Routing Header", }; static int8_t dissect_icmpv6_type1(struct pkt_buff *pkt) { struct icmpv6_type_1_3 *icmp_1; icmp_1 = (struct icmpv6_type_1_3 *) pkt_pull(pkt,sizeof(*icmp_1)); if (icmp_1 == NULL) return 0; tprintf(", Unused (0x%x)",ntohl(icmp_1->unused)); tprintf(" Payload include as much of invoking packet"); return 1; } static int8_t dissect_icmpv6_type2(struct pkt_buff *pkt) { struct icmpv6_type_2 *icmp_2; icmp_2 = (struct icmpv6_type_2 *) pkt_pull(pkt,sizeof(*icmp_2)); if (icmp_2 == NULL) return 0; tprintf(", MTU (0x%x)",ntohl(icmp_2->MTU)); tprintf(" Payload include as much of invoking packet"); return 1; } static const char *icmpv6_type_3_codes[] = { "Hop limit exceeded in transit", "Fragment reassembly time exceeded", }; static int8_t dissect_icmpv6_type3(struct pkt_buff *pkt) { struct icmpv6_type_1_3 *icmp_3; icmp_3 = (struct icmpv6_type_1_3 *) pkt_pull(pkt,sizeof(*icmp_3)); if (icmp_3 == NULL) return 0; tprintf(", Unused (0x%x)",ntohl(icmp_3->unused)); tprintf(" Payload include as much of invoking packet"); return 1; } static const char *icmpv6_type_4_codes[] = { "Erroneous header field encountered", "Unrecognized Next Header type encountered", "Unrecognized IPv6 option encountered", }; static int8_t dissect_icmpv6_type4(struct pkt_buff *pkt) { struct icmpv6_type_4 *icmp_4; icmp_4 = (struct icmpv6_type_4 *) pkt_pull(pkt,sizeof(*icmp_4)); if (icmp_4 == NULL) return 0; tprintf(", Pointer (0x%x)",ntohl(icmp_4->pointer)); tprintf(" Payload include as much of invoking packet"); return 1; } static int8_t dissect_icmpv6_type128(struct pkt_buff *pkt) { struct icmpv6_type_128_129 *icmp_128; icmp_128 = (struct icmpv6_type_128_129 *) pkt_pull(pkt,sizeof(*icmp_128)); if (icmp_128 == NULL) return 0; tprintf(", ID (0x%x)",ntohs(icmp_128->id)); tprintf(", Seq. Nr. (%u)",ntohs(icmp_128->sn)); tprintf(" Payload include Data"); return 1; } static int8_t dissect_icmpv6_type129(struct pkt_buff *pkt) { struct icmpv6_type_128_129 *icmp_129; icmp_129 = (struct icmpv6_type_128_129 *) pkt_pull(pkt,sizeof(*icmp_129)); if (icmp_129 == NULL) return 0; tprintf(", ID (0x%x)",ntohs(icmp_129->id)); tprintf(", Seq. Nr. (%u)",ntohs(icmp_129->sn)); tprintf(" Payload include Data"); return 1; } static int8_t dissect_icmpv6_type130(struct pkt_buff *pkt) { char address[INET6_ADDRSTRLEN]; uint16_t nr_src, maxrespdel; uint8_t switch_mldv2 = 0; struct icmpv6_type_130_131_132 *icmp_130; icmp_130 = (struct icmpv6_type_130_131_132 *) pkt_pull(pkt,sizeof(*icmp_130)); if (icmp_130 == NULL) return 0; maxrespdel = ntohs(icmp_130->maxrespdel); if(pkt_len(pkt) >= sizeof(struct icmpv6_type_130_mldv2)) switch_mldv2 = 1; if(switch_mldv2) tprintf(", MLDv2, Max Resp Delay (%ums)", maxrespdel >> 15 ? (((maxrespdel & 0xFFF) | 0x1000) << (((maxrespdel >> 12) & 0x3) + 3)) : maxrespdel); else tprintf(", Max Resp Delay (%ums)",maxrespdel); tprintf(", Res (0x%x)",ntohs(icmp_130->res)); tprintf(", Address: %s", inet_ntop(AF_INET6, &icmp_130->ipv6_addr, address, sizeof(address))); if(switch_mldv2) { struct icmpv6_type_130_mldv2 *icmp_130_mldv2; icmp_130_mldv2 = (struct icmpv6_type_130_mldv2 *) pkt_pull(pkt,sizeof(*icmp_130_mldv2)); if (icmp_130_mldv2 == NULL) return 0; nr_src = ntohs(icmp_130_mldv2->nr_src); tprintf(", Resv (0x%x)",icmp_130_mldv2->resv_S_QRV >> 4); tprintf(", S (%u)",(icmp_130_mldv2->resv_S_QRV >> 3) & 0x1); tprintf(", QRV (0x%x)",icmp_130_mldv2->resv_S_QRV & 0x3); tprintf(", QQIC (%u)",icmp_130_mldv2->QQIC); tprintf(", Nr Src (%u)",nr_src); return print_ipv6_addr_list(pkt, nr_src); } return 1; } static int8_t dissect_icmpv6_type131(struct pkt_buff *pkt) { char address[INET6_ADDRSTRLEN]; struct icmpv6_type_130_131_132 *icmp_131; icmp_131 = (struct icmpv6_type_130_131_132 *) pkt_pull(pkt,sizeof(*icmp_131)); if (icmp_131 == NULL) return 0; tprintf(", Max Resp Delay (%ums)",ntohs(icmp_131->maxrespdel)); tprintf(", Res (0x%x)",ntohs(icmp_131->res)); tprintf(", Address: %s", inet_ntop(AF_INET6, &icmp_131->ipv6_addr, address, sizeof(address))); return 1; } static inline int8_t dissect_icmpv6_type132(struct pkt_buff *pkt) { return dissect_icmpv6_type131(pkt); } static int8_t dissect_icmpv6_type133(struct pkt_buff *pkt) { struct icmpv6_type_133_141_142 *icmp_133; icmp_133 = (struct icmpv6_type_133_141_142 *) pkt_pull(pkt,sizeof(*icmp_133)); if (icmp_133 == NULL) return 0; tprintf(", Reserved (0x%x)",ntohl(icmp_133->res)); return dissect_neighb_disc_ops(pkt); } static int8_t dissect_icmpv6_type134(struct pkt_buff *pkt) { struct icmpv6_type_134 *icmp_134; icmp_134 = (struct icmpv6_type_134 *) pkt_pull(pkt,sizeof(*icmp_134)); if (icmp_134 == NULL) return 0; tprintf(", Cur Hop Limit (%u)",icmp_134->cur_hop_limit); tprintf(", M (%u) O (%u)",icmp_134->m_o_res >> 7, (icmp_134->m_o_res >> 6) & 0x1); tprintf(", Router Lifetime (%us)",ntohs(icmp_134->router_lifetime)); tprintf(", Reachable Time (%ums)",ntohl(icmp_134->reachable_time)); tprintf(", Retrans Timer (%ums)",ntohl(icmp_134->retrans_timer)); return dissect_neighb_disc_ops(pkt); } static int8_t dissect_icmpv6_type135(struct pkt_buff *pkt) { char address[INET6_ADDRSTRLEN]; struct icmpv6_type_135 *icmp_135; icmp_135 = (struct icmpv6_type_135 *) pkt_pull(pkt,sizeof(*icmp_135)); if (icmp_135 == NULL) return 0; tprintf(", Reserved (0x%x)",ntohl(icmp_135->res)); tprintf(", Target Address: %s", inet_ntop(AF_INET6, &icmp_135->ipv6_addr, address, sizeof(address))); return dissect_neighb_disc_ops(pkt); } static int8_t dissect_icmpv6_type136(struct pkt_buff *pkt) { char address[INET6_ADDRSTRLEN]; uint32_t r_s_o_res; struct icmpv6_type_136 *icmp_136; icmp_136 = (struct icmpv6_type_136 *) pkt_pull(pkt,sizeof(*icmp_136)); if (icmp_136 == NULL) return 0; r_s_o_res = ntohl(icmp_136->r_s_o_res); tprintf(", R (%u) S (%u) O (%u) Reserved (0x%x)", r_s_o_res >> 31, (r_s_o_res >> 30) & 0x1, (r_s_o_res >> 29) & 0x1, r_s_o_res & 0x1FFFFFFF); tprintf(", Target Address: %s", inet_ntop(AF_INET6, &icmp_136->ipv6_addr, address, sizeof(address))); return dissect_neighb_disc_ops(pkt); } static int8_t dissect_icmpv6_type137(struct pkt_buff *pkt) { char address[INET6_ADDRSTRLEN]; struct icmpv6_type_137 *icmp_137; icmp_137 = (struct icmpv6_type_137 *) pkt_pull(pkt,sizeof(*icmp_137)); if (icmp_137 == NULL) return 0; tprintf(", Reserved (0x%x)",icmp_137->res); tprintf(", Target Address: %s", inet_ntop(AF_INET6, &icmp_137->ipv6_targ_addr, address, sizeof(address))); tprintf(", Dest Address: %s", inet_ntop(AF_INET6, &icmp_137->ipv6_dest_addr, address, sizeof(address))); return dissect_neighb_disc_ops(pkt); } static void dissect_icmpv6_rr_body(struct pkt_buff *pkt) { /* * Upgrade Dissector for Message Body * from http://tools.ietf.org/html/rfc2894#section-3.2 */ if(pkt_len(pkt)) tprintf(" Message Body recognized"); } static inline char *icmpv6_type_138_codes(uint8_t code) { switch (code) { case 1: return "Router Renumbering Command"; case 2: return "Router Renumbering Result"; case 255: return "Sequence Number Reset"; } return NULL; }; static int8_t dissect_icmpv6_type138(struct pkt_buff *pkt) { struct icmpv6_type_138 *icmp_138; icmp_138 = (struct icmpv6_type_138 *) pkt_pull(pkt,sizeof(*icmp_138)); if (icmp_138 == NULL) return 0; tprintf(", Sequence Nr. (%u)",ntohl(icmp_138->seq_nr)); tprintf(", Segment Nr. (%u)",icmp_138->seg_nr); tprintf(", T (%u) R (%u) A (%u) S (%u) P (%u) Res \ (0x%x) ",icmp_138->flags >> 7, (icmp_138->flags >> 6) & 1, (icmp_138->flags >> 5) & 1, (icmp_138->flags >> 4) & 1, (icmp_138->flags >> 3) & 1, icmp_138->flags & 7); tprintf(", Max Delay (%ums)", ntohs(icmp_138->maxdelay)); tprintf(", Res (0x%x)", ntohl(icmp_138->res)); dissect_icmpv6_rr_body(pkt); return 1; } static void dissect_icmpv6_node_inf_data(struct pkt_buff *pkt) { /* * Upgrade Dissector for Data field * http://tools.ietf.org/html/rfc4620#section-4 */ if(pkt_len(pkt)) tprintf(" Data recognized"); } static const char *icmpv6_node_inf_qtypes[] = { "NOOP", "unused", "Node Name", "Node Addresses", "IPv4 Addresses ", }; static const char *icmpv6_type_139_codes[] = { "Data contains IPv6 Address", "Data contains Name or nothing", "Data contains IPv4 Address", }; static int8_t dissect_icmpv6_type139(struct pkt_buff *pkt) { const char *qtype_name = "Unknown"; uint16_t qtype_nr; struct icmpv6_type_139_140 *icmp_139; icmp_139 = (struct icmpv6_type_139_140 *) pkt_pull(pkt,sizeof(*icmp_139)); if (icmp_139 == NULL) return 0; qtype_nr = ntohs(icmp_139->qtype); if (icmpv6_code_range_valid(qtype_nr, icmpv6_node_inf_qtypes)) qtype_name = icmpv6_node_inf_qtypes[qtype_nr]; tprintf(", Qtype %s (%u)", qtype_name, qtype_nr); tprintf(", Flags (0x%x)", ntohs(icmp_139->flags)); tprintf(", Nonce (0x%x)", ntohll(icmp_139->nonce)); dissect_icmpv6_node_inf_data(pkt); return 1; } static char *icmpv6_type_140_codes[] = { "Successfull reply", "Responder refuses answer", "Qtype is unknown to the Responder", }; static inline int8_t dissect_icmpv6_type140(struct pkt_buff *pkt) { return dissect_icmpv6_type139(pkt); } static inline int8_t dissect_icmpv6_type141(struct pkt_buff *pkt) { return dissect_icmpv6_type133(pkt); } static inline int8_t dissect_icmpv6_type142(struct pkt_buff *pkt) { return dissect_icmpv6_type133(pkt); } static int8_t dissect_icmpv6_type143(struct pkt_buff *pkt) { uint16_t nr_rec; struct icmpv6_type_143 *icmp_143; icmp_143 = (struct icmpv6_type_143 *) pkt_pull(pkt,sizeof(*icmp_143)); if (icmp_143 == NULL) return 0; nr_rec = ntohs(icmp_143->nr_rec); tprintf(", Res (0x%x)",ntohs(icmp_143->res)); tprintf(", Nr. Mcast Addr Records (%u)",nr_rec); return dissect_icmpv6_mcast_rec(pkt, nr_rec); } static int8_t dissect_icmpv6_type144(struct pkt_buff *pkt) { struct icmpv6_type_144_146 *icmp_144; icmp_144 = (struct icmpv6_type_144_146 *) pkt_pull(pkt,sizeof(*icmp_144)); if (icmp_144 == NULL) return 0; tprintf(", ID (%u)",ntohs(icmp_144->id)); tprintf(", Res (0x%x)",ntohs(icmp_144->res)); return 1; } static int8_t dissect_icmpv6_type145(struct pkt_buff *pkt) { struct icmpv6_type_145 *icmp_145; icmp_145 = (struct icmpv6_type_145 *) pkt_pull(pkt,sizeof(*icmp_145)); if (icmp_145 == NULL) return 0; tprintf(", ID (%u)",ntohs(icmp_145->id)); tprintf(", Res (0x%x)",ntohs(icmp_145->res)); return print_ipv6_addr_list(pkt, pkt_len(pkt) / sizeof(struct in6_addr)); } static inline int8_t dissect_icmpv6_type146(struct pkt_buff *pkt) { return dissect_icmpv6_type144(pkt); } static int8_t dissect_icmpv6_type147(struct pkt_buff *pkt) { uint16_t m_o_res; struct icmpv6_type_147 *icmp_147; icmp_147 = (struct icmpv6_type_147 *) pkt_pull(pkt,sizeof(*icmp_147)); if (icmp_147 == NULL) return 0; m_o_res = ntohs(icmp_147->m_o_res); tprintf(", ID (%u)",ntohs(icmp_147->id)); tprintf(", M (%u) O (%u) Res (0x%x)",m_o_res >> 15, (m_o_res >> 14) & 1, m_o_res & 0x3FFF); return dissect_neighb_disc_ops(pkt); } static int8_t dissect_icmpv6_type148(struct pkt_buff *pkt) { struct icmpv6_type_148 *icmp_148; icmp_148 = (struct icmpv6_type_148 *) pkt_pull(pkt,sizeof(*icmp_148)); if (icmp_148 == NULL) return 0; tprintf(", ID (%u)",ntohs(icmp_148->id)); tprintf(", Component (%u)",ntohs(icmp_148->comp)); return dissect_neighb_disc_ops(pkt); } static int8_t dissect_icmpv6_type149(struct pkt_buff *pkt) { struct icmpv6_type_149 *icmp_149; icmp_149 = (struct icmpv6_type_149 *) pkt_pull(pkt,sizeof(*icmp_149)); if (icmp_149 == NULL) return 0; tprintf(", ID (%u)",ntohs(icmp_149->id)); tprintf(", All Components (%u)",ntohs(icmp_149->all_comp)); tprintf(", Component (%u)",ntohs(icmp_149->comp)); tprintf(", Res (0x%x)",ntohs(icmp_149->res)); return dissect_neighb_disc_ops(pkt); } static int8_t dissect_icmpv6_type150(struct pkt_buff *pkt) { struct icmpv6_type_150 *icmp_150; icmp_150 = (struct icmpv6_type_150 *) pkt_pull(pkt,sizeof(*icmp_150)); if (icmp_150 == NULL) return 0; tprintf(", Subtype (%u)",icmp_150->subtype); tprintf(", Res (0x%x)",icmp_150->res); tprintf(", Options in Payload"); return 1; } static int8_t dissect_icmpv6_type151(struct pkt_buff *pkt) { struct icmpv6_type_151 *icmp_151; icmp_151 = (struct icmpv6_type_151 *) pkt_pull(pkt,sizeof(*icmp_151)); if (icmp_151 == NULL) return 0; tprintf(", Query Interval (%us)",ntohs(icmp_151->query_intv)); tprintf(", Robustness Variable (%u)",ntohs(icmp_151->rob_var)); return 1; } static int8_t dissect_icmpv6_type152(struct pkt_buff *pkt) { struct icmpv6_type_152 *icmp_152; icmp_152 = (struct icmpv6_type_152 *) pkt_pull(pkt,sizeof(*icmp_152)); if (icmp_152 == NULL) return 0; return 1; } static int8_t dissect_icmpv6_type153(struct pkt_buff *pkt) { struct icmpv6_type_153 *icmp_153; icmp_153 = (struct icmpv6_type_153 *) pkt_pull(pkt,sizeof(*icmp_153)); if (icmp_153 == NULL) return 0; return 1; } static int8_t dissect_icmpv6_type154(struct pkt_buff *pkt) { struct icmpv6_type_154 *icmp_154; icmp_154 = (struct icmpv6_type_154 *) pkt_pull(pkt,sizeof(*icmp_154)); if (icmp_154 == NULL) return 0; tprintf(", Subtype (%u)",icmp_154->subtype); tprintf(", Res (0x%x)",icmp_154->res); tprintf(", ID (%u)",ntohs(icmp_154->id)); return dissect_neighb_disc_ops(pkt); } static inline char *icmpv6_type_155_codes(uint8_t code) { switch (code) { case 0x00: return "DODAG Information Solicitation"; case 0x01: return "DODAG Information Object"; case 0x02: return "Destination Advertisement Object"; case 0x03: return "Destination Advertisement Object Acknowledgment"; case 0x80: return "Secure DODAG Information Solicitation"; case 0x81: return "Secure DODAG Information Object"; case 0x82: return "Secure Destination Advertisement Object"; case 0x83: return "Secure Destination Advertisement Object Acknowledgment"; case 0x8A: return "Consistency Check"; } return NULL; }; static void icmpv6_process(struct icmpv6_general_hdr *icmp, const char **type, const char **code, int8_t (**optional)(struct pkt_buff *pkt)) { *type = "Unknown Type"; *code = "Unknown Code"; switch (icmp->h_type) { case 1: *type = "Destination Unreachable"; if (icmpv6_code_range_valid(icmp->h_code, icmpv6_type_1_codes)) *code = icmpv6_type_1_codes[icmp->h_code]; *optional = dissect_icmpv6_type1; return; case 2: *type = "Packet Too Big"; *optional = dissect_icmpv6_type2; return; case 3: *type = "Time Exceeded"; if (icmpv6_code_range_valid(icmp->h_code, icmpv6_type_3_codes)) *code = icmpv6_type_3_codes[icmp->h_code]; *optional = dissect_icmpv6_type3; return; case 4: *type = "Parameter Problem"; if (icmpv6_code_range_valid(icmp->h_code, icmpv6_type_4_codes)) *code = icmpv6_type_4_codes[icmp->h_code]; *optional = dissect_icmpv6_type4; return; case 100: *type = "Private experimation"; return; case 101: *type = "Private experimation"; return; case 127: *type = "Reserved for expansion of ICMPv6 error messages"; return; case 128: *type = "Echo Request"; *optional = dissect_icmpv6_type128; return; case 129: *type = "Echo Reply"; *optional = dissect_icmpv6_type129; return; case 130: *type = "Multicast Listener Query"; *optional = dissect_icmpv6_type130; return; case 131: *type = "Multicast Listener Report"; *optional = dissect_icmpv6_type131; return; case 132: *type = "Multicast Listener Done"; *optional = dissect_icmpv6_type132; return; case 133: *type = "Router Solicitation"; *optional = dissect_icmpv6_type133; return; case 134: *type = "Router Advertisement"; *optional = dissect_icmpv6_type134; return; case 135: *type = "Neighbor Solicitation"; *optional = dissect_icmpv6_type135; return; case 136: *type = "Neighbor Advertisement"; *optional = dissect_icmpv6_type136; return; case 137: *type = "Redirect Message"; *optional = dissect_icmpv6_type137; return; case 138: *type = "Router Renumbering"; if(icmpv6_type_138_codes(icmp->h_code)) *code = icmpv6_type_138_codes(icmp->h_code); *optional = dissect_icmpv6_type138; return; case 139: *type = "ICMP Node Information Query"; if (icmpv6_code_range_valid(icmp->h_code, icmpv6_type_139_codes)) *code = icmpv6_type_139_codes[icmp->h_code]; *optional = dissect_icmpv6_type139; return; case 140: *type = "ICMP Node Information Response"; if (icmpv6_code_range_valid(icmp->h_code, icmpv6_type_140_codes)) *code = icmpv6_type_140_codes[icmp->h_code]; *optional = dissect_icmpv6_type140; return; case 141: *type = "Inverse Neighbor Discovery Solicitation Message"; *optional = dissect_icmpv6_type141; return; case 142: *type = "Inverse Neighbor Discovery Advertisement Message"; *optional = dissect_icmpv6_type142; return; case 143: *type = "Multicast Listener Report v2"; *optional = dissect_icmpv6_type143; return; case 144: *type = "Home Agent Address Discovery Request Message"; *optional = dissect_icmpv6_type144; return; case 145: *type = "Home Agent Address Discovery Reply Message"; *optional = dissect_icmpv6_type145; return; case 146: *type = "Mobile Prefix Solicitation"; *optional = dissect_icmpv6_type146; return; case 147: *type = "Mobile Prefix Advertisement"; *optional = dissect_icmpv6_type147; return; case 148: *type = "Certification Path Solicitation"; *optional = dissect_icmpv6_type148; return; case 149: *type = "Certification Path Advertisement"; *optional = dissect_icmpv6_type149; return; case 150: *type = "ICMP messages utilized by experimental mobility " "protocols such as Seamoby"; *optional = dissect_icmpv6_type150; return; case 151: *type = "Multicast Router Advertisement"; *code = "Ad. Interval"; *optional = dissect_icmpv6_type151; return; case 152: *type = "Multicast Router Solicitation"; *code = "Reserved"; *optional = dissect_icmpv6_type152; return; case 153: *type = "Multicast Router Termination"; *code = "Reserved"; *optional = dissect_icmpv6_type153; return; case 154: *type = "FMIPv6 Messages"; *optional = dissect_icmpv6_type154; return; case 155: *type = "RPL Control Message"; if(icmpv6_type_155_codes(icmp->h_code)) *code = icmpv6_type_155_codes(icmp->h_code); return; case 200: *type = "Private experimation"; return; case 201: *type = "Private experimation"; return; case 255: *type = "Reserved for expansion of ICMPv6 error messages"; return; } } static void icmpv6(struct pkt_buff *pkt) { const char *type = NULL, *code = NULL; int8_t (*optional)(struct pkt_buff *pkt) = NULL; struct icmpv6_general_hdr *icmp = (struct icmpv6_general_hdr *) pkt_pull(pkt, sizeof(*icmp)); if (icmp == NULL) return; icmpv6_process(icmp, &type, &code, &optional); tprintf(" [ ICMPv6 "); tprintf("%s (%u), ", type, icmp->h_type); tprintf("%s (%u), ", code, icmp->h_code); tprintf("Chks (0x%x)", ntohs(icmp->h_chksum)); if (optional) if (!((*optional) (pkt))) tprintf("\n%s%s%s", colorize_start_full(black, red), "Failed to dissect Message", colorize_end()); tprintf(" ]\n"); } static void icmpv6_less(struct pkt_buff *pkt) { struct icmpv6_general_hdr *icmp = (struct icmpv6_general_hdr *) pkt_pull(pkt, sizeof(*icmp)); if (icmp == NULL) return; tprintf(" ICMPv6 Type (%u) Code (%u)", icmp->h_type, icmp->h_code); } struct protocol icmpv6_ops = { .key = 0x3A, .print_full = icmpv6, .print_less = icmpv6_less, }; EXPORT_SYMBOL(icmpv6_ops); netsniff-ng-0.5.7/src/proto_icmpv4.c0000664000175000017500000000233611773367375017502 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #include #include #include /* for ntohs() */ #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "pkt_buff.h" #include "built_in.h" struct icmphdr { uint8_t type; uint8_t code; uint16_t checksum; union { struct { uint16_t id; uint16_t sequence; } echo; uint32_t gateway; struct { uint16_t ____unused; uint16_t mtu; } frag; } un; } __packed; static void icmp(struct pkt_buff *pkt) { struct icmphdr *icmp = (struct icmphdr *) pkt_pull(pkt, sizeof(*icmp)); if (icmp == NULL) return; tprintf(" [ ICMP "); tprintf("Type (%u), ", icmp->type); tprintf("Code (%u), ", icmp->code); tprintf("CSum (0x%.4x)", ntohs(icmp->checksum)); tprintf(" ]\n"); } static void icmp_less(struct pkt_buff *pkt) { struct icmphdr *icmp = (struct icmphdr *) pkt_pull(pkt, sizeof(*icmp)); if (icmp == NULL) return; tprintf(" Type %u Code %u", icmp->type, icmp->code); } struct protocol icmpv4_ops = { .key = 0x01, .print_full = icmp, .print_less = icmp_less, }; EXPORT_SYMBOL(icmp_ops); netsniff-ng-0.5.7/src/proto_ethernet.c0000664000175000017500000000401011773367375020105 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #include #include #include #include #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "pkt_buff.h" #include "oui.h" static void ethernet(struct pkt_buff *pkt) { char *type; uint8_t *src_mac, *dst_mac; struct ethhdr *eth = (struct ethhdr *) pkt_pull(pkt, sizeof(*eth)); if (eth == NULL) return; src_mac = eth->h_source; dst_mac = eth->h_dest; tprintf(" [ Eth "); tprintf("MAC (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x => ", src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5]); tprintf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x), ", dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5]); tprintf("Proto (0x%.4x", ntohs(eth->h_proto)); type = lookup_ether_type(ntohs(eth->h_proto)); if (type) tprintf(", %s%s%s", colorize_start(bold), type, colorize_end()); tprintf(") ]\n"); tprintf(" [ Vendor "); tprintf("(%s => %s)", lookup_vendor((src_mac[0] << 16) | (src_mac[1] << 8) | src_mac[2]), lookup_vendor((dst_mac[0] << 16) | (dst_mac[1] << 8) | dst_mac[2])); tprintf(" ]\n"); pkt_set_proto(pkt, ð_lay2, ntohs(eth->h_proto)); } static void ethernet_less(struct pkt_buff *pkt) { uint8_t *src_mac, *dst_mac; struct ethhdr *eth = (struct ethhdr *) pkt_pull(pkt, sizeof(*eth)); if (eth == NULL) return; src_mac = eth->h_source; dst_mac = eth->h_dest; tprintf(" %s => %s ", lookup_vendor((src_mac[0] << 16) | (src_mac[1] << 8) | src_mac[2]), lookup_vendor((dst_mac[0] << 16) | (dst_mac[1] << 8) | dst_mac[2])); tprintf("%s%s%s", colorize_start(bold), lookup_ether_type(ntohs(eth->h_proto)), colorize_end()); pkt_set_proto(pkt, ð_lay2, ntohs(eth->h_proto)); } struct protocol ethernet_ops = { .key = 0, .print_full = ethernet, .print_less = ethernet_less, }; EXPORT_SYMBOL(ethernet_ops); netsniff-ng-0.5.7/src/proto_arp.c0000664000175000017500000000567411773367375017072 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #include #include #include /* for ntohs() */ #include "proto.h" #include "protos.h" #include "dissector_eth.h" #include "pkt_buff.h" #include "built_in.h" struct arphdr { uint16_t ar_hrd; /* format of hardware address */ uint16_t ar_pro; /* format of protocol address */ uint8_t ar_hln; /* length of hardware address */ uint8_t ar_pln; /* length of protocol address */ uint16_t ar_op; /* ARP opcode (command) */ uint8_t ar_sha[6]; /* sender hardware address */ uint8_t ar_sip[4]; /* sender IP address */ uint8_t ar_tha[6]; /* target hardware address */ uint8_t ar_tip[4]; /* target IP address */ } __packed; #define ARPOP_REQUEST 1 /* ARP request */ #define ARPOP_REPLY 2 /* ARP reply */ #define ARPOP_RREQUEST 3 /* RARP request */ #define ARPOP_RREPLY 4 /* RARP reply */ #define ARPOP_InREQUEST 8 /* InARP request */ #define ARPOP_InREPLY 9 /* InARP reply */ #define ARPOP_NAK 10 /* (ATM)ARP NAK */ static void arp(struct pkt_buff *pkt) { char *opcode = NULL; struct arphdr *arp = (struct arphdr *) pkt_pull(pkt, sizeof(*arp)); if (arp == NULL) return; switch (ntohs(arp->ar_op)) { case ARPOP_REQUEST: opcode = "ARP request"; break; case ARPOP_REPLY: opcode = "ARP reply"; break; case ARPOP_RREQUEST: opcode = "RARP request"; break; case ARPOP_RREPLY: opcode = "RARP reply"; break; case ARPOP_InREQUEST: opcode = "InARP request"; break; case ARPOP_InREPLY: opcode = "InARP reply"; break; case ARPOP_NAK: opcode = "(ATM) ARP NAK"; break; default: opcode = "Unknown"; break; }; tprintf(" [ ARP "); tprintf("Format HA (%u), ", ntohs(arp->ar_hrd)); tprintf("Format Proto (%u), ", ntohs(arp->ar_pro)); tprintf("HA Len (%u), ", ntohs(arp->ar_hln)); tprintf("Proto Len (%u), ", ntohs(arp->ar_pln)); tprintf("Opcode (%u => %s)", ntohs(arp->ar_op), opcode); tprintf(" ]\n"); } static void arp_less(struct pkt_buff *pkt) { char *opcode = NULL; struct arphdr *arp = (struct arphdr *) pkt_pull(pkt, sizeof(*arp)); if (arp == NULL) return; switch (ntohs(arp->ar_op)) { case ARPOP_REQUEST: opcode = "ARP request"; break; case ARPOP_REPLY: opcode = "ARP reply"; break; case ARPOP_RREQUEST: opcode = "RARP request"; break; case ARPOP_RREPLY: opcode = "RARP reply"; break; case ARPOP_InREQUEST: opcode = "InARP request"; break; case ARPOP_InREPLY: opcode = "InARP reply"; break; case ARPOP_NAK: opcode = "(ATM) ARP NAK"; break; default: opcode = "Unknown"; break; }; tprintf(" Op %s", opcode); } struct protocol arp_ops = { .key = 0x0806, .print_full = arp, .print_less = arp_less, }; EXPORT_SYMBOL(arp_ops); netsniff-ng-0.5.7/src/proto_80211_mac_hdr.c0000664000175000017500000001162511773367375020431 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright 2012 Daniel Borkmann * Copyright 2012 Markus Amend , Deutsche Flugsicherung GmbH * Subject to the GPL, version 2. */ #include #include #include /* for ntohs() */ #include #include "proto.h" #include "protos.h" #include "dissector_80211.h" #include "built_in.h" #include "pkt_buff.h" #include "oui.h" /* Note: Fields are encoded in little-endian! */ struct ieee80211_frm_ctrl { union { u16 frame_control; #if defined(__LITTLE_ENDIAN_BITFIELD) /* Correct order here ... */ __extension__ u16 proto_version:2, type:2, subtype:4, to_ds:1, from_ds:1, more_frags:1, retry:1, power_mgmt:1, more_data:1, wep:1, order:1; #elif defined(__BIG_ENDIAN_BITFIELD) __extension__ u16 subtype:4, type:2, proto_version:2, order:1, wep:1, more_data:1, power_mgmt:1, retry:1, more_frags:1, from_ds:1, to_ds:1; #else # error "Adjust your defines" #endif }; /* TODO: delete if use structs below*/ u16 duration; } __packed; /* Management Frame start */ /* Note: Fields are encoded in little-endian! */ struct ieee80211_mgmt { u16 duration; u8 da[6]; u8 sa[6]; u8 bssid[6]; u16 seq_ctrl; } __packed; struct ieee80211_mgmt_auth { u16 auth_alg; u16 auth_transaction; u16 status_code; /* possibly followed by Challenge text */ u8 variable[0]; } __packed; struct ieee80211_mgmt_deauth { u16 reason_code; } __packed; struct ieee80211_mgmt_assoc_req { u16 capab_info; u16 listen_interval; /* followed by SSID and Supported rates */ u8 variable[0]; } __packed; struct ieee80211_mgmt_assoc_resp { u16 capab_info; u16 status_code; u16 aid; /* followed by Supported rates */ u8 variable[0]; } __packed; struct ieee80211_mgmt_reassoc_resp { u16 capab_info; u16 status_code; u16 aid; /* followed by Supported rates */ u8 variable[0]; } __packed; struct ieee80211_mgmt_reassoc_req { u16 capab_info; u16 listen_interval; u8 current_ap[6]; /* followed by SSID and Supported rates */ u8 variable[0]; } __packed; struct ieee80211_mgmt_disassoc { u16 reason_code; } __packed; struct ieee80211_mgmt_probe_req { } __packed; struct ieee80211_mgmt_beacon { u8 timestamp[8]; u16 beacon_int; u16 capab_info; /* followed by some of SSID, Supported rates, * FH Params, DS Params, CF Params, IBSS Params, TIM */ u8 variable[0]; } __packed; struct ieee80211_mgmt_probe_resp { u8 timestamp[8]; u16 beacon_int; u16 capab_info; /* followed by some of SSID, Supported rates, * FH Params, DS Params, CF Params, IBSS Params, TIM */ u8 variable[0]; } __packed; /* Management Frame end */ /* Control Frame start */ /* Note: Fields are encoded in little-endian! */ struct ieee80211_ctrl { } __packed; struct ieee80211_ctrl_rts { u16 duration; u8 da[6]; u8 sa[6]; } __packed; struct ieee80211_ctrl_cts { u16 duration; u8 da[6]; } __packed; struct ieee80211_ctrl_ack { u16 duration; u8 da[6]; } __packed; struct ieee80211_ctrl_ps_poll { u16 aid; u8 bssid[6]; u8 sa[6]; } __packed; struct ieee80211_ctrl_cf_end { u16 duration; u8 bssid[6]; u8 sa[6]; } __packed; struct ieee80211_ctrl_cf_end_ack { u16 duration; u8 bssid[6]; u8 sa[6]; } __packed; /* Control Frame end */ /* Data Frame start */ /* Note: Fields are encoded in little-endian! */ struct ieee80211_data { } __packed; /* TODO: Extend */ /* Control Frame end */ static const char *frame_control_types[] = { "Management", /* 00 */ "Control", /* 01 */ "Data", /* 10 */ "Reserved", /* 11 */ }; static void ieee80211(struct pkt_buff *pkt) { struct ieee80211_frm_ctrl *frm_ctrl = (struct ieee80211_frm_ctrl *) pkt_pull(pkt, sizeof(*frm_ctrl)); if (frm_ctrl == NULL) return; tprintf(" [ 802.11 Frame Control (0x%04x), Duration/ID (%u) ]\n", le16_to_cpu(frm_ctrl->frame_control), le16_to_cpu(frm_ctrl->duration)); tprintf("\t [ Proto Version (%u), ", frm_ctrl->proto_version); tprintf("Type (%u, %s), ", frm_ctrl->type, frame_control_types[frm_ctrl->type]); tprintf("Subtype (%u)", frm_ctrl->subtype /*XXX*/); tprintf("%s%s", frm_ctrl->to_ds ? ", Frame goes to DS" : "", frm_ctrl->from_ds ? ", Frame comes from DS" : ""); tprintf("%s", frm_ctrl->more_frags ? ", More Fragments" : ""); tprintf("%s", frm_ctrl->retry ? ", Frame is retransmitted" : ""); tprintf("%s", frm_ctrl->power_mgmt ? ", In Power Saving Mode" : ""); tprintf("%s", frm_ctrl->more_data ? ", More Data" : ""); tprintf("%s", frm_ctrl->wep ? ", Needs WEP" : ""); tprintf("%s", frm_ctrl->order ? ", Order" : ""); tprintf(" ]\n"); // pkt_set_proto(pkt, &ieee802_lay2, ntohs(eth->h_proto)); } static void ieee80211_less(struct pkt_buff *pkt) { tprintf("802.11 frame (more on todo)"); } struct protocol ieee80211_ops = { .key = 0, .print_full = ieee80211, .print_less = ieee80211_less, }; EXPORT_SYMBOL(ieee80211_ops); netsniff-ng-0.5.7/src/proto.h0000664000175000017500000000147011773367375016223 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann . * Copyright (C) 2009, 2010 Daniel Borkmann * Copyright (C) 2012 Christoph Jaeger * Subject to the GPL, version 2. */ #ifndef PROTO_H #define PROTO_H #include #include #include "hash.h" #include "tprintf.h" struct pkt_buff; struct protocol { /* Needs to be filled out by user */ unsigned int key; void (*print_full)(struct pkt_buff *pkt); void (*print_less)(struct pkt_buff *pkt); /* Used by program logic */ struct protocol *next; void (*process) (struct pkt_buff *pkt); }; extern void empty(struct pkt_buff *pkt); extern void hex(struct pkt_buff *pkt); extern void ascii(struct pkt_buff *pkt); extern void hex_ascii(struct pkt_buff *pkt); #endif /* PROTO_H */ netsniff-ng-0.5.7/src/pkt_buff.h0000664000175000017500000000425611773367375016665 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * Copyright (C) 2012 Christoph Jaeger * Subject to the GPL, version 2. */ #ifndef PKT_BUFF_H #define PKT_BUFF_H #include "hash.h" #include "built_in.h" #include "proto.h" #include "xmalloc.h" struct pkt_buff { /* invariant: head <= data <= tail */ uint8_t *head; uint8_t *data; uint8_t *tail; unsigned int size; struct protocol *proto; }; static inline struct pkt_buff *pkt_alloc(uint8_t *packet, unsigned int len) { struct pkt_buff *pkt = xmalloc(sizeof(*pkt)); pkt->head = packet; pkt->data = packet; pkt->tail = packet + len; pkt->size = len; pkt->proto = NULL; return pkt; } static inline void pkt_free(struct pkt_buff *pkt) { xfree(pkt); } static inline unsigned int pkt_len(struct pkt_buff *pkt) { bug_on(!pkt || pkt->data > pkt->tail); return pkt->tail - pkt->data; } static inline uint8_t *pkt_pull(struct pkt_buff *pkt, unsigned int len) { uint8_t *data = NULL; bug_on(!pkt || pkt->head > pkt->data || pkt->data > pkt->tail); if (len <= pkt_len(pkt)) { data = pkt->data; pkt->data += len; } bug_on(!pkt || pkt->head > pkt->data || pkt->data > pkt->tail); return data; } static inline uint8_t *pkt_peek(struct pkt_buff *pkt) { bug_on(!pkt || pkt->head > pkt->data || pkt->data > pkt->tail); return pkt->data; } static inline unsigned int pkt_trim(struct pkt_buff *pkt, unsigned int len) { unsigned int ret = 0; bug_on(!pkt || pkt->head > pkt->data || pkt->data > pkt->tail); if (len <= pkt_len(pkt)) ret = len; pkt->tail -= ret; bug_on(!pkt || pkt->head > pkt->data || pkt->data > pkt->tail); return ret; } static inline uint8_t *pkt_pull_tail(struct pkt_buff *pkt, unsigned int len) { uint8_t *tail = NULL; bug_on(!pkt || pkt->head > pkt->data || pkt->data > pkt->tail); if (len <= pkt_len(pkt)) { tail = pkt->tail; pkt->tail -= len; } return tail; } static inline void pkt_set_proto(struct pkt_buff *pkt, struct hash_table *table, unsigned int key) { bug_on(!pkt || !table); pkt->proto = (struct protocol *) lookup_hash(key, table); while (pkt->proto && key != pkt->proto->key) pkt->proto = pkt->proto->next; } #endif /* PKT_BUFF_H */ netsniff-ng-0.5.7/src/pcap_sg.c0000664000175000017500000001226211773367375016470 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2011 Daniel Borkmann. * Subject to the GPL, version 2. */ #include #include #include #include #include #include #include "pcap.h" #include "xmalloc.h" #include "xio.h" #include "xutils.h" #include "locking.h" #include "built_in.h" #define IOVSIZ 1000 #define ALLSIZ (PAGE_SIZE * 3) #define ALLSIZ_2K (PAGE_SIZE * 3) // 12K max #define ALLSIZ_JUMBO (PAGE_SIZE * 16) // 64K max static struct iovec iov[IOVSIZ]; static unsigned long c = 0; static struct spinlock lock; static ssize_t iov_used; static int pcap_sg_pull_file_header(int fd, uint32_t *linktype) { ssize_t ret; struct pcap_filehdr hdr; ret = read(fd, &hdr, sizeof(hdr)); if (unlikely(ret != sizeof(hdr))) return -EIO; pcap_validate_header(&hdr); *linktype = hdr.linktype; return 0; } static int pcap_sg_push_file_header(int fd, uint32_t linktype) { ssize_t ret; struct pcap_filehdr hdr; fmemset(&hdr, 0, sizeof(hdr)); pcap_prepare_header(&hdr, linktype, 0, PCAP_DEFAULT_SNAPSHOT_LEN); ret = write_or_die(fd, &hdr, sizeof(hdr)); if (unlikely(ret != sizeof(hdr))) { whine("Failed to write pkt file header!\n"); return -EIO; } return 0; } static int pcap_sg_prepare_writing_pcap(int fd) { set_ioprio_rt(); return 0; } static ssize_t pcap_sg_write_pcap_pkt(int fd, struct pcap_pkthdr *hdr, uint8_t *packet, size_t len) { ssize_t ret; spinlock_lock(&lock); if (unlikely(c == IOVSIZ)) { ret = writev(fd, iov, IOVSIZ); if (ret < 0) panic("writev I/O error!\n"); c = 0; } iov[c].iov_len = 0; fmemcpy(iov[c].iov_base, hdr, sizeof(*hdr)); iov[c].iov_len += sizeof(*hdr); fmemcpy(iov[c].iov_base + iov[c].iov_len, packet, len); iov[c].iov_len += len; ret = iov[c].iov_len; c++; spinlock_unlock(&lock); return ret; } static int pcap_sg_prepare_reading_pcap(int fd) { set_ioprio_rt(); spinlock_lock(&lock); if (readv(fd, iov, IOVSIZ) <= 0) return -EIO; iov_used = 0; c = 0; spinlock_unlock(&lock); return 0; } static ssize_t pcap_sg_read_pcap_pkt(int fd, struct pcap_pkthdr *hdr, uint8_t *packet, size_t len) { ssize_t ret = 0; /* In contrast to writing, reading gets really ugly ... */ spinlock_lock(&lock); if (likely(iov[c].iov_len - iov_used >= sizeof(*hdr))) { fmemcpy(hdr, iov[c].iov_base + iov_used, sizeof(*hdr)); iov_used += sizeof(*hdr); } else { size_t offset = 0; ssize_t remainder; offset = iov[c].iov_len - iov_used; remainder = sizeof(*hdr) - offset; if (remainder < 0) remainder = 0; bug_on(offset + remainder != sizeof(*hdr)); fmemcpy(hdr, iov[c].iov_base + iov_used, offset); iov_used = 0; c++; if (c == IOVSIZ) { /* We need to refetch! */ c = 0; if (readv(fd, iov, IOVSIZ) <= 0) { ret = -EIO; goto out_err; } } /* Now we copy the remainder and go on with business ... */ fmemcpy((uint8_t *) hdr + offset, iov[c].iov_base + iov_used, remainder); iov_used += remainder; } /* header read completed */ if (unlikely(hdr->caplen == 0 || hdr->caplen > len)) { ret = -EINVAL; /* Bogus packet */ goto out_err; } /* now we read data ... */ if (likely(iov[c].iov_len - iov_used >= hdr->caplen)) { fmemcpy(packet, iov[c].iov_base + iov_used, hdr->caplen); iov_used += hdr->caplen; } else { size_t offset = 0; ssize_t remainder; offset = iov[c].iov_len - iov_used; remainder = hdr->caplen - offset; if (remainder < 0) remainder = 0; bug_on(offset + remainder != hdr->caplen); fmemcpy(packet, iov[c].iov_base + iov_used, offset); iov_used = 0; c++; if (c == IOVSIZ) { /* We need to refetch! */ c = 0; if (readv(fd, iov, IOVSIZ) <= 0) { ret = -EIO; goto out_err; } } /* Now we copy the remainder and go on with business ... */ fmemcpy(packet + offset, iov[c].iov_base + iov_used, remainder); iov_used += remainder; } spinlock_unlock(&lock); return sizeof(*hdr) + hdr->caplen; out_err: spinlock_unlock(&lock); return ret; } static void pcap_sg_fsync_pcap(int fd) { ssize_t ret; spinlock_lock(&lock); ret = writev(fd, iov, c); if (ret < 0) panic("writev I/O error!\n"); c = 0; fdatasync(fd); spinlock_unlock(&lock); } struct pcap_file_ops pcap_sg_ops __read_mostly = { .name = "scatter-gather", .pull_file_header = pcap_sg_pull_file_header, .push_file_header = pcap_sg_push_file_header, .write_pcap_pkt = pcap_sg_write_pcap_pkt, .prepare_reading_pcap = pcap_sg_prepare_reading_pcap, .prepare_writing_pcap = pcap_sg_prepare_writing_pcap, .read_pcap_pkt = pcap_sg_read_pcap_pkt, .fsync_pcap = pcap_sg_fsync_pcap, }; int init_pcap_sg(int jumbo_support) { unsigned long i; size_t allocsz = 0; c = 0; fmemset(iov, 0, sizeof(iov)); if (jumbo_support) allocsz = ALLSIZ_JUMBO; else allocsz = ALLSIZ_2K; for (i = 0; i < IOVSIZ; ++i) { iov[i].iov_base = xzmalloc_aligned(allocsz, 64); iov[i].iov_len = allocsz; } spinlock_init(&lock); return pcap_ops_group_register(&pcap_sg_ops, PCAP_OPS_SG); } void cleanup_pcap_sg(void) { unsigned long i; spinlock_destroy(&lock); for (i = 0; i < IOVSIZ; ++i) xfree(iov[i].iov_base); pcap_ops_group_unregister(PCAP_OPS_SG); } netsniff-ng-0.5.7/src/pcap_rw.c0000664000175000017500000000525511773367375016513 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010, 2011 Daniel Borkmann. * Subject to the GPL, version 2. */ #include #include #include #include #include #include "pcap.h" #include "built_in.h" #include "xutils.h" #include "xio.h" #include "die.h" static int pcap_rw_pull_file_header(int fd, uint32_t *linktype) { ssize_t ret; struct pcap_filehdr hdr; ret = read(fd, &hdr, sizeof(hdr)); if (unlikely(ret != sizeof(hdr))) return -EIO; pcap_validate_header(&hdr); *linktype = hdr.linktype; return 0; } static int pcap_rw_push_file_header(int fd, uint32_t linktype) { ssize_t ret; struct pcap_filehdr hdr; memset(&hdr, 0, sizeof(hdr)); pcap_prepare_header(&hdr, linktype, 0, PCAP_DEFAULT_SNAPSHOT_LEN); ret = write_or_die(fd, &hdr, sizeof(hdr)); if (unlikely(ret != sizeof(hdr))) { whine("Failed to write pkt file header!\n"); return -EIO; } return 0; } static ssize_t pcap_rw_write_pcap_pkt(int fd, struct pcap_pkthdr *hdr, uint8_t *packet, size_t len) { ssize_t ret = write_or_die(fd, hdr, sizeof(*hdr)); if (unlikely(ret != sizeof(*hdr))) { whine("Failed to write pkt header!\n"); return -EIO; } if (unlikely(hdr->len != len)) return -EINVAL; ret = write_or_die(fd, packet, hdr->len); if (unlikely(ret != hdr->len)) { whine("Failed to write pkt payload!\n"); return -EIO; } return sizeof(*hdr) + hdr->len; } static ssize_t pcap_rw_read_pcap_pkt(int fd, struct pcap_pkthdr *hdr, uint8_t *packet, size_t len) { ssize_t ret = read(fd, hdr, sizeof(*hdr)); if (unlikely(ret != sizeof(*hdr))) return -EIO; if (unlikely(hdr->caplen == 0 || hdr->caplen > len)) return -EINVAL; /* Bogus packet */ ret = read(fd, packet, hdr->caplen); if (unlikely(ret != hdr->caplen)) return -EIO; return sizeof(*hdr) + hdr->caplen; } static void pcap_rw_fsync_pcap(int fd) { fdatasync(fd); } static int pcap_rw_prepare_writing_pcap(int fd) { set_ioprio_rt(); return 0; } static int pcap_rw_prepare_reading_pcap(int fd) { set_ioprio_rt(); return 0; } struct pcap_file_ops pcap_rw_ops __read_mostly = { .name = "read-write", .pull_file_header = pcap_rw_pull_file_header, .push_file_header = pcap_rw_push_file_header, .write_pcap_pkt = pcap_rw_write_pcap_pkt, .read_pcap_pkt = pcap_rw_read_pcap_pkt, .fsync_pcap = pcap_rw_fsync_pcap, .prepare_writing_pcap = pcap_rw_prepare_writing_pcap, .prepare_reading_pcap = pcap_rw_prepare_reading_pcap, }; int init_pcap_rw(int jumbo_support) { return pcap_ops_group_register(&pcap_rw_ops, PCAP_OPS_RW); } void cleanup_pcap_rw(void) { pcap_ops_group_unregister(PCAP_OPS_RW); } netsniff-ng-0.5.7/src/pcap_mmap.c0000664000175000017500000001325411773367375017013 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2011 Daniel Borkmann. * Subject to the GPL, version 2. */ #define _GNU_SOURCE #include #include #include #include #include #include #include "pcap.h" #include "xio.h" #include "xutils.h" #include "locking.h" #include "built_in.h" #define DEFAULT_SLOTS 1000 static struct spinlock lock; static off_t map_size = 0; static char *pstart, *pcurr; static int jumbo_frames = 0; static inline off_t get_map_size(void) { int allocsz = jumbo_frames ? 16 : 3; return PAGE_ALIGN(sizeof(struct pcap_filehdr) + (PAGE_SIZE * allocsz) * DEFAULT_SLOTS); } static int pcap_mmap_pull_file_header(int fd, uint32_t *linktype) { ssize_t ret; struct pcap_filehdr hdr; ret = read(fd, &hdr, sizeof(hdr)); if (unlikely(ret != sizeof(hdr))) return -EIO; pcap_validate_header(&hdr); *linktype = hdr.linktype; return 0; } static int pcap_mmap_push_file_header(int fd, uint32_t linktype) { ssize_t ret; struct pcap_filehdr hdr; fmemset(&hdr, 0, sizeof(hdr)); pcap_prepare_header(&hdr, linktype, 0, PCAP_DEFAULT_SNAPSHOT_LEN); ret = write_or_die(fd, &hdr, sizeof(hdr)); if (unlikely(ret != sizeof(hdr))) { whine("Failed to write pkt file header!\n"); return -EIO; } return 0; } static int pcap_mmap_prepare_writing_pcap(int fd) { int ret; off_t pos; struct stat sb; set_ioprio_be(); spinlock_lock(&lock); map_size = get_map_size(); ret = fstat(fd, &sb); if (ret < 0) panic("Cannot fstat pcap file!\n"); if (!S_ISREG (sb.st_mode)) panic("pcap dump file is not a regular file!\n"); pos = lseek(fd, map_size, SEEK_SET); if (pos < 0) panic("Cannot lseek pcap file!\n"); ret = write_or_die(fd, "", 1); if (ret != 1) panic("Cannot write file!\n"); pstart = mmap(0, map_size, PROT_WRITE, MAP_SHARED /*| MAP_HUGETLB*/, fd, 0); if (pstart == MAP_FAILED) panic("mmap of file failed!"); ret = madvise(pstart, map_size, MADV_SEQUENTIAL); if (ret < 0) panic("Failed to give kernel mmap advise!\n"); pcurr = pstart + sizeof(struct pcap_filehdr); spinlock_unlock(&lock); return 0; } static ssize_t pcap_mmap_write_pcap_pkt(int fd, struct pcap_pkthdr *hdr, uint8_t *packet, size_t len) { int ret; off_t pos; spinlock_lock(&lock); if ((off_t) (pcurr - pstart) + sizeof(*hdr) + len > map_size) { off_t map_size_old = map_size; off_t offset = (pcurr - pstart); map_size = PAGE_ALIGN(map_size_old * 10 / 8); pos = lseek(fd, map_size, SEEK_SET); if (pos < 0) panic("Cannot lseek pcap file!\n"); ret = write_or_die(fd, "", 1); if (ret != 1) panic("Cannot write file!\n"); pstart = mremap(pstart, map_size_old, map_size, MREMAP_MAYMOVE); if (pstart == MAP_FAILED) panic("mmap of file failed!"); ret = madvise(pstart, map_size, MADV_SEQUENTIAL); if (ret < 0) panic("Failed to give kernel mmap advise!\n"); pcurr = pstart + offset; } fmemcpy(pcurr, hdr, sizeof(*hdr)); pcurr += sizeof(*hdr); fmemcpy(pcurr, packet, len); pcurr += len; spinlock_unlock(&lock); return sizeof(*hdr) + len; } static int pcap_mmap_prepare_reading_pcap(int fd) { int ret; struct stat sb; set_ioprio_be(); spinlock_lock(&lock); ret = fstat(fd, &sb); if (ret < 0) panic("Cannot fstat pcap file!\n"); if (!S_ISREG (sb.st_mode)) panic("pcap dump file is not a regular file!\n"); map_size = sb.st_size; pstart = mmap(0, map_size, PROT_READ, MAP_SHARED | MAP_LOCKED /*| MAP_HUGETLB*/, fd, 0); if (pstart == MAP_FAILED) panic("mmap of file failed!"); ret = madvise(pstart, map_size, MADV_SEQUENTIAL); if (ret < 0) panic("Failed to give kernel mmap advise!\n"); pcurr = pstart + sizeof(struct pcap_filehdr); spinlock_unlock(&lock); return 0; } static ssize_t pcap_mmap_read_pcap_pkt(int fd, struct pcap_pkthdr *hdr, uint8_t *packet, size_t len) { ssize_t ret; spinlock_lock(&lock); if (unlikely((off_t) (pcurr + sizeof(*hdr) - pstart) > map_size)) { spinlock_unlock(&lock); return -ENOMEM; } fmemcpy(hdr, pcurr, sizeof(*hdr)); pcurr += sizeof(*hdr); if (unlikely((off_t) (pcurr + hdr->caplen - pstart) > map_size)) { ret = -ENOMEM; goto out_err; } if (unlikely(hdr->caplen == 0 || hdr->caplen > len)) { ret = -EINVAL; /* Bogus packet */ goto out_err; } fmemcpy(packet, pcurr, hdr->caplen); pcurr += hdr->caplen; spinlock_unlock(&lock); return sizeof(*hdr) + hdr->caplen; out_err: spinlock_unlock(&lock); return ret; } static void pcap_mmap_fsync_pcap(int fd) { spinlock_lock(&lock); msync(pstart, (off_t) (pcurr - pstart), MS_ASYNC); spinlock_unlock(&lock); } static void pcap_mmap_prepare_close_pcap(int fd, enum pcap_mode mode) { spinlock_lock(&lock); int ret = munmap(pstart, map_size); if (ret < 0) panic("Cannot unmap the pcap file!\n"); if (mode == PCAP_MODE_WRITE) { ret = ftruncate(fd, (off_t) (pcurr - pstart)); if (ret) panic("Cannot truncate the pcap file!\n"); } spinlock_unlock(&lock); } struct pcap_file_ops pcap_mmap_ops __read_mostly = { .name = "mmap", .pull_file_header = pcap_mmap_pull_file_header, .push_file_header = pcap_mmap_push_file_header, .prepare_writing_pcap = pcap_mmap_prepare_writing_pcap, .write_pcap_pkt = pcap_mmap_write_pcap_pkt, .prepare_reading_pcap = pcap_mmap_prepare_reading_pcap, .read_pcap_pkt = pcap_mmap_read_pcap_pkt, .fsync_pcap = pcap_mmap_fsync_pcap, .prepare_close_pcap = pcap_mmap_prepare_close_pcap, }; int init_pcap_mmap(int jumbo_support) { spinlock_init(&lock); jumbo_frames = jumbo_support; return pcap_ops_group_register(&pcap_mmap_ops, PCAP_OPS_MMAP); } void cleanup_pcap_mmap(void) { spinlock_destroy(&lock); pcap_ops_group_unregister(PCAP_OPS_MMAP); } netsniff-ng-0.5.7/src/pcap.h0000664000175000017500000001110011773367375015772 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Copyright 2010 Emmanuel Roullit. * Subject to the GPL, version 2. */ #ifndef PCAP_H #define PCAP_H #include #include #include #include #include #include "built_in.h" #include "die.h" #define TCPDUMP_MAGIC 0xa1b2c3d4 #define PCAP_VERSION_MAJOR 2 #define PCAP_VERSION_MINOR 4 #define PCAP_DEFAULT_SNAPSHOT_LEN 65535 #define LINKTYPE_NULL 0 /* BSD loopback encapsulation */ #define LINKTYPE_EN10MB 1 /* Ethernet (10Mb) */ #define LINKTYPE_EN3MB 2 /* Experimental Ethernet (3Mb) */ #define LINKTYPE_AX25 3 /* Amateur Radio AX.25 */ #define LINKTYPE_PRONET 4 /* Proteon ProNET Token Ring */ #define LINKTYPE_CHAOS 5 /* Chaos */ #define LINKTYPE_IEEE802 6 /* 802.5 Token Ring */ #define LINKTYPE_ARCNET 7 /* ARCNET, with BSD-style header */ #define LINKTYPE_SLIP 8 /* Serial Line IP */ #define LINKTYPE_PPP 9 /* Point-to-point Protocol */ #define LINKTYPE_FDDI 10 /* FDDI */ #define LINKTYPE_IEEE802_11 105 /* IEEE 802.11 wireless */ struct pcap_filehdr { uint32_t magic; uint16_t version_major; uint16_t version_minor; int32_t thiszone; uint32_t sigfigs; uint32_t snaplen; uint32_t linktype; }; struct pcap_timeval { int32_t tv_sec; int32_t tv_usec; }; struct pcap_nsf_pkthdr { struct timeval ts; uint32_t caplen; uint32_t len; }; struct pcap_pkthdr { struct pcap_timeval ts; uint32_t caplen; uint32_t len; }; static inline void tpacket_hdr_to_pcap_pkthdr(struct tpacket_hdr *thdr, struct pcap_pkthdr *phdr) { phdr->ts.tv_sec = thdr->tp_sec; phdr->ts.tv_usec = thdr->tp_usec; phdr->caplen = thdr->tp_snaplen; /* FIXME */ /* phdr->len = thdr->tp_len; */ phdr->len = thdr->tp_snaplen; } static inline void pcap_pkthdr_to_tpacket_hdr(struct pcap_pkthdr *phdr, struct tpacket_hdr *thdr) { thdr->tp_sec = phdr->ts.tv_sec; thdr->tp_usec = phdr->ts.tv_usec; thdr->tp_snaplen = phdr->caplen; thdr->tp_len = phdr->len; } enum pcap_ops_groups { PCAP_OPS_RW = 0, #define PCAP_OPS_RW PCAP_OPS_RW PCAP_OPS_SG, #define PCAP_OPS_SG PCAP_OPS_SG PCAP_OPS_MMAP, #define PCAP_OPS_MMAP PCAP_OPS_MMAP __PCAP_OPS_MAX, }; #define PCAP_OPS_MAX (__PCAP_OPS_MAX - 1) #define PCAP_OPS_SIZ (__PCAP_OPS_MAX) enum pcap_mode { PCAP_MODE_READ = 0, PCAP_MODE_WRITE, }; struct pcap_file_ops { const char *name; int (*pull_file_header)(int fd, uint32_t *linktype); int (*push_file_header)(int fd, uint32_t linktype); int (*prepare_writing_pcap)(int fd); ssize_t (*write_pcap_pkt)(int fd, struct pcap_pkthdr *hdr, uint8_t *packet, size_t len); void (*fsync_pcap)(int fd); int (*prepare_reading_pcap)(int fd); ssize_t (*read_pcap_pkt)(int fd, struct pcap_pkthdr *hdr, uint8_t *packet, size_t len); void (*prepare_close_pcap)(int fd, enum pcap_mode mode); }; extern struct pcap_file_ops *pcap_ops[PCAP_OPS_SIZ]; extern int pcap_ops_group_register(struct pcap_file_ops *ops, enum pcap_ops_groups group); extern void pcap_ops_group_unregister(enum pcap_ops_groups group); static inline struct pcap_file_ops * pcap_ops_group_get(enum pcap_ops_groups group) { return pcap_ops[group]; } static inline void pcap_prepare_header(struct pcap_filehdr *hdr, uint32_t linktype, int32_t thiszone, uint32_t snaplen) { hdr->magic = TCPDUMP_MAGIC; hdr->version_major = PCAP_VERSION_MAJOR; hdr->version_minor = PCAP_VERSION_MINOR; hdr->thiszone = thiszone; hdr->sigfigs = 0; hdr->snaplen = snaplen; hdr->linktype = linktype; } static inline void pcap_validate_header(struct pcap_filehdr *hdr) { if (unlikely(hdr->magic != TCPDUMP_MAGIC || hdr->version_major != PCAP_VERSION_MAJOR || hdr->version_minor != PCAP_VERSION_MINOR || (hdr->linktype != LINKTYPE_EN10MB && hdr->linktype != LINKTYPE_IEEE802_11))) panic("This file has not a valid pcap header\n"); } extern int init_pcap_mmap(int jumbo_support); extern int init_pcap_rw(int jumbo_support); extern int init_pcap_sg(int jumbo_support); extern void cleanup_pcap_mmap(void); extern void cleanup_pcap_rw(void); extern void cleanup_pcap_sg(void); static inline int init_pcap(int jumbo_support) { init_pcap_rw(jumbo_support); init_pcap_sg(jumbo_support); init_pcap_mmap(jumbo_support); return 0; } static inline void cleanup_pcap(void) { cleanup_pcap_rw(); cleanup_pcap_sg(); cleanup_pcap_mmap(); } #endif /* PCAP_H */ netsniff-ng-0.5.7/src/pcap.c0000664000175000017500000000104011773367375015767 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2011 Daniel Borkmann. * Subject to the GPL, version 2. */ #include #include "pcap.h" struct pcap_file_ops *pcap_ops[PCAP_OPS_SIZ] = {0}; int pcap_ops_group_register(struct pcap_file_ops *ops, enum pcap_ops_groups group) { if (!ops) return -EINVAL; if (pcap_ops[group]) return -EBUSY; pcap_ops[group] = ops; return 0; } void pcap_ops_group_unregister(enum pcap_ops_groups group) { pcap_ops[group] = NULL; } netsniff-ng-0.5.7/src/patricia.h0000664000175000017500000000321211773367375016650 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2011 Daniel Borkmann, rewritten * Copyright 1991-2007 Kawahara Lab., Kyoto University * Copyright 2000-2005 Shikano Lab., Nara Institute of Science and Technology * Copyright 2005-2007 Julius project team, Nagoya Institute of Technology * All rights reserved * Subject to the GPL, version 2. */ #ifndef PATRICIA_H #define PATRICIA_H #include #include "built_in.h" struct patricia_node { void *key; size_t klen; struct sockaddr_storage *addr; size_t alen; union { int data; int thres_bit; } value; struct patricia_node *l, *r; } __cacheline_aligned; extern int ptree_search_data_nearest(void *str, size_t sstr, struct sockaddr_storage *addr, size_t *alen, struct patricia_node *root); extern int ptree_search_data_exact(void *str, size_t sstr, struct sockaddr_storage *addr, size_t *alen, struct patricia_node *root); extern int ptree_add_entry(void *str, size_t sstr, int data, struct sockaddr_storage *addr, size_t alen, struct patricia_node **root); extern void ptree_del_entry(void *str, size_t sstr, struct patricia_node **root); extern void ptree_get_key(int data, struct patricia_node *node, struct patricia_node **wanted); extern void ptree_get_key_addr(struct sockaddr_storage *addr, size_t alen, struct patricia_node *node, struct patricia_node **wanted); extern void ptree_display(struct patricia_node *node, int level); extern void ptree_free(struct patricia_node *root); #define ptree_maybe_add_entry ptree_add_entry #endif /* PATRICIA_H */ netsniff-ng-0.5.7/src/patricia.c0000664000175000017500000002066111773367375016652 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2011 Daniel Borkmann, rewritten * Copyright 1991-2007 Kawahara Lab., Kyoto University * Copyright 2000-2005 Shikano Lab., Nara Institute of Science and Technology * Copyright 2005-2007 Julius project team, Nagoya Institute of Technology * All rights reserved * Subject to the GPL, version 2. */ #include #include #include #include "patricia.h" #include "built_in.h" #include "xmalloc.h" static unsigned char mbit[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; static inline int testbit(char *str, size_t slen, int bitplace) { int maskptr; if ((maskptr = bitplace >> 3) > slen) return 0; return (str[maskptr] & mbit[bitplace & 7]); } static inline int testbit_max(char *str, int bitplace, int maxbitplace) { if (bitplace >= maxbitplace) return 0; return (str[bitplace >> 3] & mbit[bitplace & 7]); } static int where_the_bit_differ(char *str1, size_t l1, char *str2, size_t l2) { int p = 0, bitloc; while (str1[p] == str2[p]) p++; bitloc = p * 8; while (testbit(str1, l1, bitloc) == testbit(str2, l2, bitloc)) bitloc++; return bitloc; } static struct patricia_node *new_node(void) { struct patricia_node *n = xzmalloc(sizeof(*n)); n->l = n->r = NULL; return n; } static void free_node(struct patricia_node *n) { if (n->key) xfree(n->key); if (n->addr) xfree(n->addr); xfree(n); } void ptree_display(struct patricia_node *node, int level) { int i; for (i = 0; i < level; ++i) printf("-"); if (node->l == NULL && node->r == NULL) printf("leaf: (%s -> %d)\n", (char *) node->key, node->value.data); else { printf("thres: %d\n", node->value.thres_bit); if (node->l != NULL) ptree_display(node->l, level + 1); if (node->r != NULL) ptree_display(node->r, level + 1); } } void ptree_get_key(int data, struct patricia_node *node, struct patricia_node **wanted) { if (!node) return; if (node->l == NULL && node->r == NULL) { if (node->value.data == data) (*wanted) = node; } else { if (node->l != NULL) ptree_get_key(data, node->l, wanted); if (node->r != NULL) ptree_get_key(data, node->r, wanted); } } void ptree_get_key_addr(struct sockaddr_storage *addr, size_t alen, struct patricia_node *node, struct patricia_node **wanted) { if (!node) return; if (node->l == NULL && node->r == NULL) { if (!memcmp(node->addr, addr, node->alen)) (*wanted) = node; } else { if (node->l != NULL) ptree_get_key_addr(addr, alen, node->l, wanted); if (node->r != NULL) ptree_get_key_addr(addr, alen, node->r, wanted); } } static int ptree_search_data_r(struct patricia_node *node, char *str, size_t slen, struct sockaddr_storage *addr, size_t *alen, int maxbitplace) { if (node->l == NULL && node->r == NULL) { if (node->addr && addr) memcpy(addr, node->addr, node->alen); (*alen) = node->alen; return node->value.data; } if (testbit_max(str, node->value.thres_bit, maxbitplace) != 0) return ptree_search_data_r(node->r, str, slen, addr, alen, maxbitplace); else return ptree_search_data_r(node->l, str, slen, addr, alen, maxbitplace); } static int *ptree_search_data_r_p(struct patricia_node *node, char *str, size_t slen, int maxbitplace) { if (node->l == NULL && node->r == NULL) return &(node->value.data); if (testbit_max(str, node->value.thres_bit, maxbitplace) != 0) return ptree_search_data_r_p(node->r, str, slen, maxbitplace); else return ptree_search_data_r_p(node->l, str, slen, maxbitplace); } static int ptree_search_data_r_x(struct patricia_node *node, char *str, size_t slen, struct sockaddr_storage *addr, size_t *alen, int maxbitplace) { if (node->l == NULL && node->r == NULL) { if (node->klen == slen && !memcmp(str, node->key, node->klen)) { if (node->addr && addr) memcpy(addr, node->addr, node->alen); (*alen) = node->alen; return node->value.data; } else return -ENOENT; } if (testbit_max(str, node->value.thres_bit, maxbitplace) != 0) return ptree_search_data_r_x(node->r, str, slen, addr, alen, maxbitplace); else return ptree_search_data_r_x(node->l, str, slen, addr, alen, maxbitplace); } int ptree_search_data_nearest(void *str, size_t sstr, struct sockaddr_storage *addr, size_t *alen, struct patricia_node *root) { if (!root) return -ENOENT; return ptree_search_data_r(root, str, sstr, addr, alen, sstr * 8); } static int *ptree_search_data_nearest_ptr(char *str, size_t sstr, struct patricia_node *root) { return ptree_search_data_r_p(root, str, sstr, sstr * 8); } int ptree_search_data_exact(void *str, size_t sstr, struct sockaddr_storage *addr, size_t *alen, struct patricia_node *root) { if (!root) return -ENOENT; return ptree_search_data_r_x(root, str, sstr, addr, alen, sstr * 8); } static struct patricia_node *ptree_make_root_node(char *str, size_t sstr, int data, struct sockaddr_storage *addr, size_t alen) { struct patricia_node *n = new_node(); n->value.data = data; n->key = xmemdupz(str, sstr); n->klen = sstr; if (addr) n->addr = xmemdupz(addr, alen); else n->addr = NULL; n->alen = alen; return n; } static void ptree_add_entry_at(char *str, size_t slen, int bitloc, int data, struct sockaddr_storage *addr, size_t alen, struct patricia_node **parentlink) { struct patricia_node *node = (*parentlink); if (node->value.thres_bit > bitloc || (node->l == NULL && node->r == NULL)) { struct patricia_node *newleaf, *newbranch; newleaf = new_node(); newleaf->value.data = data; newleaf->key = xmemdupz(str, slen); newleaf->klen = slen; if (addr) newleaf->addr = xmemdupz(addr, alen); else newleaf->addr = NULL; newleaf->alen = alen; newbranch = new_node(); newbranch->value.thres_bit = bitloc; (*parentlink) = newbranch; if (testbit(str, slen, bitloc) ==0) { newbranch->l = newleaf; newbranch->r = node; } else { newbranch->l = node; newbranch->r = newleaf; } return; } else { if (testbit(str, slen, node->value.thres_bit) != 0) ptree_add_entry_at(str, slen, bitloc, data, addr, alen, &(node->r)); else ptree_add_entry_at(str, slen, bitloc, data, addr, alen, &(node->l)); } } int ptree_add_entry(void *str, size_t sstr, int data, struct sockaddr_storage *addr, size_t alen, struct patricia_node **root) { int *ptr, bitloc, malicious = 0; struct patricia_node *n; if (!(*root)) (*root) = ptree_make_root_node(str, sstr, data, addr, alen); else { ptr = ptree_search_data_nearest_ptr(str, sstr, (*root)); n = container_of(ptr, struct patricia_node, value.data); if (n->klen == sstr && !memcmp(str, n->key, n->klen)) { /* Make sure if entry exists, that we also have the * same data, otherwise, we drop the packet */ if (n->value.data != data) malicious = 1; else if (n->alen != alen) malicious = 1; else if ((n->addr && !addr) || (!n->addr && addr)) malicious = 1; else if (n->alen == alen && n->addr && addr) { if (memcmp(n->addr, addr, alen)) malicious = 1; } return malicious; } bitloc = where_the_bit_differ(str, sstr, n->key, n->klen); ptree_add_entry_at(str, sstr, bitloc, data, addr, alen, root); } return malicious; } static void ptree_remove_entry_r(struct patricia_node *now, struct patricia_node *up, struct patricia_node *up2, char *str, size_t slen, int maxbitplace, struct patricia_node **root) { struct patricia_node *b; if (now->l == NULL && now->r == NULL) { if (now->klen != slen) return; if (memcmp(now->key, str, slen)) return; if (up == NULL) { *root = NULL; free_node(now); return; } b = (up->r == now) ? up->l : up->r; if (up2 == NULL) { *root = b; free_node(now); free_node(up); return; } if (up2->l == up) up2->l = b; else up2->r = b; free_node(now); free_node(up); return; } else { if (testbit_max(str, now->value.thres_bit, maxbitplace) != 0) ptree_remove_entry_r(now->r, now, up, str, slen, maxbitplace, root); else ptree_remove_entry_r(now->l, now, up, str, slen, maxbitplace, root); } } void ptree_del_entry(void *str, size_t sstr, struct patricia_node **root) { if (!(*root)) return; ptree_remove_entry_r(*root, NULL, NULL, str, sstr, sstr * 8, root); } void ptree_free(struct patricia_node *node) { if (!node) return; if (node->l) ptree_free(node->l); if (node->r) ptree_free(node->r); free_node(node); } netsniff-ng-0.5.7/src/oui.h0000664000175000017500000000052411773367375015653 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2012 Daniel Borkmann. * Subject to the GPL, version 2. */ #ifndef OUI_H #define OUI_H extern char *lookup_vendor(unsigned int id); extern void dissector_init_oui(void); extern void dissector_cleanup_oui(void); #endif /* OUI_H */ netsniff-ng-0.5.7/src/oui.c0000664000175000017500000000404311773367375015646 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #include #include "hash.h" #include "xmalloc.h" #include "xutils.h" #include "oui.h" static struct hash_table oui; static int initialized = 0; struct vendor_id { unsigned int id; char *vendor; struct vendor_id *next; }; /* Note: this macro only applies to the lookup_* functions here in this file, * mainly to remove redundand code. */ #define __do_lookup_inline(id, struct_name, hash_ptr, struct_member) \ ({ \ struct struct_name *entry = lookup_hash(id, hash_ptr); \ while (entry && id != entry->id) \ entry = entry->next; \ (entry && id == entry->id ? entry->struct_member : "Unknown");\ }) char *lookup_vendor(unsigned int id) { return __do_lookup_inline(id, vendor_id, &oui, vendor); } void dissector_init_oui(void) { FILE *fp; char buff[512], *ptr; struct vendor_id *ven; void **pos; if (initialized) return; fp = fopen("/etc/netsniff-ng/oui.conf", "r"); if (!fp) panic("No /etc/netsniff-ng/oui.conf found!\n"); memset(buff, 0, sizeof(buff)); while (fgets(buff, sizeof(buff), fp) != NULL) { buff[sizeof(buff) - 1] = 0; ven = xmalloc(sizeof(*ven)); ptr = buff; ptr = skips(ptr); ptr = getuint(ptr, &ven->id); ptr = skips(ptr); ptr = skipchar(ptr, ','); ptr = skips(ptr); ptr = strtrim_right(ptr, '\n'); ptr = strtrim_right(ptr, ' '); ven->vendor = xstrdup(ptr); ven->next = NULL; pos = insert_hash(ven->id, ven, &oui); if (pos) { ven->next = *pos; *pos = ven; } memset(buff, 0, sizeof(buff)); } fclose(fp); initialized = 1; } static int __dissector_cleanup_oui(void *ptr) { struct vendor_id *tmp, *v = ptr; if (!ptr) return 0; while ((tmp = v->next)) { xfree(v->vendor); xfree(v); v = tmp; } xfree(v->vendor); xfree(v); return 0; } void dissector_cleanup_oui(void) { for_each_hash(&oui, __dissector_cleanup_oui); free_hash(&oui); initialized = 0; } netsniff-ng-0.5.7/src/netsniff-ng.c0000664000175000017500000010750311773367375017275 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009-2011 Daniel Borkmann. * Copyright 2010 Emmanuel Roullit. * Subject to the GPL, version 2. * * The first sniffer that invoked both, the zero-copy RX_RING as well as * the zero-copy TX_RING for high-performance network I/O and scatter/gather * or mmaped PCAP I/O. * * "I knew that danger lay ahead, of course; but I did not expect to * meet it in our own Shire. Can't a hobbit walk from the Water to the * River in peace?" "But it is not your own Shire," said Gildor. "Others * dwelt here before hobbits were; and others will dwell here again when * hobbits are no more. The wide world is all about you: you can fence * yourselves in, but you cannot for ever fence it out." * * -- The Lord of the Rings, Gildor to Frodo, * Chapter 'Three is Company'. */ /* =head1 NAME netsniff-ng - the packet sniffing beast =head1 SYNOPSIS netsniff-ng -i|-d|--dev|--in -o|--out [-f|--filter ][-t|--type ][-F|--interval ] [-s|--silent][-J|--jumbo-support][-n|--num ][-r|--rand] [-M|--no-promisc][-m|--mmap | -c|--clrw][-S|--ring-size ] [-k|--kernel-pull ][-b|--bind-cpu | -B|--unbind-cpu ] [-H|--prio-high][-Q|--notouch-irq][-q|--less | -X|--hex | -l|--ascii] [-v|--version][-h|--help] =head1 DESCRIPTION The first sniffer that invoked both, the zero-copy RX_RING as well as the zero-copy TX_RING for high-performance network I/O and scatter/gather or mmaped PCAP I/O. =head1 EXAMPLES =over =item netsniff-ng --in eth0 --out dump.pcap Capture traffic from interface 'eth0' and save it pcap file 'dump.pcap' =item netsniff-ng --in any --filter http.bpf --payload Capture HTTP traffic from any interface and print its payload on stdout =item netsniff-ng --in wlan0 --bind-cpu 0,1 Capture all traffic from wlan0 interface. Schedule process on CPU 0 and 1. =back =head1 OPTIONS =over =item -i|-d|--dev|--in Input source. Can be a network device or pcap file. =item -o|--out Output sink. Can be a network device, pcap file, a trafgen txf file or a directory. (There's only pcap to txf translation possible.) =item -f|--filter Use BPF filter file from bpfc. =item -t|--type =over =item Only handle packets of defined type: =over =item - broadcast =item - multicast =item - others =item - outgoing =back =back =item -F|--interval Dump interval in seconds. if -o is a directory, a new pcap will be created at each interval. The older files are left untouched. (default value: 60 seconds) =item -s|--silent Do not print captured packets to stdout. =item -J|--jumbo-support Support for 64KB Super Jumbo Frames. =item -n|--num When zerp, capture/replay until SIGINT is received (default). When non-zero, capture/replay the number of packets. =item -r|--rand Randomize packet forwarding order (replay mode only). =item -M|--no-promisc Do not place the interface in promiscuous mode. =item -m|--mmap Mmap pcap file i.e., for replaying. Default: scatter/gather I/O. =item -c|--clrw Instead of using scatter/gather I/O use slower read(2)/write(2) I/O. =item -S|--ring-size Manually set ring size in KB/MB/GB, e.g. '10MB'. =item -k|--kernel-pull Kernel pull from user interval in microseconds. Default is 10us. (replay mode only). =item -b|--bind-cpu Bind to specific CPU (or CPU-range). =item -B|--unbind-cpu Forbid to use specific CPU (or CPU-range). =item -H|--prio-high Run the process in high-priority mode. =item -Q|--notouch-irq Do not touch IRQ CPU affinity of NIC. =item -q|--less Print less-verbose packet information. =item -X|--hex Print packet data in hex format. =item -l|--ascii Print human-readable packet data. =item -v|--version Print version. =item -h|--help Print help text and lists all options. =back =head1 AUTHOR Written by Daniel Borkmann and Emmanuel Roullit =head1 DOCUMENTATION Documentation by Emmanuel Roullit =head1 BUGS Please report bugs to =cut */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ring_rx.h" #include "ring_tx.h" #include "mac80211.h" #include "xutils.h" #include "built_in.h" #include "pcap.h" #include "bpf.h" #include "xio.h" #include "die.h" #include "tprintf.h" #include "dissector.h" #include "xmalloc.h" #include "mtrand.h" #define CPU_UNKNOWN -1 #define CPU_NOTOUCH -2 #define PACKET_ALL -1 #define DUMP_INTERVAL 60 struct mode { char *device_in; char *device_out; char *device_trans; char *filter; int cpu; int rfraw; int dump; uint32_t link_type; int print_mode; unsigned int reserve_size; int packet_type; bool randomize; bool promiscuous; enum pcap_ops_groups pcap; unsigned long kpull; int jumbo_support; int dump_dir; unsigned long dump_interval; }; struct tx_stats { unsigned long tx_bytes; unsigned long tx_packets; }; volatile sig_atomic_t sigint = 0; static int tx_sock; static unsigned long frame_cnt_max = 0; static unsigned long interval = TX_KERNEL_PULL_INT; static struct itimerval itimer; static volatile bool next_dump = false; static const char *short_options = "d:i:o:rf:MJt:S:k:n:b:B:HQmcsqXlvhF:Rg"; static struct option long_options[] = { {"dev", required_argument, 0, 'd'}, {"in", required_argument, 0, 'i'}, {"out", required_argument, 0, 'o'}, {"rand", no_argument, 0, 'r'}, {"rfraw", no_argument, 0, 'R'}, {"mmap", no_argument, 0, 'm'}, {"sg", no_argument, 0, 'g'}, {"clrw", no_argument, 0, 'c'}, {"jumbo-support", no_argument, 0, 'J'}, {"filter", required_argument, 0, 'f'}, {"no-promisc", no_argument, 0, 'M'}, {"num", required_argument, 0, 'n'}, {"type", required_argument, 0, 't'}, {"interval", required_argument, 0, 'F'}, {"ring-size", required_argument, 0, 'S'}, {"kernel-pull", required_argument, 0, 'k'}, {"bind-cpu", required_argument, 0, 'b'}, {"unbind-cpu", required_argument, 0, 'B'}, {"prio-high", no_argument, 0, 'H'}, {"notouch-irq", no_argument, 0, 'Q'}, {"silent", no_argument, 0, 's'}, {"less", no_argument, 0, 'q'}, {"hex", no_argument, 0, 'X'}, {"ascii", no_argument, 0, 'l'}, {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; static void signal_handler(int number) { switch (number) { case SIGINT: sigint = 1; break; case SIGHUP: break; default: break; } } static void timer_elapsed(int number) { itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = interval; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = interval; pull_and_flush_tx_ring(tx_sock); setitimer(ITIMER_REAL, &itimer, NULL); } static void timer_next_dump(int number) { itimer.it_interval.tv_sec = interval; itimer.it_interval.tv_usec = 0; itimer.it_value.tv_sec = interval; itimer.it_value.tv_usec = 0; next_dump = true; setitimer(ITIMER_REAL, &itimer, NULL); } static void enter_mode_pcap_to_tx(struct mode *mode) { int irq, ifindex, fd = 0, ret; unsigned int size, it = 0; struct ring tx_ring; struct frame_map *hdr; struct sock_fprog bpf_ops; struct tx_stats stats; uint8_t *out = NULL; unsigned long trunced = 0; struct timeval start, end, diff; if (!device_up_and_running(mode->device_out)) panic("Device not up and running!\n"); tx_sock = pf_socket(); if (!pcap_ops[mode->pcap]) panic("pcap group not supported!\n"); fd = open_or_die(mode->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME); ret = pcap_ops[mode->pcap]->pull_file_header(fd, &mode->link_type); if (ret) panic("error reading pcap header!\n"); if (pcap_ops[mode->pcap]->prepare_reading_pcap) { ret = pcap_ops[mode->pcap]->prepare_reading_pcap(fd); if (ret) panic("error prepare reading pcap!\n"); } fmemset(&tx_ring, 0, sizeof(tx_ring)); fmemset(&bpf_ops, 0, sizeof(bpf_ops)); fmemset(&stats, 0, sizeof(stats)); if (mode->rfraw) { mode->device_trans = xstrdup(mode->device_out); xfree(mode->device_out); enter_rfmon_mac80211(mode->device_trans, &mode->device_out); if (mode->link_type != LINKTYPE_IEEE802_11) panic("Wrong linktype of pcap!\n"); } ifindex = device_ifindex(mode->device_out); size = ring_size(mode->device_out, mode->reserve_size); bpf_parse_rules(mode->filter, &bpf_ops); set_packet_loss_discard(tx_sock); set_sockopt_hwtimestamp(tx_sock, mode->device_out); setup_tx_ring_layout(tx_sock, &tx_ring, size, mode->jumbo_support); create_tx_ring(tx_sock, &tx_ring); mmap_tx_ring(tx_sock, &tx_ring); alloc_tx_ring_frames(&tx_ring); bind_tx_ring(tx_sock, &tx_ring, ifindex); dissector_init_all(mode->print_mode); if (mode->cpu >= 0 && ifindex > 0) { irq = device_irq_number(mode->device_out); device_bind_irq_to_cpu(mode->cpu, irq); printf("IRQ: %s:%d > CPU%d\n", mode->device_out, irq, mode->cpu); } if (mode->kpull) interval = mode->kpull; itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = interval; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = interval; setitimer(ITIMER_REAL, &itimer, NULL); printf("BPF:\n"); bpf_dump_all(&bpf_ops); printf("MD: TX %luus %s ", interval, pcap_ops[mode->pcap]->name); if (mode->rfraw) printf("802.11 raw via %s ", mode->device_out); #ifdef _LARGEFILE64_SOURCE printf("lf64 "); #endif ioprio_print(); printf("\n"); gettimeofday(&start, NULL); while (likely(sigint == 0)) { while (user_may_pull_from_tx(tx_ring.frames[it].iov_base)) { struct pcap_pkthdr phdr; hdr = tx_ring.frames[it].iov_base; /* Kernel assumes: data = ph.raw + po->tp_hdrlen - * sizeof(struct sockaddr_ll); */ out = ((uint8_t *) hdr) + TPACKET_HDRLEN - sizeof(struct sockaddr_ll); do { memset(&phdr, 0, sizeof(phdr)); ret = pcap_ops[mode->pcap]->read_pcap_pkt(fd, &phdr, out, ring_frame_size(&tx_ring)); if (unlikely(ret <= 0)) goto out; if (ring_frame_size(&tx_ring) < phdr.len) { phdr.len = ring_frame_size(&tx_ring); trunced++; } } while (mode->filter && !bpf_run_filter(&bpf_ops, out, phdr.len)); pcap_pkthdr_to_tpacket_hdr(&phdr, &hdr->tp_h); stats.tx_bytes += hdr->tp_h.tp_len;; stats.tx_packets++; show_frame_hdr(hdr, mode->print_mode, RING_MODE_EGRESS); dissector_entry_point(out, hdr->tp_h.tp_snaplen, mode->link_type, mode->print_mode); kernel_may_pull_from_tx(&hdr->tp_h); next_slot_prewr(&it, &tx_ring); if (unlikely(sigint == 1)) break; if (frame_cnt_max != 0 && stats.tx_packets >= frame_cnt_max) { sigint = 1; break; } } } out: gettimeofday(&end, NULL); diff = tv_subtract(end, start); fflush(stdout); printf("\n"); printf("\r%12lu frames outgoing\n", stats.tx_packets); printf("\r%12lu frames truncated (larger than frame)\n", trunced); printf("\r%12lu bytes outgoing\n", stats.tx_bytes); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); bpf_release(&bpf_ops); dissector_cleanup_all(); destroy_tx_ring(tx_sock, &tx_ring); if (mode->rfraw) leave_rfmon_mac80211(mode->device_trans, mode->device_out); close(tx_sock); if (pcap_ops[mode->pcap]->prepare_close_pcap) pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_READ); close(fd); } static void enter_mode_rx_to_tx(struct mode *mode) { int rx_sock, ifindex_in, ifindex_out; unsigned int size_in, size_out, it_in = 0, it_out = 0; unsigned long fcnt = 0; uint8_t *in, *out; short ifflags = 0; struct frame_map *hdr_in, *hdr_out; struct ring tx_ring; struct ring rx_ring; struct pollfd rx_poll; struct sock_fprog bpf_ops; if (!strncmp(mode->device_in, mode->device_out, strlen(mode->device_in))) panic("Ingress/egress devices must be different!\n"); if (!device_up_and_running(mode->device_out)) panic("Egress device not up and running!\n"); if (!device_up_and_running(mode->device_in)) panic("Ingress device not up and running!\n"); rx_sock = pf_socket(); tx_sock = pf_socket(); fmemset(&tx_ring, 0, sizeof(tx_ring)); fmemset(&rx_ring, 0, sizeof(rx_ring)); fmemset(&rx_poll, 0, sizeof(rx_poll)); fmemset(&bpf_ops, 0, sizeof(bpf_ops)); ifindex_in = device_ifindex(mode->device_in); size_in = ring_size(mode->device_in, mode->reserve_size); ifindex_out = device_ifindex(mode->device_out); size_out = ring_size(mode->device_out, mode->reserve_size); enable_kernel_bpf_jit_compiler(); bpf_parse_rules(mode->filter, &bpf_ops); bpf_attach_to_sock(rx_sock, &bpf_ops); setup_rx_ring_layout(rx_sock, &rx_ring, size_in, mode->jumbo_support); create_rx_ring(rx_sock, &rx_ring); mmap_rx_ring(rx_sock, &rx_ring); alloc_rx_ring_frames(&rx_ring); bind_rx_ring(rx_sock, &rx_ring, ifindex_in); prepare_polling(rx_sock, &rx_poll); set_packet_loss_discard(tx_sock); setup_tx_ring_layout(tx_sock, &tx_ring, size_out, mode->jumbo_support); create_tx_ring(tx_sock, &tx_ring); mmap_tx_ring(tx_sock, &tx_ring); alloc_tx_ring_frames(&tx_ring); bind_tx_ring(tx_sock, &tx_ring, ifindex_out); mt_init_by_seed_time(); dissector_init_all(mode->print_mode); if (mode->promiscuous == true) { ifflags = enter_promiscuous_mode(mode->device_in); printf("PROMISC\n"); } if (mode->kpull) interval = mode->kpull; itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = interval; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = interval; setitimer(ITIMER_REAL, &itimer, NULL); printf("BPF:\n"); bpf_dump_all(&bpf_ops); printf("MD: RXTX %luus\n\n", interval); printf("Running! Hang up with ^C!\n\n"); while (likely(sigint == 0)) { while (user_may_pull_from_rx(rx_ring.frames[it_in].iov_base)) { hdr_in = rx_ring.frames[it_in].iov_base; in = ((uint8_t *) hdr_in) + hdr_in->tp_h.tp_mac; fcnt++; if (mode->packet_type != PACKET_ALL) if (mode->packet_type != hdr_in->s_ll.sll_pkttype) goto next; hdr_out = tx_ring.frames[it_out].iov_base; out = ((uint8_t *) hdr_out) + TPACKET_HDRLEN - sizeof(struct sockaddr_ll); for (; !user_may_pull_from_tx(tx_ring.frames[it_out].iov_base) && likely(!sigint);) { if (mode->randomize) next_rnd_slot(&it_out, &tx_ring); else next_slot(&it_out, &tx_ring); hdr_out = tx_ring.frames[it_out].iov_base; out = ((uint8_t *) hdr_out) + TPACKET_HDRLEN - sizeof(struct sockaddr_ll); } tpacket_hdr_clone(&hdr_out->tp_h, &hdr_in->tp_h); fmemcpy(out, in, hdr_in->tp_h.tp_len); kernel_may_pull_from_tx(&hdr_out->tp_h); if (mode->randomize) next_rnd_slot(&it_out, &tx_ring); else next_slot(&it_out, &tx_ring); show_frame_hdr(hdr_in, mode->print_mode, RING_MODE_INGRESS); dissector_entry_point(in, hdr_in->tp_h.tp_snaplen, mode->link_type, mode->print_mode); if (frame_cnt_max != 0 && fcnt >= frame_cnt_max) { sigint = 1; break; } next: kernel_may_pull_from_rx(&hdr_in->tp_h); next_slot(&it_in, &rx_ring); if (unlikely(sigint == 1)) goto out; } poll(&rx_poll, 1, -1); poll_error_maybe_die(rx_sock, &rx_poll); } out: sock_print_net_stats(rx_sock, 0); bpf_release(&bpf_ops); dissector_cleanup_all(); destroy_tx_ring(tx_sock, &tx_ring); destroy_rx_ring(rx_sock, &rx_ring); if (mode->promiscuous == true) leave_promiscuous_mode(mode->device_in, ifflags); close(tx_sock); close(rx_sock); } static void enter_mode_read_pcap(struct mode *mode) { int ret, fd, fdo = 0; struct pcap_pkthdr phdr; struct sock_fprog bpf_ops; struct tx_stats stats; struct frame_map fm; uint8_t *out; size_t out_len; unsigned long trunced = 0; struct timeval start, end, diff; if (!pcap_ops[mode->pcap]) panic("pcap group not supported!\n"); fd = open_or_die(mode->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME); ret = pcap_ops[mode->pcap]->pull_file_header(fd, &mode->link_type); if (ret) panic("error reading pcap header!\n"); if (pcap_ops[mode->pcap]->prepare_reading_pcap) { ret = pcap_ops[mode->pcap]->prepare_reading_pcap(fd); if (ret) panic("error prepare reading pcap!\n"); } fmemset(&fm, 0, sizeof(fm)); fmemset(&bpf_ops, 0, sizeof(bpf_ops)); fmemset(&stats, 0, sizeof(stats)); bpf_parse_rules(mode->filter, &bpf_ops); dissector_init_all(mode->print_mode); out_len = 64 * 1024; out = xmalloc_aligned(out_len, CO_CACHE_LINE_SIZE); printf("BPF:\n"); bpf_dump_all(&bpf_ops); printf("MD: RD %s ", pcap_ops[mode->pcap]->name); #ifdef _LARGEFILE64_SOURCE printf("lf64 "); #endif ioprio_print(); printf("\n"); if (mode->device_out) { fdo = open_or_die_m(mode->device_out, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE, DEFFILEMODE); } gettimeofday(&start, NULL); while (likely(sigint == 0)) { do { memset(&phdr, 0, sizeof(phdr)); ret = pcap_ops[mode->pcap]->read_pcap_pkt(fd, &phdr, out, out_len); if (unlikely(ret < 0)) goto out; if (unlikely(phdr.len == 0)) { trunced++; continue; } if (unlikely(phdr.len > out_len)) { phdr.len = out_len; trunced++; } } while (mode->filter && !bpf_run_filter(&bpf_ops, out, phdr.len)); pcap_pkthdr_to_tpacket_hdr(&phdr, &fm.tp_h); stats.tx_bytes += fm.tp_h.tp_len; stats.tx_packets++; show_frame_hdr(&fm, mode->print_mode, RING_MODE_EGRESS); dissector_entry_point(out, fm.tp_h.tp_snaplen, mode->link_type, mode->print_mode); if (mode->device_out) { int i = 0; char bout[80]; slprintf(bout, sizeof(bout), "{\n "); write_or_die(fdo, bout, strlen(bout)); while (i < fm.tp_h.tp_snaplen) { slprintf(bout, sizeof(bout), "0x%02x, ", out[i]); write_or_die(fdo, bout, strlen(bout)); i++; if (i % 10 == 0) { slprintf(bout, sizeof(bout), "\n", out[i]); write_or_die(fdo, bout, strlen(bout)); if (i < fm.tp_h.tp_snaplen) { slprintf(bout, sizeof(bout), " ", out[i]); write_or_die(fdo, bout, strlen(bout)); } } } if (i % 10 != 0) { slprintf(bout, sizeof(bout), "\n"); write_or_die(fdo, bout, strlen(bout)); } slprintf(bout, sizeof(bout), "}\n\n"); write_or_die(fdo, bout, strlen(bout)); } if (frame_cnt_max != 0 && stats.tx_packets >= frame_cnt_max) { sigint = 1; break; } } out: gettimeofday(&end, NULL); diff = tv_subtract(end, start); fflush(stdout); printf("\n"); printf("\r%12lu frames outgoing\n", stats.tx_packets); printf("\r%12lu frames truncated (larger than mtu)\n", trunced); printf("\r%12lu bytes outgoing\n", stats.tx_bytes); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); xfree(out); bpf_release(&bpf_ops); dissector_cleanup_all(); if (pcap_ops[mode->pcap]->prepare_close_pcap) pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_READ); close(fd); if (mode->device_out) close(fdo); } static void finish_multi_pcap_file(struct mode *mode, int fd) { pcap_ops[mode->pcap]->fsync_pcap(fd); if (pcap_ops[mode->pcap]->prepare_close_pcap) pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_WRITE); close(fd); fmemset(&itimer, 0, sizeof(itimer)); setitimer(ITIMER_REAL, &itimer, NULL); } static int next_multi_pcap_file(struct mode *mode, int fd) { int ret; char tmp[512]; pcap_ops[mode->pcap]->fsync_pcap(fd); if (pcap_ops[mode->pcap]->prepare_close_pcap) pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_WRITE); close(fd); slprintf(tmp, sizeof(tmp), "%s/%lu.pcap", mode->device_out, time(0)); fd = open_or_die_m(tmp, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE, DEFFILEMODE); ret = pcap_ops[mode->pcap]->push_file_header(fd, mode->link_type); if (ret) panic("error writing pcap header!\n"); if (pcap_ops[mode->pcap]->prepare_writing_pcap) { ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd); if (ret) panic("error prepare writing pcap!\n"); } return fd; } static int begin_multi_pcap_file(struct mode *mode) { int fd, ret; char tmp[512]; if (!pcap_ops[mode->pcap]) panic("pcap group not supported!\n"); if (mode->device_out[strlen(mode->device_out) - 1] == '/') mode->device_out[strlen(mode->device_out) - 1] = 0; slprintf(tmp, sizeof(tmp), "%s/%lu.pcap", mode->device_out, time(0)); fd = open_or_die_m(tmp, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE, DEFFILEMODE); ret = pcap_ops[mode->pcap]->push_file_header(fd, mode->link_type); if (ret) panic("error writing pcap header!\n"); if (pcap_ops[mode->pcap]->prepare_writing_pcap) { ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd); if (ret) panic("error prepare writing pcap!\n"); } interval = mode->dump_interval; itimer.it_interval.tv_sec = interval; itimer.it_interval.tv_usec = 0; itimer.it_value.tv_sec = interval; itimer.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &itimer, NULL); return fd; } static void finish_single_pcap_file(struct mode *mode, int fd) { pcap_ops[mode->pcap]->fsync_pcap(fd); if (pcap_ops[mode->pcap]->prepare_close_pcap) pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_WRITE); close(fd); } static int begin_single_pcap_file(struct mode *mode) { int fd, ret; if (!pcap_ops[mode->pcap]) panic("pcap group not supported!\n"); fd = open_or_die_m(mode->device_out, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE, DEFFILEMODE); ret = pcap_ops[mode->pcap]->push_file_header(fd, mode->link_type); if (ret) panic("error writing pcap header!\n"); if (pcap_ops[mode->pcap]->prepare_writing_pcap) { ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd); if (ret) panic("error prepare writing pcap!\n"); } return fd; } static void enter_mode_rx_only_or_dump(struct mode *mode) { int sock, irq, ifindex, fd = 0, ret; unsigned int size, it = 0; unsigned long fcnt = 0, skipped = 0; short ifflags = 0; uint8_t *packet; struct ring rx_ring; struct pollfd rx_poll; struct frame_map *hdr; struct sock_fprog bpf_ops; struct timeval start, end, diff; if (!device_up_and_running(mode->device_in)) panic("Device not up and running!\n"); sock = pf_socket(); if (mode->rfraw) { mode->device_trans = xstrdup(mode->device_in); xfree(mode->device_in); enter_rfmon_mac80211(mode->device_trans, &mode->device_in); mode->link_type = LINKTYPE_IEEE802_11; } if (mode->dump) { struct stat tmp; fmemset(&tmp, 0, sizeof(tmp)); ret = stat(mode->device_out, &tmp); if (ret < 0) { mode->dump_dir = 0; goto try_file; } mode->dump_dir = !!S_ISDIR(tmp.st_mode); if (mode->dump_dir) { fd = begin_multi_pcap_file(mode); } else { try_file: fd = begin_single_pcap_file(mode); } } fmemset(&rx_ring, 0, sizeof(rx_ring)); fmemset(&rx_poll, 0, sizeof(rx_poll)); fmemset(&bpf_ops, 0, sizeof(bpf_ops)); ifindex = device_ifindex(mode->device_in); size = ring_size(mode->device_in, mode->reserve_size); enable_kernel_bpf_jit_compiler(); bpf_parse_rules(mode->filter, &bpf_ops); bpf_attach_to_sock(sock, &bpf_ops); set_sockopt_hwtimestamp(sock, mode->device_in); setup_rx_ring_layout(sock, &rx_ring, size, mode->jumbo_support); create_rx_ring(sock, &rx_ring); mmap_rx_ring(sock, &rx_ring); alloc_rx_ring_frames(&rx_ring); bind_rx_ring(sock, &rx_ring, ifindex); prepare_polling(sock, &rx_poll); dissector_init_all(mode->print_mode); if (mode->cpu >= 0 && ifindex > 0) { irq = device_irq_number(mode->device_in); device_bind_irq_to_cpu(mode->cpu, irq); printf("IRQ: %s:%d > CPU%d\n", mode->device_in, irq, mode->cpu); } if (mode->promiscuous == true) { ifflags = enter_promiscuous_mode(mode->device_in); printf("PROMISC\n"); } printf("BPF:\n"); bpf_dump_all(&bpf_ops); printf("MD: RX %s ", mode->dump ? pcap_ops[mode->pcap]->name : ""); if (mode->rfraw) printf("802.11 raw via %s ", mode->device_in); #ifdef _LARGEFILE64_SOURCE printf("lf64 "); #endif ioprio_print(); printf("\n"); gettimeofday(&start, NULL); while (likely(sigint == 0)) { while (user_may_pull_from_rx(rx_ring.frames[it].iov_base)) { hdr = rx_ring.frames[it].iov_base; packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac; fcnt++; if (mode->packet_type != PACKET_ALL) if (mode->packet_type != hdr->s_ll.sll_pkttype) goto next; if (unlikely(ring_frame_size(&rx_ring) < hdr->tp_h.tp_snaplen)) { skipped++; goto next; } if (mode->dump) { struct pcap_pkthdr phdr; tpacket_hdr_to_pcap_pkthdr(&hdr->tp_h, &phdr); ret = pcap_ops[mode->pcap]->write_pcap_pkt(fd, &phdr, packet, phdr.len); if (unlikely(ret != sizeof(phdr) + phdr.len)) panic("Write error to pcap!\n"); } show_frame_hdr(hdr, mode->print_mode, RING_MODE_INGRESS); dissector_entry_point(packet, hdr->tp_h.tp_snaplen, mode->link_type, mode->print_mode); if (frame_cnt_max != 0 && fcnt >= frame_cnt_max) { sigint = 1; break; } next: kernel_may_pull_from_rx(&hdr->tp_h); next_slot_prerd(&it, &rx_ring); if (unlikely(sigint == 1)) break; if (mode->dump && next_dump) { struct tpacket_stats kstats; socklen_t slen = sizeof(kstats); fmemset(&kstats, 0, sizeof(kstats)); getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen); fd = next_multi_pcap_file(mode, fd); next_dump = false; if (mode->print_mode == FNTTYPE_PRINT_NONE) { printf(".(+%lu/-%lu)", 1UL * kstats.tp_packets - kstats.tp_drops - skipped, 1UL * kstats.tp_drops + skipped); fflush(stdout); } } } poll(&rx_poll, 1, -1); poll_error_maybe_die(sock, &rx_poll); } gettimeofday(&end, NULL); diff = tv_subtract(end, start); if (!(mode->dump_dir && mode->print_mode == FNTTYPE_PRINT_NONE)) { sock_print_net_stats(sock, skipped); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); } else { printf("\n\n"); fflush(stdout); } bpf_release(&bpf_ops); dissector_cleanup_all(); destroy_rx_ring(sock, &rx_ring); if (mode->promiscuous == true) leave_promiscuous_mode(mode->device_in, ifflags); if (mode->rfraw) leave_rfmon_mac80211(mode->device_trans, mode->device_in); close(sock); if (mode->dump) { if (mode->dump_dir) finish_multi_pcap_file(mode, fd); else finish_single_pcap_file(mode, fd); } } static void help(void) { printf("\n%s %s, the packet sniffing beast\n", PROGNAME_STRING, VERSION_STRING); printf("http://www.netsniff-ng.org\n\n"); printf("Usage: netsniff-ng [options]\n"); printf("Options:\n"); printf(" -i|-d|--dev|--in Input source as netdev or pcap\n"); printf(" -o|--out Output sink as netdev, pcap, directory, txf file\n"); printf(" -f|--filter Use BPF filter file from bpfc\n"); printf(" -t|--type Only handle packets of defined type:\n"); printf(" host|broadcast|multicast|others|outgoing\n"); printf(" -F|--interval Dump interval in sec if -o is a directory where\n"); printf(" pcap files should be stored (default: 60)\n"); printf(" -J|--jumbo-support Support for 64KB Super Jumbo Frames\n"); printf(" Default RX/TX slot: 2048Byte\n"); printf(" -R|--rfraw Capture or inject raw 802.11 frames\n"); printf(" -n|--num Number of packets until exit\n"); printf(" `-- 0 Loop until interrupted (default)\n"); printf(" `- n Send n packets and done\n"); printf("Options for printing:\n"); printf(" -s|--silent Do not print captured packets\n"); printf(" -q|--less Print less-verbose packet information\n"); printf(" -X|--hex Print packet data in hex format\n"); printf(" -l|--ascii Print human-readable packet data\n"); printf("Options, advanced:\n"); printf(" -r|--rand Randomize packet forwarding order\n"); printf(" -M|--no-promisc No promiscuous mode for netdev\n"); printf(" -m|--mmap Mmap pcap file i.e., for replaying\n"); printf(" -g|--sg Scatter/gather pcap file I/O\n"); printf(" -c|--clrw Use slower read(2)/write(2) I/O\n"); printf(" -S|--ring-size Manually set ring size to :\n"); printf(" mmap space in KB/MB/GB, e.g. \'10MB\'\n"); printf(" -k|--kernel-pull Kernel pull from user interval in us\n"); printf(" Default is 10us where the TX_RING\n"); printf(" is populated with payload from uspace\n"); printf(" -b|--bind-cpu Bind to specific CPU (or CPU-range)\n"); printf(" -B|--unbind-cpu Forbid to use specific CPU (or CPU-range)\n"); printf(" -H|--prio-high Make this high priority process\n"); printf(" -Q|--notouch-irq Do not touch IRQ CPU affinity of NIC\n"); printf(" -v|--version Show version\n"); printf(" -h|--help Guess what?!\n"); printf("\n"); printf("Examples:\n"); printf(" netsniff-ng --in eth0 --out dump.pcap --silent --bind-cpu 0\n"); printf(" netsniff-ng --in wlan0 --rfraw --out dump.pcap --silent --bind-cpu 0\n"); printf(" netsniff-ng --in dump.pcap --mmap --out eth0 --silent --bind-cpu 0\n"); printf(" netsniff-ng --in dump.pcap --out dump.txf --silent --bind-cpu 0\n"); printf(" netsniff-ng --in eth0 --out eth1 --silent --bind-cpu 0 --type host\n"); printf(" netsniff-ng --in eth1 --out /opt/probe1/ -s -m -J --interval 30 -b 0\n"); printf(" netsniff-ng --in any --filter http.bpf --jumbo-support --ascii\n"); printf("\n"); printf("Note:\n"); printf(" This tool is targeted for network developers! You should\n"); printf(" be aware of what you are doing and what these options above\n"); printf(" mean! Use netsniff-ng's bpfc compiler for generating filter files.\n"); printf(" Further, netsniff-ng automatically enables the kernel BPF JIT\n"); printf(" if present. Txf file output is only possible if the input source\n"); printf(" is a pcap file.\n"); printf("\n"); printf("Please report bugs to \n"); printf("Copyright (C) 2009-2012 Daniel Borkmann \n"); printf("Copyright (C) 2009-2012 Emmanuel Roullit \n"); printf("License: GNU GPL version 2\n"); printf("This is free software: you are free to change and redistribute it.\n"); printf("There is NO WARRANTY, to the extent permitted by law.\n\n"); die(); } static void version(void) { printf("\n%s %s, the packet sniffing beast\n", PROGNAME_STRING, VERSION_STRING); printf("http://www.netsniff-ng.org\n\n"); printf("Please report bugs to \n"); printf("Copyright (C) 2009-2012 Daniel Borkmann \n"); printf("Copyright (C) 2009-2012 Emmanuel Roullit \n"); printf("License: GNU GPL version 2\n"); printf("This is free software: you are free to change and redistribute it.\n"); printf("There is NO WARRANTY, to the extent permitted by law.\n\n"); die(); } static void header(void) { printf("%s%s%s\n", colorize_start(bold), PROGNAME_STRING " " VERSION_STRING, colorize_end()); } int main(int argc, char **argv) { int c, i, j, opt_index, ops_touched = 0; char *ptr; bool prio_high = false; struct mode mode; void (*enter_mode)(struct mode *mode) = NULL; check_for_root_maybe_die(); fmemset(&mode, 0, sizeof(mode)); mode.link_type = LINKTYPE_EN10MB; mode.print_mode = FNTTYPE_PRINT_NORM; mode.cpu = CPU_UNKNOWN; mode.packet_type = PACKET_ALL; mode.promiscuous = true; mode.randomize = false; mode.pcap = PCAP_OPS_SG; mode.dump_interval = DUMP_INTERVAL; while ((c = getopt_long(argc, argv, short_options, long_options, &opt_index)) != EOF) { switch (c) { case 'd': case 'i': mode.device_in = xstrdup(optarg); break; case 'o': mode.device_out = xstrdup(optarg); break; case 'R': mode.link_type = LINKTYPE_IEEE802_11; mode.rfraw = 1; break; case 'r': mode.randomize = true; break; case 'J': mode.jumbo_support = 1; break; case 'f': mode.filter = xstrdup(optarg); break; case 'M': mode.promiscuous = false; break; case 't': if (!strncmp(optarg, "host", strlen("host"))) mode.packet_type = PACKET_HOST; else if (!strncmp(optarg, "broadcast", strlen("broadcast"))) mode.packet_type = PACKET_BROADCAST; else if (!strncmp(optarg, "multicast", strlen("multicast"))) mode.packet_type = PACKET_MULTICAST; else if (!strncmp(optarg, "others", strlen("others"))) mode.packet_type = PACKET_OTHERHOST; else if (!strncmp(optarg, "outgoing", strlen("outgoing"))) mode.packet_type = PACKET_OUTGOING; else mode.packet_type = PACKET_ALL; break; case 'S': ptr = optarg; mode.reserve_size = 0; for (j = i = strlen(optarg); i > 0; --i) { if (!isdigit(optarg[j - i])) break; ptr++; } if (!strncmp(ptr, "KB", strlen("KB"))) mode.reserve_size = 1 << 10; else if (!strncmp(ptr, "MB", strlen("MB"))) mode.reserve_size = 1 << 20; else if (!strncmp(ptr, "GB", strlen("GB"))) mode.reserve_size = 1 << 30; else panic("Syntax error in ring size param!\n"); *ptr = 0; mode.reserve_size *= atoi(optarg); break; case 'b': set_cpu_affinity(optarg, 0); if (mode.cpu != CPU_NOTOUCH) mode.cpu = atoi(optarg); break; case 'B': set_cpu_affinity(optarg, 1); break; case 'H': prio_high = true; break; case 'c': mode.pcap = PCAP_OPS_RW; ops_touched = 1; break; case 'm': mode.pcap = PCAP_OPS_MMAP; ops_touched = 1; break; case 'g': mode.pcap = PCAP_OPS_SG; ops_touched = 1; break; case 'Q': mode.cpu = CPU_NOTOUCH; break; case 's': mode.print_mode = FNTTYPE_PRINT_NONE; break; case 'q': mode.print_mode = FNTTYPE_PRINT_LESS; break; case 'X': mode.print_mode = (mode.print_mode == FNTTYPE_PRINT_ASCII) ? FNTTYPE_PRINT_HEX_ASCII : FNTTYPE_PRINT_HEX; break; case 'l': mode.print_mode = (mode.print_mode == FNTTYPE_PRINT_HEX) ? FNTTYPE_PRINT_HEX_ASCII : FNTTYPE_PRINT_ASCII; break; case 'k': mode.kpull = (unsigned long) atol(optarg); break; case 'n': frame_cnt_max = (unsigned long) atol(optarg); break; case 'F': mode.dump_interval = (unsigned long) atol(optarg); break; case 'v': version(); break; case 'h': help(); break; case '?': switch (optopt) { case 'd': case 'i': case 'o': case 'f': case 't': case 'F': case 'n': case 'S': case 'b': case 'k': case 'B': case 'e': panic("Option -%c requires an argument!\n", optopt); default: if (isprint(optopt)) whine("Unknown option character " "`0x%X\'!\n", optopt); die(); } default: break; } } if (!mode.device_in) mode.device_in = xstrdup("any"); register_signal(SIGINT, signal_handler); register_signal(SIGHUP, signal_handler); init_pcap(mode.jumbo_support); tprintf_init(); header(); if (prio_high == true) { set_proc_prio(get_default_proc_prio()); set_sched_status(get_default_sched_policy(), get_default_sched_prio()); } if (mode.device_in && (device_mtu(mode.device_in) || !strncmp("any", mode.device_in, strlen(mode.device_in)))) { if (!mode.device_out) { mode.dump = 0; enter_mode = enter_mode_rx_only_or_dump; } else if (device_mtu(mode.device_out)) { register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); enter_mode = enter_mode_rx_to_tx; } else { mode.dump = 1; register_signal_f(SIGALRM, timer_next_dump, SA_SIGINFO); enter_mode = enter_mode_rx_only_or_dump; if (!ops_touched) mode.pcap = PCAP_OPS_SG; } } else { if (mode.device_out && device_mtu(mode.device_out)) { register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); enter_mode = enter_mode_pcap_to_tx; if (!ops_touched) mode.pcap = PCAP_OPS_MMAP; } else { enter_mode = enter_mode_read_pcap; if (!ops_touched) mode.pcap = PCAP_OPS_SG; } } if (!enter_mode) panic("Selection not supported!\n"); enter_mode(&mode); tprintf_cleanup(); cleanup_pcap(); if (mode.device_in) xfree(mode.device_in); if (mode.device_out) xfree(mode.device_out); if (mode.device_trans) xfree(mode.device_trans); return 0; } netsniff-ng-0.5.7/src/mtrand.h0000664000175000017500000000126411773367375016346 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #ifndef MTRAND_H #define MTRAND_H extern void mt_init_by_seed_rand(unsigned long s); extern void mt_init_by_seed_time(void); extern void mt_init_by_seed_array(unsigned long key[], int len); extern void mt_init_by_seed_rand_array(void); extern void mt_init_by_random_device(void); extern unsigned long mt_rand_int32(void); extern long mt_rand_int31(void); extern double mt_rand_real1(void); extern double mt_rand_real2(void); extern double mt_rand_real3(void); extern double mt_rand_res53(void); #endif /* MTRAND_H */ netsniff-ng-0.5.7/src/mtrand.c0000664000175000017500000000705511773367375016345 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Copyright (C) 1997-2004, Makoto Matsumoto, Takuji Nishimura, and * Eric Landry; All rights reserved. (3-clause BSD license) * Daniel Borkmann: Refactored, added initialization functions. * Subject to the GPL, version 2. * Reference: M. Matsumoto and T. Nishimura, "Mersenne Twister: * A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number * Generator", ACM Transactions on Modeling and Computer Simulation, * Vol. 8, No. 1, January 1998, pp 3--30. */ #include #include #include #include #include #include "mtrand.h" #include "xio.h" #define N 624 #define M 397 #define LEN_INIT 256 #define MATRIX_A 0x9908b0dfUL #define UPPER_MASK 0x80000000UL #define LOWER_MASK 0x7fffffffUL static unsigned long x[N]; static unsigned long *p0, *p1, *pm; void mt_init_by_seed_rand(unsigned long s) { int i; x[0] = s & 0xffffffffUL; for (i = 1; i < N; ++i) { x[i] = (1812433253UL * (x[i - 1] ^ (x[i - 1] >> 30)) + i) & 0xffffffffUL; } p0 = x; p1 = x + 1; pm = x + M; } void mt_init_by_seed_time(void) { int i; x[0] = ((unsigned long) time(NULL)) & 0xffffffffUL; for (i = 1; i < N; ++i) { x[i] = (1812433253UL * (x[i - 1] ^ (x[i - 1] >> 30)) + i) & 0xffffffffUL; } p0 = x; p1 = x + 1; pm = x + M; } void mt_init_by_seed_array(unsigned long key[], int len) { int i, j, k; mt_init_by_seed_rand(19650218UL); i = 1; j = 0; for (k = (N > len ? N : len); k; --k) { /* Non linear */ x[i] = ((x[i] ^ ((x[i - 1] ^ (x[i - 1] >> 30)) * 1664525UL)) + key[j] + j) & 0xffffffffUL; if (++i >= N) { x[0] = x[N - 1]; i = 1; } if (++j >= len) j = 0; } for (k = N - 1; k; --k) { /* Non linear */ x[i] = ((x[i] ^ ((x[i - 1] ^ (x[i - 1] >> 30)) * 1566083941UL)) - i) & 0xffffffffUL; if (++i >= N) { x[0] = x[N - 1]; i = 1; } } x[0] = 0x80000000UL; } void mt_init_by_seed_rand_array(void) { int i; unsigned long k[LEN_INIT]; srand((unsigned int) time(NULL)); for (i = 0; i < LEN_INIT; i++) k[i] = rand(); mt_init_by_seed_array(k, LEN_INIT); } void mt_init_by_random_device(void) { int fd; unsigned long k[LEN_INIT]; fd = open_or_die("/dev/random", O_RDONLY); read_or_die(fd, k, sizeof(unsigned long) * LEN_INIT); close(fd); mt_init_by_seed_array(k, LEN_INIT); } unsigned long mt_rand_int32(void) { /* Interval [0,0xffffffff] */ unsigned long y; /* Default seed */ if (p0 == NULL) mt_init_by_seed_rand(5489UL); /* Twisted feedback */ y = *p0 = *pm++ ^ (((*p0 & UPPER_MASK) | (*p1 & LOWER_MASK)) >> 1) ^ (-(*p1 & 1) & MATRIX_A); p0 = p1++; if (pm == x + N) pm = x; if (p1 == x + N) p1 = x; /* Temper */ y ^= y >> 11; y ^= y << 7 & 0x9d2c5680UL; y ^= y << 15 & 0xefc60000UL; y ^= y >> 18; return y; } long mt_rand_int31(void) { /* Interval [0,0x7fffffff] */ return (long) mt_rand_int32() >> 1; } double mt_rand_real1(void) { /* Interval [0,1]; Divided by 2^32-1 */ return mt_rand_int32() * (1.0 / 4294967295.0); } double mt_rand_real2(void) { /* Interval [0,1); Divided by 2^32 */ return mt_rand_int32() * (1.0 / 4294967296.0); } double mt_rand_real3(void) { /* Interval (0,1); Divided by 2^32 */ return (((double) mt_rand_int32()) + 0.5) * (1.0 / 4294967296.0); } double mt_rand_res53(void) { /* 53-bit random number on the real interval [0,1) */ unsigned long a = mt_rand_int32() >> 5, b = mt_rand_int32() >> 6; return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0); } netsniff-ng-0.5.7/src/mac80211.h0000664000175000017500000000056611773367375016221 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2012 Daniel Borkmann. * Subject to the GPL, version 2. */ #ifndef MAC80211_H #define MAC80211_H extern void enter_rfmon_mac80211(const char *device, char **mondev); extern void leave_rfmon_mac80211(const char *device, const char *mondev); #endif /* MAC80211_H */ netsniff-ng-0.5.7/src/mac80211.c0000664000175000017500000001340211773367375016205 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2012 Daniel Borkmann. * Subject to the GPL, version 2. * Parts derived from iw, subject to ISC license. * Copyright 2007, 2008 Johannes Berg * Copyright 2007 Andy Lutomirski * Copyright 2007 Mike Kershaw * Copyright 2008-2009 Luis R. Rodriguez */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "die.h" #include "xutils.h" #include "mac80211.h" #include "xmalloc.h" #include "built_in.h" #ifdef HAVE_LIBNL_2_x # define LIBNL_FAILURE NLE_FAILURE # define get_nl_errmsg nl_geterror #else # define LIBNL_FAILURE ENFILE /* libnl 2.x compatibility code */ # define nl_sock nl_handle static inline struct nl_handle *nl_socket_alloc(void) { return nl_handle_alloc(); } static inline void nl_socket_free(struct nl_handle *h) { nl_handle_destroy(h); } # define get_nl_errmsg strerror static inline int __genl_ctrl_alloc_cache(struct nl_handle *h, struct nl_cache **cache) { struct nl_cache *tmp = genl_ctrl_alloc_cache(h); if (!tmp) return -ENOMEM; *cache = tmp; return 0; } # define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache #endif /* !HAVE_LIBNL_2_x */ struct nl80211_state { struct nl_sock *nl_sock; struct nl_cache *nl_cache; struct genl_family *nl80211; }; static void get_mac80211_phydev(const char *device, char *phydev_path, size_t phydev_len) { int ret; char *pathstr; ssize_t num; ret = asprintf(&pathstr, "/sys/class/net/%s/phy80211", device); if (ret < 0) panic("Can't generate path name string for /sys/class/net device"); num = readlink(pathstr, phydev_path, phydev_len); if (num < 0) { if (errno == ENOENT || errno == EINVAL) panic("It's probably not a mac80211 device!\n"); panic("Can't readlink %s: %s!\n", pathstr, strerror(errno)); } xfree(pathstr); phydev_path[min(num, phydev_len - 1)] = 0; } static inline struct nl_msg *nl80211_nlmsg_xalloc(void) { struct nl_msg *ret = nlmsg_alloc(); if (!ret) panic("Cannot allocate nlmsg memory!\n"); return ret; } static inline struct nl_handle *nl80211_nl_socket_xalloc(void) { struct nl_handle *ret = nl_socket_alloc(); if (!ret) panic("Cannot allocate nl socket memory!\n"); return ret; } static void nl80211_init(struct nl80211_state *state, const char *device) { int ret; state->nl_sock = nl80211_nl_socket_xalloc(); ret = genl_connect(state->nl_sock); if (ret) panic("Cannot connect generic netlink!\n"); ret = genl_ctrl_alloc_cache(state->nl_sock, &state->nl_cache); if (ret < 0) panic("Failed to allocate generic netlink cache: %s!", get_nl_errmsg(-ret)); state->nl80211 = genl_ctrl_search_by_name(state->nl_cache, "nl80211"); if (!state->nl80211) panic("nl80211 not found in netlink cache!\n"); } static void nl80211_cleanup(struct nl80211_state *state) { genl_family_put(state->nl80211); nl_cache_free(state->nl_cache); nl_socket_free(state->nl_sock); } static int nl80211_add_mon_if(struct nl80211_state *state, const char *device, const char *mondevice) { int ifindex, ret; struct nl_msg *msg; ifindex = device_ifindex(device); msg = nl80211_nlmsg_xalloc(); genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0, 0, NL80211_CMD_NEW_INTERFACE, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, mondevice); NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR); ret = nl_send_auto_complete(state->nl_sock, msg); if (ret < 0) { if (ret == -LIBNL_FAILURE) { nlmsg_free(msg); return -EBUSY; } panic("Cannot send_auto_complete!\n"); } ret = nl_wait_for_ack(state->nl_sock); if (ret < 0) { if (ret == -LIBNL_FAILURE) { nlmsg_free(msg); return -EBUSY; } panic("Waiting for netlink ack failed!\n"); } nlmsg_free(msg); return 0; nla_put_failure: panic("nla put failure!\n"); return -EIO; /* dummy */ } static int nl80211_del_mon_if(struct nl80211_state *state, const char *device, const char *mondevice) { int ifindex, ret; struct nl_msg *msg; ifindex = device_ifindex(mondevice); msg = nl80211_nlmsg_xalloc(); genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0, 0, NL80211_CMD_DEL_INTERFACE, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); ret = nl_send_auto_complete(state->nl_sock, msg); if (ret < 0) panic("Cannot send_auto_complete!\n"); ret = nl_wait_for_ack(state->nl_sock); if (ret < 0) panic("Waiting for netlink ack failed!\n"); nlmsg_free(msg); return 0; nla_put_failure: panic("nla put failure!\n"); return -EIO; /* dummy */ } void enter_rfmon_mac80211(const char *device, char **mondev) { int ret; short flags; uint32_t n; char phydev_path[256]; struct nl80211_state nlstate; /* XXX: is this already a monN device? */ get_mac80211_phydev(device, phydev_path, sizeof(phydev_path)); nl80211_init(&nlstate, device); for (n = 0; n < UINT_MAX; n++) { char mondevice[32]; slprintf(mondevice, sizeof(mondevice), "mon%u", n); ret = nl80211_add_mon_if(&nlstate, device, mondevice); if (ret == 0) { *mondev = xstrdup(mondevice); flags = device_get_flags(*mondev); flags |= IFF_UP | IFF_RUNNING; device_set_flags(*mondev, flags); nl80211_cleanup(&nlstate); return; } } panic("No free monN interfaces!\n"); } void leave_rfmon_mac80211(const char *device, const char *mondev) { short flags; struct nl80211_state nlstate; flags = device_get_flags(mondev); flags &= ~(IFF_UP | IFF_RUNNING); device_set_flags(mondev, flags); nl80211_init(&nlstate, device); nl80211_del_mon_if(&nlstate, device, mondev); nl80211_cleanup(&nlstate); } netsniff-ng-0.5.7/src/locking.h0000664000175000017500000000310311773367375016501 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2011 Daniel Borkmann. * Subject to the GPL, version 2. */ #ifndef LOCKING_H #define LOCKING_H #include struct spinlock { pthread_spinlock_t lock; }; struct mutexlock { pthread_mutex_t lock; }; struct rwlock { pthread_rwlock_t lock; }; static inline int spinlock_init(struct spinlock *l) { return -pthread_spin_init(&l->lock, 0); } static inline void spinlock_destroy(struct spinlock *l) { pthread_spin_destroy(&l->lock); } static inline void spinlock_lock(struct spinlock *l) { pthread_spin_lock(&l->lock); } static inline void spinlock_unlock(struct spinlock *l) { pthread_spin_unlock(&l->lock); } static inline int mutexlock_init(struct mutexlock *l) { return -pthread_mutex_init(&l->lock, 0); } static inline void mutexlock_destroy(struct mutexlock *l) { pthread_mutex_destroy(&l->lock); } static inline void mutexlock_lock(struct mutexlock *l) { pthread_mutex_lock(&l->lock); } static inline void mutexlock_unlock(struct mutexlock *l) { pthread_mutex_unlock(&l->lock); } static inline int rwlock_init(struct rwlock *l) { return -pthread_rwlock_init(&l->lock, 0); } static inline void rwlock_destroy(struct rwlock *l) { pthread_rwlock_destroy(&l->lock); } static inline void rwlock_rd_lock(struct rwlock *l) { pthread_rwlock_rdlock(&l->lock); } static inline void rwlock_wr_lock(struct rwlock *l) { pthread_rwlock_wrlock(&l->lock); } static inline void rwlock_unlock(struct rwlock *l) { pthread_rwlock_unlock(&l->lock); } #endif /* LOCKING_H */ netsniff-ng-0.5.7/src/ifpps.c0000664000175000017500000005614611773367375016206 0ustar bordaniebordanie/* * netsniff-ng - the packet sniffing beast * By Daniel Borkmann * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. * * A tiny tool to provide top-like reliable networking statistics. * Why? Well, some time ago I used iptraf to display network traffic * statistics. During that time and probably also today, they are * using libpcap to collect statistics. Well, bad idea since this * will give you false statistics on high I/O load. Therefore, ifpps * reads out the 'real' kernel statistics, so things your NIC sees * and not some userland library. * * He had all the injured air of a liar suspected when for once he * has told the truth, or part of it. * * -- The Lord of the Rings, On Gollum, * Chapter 'The Black Gate is Closed'. */ /* =head1 NAME ifpps - fetch and format kernel network statistics =head1 SYNOPSIS ifpps -d|--dev [-t|--interval ][-p|--promisc][-c|--term] [-C|--csv][-H|--csv-tablehead][-l|--loop][-v|--version][-h|--help] =head1 DESCRIPTION A tiny tool to provide top-like reliable networking statistics. ifpps reads out the 'real' kernel statistics, so it does not give erroneous statistics on high I/O load. =head1 OPTIONS =over =item ifpps --dev eth0 Fetch eth0 interface statistics. =item ifpps --dev eth0 --interval 60 --csv Output eth0 interface statistics every minute in CSV format. =back =head1 OPTIONS =over =item -h|--help Print help text and lists all options. =item -v|--version Print version. =item -d|--dev Device to fetch statistics for i.e., eth0. =item -p|--promisc Put the device in promiscuous mode =item -t|--interval