├── .gitignore ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile.am ├── Makefile.in ├── NEWS ├── README ├── VERSION ├── aclocal.m4 ├── capture.c ├── capture.h ├── config.guess ├── config.h.in ├── config.sub ├── configure ├── configure.ac ├── datalink.c ├── datalink.h ├── examples.txt ├── install-sh ├── main.c ├── missing ├── mkinstalldirs ├── probe.c ├── probe.h ├── stamp-h.in ├── tcptraceroute.1 ├── tcptraceroute.1.html ├── tcptraceroute.h ├── tcptraceroute.lsm ├── testsuite.pl ├── traceroute.cgi ├── util.c └── util.h /.gitignore: -------------------------------------------------------------------------------- 1 | .deps/ 2 | Makefile 3 | config.h 4 | config.log 5 | config.status 6 | stamp-h 7 | *.o 8 | tcptraceroute 9 | tags 10 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Michael C. Toren 2 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | Version 1.5beta7 (2006-03-28) 2 | 3 | Added check to ensure pcap_fd is within the range of select(2) to 4 | avoid any potential FD_SET overflows, by Shaun Colley 5 | 6 | Rebuilt autoconf files with a more recent version of autoconf from a 7 | Debian Sarge system, to resolve Debian Bug#333827. 8 | 9 | Updated the man page and examples.txt files to document the new --dnat 10 | detection features. 11 | 12 | Updated the (unofficial) debian/control file to build-depend on 13 | libnet1-dev rather than libnet0-dev. 14 | 15 | Version 1.5beta6 (2005-01-03) 16 | 17 | New --dnat, --no-dnat (default), and --no-dnat-strict command line 18 | arguments. --dnat enabled Destination NAT detection, which works by 19 | comparing the quoted IP address in an ICMP payload with the 20 | destination a probe packet was addressed to. 21 | 22 | Numeric IP address in parenthesis is now only displayed if the content 23 | in the parenthesis is different than the non-parenthesized content, 24 | making the output less busy. 25 | 26 | The SYN ISN (Initial Sequence Number) now set to a random 32bit value; 27 | previously had always been zero. 28 | 29 | Added missing htons() call around the arguments to getservbyport(), 30 | which resulted in the destination port service name not being correctly 31 | reported on some architectures, by Dmitry Karasik 32 | 33 | Improved the configure.ac so that it is less likely to link against 34 | unnecessary libraries by "Dmitry V. Levin" 35 | 36 | --no-select is now the default under NetBSD, based on a report and data 37 | collected by Ed Ravin . 38 | 39 | Split the tcptraceroute.c file into main.c, datalink.c, probe.c, 40 | capture.c, util.c, and a number of include files, which should make 41 | things much more manageable. 42 | 43 | Version 1.5beta5 (2003-07-02) 44 | 45 | Now functions properly with libpcap when using an interface without a 46 | valid IPv4 addresss. Reported by Kris Shannon 47 | in Debian Bug#183456. 48 | 49 | Improved autoconf handling of the --with-libpcap= command line argument, 50 | by Richard van den Berg . 51 | 52 | Moved the tcptraceroute man page to section 1 from section 8 now that 53 | tcptraceroute is installed in /usr/bin by default, as suggested by 54 | James Ralston . 55 | 56 | Added a missing call to pcap_freecode() to free up memory utilized 57 | by the bpf_program struct, after applying it with pcap_setfilter(). 58 | 59 | Should now deal better (and skip over) unconfigured interface under 60 | NetBSD. 61 | 62 | Version 1.5beta4 (2003-06-29) 63 | 64 | A call to seteuid() has been replaced with a call to setuid() to fully 65 | drop root privileges. As there are currently no known exploitable 66 | portions of tcptraceroute, older versions are still believed to be 67 | safe even without fully dropping privileges, however users are still 68 | encouraged to upgrade to provide a measure of containment in the event 69 | that an exploitable flaw is discovered in the future. Reported by Matt 70 | Zimmerman , and published in Debian Security Advisory 71 | DSA 330-1. 72 | 73 | AC_FUNC_REALLOC was commented out of configure.ac, which was failing on 74 | HP/UX badly systems. The xrealloc() function in tcptraceroute already 75 | works around the realloc(0,0) case that AC_FUNC_REALLOC is attempting 76 | to prevent against, anyway. Reported by Petter Reinholdtsen 77 | . 78 | 79 | Version 1.5beta3 (2003-06-01) 80 | 81 | Added some additional AC_CHECK_LIB lines to the configure.ac file, 82 | required for Solaris systems, by Petter Reinholdtsen . 83 | 84 | Fixed a number of type warnings under non-gcc compilers by adding a few 85 | casts; reported by Petter Reinholdtsen . 86 | 87 | Version 1.5beta2 (2003-05-25) 88 | 89 | Added an autoconf check to detect MacOS X systems by looking to see if 90 | __APPLE__ and __MACH__ are defined. Also added an autoconf configure 91 | command line argument --enable-noselect-default to control the default 92 | behavior of the tcptraceroute --noselect command line argument, and 93 | enabled it by default on MacOS X systems if not otherwise specified. 94 | 95 | Version 1.5beta1 (2003-05-24) 96 | 97 | Most substantially, support for both autoconf and libnet-1.1.x 98 | has been added, based on patches from (in alphabetical order): 99 | 100 | jbash@velvet.com 101 | Jon Allen Boone 102 | James Ralston 103 | Darren Tucker 104 | Matt Weidner 105 | 106 | Added linklayer support for PPPoE interfaces, by Darren Tucker 107 | . 108 | 109 | Improved the round trip time calculations, by Amgad Zeitoun 110 | . 111 | 112 | Removed a number of multi-line strings, which apparently causes 113 | trouble for some compilers, based on patches from: 114 | 115 | jbash@velvet.com 116 | Richard van den Berg 117 | Petter Reinholdtsen 118 | 119 | Version 1.4 (2002-07-30) 120 | 121 | Added linklayer support for Linux ISDN Sync-PPP interfaces, 122 | by Dr. Peter Bieringer . 123 | 124 | Adds support back for DLT_RAW interfaces, which was inadvertently 125 | removed sometime between 1.2 and 1.3beta1, and as a result caused 126 | tcptraceroute to fail over PPP interfaces. Reported in Debian 127 | Bug#154793 by David Harris . 128 | 129 | Version 1.3 (2002-05-19) 130 | 131 | Now detects (and ignores) IP packets with IP options. 132 | 133 | Packets are now properly aligned by allocating new space and 134 | copying the packet data there before casting packet header 135 | structs against them. 136 | 137 | New, undocumented --no-select command line argument added to never 138 | call select(), which fails to indicate that a BPF socket is ready 139 | for reading on some BSD systems. 140 | 141 | Now sets a non-zero exit code if the destination was not reached, 142 | as suggested by Arndt Schoenewald 143 | 144 | Fixes an off-by-one error in getinterfaces(), discovered by 145 | Kit Knox . 146 | 147 | probe() and capture() now use a new proberecord structure which 148 | contains information about each probe in a modularized way. 149 | 150 | Added a new command line argument, --track-port, which causes each 151 | probe to have a unique source port so that something other than the 152 | IP ID can be used to track it, and also a corresponding --track-id 153 | argument to specify the old behavior of tracking IP ID's. If a 154 | source port is specified with -p, --track-id is implied. The 155 | compile-time default on Solaris is --track-port, enabling 156 | tcptraceroute to work out-of-the-box, and --track-id on all other 157 | platforms. 158 | 159 | probe() now calls allocateid() to generate an IP ID, which 160 | caches the last ALLOCATEID_CACHE_SIZE allocations to prevent 161 | against duplicates. 162 | 163 | Display "!" instead of "!?" for unknown ICMP codes, as 164 | suggested by Kevin McAllister 165 | 166 | Attempts to find virtual addresses under OpenBSD, based on a 167 | patch by Scott Gifford 168 | 169 | Moves the datalinkoffset and datalinkname information into a 170 | single data structure, which is much more logical, and less 171 | prone to error. 172 | 173 | Improved command line argument handling a good deal, based 174 | on suggestions by Scott Fenton . First, 175 | a pass through is made to process and shift out long command 176 | line arguments, then the remaining command line is passed to 177 | getopt(). 178 | 179 | It is now possible to traceroute to yourself, by switching the 180 | device to the loopback interface if the destination matches the 181 | address of a local interface. Additionally, as learned by 182 | looking through the nmap source, we now never set a libpcap 183 | filter on the loopback interface to avoid apparent libpcap bugs 184 | which previously made it impossible to traceroute to 127.0.0.1 185 | 186 | Added -S and -A command line arguments to control the SYN 187 | and ACK flags in outgoing packets. By using -A, it is now 188 | possible to traceroute through stateless firewalls which 189 | permit hosts behind the firewalls to establish outgoing TCP 190 | connections. In the absence of either -A or -S, -S is set. 191 | 192 | Added -N command line argument which takes the place of the 193 | previous RESOLVE_RFC1918 #define. 194 | 195 | Now displays if the remote host is ECN capable when using -E 196 | 197 | Version 1.2 (2001-07-31) 198 | 199 | Contains large portions of code and ideas contributed by 200 | Scott Gifford 201 | 202 | Attempt to determine what outgoing interface to use based on 203 | the destination address and the local system's interface list. 204 | Could still use a good deal of work on BSD systems, though, 205 | especially when it comes to virtual addresses which reside on 206 | subnets different than the primary address. 207 | 208 | The timeout code has been reworked significantly, and should 209 | now be much more reliable. 210 | 211 | Added -E command line argument to send ECN (RFC2481) packets. 212 | Requested by Christophe Barb and 213 | Jim Penny 214 | 215 | Added -l command line argument to set the total packet length, 216 | including IP header. 217 | 218 | Added support for sending more than one probe to each hop, and 219 | the -q command line option to specify the number of probes. 220 | 221 | Added -F command line argument to set the IP_DF bit. 222 | 223 | Added -t command line argument to set the IP TOS. 224 | 225 | Now properly checks the length of the packets returned by libpcap 226 | before blindly assuming that the entire header structure we happen 227 | to be looking for is there. This could have been very ugly had the 228 | snaplen not been set so conservatively. 229 | 230 | Print banner information to stderr, not stdout, to be compatible with 231 | traceroute(8). Reported by Scott Fenton 232 | 233 | Fixed an endian bug reported by Zoran Dzelajlija , 234 | which prevented users from specifying the destination port number by 235 | name. 236 | 237 | Version 1.1 (2001-06-30) 238 | 239 | Now drops root privileges after sockets have been opened. 240 | 241 | Must now be root to use -s or -p, making it now safe to to install 242 | tcptraceroute suid root, without fear that users can generate arbitrary 243 | SYN packets. 244 | 245 | Version 1.0 (2001-04-10) 246 | 247 | Initial Release. 248 | 249 | # vim:set ts=4 sw=4 tw=75 ai syntax=off: 250 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | As of release 1.5beta1, tcptraceroute now uses GNU autoconf to ease the 2 | task of installation and to provide better portability. As with all 3 | programs utilizing autoconf, the simplest way to compile the package is 4 | (quoting from the default INSTALL documentation that ships with 5 | autoconf): 6 | 7 | 1. `cd' to the directory containing the package's source code and type 8 | `./configure' to configure the package for your system. If you're 9 | using `csh' on an old version of System V, you might need to type 10 | `sh ./configure' instead to prevent `csh' from trying to execute 11 | `configure' itself. 12 | 13 | Running `configure' takes awhile. While running, it prints some 14 | messages telling which features it is checking for. 15 | 16 | 2. Type `make' to compile the package. 17 | 18 | 3. Type `make install' to install the programs and any data files and 19 | documentation. 20 | 21 | 4. You can remove the program binaries and object files from the 22 | source code directory by typing `make clean'. To also remove the 23 | files that `configure' created (so you can compile the package for 24 | a different kind of computer), type `make distclean'. 25 | 26 | The configure scripts supports a number of command line options. The 27 | ones you're most likely to use are: 28 | 29 | --prefix=PREFIX install architecture-independent files in 30 | PREFIX [/usr/local] 31 | --with-libpcap=DIR use libpcap in DIR 32 | --with-libnet=DIR use libnet in DIR 33 | --enable-noselect-default 34 | default to not using select(2) 35 | --enable-track-default=PORT|ID 36 | default to tracking probes by PORT or ID 37 | --enable-default-port=N default destination port 38 | --enable-static compile staticly, if using gcc 39 | 40 | -mct, Sun May 25 11:16:48 EDT 2003 41 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = tcptraceroute 2 | tcptraceroute_SOURCES = main.c datalink.c util.c probe.c capture.c 3 | man_MANS = tcptraceroute.1 4 | 5 | docdir = $(datadir)/doc/tcptraceroute 6 | doc_DATA = AUTHORS COPYING ChangeLog NEWS README \ 7 | examples.txt tcptraceroute.1.html tcptraceroute.lsm 8 | 9 | EXTRA_DIST = $(doc_DATA) $(man_MANS) VERSION debian 10 | 11 | # AM_CFLAGS = @AM_CFLAGS@ 12 | 13 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated automatically by automake 1.4-p6 from Makefile.am 2 | 3 | # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. 4 | # This Makefile.in is free software; the Free Software Foundation 5 | # gives unlimited permission to copy and/or distribute it, 6 | # with or without modifications, as long as this notice is preserved. 7 | 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 10 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 11 | # PARTICULAR PURPOSE. 12 | 13 | 14 | SHELL = @SHELL@ 15 | 16 | srcdir = @srcdir@ 17 | top_srcdir = @top_srcdir@ 18 | VPATH = @srcdir@ 19 | prefix = @prefix@ 20 | exec_prefix = @exec_prefix@ 21 | 22 | bindir = @bindir@ 23 | sbindir = @sbindir@ 24 | libexecdir = @libexecdir@ 25 | datadir = @datadir@ 26 | sysconfdir = @sysconfdir@ 27 | sharedstatedir = @sharedstatedir@ 28 | localstatedir = @localstatedir@ 29 | libdir = @libdir@ 30 | infodir = @infodir@ 31 | mandir = @mandir@ 32 | includedir = @includedir@ 33 | oldincludedir = /usr/include 34 | 35 | DESTDIR = 36 | 37 | pkgdatadir = $(datadir)/@PACKAGE@ 38 | pkglibdir = $(libdir)/@PACKAGE@ 39 | pkgincludedir = $(includedir)/@PACKAGE@ 40 | 41 | top_builddir = . 42 | 43 | ACLOCAL = @ACLOCAL@ 44 | AUTOCONF = @AUTOCONF@ 45 | AUTOMAKE = @AUTOMAKE@ 46 | AUTOHEADER = @AUTOHEADER@ 47 | 48 | INSTALL = @INSTALL@ 49 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) 50 | INSTALL_DATA = @INSTALL_DATA@ 51 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 52 | transform = @program_transform_name@ 53 | 54 | NORMAL_INSTALL = : 55 | PRE_INSTALL = : 56 | POST_INSTALL = : 57 | NORMAL_UNINSTALL = : 58 | PRE_UNINSTALL = : 59 | POST_UNINSTALL = : 60 | build_alias = @build_alias@ 61 | build_triplet = @build@ 62 | host_alias = @host_alias@ 63 | host_triplet = @host@ 64 | target_alias = @target_alias@ 65 | target_triplet = @target@ 66 | CC = @CC@ 67 | HAVE_LIB = @HAVE_LIB@ 68 | LIB = @LIB@ 69 | LTLIB = @LTLIB@ 70 | MAKEINFO = @MAKEINFO@ 71 | PACKAGE = @PACKAGE@ 72 | VERSION = @VERSION@ 73 | 74 | bin_PROGRAMS = tcptraceroute 75 | tcptraceroute_SOURCES = main.c datalink.c util.c probe.c capture.c 76 | man_MANS = tcptraceroute.1 77 | 78 | docdir = $(datadir)/doc/tcptraceroute 79 | doc_DATA = AUTHORS COPYING ChangeLog NEWS README examples.txt tcptraceroute.1.html tcptraceroute.lsm 80 | 81 | 82 | EXTRA_DIST = $(doc_DATA) $(man_MANS) VERSION debian 83 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 84 | mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs 85 | CONFIG_HEADER = config.h 86 | CONFIG_CLEAN_FILES = 87 | PROGRAMS = $(bin_PROGRAMS) 88 | 89 | 90 | DEFS = @DEFS@ -I. -I$(srcdir) -I. 91 | CPPFLAGS = @CPPFLAGS@ 92 | LDFLAGS = @LDFLAGS@ 93 | LIBS = @LIBS@ 94 | tcptraceroute_OBJECTS = main.o datalink.o util.o probe.o capture.o 95 | tcptraceroute_LDADD = $(LDADD) 96 | tcptraceroute_DEPENDENCIES = 97 | tcptraceroute_LDFLAGS = 98 | CFLAGS = @CFLAGS@ 99 | COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) 100 | CCLD = $(CC) 101 | LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ 102 | man1dir = $(mandir)/man1 103 | MANS = $(man_MANS) 104 | 105 | NROFF = nroff 106 | DATA = $(doc_DATA) 107 | 108 | DIST_COMMON = README ./stamp-h.in AUTHORS COPYING ChangeLog INSTALL \ 109 | Makefile.am Makefile.in NEWS aclocal.m4 config.guess config.h.in \ 110 | config.sub configure configure.ac install-sh missing mkinstalldirs 111 | 112 | 113 | DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) 114 | 115 | TAR = tar 116 | GZIP_ENV = --best 117 | DEP_FILES = .deps/capture.P .deps/datalink.P .deps/main.P .deps/probe.P \ 118 | .deps/util.P 119 | SOURCES = $(tcptraceroute_SOURCES) 120 | OBJECTS = $(tcptraceroute_OBJECTS) 121 | 122 | all: all-redirect 123 | .SUFFIXES: 124 | .SUFFIXES: .S .c .o .s 125 | $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) 126 | cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile 127 | 128 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) 129 | cd $(top_builddir) \ 130 | && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status 131 | 132 | $(ACLOCAL_M4): configure.ac 133 | cd $(srcdir) && $(ACLOCAL) 134 | 135 | config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 136 | $(SHELL) ./config.status --recheck 137 | $(srcdir)/configure: $(srcdir)/configure.ac $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) 138 | cd $(srcdir) && $(AUTOCONF) 139 | 140 | config.h: stamp-h 141 | @if test ! -f $@; then \ 142 | rm -f stamp-h; \ 143 | $(MAKE) stamp-h; \ 144 | else :; fi 145 | stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status 146 | cd $(top_builddir) \ 147 | && CONFIG_FILES= CONFIG_HEADERS=config.h \ 148 | $(SHELL) ./config.status 149 | @echo timestamp > stamp-h 2> /dev/null 150 | $(srcdir)/config.h.in: $(srcdir)/stamp-h.in 151 | @if test ! -f $@; then \ 152 | rm -f $(srcdir)/stamp-h.in; \ 153 | $(MAKE) $(srcdir)/stamp-h.in; \ 154 | else :; fi 155 | $(srcdir)/stamp-h.in: $(top_srcdir)/configure.ac $(ACLOCAL_M4) 156 | cd $(top_srcdir) && $(AUTOHEADER) 157 | @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null 158 | 159 | mostlyclean-hdr: 160 | 161 | clean-hdr: 162 | 163 | distclean-hdr: 164 | -rm -f config.h 165 | 166 | maintainer-clean-hdr: 167 | 168 | mostlyclean-binPROGRAMS: 169 | 170 | clean-binPROGRAMS: 171 | -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) 172 | 173 | distclean-binPROGRAMS: 174 | 175 | maintainer-clean-binPROGRAMS: 176 | 177 | install-binPROGRAMS: $(bin_PROGRAMS) 178 | @$(NORMAL_INSTALL) 179 | $(mkinstalldirs) $(DESTDIR)$(bindir) 180 | @list='$(bin_PROGRAMS)'; for p in $$list; do \ 181 | if test -f $$p; then \ 182 | echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ 183 | $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ 184 | else :; fi; \ 185 | done 186 | 187 | uninstall-binPROGRAMS: 188 | @$(NORMAL_UNINSTALL) 189 | list='$(bin_PROGRAMS)'; for p in $$list; do \ 190 | rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ 191 | done 192 | 193 | .s.o: 194 | $(COMPILE) -c $< 195 | 196 | .S.o: 197 | $(COMPILE) -c $< 198 | 199 | mostlyclean-compile: 200 | -rm -f *.o core *.core 201 | 202 | clean-compile: 203 | 204 | distclean-compile: 205 | -rm -f *.tab.c 206 | 207 | maintainer-clean-compile: 208 | 209 | tcptraceroute: $(tcptraceroute_OBJECTS) $(tcptraceroute_DEPENDENCIES) 210 | @rm -f tcptraceroute 211 | $(LINK) $(tcptraceroute_LDFLAGS) $(tcptraceroute_OBJECTS) $(tcptraceroute_LDADD) $(LIBS) 212 | 213 | install-man1: 214 | $(mkinstalldirs) $(DESTDIR)$(man1dir) 215 | @list='$(man1_MANS)'; \ 216 | l2='$(man_MANS)'; for i in $$l2; do \ 217 | case "$$i" in \ 218 | *.1*) list="$$list $$i" ;; \ 219 | esac; \ 220 | done; \ 221 | for i in $$list; do \ 222 | if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ 223 | else file=$$i; fi; \ 224 | ext=`echo $$i | sed -e 's/^.*\\.//'`; \ 225 | inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ 226 | inst=`echo $$inst | sed '$(transform)'`.$$ext; \ 227 | echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \ 228 | $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \ 229 | done 230 | 231 | uninstall-man1: 232 | @list='$(man1_MANS)'; \ 233 | l2='$(man_MANS)'; for i in $$l2; do \ 234 | case "$$i" in \ 235 | *.1*) list="$$list $$i" ;; \ 236 | esac; \ 237 | done; \ 238 | for i in $$list; do \ 239 | ext=`echo $$i | sed -e 's/^.*\\.//'`; \ 240 | inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ 241 | inst=`echo $$inst | sed '$(transform)'`.$$ext; \ 242 | echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \ 243 | rm -f $(DESTDIR)$(man1dir)/$$inst; \ 244 | done 245 | install-man: $(MANS) 246 | @$(NORMAL_INSTALL) 247 | $(MAKE) $(AM_MAKEFLAGS) install-man1 248 | uninstall-man: 249 | @$(NORMAL_UNINSTALL) 250 | $(MAKE) $(AM_MAKEFLAGS) uninstall-man1 251 | 252 | install-docDATA: $(doc_DATA) 253 | @$(NORMAL_INSTALL) 254 | $(mkinstalldirs) $(DESTDIR)$(docdir) 255 | @list='$(doc_DATA)'; for p in $$list; do \ 256 | if test -f $(srcdir)/$$p; then \ 257 | echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(docdir)/$$p"; \ 258 | $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(docdir)/$$p; \ 259 | else if test -f $$p; then \ 260 | echo " $(INSTALL_DATA) $$p $(DESTDIR)$(docdir)/$$p"; \ 261 | $(INSTALL_DATA) $$p $(DESTDIR)$(docdir)/$$p; \ 262 | fi; fi; \ 263 | done 264 | 265 | uninstall-docDATA: 266 | @$(NORMAL_UNINSTALL) 267 | list='$(doc_DATA)'; for p in $$list; do \ 268 | rm -f $(DESTDIR)$(docdir)/$$p; \ 269 | done 270 | 271 | tags: TAGS 272 | 273 | ID: $(HEADERS) $(SOURCES) $(LISP) 274 | list='$(SOURCES) $(HEADERS)'; \ 275 | unique=`for i in $$list; do echo $$i; done | \ 276 | awk ' { files[$$0] = 1; } \ 277 | END { for (i in files) print i; }'`; \ 278 | here=`pwd` && cd $(srcdir) \ 279 | && mkid -f$$here/ID $$unique $(LISP) 280 | 281 | TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP) 282 | tags=; \ 283 | here=`pwd`; \ 284 | list='$(SOURCES) $(HEADERS)'; \ 285 | unique=`for i in $$list; do echo $$i; done | \ 286 | awk ' { files[$$0] = 1; } \ 287 | END { for (i in files) print i; }'`; \ 288 | test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ 289 | || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP)) 290 | 291 | mostlyclean-tags: 292 | 293 | clean-tags: 294 | 295 | distclean-tags: 296 | -rm -f TAGS ID 297 | 298 | maintainer-clean-tags: 299 | 300 | distdir = $(PACKAGE)-$(VERSION) 301 | top_distdir = $(distdir) 302 | 303 | # This target untars the dist file and tries a VPATH configuration. Then 304 | # it guarantees that the distribution is self-contained by making another 305 | # tarfile. 306 | distcheck: dist 307 | -rm -rf $(distdir) 308 | GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz 309 | mkdir $(distdir)/=build 310 | mkdir $(distdir)/=inst 311 | dc_install_base=`cd $(distdir)/=inst && pwd`; \ 312 | cd $(distdir)/=build \ 313 | && ../configure --srcdir=.. --prefix=$$dc_install_base \ 314 | && $(MAKE) $(AM_MAKEFLAGS) \ 315 | && $(MAKE) $(AM_MAKEFLAGS) dvi \ 316 | && $(MAKE) $(AM_MAKEFLAGS) check \ 317 | && $(MAKE) $(AM_MAKEFLAGS) install \ 318 | && $(MAKE) $(AM_MAKEFLAGS) installcheck \ 319 | && $(MAKE) $(AM_MAKEFLAGS) dist 320 | -rm -rf $(distdir) 321 | @banner="$(distdir).tar.gz is ready for distribution"; \ 322 | dashes=`echo "$$banner" | sed s/./=/g`; \ 323 | echo "$$dashes"; \ 324 | echo "$$banner"; \ 325 | echo "$$dashes" 326 | dist: distdir 327 | -chmod -R a+r $(distdir) 328 | GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) 329 | -rm -rf $(distdir) 330 | dist-all: distdir 331 | -chmod -R a+r $(distdir) 332 | GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) 333 | -rm -rf $(distdir) 334 | distdir: $(DISTFILES) 335 | -rm -rf $(distdir) 336 | mkdir $(distdir) 337 | -chmod 755 $(distdir) 338 | here=`cd $(top_builddir) && pwd`; \ 339 | top_distdir=`cd $(distdir) && pwd`; \ 340 | distdir=`cd $(distdir) && pwd`; \ 341 | cd $(top_srcdir) \ 342 | && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Makefile 343 | @for file in $(DISTFILES); do \ 344 | d=$(srcdir); \ 345 | if test -d $$d/$$file; then \ 346 | cp -pr $$d/$$file $(distdir)/$$file; \ 347 | else \ 348 | test -f $(distdir)/$$file \ 349 | || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ 350 | || cp -p $$d/$$file $(distdir)/$$file || :; \ 351 | fi; \ 352 | done 353 | 354 | DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) 355 | 356 | -include $(DEP_FILES) 357 | 358 | mostlyclean-depend: 359 | 360 | clean-depend: 361 | 362 | distclean-depend: 363 | -rm -rf .deps 364 | 365 | maintainer-clean-depend: 366 | 367 | %.o: %.c 368 | @echo '$(COMPILE) -c $<'; \ 369 | $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< 370 | @-cp .deps/$(*F).pp .deps/$(*F).P; \ 371 | tr ' ' '\012' < .deps/$(*F).pp \ 372 | | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ 373 | >> .deps/$(*F).P; \ 374 | rm .deps/$(*F).pp 375 | 376 | %.lo: %.c 377 | @echo '$(LTCOMPILE) -c $<'; \ 378 | $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< 379 | @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ 380 | < .deps/$(*F).pp > .deps/$(*F).P; \ 381 | tr ' ' '\012' < .deps/$(*F).pp \ 382 | | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ 383 | >> .deps/$(*F).P; \ 384 | rm -f .deps/$(*F).pp 385 | info-am: 386 | info: info-am 387 | dvi-am: 388 | dvi: dvi-am 389 | check-am: all-am 390 | check: check-am 391 | installcheck-am: 392 | installcheck: installcheck-am 393 | all-recursive-am: config.h 394 | $(MAKE) $(AM_MAKEFLAGS) all-recursive 395 | 396 | install-exec-am: install-binPROGRAMS 397 | install-exec: install-exec-am 398 | 399 | install-data-am: install-man install-docDATA 400 | install-data: install-data-am 401 | 402 | install-am: all-am 403 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 404 | install: install-am 405 | uninstall-am: uninstall-binPROGRAMS uninstall-man uninstall-docDATA 406 | uninstall: uninstall-am 407 | all-am: Makefile $(PROGRAMS) $(MANS) $(DATA) config.h 408 | all-redirect: all-am 409 | install-strip: 410 | $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install 411 | installdirs: 412 | $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1 \ 413 | $(DESTDIR)$(docdir) 414 | 415 | 416 | mostlyclean-generic: 417 | 418 | clean-generic: 419 | 420 | distclean-generic: 421 | -rm -f Makefile $(CONFIG_CLEAN_FILES) 422 | -rm -f config.cache config.log stamp-h stamp-h[0-9]* 423 | 424 | maintainer-clean-generic: 425 | mostlyclean-am: mostlyclean-hdr mostlyclean-binPROGRAMS \ 426 | mostlyclean-compile mostlyclean-tags mostlyclean-depend \ 427 | mostlyclean-generic 428 | 429 | mostlyclean: mostlyclean-am 430 | 431 | clean-am: clean-hdr clean-binPROGRAMS clean-compile clean-tags \ 432 | clean-depend clean-generic mostlyclean-am 433 | 434 | clean: clean-am 435 | 436 | distclean-am: distclean-hdr distclean-binPROGRAMS distclean-compile \ 437 | distclean-tags distclean-depend distclean-generic \ 438 | clean-am 439 | 440 | distclean: distclean-am 441 | -rm -f config.status 442 | 443 | maintainer-clean-am: maintainer-clean-hdr maintainer-clean-binPROGRAMS \ 444 | maintainer-clean-compile maintainer-clean-tags \ 445 | maintainer-clean-depend maintainer-clean-generic \ 446 | distclean-am 447 | @echo "This command is intended for maintainers to use;" 448 | @echo "it deletes files that may require special tools to rebuild." 449 | 450 | maintainer-clean: maintainer-clean-am 451 | -rm -f config.status 452 | 453 | .PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ 454 | mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ 455 | maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ 456 | mostlyclean-compile distclean-compile clean-compile \ 457 | maintainer-clean-compile install-man1 uninstall-man1 install-man \ 458 | uninstall-man uninstall-docDATA install-docDATA tags mostlyclean-tags \ 459 | distclean-tags clean-tags maintainer-clean-tags distdir \ 460 | mostlyclean-depend distclean-depend clean-depend \ 461 | maintainer-clean-depend info-am info dvi-am dvi check check-am \ 462 | installcheck-am installcheck all-recursive-am install-exec-am \ 463 | install-exec install-data-am install-data install-am install \ 464 | uninstall-am uninstall all-redirect all-am all installdirs \ 465 | mostlyclean-generic distclean-generic clean-generic \ 466 | maintainer-clean-generic clean mostlyclean distclean maintainer-clean 467 | 468 | 469 | # AM_CFLAGS = @AM_CFLAGS@ 470 | 471 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 472 | # Otherwise a system limit (for SysV at least) may be exceeded. 473 | .NOEXPORT: 474 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | See the ChangeLog file for recent news. 2 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | tcptraceroute -- A traceroute implementation using TCP packets 2 | Copyright (c) 2001-2015 Michael C. Toren 3 | 4 | Updates are available from 5 | 6 | Requires libnet and libpcap 7 | . For compilation instructions, see the 8 | INSTALL file. 9 | 10 | This program is free software; you can redistribute it and/or modify it 11 | under the terms of the GNU General Public License, version 2, as published 12 | by the Free Software Foundation. 13 | 14 | This program is distributed in the hope that it will be useful, but 15 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 | for more details. 18 | 19 | A copy of the GNU GPL is available as /usr/doc/copyright/GPL on Debian 20 | systems, or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html 21 | You can also obtain it by writing to the Free Software Foundation, Inc., 22 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 23 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 1.5beta7 2 | -------------------------------------------------------------------------------- /capture.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: c; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4; -*- */ 2 | /* vim:set ts=4 sw=4 ai nobackup nocindent sm: */ 3 | 4 | /* 5 | * tcptraceroute -- A traceroute implementation using TCP packets 6 | * Copyright (c) 2001-2015 Michael C. Toren 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License, version 2, as published 10 | * by the Free Software Foundation. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | * for more details. 16 | * 17 | * A copy of the GNU GPL is available as /usr/doc/copyright/GPL on Debian 18 | * systems, or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html 19 | * You can also obtain it by writing to the Free Software Foundation, Inc., 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 21 | */ 22 | 23 | #include "tcptraceroute.h" 24 | 25 | pcap_t *pcap; 26 | int pcap_fd; 27 | 28 | /* 29 | * Open the pcap listening device and apply our filter. 30 | */ 31 | 32 | void initcapture(void) 33 | { 34 | struct bpf_program fcode; 35 | bpf_u_int32 localnet, netmask; 36 | 37 | if (! (pcap = pcap_open_live(device, offset + SNAPLEN, 0, 10, errbuf))) 38 | fatal("pcap_open_live failed: %s", errbuf); 39 | 40 | safe_snprintf(filter, TEXTSIZE, "\n\ 41 | (tcp and src host %s and src port %d and dst host %s)\n\ 42 | or ((icmp[0] == 11 or icmp[0] == 3) and dst host %s)", 43 | iptos(dst_ip), dst_prt, iptos(src_ip), iptos(src_ip)); 44 | 45 | if (o_nofilter) 46 | filter[0] = '\0'; 47 | 48 | debug("pcap filter is: %s\n", o_nofilter ? "(nothing)" : filter); 49 | 50 | if (pcap_lookupnet(device, &localnet, &netmask, errbuf) < 0) 51 | { 52 | warn("pcap_lookupnet failed: %s\n", errbuf); 53 | localnet = 0; 54 | netmask = 0; 55 | } 56 | 57 | if (pcap_compile(pcap, &fcode, filter, 1, netmask) < 0) 58 | fatal("filter compile failed: %s", pcap_geterr(pcap)); 59 | 60 | if (pcap_setfilter(pcap, &fcode) < 0) 61 | fatal("pcap_setfilter failed\n"); 62 | 63 | pcap_fd = pcap_fileno(pcap); 64 | 65 | if (pcap_fd > 100) 66 | fatal("Sorry, pcap_fd (%d) is too high. Why are there so many open file descriptors?\n", 67 | pcap_fd); 68 | 69 | if (fcntl(pcap_fd, F_SETFL, O_NONBLOCK) < 0) 70 | pfatal("fcntl(F_SETFL, O_NONBLOCK) failed"); 71 | 72 | pcap_freecode(&fcode); 73 | } 74 | 75 | /* 76 | * Horrible macro kludge only to be called from capture(), for architectures 77 | * such as sparc that don't permit non-aligned memory access. The idea is to 78 | * malloc new space (which is guaranteed to be properly aligned), copy the 79 | * packet we want to parse there, then cast the packet header struct against 80 | * the new, aligned space. 81 | */ 82 | 83 | #define ALIGN_PACKET(dest, cast, offset) do { \ 84 | static u_char *buf; \ 85 | if (buf == NULL) buf = xrealloc(NULL, SNAPLEN - (offset)); \ 86 | memcpy(buf, packet + (offset), len - (offset)); \ 87 | dest = (struct cast *)buf; \ 88 | } while (0) /* no semi-colon */ 89 | 90 | /* 91 | * Listens for responses to our probe matching the specified proberecord 92 | * structure. Returns 1 if the destination was reached, or 0 if we need 93 | * to increment the TTL some more. 94 | */ 95 | 96 | int capture(proberecord *record) 97 | { 98 | u_char *packet; 99 | struct pcap_pkthdr packet_hdr; 100 | struct libnet_ipv4_hdr *ip_hdr; 101 | struct timeval start, now, timepassed, timeout_tv, timeleft; 102 | int firstpass, ret, len; 103 | double delta; 104 | fd_set sfd; 105 | 106 | firstpass = 1; 107 | timeout_tv.tv_sec = o_timeout; 108 | timeout_tv.tv_usec = 0; 109 | 110 | if (gettimeofday(&start, NULL) < 0) 111 | pfatal("gettimeofday"); 112 | 113 | for(;;) 114 | { 115 | if (firstpass) 116 | { 117 | firstpass = 0; 118 | timeleft = timeout_tv; 119 | } 120 | else 121 | { 122 | if (gettimeofday(&now, NULL) < 0) 123 | pfatal("gettimeofday"); 124 | 125 | timepassed = tvdiff(&now, &start); 126 | 127 | if (tvsign(&timepassed) < 0) 128 | { 129 | /* Deal with weird clock skew */ 130 | timepassed.tv_sec = 0; 131 | timepassed.tv_usec = 0; 132 | } 133 | 134 | timeleft = tvdiff(&timeout_tv, &timepassed); 135 | 136 | if (tvsign(&timeleft) <= 0) 137 | { 138 | debug("timeout\n"); 139 | return 0; 140 | } 141 | } 142 | 143 | /* 144 | * The libpcap documentation is wrong; pcap_fileno actually 145 | * returns the fd of the live capture device, not the save 146 | * file. References: 147 | * 148 | * http://www.tcpdump.org/lists/workers/2001/01/msg00223.html 149 | * http://www.tcpdump.org/lists/workers/2001/03/msg00107.html 150 | * http://www.tcpdump.org/lists/workers/2001/03/msg00109.html 151 | * http://www.tcpdump.org/lists/workers/2001/03/msg00110.html 152 | */ 153 | 154 | FD_ZERO(&sfd); 155 | FD_SET(pcap_fd, &sfd); 156 | 157 | ret = o_noselect ? 1 : select(pcap_fd + 1, &sfd, NULL, NULL, &timeleft); 158 | 159 | if (ret < 0) 160 | { 161 | fatal("select"); 162 | } 163 | else if (ret == 0) 164 | { 165 | debug("select() timeout\n"); 166 | continue; 167 | } 168 | 169 | if ((packet = (u_char *)pcap_next(pcap, &packet_hdr)) == NULL) 170 | { 171 | debug("null pointer from pcap_next()\n"); 172 | continue; 173 | } 174 | 175 | packet += offset; 176 | len = packet_hdr.caplen - offset; 177 | 178 | debug("received %d byte IP packet from pcap_next()\n", len); 179 | 180 | if (len < LIBNET_IPV4_H) 181 | { 182 | debug("Ignoring partial IP packet\n"); 183 | continue; 184 | } 185 | 186 | if (len > SNAPLEN) 187 | { 188 | debug("Packet received is larger than our snaplen (%d)? Ignoring\n", SNAPLEN); 189 | continue; 190 | } 191 | 192 | ALIGN_PACKET(ip_hdr, libnet_ipv4_hdr, 0); 193 | 194 | if (ip_hdr->ip_v != 4) 195 | { 196 | debug("Ignoring non-IPv4 packet\n"); 197 | continue; 198 | } 199 | 200 | if (ip_hdr->ip_hl > 5) 201 | { 202 | debug("Ignoring IP packet with IP options\n"); 203 | continue; 204 | } 205 | 206 | if (ip_hdr->ip_dst.s_addr != src_ip) 207 | { 208 | debug("Ignoring IP packet not addressed to us (%s, not %s)\n", 209 | iptos(ip_hdr->ip_dst.s_addr), iptos(src_ip)); 210 | continue; 211 | } 212 | 213 | delta = (double)(packet_hdr.ts.tv_sec - record->timestamp.tv_sec) * 1000 + 214 | (double)(packet_hdr.ts.tv_usec - record->timestamp.tv_usec) / 1000; 215 | 216 | if (ip_hdr->ip_p == IPPROTO_ICMP) 217 | { 218 | struct libnet_icmpv4_hdr *icmp_hdr; 219 | struct libnet_ipv4_hdr *old_ip_hdr; 220 | struct libnet_tcp_hdr *old_tcp_hdr; 221 | 222 | if (len < LIBNET_IPV4_H + LIBNET_ICMPV4_H + 4) 223 | { 224 | debug("Ignoring partial ICMP packet\n"); 225 | continue; 226 | } 227 | 228 | ALIGN_PACKET(icmp_hdr, libnet_icmpv4_hdr, 0 + LIBNET_IPV4_H); 229 | debug("Received ICMP packet\n"); 230 | 231 | /* 232 | * The IP header, plus eight bytes of it's payload that generated 233 | * the ICMP packet is quoted here, prepended with four bytes of 234 | * padding. 235 | */ 236 | 237 | if (len < LIBNET_IPV4_H + LIBNET_ICMPV4_H + 4 + LIBNET_IPV4_H + 8) 238 | { 239 | debug("Ignoring ICMP with incomplete payload\n"); 240 | continue; 241 | } 242 | 243 | ALIGN_PACKET(old_ip_hdr, libnet_ipv4_hdr, 244 | 0 + LIBNET_IPV4_H + LIBNET_ICMPV4_H + 4); 245 | 246 | /* 247 | * The entire TCP header isn't here, but the source port, 248 | * destination port, and sequence number fields are. 249 | */ 250 | 251 | ALIGN_PACKET(old_tcp_hdr, libnet_tcp_hdr, 252 | 0 + LIBNET_IPV4_H + LIBNET_ICMPV4_H + 4 + LIBNET_IPV4_H); 253 | 254 | if (old_ip_hdr->ip_v != 4) 255 | { 256 | debug("Ignoring ICMP which quotes a non-IPv4 packet\n"); 257 | continue; 258 | } 259 | 260 | if (old_ip_hdr->ip_hl > 5) 261 | { 262 | debug("Ignoring ICMP which quotes an IP packet with IP options\n"); 263 | continue; 264 | } 265 | 266 | if (old_ip_hdr->ip_src.s_addr != src_ip) 267 | { 268 | debug("Ignoring ICMP with incorrect quoted source (%s, not %s)\n", 269 | iptos(old_ip_hdr->ip_src.s_addr), iptos(src_ip)); 270 | continue; 271 | } 272 | 273 | /* These are not the droids you are looking for */ 274 | if (old_ip_hdr->ip_p != IPPROTO_TCP) 275 | { 276 | debug("Ignoring ICMP which doesn't quote a TCP header\n"); 277 | continue; 278 | } 279 | 280 | /* We are free to go about our business */ 281 | if (! o_trackport && (ntohs(old_ip_hdr->ip_id) != record->id)) 282 | { 283 | debug("Ignoring ICMP which doesn't contain the IPID we sent\n"); 284 | continue; 285 | } 286 | 287 | /* Move along, move along */ 288 | if (ntohs(old_tcp_hdr->th_sport) != record->src_prt) 289 | { 290 | debug("Ignoring ICMP which doesn't quote the correct TCP source port\n"); 291 | continue; 292 | } 293 | 294 | if (ntohs(old_tcp_hdr->th_dport) != dst_prt) 295 | { 296 | /* Very strict checking, no DNAT detection */ 297 | if (o_dnat < 0) 298 | { 299 | debug("Ignoring ICMP which doesn't quote the correct TCP destination port\n"); 300 | continue; 301 | } 302 | 303 | /* DNAT detection */ 304 | if (o_dnat > 0) 305 | record->dnat_dport = old_tcp_hdr->th_dport; 306 | } 307 | 308 | if (icmp_hdr->icmp_type == ICMP_UNREACH) 309 | { 310 | char s[TEXTSIZE]; 311 | 312 | switch(icmp_hdr->icmp_code) 313 | { 314 | case ICMP_UNREACH_NET: 315 | safe_strncpy(s, "!N", TEXTSIZE); break; 316 | 317 | case ICMP_UNREACH_HOST: 318 | safe_strncpy(s, "!H", TEXTSIZE); break; 319 | 320 | case ICMP_UNREACH_PROTOCOL: 321 | safe_strncpy(s, "!P", TEXTSIZE); break; 322 | 323 | case ICMP_UNREACH_PORT: 324 | safe_strncpy(s, "!p", TEXTSIZE); break; 325 | 326 | case ICMP_UNREACH_NEEDFRAG: 327 | safe_strncpy(s, "!F", TEXTSIZE); break; 328 | 329 | case ICMP_UNREACH_SRCFAIL: 330 | safe_strncpy(s, "!S", TEXTSIZE); break; 331 | 332 | case ICMP_UNREACH_NET_PROHIB: 333 | case ICMP_UNREACH_FILTER_PROHIB: 334 | safe_strncpy(s, "!A", TEXTSIZE); break; 335 | 336 | case ICMP_UNREACH_HOST_PROHIB: 337 | safe_strncpy(s, "!C", TEXTSIZE); break; 338 | 339 | case ICMP_UNREACH_NET_UNKNOWN: 340 | case ICMP_UNREACH_HOST_UNKNOWN: 341 | safe_strncpy(s, "!U", TEXTSIZE); break; 342 | 343 | case ICMP_UNREACH_ISOLATED: 344 | safe_strncpy(s, "!I", TEXTSIZE); break; 345 | 346 | case ICMP_UNREACH_TOSNET: 347 | case ICMP_UNREACH_TOSHOST: 348 | safe_strncpy(s, "!T", TEXTSIZE); break; 349 | 350 | case ICMP_UNREACH_HOST_PRECEDENCE: 351 | case ICMP_UNREACH_PRECEDENCE_CUTOFF: 352 | default: 353 | safe_snprintf(s, TEXTSIZE, "!<%d>", icmp_hdr->icmp_code); 354 | } 355 | 356 | record->delta = delta; 357 | record->addr = ip_hdr->ip_src.s_addr; 358 | safe_snprintf(record->string, TEXTSIZE, "%%.3f ms %s", s); 359 | return 1; 360 | } 361 | 362 | if (icmp_hdr->icmp_type == ICMP_TIMXCEED) 363 | { 364 | /* If all of the fields of the IP, ICMP, quoted IP, and 365 | * quoted IP payload are consistent with the probe packet we 366 | * sent, yet the quoted destination address is different than 367 | * the address we're trying to reach, it's likely the 368 | * preceding hop was performing DNAT. 369 | */ 370 | 371 | if (old_ip_hdr->ip_dst.s_addr != dst_ip) 372 | { 373 | /* Very strict checking, no DNAT detection */ 374 | if (o_dnat < 0) 375 | { 376 | debug("Ignoring ICMP with incorrect quoted destination (%s, not %s)\n", 377 | iptos(old_ip_hdr->ip_dst.s_addr), iptos(dst_ip)); 378 | continue; 379 | } 380 | 381 | /* DNAT detection */ 382 | if (o_dnat > 0) 383 | record->dnat_ip = old_ip_hdr->ip_dst.s_addr; 384 | } 385 | 386 | record->delta = delta; 387 | record->addr = ip_hdr->ip_src.s_addr; 388 | safe_strncpy(record->string, "%.3f ms", TEXTSIZE); 389 | return 0; 390 | } 391 | 392 | if (icmp_hdr->icmp_type != ICMP_TIMXCEED && 393 | icmp_hdr->icmp_type != ICMP_UNREACH) 394 | { 395 | record->delta = delta; 396 | record->addr = ip_hdr->ip_src.s_addr; 397 | safe_strncpy(record->string, "%.3f ms -- Unexpected ICMP", TEXTSIZE); 398 | return 0; 399 | } 400 | 401 | fatal("Something bad happened\n"); 402 | } 403 | 404 | if (ip_hdr->ip_p == IPPROTO_TCP) 405 | { 406 | struct libnet_tcp_hdr *tcp_hdr; 407 | debug("Received TCP packet\n"); 408 | 409 | if (ip_hdr->ip_src.s_addr != dst_ip) 410 | { 411 | debug("Ignoring TCP from source (%s) different than target (%s)\n", 412 | iptos(ip_hdr->ip_src.s_addr), iptos(dst_ip)); 413 | continue; 414 | } 415 | 416 | if (len < LIBNET_IPV4_H + LIBNET_TCP_H) 417 | { 418 | debug("Ignoring partial TCP packet\n"); 419 | continue; 420 | } 421 | 422 | ALIGN_PACKET(tcp_hdr, libnet_tcp_hdr, 0 + LIBNET_IPV4_H); 423 | 424 | debug("Received TCP packet %s:%d -> %s:%d, flags %s%s%s%s%s%s%s%s%s\n", 425 | iptos(ip_hdr->ip_src.s_addr), ntohs(tcp_hdr->th_sport), 426 | iptos(ip_hdr->ip_dst.s_addr), ntohs(tcp_hdr->th_dport), 427 | tcp_hdr->th_flags & TH_RST ? "RST " : "", 428 | tcp_hdr->th_flags & TH_SYN ? "SYN " : "", 429 | tcp_hdr->th_flags & TH_ACK ? "ACK " : "", 430 | tcp_hdr->th_flags & TH_PUSH ? "PSH " : "", 431 | tcp_hdr->th_flags & TH_FIN ? "FIN " : "", 432 | tcp_hdr->th_flags & TH_URG ? "URG " : "", 433 | tcp_hdr->th_flags & TH_CWR ? "CWR " : "", 434 | tcp_hdr->th_flags & TH_ECN ? "ECN " : "", 435 | tcp_hdr->th_flags ? "" : "(none)"); 436 | 437 | if ((ntohs(tcp_hdr->th_sport) != dst_prt) 438 | || (ntohs(tcp_hdr->th_dport) != record->src_prt)) 439 | { 440 | debug("Ignoring TCP which doesn't match the correct port numbers\n"); 441 | continue; 442 | } 443 | 444 | if (tcp_hdr->th_flags & TH_RST) 445 | safe_strncpy(record->state, "closed", TEXTSIZE); 446 | 447 | else if ((tcp_hdr->th_flags & TH_SYN) 448 | && (tcp_hdr->th_flags & TH_ACK) 449 | && (tcp_hdr->th_flags & TH_ECN)) 450 | safe_strncpy(record->state, "open, ecn", TEXTSIZE); 451 | 452 | else if ((tcp_hdr->th_flags & TH_SYN) 453 | && (tcp_hdr->th_flags & TH_ACK)) 454 | safe_strncpy(record->state, "open", TEXTSIZE); 455 | 456 | else 457 | safe_snprintf(record->state, TEXTSIZE, "unknown,%s%s%s%s%s%s%s%s%s", 458 | tcp_hdr->th_flags & TH_RST ? " RST" : "", 459 | tcp_hdr->th_flags & TH_SYN ? " SYN" : "", 460 | tcp_hdr->th_flags & TH_ACK ? " ACK" : "", 461 | tcp_hdr->th_flags & TH_PUSH ? " PSH" : "", 462 | tcp_hdr->th_flags & TH_FIN ? " FIN" : "", 463 | tcp_hdr->th_flags & TH_URG ? " URG" : "", 464 | tcp_hdr->th_flags & TH_CWR ? " CWR" : "", 465 | tcp_hdr->th_flags & TH_ECN ? " ECN" : "", 466 | tcp_hdr->th_flags ? "" : " no flags"); 467 | 468 | record->delta = delta; 469 | record->addr = ip_hdr->ip_src.s_addr; 470 | safe_strncpy(record->string, "%.3f ms", TEXTSIZE); 471 | return 1; 472 | } 473 | 474 | debug("Ignoring non-ICMP and non-TCP packet\n"); 475 | continue; 476 | } 477 | } 478 | -------------------------------------------------------------------------------- /capture.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: c; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4; -*- */ 2 | /* vim:set ts=4 sw=4 ai nobackup nocindent sm: */ 3 | 4 | /* 5 | * tcptraceroute -- A traceroute implementation using TCP packets 6 | * Copyright (c) 2001-2015 Michael C. Toren 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License, version 2, as published 10 | * by the Free Software Foundation. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | * for more details. 16 | * 17 | * A copy of the GNU GPL is available as /usr/doc/copyright/GPL on Debian 18 | * systems, or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html 19 | * You can also obtain it by writing to the Free Software Foundation, Inc., 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 21 | */ 22 | 23 | extern pcap_t *pcap; 24 | extern int pcap_fd; 25 | 26 | /* 27 | * How many bytes should we examine on every packet that comes off the 28 | * wire? This doesn't include the link layer which is accounted for 29 | * later. We're looking only for ICMP and TCP packets, so this should 30 | * work. For ICMP, we also examine the quoted IP header, which is why 31 | * there's a *2 there. The +32 is just to be safe. 32 | */ 33 | 34 | #define SNAPLEN (LIBNET_IPV4_H * 2 + \ 35 | (LIBNET_TCP_H > LIBNET_ICMPV4_H ? LIBNET_TCP_H : LIBNET_ICMPV4_H) + 32) 36 | 37 | void initcapture(void); 38 | int capture(proberecord *); 39 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Default destination port */ 4 | #undef DEFAULT_PORT 5 | 6 | /* Define to 1 if you have the header file. */ 7 | #undef HAVE_ARPA_INET_H 8 | 9 | /* Is this a BSDI system? */ 10 | #undef HAVE_BSDI 11 | 12 | /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ 13 | #undef HAVE_DOPRNT 14 | 15 | /* Define to 1 if you have the header file. */ 16 | #undef HAVE_FCNTL_H 17 | 18 | /* Define to 1 if you have the `gettimeofday' function. */ 19 | #undef HAVE_GETTIMEOFDAY 20 | 21 | /* Define to 1 if you have the header file. */ 22 | #undef HAVE_INTTYPES_H 23 | 24 | /* Define to 1 if you have the `inet' library (-linet). */ 25 | #undef HAVE_LIBINET 26 | 27 | /* Define to 1 if you have the `net' library (-lnet). */ 28 | #undef HAVE_LIBNET 29 | 30 | /* Define to 1 if you have the `nsl' library (-lnsl). */ 31 | #undef HAVE_LIBNSL 32 | 33 | /* Define to 1 if you have the `pcap' library (-lpcap). */ 34 | #undef HAVE_LIBPCAP 35 | 36 | /* Define to 1 if you have the `resolv' library (-lresolv). */ 37 | #undef HAVE_LIBRESOLV 38 | 39 | /* Define to 1 if you have the `socket' library (-lsocket). */ 40 | #undef HAVE_LIBSOCKET 41 | 42 | /* Is this a MacOS X system? */ 43 | #undef HAVE_MACOSX 44 | 45 | /* Define to 1 if your system has a GNU libc compatible `malloc' function, and 46 | to 0 otherwise. */ 47 | #undef HAVE_MALLOC 48 | 49 | /* Define to 1 if you have the header file. */ 50 | #undef HAVE_MEMORY_H 51 | 52 | /* Define to 1 if you have the `memset' function. */ 53 | #undef HAVE_MEMSET 54 | 55 | /* Is this a NetBSD system? */ 56 | #undef HAVE_NETBSD 57 | 58 | /* Define to 1 if you have the header file. */ 59 | #undef HAVE_NETDB_H 60 | 61 | /* Define to 1 if you have the header file. */ 62 | #undef HAVE_NETINET_IN_H 63 | 64 | /* Define to 1 if you have the `select' function. */ 65 | #undef HAVE_SELECT 66 | 67 | /* Has socket.sa_len */ 68 | #undef HAVE_SOCKADDR_SA_LEN 69 | 70 | /* Define to 1 if you have the `socket' function. */ 71 | #undef HAVE_SOCKET 72 | 73 | /* Is this a Solaris system? */ 74 | #undef HAVE_SOLARIS 75 | 76 | /* Define to 1 if you have the header file. */ 77 | #undef HAVE_STDINT_H 78 | 79 | /* Define to 1 if you have the header file. */ 80 | #undef HAVE_STDLIB_H 81 | 82 | /* Define to 1 if you have the `strchr' function. */ 83 | #undef HAVE_STRCHR 84 | 85 | /* Define to 1 if you have the header file. */ 86 | #undef HAVE_STRINGS_H 87 | 88 | /* Define to 1 if you have the header file. */ 89 | #undef HAVE_STRING_H 90 | 91 | /* Define to 1 if you have the header file. */ 92 | #undef HAVE_SYS_IOCTL_H 93 | 94 | /* Define to 1 if you have the header file. */ 95 | #undef HAVE_SYS_SELECT_H 96 | 97 | /* Define to 1 if you have the header file. */ 98 | #undef HAVE_SYS_SOCKET_H 99 | 100 | /* Define to 1 if you have the header file. */ 101 | #undef HAVE_SYS_STAT_H 102 | 103 | /* Define to 1 if you have the header file. */ 104 | #undef HAVE_SYS_TYPES_H 105 | 106 | /* Define to 1 if you have the header file. */ 107 | #undef HAVE_UNISTD_H 108 | 109 | /* Define to 1 if you have the `vprintf' function. */ 110 | #undef HAVE_VPRINTF 111 | 112 | /* libnet API version */ 113 | #undef LIBNET_API_VERSION 114 | 115 | /* Use select(2) by default? */ 116 | #undef NOSELECT_DEFAULT 117 | 118 | /* Name of package */ 119 | #undef PACKAGE 120 | 121 | /* Define to the address where bug reports for this package should be sent. */ 122 | #undef PACKAGE_BUGREPORT 123 | 124 | /* Define to the full name of this package. */ 125 | #undef PACKAGE_NAME 126 | 127 | /* Define to the full name and version of this package. */ 128 | #undef PACKAGE_STRING 129 | 130 | /* Define to the one symbol short name of this package. */ 131 | #undef PACKAGE_TARNAME 132 | 133 | /* Define to the home page for this package. */ 134 | #undef PACKAGE_URL 135 | 136 | /* Define to the version of this package. */ 137 | #undef PACKAGE_VERSION 138 | 139 | /* Define to the type of arg 1 for `select'. */ 140 | #undef SELECT_TYPE_ARG1 141 | 142 | /* Define to the type of args 2, 3 and 4 for `select'. */ 143 | #undef SELECT_TYPE_ARG234 144 | 145 | /* Define to the type of arg 5 for `select'. */ 146 | #undef SELECT_TYPE_ARG5 147 | 148 | /* Define to 1 if you have the ANSI C header files. */ 149 | #undef STDC_HEADERS 150 | 151 | /* Target platform */ 152 | #undef TARGET 153 | 154 | /* Define to 1 if you can safely include both and . */ 155 | #undef TIME_WITH_SYS_TIME 156 | 157 | /* Track ports by default */ 158 | #undef TRACK_PORT_DEFAULT 159 | 160 | /* Version number of package */ 161 | #undef VERSION 162 | 163 | /* Define to rpl_malloc if the replacement function should be used. */ 164 | #undef malloc 165 | -------------------------------------------------------------------------------- /config.sub: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Configuration validation subroutine script. 3 | # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 4 | # 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 5 | 6 | timestamp='2003-05-09' 7 | 8 | # This file is (in principle) common to ALL GNU software. 9 | # The presence of a machine in this file suggests that SOME GNU software 10 | # can handle that machine. It does not imply ALL GNU software can. 11 | # 12 | # This file is free software; you can redistribute it and/or modify 13 | # it under the terms of the GNU General Public License as published by 14 | # the Free Software Foundation; either version 2 of the License, or 15 | # (at your option) any later version. 16 | # 17 | # This program is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, write to the Free Software 24 | # Foundation, Inc., 59 Temple Place - Suite 330, 25 | # Boston, MA 02111-1307, USA. 26 | 27 | # As a special exception to the GNU General Public License, if you 28 | # distribute this file as part of a program that contains a 29 | # configuration script generated by Autoconf, you may include it under 30 | # the same distribution terms that you use for the rest of that program. 31 | 32 | # Please send patches to . Submit a context 33 | # diff and a properly formatted ChangeLog entry. 34 | # 35 | # Configuration subroutine to validate and canonicalize a configuration type. 36 | # Supply the specified configuration type as an argument. 37 | # If it is invalid, we print an error message on stderr and exit with code 1. 38 | # Otherwise, we print the canonical config type on stdout and succeed. 39 | 40 | # This file is supposed to be the same for all GNU packages 41 | # and recognize all the CPU types, system types and aliases 42 | # that are meaningful with *any* GNU software. 43 | # Each package is responsible for reporting which valid configurations 44 | # it does not support. The user should be able to distinguish 45 | # a failure to support a valid configuration from a meaningless 46 | # configuration. 47 | 48 | # The goal of this file is to map all the various variations of a given 49 | # machine specification into a single specification in the form: 50 | # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM 51 | # or in some cases, the newer four-part form: 52 | # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM 53 | # It is wrong to echo any other type of specification. 54 | 55 | me=`echo "$0" | sed -e 's,.*/,,'` 56 | 57 | usage="\ 58 | Usage: $0 [OPTION] CPU-MFR-OPSYS 59 | $0 [OPTION] ALIAS 60 | 61 | Canonicalize a configuration name. 62 | 63 | Operation modes: 64 | -h, --help print this help, then exit 65 | -t, --time-stamp print date of last modification, then exit 66 | -v, --version print version number, then exit 67 | 68 | Report bugs and patches to ." 69 | 70 | version="\ 71 | GNU config.sub ($timestamp) 72 | 73 | Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 74 | Free Software Foundation, Inc. 75 | 76 | This is free software; see the source for copying conditions. There is NO 77 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." 78 | 79 | help=" 80 | Try \`$me --help' for more information." 81 | 82 | # Parse command line 83 | while test $# -gt 0 ; do 84 | case $1 in 85 | --time-stamp | --time* | -t ) 86 | echo "$timestamp" ; exit 0 ;; 87 | --version | -v ) 88 | echo "$version" ; exit 0 ;; 89 | --help | --h* | -h ) 90 | echo "$usage"; exit 0 ;; 91 | -- ) # Stop option processing 92 | shift; break ;; 93 | - ) # Use stdin as input. 94 | break ;; 95 | -* ) 96 | echo "$me: invalid option $1$help" 97 | exit 1 ;; 98 | 99 | *local*) 100 | # First pass through any local machine types. 101 | echo $1 102 | exit 0;; 103 | 104 | * ) 105 | break ;; 106 | esac 107 | done 108 | 109 | case $# in 110 | 0) echo "$me: missing argument$help" >&2 111 | exit 1;; 112 | 1) ;; 113 | *) echo "$me: too many arguments$help" >&2 114 | exit 1;; 115 | esac 116 | 117 | # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). 118 | # Here we must recognize all the valid KERNEL-OS combinations. 119 | maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` 120 | case $maybe_os in 121 | nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) 122 | os=-$maybe_os 123 | basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` 124 | ;; 125 | *) 126 | basic_machine=`echo $1 | sed 's/-[^-]*$//'` 127 | if [ $basic_machine != $1 ] 128 | then os=`echo $1 | sed 's/.*-/-/'` 129 | else os=; fi 130 | ;; 131 | esac 132 | 133 | ### Let's recognize common machines as not being operating systems so 134 | ### that things like config.sub decstation-3100 work. We also 135 | ### recognize some manufacturers as not being operating systems, so we 136 | ### can provide default operating systems below. 137 | case $os in 138 | -sun*os*) 139 | # Prevent following clause from handling this invalid input. 140 | ;; 141 | -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ 142 | -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ 143 | -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ 144 | -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ 145 | -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ 146 | -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ 147 | -apple | -axis) 148 | os= 149 | basic_machine=$1 150 | ;; 151 | -sim | -cisco | -oki | -wec | -winbond) 152 | os= 153 | basic_machine=$1 154 | ;; 155 | -scout) 156 | ;; 157 | -wrs) 158 | os=-vxworks 159 | basic_machine=$1 160 | ;; 161 | -chorusos*) 162 | os=-chorusos 163 | basic_machine=$1 164 | ;; 165 | -chorusrdb) 166 | os=-chorusrdb 167 | basic_machine=$1 168 | ;; 169 | -hiux*) 170 | os=-hiuxwe2 171 | ;; 172 | -sco5) 173 | os=-sco3.2v5 174 | basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` 175 | ;; 176 | -sco4) 177 | os=-sco3.2v4 178 | basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` 179 | ;; 180 | -sco3.2.[4-9]*) 181 | os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` 182 | basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` 183 | ;; 184 | -sco3.2v[4-9]*) 185 | # Don't forget version if it is 3.2v4 or newer. 186 | basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` 187 | ;; 188 | -sco*) 189 | os=-sco3.2v2 190 | basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` 191 | ;; 192 | -udk*) 193 | basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` 194 | ;; 195 | -isc) 196 | os=-isc2.2 197 | basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` 198 | ;; 199 | -clix*) 200 | basic_machine=clipper-intergraph 201 | ;; 202 | -isc*) 203 | basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` 204 | ;; 205 | -lynx*) 206 | os=-lynxos 207 | ;; 208 | -ptx*) 209 | basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` 210 | ;; 211 | -windowsnt*) 212 | os=`echo $os | sed -e 's/windowsnt/winnt/'` 213 | ;; 214 | -psos*) 215 | os=-psos 216 | ;; 217 | -mint | -mint[0-9]*) 218 | basic_machine=m68k-atari 219 | os=-mint 220 | ;; 221 | esac 222 | 223 | # Decode aliases for certain CPU-COMPANY combinations. 224 | case $basic_machine in 225 | # Recognize the basic CPU types without company name. 226 | # Some are omitted here because they have special meanings below. 227 | 1750a | 580 \ 228 | | a29k \ 229 | | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ 230 | | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ 231 | | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ 232 | | clipper \ 233 | | d10v | d30v | dlx | dsp16xx \ 234 | | fr30 | frv \ 235 | | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ 236 | | i370 | i860 | i960 | ia64 \ 237 | | ip2k \ 238 | | m32r | m68000 | m68k | m88k | mcore \ 239 | | mips | mipsbe | mipseb | mipsel | mipsle \ 240 | | mips16 \ 241 | | mips64 | mips64el \ 242 | | mips64vr | mips64vrel \ 243 | | mips64orion | mips64orionel \ 244 | | mips64vr4100 | mips64vr4100el \ 245 | | mips64vr4300 | mips64vr4300el \ 246 | | mips64vr5000 | mips64vr5000el \ 247 | | mipsisa32 | mipsisa32el \ 248 | | mipsisa32r2 | mipsisa32r2el \ 249 | | mipsisa64 | mipsisa64el \ 250 | | mipsisa64sb1 | mipsisa64sb1el \ 251 | | mipsisa64sr71k | mipsisa64sr71kel \ 252 | | mipstx39 | mipstx39el \ 253 | | mn10200 | mn10300 \ 254 | | msp430 \ 255 | | ns16k | ns32k \ 256 | | openrisc | or32 \ 257 | | pdp10 | pdp11 | pj | pjl \ 258 | | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ 259 | | pyramid \ 260 | | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ 261 | | sh64 | sh64le \ 262 | | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ 263 | | strongarm \ 264 | | tahoe | thumb | tic80 | tron \ 265 | | v850 | v850e \ 266 | | we32k \ 267 | | x86 | xscale | xstormy16 | xtensa \ 268 | | z8k) 269 | basic_machine=$basic_machine-unknown 270 | ;; 271 | m6811 | m68hc11 | m6812 | m68hc12) 272 | # Motorola 68HC11/12. 273 | basic_machine=$basic_machine-unknown 274 | os=-none 275 | ;; 276 | m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) 277 | ;; 278 | 279 | # We use `pc' rather than `unknown' 280 | # because (1) that's what they normally are, and 281 | # (2) the word "unknown" tends to confuse beginning users. 282 | i*86 | x86_64) 283 | basic_machine=$basic_machine-pc 284 | ;; 285 | # Object if more than one company name word. 286 | *-*-*) 287 | echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 288 | exit 1 289 | ;; 290 | # Recognize the basic CPU types with company name. 291 | 580-* \ 292 | | a29k-* \ 293 | | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ 294 | | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ 295 | | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ 296 | | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ 297 | | avr-* \ 298 | | bs2000-* \ 299 | | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ 300 | | clipper-* | cydra-* \ 301 | | d10v-* | d30v-* | dlx-* \ 302 | | elxsi-* \ 303 | | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ 304 | | h8300-* | h8500-* \ 305 | | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ 306 | | i*86-* | i860-* | i960-* | ia64-* \ 307 | | ip2k-* \ 308 | | m32r-* \ 309 | | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ 310 | | m88110-* | m88k-* | mcore-* \ 311 | | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ 312 | | mips16-* \ 313 | | mips64-* | mips64el-* \ 314 | | mips64vr-* | mips64vrel-* \ 315 | | mips64orion-* | mips64orionel-* \ 316 | | mips64vr4100-* | mips64vr4100el-* \ 317 | | mips64vr4300-* | mips64vr4300el-* \ 318 | | mips64vr5000-* | mips64vr5000el-* \ 319 | | mipsisa32-* | mipsisa32el-* \ 320 | | mipsisa32r2-* | mipsisa32r2el-* \ 321 | | mipsisa64-* | mipsisa64el-* \ 322 | | mipsisa64sb1-* | mipsisa64sb1el-* \ 323 | | mipsisa64sr71k-* | mipsisa64sr71kel-* \ 324 | | mipstx39-* | mipstx39el-* \ 325 | | msp430-* \ 326 | | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ 327 | | orion-* \ 328 | | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ 329 | | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ 330 | | pyramid-* \ 331 | | romp-* | rs6000-* \ 332 | | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ 333 | | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ 334 | | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ 335 | | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ 336 | | tahoe-* | thumb-* \ 337 | | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ 338 | | tron-* \ 339 | | v850-* | v850e-* | vax-* \ 340 | | we32k-* \ 341 | | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ 342 | | xtensa-* \ 343 | | ymp-* \ 344 | | z8k-*) 345 | ;; 346 | # Recognize the various machine names and aliases which stand 347 | # for a CPU type and a company and sometimes even an OS. 348 | 386bsd) 349 | basic_machine=i386-unknown 350 | os=-bsd 351 | ;; 352 | 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) 353 | basic_machine=m68000-att 354 | ;; 355 | 3b*) 356 | basic_machine=we32k-att 357 | ;; 358 | a29khif) 359 | basic_machine=a29k-amd 360 | os=-udi 361 | ;; 362 | adobe68k) 363 | basic_machine=m68010-adobe 364 | os=-scout 365 | ;; 366 | alliant | fx80) 367 | basic_machine=fx80-alliant 368 | ;; 369 | altos | altos3068) 370 | basic_machine=m68k-altos 371 | ;; 372 | am29k) 373 | basic_machine=a29k-none 374 | os=-bsd 375 | ;; 376 | amd64) 377 | basic_machine=x86_64-pc 378 | ;; 379 | amdahl) 380 | basic_machine=580-amdahl 381 | os=-sysv 382 | ;; 383 | amiga | amiga-*) 384 | basic_machine=m68k-unknown 385 | ;; 386 | amigaos | amigados) 387 | basic_machine=m68k-unknown 388 | os=-amigaos 389 | ;; 390 | amigaunix | amix) 391 | basic_machine=m68k-unknown 392 | os=-sysv4 393 | ;; 394 | apollo68) 395 | basic_machine=m68k-apollo 396 | os=-sysv 397 | ;; 398 | apollo68bsd) 399 | basic_machine=m68k-apollo 400 | os=-bsd 401 | ;; 402 | aux) 403 | basic_machine=m68k-apple 404 | os=-aux 405 | ;; 406 | balance) 407 | basic_machine=ns32k-sequent 408 | os=-dynix 409 | ;; 410 | c90) 411 | basic_machine=c90-cray 412 | os=-unicos 413 | ;; 414 | convex-c1) 415 | basic_machine=c1-convex 416 | os=-bsd 417 | ;; 418 | convex-c2) 419 | basic_machine=c2-convex 420 | os=-bsd 421 | ;; 422 | convex-c32) 423 | basic_machine=c32-convex 424 | os=-bsd 425 | ;; 426 | convex-c34) 427 | basic_machine=c34-convex 428 | os=-bsd 429 | ;; 430 | convex-c38) 431 | basic_machine=c38-convex 432 | os=-bsd 433 | ;; 434 | cray | j90) 435 | basic_machine=j90-cray 436 | os=-unicos 437 | ;; 438 | crds | unos) 439 | basic_machine=m68k-crds 440 | ;; 441 | cris | cris-* | etrax*) 442 | basic_machine=cris-axis 443 | ;; 444 | da30 | da30-*) 445 | basic_machine=m68k-da30 446 | ;; 447 | decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) 448 | basic_machine=mips-dec 449 | ;; 450 | decsystem10* | dec10*) 451 | basic_machine=pdp10-dec 452 | os=-tops10 453 | ;; 454 | decsystem20* | dec20*) 455 | basic_machine=pdp10-dec 456 | os=-tops20 457 | ;; 458 | delta | 3300 | motorola-3300 | motorola-delta \ 459 | | 3300-motorola | delta-motorola) 460 | basic_machine=m68k-motorola 461 | ;; 462 | delta88) 463 | basic_machine=m88k-motorola 464 | os=-sysv3 465 | ;; 466 | dpx20 | dpx20-*) 467 | basic_machine=rs6000-bull 468 | os=-bosx 469 | ;; 470 | dpx2* | dpx2*-bull) 471 | basic_machine=m68k-bull 472 | os=-sysv3 473 | ;; 474 | ebmon29k) 475 | basic_machine=a29k-amd 476 | os=-ebmon 477 | ;; 478 | elxsi) 479 | basic_machine=elxsi-elxsi 480 | os=-bsd 481 | ;; 482 | encore | umax | mmax) 483 | basic_machine=ns32k-encore 484 | ;; 485 | es1800 | OSE68k | ose68k | ose | OSE) 486 | basic_machine=m68k-ericsson 487 | os=-ose 488 | ;; 489 | fx2800) 490 | basic_machine=i860-alliant 491 | ;; 492 | genix) 493 | basic_machine=ns32k-ns 494 | ;; 495 | gmicro) 496 | basic_machine=tron-gmicro 497 | os=-sysv 498 | ;; 499 | go32) 500 | basic_machine=i386-pc 501 | os=-go32 502 | ;; 503 | h3050r* | hiux*) 504 | basic_machine=hppa1.1-hitachi 505 | os=-hiuxwe2 506 | ;; 507 | h8300hms) 508 | basic_machine=h8300-hitachi 509 | os=-hms 510 | ;; 511 | h8300xray) 512 | basic_machine=h8300-hitachi 513 | os=-xray 514 | ;; 515 | h8500hms) 516 | basic_machine=h8500-hitachi 517 | os=-hms 518 | ;; 519 | harris) 520 | basic_machine=m88k-harris 521 | os=-sysv3 522 | ;; 523 | hp300-*) 524 | basic_machine=m68k-hp 525 | ;; 526 | hp300bsd) 527 | basic_machine=m68k-hp 528 | os=-bsd 529 | ;; 530 | hp300hpux) 531 | basic_machine=m68k-hp 532 | os=-hpux 533 | ;; 534 | hp3k9[0-9][0-9] | hp9[0-9][0-9]) 535 | basic_machine=hppa1.0-hp 536 | ;; 537 | hp9k2[0-9][0-9] | hp9k31[0-9]) 538 | basic_machine=m68000-hp 539 | ;; 540 | hp9k3[2-9][0-9]) 541 | basic_machine=m68k-hp 542 | ;; 543 | hp9k6[0-9][0-9] | hp6[0-9][0-9]) 544 | basic_machine=hppa1.0-hp 545 | ;; 546 | hp9k7[0-79][0-9] | hp7[0-79][0-9]) 547 | basic_machine=hppa1.1-hp 548 | ;; 549 | hp9k78[0-9] | hp78[0-9]) 550 | # FIXME: really hppa2.0-hp 551 | basic_machine=hppa1.1-hp 552 | ;; 553 | hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) 554 | # FIXME: really hppa2.0-hp 555 | basic_machine=hppa1.1-hp 556 | ;; 557 | hp9k8[0-9][13679] | hp8[0-9][13679]) 558 | basic_machine=hppa1.1-hp 559 | ;; 560 | hp9k8[0-9][0-9] | hp8[0-9][0-9]) 561 | basic_machine=hppa1.0-hp 562 | ;; 563 | hppa-next) 564 | os=-nextstep3 565 | ;; 566 | hppaosf) 567 | basic_machine=hppa1.1-hp 568 | os=-osf 569 | ;; 570 | hppro) 571 | basic_machine=hppa1.1-hp 572 | os=-proelf 573 | ;; 574 | i370-ibm* | ibm*) 575 | basic_machine=i370-ibm 576 | ;; 577 | # I'm not sure what "Sysv32" means. Should this be sysv3.2? 578 | i*86v32) 579 | basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` 580 | os=-sysv32 581 | ;; 582 | i*86v4*) 583 | basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` 584 | os=-sysv4 585 | ;; 586 | i*86v) 587 | basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` 588 | os=-sysv 589 | ;; 590 | i*86sol2) 591 | basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` 592 | os=-solaris2 593 | ;; 594 | i386mach) 595 | basic_machine=i386-mach 596 | os=-mach 597 | ;; 598 | i386-vsta | vsta) 599 | basic_machine=i386-unknown 600 | os=-vsta 601 | ;; 602 | iris | iris4d) 603 | basic_machine=mips-sgi 604 | case $os in 605 | -irix*) 606 | ;; 607 | *) 608 | os=-irix4 609 | ;; 610 | esac 611 | ;; 612 | isi68 | isi) 613 | basic_machine=m68k-isi 614 | os=-sysv 615 | ;; 616 | m88k-omron*) 617 | basic_machine=m88k-omron 618 | ;; 619 | magnum | m3230) 620 | basic_machine=mips-mips 621 | os=-sysv 622 | ;; 623 | merlin) 624 | basic_machine=ns32k-utek 625 | os=-sysv 626 | ;; 627 | mingw32) 628 | basic_machine=i386-pc 629 | os=-mingw32 630 | ;; 631 | miniframe) 632 | basic_machine=m68000-convergent 633 | ;; 634 | *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) 635 | basic_machine=m68k-atari 636 | os=-mint 637 | ;; 638 | mips3*-*) 639 | basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` 640 | ;; 641 | mips3*) 642 | basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown 643 | ;; 644 | mmix*) 645 | basic_machine=mmix-knuth 646 | os=-mmixware 647 | ;; 648 | monitor) 649 | basic_machine=m68k-rom68k 650 | os=-coff 651 | ;; 652 | morphos) 653 | basic_machine=powerpc-unknown 654 | os=-morphos 655 | ;; 656 | msdos) 657 | basic_machine=i386-pc 658 | os=-msdos 659 | ;; 660 | mvs) 661 | basic_machine=i370-ibm 662 | os=-mvs 663 | ;; 664 | ncr3000) 665 | basic_machine=i486-ncr 666 | os=-sysv4 667 | ;; 668 | netbsd386) 669 | basic_machine=i386-unknown 670 | os=-netbsd 671 | ;; 672 | netwinder) 673 | basic_machine=armv4l-rebel 674 | os=-linux 675 | ;; 676 | news | news700 | news800 | news900) 677 | basic_machine=m68k-sony 678 | os=-newsos 679 | ;; 680 | news1000) 681 | basic_machine=m68030-sony 682 | os=-newsos 683 | ;; 684 | news-3600 | risc-news) 685 | basic_machine=mips-sony 686 | os=-newsos 687 | ;; 688 | necv70) 689 | basic_machine=v70-nec 690 | os=-sysv 691 | ;; 692 | next | m*-next ) 693 | basic_machine=m68k-next 694 | case $os in 695 | -nextstep* ) 696 | ;; 697 | -ns2*) 698 | os=-nextstep2 699 | ;; 700 | *) 701 | os=-nextstep3 702 | ;; 703 | esac 704 | ;; 705 | nh3000) 706 | basic_machine=m68k-harris 707 | os=-cxux 708 | ;; 709 | nh[45]000) 710 | basic_machine=m88k-harris 711 | os=-cxux 712 | ;; 713 | nindy960) 714 | basic_machine=i960-intel 715 | os=-nindy 716 | ;; 717 | mon960) 718 | basic_machine=i960-intel 719 | os=-mon960 720 | ;; 721 | nonstopux) 722 | basic_machine=mips-compaq 723 | os=-nonstopux 724 | ;; 725 | np1) 726 | basic_machine=np1-gould 727 | ;; 728 | nv1) 729 | basic_machine=nv1-cray 730 | os=-unicosmp 731 | ;; 732 | nsr-tandem) 733 | basic_machine=nsr-tandem 734 | ;; 735 | op50n-* | op60c-*) 736 | basic_machine=hppa1.1-oki 737 | os=-proelf 738 | ;; 739 | or32 | or32-*) 740 | basic_machine=or32-unknown 741 | os=-coff 742 | ;; 743 | OSE68000 | ose68000) 744 | basic_machine=m68000-ericsson 745 | os=-ose 746 | ;; 747 | os68k) 748 | basic_machine=m68k-none 749 | os=-os68k 750 | ;; 751 | pa-hitachi) 752 | basic_machine=hppa1.1-hitachi 753 | os=-hiuxwe2 754 | ;; 755 | paragon) 756 | basic_machine=i860-intel 757 | os=-osf 758 | ;; 759 | pbd) 760 | basic_machine=sparc-tti 761 | ;; 762 | pbb) 763 | basic_machine=m68k-tti 764 | ;; 765 | pc532 | pc532-*) 766 | basic_machine=ns32k-pc532 767 | ;; 768 | pentium | p5 | k5 | k6 | nexgen | viac3) 769 | basic_machine=i586-pc 770 | ;; 771 | pentiumpro | p6 | 6x86 | athlon | athlon_*) 772 | basic_machine=i686-pc 773 | ;; 774 | pentiumii | pentium2) 775 | basic_machine=i686-pc 776 | ;; 777 | pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) 778 | basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` 779 | ;; 780 | pentiumpro-* | p6-* | 6x86-* | athlon-*) 781 | basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` 782 | ;; 783 | pentiumii-* | pentium2-*) 784 | basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` 785 | ;; 786 | pn) 787 | basic_machine=pn-gould 788 | ;; 789 | power) basic_machine=power-ibm 790 | ;; 791 | ppc) basic_machine=powerpc-unknown 792 | ;; 793 | ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` 794 | ;; 795 | ppcle | powerpclittle | ppc-le | powerpc-little) 796 | basic_machine=powerpcle-unknown 797 | ;; 798 | ppcle-* | powerpclittle-*) 799 | basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` 800 | ;; 801 | ppc64) basic_machine=powerpc64-unknown 802 | ;; 803 | ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` 804 | ;; 805 | ppc64le | powerpc64little | ppc64-le | powerpc64-little) 806 | basic_machine=powerpc64le-unknown 807 | ;; 808 | ppc64le-* | powerpc64little-*) 809 | basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` 810 | ;; 811 | ps2) 812 | basic_machine=i386-ibm 813 | ;; 814 | pw32) 815 | basic_machine=i586-unknown 816 | os=-pw32 817 | ;; 818 | rom68k) 819 | basic_machine=m68k-rom68k 820 | os=-coff 821 | ;; 822 | rm[46]00) 823 | basic_machine=mips-siemens 824 | ;; 825 | rtpc | rtpc-*) 826 | basic_machine=romp-ibm 827 | ;; 828 | s390 | s390-*) 829 | basic_machine=s390-ibm 830 | ;; 831 | s390x | s390x-*) 832 | basic_machine=s390x-ibm 833 | ;; 834 | sa29200) 835 | basic_machine=a29k-amd 836 | os=-udi 837 | ;; 838 | sb1) 839 | basic_machine=mipsisa64sb1-unknown 840 | ;; 841 | sb1el) 842 | basic_machine=mipsisa64sb1el-unknown 843 | ;; 844 | sequent) 845 | basic_machine=i386-sequent 846 | ;; 847 | sh) 848 | basic_machine=sh-hitachi 849 | os=-hms 850 | ;; 851 | sparclite-wrs | simso-wrs) 852 | basic_machine=sparclite-wrs 853 | os=-vxworks 854 | ;; 855 | sps7) 856 | basic_machine=m68k-bull 857 | os=-sysv2 858 | ;; 859 | spur) 860 | basic_machine=spur-unknown 861 | ;; 862 | st2000) 863 | basic_machine=m68k-tandem 864 | ;; 865 | stratus) 866 | basic_machine=i860-stratus 867 | os=-sysv4 868 | ;; 869 | sun2) 870 | basic_machine=m68000-sun 871 | ;; 872 | sun2os3) 873 | basic_machine=m68000-sun 874 | os=-sunos3 875 | ;; 876 | sun2os4) 877 | basic_machine=m68000-sun 878 | os=-sunos4 879 | ;; 880 | sun3os3) 881 | basic_machine=m68k-sun 882 | os=-sunos3 883 | ;; 884 | sun3os4) 885 | basic_machine=m68k-sun 886 | os=-sunos4 887 | ;; 888 | sun4os3) 889 | basic_machine=sparc-sun 890 | os=-sunos3 891 | ;; 892 | sun4os4) 893 | basic_machine=sparc-sun 894 | os=-sunos4 895 | ;; 896 | sun4sol2) 897 | basic_machine=sparc-sun 898 | os=-solaris2 899 | ;; 900 | sun3 | sun3-*) 901 | basic_machine=m68k-sun 902 | ;; 903 | sun4) 904 | basic_machine=sparc-sun 905 | ;; 906 | sun386 | sun386i | roadrunner) 907 | basic_machine=i386-sun 908 | ;; 909 | sv1) 910 | basic_machine=sv1-cray 911 | os=-unicos 912 | ;; 913 | symmetry) 914 | basic_machine=i386-sequent 915 | os=-dynix 916 | ;; 917 | t3e) 918 | basic_machine=alphaev5-cray 919 | os=-unicos 920 | ;; 921 | t90) 922 | basic_machine=t90-cray 923 | os=-unicos 924 | ;; 925 | tic4x | c4x*) 926 | basic_machine=tic4x-unknown 927 | os=-coff 928 | ;; 929 | tic54x | c54x*) 930 | basic_machine=tic54x-unknown 931 | os=-coff 932 | ;; 933 | tic55x | c55x*) 934 | basic_machine=tic55x-unknown 935 | os=-coff 936 | ;; 937 | tic6x | c6x*) 938 | basic_machine=tic6x-unknown 939 | os=-coff 940 | ;; 941 | tx39) 942 | basic_machine=mipstx39-unknown 943 | ;; 944 | tx39el) 945 | basic_machine=mipstx39el-unknown 946 | ;; 947 | toad1) 948 | basic_machine=pdp10-xkl 949 | os=-tops20 950 | ;; 951 | tower | tower-32) 952 | basic_machine=m68k-ncr 953 | ;; 954 | udi29k) 955 | basic_machine=a29k-amd 956 | os=-udi 957 | ;; 958 | ultra3) 959 | basic_machine=a29k-nyu 960 | os=-sym1 961 | ;; 962 | v810 | necv810) 963 | basic_machine=v810-nec 964 | os=-none 965 | ;; 966 | vaxv) 967 | basic_machine=vax-dec 968 | os=-sysv 969 | ;; 970 | vms) 971 | basic_machine=vax-dec 972 | os=-vms 973 | ;; 974 | vpp*|vx|vx-*) 975 | basic_machine=f301-fujitsu 976 | ;; 977 | vxworks960) 978 | basic_machine=i960-wrs 979 | os=-vxworks 980 | ;; 981 | vxworks68) 982 | basic_machine=m68k-wrs 983 | os=-vxworks 984 | ;; 985 | vxworks29k) 986 | basic_machine=a29k-wrs 987 | os=-vxworks 988 | ;; 989 | w65*) 990 | basic_machine=w65-wdc 991 | os=-none 992 | ;; 993 | w89k-*) 994 | basic_machine=hppa1.1-winbond 995 | os=-proelf 996 | ;; 997 | xps | xps100) 998 | basic_machine=xps100-honeywell 999 | ;; 1000 | ymp) 1001 | basic_machine=ymp-cray 1002 | os=-unicos 1003 | ;; 1004 | z8k-*-coff) 1005 | basic_machine=z8k-unknown 1006 | os=-sim 1007 | ;; 1008 | none) 1009 | basic_machine=none-none 1010 | os=-none 1011 | ;; 1012 | 1013 | # Here we handle the default manufacturer of certain CPU types. It is in 1014 | # some cases the only manufacturer, in others, it is the most popular. 1015 | w89k) 1016 | basic_machine=hppa1.1-winbond 1017 | ;; 1018 | op50n) 1019 | basic_machine=hppa1.1-oki 1020 | ;; 1021 | op60c) 1022 | basic_machine=hppa1.1-oki 1023 | ;; 1024 | romp) 1025 | basic_machine=romp-ibm 1026 | ;; 1027 | rs6000) 1028 | basic_machine=rs6000-ibm 1029 | ;; 1030 | vax) 1031 | basic_machine=vax-dec 1032 | ;; 1033 | pdp10) 1034 | # there are many clones, so DEC is not a safe bet 1035 | basic_machine=pdp10-unknown 1036 | ;; 1037 | pdp11) 1038 | basic_machine=pdp11-dec 1039 | ;; 1040 | we32k) 1041 | basic_machine=we32k-att 1042 | ;; 1043 | sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) 1044 | basic_machine=sh-unknown 1045 | ;; 1046 | sh64) 1047 | basic_machine=sh64-unknown 1048 | ;; 1049 | sparc | sparcv9 | sparcv9b) 1050 | basic_machine=sparc-sun 1051 | ;; 1052 | cydra) 1053 | basic_machine=cydra-cydrome 1054 | ;; 1055 | orion) 1056 | basic_machine=orion-highlevel 1057 | ;; 1058 | orion105) 1059 | basic_machine=clipper-highlevel 1060 | ;; 1061 | mac | mpw | mac-mpw) 1062 | basic_machine=m68k-apple 1063 | ;; 1064 | pmac | pmac-mpw) 1065 | basic_machine=powerpc-apple 1066 | ;; 1067 | *-unknown) 1068 | # Make sure to match an already-canonicalized machine name. 1069 | ;; 1070 | *) 1071 | echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 1072 | exit 1 1073 | ;; 1074 | esac 1075 | 1076 | # Here we canonicalize certain aliases for manufacturers. 1077 | case $basic_machine in 1078 | *-digital*) 1079 | basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` 1080 | ;; 1081 | *-commodore*) 1082 | basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` 1083 | ;; 1084 | *) 1085 | ;; 1086 | esac 1087 | 1088 | # Decode manufacturer-specific aliases for certain operating systems. 1089 | 1090 | if [ x"$os" != x"" ] 1091 | then 1092 | case $os in 1093 | # First match some system type aliases 1094 | # that might get confused with valid system types. 1095 | # -solaris* is a basic system type, with this one exception. 1096 | -solaris1 | -solaris1.*) 1097 | os=`echo $os | sed -e 's|solaris1|sunos4|'` 1098 | ;; 1099 | -solaris) 1100 | os=-solaris2 1101 | ;; 1102 | -svr4*) 1103 | os=-sysv4 1104 | ;; 1105 | -unixware*) 1106 | os=-sysv4.2uw 1107 | ;; 1108 | -gnu/linux*) 1109 | os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` 1110 | ;; 1111 | # First accept the basic system types. 1112 | # The portable systems comes first. 1113 | # Each alternative MUST END IN A *, to match a version number. 1114 | # -sysv* is not here because it comes later, after sysvr4. 1115 | -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ 1116 | | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ 1117 | | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ 1118 | | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ 1119 | | -aos* \ 1120 | | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ 1121 | | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ 1122 | | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ 1123 | | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ 1124 | | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ 1125 | | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ 1126 | | -chorusos* | -chorusrdb* \ 1127 | | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ 1128 | | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ 1129 | | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ 1130 | | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ 1131 | | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ 1132 | | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ 1133 | | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ 1134 | | -powermax* | -dnix*) 1135 | # Remember, each alternative MUST END IN *, to match a version number. 1136 | ;; 1137 | -qnx*) 1138 | case $basic_machine in 1139 | x86-* | i*86-*) 1140 | ;; 1141 | *) 1142 | os=-nto$os 1143 | ;; 1144 | esac 1145 | ;; 1146 | -nto-qnx*) 1147 | ;; 1148 | -nto*) 1149 | os=`echo $os | sed -e 's|nto|nto-qnx|'` 1150 | ;; 1151 | -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ 1152 | | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ 1153 | | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) 1154 | ;; 1155 | -mac*) 1156 | os=`echo $os | sed -e 's|mac|macos|'` 1157 | ;; 1158 | -linux*) 1159 | os=`echo $os | sed -e 's|linux|linux-gnu|'` 1160 | ;; 1161 | -sunos5*) 1162 | os=`echo $os | sed -e 's|sunos5|solaris2|'` 1163 | ;; 1164 | -sunos6*) 1165 | os=`echo $os | sed -e 's|sunos6|solaris3|'` 1166 | ;; 1167 | -opened*) 1168 | os=-openedition 1169 | ;; 1170 | -wince*) 1171 | os=-wince 1172 | ;; 1173 | -osfrose*) 1174 | os=-osfrose 1175 | ;; 1176 | -osf*) 1177 | os=-osf 1178 | ;; 1179 | -utek*) 1180 | os=-bsd 1181 | ;; 1182 | -dynix*) 1183 | os=-bsd 1184 | ;; 1185 | -acis*) 1186 | os=-aos 1187 | ;; 1188 | -atheos*) 1189 | os=-atheos 1190 | ;; 1191 | -386bsd) 1192 | os=-bsd 1193 | ;; 1194 | -ctix* | -uts*) 1195 | os=-sysv 1196 | ;; 1197 | -nova*) 1198 | os=-rtmk-nova 1199 | ;; 1200 | -ns2 ) 1201 | os=-nextstep2 1202 | ;; 1203 | -nsk*) 1204 | os=-nsk 1205 | ;; 1206 | # Preserve the version number of sinix5. 1207 | -sinix5.*) 1208 | os=`echo $os | sed -e 's|sinix|sysv|'` 1209 | ;; 1210 | -sinix*) 1211 | os=-sysv4 1212 | ;; 1213 | -triton*) 1214 | os=-sysv3 1215 | ;; 1216 | -oss*) 1217 | os=-sysv3 1218 | ;; 1219 | -svr4) 1220 | os=-sysv4 1221 | ;; 1222 | -svr3) 1223 | os=-sysv3 1224 | ;; 1225 | -sysvr4) 1226 | os=-sysv4 1227 | ;; 1228 | # This must come after -sysvr4. 1229 | -sysv*) 1230 | ;; 1231 | -ose*) 1232 | os=-ose 1233 | ;; 1234 | -es1800*) 1235 | os=-ose 1236 | ;; 1237 | -xenix) 1238 | os=-xenix 1239 | ;; 1240 | -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) 1241 | os=-mint 1242 | ;; 1243 | -aros*) 1244 | os=-aros 1245 | ;; 1246 | -kaos*) 1247 | os=-kaos 1248 | ;; 1249 | -none) 1250 | ;; 1251 | *) 1252 | # Get rid of the `-' at the beginning of $os. 1253 | os=`echo $os | sed 's/[^-]*-//'` 1254 | echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 1255 | exit 1 1256 | ;; 1257 | esac 1258 | else 1259 | 1260 | # Here we handle the default operating systems that come with various machines. 1261 | # The value should be what the vendor currently ships out the door with their 1262 | # machine or put another way, the most popular os provided with the machine. 1263 | 1264 | # Note that if you're going to try to match "-MANUFACTURER" here (say, 1265 | # "-sun"), then you have to tell the case statement up towards the top 1266 | # that MANUFACTURER isn't an operating system. Otherwise, code above 1267 | # will signal an error saying that MANUFACTURER isn't an operating 1268 | # system, and we'll never get to this point. 1269 | 1270 | case $basic_machine in 1271 | *-acorn) 1272 | os=-riscix1.2 1273 | ;; 1274 | arm*-rebel) 1275 | os=-linux 1276 | ;; 1277 | arm*-semi) 1278 | os=-aout 1279 | ;; 1280 | # This must come before the *-dec entry. 1281 | pdp10-*) 1282 | os=-tops20 1283 | ;; 1284 | pdp11-*) 1285 | os=-none 1286 | ;; 1287 | *-dec | vax-*) 1288 | os=-ultrix4.2 1289 | ;; 1290 | m68*-apollo) 1291 | os=-domain 1292 | ;; 1293 | i386-sun) 1294 | os=-sunos4.0.2 1295 | ;; 1296 | m68000-sun) 1297 | os=-sunos3 1298 | # This also exists in the configure program, but was not the 1299 | # default. 1300 | # os=-sunos4 1301 | ;; 1302 | m68*-cisco) 1303 | os=-aout 1304 | ;; 1305 | mips*-cisco) 1306 | os=-elf 1307 | ;; 1308 | mips*-*) 1309 | os=-elf 1310 | ;; 1311 | or32-*) 1312 | os=-coff 1313 | ;; 1314 | *-tti) # must be before sparc entry or we get the wrong os. 1315 | os=-sysv3 1316 | ;; 1317 | sparc-* | *-sun) 1318 | os=-sunos4.1.1 1319 | ;; 1320 | *-be) 1321 | os=-beos 1322 | ;; 1323 | *-ibm) 1324 | os=-aix 1325 | ;; 1326 | *-wec) 1327 | os=-proelf 1328 | ;; 1329 | *-winbond) 1330 | os=-proelf 1331 | ;; 1332 | *-oki) 1333 | os=-proelf 1334 | ;; 1335 | *-hp) 1336 | os=-hpux 1337 | ;; 1338 | *-hitachi) 1339 | os=-hiux 1340 | ;; 1341 | i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) 1342 | os=-sysv 1343 | ;; 1344 | *-cbm) 1345 | os=-amigaos 1346 | ;; 1347 | *-dg) 1348 | os=-dgux 1349 | ;; 1350 | *-dolphin) 1351 | os=-sysv3 1352 | ;; 1353 | m68k-ccur) 1354 | os=-rtu 1355 | ;; 1356 | m88k-omron*) 1357 | os=-luna 1358 | ;; 1359 | *-next ) 1360 | os=-nextstep 1361 | ;; 1362 | *-sequent) 1363 | os=-ptx 1364 | ;; 1365 | *-crds) 1366 | os=-unos 1367 | ;; 1368 | *-ns) 1369 | os=-genix 1370 | ;; 1371 | i370-*) 1372 | os=-mvs 1373 | ;; 1374 | *-next) 1375 | os=-nextstep3 1376 | ;; 1377 | *-gould) 1378 | os=-sysv 1379 | ;; 1380 | *-highlevel) 1381 | os=-bsd 1382 | ;; 1383 | *-encore) 1384 | os=-bsd 1385 | ;; 1386 | *-sgi) 1387 | os=-irix 1388 | ;; 1389 | *-siemens) 1390 | os=-sysv4 1391 | ;; 1392 | *-masscomp) 1393 | os=-rtu 1394 | ;; 1395 | f30[01]-fujitsu | f700-fujitsu) 1396 | os=-uxpv 1397 | ;; 1398 | *-rom68k) 1399 | os=-coff 1400 | ;; 1401 | *-*bug) 1402 | os=-coff 1403 | ;; 1404 | *-apple) 1405 | os=-macos 1406 | ;; 1407 | *-atari*) 1408 | os=-mint 1409 | ;; 1410 | *) 1411 | os=-none 1412 | ;; 1413 | esac 1414 | fi 1415 | 1416 | # Here we handle the case where we know the os, and the CPU type, but not the 1417 | # manufacturer. We pick the logical manufacturer. 1418 | vendor=unknown 1419 | case $basic_machine in 1420 | *-unknown) 1421 | case $os in 1422 | -riscix*) 1423 | vendor=acorn 1424 | ;; 1425 | -sunos*) 1426 | vendor=sun 1427 | ;; 1428 | -aix*) 1429 | vendor=ibm 1430 | ;; 1431 | -beos*) 1432 | vendor=be 1433 | ;; 1434 | -hpux*) 1435 | vendor=hp 1436 | ;; 1437 | -mpeix*) 1438 | vendor=hp 1439 | ;; 1440 | -hiux*) 1441 | vendor=hitachi 1442 | ;; 1443 | -unos*) 1444 | vendor=crds 1445 | ;; 1446 | -dgux*) 1447 | vendor=dg 1448 | ;; 1449 | -luna*) 1450 | vendor=omron 1451 | ;; 1452 | -genix*) 1453 | vendor=ns 1454 | ;; 1455 | -mvs* | -opened*) 1456 | vendor=ibm 1457 | ;; 1458 | -ptx*) 1459 | vendor=sequent 1460 | ;; 1461 | -vxsim* | -vxworks* | -windiss*) 1462 | vendor=wrs 1463 | ;; 1464 | -aux*) 1465 | vendor=apple 1466 | ;; 1467 | -hms*) 1468 | vendor=hitachi 1469 | ;; 1470 | -mpw* | -macos*) 1471 | vendor=apple 1472 | ;; 1473 | -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) 1474 | vendor=atari 1475 | ;; 1476 | -vos*) 1477 | vendor=stratus 1478 | ;; 1479 | esac 1480 | basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` 1481 | ;; 1482 | esac 1483 | 1484 | echo $basic_machine$os 1485 | exit 0 1486 | 1487 | # Local variables: 1488 | # eval: (add-hook 'write-file-hooks 'time-stamp) 1489 | # time-stamp-start: "timestamp='" 1490 | # time-stamp-format: "%:y-%02m-%02d" 1491 | # time-stamp-end: "'" 1492 | # End: 1493 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # vim:set syntax=conf nowrap sw=4 ts=4: 3 | # Process this file with autoconf to produce a configure script. 4 | 5 | # Initialization. 6 | AC_PREREQ(2.50) 7 | 8 | AC_INIT(tcptraceroute,`cat VERSION`) 9 | AC_CONFIG_SRCDIR(main.c) 10 | AC_CANONICAL_SYSTEM 11 | AM_INIT_AUTOMAKE 12 | AC_CONFIG_SRCDIR(main.c) 13 | AM_CONFIG_HEADER(config.h) 14 | 15 | # Checks for programs. 16 | AC_PROG_CC 17 | AC_PROG_GCC_TRADITIONAL 18 | if test "$GCC" = yes ; then 19 | CFLAGS="$CFLAGS -Wall" 20 | fi 21 | AC_PROG_INSTALL 22 | 23 | # Checks for libraries. 24 | AC_CHECK_FUNC(gethostbyname, ,[AC_CHECK_LIB(nsl, gethostbyname)]) 25 | AC_CHECK_FUNC(socket, ,[AC_CHECK_LIB(socket, socket)]) 26 | AC_CHECK_FUNC(connect, ,[AC_CHECK_LIB(inet, connect)]) 27 | AC_CHECK_FUNC(inet_aton, ,[AC_CHECK_LIB(resolv, inet_aton)]) 28 | 29 | AC_ARG_WITH(pcap, [], 30 | [ 31 | AC_MSG_ERROR([Please use "--with-libpcap=DIR", not "--with-pcap=DIR"]) 32 | ], 33 | []) 34 | 35 | AC_ARG_WITH(libpcap, AC_HELP_STRING([--with-libpcap=DIR], [use libpcap in DIR]), 36 | [ 37 | LIBPCAPCC="" 38 | LIBPCAPLD="" 39 | 40 | test -f "$withval/pcap.h" && LIBPCAPCC="$LIBPCAPCC -I$withval" 41 | test -d "$withval/bpf" && LIBPCAPCC="$LIBPCAPCC -I$withval/bpf" 42 | test -f "$withval/include/pcap.h" && LIBPCAPCC="$LIBPCAPCC -I$withval/include" 43 | 44 | test -f "$withval/pcap.a" && LIBPCAPLD="$LIBPCAPLD -L$withval" 45 | test -f "$withval/libpcap.a" && LIBPCAPLD="$LIBPCAPLD -L$withval" 46 | test -f "$withval/lib/pcap.a" && LIBPCAPLD="$LIBPCAPLD -L$withval/lib" 47 | test -f "$withval/lib/libpcap.a" && LIBPCAPLD="$LIBPCAPLD -L$withval/lib" 48 | 49 | if test -z "$LIBPCAPCC" -o -z "$LIBPCAPLD" 50 | then 51 | AC_MSG_ERROR([No valid libpcap library found in $withval]) 52 | else 53 | CPPFLAGS="$CPPFLAGS $LIBPCAPCC" 54 | LDFLAGS="$LDFLAGS $LIBPCAPLD" 55 | AC_MSG_NOTICE([using libpcap in $withval]) 56 | fi 57 | ], []) 58 | 59 | LIBNET_CONFIG="libnet-config" # relative, using $PATH 60 | AC_ARG_WITH(libnet, AC_HELP_STRING( [--with-libnet=DIR], [use libnet in DIR]), 61 | [ 62 | LIBNETCC="" 63 | LIBNETLD="" 64 | 65 | test -x "$withval/bin/libnet-config" && LIBNET_CONFIG="$withval/bin/libnet-config" 66 | test -x "$withval/libnet-config" && LIBNET_CONFIG="$withval/libnet-config" 67 | 68 | test -f "$withval/libnet.h" && LIBNETCC="$LIBNETCC -I$withval" 69 | test -f "$withval/include/libnet.h" && LIBNETCC="$LIBNETCC -I$withval/include" 70 | 71 | test -f "$withval/libnet.a" && LIBNETLD="$LIBNETLD -L$withval" 72 | test -f "$withval/lib/libnet.a" && LIBNETLD="$LIBNETLD -L$withval/lib" 73 | 74 | if test -z "$LIBNETCC" -o -z "$LIBNETLD" 75 | then 76 | AC_MSG_ERROR([No valid libnet library found in $withval]) 77 | else 78 | CPPFLAGS="$CPPFLAGS $LIBNETCC" 79 | LDFLAGS="$LDFLAGS $LIBNETLD" 80 | AC_MSG_NOTICE([using libnet in $withval]) 81 | fi 82 | ], []) 83 | 84 | AC_CHECK_LIB(pcap, pcap_open_live, [], [AC_MSG_ERROR([cannot find libpcap])]) 85 | 86 | # Libnet underwent a major API change in between version 1.0.2a and 1.1.0. 87 | # The code below sets the preprocessor symbol LIBNET_API_VERSION to 100 if a 88 | # pre-1.1.0 version of libnet is being used, and to 110 if version 1.1.0 or 89 | # greater is being used. 90 | # 91 | # It would've been simpler to just have a HAVE_LIBNET_110 symbol or the like, 92 | # but this way, if there are more incompatible API changes in the future, the 93 | # values assigned to LIBNET_API_VERSION can be updated accordingly. 94 | 95 | AC_CHECK_LIB(net, main, [], [AC_MSG_ERROR([cannot find libnet])]) 96 | AC_CHECK_LIB(net, libnet_init_packet, 97 | [ 98 | AC_DEFINE(LIBNET_API_VERSION, 100, [libnet API version]) 99 | AC_MSG_NOTICE([libnet version: < 1.1.0]) 100 | CPPFLAGS="$CPPFLAGS `$LIBNET_CONFIG --defines`" 101 | CPPFLAGS="$CPPFLAGS `$LIBNET_CONFIG --cflags`" 102 | ], [ 103 | AC_CHECK_LIB(net, libnet_init, 104 | [ 105 | AC_DEFINE(LIBNET_API_VERSION, 110, [libnet API version]) 106 | AC_MSG_NOTICE([libnet version: >= 1.1.0]) 107 | ], [ 108 | AC_MSG_ERROR([could not identify the version of libnet]) 109 | ]) 110 | ]) 111 | 112 | # Checks for header files. 113 | AC_HEADER_STDC 114 | AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/ioctl.h sys/socket.h unistd.h]) 115 | 116 | # Checks for typedefs, structures, and compiler characteristics. 117 | AC_HEADER_TIME 118 | 119 | # Check to see if socket.sa_len exists. Adapted from the configure.in of _Unix 120 | # Network Programming_ second edition example code, by W. Richard Stevens. 121 | AC_MSG_CHECKING(for sockaddr.sa_len) 122 | AC_COMPILE_IFELSE( 123 | [AC_LANG_PROGRAM([ 124 | #include 125 | #include 126 | ], 127 | [ unsigned int i = sizeof(((struct sockaddr *)0)->sa_len) ])], 128 | [ 129 | AC_MSG_RESULT(yes) 130 | AC_DEFINE([HAVE_SOCKADDR_SA_LEN], 1, [Has socket.sa_len]) 131 | ], [ 132 | AC_MSG_RESULT(no) 133 | ]) 134 | 135 | AC_CHECK_MEMBER([struct sockaddr.sa_len], 136 | [AC_DEFINE([HAVE_SOCKADDR_SA_LEN], 1, [Has socket.sa_len])], 137 | [], 138 | [#include 139 | #include ]) 140 | 141 | # Checks for library functions. 142 | AC_FUNC_MALLOC 143 | # AC_FUNC_REALLOC # our util.c:xrealloc() function deals with the 144 | # realloc(0,0) case, and AC_FUNC_REALLOC doesn't 145 | # appear to break on HP/UX systems. 146 | AC_FUNC_SELECT_ARGTYPES 147 | AC_FUNC_VPRINTF 148 | AC_CHECK_FUNCS([gettimeofday memset select socket strchr]) 149 | 150 | # Is this Solaris? 151 | AC_MSG_CHECKING(for Solaris) 152 | AC_RUN_IFELSE([AC_LANG_PROGRAM( [], [ 153 | #if defined (__SVR4) && defined (__sun) 154 | exit(0); 155 | #else 156 | exit(-1); 157 | #endif 158 | ]) 159 | ],[ 160 | AC_MSG_RESULT(yes) 161 | AC_DEFINE([HAVE_SOLARIS], 1, [Is this a Solaris system?]) 162 | HAVE_SOLARIS=yes 163 | ],[ 164 | AC_MSG_RESULT(no) 165 | ]) 166 | 167 | # Is this BSDI? 168 | AC_MSG_CHECKING(for BSDI) 169 | AC_RUN_IFELSE([AC_LANG_PROGRAM( [], [ 170 | #if defined (__bsdi__) 171 | exit(0); 172 | #else 173 | exit(-1); 174 | #endif 175 | ]) 176 | ],[ 177 | AC_MSG_RESULT(yes) 178 | AC_DEFINE([HAVE_BSDI], 1, [Is this a BSDI system?]) 179 | HAVE_BSDI=yes 180 | ],[ 181 | AC_MSG_RESULT(no) 182 | ]) 183 | 184 | # Is this NetBSD? 185 | AC_MSG_CHECKING(for NetBSD) 186 | AC_RUN_IFELSE([AC_LANG_PROGRAM( [], [ 187 | #if defined (__NetBSD__) 188 | exit(0); 189 | #else 190 | exit(-1); 191 | #endif 192 | ]) 193 | ],[ 194 | AC_MSG_RESULT(yes) 195 | AC_DEFINE([HAVE_NETBSD], 1, [Is this a NetBSD system?]) 196 | HAVE_NETBSD=yes 197 | ],[ 198 | AC_MSG_RESULT(no) 199 | ]) 200 | 201 | # Is this MacOS X? 202 | AC_MSG_CHECKING(for MacOS X) 203 | AC_RUN_IFELSE([AC_LANG_PROGRAM( [], [ 204 | #if defined (__APPLE__) && defined (__MACH__) 205 | exit(0); 206 | #else 207 | exit(-1); 208 | #endif 209 | ]) 210 | ],[ 211 | AC_MSG_RESULT(yes) 212 | AC_DEFINE([HAVE_MACOSX], 1, [Is this a MacOS X system?]) 213 | HAVE_MACOSX=yes 214 | ],[ 215 | AC_MSG_RESULT(no) 216 | ]) 217 | 218 | # Handle --enable-noselect-default 219 | AC_ARG_ENABLE(noselect-default, 220 | AC_HELP_STRING([--enable-noselect-default], [default to not using select(2)]), 221 | [ 222 | NOSELECT_DEFAULT=$enable_noselect_default 223 | ], [ 224 | if test "$HAVE_MACOSX" = "yes"; then 225 | NOSELECT_DEFAULT=yes 226 | elif test "$HAVE_BSDI" = "yes"; then 227 | NOSELECT_DEFAULT=yes 228 | elif test "$HAVE_NETBSD" = "yes"; then 229 | NOSELECT_DEFAULT=yes 230 | else 231 | NOSELECT_DEFAULT=no 232 | fi 233 | ]) 234 | if test "$NOSELECT_DEFAULT" = "yes"; then 235 | AC_DEFINE(NOSELECT_DEFAULT, 1, [Use select(2) by default?]) 236 | fi 237 | 238 | # Handle --enable-track-default=IP|PORT 239 | AC_ARG_ENABLE(track-default, 240 | AC_HELP_STRING([--enable-track-default=PORT|ID], [default to tracking probes by PORT or ID]), 241 | [ 242 | if test "$enable_track_default" = "id" -o "$enable_track_default" = "ID"; then 243 | TRACK_DEFAULT=id 244 | elif test "$enable_track_default" = "port" -o "$enable_track_default" = "PORT"; then 245 | TRACK_DEFAULT=port 246 | else 247 | AC_MSG_ERROR([valid arguments for --enable-track-default are PORT or ID]) 248 | fi 249 | ], [ 250 | if test "$HAVE_SOLARIS" = "yes"; then 251 | TRACK_DEFAULT=port 252 | else 253 | TRACK_DEFAULT=id 254 | fi 255 | ]) 256 | if test "$TRACK_DEFAULT" = "port"; then 257 | AC_DEFINE(TRACK_PORT_DEFAULT, 1, [Track ports by default]) 258 | fi 259 | 260 | # Handle --enable-default-port=N 261 | AC_ARG_ENABLE(default-port, 262 | AC_HELP_STRING([--enable-default-port=N], [default destination port]), 263 | [ 264 | case $enable_default_port in 265 | [[0-9][0-9][0-9][0-9][0-9]|[0-9][0-9][0-9][0-9]|[0-9][0-9][0-9]|[0-9][0-9]|[0-9]]) 266 | DEFAULT_PORT=$enable_default_port 267 | ;; 268 | *) 269 | echo "default port: $enable_default_port" 270 | AC_MSG_ERROR([numeric argument required for --enable-default-port]) 271 | ;; 272 | esac 273 | ], [ 274 | DEFAULT_PORT=80 275 | ]) 276 | AC_DEFINE_UNQUOTED(DEFAULT_PORT, $DEFAULT_PORT, [Default destination port]) 277 | 278 | # If using gcc, --enable-static will compile staticly 279 | AC_ARG_ENABLE(static, 280 | AC_HELP_STRING([--enable-static], [compile staticly, if using gcc]), 281 | [ 282 | if test "$GCC" = yes ; then 283 | CFLAGS="$CFLAGS -static" 284 | else 285 | AC_MSG_ERROR([Sorry, I only know how to compile staticly for gcc]) 286 | fi 287 | ], []) 288 | 289 | echo "Target OS is $target_os" 290 | 291 | AC_DEFINE_UNQUOTED(TARGET, "$target", [Target platform]) 292 | AC_CONFIG_FILES(Makefile) 293 | AC_OUTPUT 294 | -------------------------------------------------------------------------------- /datalink.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: c; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4; -*- */ 2 | /* vim:set ts=4 sw=4 ai nobackup nocindent sm: */ 3 | 4 | /* 5 | * tcptraceroute -- A traceroute implementation using TCP packets 6 | * Copyright (c) 2001-2015 Michael C. Toren 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License, version 2, as published 10 | * by the Free Software Foundation. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | * for more details. 16 | * 17 | * A copy of the GNU GPL is available as /usr/doc/copyright/GPL on Debian 18 | * systems, or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html 19 | * You can also obtain it by writing to the Free Software Foundation, Inc., 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 21 | */ 22 | 23 | #include "tcptraceroute.h" 24 | 25 | #ifndef SIOCGIFCONF 26 | #include /* Solaris, maybe others? */ 27 | #endif 28 | 29 | #ifndef AF_LINK 30 | #define AF_LINK AF_INET /* BSD defines some AF_INET interfaces as AF_LINK */ 31 | #endif 32 | 33 | struct interface_entry *interfaces; 34 | 35 | /* 36 | * To add support for additional link layers add entries to the following 37 | * table. The numbers below are believed to be correct and were obtained 38 | * by looking through other pcap programs, however tcptraceroute has only 39 | * been well tested on ethernet, PPP, and loopback interfaces. 40 | */ 41 | 42 | struct datalinktype datalinktypes[] = { 43 | /* type offset name */ 44 | #ifdef DLT_RAW 45 | { DLT_RAW, 0, "RAW" }, 46 | #endif 47 | #ifdef DLT_EN10MB 48 | { DLT_EN10MB, 14, "ETHERNET" }, 49 | #endif 50 | #ifdef DLT_PPP 51 | { DLT_PPP, 4, "PPP" }, 52 | #endif 53 | #ifdef DLT_LINUX_SLL 54 | { DLT_LINUX_SLL, 16, "PPP_HDLC" }, 55 | #endif 56 | #ifdef DLT_SLIP 57 | { DLT_SLIP, 16, "SLIP" }, 58 | #endif 59 | #ifdef DLT_PPP_BSDOS 60 | { DLT_PPP_BSDOS, 24, "PPP_BSDOS" }, 61 | #endif 62 | #ifdef DLT_SLIP_BSDOS 63 | { DLT_SLIP_BSDOS, 24, "SLIP_BSDOS" }, 64 | #endif 65 | #ifdef DLT_FDDI 66 | { DLT_FDDI, 21, "FDDI" }, 67 | #endif 68 | #ifdef DLT_IEEE802 69 | { DLT_IEEE802, 22, "IEEE802" }, 70 | #endif 71 | #ifdef DLT_NULL 72 | { DLT_NULL, 4, "DLT_NULL" }, 73 | #endif 74 | #ifdef DLT_LOOP 75 | { DLT_LOOP, 4, "DLT_LOOP" }, 76 | #endif 77 | #ifdef DLT_PPP_ETHER 78 | { DLT_PPP_ETHER, 12, "PPP_ETHER" }, 79 | #endif 80 | 81 | /* Does anyone know correct values for these? */ 82 | #ifdef DLT_ATM_RFC1483 83 | { DLT_ATM_RFC1483, -1, "ATM_RFC1483" }, 84 | #endif 85 | #ifdef DLT_EN3MB 86 | { DLT_EN3MB, -1, "EN3MB" }, 87 | #endif 88 | #ifdef DLT_AX25 89 | { DLT_AX25, -1, "AX25" }, 90 | #endif 91 | #ifdef DLT_PRONET 92 | { DLT_PRONET, -1, "PRONET" }, 93 | #endif 94 | #ifdef DLT_CHAOS 95 | { DLT_CHAOS, -1, "CHAOS" }, 96 | #endif 97 | #ifdef DLT_ARCNET 98 | { DLT_ARCNET, -1, "ARCNET" }, 99 | #endif 100 | 101 | /* End of the road */ 102 | { -1, -1, NULL } 103 | }; 104 | 105 | 106 | int datalinkoffset(int type) 107 | { 108 | int i; 109 | 110 | for (i = 0; datalinktypes[i].name; i++) 111 | if (datalinktypes[i].type == type) 112 | return datalinktypes[i].offset; 113 | 114 | return -1; 115 | } 116 | 117 | char *datalinkname(int type) 118 | { 119 | static char name[TEXTSIZE]; 120 | int i; 121 | 122 | for (i = 0; datalinktypes[i].name; i++) 123 | if (datalinktypes[i].type == type) 124 | return datalinktypes[i].name; 125 | 126 | safe_snprintf(name, TEXTSIZE, "#%d", type); 127 | return name; 128 | } 129 | 130 | /* 131 | * Fetches the interface list, storing it in struct interface_entry interfaces. 132 | */ 133 | 134 | void getinterfaces(void) 135 | { 136 | struct interface_entry *p; 137 | struct ifconf ifc; 138 | struct ifreq *ifrp, ifr; 139 | int numreqs, i, s; 140 | u_long addr; 141 | int salen; 142 | char *x; 143 | 144 | debug("entering getinterfaces()\n"); 145 | 146 | if (o_nogetinterfaces) 147 | { 148 | debug("Not fetching the interface list\n"); 149 | return; 150 | } 151 | 152 | if (interfaces) 153 | fatal("Double call to getinterfaces()\n"); 154 | 155 | ifc.ifc_buf = NULL; 156 | p = NULL; 157 | 158 | numreqs = 32; 159 | 160 | if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 161 | fatal("socket error"); 162 | 163 | debug("ifreq buffer set to %d\n", numreqs); 164 | 165 | for (;;) 166 | { 167 | ifc.ifc_len = sizeof(struct ifreq) * numreqs; 168 | ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len); 169 | 170 | if (ioctl(s, SIOCGIFCONF, &ifc) < 0) 171 | pfatal("ioctl"); 172 | 173 | /* This "+ sizeof(struct ifreq) + 64" crap seems to be an (Open?)BSDism. */ 174 | if ( (ifc.ifc_len + sizeof(struct ifreq) + 64) >= (sizeof(struct ifreq) * numreqs) ) 175 | { 176 | /* Assume it overflowed and try again */ 177 | numreqs += 32; 178 | if (numreqs > 20000) 179 | break; /* Too big! */ 180 | debug("ifreq buffer grown to %d\n", numreqs); 181 | continue; 182 | } 183 | 184 | break; 185 | } 186 | 187 | debug("Successfully retrieved interface list\n"); 188 | 189 | #ifdef HAVE_SOCKADDR_SA_LEN 190 | debug("Using HAVE_SOCKADDR_SA_LEN method for finding addresses.\n"); 191 | #endif 192 | 193 | for (x = ifc.ifc_buf; x < (ifc.ifc_buf + ifc.ifc_len); x += salen) 194 | { 195 | ifrp = (struct ifreq *)x; 196 | 197 | memset(&ifr, 0, sizeof(struct ifreq)); 198 | strcpy(ifr.ifr_name, ifrp->ifr_name); 199 | 200 | #ifdef HAVE_SOCKADDR_SA_LEN 201 | 202 | salen = sizeof(ifrp->ifr_name) + ifrp->ifr_addr.sa_len; 203 | if (salen < sizeof(*ifrp)) 204 | salen = sizeof(*ifrp); 205 | 206 | addr = ((struct sockaddr_in *)&ifrp->ifr_addr)->sin_addr.s_addr; 207 | if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) 208 | pfatal("ioctl(SIOCGIFFLAGS)"); 209 | 210 | #else /* HAVE_SOCKADDR_SA_LEN */ 211 | 212 | salen = sizeof(*ifrp); 213 | 214 | if (ioctl(s, SIOCGIFADDR, &ifr) < 0) 215 | { 216 | debug("ioctl(SIOCGIFADDR) on unconfigured interface %s failed; skipping\n", 217 | sprintable(ifr.ifr_name)); 218 | continue; 219 | } 220 | addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; 221 | 222 | #endif /* HAVE_SOCKADDR_SA_LEN else */ 223 | 224 | #ifdef AF_INET6 225 | if (ifrp->ifr_addr.sa_family == AF_INET6) 226 | { 227 | debug("Ignoring AF_INET6 address on interface %s\n", 228 | sprintable(ifr.ifr_name)); 229 | continue; 230 | } 231 | #endif 232 | 233 | if (ifrp->ifr_addr.sa_family != AF_INET && 234 | ifrp->ifr_addr.sa_family != AF_LINK) 235 | { 236 | debug("Ignoring non-AF_INET address on interface %s\n", 237 | sprintable(ifr.ifr_name)); 238 | continue; 239 | } 240 | 241 | if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) 242 | pfatal("ioctl(SIOCGIFFLAGS)"); 243 | if ((ifr.ifr_flags & IFF_UP) == 0) 244 | { 245 | debug("Ignoring down interface %s\n", 246 | sprintable(ifr.ifr_name)); 247 | continue; 248 | } 249 | 250 | /* Deal with virtual hosts */ 251 | for (i = 0; ifr.ifr_name[i]; i++) 252 | if (ifr.ifr_name[i] == ':') 253 | ifr.ifr_name[i] = '\0'; 254 | 255 | /* Grow another node on the linked list... */ 256 | if (!p) 257 | p = interfaces = xrealloc(NULL, sizeof(struct interface_entry)); 258 | else 259 | p = p->next = xrealloc(NULL, sizeof(struct interface_entry)); 260 | 261 | p->next = NULL; 262 | 263 | /* ... and fill it in */ 264 | p->addr = addr; 265 | p->name = xrealloc(NULL, strlen(ifr.ifr_name) + 1); 266 | strcpy(p->name, ifr.ifr_name); 267 | 268 | debug("Discovered interface %s with address %s\n", 269 | sprintable(p->name), iptos(p->addr)); 270 | } 271 | 272 | free(ifc.ifc_buf); 273 | debug("leaving getinterfaces()\n"); 274 | } 275 | 276 | /* 277 | * Determines the source address that should be used to reach the 278 | * given destination address. 279 | */ 280 | 281 | u_long findsrc(u_long dest) 282 | { 283 | struct sockaddr_in sinsrc, sindest; 284 | int s; 285 | unsigned int size; 286 | 287 | if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 288 | pfatal("socket error"); 289 | 290 | memset(&sinsrc, 0, sizeof(struct sockaddr_in)); 291 | memset(&sindest, 0, sizeof(struct sockaddr_in)); 292 | 293 | sindest.sin_family = AF_INET; 294 | sindest.sin_addr.s_addr = dest; 295 | sindest.sin_port = htons(53); /* can be anything but zero */ 296 | 297 | if (connect(s, (struct sockaddr *)&sindest, sizeof(sindest)) < 0) 298 | pfatal("connect"); 299 | 300 | size = sizeof(sinsrc); 301 | if (getsockname(s, (struct sockaddr *)&sinsrc, &size) < 0) 302 | pfatal("getsockname"); 303 | 304 | close(s); 305 | debug("Determined source address of %s to reach %s\n", 306 | iptos(sinsrc.sin_addr.s_addr), iptos(dest)); 307 | return sinsrc.sin_addr.s_addr; 308 | } 309 | 310 | /* 311 | * Find an appropriate device to use given the specified source address. 312 | * However, if we find an interface matching the global dst_ip address, set 313 | * the source address we're looking for to 127.0.0.1 in an attempt to select 314 | * the loopback. Ofcourse, this entirely depends on the fact that a loopback 315 | * interface exists with an address of 127.0.0.1. 316 | */ 317 | 318 | char *finddev(u_long with_src) 319 | { 320 | struct interface_entry *p; 321 | char *device = NULL; 322 | 323 | debug("entering finddev()\n"); 324 | 325 | /* First, see if we're trying to trace to ourself */ 326 | for (p = interfaces; p; p = p->next) 327 | if (p->addr == dst_ip) 328 | { 329 | debug("Destination matches local address of interface %s;\n\tattempting to find loopback interface, o_nofilter set\n", p->name); 330 | with_src = hosttoip("127.0.0.1", LIBNET_DONT_RESOLVE); 331 | o_nofilter = 1; 332 | } 333 | 334 | for (p = interfaces; p; p = p->next) 335 | if (p->addr == with_src) 336 | device = p->name; 337 | 338 | debug("finddev() returning %s\n", device); 339 | return device; 340 | } 341 | -------------------------------------------------------------------------------- /datalink.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: c; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4; -*- */ 2 | /* vim:set ts=4 sw=4 ai nobackup nocindent sm: */ 3 | 4 | /* 5 | * tcptraceroute -- A traceroute implementation using TCP packets 6 | * Copyright (c) 2001-2015 Michael C. Toren 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License, version 2, as published 10 | * by the Free Software Foundation. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | * for more details. 16 | * 17 | * A copy of the GNU GPL is available as /usr/doc/copyright/GPL on Debian 18 | * systems, or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html 19 | * You can also obtain it by writing to the Free Software Foundation, Inc., 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 21 | */ 22 | 23 | /* array of supported datalink types */ 24 | extern struct datalinktype { 25 | int type, offset; 26 | char *name; 27 | } datalinktypes[]; 28 | 29 | /* interface linked list, built by getinterfaces() */ 30 | extern struct interface_entry { 31 | char *name; 32 | u_long addr; 33 | struct interface_entry *next; 34 | } *interfaces; 35 | 36 | int datalinkoffset(int); 37 | char *datalinkname(int); 38 | void getinterfaces(void); 39 | u_long findsrc(u_long); 40 | char *finddev(u_long); 41 | -------------------------------------------------------------------------------- /examples.txt: -------------------------------------------------------------------------------- 1 | A few real world examples of using tcptraceroute to trace through 2 | firewalls that traceroute(8) has trouble with. These are all sites 3 | that pass TCP SYN packets on to hosts sitting on the clean side of the 4 | firewall, and which don't filter ICMP time exceeded messages leaving 5 | their network. All examples listed below were captured on July 1st. 6 | 7 | -- Michael C. Toren Sun, 1 Jul 2001 21:25:26 -0400 8 | 9 | 10 | pages.ebay.com, a classic firewalled webserver: 11 | 12 | [mct@quint ~]$ traceroute -w2 -q1 -f 5 pages.ebay.com 13 | traceroute to pages.ebay.com (216.32.120.133), 30 hops max, 38 byte packets 14 | 5 core2-abov-ds3.b2.iad.netaxs.net (207.106.127.130) 10.390 ms 15 | 6 core1-mae-e-gige-1.mae-e.iad.netaxs.net (207.106.127.101) 14.310 ms 16 | 7 core1-core3-fe-1.mae-e.iad.netaxs.net (207.106.31.28) 9.935 ms 17 | 8 250.ATM3-0.BR3.DCA6.ALTER.NET (137.39.92.25) 14.727 ms 18 | 9 0.so-3-1-0.XL1.DCA6.ALTER.NET (152.63.38.118) 18.766 ms 19 | 10 0.so-7-0-0.XR1.DCA6.ALTER.NET (152.63.38.86) 22.659 ms 20 | 11 0.so-3-0-0.TR1.DCA6.ALTER.NET (152.63.11.97) 15.002 ms 21 | 12 121.at-5-0-0.TR1.SAC1.ALTER.NET (152.63.2.178) 120.593 ms 22 | 13 297.ATM7-0.XR1.SFO4.ALTER.NET (152.63.51.5) 123.571 ms 23 | 14 191.ATM7-0.GW8.SJC2.ALTER.NET (152.63.49.245) 130.606 ms 24 | 15 * 25 | 16 * 26 | 17 * 27 | 28 | [mct@quint ~]$ tcptraceroute -f 5 pages.ebay.com 29 | Selected device eth0, address 207.8.132.210, port 1056 for outgoing packets 30 | Tracing the path to pages.ebay.com (216.32.120.133) on TCP port 80 (www), 30 hops max 31 | 5 core2-abov-ds3.b2.iad.netaxs.net (207.106.127.130) 10.849 ms 32 | 6 core1-mae-e-gige-1.mae-e.iad.netaxs.net (207.106.127.101) 105.601 ms 33 | 7 core1-core3-fe-1.mae-e.iad.netaxs.net (207.106.31.28) 19.929 ms 34 | 8 250.ATM3-0.BR3.DCA6.ALTER.NET (137.39.92.25) 16.123 ms 35 | 9 0.so-3-1-0.XL1.DCA6.ALTER.NET (152.63.38.118) 14.717 ms 36 | 10 0.so-7-0-0.XR1.DCA6.ALTER.NET (152.63.38.86) 22.183 ms 37 | 11 0.so-3-0-0.TR1.DCA6.ALTER.NET (152.63.11.97) 18.194 ms 38 | 12 121.at-5-0-0.TR1.SAC1.ALTER.NET (152.63.2.178) 101.491 ms 39 | 13 297.ATM7-0.XR1.SFO4.ALTER.NET (152.63.51.5) 110.817 ms 40 | 14 191.ATM7-0.GW8.SJC2.ALTER.NET (152.63.49.245) 113.841 ms 41 | 15 ebay-oc12-gw.customer.alter.net (157.130.209.10) 121.632 ms 42 | 16 10.128.1.42 (10.128.1.42) 109.132 ms 43 | 17 pages.ebay.com (216.32.120.133) [open] 115.378 ms 44 | 45 | 46 | www.microsoft.com, another classic firewalled webserver: 47 | 48 | [mct@quint ~]$ traceroute -w2 -q1 -f 5 www.microsoft.com 49 | traceroute: Warning: www.microsoft.com has multiple addresses; using 207.46.197.100 50 | traceroute to www.microsoft.akadns.net (207.46.197.100), 30 hops max, 38 byte packets 51 | 5 baltimore.balt-core.h0-0-45M.netaxs.net (207.106.2.18) 17.560 ms 52 | 6 blt-dc.dc-core.h5-0-45M.netaxs.net (207.106.2.2) 27.769 ms 53 | 7 core1-core3-fe-1.mae-e.iad.netaxs.net (207.106.31.28) 28.802 ms 54 | 8 250.ATM3-0.BR3.DCA6.ALTER.NET (137.39.92.25) 27.934 ms 55 | 9 0.so-3-1-0.XL2.DCA6.ALTER.NET (152.63.38.122) 24.210 ms 56 | 10 0.so-0-0-0.XR2.DCA6.ALTER.NET (152.63.35.117) 35.693 ms 57 | 11 0.so-4-0-0.TR2.DCA6.ALTER.NET (152.63.11.93) 22.170 ms 58 | 12 121.at-1-1-0.TR2.SEA1.ALTER.NET (146.188.140.78) 94.099 ms 59 | 13 0.so-1-0-0.XL2.SEA1.ALTER.NET (152.63.106.237) 101.325 ms 60 | 14 POS7-0.GW4.SEA1.ALTER.NET (146.188.201.53) 91.887 ms 61 | 15 microsoftoc48-gw.customer.alter.net (157.130.184.26) 89.536 ms 62 | 16 * 63 | 17 * 64 | 18 * 65 | 66 | [mct@quint ~]$ tcptraceroute -f 5 207.46.197.100 67 | Selected device eth0, address 207.8.132.210, port 1058 for outgoing packets 68 | Tracing the path to 207.46.197.100 on TCP port 80 (www), 30 hops max 69 | 5 baltimore.balt-core.h0-0-45M.netaxs.net (207.106.2.18) 9.430 ms 70 | 6 blt-dc.dc-core.h5-0-45M.netaxs.net (207.106.2.2) 17.514 ms 71 | 7 core1-core3-fe-1.mae-e.iad.netaxs.net (207.106.31.28) 23.256 ms 72 | 8 250.ATM3-0.BR3.DCA6.ALTER.NET (137.39.92.25) 30.819 ms 73 | 9 0.so-3-1-0.XL2.DCA6.ALTER.NET (152.63.38.122) 26.605 ms 74 | 10 0.so-0-0-0.XR2.DCA6.ALTER.NET (152.63.35.117) 38.700 ms 75 | 11 0.so-4-0-0.TR2.DCA6.ALTER.NET (152.63.11.93) 31.402 ms 76 | 12 121.at-1-1-0.TR2.SEA1.ALTER.NET (146.188.140.78) 93.992 ms 77 | 13 0.so-1-0-0.XL2.SEA1.ALTER.NET (152.63.106.237) 105.176 ms 78 | 14 POS7-0.GW4.SEA1.ALTER.NET (146.188.201.53) 86.524 ms 79 | 15 microsoftoc48-gw.customer.alter.net (157.130.184.26) 85.916 ms 80 | 16 207.46.129.51 (207.46.129.51) 84.920 ms 81 | 17 microsoft.com (207.46.197.100) [open] 85.344 ms 82 | 83 | 84 | odc-t.ankara.af.mil, a firewalled mail server: 85 | 86 | [mct@quint ~]$ traceroute -w2 -q1 -f 5 odc-t.ankara.af.mil 87 | traceroute to odc-t.ankara.af.mil (207.133.163.7), 30 hops max, 38 byte packets 88 | 5 nyc-l3.nyc-core.h3-0-45M.netaxs.net (207.106.127.18) 7.277 ms 89 | 6 nyc-pos-l.netaxs.net (207.106.3.133) 11.803 ms 90 | 7 mae-east.dc-core.netaxs.net (207.106.31.29) 18.922 ms 91 | 8 netaxs-core3.iad.above.net (209.249.119.233) 19.200 ms 92 | 9 core1-core3-oc48.iad1.above.net (209.249.203.34) 11.942 ms 93 | 10 sjc2-iad1-oc48.sjc2.above.net (216.200.127.26) 80.741 ms 94 | 11 core5-sjc2-oc48-2.sjc1.above.net (208.184.102.205) 80.829 ms 95 | 12 core2-sjc1-oc3.sjc6.above.net (207.126.96.106) 81.621 ms 96 | 13 fix-west-pilot-fddi2.disa.mil (198.32.136.88) 93.961 ms 97 | 14 137.209.200.207 (137.209.200.207) 99.437 ms 98 | 15 206.38.100.2 (206.38.100.2) 258.541 ms 99 | 16 140.35.16.18 (140.35.16.18) 373.297 ms 100 | 17 198.26.165.18 (198.26.165.18) 373.686 ms 101 | 18 * 102 | 19 * 103 | 20 * 104 | 21 * 105 | 106 | [mct@quint ~]$ tcptraceroute -f 5 odc-t.ankara.af.mil smtp 107 | Selected device eth0, address 207.8.132.210, port 1150 for outgoing packets 108 | Tracing the path to odc-t.ankara.af.mil (207.133.163.7) on TCP port 25 (smtp), 30 hops max 109 | 5 nyc-l3.nyc-core.h3-0-45M.netaxs.net (207.106.127.18) 9.456 ms 110 | 6 nyc-pos-l.netaxs.net (207.106.3.133) 11.762 ms 111 | 7 mae-east.dc-core.netaxs.net (207.106.31.29) 11.958 ms 112 | 8 netaxs-core3.iad.above.net (209.249.119.233) 11.791 ms 113 | 9 core1-core3-oc48.iad1.above.net (209.249.203.34) 12.510 ms 114 | 10 sjc2-iad1-oc48.sjc2.above.net (216.200.127.26) 80.335 ms 115 | 11 core5-sjc2-oc48-2.sjc1.above.net (208.184.102.205) 81.364 ms 116 | 12 core2-sjc1-oc3.sjc6.above.net (207.126.96.106) 83.107 ms 117 | 13 fix-west-pilot-fddi2.disa.mil (198.32.136.88) 76.092 ms 118 | 14 137.209.200.207 (137.209.200.207) 99.776 ms 119 | 15 206.38.100.2 (206.38.100.2) 252.840 ms 120 | 16 140.35.16.18 (140.35.16.18) 370.720 ms 121 | 17 198.26.165.18 (198.26.165.18) 485.771 ms 122 | 18 odctfw.ankara.af.mil (207.133.163.161) 443.782 ms 123 | 19 odc-t.ankara.af.mil (207.133.163.7) [open] 745.611 ms 124 | 125 | 126 | 127 | 128 | tcptraceroute-1.3beta1 added support for controlling the SYN and ACK 129 | flags used in outgoing probe packets through the -S and -A command line 130 | arguments. By utilizing probe packets with the ACK bit set, it is 131 | possible to traceroute to hosts located behind stateless firewalls that 132 | block all inbound TCP connections, but permit those hosts to establish 133 | outbound connections. Below are two examples of such behavior, 134 | recorded on August 15th, 2001. 135 | 136 | -- Michael C. Toren Sun, 29 Jun 2003 17:18:41 -0400 137 | 138 | 139 | Tracing to a host protected by a Linux 2.2 ipchains firewall: 140 | 141 | [mct@quint ~]$ tcptraceroute -f7 -q1 argo.starforce.com 142 | Selected device eth0, address 207.8.132.210, port 3738 for outgoing packets 143 | Tracing the path to argo.starforce.com (216.158.56.82) on TCP port 80 (www), 30 hops max 144 | 7 voicenet-gw.core-1-hssi-6-0-0-50.oldcity.dca.net (207.103.28.30) 69.252 ms 145 | 8 node-150-eth3-0-local.oldcity.dca.net (207.245.82.150) 16.216 ms 146 | 9 * 147 | 10 * 148 | 11 * 149 | 150 | [mct@quint ~]$ tcptraceroute -f7 -q1 -A argo.starforce.com 151 | Selected device eth0, address 207.8.132.210, port 3747 for outgoing packets 152 | Tracing the path to argo.starforce.com (216.158.56.82) on TCP port 80 (www), 30 hops max 153 | 7 voicenet-gw.core-1-hssi-6-0-0-50.oldcity.dca.net (207.103.28.30) 11.030 ms 154 | 8 node-150-eth3-0-local.oldcity.dca.net (207.245.82.150) 24.488 ms 155 | 9 argo.starforce.com (216.158.56.82) [closed] 1514.142 ms 156 | 157 | Tracing to falkland, a host behind jumpgate, a Cisco router with the 158 | following access-list: 159 | 160 | access-list 100 permit tcp any any established 161 | access-list 100 deny ip any any 162 | 163 | 164 | [mct@quint ~]$ tcptraceroute -q1 falkland 165 | Selected device eth0, address 207.8.132.210, port 3771 for outgoing packets 166 | Tracing the path to falkland (207.106.130.86) on TCP port 80 (www), 30 hops max 167 | 1 jumpgate.netisland.net (207.106.130.81) 2.111 ms 168 | 2 * 169 | 3 * 170 | 4 * 171 | 172 | [mct@quint ~]$ tcptraceroute -q1 -A falkland 173 | Selected device eth0, address 207.8.132.210, port 3773 for outgoing packets 174 | Tracing the path to falkland (207.106.130.86) on TCP port 80 (www), 30 hops max 175 | 1 jumpgate.netisland.net (207.106.130.81) 2.044 ms 176 | 2 falkland.netisland.net (207.106.130.86) [closed] 4.635 ms 177 | 178 | 179 | Another example of tracing to a host protected by a stateless firewall, which 180 | permits hosts behind it to make outbound TCP connections: 181 | 182 | [mct@ellesmere ~]$ tcptraceroute -q1 -f9 uunet1.fe.weather.com 183 | Selected device eth0, address 209.163.107.174, port 35833 for outgoing packets 184 | Tracing the path to uunet1.fe.weather.com (63.111.66.2) on TCP port 80 (www), 30 hops max 185 | 9 0.so-3-1-0.XL2.ATL5.ALTER.NET (152.63.0.238) 32.925 ms 186 | 10 0.so-7-0-0.XR2.ATL5.ALTER.NET (152.63.85.194) 32.765 ms 187 | 11 110.at-5-1-0.WR1.ATL5.ALTER.NET (152.63.3.58) 32.941 ms 188 | 12 pos6-0.ur1.atl7.web.wcom.net (157.130.216.50) 32.781 ms 189 | 13 198.5.128.134 32.802 ms 190 | 14 * 191 | 15 * 192 | 16 * 193 | 194 | [mct@ellesmere ~]$ tcptraceroute -q1 -f9 -A uunet1.fe.weather.com 195 | Selected device eth0, address 209.163.107.174, port 35834 for outgoing packets 196 | Tracing the path to uunet1.fe.weather.com (63.111.66.2) on TCP port 80 (www), 30 hops max 197 | 9 0.so-3-1-0.XL2.ATL5.ALTER.NET (152.63.0.238) 32.704 ms 198 | 10 0.so-7-0-0.XR2.ATL5.ALTER.NET (152.63.85.194) 32.665 ms 199 | 11 110.at-5-1-0.WR1.ATL5.ALTER.NET (152.63.3.58) 32.996 ms 200 | 12 pos6-0.ur1.atl7.web.wcom.net (157.130.216.50) 32.779 ms 201 | 13 198.5.128.134 33.122 ms 202 | 14 uunet1.fe.weather.com (63.111.66.2) [closed] 33.399 ms 203 | 204 | 205 | 206 | 207 | tcptraceroute-1.5beta6 added the --dnat detection support, to detect 208 | DNAT devices which do not correctly rewrite the IP address of the IP 209 | packets quoted in ICMP time-exceeded messages tcptraceroute solicits, 210 | revealing the destination IP address an outbound probe packet was NATed 211 | to. Below are examples of using --dnat to determine the IP address our 212 | probe packets are being NATed to, recorded on March 28th, 2006. 213 | 214 | -- Michael C. Toren Tue, 28 Mar 2006 23:40:54 -0500 215 | 216 | 217 | [mct@ellesmere ~]$ tcptraceroute -q1 -f5 --track-port --dnat pages.ebay.com 218 | Selected device eth0, address 209.163.107.174 for outgoing packets 219 | Tracing the path to pages.ebay.com (66.135.192.87) on TCP port 80 (www), 30 hops max 220 | 5 equinix-chaz.coretel.net (209.163.107.121) 5.288 ms 221 | 6 gsr12012.ash.he.net (206.223.137.132) 5.610 ms 222 | 7 pos3-3.gsr12416.pao.he.net (216.218.254.205) 88.611 ms 223 | 8 pao1-br01.net.ebay.com (198.32.176.56) 88.637 ms 224 | 9 10.6.1.133 90.605 ms 225 | 10 ge2-7-snv1-xr01.net.ebay.com (66.135.207.54) 91.667 ms 226 | 11 10.6.1.74 92.471 ms 227 | Detected DNAT to 10.6.35.86 228 | 12 10.6.105.8 91.187 ms 229 | 13 pages.ebay.com (66.135.192.87) [open] 91.908 ms 230 | 231 | 232 | [mct@ellesmere ~]$ tcptraceroute -q1 -f8 --dnat magicpipe.no-ip.com 22 233 | Selected device eth0, address 209.163.107.174, port 40857 for outgoing packets 234 | Tracing the path to magicpipe.no-ip.com (69.142.94.59) on TCP port 22 (ssh), 30 hops max 235 | 8 tbr2-cl15.n54ny.ip.att.net (12.122.10.53) 12.965 ms 236 | 9 gar7-p390.n54ny.ip.att.net (12.123.3.85) 79.347 ms 237 | 10 12.118.102.22 12.430 ms 238 | 11 te-8-1-ar01.plainfield.nj.panjde.comcast.net (68.86.211.1) 12.425 ms 239 | 12 po80-ar01.audubon.nj.panjde.comcast.net (68.86.208.2) 14.968 ms 240 | 13 po10-ar01.wallingford.pa.panjde.comcast.net (68.86.208.26) 16.521 ms 241 | 14 po90-ur02.wallingford.pa.panjde.comcast.net (68.86.208.189) 16.356 ms 242 | 15 * 243 | Detected DNAT to 192.168.1.100 244 | 16 c-69-142-94-59.hsd1.pa.comcast.net (69.142.94.59) 24.674 ms 245 | 17 c-69-142-94-59.hsd1.pa.comcast.net (69.142.94.59) [open] 25.230 ms 246 | 247 | (The timeout on the 15th hop is normal behavior on Comcast's 248 | network, and is unrelated to tcptraceroute.) 249 | 250 | -------------------------------------------------------------------------------- /install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # install - install a program, script, or datafile 4 | # This comes from X11R5 (mit/util/scripts/install.sh). 5 | # 6 | # Copyright 1991 by the Massachusetts Institute of Technology 7 | # 8 | # Permission to use, copy, modify, distribute, and sell this software and its 9 | # documentation for any purpose is hereby granted without fee, provided that 10 | # the above copyright notice appear in all copies and that both that 11 | # copyright notice and this permission notice appear in supporting 12 | # documentation, and that the name of M.I.T. not be used in advertising or 13 | # publicity pertaining to distribution of the software without specific, 14 | # written prior permission. M.I.T. makes no representations about the 15 | # suitability of this software for any purpose. It is provided "as is" 16 | # without express or implied warranty. 17 | # 18 | # Calling this script install-sh is preferred over install.sh, to prevent 19 | # `make' implicit rules from creating a file called install from it 20 | # when there is no Makefile. 21 | # 22 | # This script is compatible with the BSD install script, but was written 23 | # from scratch. It can only install one file at a time, a restriction 24 | # shared with many OS's install programs. 25 | 26 | 27 | # set DOITPROG to echo to test this script 28 | 29 | # Don't use :- since 4.3BSD and earlier shells don't like it. 30 | doit="${DOITPROG-}" 31 | 32 | 33 | # put in absolute paths if you don't have them in your path; or use env. vars. 34 | 35 | mvprog="${MVPROG-mv}" 36 | cpprog="${CPPROG-cp}" 37 | chmodprog="${CHMODPROG-chmod}" 38 | chownprog="${CHOWNPROG-chown}" 39 | chgrpprog="${CHGRPPROG-chgrp}" 40 | stripprog="${STRIPPROG-strip}" 41 | rmprog="${RMPROG-rm}" 42 | mkdirprog="${MKDIRPROG-mkdir}" 43 | 44 | transformbasename="" 45 | transform_arg="" 46 | instcmd="$mvprog" 47 | chmodcmd="$chmodprog 0755" 48 | chowncmd="" 49 | chgrpcmd="" 50 | stripcmd="" 51 | rmcmd="$rmprog -f" 52 | mvcmd="$mvprog" 53 | src="" 54 | dst="" 55 | dir_arg="" 56 | 57 | while [ x"$1" != x ]; do 58 | case $1 in 59 | -c) instcmd="$cpprog" 60 | shift 61 | continue;; 62 | 63 | -d) dir_arg=true 64 | shift 65 | continue;; 66 | 67 | -m) chmodcmd="$chmodprog $2" 68 | shift 69 | shift 70 | continue;; 71 | 72 | -o) chowncmd="$chownprog $2" 73 | shift 74 | shift 75 | continue;; 76 | 77 | -g) chgrpcmd="$chgrpprog $2" 78 | shift 79 | shift 80 | continue;; 81 | 82 | -s) stripcmd="$stripprog" 83 | shift 84 | continue;; 85 | 86 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` 87 | shift 88 | continue;; 89 | 90 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 91 | shift 92 | continue;; 93 | 94 | *) if [ x"$src" = x ] 95 | then 96 | src=$1 97 | else 98 | # this colon is to work around a 386BSD /bin/sh bug 99 | : 100 | dst=$1 101 | fi 102 | shift 103 | continue;; 104 | esac 105 | done 106 | 107 | if [ x"$src" = x ] 108 | then 109 | echo "install: no input file specified" 110 | exit 1 111 | else 112 | true 113 | fi 114 | 115 | if [ x"$dir_arg" != x ]; then 116 | dst=$src 117 | src="" 118 | 119 | if [ -d $dst ]; then 120 | instcmd=: 121 | chmodcmd="" 122 | else 123 | instcmd=mkdir 124 | fi 125 | else 126 | 127 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command 128 | # might cause directories to be created, which would be especially bad 129 | # if $src (and thus $dsttmp) contains '*'. 130 | 131 | if [ -f $src -o -d $src ] 132 | then 133 | true 134 | else 135 | echo "install: $src does not exist" 136 | exit 1 137 | fi 138 | 139 | if [ x"$dst" = x ] 140 | then 141 | echo "install: no destination specified" 142 | exit 1 143 | else 144 | true 145 | fi 146 | 147 | # If destination is a directory, append the input filename; if your system 148 | # does not like double slashes in filenames, you may need to add some logic 149 | 150 | if [ -d $dst ] 151 | then 152 | dst="$dst"/`basename $src` 153 | else 154 | true 155 | fi 156 | fi 157 | 158 | ## this sed command emulates the dirname command 159 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 160 | 161 | # Make sure that the destination directory exists. 162 | # this part is taken from Noah Friedman's mkinstalldirs script 163 | 164 | # Skip lots of stat calls in the usual case. 165 | if [ ! -d "$dstdir" ]; then 166 | defaultIFS=' 167 | ' 168 | IFS="${IFS-${defaultIFS}}" 169 | 170 | oIFS="${IFS}" 171 | # Some sh's can't handle IFS=/ for some reason. 172 | IFS='%' 173 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` 174 | IFS="${oIFS}" 175 | 176 | pathcomp='' 177 | 178 | while [ $# -ne 0 ] ; do 179 | pathcomp="${pathcomp}${1}" 180 | shift 181 | 182 | if [ ! -d "${pathcomp}" ] ; 183 | then 184 | $mkdirprog "${pathcomp}" 185 | else 186 | true 187 | fi 188 | 189 | pathcomp="${pathcomp}/" 190 | done 191 | fi 192 | 193 | if [ x"$dir_arg" != x ] 194 | then 195 | $doit $instcmd $dst && 196 | 197 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && 198 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && 199 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && 200 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi 201 | else 202 | 203 | # If we're going to rename the final executable, determine the name now. 204 | 205 | if [ x"$transformarg" = x ] 206 | then 207 | dstfile=`basename $dst` 208 | else 209 | dstfile=`basename $dst $transformbasename | 210 | sed $transformarg`$transformbasename 211 | fi 212 | 213 | # don't allow the sed command to completely eliminate the filename 214 | 215 | if [ x"$dstfile" = x ] 216 | then 217 | dstfile=`basename $dst` 218 | else 219 | true 220 | fi 221 | 222 | # Make a temp file name in the proper directory. 223 | 224 | dsttmp=$dstdir/#inst.$$# 225 | 226 | # Move or copy the file name to the temp name 227 | 228 | $doit $instcmd $src $dsttmp && 229 | 230 | trap "rm -f ${dsttmp}" 0 && 231 | 232 | # and set any options; do chmod last to preserve setuid bits 233 | 234 | # If any of these fail, we abort the whole thing. If we want to 235 | # ignore errors from any of these, just make sure not to ignore 236 | # errors from the above "$doit $instcmd $src $dsttmp" command. 237 | 238 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && 239 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && 240 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && 241 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && 242 | 243 | # Now rename the file to the real destination. 244 | 245 | $doit $rmcmd -f $dstdir/$dstfile && 246 | $doit $mvcmd $dsttmp $dstdir/$dstfile 247 | 248 | fi && 249 | 250 | 251 | exit 0 252 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: c; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4; -*- */ 2 | /* vim:set ts=4 sw=4 ai nobackup nocindent sm: */ 3 | 4 | /* 5 | * tcptraceroute -- A traceroute implementation using TCP packets 6 | * Copyright (c) 2001-2015 Michael C. Toren 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License, version 2, as published 10 | * by the Free Software Foundation. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | * for more details. 16 | * 17 | * A copy of the GNU GPL is available as /usr/doc/copyright/GPL on Debian 18 | * systems, or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html 19 | * You can also obtain it by writing to the Free Software Foundation, Inc., 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 21 | */ 22 | 23 | #include "tcptraceroute.h" 24 | 25 | /* globals */ 26 | u_long dst_ip, src_ip, isn; 27 | u_short src_prt, dst_prt; 28 | char *device, *name, *dst, *src; 29 | char dst_name[TEXTSIZE], dst_prt_name[TEXTSIZE], filter[TEXTSIZE]; 30 | int datalink, offset; 31 | int o_minttl, o_maxttl, o_timeout, o_debug, o_numeric, o_pktlen, 32 | o_nqueries, o_dontfrag, o_tos, o_forceport, o_syn, o_ack, o_ecn, 33 | o_nofilter, o_nogetinterfaces, o_noselect, o_trackport, o_dnat, 34 | o_isn; 35 | 36 | char errbuf [PCAP_ERRBUF_SIZE > LIBNET_ERRBUF_SIZE ? 37 | PCAP_ERRBUF_SIZE : LIBNET_ERRBUF_SIZE]; 38 | 39 | /* 40 | * Check command line arguments for sanity, and fill in the blanks. 41 | */ 42 | 43 | void defaults(void) 44 | { 45 | struct servent *serv; 46 | u_long recommended_src; 47 | 48 | getinterfaces(); 49 | 50 | if ((dst_ip = hosttoip(dst, LIBNET_RESOLVE)) == 0xFFFFFFFF) 51 | fatal("Bad destination address: %s\n", dst); 52 | 53 | recommended_src = findsrc(dst_ip); 54 | 55 | if (src) 56 | { 57 | if ((src_ip = hosttoip(src, LIBNET_RESOLVE)) == 0xFFFFFFFF) 58 | fatal("Bad source address: %s\n", src); 59 | } 60 | else 61 | { 62 | src_ip = recommended_src; 63 | } 64 | 65 | if (device == NULL) 66 | /* not specified on command line */ 67 | device = finddev(recommended_src); 68 | 69 | if (device == NULL) 70 | { 71 | /* couldn't find an appropriate interface */ 72 | warn("Could not determine appropriate device; resorting to pcap_lookupdev()\n"); 73 | device = pcap_lookupdev(errbuf); 74 | } 75 | 76 | if (device == NULL) 77 | fatal("Could not determine device via pcap_lookupdev(): %\n", errbuf); 78 | 79 | if ((pcap = pcap_open_live(device, 0, 0, 0, errbuf)) == NULL) 80 | fatal("error opening device %s: %s\n", device, errbuf); 81 | 82 | datalink = pcap_datalink(pcap); 83 | offset = datalinkoffset(datalink); 84 | 85 | if (offset < 0) 86 | fatal("Sorry, media type of device %s (%s) is not supported\n", 87 | device, datalinkname(datalink)); 88 | 89 | pcap_close(pcap); 90 | 91 | if (src_prt && o_trackport) 92 | { 93 | warn("--track-id implied by specifying the local source port\n"); 94 | o_trackport = 0; 95 | } 96 | 97 | if (! o_trackport) 98 | { 99 | #ifdef HAVE_SOLARIS 100 | warn("--track-id is unlikely to work on Solaris\n"); 101 | #endif 102 | 103 | if (! o_forceport) 104 | src_prt = allocateport(src_prt); 105 | 106 | if (src_prt == 0) 107 | fatal("Sorry, requested local port is already in use. Use -P, instead of -p, to override.\n"); 108 | } 109 | 110 | if (o_minttl <= 0 || o_maxttl <= 0) 111 | fatal("TTL must be greater than 0\n"); 112 | 113 | if (o_minttl >= 256 || o_maxttl >= 256) 114 | fatal("TTL must be less than 256\n"); 115 | 116 | if (o_minttl > o_maxttl) 117 | fatal("Minimum TTL (%d) must be less than maximum TTL (%d)\n", 118 | o_minttl, o_maxttl); 119 | 120 | if (o_nqueries <= 0) 121 | fatal("Number of queries must be at least 1\n"); 122 | 123 | if (o_timeout <= 0) 124 | fatal("Timeout must be at least 1\n"); 125 | 126 | if (o_pktlen < LIBNET_TCP_H + LIBNET_IPV4_H) 127 | { 128 | if (o_pktlen != 0) 129 | warn("Increasing packet length to %d bytes\n", LIBNET_TCP_H + LIBNET_IPV4_H); 130 | o_pktlen = 0; 131 | } 132 | else 133 | o_pktlen -= (LIBNET_TCP_H + LIBNET_IPV4_H); 134 | 135 | #if (LIBNET_API_VERSION < 110) 136 | if ((sockfd = libnet_open_raw_sock(IPPROTO_RAW)) < 0) 137 | pfatal("socket allocation"); 138 | #endif 139 | 140 | #if (LIBNET_API_VERSION < 110) 141 | libnet_seed_prand(); 142 | #else 143 | libnet_seed_prand(libnet_context); 144 | #endif 145 | 146 | if (strcmp(dst, iptos(dst_ip)) == 0) 147 | safe_snprintf(dst_name, TEXTSIZE, "%s", dst); 148 | else 149 | safe_snprintf(dst_name, TEXTSIZE, "%s (%s)", dst, iptos(dst_ip)); 150 | 151 | if ((serv = getservbyport(htons(dst_prt), "tcp")) == NULL) 152 | safe_snprintf(dst_prt_name, TEXTSIZE, "%d", dst_prt); 153 | else 154 | safe_snprintf(dst_prt_name, TEXTSIZE, "%d (%s)", dst_prt, serv->s_name); 155 | 156 | if (! (o_syn|o_ack)) 157 | { 158 | debug("Setting o_syn, in absence of either o_syn or o_ack\n"); 159 | o_syn = 1; 160 | } 161 | 162 | if (! o_isn) 163 | isn = libnet_get_prand(LIBNET_PRu32); 164 | 165 | debugoptions(); 166 | 167 | fprintf(stderr, "Selected device %s, address %s", device, iptos(src_ip)); 168 | if (! o_trackport) fprintf(stderr, ", port %d", src_prt); 169 | fprintf(stderr, " for outgoing packets\n"); 170 | } 171 | 172 | int trace(void) 173 | { 174 | int ttl, q, done; 175 | proberecord *record; 176 | 177 | fprintf(stderr, "Tracing the path to %s on TCP port %s, %d hops max", 178 | dst_name, dst_prt_name, o_maxttl); 179 | if (o_pktlen) 180 | fprintf(stderr, ", %d byte packets", o_pktlen + LIBNET_TCP_H + LIBNET_IPV4_H); 181 | fprintf(stderr, "\n"); 182 | 183 | for (ttl = o_minttl, done = 0; !done && ttl <= o_maxttl; ttl++) 184 | { 185 | for (q = 1; q <= o_nqueries; q++) 186 | { 187 | record = newproberecord(); 188 | probe(record, ttl, q); 189 | 190 | debug("Sent probe %d of %d for hop %d, IP ID %d, source port %d, %s%s%s\n", 191 | q, o_nqueries, ttl, record->id, record->src_prt, 192 | o_syn ? "SYN " : "", 193 | o_ack ? "ACK " : "", 194 | o_ecn ? "CWR ECN " : ""); 195 | 196 | if (capture(record)) 197 | done = 1; 198 | 199 | showprobe(record); 200 | freeproberecord(record); 201 | } 202 | } 203 | 204 | if (!done) 205 | fprintf(stderr, "Destination not reached\n"); 206 | 207 | return !done; 208 | } 209 | 210 | /* 211 | * Verify a command line argument is numeric; only to be called from main(). 212 | */ 213 | 214 | int checknumericarg(void) 215 | { 216 | if (! isnumeric(optarg)) 217 | fatal("Numeric argument required for -%c\n", optopt); 218 | 219 | return atoi(optarg); 220 | } 221 | 222 | /* 223 | * A kludge to help us process long command line arguments, only to be called 224 | * using the CHECKLONG() macro, and only from main(). If the given word 225 | * matches the current word being processed, it's removed from the argument 226 | * list, and returns 1. 227 | */ 228 | 229 | #define CHECKLONG(word) ( checklong_real(word, &i, &argc, &argv) ) 230 | int checklong_real(char *word, int *i, int *argc, char ***argv) 231 | { 232 | int j; 233 | 234 | if (strcmp((*argv)[*i], word) != 0) 235 | return 0; 236 | 237 | /* shift */ 238 | for (j = *i; (*argv)[j]; j++) 239 | (*argv)[j] = (*argv)[j+1]; 240 | 241 | (*argc)--; 242 | (*i)--; 243 | 244 | return 1; 245 | } 246 | 247 | int main(int argc, char **argv) 248 | { 249 | char *optstring, *s; 250 | int op, i, exitcode; 251 | 252 | src_ip = 0; 253 | src_prt = 0; 254 | dst_prt = DEFAULT_PORT; 255 | src = NULL; 256 | device = NULL; 257 | interfaces = NULL; 258 | 259 | o_minttl = 1; 260 | o_maxttl = 30; 261 | o_debug = 0; 262 | o_numeric = 0; 263 | o_nqueries = 3; 264 | o_forceport = 0; 265 | o_pktlen = 0; 266 | o_tos = 0; 267 | o_ecn = 0; 268 | o_syn = 0; 269 | o_ack = 0; 270 | o_dontfrag = 0; 271 | o_timeout = 3; 272 | o_nofilter = 0; 273 | o_nogetinterfaces = 0; 274 | o_dnat = 0; 275 | o_isn = 0; 276 | 277 | #ifdef NOSELECT_DEFAULT 278 | o_noselect = 1; 279 | #else 280 | o_noselect = 0; 281 | #endif 282 | 283 | #ifdef TRACK_PORT_DEFAULT 284 | o_trackport = 1; 285 | #else 286 | o_trackport = 0; 287 | #endif 288 | 289 | /* strip out path from argv[0] */ 290 | for (name = s = argv[0]; s[0]; s++) 291 | if (s[0] == '/' && s[1]) 292 | name = &s[1]; 293 | 294 | /* First loop through and extract long command line arguments ... */ 295 | 296 | for(i = 1; argv[i]; i++) 297 | { 298 | if (CHECKLONG("--help")) 299 | usage(); 300 | 301 | if (CHECKLONG("--version")) 302 | about(); 303 | 304 | /* undocumented, for debugging only */ 305 | if (CHECKLONG("--no-filter")) 306 | { 307 | o_nofilter = 1; 308 | debug("o_nofilter set\n"); 309 | continue; 310 | } 311 | 312 | /* undocumented, for debugging only */ 313 | if (CHECKLONG("--no-getinterfaces")) 314 | { 315 | o_nogetinterfaces = 1; 316 | debug("o_nogetinterfaces set\n"); 317 | continue; 318 | } 319 | 320 | /* undocumented, for debugging only */ 321 | if (CHECKLONG("--no-select")) 322 | { 323 | o_noselect = 1; 324 | debug("o_noselect set\n"); 325 | continue; 326 | } 327 | 328 | /* undocumented, for debugging only */ 329 | if (CHECKLONG("--select")) 330 | { 331 | o_noselect = 0; 332 | debug("o_noselect disabled\n"); 333 | continue; 334 | } 335 | 336 | if (CHECKLONG("--track-id") || 337 | CHECKLONG("--track-ipid")) 338 | { 339 | o_trackport = 0; 340 | debug("o_trackport disabled\n"); 341 | continue; 342 | } 343 | 344 | if (CHECKLONG("--track-port")) 345 | { 346 | o_trackport = 1; 347 | debug("o_trackport set\n"); 348 | continue; 349 | } 350 | 351 | if (CHECKLONG("--dnat")) 352 | { 353 | o_dnat = 1; 354 | debug("o_dnat set\n"); 355 | continue; 356 | } 357 | 358 | if (CHECKLONG("--no-dnat")) 359 | { 360 | o_dnat = 0; 361 | debug("o_dnat unset\n"); 362 | continue; 363 | } 364 | 365 | if (CHECKLONG("--no-dnat-strict")) 366 | { 367 | o_dnat = -1; 368 | debug("o_dnat set to -1\n"); 369 | continue; 370 | } 371 | 372 | /* One day, when our command line argument processing is improved, 373 | * and we CHECKLONG() can take optional or required arguments... */ 374 | /* 375 | if (CHECKLONG("--isn")) 376 | { 377 | o_isn = 1; 378 | isn = // XXX 379 | debug("o_dnat set to -1\n"); 380 | continue; 381 | } 382 | */ 383 | 384 | if (strcmp(argv[i], "--") == 0) 385 | break; 386 | 387 | if (argv[i][0] == '-' && argv[i][1] == '-') 388 | { 389 | fprintf(stderr, "Unknown command line argument: %s\n", argv[i]); 390 | usage(); 391 | } 392 | } 393 | 394 | /* ... then handoff to getopt() */ 395 | 396 | opterr = 0; 397 | optstring = "hvdnNi:l:f:Fm:P:p:q:w:s:t:SAE"; 398 | 399 | while ((op = getopt(argc, argv, optstring)) != -1) 400 | switch(op) 401 | { 402 | case 'h': 403 | usage(); 404 | 405 | case 'v': 406 | about(); 407 | 408 | case 'd': 409 | o_debug++; 410 | debug("%s %s, %s\n", PACKAGE, VERSION, TARGET); 411 | debug("Compiled with %s; libnet %s (API %d)\n", 412 | pcap_lib_version(), LIBNET_VERSION, LIBNET_API_VERSION); 413 | break; 414 | 415 | case 'n': 416 | o_numeric = 1; 417 | debug("o_numeric set to 1\n"); 418 | break; 419 | 420 | case 'N': 421 | o_numeric = -1; 422 | debug("o_numeric set to -1\n"); 423 | break; 424 | 425 | case 'i': /* ARG */ 426 | device = optarg; 427 | debug("device set to %s\n", device); 428 | break; 429 | 430 | case 'l': /* ARG */ 431 | o_pktlen = checknumericarg(); 432 | debug("o_pktlen set to %d\n", o_pktlen); 433 | break; 434 | 435 | case 'f': /* ARG */ 436 | o_minttl = checknumericarg(); 437 | debug("o_minttl set to %d\n", o_minttl); 438 | break; 439 | 440 | case 'F': 441 | o_dontfrag = 1; 442 | debug("o_dontfrag set\n"); 443 | break; 444 | 445 | case 'm': /* ARG */ 446 | o_maxttl = checknumericarg(); 447 | debug("o_maxttl set to %d\n", o_maxttl); 448 | break; 449 | 450 | case 'P': /* ARG */ 451 | o_forceport = 1; 452 | case 'p': /* ARG */ 453 | if (getuid()) fatal("Sorry, must be root to use -p\n"); 454 | src_prt = checknumericarg(); 455 | debug("src_prt set to %d\n", src_prt); 456 | break; 457 | 458 | case 'q': /* ARG */ 459 | o_nqueries = checknumericarg(); 460 | debug("o_nqueries set to %d\n", o_nqueries); 461 | break; 462 | 463 | case 'w': /* ARG */ 464 | o_timeout = checknumericarg(); 465 | debug("o_timeout set to %d\n", o_timeout); 466 | break; 467 | 468 | case 's': /* ARG */ 469 | if (getuid()) fatal("Sorry, must be root to use -s\n"); 470 | src = optarg; 471 | break; 472 | 473 | case 't': /* ARG */ 474 | o_tos = checknumericarg(); 475 | debug("o_tos set to %d\n", o_tos); 476 | break; 477 | 478 | case 'S': 479 | o_syn = 1; 480 | debug("o_syn set\n"); 481 | break; 482 | 483 | case 'A': 484 | o_ack = 1; 485 | debug("o_ack set\n"); 486 | break; 487 | 488 | case 'E': 489 | o_ecn = 1; 490 | debug("o_ecn set\n"); 491 | break; 492 | 493 | case '?': 494 | default: 495 | if (optopt != ':' && strchr(optstring, optopt)) 496 | fatal("Argument required for -%c\n", optopt); 497 | fprintf(stderr, "Unknown command line argument: -%c\n", optopt); 498 | usage(); 499 | } 500 | 501 | argc -= optind; 502 | argv += optind; 503 | 504 | switch(argc - 1) 505 | { 506 | case 2: 507 | o_pktlen = atoi(argv[2]); 508 | 509 | case 1: 510 | if (isnumeric(argv[1])) 511 | { 512 | dst_prt = atoi(argv[1]); 513 | } 514 | else 515 | { 516 | struct servent *serv; 517 | 518 | if ((serv = getservbyname(argv[1], "tcp")) == NULL) 519 | fatal("Unknown port: %s\n", argv[1]); 520 | 521 | dst_prt = ntohs(serv->s_port); 522 | } 523 | 524 | case 0: 525 | dst = argv[0]; 526 | break; 527 | 528 | default: 529 | usage(); 530 | } 531 | 532 | if (getuid() & geteuid()) 533 | fatal("Got root?\n"); 534 | 535 | initlibnet(); 536 | defaults(); 537 | initcapture(); 538 | setuid(getuid()); 539 | exitcode = trace(); 540 | #if (LIBNET_API_VERSION >= 110) 541 | libnet_destroy(libnet_context); 542 | #endif 543 | return exitcode; 544 | } 545 | -------------------------------------------------------------------------------- /missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common stub for a few missing GNU programs while installing. 3 | # Copyright (C) 1996, 1997 Free Software Foundation, Inc. 4 | # Franc,ois Pinard , 1996. 5 | 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2, or (at your option) 9 | # any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 | # 02111-1307, USA. 20 | 21 | if test $# -eq 0; then 22 | echo 1>&2 "Try \`$0 --help' for more information" 23 | exit 1 24 | fi 25 | 26 | case "$1" in 27 | 28 | -h|--h|--he|--hel|--help) 29 | echo "\ 30 | $0 [OPTION]... PROGRAM [ARGUMENT]... 31 | 32 | Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an 33 | error status if there is no known handling for PROGRAM. 34 | 35 | Options: 36 | -h, --help display this help and exit 37 | -v, --version output version information and exit 38 | 39 | Supported PROGRAM values: 40 | aclocal touch file \`aclocal.m4' 41 | autoconf touch file \`configure' 42 | autoheader touch file \`config.h.in' 43 | automake touch all \`Makefile.in' files 44 | bison create \`y.tab.[ch]', if possible, from existing .[ch] 45 | flex create \`lex.yy.c', if possible, from existing .c 46 | lex create \`lex.yy.c', if possible, from existing .c 47 | makeinfo touch the output file 48 | yacc create \`y.tab.[ch]', if possible, from existing .[ch]" 49 | ;; 50 | 51 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 52 | echo "missing - GNU libit 0.0" 53 | ;; 54 | 55 | -*) 56 | echo 1>&2 "$0: Unknown \`$1' option" 57 | echo 1>&2 "Try \`$0 --help' for more information" 58 | exit 1 59 | ;; 60 | 61 | aclocal) 62 | echo 1>&2 "\ 63 | WARNING: \`$1' is missing on your system. You should only need it if 64 | you modified \`acinclude.m4' or \`configure.in'. You might want 65 | to install the \`Automake' and \`Perl' packages. Grab them from 66 | any GNU archive site." 67 | touch aclocal.m4 68 | ;; 69 | 70 | autoconf) 71 | echo 1>&2 "\ 72 | WARNING: \`$1' is missing on your system. You should only need it if 73 | you modified \`configure.in'. You might want to install the 74 | \`Autoconf' and \`GNU m4' packages. Grab them from any GNU 75 | archive site." 76 | touch configure 77 | ;; 78 | 79 | autoheader) 80 | echo 1>&2 "\ 81 | WARNING: \`$1' is missing on your system. You should only need it if 82 | you modified \`acconfig.h' or \`configure.in'. You might want 83 | to install the \`Autoconf' and \`GNU m4' packages. Grab them 84 | from any GNU archive site." 85 | files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in` 86 | test -z "$files" && files="config.h" 87 | touch_files= 88 | for f in $files; do 89 | case "$f" in 90 | *:*) touch_files="$touch_files "`echo "$f" | 91 | sed -e 's/^[^:]*://' -e 's/:.*//'`;; 92 | *) touch_files="$touch_files $f.in";; 93 | esac 94 | done 95 | touch $touch_files 96 | ;; 97 | 98 | automake) 99 | echo 1>&2 "\ 100 | WARNING: \`$1' is missing on your system. You should only need it if 101 | you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'. 102 | You might want to install the \`Automake' and \`Perl' packages. 103 | Grab them from any GNU archive site." 104 | find . -type f -name Makefile.am -print | 105 | sed 's/\.am$/.in/' | 106 | while read f; do touch "$f"; done 107 | ;; 108 | 109 | bison|yacc) 110 | echo 1>&2 "\ 111 | WARNING: \`$1' is missing on your system. You should only need it if 112 | you modified a \`.y' file. You may need the \`Bison' package 113 | in order for those modifications to take effect. You can get 114 | \`Bison' from any GNU archive site." 115 | rm -f y.tab.c y.tab.h 116 | if [ $# -ne 1 ]; then 117 | eval LASTARG="\${$#}" 118 | case "$LASTARG" in 119 | *.y) 120 | SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` 121 | if [ -f "$SRCFILE" ]; then 122 | cp "$SRCFILE" y.tab.c 123 | fi 124 | SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` 125 | if [ -f "$SRCFILE" ]; then 126 | cp "$SRCFILE" y.tab.h 127 | fi 128 | ;; 129 | esac 130 | fi 131 | if [ ! -f y.tab.h ]; then 132 | echo >y.tab.h 133 | fi 134 | if [ ! -f y.tab.c ]; then 135 | echo 'main() { return 0; }' >y.tab.c 136 | fi 137 | ;; 138 | 139 | lex|flex) 140 | echo 1>&2 "\ 141 | WARNING: \`$1' is missing on your system. You should only need it if 142 | you modified a \`.l' file. You may need the \`Flex' package 143 | in order for those modifications to take effect. You can get 144 | \`Flex' from any GNU archive site." 145 | rm -f lex.yy.c 146 | if [ $# -ne 1 ]; then 147 | eval LASTARG="\${$#}" 148 | case "$LASTARG" in 149 | *.l) 150 | SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` 151 | if [ -f "$SRCFILE" ]; then 152 | cp "$SRCFILE" lex.yy.c 153 | fi 154 | ;; 155 | esac 156 | fi 157 | if [ ! -f lex.yy.c ]; then 158 | echo 'main() { return 0; }' >lex.yy.c 159 | fi 160 | ;; 161 | 162 | makeinfo) 163 | echo 1>&2 "\ 164 | WARNING: \`$1' is missing on your system. You should only need it if 165 | you modified a \`.texi' or \`.texinfo' file, or any other file 166 | indirectly affecting the aspect of the manual. The spurious 167 | call might also be the consequence of using a buggy \`make' (AIX, 168 | DU, IRIX). You might want to install the \`Texinfo' package or 169 | the \`GNU make' package. Grab either from any GNU archive site." 170 | file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` 171 | if test -z "$file"; then 172 | file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` 173 | file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` 174 | fi 175 | touch $file 176 | ;; 177 | 178 | *) 179 | echo 1>&2 "\ 180 | WARNING: \`$1' is needed, and you do not seem to have it handy on your 181 | system. You might have modified some files without having the 182 | proper tools for further handling them. Check the \`README' file, 183 | it often tells you about the needed prerequirements for installing 184 | this package. You may also peek at any GNU archive site, in case 185 | some other package would contain this missing \`$1' program." 186 | exit 1 187 | ;; 188 | esac 189 | 190 | exit 0 191 | -------------------------------------------------------------------------------- /mkinstalldirs: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # mkinstalldirs --- make directory hierarchy 3 | # Author: Noah Friedman 4 | # Created: 1993-05-16 5 | # Public domain 6 | 7 | # $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $ 8 | 9 | errstatus=0 10 | 11 | for file 12 | do 13 | set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` 14 | shift 15 | 16 | pathcomp= 17 | for d 18 | do 19 | pathcomp="$pathcomp$d" 20 | case "$pathcomp" in 21 | -* ) pathcomp=./$pathcomp ;; 22 | esac 23 | 24 | if test ! -d "$pathcomp"; then 25 | echo "mkdir $pathcomp" 26 | 27 | mkdir "$pathcomp" || lasterr=$? 28 | 29 | if test ! -d "$pathcomp"; then 30 | errstatus=$lasterr 31 | fi 32 | fi 33 | 34 | pathcomp="$pathcomp/" 35 | done 36 | done 37 | 38 | exit $errstatus 39 | 40 | # mkinstalldirs ends here 41 | -------------------------------------------------------------------------------- /probe.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: c; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4; -*- */ 2 | /* vim:set ts=4 sw=4 ai nobackup nocindent sm: */ 3 | 4 | /* 5 | * tcptraceroute -- A traceroute implementation using TCP packets 6 | * Copyright (c) 2001-2015 Michael C. Toren 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License, version 2, as published 10 | * by the Free Software Foundation. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | * for more details. 16 | * 17 | * A copy of the GNU GPL is available as /usr/doc/copyright/GPL on Debian 18 | * systems, or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html 19 | * You can also obtain it by writing to the Free Software Foundation, Inc., 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 21 | */ 22 | 23 | #include "tcptraceroute.h" 24 | 25 | #if (LIBNET_API_VERSION < 110) 26 | int sockfd; 27 | #else 28 | libnet_t *libnet_context; 29 | #endif 30 | 31 | /* 32 | * Initialize the libnet library context. 33 | */ 34 | 35 | void initlibnet(void) 36 | { 37 | #if (LIBNET_API_VERSION >= 110) 38 | libnet_context = libnet_init(LIBNET_RAW4, NULL, errbuf); 39 | if (libnet_context == NULL) 40 | fatal("libnet_init() failed: %s\n", errbuf); 41 | #else 42 | /* Nothing to do for libnet-1.0 */ 43 | #endif 44 | return; 45 | } 46 | 47 | /* 48 | * Allocates memory for a new proberecord structure. 49 | */ 50 | 51 | proberecord *newproberecord(void) 52 | { 53 | proberecord *record; 54 | 55 | record = xrealloc(NULL, sizeof(proberecord)); 56 | record->state = xrealloc(NULL, TEXTSIZE); 57 | record->string = xrealloc(NULL, TEXTSIZE); 58 | return record; 59 | } 60 | 61 | /* 62 | * Destroys a proberecord structure, carefully, as not to leak memory. 63 | */ 64 | 65 | void freeproberecord(proberecord *record) 66 | { 67 | if (record->string) 68 | free(record->string); 69 | 70 | if (record->state) 71 | free(record->state); 72 | 73 | free(record); 74 | } 75 | 76 | /* 77 | * Request a local unused TCP port from the kernel using bind(2) 78 | */ 79 | 80 | u_short allocateport(u_short requested) 81 | { 82 | struct sockaddr_in in; 83 | int s; 84 | unsigned int insize; 85 | 86 | if ((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) 87 | pfatal("socket error"); 88 | 89 | insize = sizeof(in); 90 | memset(&in, 0, insize); 91 | 92 | in.sin_family = AF_INET; 93 | in.sin_port = htons(requested); 94 | 95 | if ((bind(s, (struct sockaddr *)&in, insize)) < 0) 96 | return 0; 97 | 98 | if ((getsockname(s, (struct sockaddr *)&in, &insize)) < 0) 99 | pfatal("getsockname"); 100 | 101 | close(s); 102 | return ntohs(in.sin_port); 103 | } 104 | 105 | /* 106 | * Allocate an IP ID from our pool of unallocated ID's. A cache is kept of 107 | * the last ALLOCATEID_CACHE_SIZE allocations, so we can check for duplicates. 108 | */ 109 | 110 | u_short allocateid(void) 111 | { 112 | static u_short ids[ALLOCATEID_CACHE_SIZE]; 113 | static int n; 114 | int i, j; 115 | 116 | if ((n = n % ALLOCATEID_CACHE_SIZE) == 0) 117 | { 118 | debug("Generating a new batch of %d IP ID's\n", ALLOCATEID_CACHE_SIZE); 119 | 120 | for(i = 0; i < ALLOCATEID_CACHE_SIZE; i++) 121 | { 122 | for(ids[i] = libnet_get_prand(LIBNET_PRu16), j = i + 1; j < ALLOCATEID_CACHE_SIZE + i; j++) 123 | if (ids[i] == ids[j % ALLOCATEID_CACHE_SIZE]) 124 | ids[i] = libnet_get_prand(LIBNET_PRu16), j = i + 1; 125 | } 126 | } 127 | 128 | return ids[n++]; 129 | } 130 | 131 | /* 132 | * Sends out a TCP SYN packet with the specified TTL, and returns a 133 | * proberecord structure describing the packet sent, so we know what 134 | * to listen for later. A new IP ID is generated for each probe, and 135 | * a new source port if o_trackport is specified. 136 | */ 137 | 138 | void probe(proberecord *record, int ttl, int q) 139 | { 140 | static u_char *payload; 141 | int i, size, ret; 142 | 143 | #if (LIBNET_API_VERSION < 110) 144 | static u_char *buf; 145 | #else 146 | static libnet_ptag_t ip_tag, tcp_tag, data_tag; 147 | #endif 148 | 149 | size = LIBNET_IPV4_H + LIBNET_TCP_H + o_pktlen; 150 | 151 | #if (LIBNET_API_VERSION < 110) 152 | if (!buf) 153 | { 154 | debug("Initializing packet buffer of %d bytes\n", size); 155 | buf = xrealloc(buf, size); 156 | } 157 | 158 | else 159 | memset(buf, 0, size); 160 | #endif 161 | 162 | /* Initialize the packet payload */ 163 | if (o_pktlen && !payload) 164 | { 165 | debug("Initializing payload of %d bytes\n", o_pktlen); 166 | payload = xrealloc(payload, o_pktlen); 167 | 168 | for(i = 0; i < o_pktlen; i++) 169 | payload[i] = i % ('~' - '!') + '!'; 170 | 171 | debug("Payload: %s\n", sprintable((char *)payload)); 172 | } 173 | 174 | /* Set some values of the probe record */ 175 | record->q = q; 176 | record->ttl = ttl; 177 | record->addr = INADDR_ANY; 178 | record->dnat_ip = INADDR_ANY; 179 | record->src_prt = src_prt; 180 | record->id = allocateid(); 181 | record->delta = 0; 182 | 183 | if (o_trackport) 184 | { 185 | record->src_prt = allocateport(0); 186 | if (record->src_prt == 0) 187 | pfatal("Could not allocate local port: bind"); 188 | } 189 | 190 | if (gettimeofday(&(record->timestamp), NULL) < 0) 191 | pfatal("gettimeofday"); 192 | 193 | /* Build the packet, and send it off into the cold, cruel world */ 194 | 195 | #if (LIBNET_API_VERSION < 110) 196 | libnet_build_ip( 197 | LIBNET_TCP_H+o_pktlen, /* len */ 198 | o_tos, /* tos */ 199 | record->id, /* id */ 200 | o_dontfrag ? IP_DF : 0, /* frag */ 201 | ttl, /* ttl */ 202 | IPPROTO_TCP, /* proto */ 203 | src_ip, /* saddr */ 204 | dst_ip, /* daddr */ 205 | NULL, /* data */ 206 | 0, /* datasize? */ 207 | buf); /* buffer */ 208 | 209 | libnet_build_tcp( 210 | record->src_prt, /* source port */ 211 | dst_prt, /* dest port */ 212 | isn, /* seq number */ 213 | 0, /* ack number */ 214 | 215 | (o_syn ? TH_SYN : 0) | 216 | (o_ack ? TH_ACK : 0) | 217 | (o_ecn ? TH_CWR|TH_ECN : 0), /* control */ 218 | 219 | 0, /* window */ 220 | 0, /* urgent? */ 221 | payload, /* data */ 222 | o_pktlen, /* datasize */ 223 | buf + LIBNET_IPV4_H); /* buffer */ 224 | 225 | libnet_do_checksum(buf, IPPROTO_TCP, LIBNET_TCP_H + o_pktlen); 226 | 227 | /* Write */ 228 | if ((ret = libnet_write_ip(sockfd, buf, size)) < size) 229 | fatal("libnet_write_ip failed? Attempted to write %d bytes, only wrote %d\n", 230 | size, ret); 231 | #else 232 | 233 | /* Add the payload */ 234 | data_tag = libnet_build_data(payload, o_pktlen, libnet_context, data_tag); 235 | 236 | if (data_tag < 0) 237 | fatal("Can't add payload: %s\n", libnet_geterror(libnet_context)); 238 | 239 | /* Add the TCP header */ 240 | tcp_tag = libnet_build_tcp( 241 | record->src_prt, /* source port */ 242 | dst_prt, /* dest port */ 243 | isn, /* seq number */ 244 | 0, /* ack number */ 245 | 246 | (o_syn ? TH_SYN : 0) | 247 | (o_ack ? TH_ACK : 0) | 248 | (o_ecn ? TH_CWR|TH_ECN : 0), /* control */ 249 | 250 | 0, /* window */ 251 | 0, /* checksum TBD */ 252 | 0, /* urgent? */ 253 | LIBNET_TCP_H + o_pktlen, /* TCP PDU size */ 254 | NULL, /* data */ 255 | 0, /* datasize */ 256 | libnet_context, /* libnet context */ 257 | tcp_tag); /* libnet protocol tag */ 258 | 259 | if (tcp_tag < 0) 260 | fatal("Can't build TCP header: %s\n", libnet_geterror(libnet_context)); 261 | 262 | /* Add the IP header */ 263 | ip_tag = libnet_build_ipv4( 264 | size, /* total packet len */ 265 | o_tos, /* tos */ 266 | record->id, /* id */ 267 | o_dontfrag ? IP_DF : 0, /* frag */ 268 | ttl, /* ttl */ 269 | IPPROTO_TCP, /* proto */ 270 | 0, /* checksum TBD */ 271 | src_ip, /* saddr */ 272 | dst_ip, /* daddr */ 273 | NULL, /* data */ 274 | 0, /* datasize? */ 275 | libnet_context, /* libnet context */ 276 | ip_tag); /* libnet protocol tag */ 277 | 278 | if (ip_tag < 0) 279 | fatal("Can't build IP header: %s\n", libnet_geterror(libnet_context)); 280 | 281 | /* Write */ 282 | if ((ret = libnet_write(libnet_context)) < size) 283 | fatal("libnet_write failed? Attempted to write %d bytes, only wrote %d\n", 284 | size, ret); 285 | #endif 286 | } 287 | 288 | /* 289 | * A mess of a function, but it works. The aim is to be as compatible as 290 | * possible with traceroute(8), with the one exception that if for the same hop 291 | * we receive a response from two different hosts, display the second host on a 292 | * new line, as Cisco does. This drastically improves readability when tracing 293 | * through links which have per-packet, round-robin load balancing. 294 | */ 295 | 296 | void showprobe(proberecord *record) 297 | { 298 | /* Variables to keep state between calls */ 299 | static char laststate[TEXTSIZE]; 300 | static int lastttl; 301 | static u_long lastaddr, lastdnat_ip; 302 | static u_short lastdnat_dport; 303 | 304 | static int everprinthost; // have we ever printed the hostname? 305 | int printhost = 0; // should we print the hostname this time? 306 | 307 | /* kludge to make debug mode usable */ 308 | if (o_debug) 309 | { 310 | fflush(stdout); 311 | fprintf(stderr, "debug: displayed hop\n"); 312 | fflush(stderr); 313 | } 314 | 315 | /* print the DNAT line */ 316 | if ((lastdnat_ip != record->dnat_ip && record->dnat_ip != INADDR_ANY) 317 | || (lastdnat_dport != record->dnat_dport && record->dnat_dport != 0)) 318 | { 319 | /* If lastttl != record->ttl, we're already on a newline */ 320 | if (lastttl == record->ttl) 321 | printf("\n"); 322 | 323 | printf(" Detected DNAT to %s", iptos(record->dnat_ip)); 324 | if (record->dnat_dport) 325 | printf(":%d", ntohs(record->dnat_dport)); 326 | printf("\n"); 327 | 328 | /* Only print the leading four spaces if this is not the start of a new hop */ 329 | if (lastttl == record->ttl) 330 | printf(" "); 331 | 332 | lastdnat_ip = record->dnat_ip; 333 | lastdnat_dport = record->dnat_dport; 334 | printhost = 1; 335 | } 336 | 337 | /* ttl */ 338 | if (lastttl != record->ttl) 339 | { 340 | printf("%2d ", record->ttl); 341 | printhost = 1; 342 | everprinthost = 0; 343 | safe_strncpy(laststate, "", TEXTSIZE); 344 | } 345 | else if (lastaddr != record->addr && record->addr != INADDR_ANY && lastaddr != INADDR_ANY) 346 | { 347 | printf("\n "); 348 | printhost = 1; 349 | } 350 | 351 | /* host */ 352 | if ((printhost || !everprinthost) && record->addr != INADDR_ANY) 353 | { 354 | char buf[TEXTSIZE]; 355 | 356 | if (record->q > 1 && lastaddr == INADDR_ANY) 357 | printf(" "); 358 | 359 | printf("%s", iptohost(record->addr)); 360 | 361 | safe_strncpy(buf, iptohost(record->addr), TEXTSIZE); 362 | if (strncmp(buf, iptos(record->addr), IPTOSBUFSIZ) != 0) 363 | printf(" (%s)", iptos(record->addr)); 364 | 365 | everprinthost = 1; 366 | } 367 | 368 | /* tcp state */ 369 | if ( ((record->ttl != lastttl) && *(record->state)) || 370 | ((record->ttl == lastttl) && *(record->state) && (strncmp(laststate, record->state, TEXTSIZE) != 0))) 371 | { 372 | printf(" [%s]", record->state); 373 | } 374 | 375 | /* space before ms */ 376 | if (! (record->addr == INADDR_ANY && record->q == 1)) 377 | { 378 | /* if timeout, only print one space. otherwise, two */ 379 | if ((record->addr == INADDR_ANY) || (lastaddr == INADDR_ANY && record->q > 1)) 380 | printf(" "); 381 | else 382 | printf(" "); 383 | } 384 | 385 | if (record->addr == INADDR_ANY) 386 | safe_strncpy(record->string, "*", TEXTSIZE); 387 | 388 | if (! record->string) 389 | fatal("something bad happened\n"); 390 | 391 | printf(record->string, record->delta); 392 | 393 | /* If this will be the last probe, print the newline */ 394 | if (record->q == o_nqueries) 395 | printf("\n"); 396 | 397 | lastttl = record->ttl; 398 | lastaddr = record->addr; 399 | if (*(record->state)) 400 | safe_strncpy(laststate, record->state, TEXTSIZE); 401 | 402 | /* kludge to make debug mode usable */ 403 | if (o_debug) 404 | fprintf(stdout, "\n"); 405 | if (o_debug && record->q != o_nqueries) 406 | fprintf(stdout, "\n"); 407 | 408 | fflush(stdout); 409 | } 410 | -------------------------------------------------------------------------------- /probe.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: c; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4; -*- */ 2 | /* vim:set ts=4 sw=4 ai nobackup nocindent sm: */ 3 | 4 | /* 5 | * tcptraceroute -- A traceroute implementation using TCP packets 6 | * Copyright (c) 2001-2015 Michael C. Toren 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License, version 2, as published 10 | * by the Free Software Foundation. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | * for more details. 16 | * 17 | * A copy of the GNU GPL is available as /usr/doc/copyright/GPL on Debian 18 | * systems, or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html 19 | * You can also obtain it by writing to the Free Software Foundation, Inc., 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 21 | */ 22 | 23 | #if (LIBNET_API_VERSION < 110) 24 | extern int sockfd; 25 | #else 26 | extern libnet_t *libnet_context; 27 | #endif 28 | 29 | /* ECN (RFC2481) */ 30 | #ifndef TH_ECN 31 | #define TH_ECN 0x40 32 | #endif 33 | #ifndef TH_CWR 34 | #define TH_CWR 0x80 35 | #endif 36 | 37 | /* How many IP IDs should allocateid() remember? */ 38 | #define ALLOCATEID_CACHE_SIZE 512 39 | 40 | /* probe() returns this structure, which describes the probe packet sent */ 41 | typedef struct { 42 | int ttl, q; 43 | u_short id, src_prt, dnat_dport; 44 | struct timeval timestamp; 45 | double delta; 46 | u_long addr, dnat_ip; 47 | char *state; 48 | char *string; 49 | } proberecord; 50 | 51 | proberecord *newproberecord(void); 52 | void freeproberecord(proberecord *); 53 | u_short allocateport(u_short); 54 | u_short allocateid(void); 55 | void showprobe(proberecord *); 56 | void initlibnet(void); 57 | void probe(proberecord *, int, int); 58 | -------------------------------------------------------------------------------- /stamp-h.in: -------------------------------------------------------------------------------- 1 | timestamp 2 | -------------------------------------------------------------------------------- /tcptraceroute.1: -------------------------------------------------------------------------------- 1 | .TH TCPTRACEROUTE 1 "2006 March 28" 2 | .SH NAME 3 | tcptraceroute \- A traceroute implementation using TCP packets 4 | .SH SYNOPSIS 5 | .B tcptraceroute [\-nNFSAE] [ \-i 6 | .I interface 7 | .B ] [ \-f 8 | .I first ttl 9 | .B ] 10 | .br 11 | .B [ \-l 12 | .I length 13 | .B ] [ \-q 14 | .I number of queries 15 | .B ] [ \-t 16 | .I tos 17 | .B ] 18 | .br 19 | .B [ \-m 20 | .I max ttl 21 | .B ] [ \-p 22 | .I source port 23 | .B ] [ \-s 24 | .I source address 25 | .B ] 26 | .br 27 | .B [ \-w 28 | .I wait time 29 | .B ] 30 | .I host 31 | .B [ 32 | .I destination port 33 | .B ] 34 | .B [ 35 | .I length 36 | .B ] 37 | .SH DESCRIPTION 38 | .B tcptraceroute 39 | is a traceroute implementation using TCP packets. 40 | .P 41 | The more traditional 42 | .IR traceroute (8) 43 | sends out either UDP or ICMP ECHO packets with a TTL of one, and increments 44 | the TTL until the destination has been reached. By printing the gateways that 45 | generate ICMP time exceeded messages along the way, it is able to determine the 46 | path packets are taking to reach the destination. 47 | .P 48 | The problem is that with the widespread use of firewalls on the modern 49 | Internet, many of the packets that 50 | .IR traceroute (8) 51 | sends out end up being filtered, making it impossible to completely trace the 52 | path to the destination. However, in many cases, these firewalls will permit 53 | inbound TCP packets to specific ports that hosts sitting behind the 54 | firewall are listening for connections on. By sending out TCP SYN packets 55 | instead of UDP or ICMP ECHO packets, 56 | .B tcptraceroute 57 | is able to bypass the most common firewall filters. 58 | .P 59 | It is worth noting that 60 | .B tcptraceroute 61 | never completely establishes a TCP connection with the destination host. 62 | If the host is not listening for incoming connections, it will respond with 63 | an RST indicating that the port is closed. If the host instead responds 64 | with a SYN|ACK, the port is known to be open, and an RST is sent by the 65 | kernel 66 | .B tcptraceroute 67 | is running on to tear down the connection without completing 68 | three\-way handshake. This is the same half\-open scanning technique 69 | that 70 | .IR nmap (1) 71 | uses when passed the 72 | .BR \-sS 73 | flag. 74 | .SH OPTIONS 75 | .B 76 | .IP \-n 77 | Display numeric output, rather than doing a reverse DNS lookup for each hop. 78 | By default, reverse lookups are never attempted on RFC1918 address space, 79 | regardless of the \-n flag. 80 | .B 81 | .IP \-N 82 | Perform a reverse DNS lookup for each hop, including RFC1918 addresses. 83 | .B 84 | .IP \-f 85 | Set the initial TTL used in the first outgoing packet. The default is 1. 86 | .B 87 | .IP \-m 88 | Set the maximum TTL used in outgoing packets. The default is 30. 89 | .B 90 | .IP \-p 91 | Use the specified local TCP port in outgoing packets. The default is to 92 | obtain a free port from the kernel using 93 | .IR bind (2). 94 | Unlike with traditional 95 | .IR traceroute (8), 96 | this number will not increase with each hop. 97 | .B 98 | .IP \-s 99 | Set the source address for outgoing packets. See also the \-i flag. 100 | .B 101 | .IP \-i 102 | Use the specified interface for outgoing packets. 103 | .B 104 | .IP \-q 105 | Set the number of probes to be sent to each hop. The default is 3. 106 | .B 107 | .IP \-w 108 | Set the timeout, in seconds, to wait for a response for each probe. The 109 | default is 3. 110 | .B 111 | .IP \-S 112 | Set the TCP SYN flag in outgoing packets. This is the default, if neither 113 | \-S or \-A is specified. 114 | .B 115 | .B 116 | .IP \-A 117 | Set the TCP ACK flag in outgoing packets. By doing so, it is possible to 118 | trace through stateless firewalls which permit outgoing TCP connections. 119 | .B 120 | .IP \-E 121 | Send ECN SYN packets, as described in RFC2481. 122 | .B 123 | .IP \-t 124 | Set the IP TOS (type of service) to be used in outgoing packets. The 125 | default is not to set any TOS. 126 | .B 127 | .IP \-F 128 | Set the IP "don't fragment" bit in outgoing packets. 129 | .B 130 | .IP \-l 131 | Set the total packet length to be used in outgoing packets. If the length 132 | is greater than the minimum size required to assemble the necessary probe 133 | packet headers, this value is automatically increased. 134 | .B 135 | .IP \-d 136 | Enable debugging, which may or may not be useful. 137 | .B 138 | .IP \-\-dnat 139 | .br 140 | Enable DNAT detection, and display messages when DNAT transitions are 141 | observed. DNAT detection is based on the fact that some NAT devices, 142 | such as some Linux 2.4 kernels, do not correctly rewrite the IP address 143 | of the IP packets quoted in ICMP time-exceeded messages 144 | tcptraceroute solicits, revealing the destination IP address an outbound 145 | probe packet was NATed to. NAT devices which correctly rewrite the IP 146 | address quoted by ICMP messages, such as some Linux 2.6 kernels, will 147 | not be detected. For some target hosts, it may be necessary to use 148 | \-\-dnat in conjunction with \-\-track\-port. See the examples.txt file for 149 | examples. 150 | .B 151 | .IP \-\-no-dnat 152 | .br 153 | Enable DNAT detection for the purposes of correctly identifying ICMP 154 | time-exceeded messages that match up with outbound probe packets, but 155 | do not display messages when a DNAT transition is observed. This is 156 | the default behavior. 157 | .B 158 | .IP \-\-no-dnat-strict 159 | .br 160 | Do not perform any DNAT detection whatsoever. No attempt will be made 161 | match up ICMP time-exceeded messages with outbound probe packets, and 162 | when tracerouting through a NAT device which does not rewrite the IP 163 | addresses of the IP packets quoted in ICMP time-exceeded messages, some 164 | hops along the path may appear to be unresponsive. This option should 165 | not be needed in the vast majority of cases, but may be utilized if 166 | it is suspected that the DNAT detection code is misidentifying ICMP 167 | time-exceeded messages. 168 | .SH EXAMPLES 169 | Please see the 170 | .I examples.txt 171 | file included in the 172 | .B tcptraceroute 173 | distribution for a few real world examples. 174 | .P 175 | To trace the path to a web server listening for connections on port 80: 176 | .P 177 | .RS 178 | .B tcptraceroute webserver 179 | .RE 180 | .P 181 | To trace the path to a mail server listening for connections on port 25: 182 | .P 183 | .RS 184 | .B tcptraceroute mailserver 25 185 | .RE 186 | .SH BUGS 187 | No error checking is performed on the source address specified by the \-s 188 | flag, and it is therefore possible for 189 | .B 190 | tcptraceroute 191 | to send out TCP SYN packets for which it has no chance of seeing a response 192 | to. 193 | .SH AUTHOR 194 | Michael C. Toren 195 | .SH AVAILABILITY 196 | For updates, please see: 197 | .br 198 | .RS 199 | http://michael.toren.net/code/tcptraceroute/ 200 | .RE 201 | .SH "SEE ALSO" 202 | .IR traceroute (8), 203 | .IR ping (8), 204 | .IR nmap (1) 205 | -------------------------------------------------------------------------------- /tcptraceroute.1.html: -------------------------------------------------------------------------------- 1 | 2 | Man page of TCPTRACEROUTE 3 | 4 | 5 |   6 |

NAME

7 | 8 | tcptraceroute - A traceroute implementation using TCP packets 9 |   10 |

SYNOPSIS

11 | 12 | tcptraceroute [-nNFSAE] [ -i 13 | 14 | interface 15 | 16 | ] [ -f 17 | 18 | first ttl 19 | 20 | ] 21 | 22 |
23 | 24 | [ -l 25 | 26 | length 27 | 28 | ] [ -q 29 | 30 | number of queries 31 | 32 | ] [ -t 33 | 34 | tos 35 | 36 | ] 37 | 38 |
39 | 40 | [ -m 41 | 42 | max ttl 43 | 44 | ] [ -p 45 | 46 | source port 47 | 48 | ] [ -s 49 | 50 | source address 51 | 52 | ] 53 | 54 |
55 | 56 | [ -w 57 | 58 | wait time 59 | 60 | ] 61 | 62 | host 63 | 64 | [ 65 | 66 | destination port 67 | 68 | ] 69 | 70 | [ 71 | 72 | length 73 | 74 | ] 75 | 76 |   77 |

DESCRIPTION

78 | 79 | tcptraceroute 80 | 81 | is a traceroute implementation using TCP packets. 82 | 83 | The more traditional 84 | traceroute(8) 85 | 86 | sends out either UDP or ICMP ECHO packets with a TTL of one, and increments 87 | the TTL until the destination has been reached. By printing the gateways that 88 | generate ICMP time exceeded messages along the way, it is able to determine the 89 | path packets are taking to reach the destination. 90 |

91 | 92 | The problem is that with the widespread use of firewalls on the modern 93 | Internet, many of the packets that 94 | traceroute(8) 95 | sends out end up being filtered, making it impossible to completely trace the 96 | path to the destination. However, in many cases, these firewalls will permit 97 | inbound TCP packets to specific ports that hosts sitting behind the 98 | firewall are listening for connections on. By sending out TCP SYN packets 99 | instead of UDP or ICMP ECHO packets, 100 | tcptraceroute 101 | is able to bypass the most common firewall filters. 102 |

103 | 104 | It is worth noting that 105 | tcptraceroute 106 | 107 | never completely establishes a TCP connection with the destination host. 108 | If the host is not listening for incoming connections, it will respond with 109 | an RST indicating that the port is closed. If the host instead responds 110 | with a SYN|ACK, the port is known to be open, and an RST is sent by the 111 | kernel 112 | tcptraceroute 113 | 114 | is running on to tear down the connection without completing 115 | three-way handshake. This is the same half-open scanning technique 116 | that 117 | nmap(1) 118 | 119 | uses when passed the 120 | -sS 121 | 122 | flag. 123 |   124 |

OPTIONS

125 | 126 |
127 |
-n
128 | 129 | 130 | Display numeric output, rather than doing a reverse DNS lookup for each hop. 131 | By default, reverse lookups are never attempted on RFC1918 address space, 132 | regardless of the -n flag. 133 |
-N
134 | 135 | 136 | Perform a reverse DNS lookup for each hop, including RFC1918 addresses. 137 |
-f
138 | 139 | 140 | Set the initial TTL used in the first outgoing packet. The default is 1. 141 |
-m
142 | 143 | 144 | Set the maximum TTL used in outgoing packets. The default is 30. 145 |
-p
146 | 147 | 148 | Use the specified local TCP port in outgoing packets. The default is to 149 | obtain a free port from the kernel using 150 | >bind(2). 151 | 152 | Unlike with traditional 153 | traceroute(8), 154 | 155 | this number will not increase with each hop. 156 |
-s
157 | 158 | 159 | Set the source address for outgoing packets. See also the -i flag. 160 |
-i
161 | 162 | 163 | Use the specified interface for outgoing packets. 164 |
-q
165 | 166 | 167 | Set the number of probes to be sent to each hop. The default is 3. 168 |
-w
169 | 170 | 171 | Set the timeout, in seconds, to wait for a response for each probe. The 172 | default is 3. 173 |
-S
174 | 175 | 176 | Set the TCP SYN flag in outgoing packets. This is the default, if neither 177 | -S or -A is specified. 178 |
-A
179 | 180 | 181 | 182 | 183 | Set the TCP ACK flag in outgoing packets. By doing so, it is possible to 184 | trace through stateless firewalls which permit outgoing TCP connections. 185 |
-E
186 | 187 | 188 | Send ECN SYN packets, as described in RFC2481. 189 |
-t
190 | 191 | 192 | Set the IP TOS (type of service) to be used in outgoing packets. The 193 | default is not to set any TOS. 194 |
-F
195 | 196 | 197 | Set the IP "don't fragment" bit in outgoing packets. 198 |
-l
199 | 200 | 201 | Set the total packet length to be used in outgoing packets. If the length 202 | is greater than the minimum size required to assemble the necessary probe 203 | packet headers, this value is automatically increased. 204 |
-d
205 | 206 | Enable debugging, which may or may not be useful. 207 |

208 | 209 |

--dnat
210 | 211 |
212 | Enable DNAT detection, and display messages when DNAT transitions are 213 | observed. DNAT detection is based on the fact that some NAT devices, 214 | such as some Linux 2.4 kernels, do not correctly rewrite the IP address 215 | of the IP packets quoted in ICMP time-exceeded messages 216 | tcptraceroute solicits, revealing the destination IP address an outbound 217 | probe packet was NATed to. NAT devices which correctly rewrite the IP 218 | address quoted by ICMP messages, such as some Linux 2.6 kernels, will 219 | not be detected. For some target hosts, it may be necessary to use 220 | --dnat in conjunction with --track-port. See the examples.txt file for 221 | examples. 222 |

223 | 224 |

--no-dnat
225 |
226 | Enable DNAT detection for the purposes of correctly identifying ICMP 227 | time-exceeded messages that match up with outbound probe packets, but 228 | do not display messages when a DNAT transition is observed. This is 229 | the default behavior. 230 |

231 | 232 |

--no-dnat-strict
233 |
234 | Do not perform any DNAT detection whatsoever. No attempt will be made 235 | match up ICMP time-exceeded messages with outbound probe packets, and 236 | when tracerouting through a NAT device which does not rewrite the IP 237 | addresses of the IP packets quoted in ICMP time-exceeded messages, some 238 | hops along the path may appear to be unresponsive. This option should 239 | not be needed in the vast majority of cases, but may be utilized if 240 | it is suspected that the DNAT detection code is misidentifying ICMP 241 | time-exceeded messages. 242 |

243 | 244 |

245 |   246 |

EXAMPLES

247 | 248 | Please see the 249 | examples.txt 250 | 251 | file included in the 252 | tcptraceroute 253 | 254 | distribution for a few real world examples. 255 | 256 | To trace the path to a web server listening for connections on port 80: 257 | 258 |
259 | tcptraceroute webserver 260 | 261 |
262 | 263 | 264 | To trace the path to a mail server listening for connections on port 25: 265 | 266 |
267 | tcptraceroute mailserver 25 268 | 269 |
270 | 271 |   272 |

BUGS

273 | 274 | No error checking is performed on the source address specified by the -s 275 | flag, and it is therefore possible for 276 | tcptraceroute 277 | 278 | to send out TCP SYN packets for which it has no chance of seeing a response 279 | to. 280 |   281 |

AUTHOR

282 | 283 | Michael C. Toren <mct@toren.net> 284 |   285 |

AVAILABILITY

286 | 287 | For updates, please see: 288 |
289 | 290 |
291 | http://michael.toren.net/code/tcptraceroute/ 292 |
293 | 294 |   295 |

SEE ALSO

296 | 297 | traceroute(8), 298 | 299 | ping(8), 300 | 301 | nmap(1) 302 | 303 |

304 | 305 |


306 |  

Index

307 |
308 |
NAME
309 |
SYNOPSIS
310 |
DESCRIPTION
311 |
OPTIONS
312 |
EXAMPLES
313 |
BUGS
314 |
AUTHOR
315 |
AVAILABILITY
316 |
SEE ALSO
317 |
318 |
319 | This document was created by man2html. 320 | 321 | 322 | -------------------------------------------------------------------------------- /tcptraceroute.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: c; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4; -*- */ 2 | /* vim:set ts=4 sw=4 ai nobackup nocindent sm: */ 3 | 4 | /* 5 | * tcptraceroute -- A traceroute implementation using TCP packets 6 | * Copyright (c) 2001-2015 Michael C. Toren 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License, version 2, as published 10 | * by the Free Software Foundation. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | * for more details. 16 | * 17 | * A copy of the GNU GPL is available as /usr/doc/copyright/GPL on Debian 18 | * systems, or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html 19 | * You can also obtain it by writing to the Free Software Foundation, Inc., 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | /* Some earlier versions lacked support for double inclusion */ 41 | #ifndef __OpenBSD__ 42 | #include 43 | #endif 44 | 45 | #ifdef HAVE_CONFIG_H 46 | #include "config.h" 47 | #endif 48 | 49 | #define BANNER "Copyright (c) 2001-2015 Michael C. Toren \n\ 50 | Updates are available from http://michael.toren.net/code/tcptraceroute/\n" 51 | 52 | /* Buffer size used for a number of strings, including the pcap filter */ 53 | #define TEXTSIZE 1024 54 | 55 | /* For compatibility with older versions of libnet */ 56 | #if (LIBNET_API_VERSION < 110) 57 | #define LIBNET_IPV4_H LIBNET_IP_H 58 | #define LIBNET_ICMPV4_H LIBNET_ICMP_H 59 | #define LIBNET_DONT_RESOLVE 0 60 | #define LIBNET_RESOLVE 1 61 | #define libnet_addr2name4 libnet_host_lookup 62 | #define libnet_ipv4_hdr libnet_ip_hdr 63 | #define libnet_icmpv4_hdr libnet_icmp_hdr 64 | #endif 65 | 66 | #ifndef LIBNET_VERSION 67 | #define LIBNET_VERSION "UNKNOWN" 68 | #endif 69 | 70 | #ifndef LIBNET_ERRBUF_SIZE 71 | #define LIBNET_ERRBUF_SIZE TEXTSIZE 72 | #endif 73 | 74 | #include "datalink.h" 75 | #include "util.h" 76 | #include "probe.h" 77 | #include "capture.h" 78 | 79 | extern u_long dst_ip, src_ip, isn; 80 | extern u_short src_prt, dst_prt; 81 | extern char *device, *name, *dst, *src; 82 | extern char dst_name[], dst_prt_name[], filter[], errbuf[]; 83 | extern int datalink, offset; 84 | extern int o_minttl, o_maxttl, o_timeout, o_debug, o_numeric, o_pktlen, 85 | o_nqueries, o_dontfrag, o_tos, o_forceport, o_syn, o_ack, o_ecn, 86 | o_nofilter, o_nogetinterfaces, o_noselect, o_trackport, o_dnat, 87 | o_isn; 88 | 89 | extern char *optarg; 90 | extern int optind, opterr, optopt; 91 | -------------------------------------------------------------------------------- /tcptraceroute.lsm: -------------------------------------------------------------------------------- 1 | Begin4 2 | Title: tcptraceroute 3 | Version: 1.5beta7 4 | Entered-date: 2015-03-28 5 | Description: A traceroute implementation using TCP packets 6 | Keywords: network, traceroute, firewall 7 | Author: mct@toren.net (Michael C. Toren) 8 | Maintained-by: mct@toren.net (Michael C. Toren) 9 | Primary-site: http://michael.toren.net/code/tcptraceroute/ 10 | Platforms: Requires libnet and libpcap 11 | Copying-policy: GPL 12 | End 13 | -------------------------------------------------------------------------------- /testsuite.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # vim:set ts=4 sw=4 ai: 3 | # 4 | # (c) Copyright 2003, Michel C. Toren 5 | # mct, Sun Jun 1 23:54:39 EDT 2003 6 | 7 | use strict; 8 | 9 | my $tcptra = shift || "./tcptraceroute"; 10 | my $host = shift || "michael.toren.net"; 11 | my $loopback = shift || "127.0.0.1"; 12 | 13 | print <<"EOT"; 14 | 15 | --------------------------- 16 | tcptraceroute test suite version 1.03 17 | Please send results to mct\@toren.net 18 | --------------------------- 19 | 20 | The current time is ${\(scalar localtime)} (${\(scalar gmtime)} GMT) 21 | 22 | EOT 23 | 24 | sub findsource($) 25 | { 26 | use Socket; 27 | my $host = shift; 28 | my $udp = getprotobyname("udp") or die "getprotobyname: $!\n"; 29 | socket(S, PF_INET, SOCK_DGRAM, $udp) or die "scoket: $!\n"; 30 | my $s = sockaddr_in 1, (inet_aton $host or die "Unknown host: $host\n"); 31 | connect S, $s or die "connect: $!\n"; 32 | return inet_ntoa((sockaddr_in getsockname S)[1]); 33 | } 34 | 35 | sub run($) 36 | { 37 | my $command = shift; 38 | my $output = qx($command); 39 | my $exit = $? >> 8; 40 | my $signal = $? & 127; 41 | $output =~ s/^/> /mg; 42 | $output =~ s/>\s*$//s; 43 | return wantarray ? ($output, $exit, $signal) : $output; 44 | } 45 | 46 | sub uname 47 | { 48 | print "Executing 'uname -a' to determine system type:\n"; 49 | my ($output, $exit, $signal) = run "uname -a 2>&1"; 50 | print $output; 51 | print "Failed! Exit code $exit", 52 | ($signal ? ", signal $signal" : ""), "\n" 53 | if ($exit != 0); 54 | print "\n"; 55 | } 56 | 57 | sub ver 58 | { 59 | print "Executing '$tcptra -d -v' to determine version:\n"; 60 | my ($output, $exit, $signal) = run "$tcptra -d -v 2>&1"; 61 | print $output; 62 | print "Failed! Exit code $exit", 63 | ($signal ? ", signal $signal" : ""), "\n" 64 | if ($exit != 0); 65 | print "\n"; 66 | } 67 | 68 | sub trace($) 69 | { 70 | my $host = shift; 71 | print "Executing '$tcptra $host':\n"; 72 | my ($output, $exit, $signal) = run "$tcptra $host 2>&1"; 73 | print $output; 74 | 75 | print "Failed! Exit code $exit", 76 | ($signal ? ", signal $signal" : ""), "\n" 77 | if ($exit != 0); 78 | 79 | print "\n"; 80 | } 81 | 82 | sub linklayer($) 83 | { 84 | my $host = shift; 85 | print "Attempting to determine linklayer type used to reach $host...\n"; 86 | my ($output, $exit, $signal) = run "$tcptra -d -f 255 -m 255 -q 1 $host 2>&1"; 87 | 88 | if ($exit != 0) 89 | { 90 | print "Failed! Exit code $exit", 91 | ($signal ? ", signal $signal" : ""), "\n\n"; 92 | return; 93 | } 94 | 95 | my ($snaplen) = ($output =~ /^> debug:\s+.*\s+SNAPLEN: (\d+)/m); 96 | my ($datalink) = ($output =~ /^> debug:\s+.*\s+datalink: (\d+)/m); 97 | my ($datalinkoffset)= ($output =~ /^> debug:\s+.*\s+datalinkoffset: (\d+)/m); 98 | my ($datalinkname) = ($output =~ /^> debug:\s+.*\s+datalinkname: ([^\s]+)/m); 99 | my ($device) = ($output =~ /^> debug:\s+.*\s+device: ([^\s]+)/m); 100 | my ($trackport) = ($output =~ /^> debug:\s+.*\s+o_trackport: ([^\s]+)/m); 101 | my ($noselect) = ($output =~ /^> debug:\s+.*\s+o_noselect: ([^\s]+)/m); 102 | 103 | print "Device $device, type $datalinkname, offset $datalinkoffset, snaplen $snaplen, o_noselect $noselect, o_trackport $trackport\n"; 104 | print "\n"; 105 | } 106 | 107 | uname; 108 | ver; 109 | 110 | print "Warning: findsource($loopback) != $loopback, but instead ", 111 | findsource $loopback, "?\n\n" 112 | unless (findsource $loopback eq $loopback); 113 | 114 | trace "-f 1 -m 1 $loopback"; 115 | trace $host; 116 | trace "-f 1 -m 1 " . findsource $host; 117 | linklayer $host; 118 | -------------------------------------------------------------------------------- /traceroute.cgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w -T 2 | # 3 | # (c) Copyright 2001, Michael C. Toren 4 | # 5 | # mct, Fri Jul 20 15:33:21 EDT 2001 6 | # mct, Wed Aug 1 14:39:36 EDT 2001 7 | # mct, Tue Mar 30 08:45:08 EST 2004 8 | # 9 | 10 | use CGI; 11 | use strict; 12 | 13 | my ($q, $me, $bin, $host, $type, $validhost, $validtype, @command); 14 | 15 | $q = new CGI; 16 | $me = (split /\?/, $q->self_url)[0] || ""; 17 | $host = $q->param("h") || ($q->keywords)[0] || ""; 18 | $type = $q->param("t") || "u"; 19 | $ENV{PATH} = "/usr/sbin"; 20 | 21 | $validhost = ($host =~ /^[a-z0-9_\.]+$/i) ? $host : ""; 22 | $validtype = ($type =~ /^[tiu]$/) ? $type : "u"; 23 | 24 | $bin = { 25 | t => { string => "TCP", command => [ qw(/usr/bin/tcptraceroute ) ] }, 26 | u => { string => "UDP", command => [ qw(/usr/sbin/traceroute ) ] }, 27 | i => { string => "ICMP", command => [ qw(/usr/sbin/traceroute -I ) ] } 28 | }; 29 | 30 | print $q->header("text/html"), <<" !"; 31 | 32 | 33 | Traceroute CGI Gateway 34 | 35 | 37 |
38 |
39 | 40 |
41 | traceroute CGI gateway 42 |
43 | 44 |
45 | 46 |
47 | Host:     49 |     50 | 51 |     UDP 53 |     ICMP 55 |     TCP 56 | 58 | 59 |           60 |
61 | 62 |
63 | ! 64 | 65 | exit unless ($host); 66 | 67 | unless ($validhost) 68 | { 69 | print <<" !"; 70 |
71 | ERROR:   Invalid hostname! 72 |
73 | 74 | 75 | ! 76 | exit; 77 | } 78 | 79 | $| = 1; 80 | close STDERR; 81 | open STDERR, ">&STDOUT"; 82 | @command = (@{ $bin->{$validtype}->{command} }, $validhost); 83 | 84 | print "



\n"; 85 | print "% ", join(" ", @command), "\n
\n"; 
86 | #     $bin->{$validtype}->{string}, " packets.\n
\n";
87 | 
88 | system { $command[0] } @command;
89 | print <<"	!";
90 | 	
91 | 92 | 93 | ! 94 | 95 | exit; 96 | -------------------------------------------------------------------------------- /util.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: c; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4; -*- */ 2 | /* vim:set ts=4 sw=4 ai nobackup nocindent sm: */ 3 | 4 | /* 5 | * tcptraceroute -- A traceroute implementation using TCP packets 6 | * Copyright (c) 2001-2015 Michael C. Toren 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License, version 2, as published 10 | * by the Free Software Foundation. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | * for more details. 16 | * 17 | * A copy of the GNU GPL is available as /usr/doc/copyright/GPL on Debian 18 | * systems, or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html 19 | * You can also obtain it by writing to the Free Software Foundation, Inc., 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 21 | */ 22 | 23 | #include "tcptraceroute.h" 24 | #include 25 | 26 | /* 27 | * fatal() and pfatal() are useful stdarg functions from 28 | * namp. debug() and warn() are based on them. 29 | */ 30 | 31 | void fatal(char *fmt, ...) 32 | { 33 | va_list ap; 34 | fflush(stdout); 35 | va_start(ap, fmt); 36 | vfprintf(stderr, fmt, ap); 37 | va_end(ap); 38 | exit(1); 39 | } 40 | 41 | void debug(char *fmt, ...) 42 | { 43 | va_list ap; 44 | if (! o_debug) return; 45 | fflush(stdout); 46 | fprintf(stderr, "debug: "); 47 | va_start(ap, fmt); 48 | vfprintf(stderr, fmt, ap); 49 | va_end(ap); 50 | fflush(stderr); 51 | } 52 | 53 | void warn(char *fmt, ...) 54 | { 55 | va_list ap; 56 | fflush(stdout); 57 | fprintf(stderr, "Warning: "); 58 | va_start(ap, fmt); 59 | vfprintf(stderr, fmt, ap); 60 | va_end(ap); 61 | fflush(stderr); 62 | } 63 | 64 | void pfatal(char *err) 65 | { 66 | debug("errno == %d\n", errno); 67 | fflush(stdout); 68 | perror(err); 69 | exit(1); 70 | } 71 | 72 | void usage(void) 73 | { 74 | printf("\n%s %s\n%s\n", PACKAGE, VERSION, BANNER); 75 | fatal("\ 76 | Usage: %s [-nNFSAE] [-i ] [-f ]\n\ 77 | [-l ] [-q ] [-t ]\n\ 78 | [-m ] [-pP] ] [-s ]\n\ 79 | [-w ] [destination port] [packet length]\n\n", name); 80 | } 81 | 82 | void about(void) 83 | { 84 | printf("\n%s %s\n%s\n", PACKAGE, VERSION, BANNER); 85 | exit(0); 86 | } 87 | 88 | /* 89 | * realloc(3) or bust! 90 | */ 91 | 92 | void *xrealloc(void *oldp, int size) 93 | { 94 | void *p; 95 | 96 | if (!oldp) 97 | p = malloc(size); 98 | else 99 | p = realloc(oldp, size); 100 | 101 | if (!p) 102 | fatal("Out of memory! Could not reallocate %d bytes!\n", size); 103 | 104 | memset(p, 0, size); 105 | return p; 106 | } 107 | 108 | /* 109 | * Same as strncpy and snprintf, but always be sure the result is terminated. 110 | */ 111 | 112 | char *safe_strncpy(char *dst, char *src, int size) 113 | { 114 | dst[size-1] = '\0'; 115 | return strncpy(dst, src, size-1); 116 | } 117 | 118 | int safe_snprintf(char *s, int size, char *fmt, ...) 119 | { 120 | va_list ap; 121 | int ret; 122 | 123 | va_start(ap, fmt); 124 | ret = vsnprintf(s, size, fmt, ap); 125 | s[size-1] = '\0'; 126 | va_end(ap); 127 | 128 | return ret; 129 | } 130 | 131 | /* 132 | * return a pointer to a string containing only the 133 | * printable characters of the string passed to it. 134 | */ 135 | 136 | char *sprintable(char *s) 137 | { 138 | static char buf[TEXTSIZE]; 139 | int i; 140 | 141 | if (s && s[0]) 142 | safe_strncpy(buf, s, TEXTSIZE); 143 | else 144 | safe_strncpy(buf, "(empty)", TEXTSIZE); 145 | 146 | for (i = 0; buf[i]; i++) 147 | if (! isprint((u_char) buf[i])) 148 | buf[i] = '?'; 149 | 150 | return buf; 151 | } 152 | 153 | /* 154 | * isdigit() across an entire string. 155 | */ 156 | 157 | int isnumeric(char *s) 158 | { 159 | int i; 160 | 161 | if (!s || !s[0]) 162 | return 0; 163 | 164 | for (i = 0; s[i]; i++) 165 | if (! isdigit((u_char) s[i])) 166 | return 0; 167 | 168 | return 1; 169 | } 170 | 171 | /* 172 | * Compute the difference between two timeval structures. 173 | */ 174 | 175 | struct timeval tvdiff(struct timeval *tv1, struct timeval *tv2) 176 | { 177 | struct timeval tvdiff; 178 | 179 | tvdiff.tv_sec = tv1->tv_sec - tv2->tv_sec; 180 | tvdiff.tv_usec = tv1->tv_usec - tv2->tv_usec; 181 | 182 | if ((tvdiff.tv_sec > 0) && (tvdiff.tv_usec < 0)) 183 | { 184 | tvdiff.tv_usec += 1000000L; 185 | tvdiff.tv_sec--; 186 | } 187 | 188 | else if ((tvdiff.tv_sec < 0) && (tvdiff.tv_usec > 0)) 189 | { 190 | tvdiff.tv_usec -= 1000000L; 191 | tvdiff.tv_sec++; 192 | } 193 | 194 | return tvdiff; 195 | } 196 | 197 | /* 198 | * Is the timeval less than, equal to, or greater than zero? 199 | */ 200 | 201 | int tvsign(struct timeval *tv) 202 | { 203 | if (tv->tv_sec < 0) return -1; 204 | 205 | if (tv->tv_sec == 0) 206 | { 207 | if (tv->tv_usec < 0) return -1; 208 | if (tv->tv_usec == 0) return 0; 209 | if (tv->tv_usec > 0) return 1; 210 | } 211 | 212 | if (tv->tv_sec > 0) return 1; 213 | 214 | return -1; 215 | } 216 | 217 | /* 218 | * Inspired by libnet_host_lookup(), but I needed more than 2 buffers while 219 | * I was debugging. I really could get by with only 2 now, but *shrug*. 220 | */ 221 | 222 | char *iptos(u_long in) 223 | { 224 | static char output[IPTOSBUFFERS][IPTOSBUFSIZ]; 225 | static short which; 226 | u_char *p; 227 | 228 | p = (u_char *)∈ 229 | which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1); 230 | safe_snprintf(output[which], IPTOSBUFSIZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 231 | return output[which]; 232 | } 233 | 234 | /* 235 | * A wrapper for libnet_addr2name4(), with the option not to resolve 236 | * RFC1918 space. 237 | */ 238 | 239 | char *iptohost(u_long in) 240 | { 241 | u_char *p = (u_char *)∈ 242 | 243 | if ((o_numeric > -1) && 244 | ((p[0] == 10) || 245 | (p[0] == 192 && p[1] == 168) || 246 | (p[0] == 172 && p[1] >= 16 && p[1] <= 31))) 247 | { 248 | debug("Not attempting to resolve RFC1918 address %s\n", iptos(in)); 249 | return iptos(in); 250 | } 251 | 252 | return (char *)libnet_addr2name4(in, 253 | o_numeric > 0 ? LIBNET_DONT_RESOLVE : LIBNET_RESOLVE); 254 | } 255 | 256 | /* 257 | * Useful for debugging; dump #define's and command line options. 258 | */ 259 | 260 | void debugoptions(void) 261 | { 262 | if (! o_debug) 263 | return; 264 | 265 | debug("debugoptions():\n"); 266 | 267 | debug("%16s: %-2d %14s: %-2d %16s: %-2d\n", 268 | "TEXTSIZE", TEXTSIZE, 269 | "SNAPLEN", SNAPLEN, 270 | "IPTOSBUFFERS", IPTOSBUFFERS); 271 | 272 | debug("%16s: %-3d %15s: %-2d %16s: %-2d\n", 273 | "ALLOCATEID_CACHE", ALLOCATEID_CACHE_SIZE, 274 | "datalink", datalink, 275 | "datalinkoffset", datalinkoffset(datalink)); 276 | 277 | debug("%16s: %-2d %16s: %-2d %16s: %-2d\n", 278 | "o_minttl", o_minttl, 279 | "o_maxttl", o_maxttl, 280 | "o_timeout", o_timeout); 281 | 282 | debug("%16s: %-2d %16s: %-2d %16s: %-2d\n", 283 | "o_debug", o_debug, 284 | "o_numeric", o_numeric, 285 | "o_pktlen", o_pktlen); 286 | 287 | debug("%16s: %-2d %16s: %-2d %16s: %-2d\n", 288 | "o_nqueries", o_nqueries, 289 | "o_dontfrag", o_dontfrag, 290 | "o_tos", o_tos); 291 | 292 | debug("%16s: %-2d %16s: %-2d %16s: %-2d\n", 293 | "o_forceport", o_forceport, 294 | "o_syn", o_syn, 295 | "o_ack", o_ack); 296 | 297 | debug("%16s: %-2d %16s: %d %16s: %-2d\n", 298 | "o_ecn", o_ecn, 299 | "o_nofilter", o_nofilter, 300 | "o_nogetinterfaces", o_nogetinterfaces); 301 | 302 | debug("%16s: %-2d %16s: %-12s %s: %s\n", 303 | "o_trackport", o_trackport, 304 | "datalinkname", datalinkname(datalink), 305 | "device", device); 306 | 307 | debug("%16s: %-2d %16s: %-2d %16s: %-10ld\n", 308 | "o_noselect", o_noselect, 309 | "o_dnat", o_dnat, 310 | "isn", isn); 311 | } 312 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: c; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4; -*- */ 2 | /* vim:set ts=4 sw=4 ai nobackup nocindent sm: */ 3 | 4 | /* 5 | * tcptraceroute -- A traceroute implementation using TCP packets 6 | * Copyright (c) 2001-2015 Michael C. Toren 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License, version 2, as published 10 | * by the Free Software Foundation. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | * for more details. 16 | * 17 | * A copy of the GNU GPL is available as /usr/doc/copyright/GPL on Debian 18 | * systems, or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html 19 | * You can also obtain it by writing to the Free Software Foundation, Inc., 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 21 | */ 22 | 23 | #define IPTOSBUFFERS 12 24 | #define IPTOSBUFSIZ (4*3+3+1) /* Four three-digit numbers, three dots, and NUL */ 25 | 26 | /* 27 | * A generic wrapper for libnet_name_resolve and libnet_name2addr4, because 28 | * it's annoying to have #ifdef's all over the place to support both versions 29 | * of libnet. 30 | */ 31 | 32 | #if (LIBNET_API_VERSION < 110) 33 | #define hosttoip(hostname, numeric) \ 34 | libnet_name_resolve((u_char *)hostname, numeric) 35 | #else 36 | #define hosttoip(hostname, numeric) \ 37 | libnet_name2addr4(libnet_context, (char *)hostname, numeric) 38 | #endif 39 | 40 | void fatal(char *, ...); 41 | void debug(char *, ...); 42 | void warn(char *, ...); 43 | void pfatal(char *); 44 | void usage(void); 45 | void about(void); 46 | void *xrealloc(void *, int); 47 | char *safe_strncpy(char *, char *, int); 48 | int safe_snprintf(char *, int, char *, ...); 49 | char *sprintable(char *); 50 | int isnumeric(char *); 51 | struct timeval tvdiff(struct timeval *, struct timeval *); 52 | int tvsign(struct timeval *); 53 | char *iptos(u_long); 54 | char *iptohost(u_long); 55 | void debugoptions(void); 56 | --------------------------------------------------------------------------------