From 86534f46e150856fcce76af5c7598d354fb32ca9 Mon Sep 17 00:00:00 2001 From: Gerald Combs Date: Wed, 16 Sep 1998 02:39:15 +0000 Subject: Initial revision svn path=/trunk/; revision=2 --- AUTHORS | 36 + COPYING | 482 ++++++++++++ ChangeLog | 0 INSTALL | 182 +++++ Makefile.am | 69 ++ Makefile.in | 475 ++++++++++++ NEWS | 118 +++ README | 112 +++ acconfig.h | 5 + aclocal.m4 | 335 +++++++++ capture.c | 501 +++++++++++++ capture.h | 49 ++ config.h | 24 + config.h.in | 23 + configure | 2075 +++++++++++++++++++++++++++++++++++++++++++++++++++ configure.in | 51 ++ doc/Makefile | 5 + doc/ethereal.pod | 233 ++++++ ethereal.1 | 427 +++++++++++ ethereal.c | 440 +++++++++++ ethereal.h | 79 ++ ethertype.c | 107 +++ etypes.h | 67 ++ file.c | 356 +++++++++ file.h | 99 +++ filter.c | 472 ++++++++++++ filter.h | 55 ++ image/icon-excl.xpm | 88 +++ install-sh | 250 +++++++ menu.c | 215 ++++++ menu.h | 41 + missing | 188 +++++ mkinstalldirs | 40 + packet-arp.c | 122 +++ packet-bootp.c | 487 ++++++++++++ packet-data.c | 51 ++ packet-dns.c | 442 +++++++++++ packet-eth.c | 125 ++++ packet-ip.c | 319 ++++++++ packet-ipv6.c | 105 +++ packet-ipv6.h | 8 + packet-ipx.c | 492 ++++++++++++ packet-llc.c | 163 ++++ packet-lpd.c | 154 ++++ packet-ospf.c | 550 ++++++++++++++ packet-ospf.h | 127 ++++ packet-ppp.c | 79 ++ packet-raw.c | 72 ++ packet-rip.c | 144 ++++ packet-rip.h | 23 + packet-tcp.c | 116 +++ packet-tr.c | 253 +++++++ packet-trmac.c | 322 ++++++++ packet-udp.c | 92 +++ packet.c | 216 ++++++ packet.h | 354 +++++++++ print.c | 509 +++++++++++++ print.h | 47 ++ print.ps | 100 +++ ps.c | 87 +++ ps.h | 35 + rdps.c | 185 +++++ resolv.c | 269 +++++++ resolv.h | 39 + snprintf.c | 822 ++++++++++++++++++++ snprintf.h | 232 ++++++ stamp-h.in | 1 + util.c | 125 ++++ util.h | 49 ++ 69 files changed, 15015 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 NEWS create mode 100644 README create mode 100644 acconfig.h create mode 100644 aclocal.m4 create mode 100644 capture.c create mode 100644 capture.h create mode 100644 config.h create mode 100644 config.h.in create mode 100755 configure create mode 100644 configure.in create mode 100644 doc/Makefile create mode 100644 doc/ethereal.pod create mode 100644 ethereal.1 create mode 100644 ethereal.c create mode 100644 ethereal.h create mode 100644 ethertype.c create mode 100644 etypes.h create mode 100644 file.c create mode 100644 file.h create mode 100644 filter.c create mode 100644 filter.h create mode 100644 image/icon-excl.xpm create mode 100755 install-sh create mode 100644 menu.c create mode 100644 menu.h create mode 100755 missing create mode 100755 mkinstalldirs create mode 100644 packet-arp.c create mode 100644 packet-bootp.c create mode 100644 packet-data.c create mode 100644 packet-dns.c create mode 100644 packet-eth.c create mode 100644 packet-ip.c create mode 100644 packet-ipv6.c create mode 100644 packet-ipv6.h create mode 100644 packet-ipx.c create mode 100644 packet-llc.c create mode 100644 packet-lpd.c create mode 100644 packet-ospf.c create mode 100644 packet-ospf.h create mode 100644 packet-ppp.c create mode 100644 packet-raw.c create mode 100644 packet-rip.c create mode 100644 packet-rip.h create mode 100644 packet-tcp.c create mode 100644 packet-tr.c create mode 100644 packet-trmac.c create mode 100644 packet-udp.c create mode 100644 packet.c create mode 100644 packet.h create mode 100644 print.c create mode 100644 print.h create mode 100644 print.ps create mode 100644 ps.c create mode 100644 ps.h create mode 100644 rdps.c create mode 100644 resolv.c create mode 100644 resolv.h create mode 100644 snprintf.c create mode 100644 snprintf.h create mode 100644 stamp-h.in create mode 100644 util.c create mode 100644 util.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000000..d2f4f82996 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,36 @@ +Original Author +-------- ------ +Gerald Combs + + +Contributors +------------ +Gilbert Ramirez Jr. { + /* add your info here */ +} + +Hannes R. Boehm { + http://hannes.boehm.org/ + + OSPFv2 + RIPv1, RIPv2 + started IPv6 support +} + +Mike Hall { + /* add your info here */ +} + +Bobo Rajec { + /* add your info here */ +} + +Laurent Deniel { + /* add your info here */ +} + +Alain Magloire was kind enough to +give his permission to use his version of snprintf.c. + +Dan Lasley gave permission for his dumpit() hex-dump +routine to be used. diff --git a/COPYING b/COPYING new file mode 100644 index 0000000000..bf50f20de6 --- /dev/null +++ b/COPYING @@ -0,0 +1,482 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307 USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000000..e69de29bb2 diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000000..b42a17ac46 --- /dev/null +++ b/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000000..2c148261ab --- /dev/null +++ b/Makefile.am @@ -0,0 +1,69 @@ +bin_PROGRAMS = ethereal + +man_MANS = ethereal.1 + +ethereal_SOURCES = \ + capture.c \ + ethereal.c \ + ethertype.c \ + file.c \ + filter.c \ + menu.c \ + packet.c \ + packet-arp.c \ + packet-bootp.c \ + packet-data.c \ + packet-dns.c \ + packet-eth.c \ + packet-llc.c \ + packet-lpd.c \ + packet-ip.c \ + packet-ipv6.c \ + packet-ipx.c \ + packet-ospf.c \ + packet-ppp.c \ + packet-raw.c \ + packet-rip.c \ + packet-tcp.c \ + packet-tr.c \ + packet-trmac.c \ + packet-udp.c \ + print.c \ + ps.c \ + resolv.c \ + util.c \ + capture.h \ + config.h \ + ethereal.h \ + etypes.h \ + file.h \ + filter.h \ + menu.h \ + packet.h \ + packet-ipv6.h \ + packet-ospf.h \ + packet-rip.h \ + print.h \ + ps.h \ + resolv.h \ + snprintf.h \ + util.h + +ps.c: print.ps rdps + ./rdps print.ps ps.c + +rdps: rdps.c + $(CC) -o rdps rdps.c + +EXTRA_ethereal_SOURCES = @SNPRINTF_C@ +ethereal_DEPENDENCIES = @SNPRINTF_O@ +LDADD = @SNPRINTF_O@ + +EXTRA_DIST = \ + ethereal.1 \ + snprintf.c \ + rdps.c \ + print.ps \ + image/icon-excl.xpm \ + doc/Makefile \ + doc/ethereal.pod diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000000..9881ae67d1 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,475 @@ +# Makefile.in generated automatically by automake 1.3 from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DISTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_CONFIG = @GTK_CONFIG@ +GTK_LIBS = @GTK_LIBS@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +SNPRINTF_C = @SNPRINTF_C@ +SNPRINTF_O = @SNPRINTF_O@ +VERSION = @VERSION@ + +bin_PROGRAMS = ethereal + +man_MANS = ethereal.1 + +ethereal_SOURCES = \ + capture.c \ + ethereal.c \ + ethertype.c \ + file.c \ + filter.c \ + menu.c \ + packet.c \ + packet-arp.c \ + packet-bootp.c \ + packet-data.c \ + packet-dns.c \ + packet-eth.c \ + packet-llc.c \ + packet-lpd.c \ + packet-ip.c \ + packet-ipv6.c \ + packet-ipx.c \ + packet-ospf.c \ + packet-ppp.c \ + packet-raw.c \ + packet-rip.c \ + packet-tcp.c \ + packet-tr.c \ + packet-trmac.c \ + packet-udp.c \ + print.c \ + ps.c \ + resolv.c \ + util.c \ + capture.h \ + config.h \ + ethereal.h \ + etypes.h \ + file.h \ + filter.h \ + menu.h \ + packet.h \ + packet-ipv6.h \ + packet-ospf.h \ + packet-rip.h \ + print.h \ + ps.h \ + resolv.h \ + snprintf.h \ + util.h + +EXTRA_ethereal_SOURCES = @SNPRINTF_C@ +ethereal_DEPENDENCIES = @SNPRINTF_O@ +LDADD = @SNPRINTF_O@ + +EXTRA_DIST = \ + ethereal.1 \ + snprintf.c \ + rdps.c \ + print.ps \ + image/icon-excl.xpm \ + doc/Makefile \ + doc/ethereal.pod +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +PROGRAMS = $(bin_PROGRAMS) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +ethereal_OBJECTS = capture.o ethereal.o ethertype.o file.o filter.o \ +menu.o packet.o packet-arp.o packet-bootp.o packet-data.o packet-dns.o \ +packet-eth.o packet-llc.o packet-lpd.o packet-ip.o packet-ipv6.o \ +packet-ipx.o packet-ospf.o packet-ppp.o packet-raw.o packet-rip.o \ +packet-tcp.o packet-tr.o packet-trmac.o packet-udp.o print.o ps.o \ +resolv.o util.o +ethereal_LDADD = $(LDADD) +ethereal_LDFLAGS = +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) +LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ +man1dir = $(mandir)/man1 +MANS = $(man_MANS) + +NROFF = nroff +DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \ +Makefile.in NEWS acconfig.h aclocal.m4 config.h.in configure \ +configure.in install-sh missing mkinstalldirs stamp-h.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +SOURCES = $(ethereal_SOURCES) $(EXTRA_ethereal_SOURCES) +OBJECTS = $(ethereal_OBJECTS) + +all: Makefile $(PROGRAMS) $(MANS) config.h + +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): configure.in + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure + $(SHELL) ./config.status --recheck +$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +config.h: stamp-h + @: +stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=config.h \ + $(SHELL) ./config.status + @echo timestamp > stamp-h +$(srcdir)/config.h.in: $(srcdir)/stamp-h.in +$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h + cd $(top_srcdir) && $(AUTOHEADER) + @echo timestamp > $(srcdir)/stamp-h.in + +mostlyclean-hdr: + +clean-hdr: + +distclean-hdr: + -rm -f config.h + +maintainer-clean-hdr: + +mostlyclean-binPROGRAMS: + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +distclean-binPROGRAMS: + +maintainer-clean-binPROGRAMS: + +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(bin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \ + done + +.c.o: + $(COMPILE) -c $< + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +ethereal: $(ethereal_OBJECTS) $(ethereal_DEPENDENCIES) + @rm -f ethereal + $(LINK) $(ethereal_LDFLAGS) $(ethereal_OBJECTS) $(ethereal_LDADD) $(LIBS) + +install-man1: + $(mkinstalldirs) $(DESTDIR)$(man1dir) + @list='$(man1_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \ + done + +uninstall-man1: + @list='$(man1_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \ + rm -f $(DESTDIR)$(man1dir)/$$inst; \ + done +install-man: $(MANS) + @$(NORMAL_INSTALL) + $(MAKE) install-man1 +uninstall-man: + @$(NORMAL_UNINSTALL) + $(MAKE) uninstall-man1 + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP) + +TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) \ + && $(MAKE) dvi \ + && $(MAKE) check \ + && $(MAKE) install \ + && $(MAKE) installcheck \ + && $(MAKE) dist + -rm -rf $(distdir) + @echo "========================"; \ + echo "$(distdir).tar.gz is ready for distribution"; \ + echo "========================" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + $(mkinstalldirs) $(distdir)/doc $(distdir)/image + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done +capture.o: capture.c config.h packet.h file.h capture.h etypes.h util.h \ + image/icon-excl.xpm +ethereal.o: ethereal.c config.h packet.h file.h ethereal.h menu.h \ + etypes.h print.h resolv.h +ethertype.o: ethertype.c config.h packet.h ethereal.h etypes.h +file.o: file.c config.h packet.h file.h ethereal.h util.h \ + image/icon-excl.xpm +filter.o: filter.c config.h filter.h packet.h file.h menu.h +menu.o: menu.c config.h menu.h ethereal.h capture.h filter.h packet.h \ + print.h +packet-arp.o: packet-arp.c config.h ethereal.h packet.h etypes.h +packet-bootp.o: packet-bootp.c config.h packet.h ethereal.h etypes.h +packet-data.o: packet-data.c config.h ethereal.h packet.h +packet-dns.o: packet-dns.c config.h packet.h +packet-eth.o: packet-eth.c config.h packet.h ethereal.h etypes.h +packet-ip.o: packet-ip.c config.h ethereal.h packet.h etypes.h resolv.h +packet-ipv6.o: packet-ipv6.c config.h ethereal.h packet.h packet-ipv6.h \ + etypes.h +packet-ipx.o: packet-ipx.c config.h ethereal.h packet.h +packet-llc.o: packet-llc.c config.h packet.h ethereal.h etypes.h +packet-lpd.o: packet-lpd.c config.h packet.h ethereal.h etypes.h +packet-ospf.o: packet-ospf.c config.h ethereal.h packet.h packet-ospf.h +packet-ppp.o: packet-ppp.c config.h packet.h ethereal.h +packet-raw.o: packet-raw.c config.h packet.h ethereal.h +packet-rip.o: packet-rip.c config.h ethereal.h packet.h packet-rip.h +packet-tcp.o: packet-tcp.c config.h ethereal.h packet.h +packet-tr.o: packet-tr.c config.h packet.h ethereal.h etypes.h +packet-trmac.o: packet-trmac.c config.h packet.h ethereal.h etypes.h +packet-udp.o: packet-udp.c config.h ethereal.h packet.h resolv.h +packet.o: packet.c config.h packet.h ethereal.h etypes.h file.h +print.o: print.c config.h packet.h print.h +ps.o: ps.c ps.h +resolv.o: resolv.c config.h packet.h resolv.h +util.o: util.c config.h util.h image/icon-excl.xpm + +info: +dvi: +check: all + $(MAKE) +installcheck: +install-exec: install-binPROGRAMS + @$(NORMAL_INSTALL) + +install-data: install-man + @$(NORMAL_INSTALL) + +install: install-exec install-data all + @: + +uninstall: uninstall-binPROGRAMS uninstall-man + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: + $(mkinstalldirs) $(DATADIR)$(bindir) $(DESTDIR)$(mandir)/man1 + + +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(DISTCLEANFILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +mostlyclean: mostlyclean-hdr mostlyclean-binPROGRAMS \ + mostlyclean-compile mostlyclean-tags \ + mostlyclean-generic + +clean: clean-hdr clean-binPROGRAMS clean-compile clean-tags \ + clean-generic mostlyclean + +distclean: distclean-hdr distclean-binPROGRAMS distclean-compile \ + distclean-tags distclean-generic clean + -rm -f config.status + +maintainer-clean: maintainer-clean-hdr maintainer-clean-binPROGRAMS \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-generic distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + -rm -f config.status + +.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ +mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ +maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile install-man1 uninstall-man1 install-man \ +uninstall-man tags mostlyclean-tags distclean-tags clean-tags \ +maintainer-clean-tags distdir info dvi installcheck install-exec \ +install-data install uninstall all installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean + + +ps.c: print.ps rdps + ./rdps print.ps ps.c + +rdps: rdps.c + $(CC) -o rdps rdps.c + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/NEWS b/NEWS new file mode 100644 index 0000000000..dbbbb64b83 --- /dev/null +++ b/NEWS @@ -0,0 +1,118 @@ +Overview of changes in Ethereal 0.3.15: + +* OSPF fixes (Hannes) +* Preliminary IPv6 support (Hannes) +* Name resolution (Laurent) +* Font and help option (Laurent) +* Token ring fixes (Gilbert) +* DLT_RAW #define fixes (Laurent, Hannes and a few others) + +Overview of changes in Ethereal 0.3.14: + +* Added Laurent's fixes to pntoh[sl]. +* RIP fixes (Laurent) +* Added Gilbert's BOOTP code. + +Overview of changes in Ethereal 0.3.13: + +* Made the tree items "sticky" +* Expanded the pntoh[sl] macros, fixed alignment problems with IPX code. +* Changes to packet-ppp and packet-raw + +Overview of changes in Ethereal 0.3.12: + +* RIP support (Hannes) +* LPR/LPD support (Gilbert) +* Changes to #includes to improve compatibility. + +Overview of changes in Ethereal 0.3.11: + +* Fixed a file capture bug. + +Overview of changes in Ethereal 0.3.10: + +* Fixed a Makefile bug with the new snprintf package. + +Overview of changes in Ethereal 0.3.9: + +* Switched to a different version of snprintf.c. +* Minor bug fixes. +* Fixes to Makefile.am. + +Overview of changes in Ethereal 0.3.8: + +* PostScript(R) output (Gilbert) +* More OSPF code (Hannes) +* Enhanced DNS (Bobo) + +Overview of changes in Ethereal 0.3.7: + +* Enhanced OSPF (Hannes) +* Fixed small bug in filter dialog. + +Overview of changes in Ethereal 0.3.6: + +* Added OSPF support, thanks to Hannes Boehm. +* Added -B, -P, and -T flags. + +Overview of changes in Ethereal 0.3.5: + +* Command line argument fixes/upgrades. +* Compatibility fixes. +* Initial pod/man page documentation. +* Miscellaneous changes to the way things are done in capture.c. +* Initial support for DNS and IGMP. + +Overview of changes in Ethereal 0.3.4: + +* Printer preferences dialog added (Gilbert) +* Misc fixes/upgrades. + +Overview of changes in Ethereal 0.3.3: + +* Added PPP support, thanks to Mike Hall. +* Added dialogs for errors/warnings. +* Support for the -r flag was added. +* Other minor fixes/upgrades. + +Overview of changes in Ethereal 0.3.2: + +* Misc bug fixes & minor enhancements. +* Added preliminary ICMP support +* Added preliminary printing support (Gilbert) + +Overview of changes in Ethereal 0.3.1: + +* Fixed bug that prevented capturing with a filter. +* Fixed misc. header problems. + +Overview of changes in Ethereal 0.3.0: + +* Initial support for filters. +* Fixes/enhancements for IPX and token ring (Gilbert). + +Overview of changes in Ethereal 0.2.3: + +* Added support for IPX, thanks to Gilbert. + +Overview of changes in Ethereal 0.2.2: + +* Added support for token ring, thanks to Gilbert Ramirez, Jr. + +Overview of changes in Ethereal 0.2.1: + +* Internal structs for ARP/RARP, IP, TCP, and UDP were created. Trying to + sort out which #includes were needed for each system was just too much of + a hassle. +* Added support for systems that don't have snprintf() and vsnprintf(), thanks + to Theo de Raadt. +* Minor changes to the README file. + +Overview of changes in Ethereal 0.2.0: + +* Initial public release. +* GNU autoconf-ified distribution +* Runs under Linux 2.0.x and Solaris 2.6. +* Requires GTK+ (1.0.1 tested) and libpcap (0.4a6 tested) +* For optimal results under Linux, the Karpski libpcap should be used. +* General documentation and a minimal web site have been prepared. diff --git a/README b/README new file mode 100644 index 0000000000..859859a6e7 --- /dev/null +++ b/README @@ -0,0 +1,112 @@ +General Information +------- ----------- + +Ethereal is a network traffic analyzer for Unix-ish operating systems. +It is based on GTK+, a graphical user interface library, and libpcap, +a packet capture and filtering library. + +The official home of Ethereal is + + http://ethereal.zing.org + +The latest distribution can be found in the subdirectory + + http://ethereal.zing.org/distribution + + +Installation +------------ + +Ethereal is known to compile and run under Linux (2.0.35) and Solaris +(2.6). It should run on other systems without too much trouble. + + +Installation Checklist (Short): + + [ ] 1. Unpack the archive. + + [ ] 2. Run './configure; make; make install; make install-man'. + If there are any problems, read on: + + +Installation Checklist (Long): + + [ ] 0. This is alpha software. Beware. + + [ ] 1. Make sure you have GTK+ installed. Try running 'gtk-config + --version'. If you need to install/reinstall GTK, you can find + it at + + http://www.gtk.org . + + Ethereal should work with the latest stable (1.0.x) version, but + I've had reports that it doesn't compile with the development + (1.1.x) tree. + + [ ] 2. Make sure you have libpcap installed. The latest version can be + found at + + ftp://ftp.ee.lbl.gov . + + Make sure you install the headers ('make install-incl') when you + install the library. + + [ ] 3. Run './configure' in the Ethereal distribution directory. + Running './configure --help' displays a list of options. + The file 'INSTALL' contains general instructions for running + 'configure'. + + [ ] 4. Run 'make'. Hopefully, you won't run into any problems. + + [ ] 5. Run './ethereal', and make sure things are working. You must + have root privileges in order to capture live data. + + [ ] 6. Run 'make install'. If you wish to install the man page, run + 'make install-man'. You're done. + + +Usage +----- + +In order to capture packets from the network, you need to be running +as root. Although it might be tempting to make the Ethereal executable +setuid root, please don't - alpha code is by nature not very robust, and +liable to contain security holes. + +The filtering mechanism is far from complete. Until the interface +solidifies, here's a description of what each component of the filter +dialog: + + - 'Filter name' entry: Gives a name to the filter you are about to create + or modify, e.g. 'Web and DNS traffic' + + - 'Filter string' entry: The text describing the filtering action to + take. It must have the same format as tcpdump filter strings (both + programs use the same underlying library), e.g. + + 'tcp port 80 or tcp port 443 or port 53' + + - 'New' button: If there is text in the two entry boxes, adds it to the + list. + + - 'Change' button: Modifies the currently selected list item to match + what's in the two entry boxes. + + - 'Copy' button: Makes a copy of the currently-selected list item. + + - 'Delete' button: Deletes the currently-selected list item. + + - 'OK' button: Sets the selected list item as the active filter. If + nothing is selected, turns filtering off. + + - 'Save' button: Saves the current filter list in + $HOME/.ethereal/filters. + + - 'Cancel' button: Closes the window without making changes. + + +Disclaimer +---------- + +There is no warranty, expressed or implied, associated with this product. +Use at your own risk. diff --git a/acconfig.h b/acconfig.h new file mode 100644 index 0000000000..789385ab98 --- /dev/null +++ b/acconfig.h @@ -0,0 +1,5 @@ +#undef PACKAGE + +#undef VERSION + +#undef HAVE_SOCKADDR_SA_LEN diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000000..de2d1a35e6 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,335 @@ +dnl aclocal.m4 generated automatically by aclocal 1.3 + +dnl Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +dnl This Makefile.in is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN(AM_INIT_AUTOMAKE, +[AC_REQUIRE([AM_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE") +AC_DEFINE_UNQUOTED(VERSION, "$VERSION")) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + + +# serial 1 + +AC_DEFUN(AM_PROG_INSTALL, +[AC_REQUIRE([AC_PROG_INSTALL]) +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' +AC_SUBST(INSTALL_SCRIPT)dnl +]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN(AM_SANITY_CHECK, +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN(AM_MISSING_PROG, +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + +# Configure paths for GTK+ +# Owen Taylor 97-11-3 + +dnl AM_PATH_GTK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for GTK, and define GTK_CFLAGS and GTK_LIBS +dnl +AC_DEFUN(AM_PATH_GTK, +[dnl +dnl Get the cflags and libraries from the gtk-config script +dnl +AC_ARG_WITH(gtk-prefix,[ --with-gtk-prefix=PFX Prefix where GTK is installed (optional)], + gtk_config_prefix="$withval", gtk_config_prefix="") +AC_ARG_WITH(gtk-exec-prefix,[ --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)], + gtk_config_exec_prefix="$withval", gtk_config_exec_prefix="") +AC_ARG_ENABLE(gtktest, [ --disable-gtktest Do not try to compile and run a test GTK program], + , enable_gtktest=yes) + + if test x$gtk_config_exec_prefix != x ; then + gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix" + if test x${GTK_CONFIG+set} != xset ; then + GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config + fi + fi + if test x$gtk_config_prefix != x ; then + gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix" + if test x${GTK_CONFIG+set} != xset ; then + GTK_CONFIG=$gtk_config_prefix/bin/gtk-config + fi + fi + + AC_PATH_PROG(GTK_CONFIG, gtk-config, no) + min_gtk_version=ifelse([$1], ,0.99.7,$1) + AC_MSG_CHECKING(for GTK - version >= $min_gtk_version) + no_gtk="" + if test "$GTK_CONFIG" = "no" ; then + no_gtk=yes + else + GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags` + GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs` + gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_gtktest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GTK_CFLAGS" + LIBS="$LIBS $GTK_LIBS" +dnl +dnl Now check if the installed GTK is sufficiently new. (Also sanity +dnl checks the results of gtk-config to some extent +dnl + rm -f conf.gtktest + AC_TRY_RUN([ +#include +#include + +int +main () +{ + int major, minor, micro; + + system ("touch conf.gtktest"); + + if (sscanf("$min_gtk_version", "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_gtk_version"); + exit(1); + } + + if ((gtk_major_version != $gtk_config_major_version) || + (gtk_minor_version != $gtk_config_minor_version) || + (gtk_micro_version != $gtk_config_micro_version)) + { + printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n", + $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version, + gtk_major_version, gtk_minor_version, gtk_micro_version); + printf ("*** was found! If gtk-config was correct, then it is best\n"); + printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n"); + printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); + printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); + printf("*** required on your system.\n"); + printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n"); + printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n"); + printf("*** before re-running configure\n"); + } + else + { + if ((gtk_major_version > major) || + ((gtk_major_version == major) && (gtk_minor_version > minor)) || + ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n", + gtk_major_version, gtk_minor_version, gtk_micro_version); + printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n", + major, minor, micro); + printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the gtk-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n"); + printf("*** correct copy of gtk-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + } + return 1; +} +],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_gtk" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$GTK_CONFIG" = "no" ; then + echo "*** The gtk-config script installed by GTK could not be found" + echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the GTK_CONFIG environment variable to the" + echo "*** full path to gtk-config." + else + if test -f conf.gtktest ; then + : + else + echo "*** Could not run GTK test program, checking why..." + CFLAGS="$CFLAGS $GTK_CFLAGS" + LIBS="$LIBS $GTK_LIBS" + AC_TRY_LINK([ +#include +#include +], [ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GTK or finding the wrong" + echo "*** version of GTK. If it is not finding GTK, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" + echo "***" + echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that" + echo "*** came with the system with the command" + echo "***" + echo "*** rpm --erase --nodeps gtk gtk-devel" ], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GTK was incorrectly installed" + echo "*** or that you have moved GTK since it was installed. In the latter case, you" + echo "*** may want to edit the gtk-config script: $GTK_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GTK_CFLAGS="" + GTK_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GTK_CFLAGS) + AC_SUBST(GTK_LIBS) + rm -f conf.gtktest +]) + +dnl This was copied from the libpcap 0.4a6 source. +dnl ftp://ftp.ee.lbl.gov + +dnl +dnl Checks to see if the sockaddr struct has the 4.4 BSD sa_len member +dnl +dnl usage: +dnl +dnl AC_LBL_SOCKADDR_SA_LEN +dnl +dnl results: +dnl +dnl HAVE_SOCKADDR_SA_LEN (defined) +dnl +AC_DEFUN(AC_LBL_SOCKADDR_SA_LEN, + [AC_MSG_CHECKING(if sockaddr struct has sa_len member) + AC_CACHE_VAL(ac_cv_lbl_sockaddr_has_sa_len, + AC_TRY_COMPILE([ +# include +# include ], + [u_int i = sizeof(((struct sockaddr *)0)->sa_len)], + ac_cv_lbl_sockaddr_has_sa_len=yes, + ac_cv_lbl_sockaddr_has_sa_len=no)) + AC_MSG_RESULT($ac_cv_lbl_sockaddr_has_sa_len) + if test $ac_cv_lbl_sockaddr_has_sa_len = yes ; then + AC_DEFINE(HAVE_SOCKADDR_SA_LEN) + fi]) + +# Like AC_CONFIG_HEADER, but automatically create stamp file. + +AC_DEFUN(AM_CONFIG_HEADER, +[AC_PREREQ([2.12]) +AC_CONFIG_HEADER([$1]) +dnl When config.status generates a header, we must update the stamp-h file. +dnl This file resides in the same directory as the config header +dnl that is generated. We must strip everything past the first ":", +dnl and everything past the last "/". +AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl +ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>, +<>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>, +<>; do + case " <<$>>CONFIG_HEADERS " in + *" <<$>>am_file "*<<)>> + echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx + ;; + esac + am_indx=`expr "<<$>>am_indx" + 1` +done<<>>dnl>>) +changequote([,]))]) + diff --git a/capture.c b/capture.c new file mode 100644 index 0000000000..73d575fbb2 --- /dev/null +++ b/capture.c @@ -0,0 +1,501 @@ +/* capture.c + * Routines for packet capture windows + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include +#include +#include + +#ifdef HAVE_SYS_SOCKIO_H +# include +#endif + +#include "packet.h" +#include "file.h" +#include "capture.h" +#include "etypes.h" +#include "util.h" + +extern capture_file cf; +extern GtkWidget *info_bar; +extern guint file_ctx; + +/* File selection data keys */ +const gchar *prep_fs_key = "prep_fs", + *prep_te_key = "prep_te"; + +/* Capture callback data keys */ +const gchar *cap_iface_key = "cap_iface", + *cap_file_key = "cap_file", + *cap_count_key = "cap_count", + *cap_open_key = "cap_open", + *cap_snap_key = "cap_snap"; + +GList * +get_interface_list() { + GList *il = NULL; + struct ifreq *ifr, *last; + struct ifconf ifc; + int sock = socket(AF_INET, SOCK_DGRAM, 0); + + if (sock < 0) + { + simple_dialog(ESD_TYPE_WARN, NULL, + "Can't list interfaces: error opening socket."); + return NULL; + } + + /* Since we have to grab the interface list all at once, we'll make + plenty of room */ + ifc.ifc_len = 1024 * sizeof(struct ifreq); + ifc.ifc_buf = malloc(ifc.ifc_len); + + if (ioctl(sock, SIOCGIFCONF, &ifc) < 0 || + ifc.ifc_len < sizeof(struct ifreq)) + { + simple_dialog(ESD_TYPE_WARN, NULL, + "Can't list interfaces: ioctl error."); + return NULL; + } + + ifr = (struct ifreq *) ifc.ifc_req; + last = (struct ifreq *) ((char *) ifr + ifc.ifc_len); + while (ifr < last) + { + /* + * What we want: + * - Interfaces that are up, and not loopback + * - IP interfaces (do we really need this?) + * - Anything that doesn't begin with "lo" (loopback again) or "dummy" + * - Anything that doesn't include a ":" (Solaris virtuals) + */ + if (! (ifr->ifr_flags & (IFF_UP | IFF_LOOPBACK)) && + (ifr->ifr_addr.sa_family == AF_INET) && + strncmp(ifr->ifr_name, "lo", 2) && + strncmp(ifr->ifr_name, "dummy", 5) && + ! strchr(ifr->ifr_name, ':')) { + il = g_list_append(il, g_strdup(ifr->ifr_name)); + } +#ifdef HAVE_SOCKADDR_SA_LEN + ifr = (struct ifreq *) ((char *) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ); +#else + ifr = (struct ifreq *) ((char *) ifr + sizeof(struct ifreq)); +#endif + } + + free(ifc.ifc_buf); + return il; +} + +void +capture_prep_cb(GtkWidget *w, gpointer d) { + GtkWidget *cap_open_w, *if_cb, *if_lb, *file_te, *file_bt, + *count_lb, *count_cb, *main_vb, *top_hb, *middle_hb, + *bottom_hb, *bbox, *ok_bt, *cancel_bt, *capfile_ck, + *snap_lb, *snap_sb; + GtkAdjustment *adj; + GList *if_list, *count_list = NULL; + gchar *count_item1 = "0 (Infinite)", count_item2[16]; + + cap_open_w = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(cap_open_w), "Ethereal: Capture Preferences"); + + /* Container for each row of widgets */ + main_vb = gtk_vbox_new(FALSE, 3); + gtk_container_border_width(GTK_CONTAINER(main_vb), 5); + gtk_container_add(GTK_CONTAINER(cap_open_w), main_vb); + gtk_widget_show(main_vb); + + /* Top row: Interface and count selections */ + top_hb = gtk_hbox_new(FALSE, 1); + gtk_container_add(GTK_CONTAINER(main_vb), top_hb); + gtk_widget_show(top_hb); + + if_lb = gtk_label_new("Interface:"); + gtk_box_pack_start(GTK_BOX(top_hb), if_lb, FALSE, FALSE, 3); + gtk_widget_show(if_lb); + + if_list = get_interface_list(); + if_cb = gtk_combo_new(); + gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), if_list); + if (cf.iface) + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), cf.iface); + else if (if_list) + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), if_list->data); + gtk_box_pack_start(GTK_BOX(top_hb), if_cb, FALSE, FALSE, 3); + gtk_widget_show(if_cb); + while (if_list) { + g_free(if_list->data); + if_list = g_list_remove_link(if_list, if_list); + } + + if (cf.count) { + snprintf(count_item2, 15, "%d", cf.count); + count_list = g_list_append(count_list, count_item2); + } + count_list = g_list_append(count_list, count_item1); + count_cb = gtk_combo_new(); + gtk_combo_set_popdown_strings(GTK_COMBO(count_cb), count_list); + gtk_box_pack_end(GTK_BOX(top_hb), count_cb, FALSE, FALSE, 3); + gtk_widget_show(count_cb); + while (count_list) + count_list = g_list_remove_link(count_list, count_list); + + count_lb = gtk_label_new("Count:"); + gtk_box_pack_end(GTK_BOX(top_hb), count_lb, FALSE, FALSE, 3); + gtk_widget_show(count_lb); + + /* Middle row: File: button and text entry */ + middle_hb = gtk_hbox_new(FALSE, 1); + gtk_container_add(GTK_CONTAINER(main_vb), middle_hb); + gtk_widget_show(middle_hb); + + file_bt = gtk_button_new_with_label("File:"); + gtk_box_pack_start(GTK_BOX(middle_hb), file_bt, FALSE, FALSE, 3); + gtk_widget_show(file_bt); + + file_te = gtk_entry_new(); + if (cf.save_file) + gtk_entry_set_text(GTK_ENTRY(file_te), cf.save_file); + gtk_box_pack_start(GTK_BOX(middle_hb), file_te, TRUE, TRUE, 3); + gtk_widget_show(file_te); + + gtk_signal_connect_object(GTK_OBJECT(file_bt), "clicked", + GTK_SIGNAL_FUNC(capture_prep_file_cb), GTK_OBJECT(file_te)); + + /* Bottom row: Capture file checkbox and snap spinbutton */ + bottom_hb = gtk_hbox_new(FALSE, 1); + gtk_container_add(GTK_CONTAINER(main_vb), bottom_hb); + gtk_widget_show(bottom_hb); + + capfile_ck = gtk_check_button_new_with_label("Open file after capture"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(capfile_ck), TRUE); + gtk_box_pack_start(GTK_BOX(bottom_hb), capfile_ck, FALSE, FALSE, 3); + gtk_widget_show(capfile_ck); + + snap_lb = gtk_label_new("Capture length"); + gtk_misc_set_alignment(GTK_MISC(snap_lb), 0, 0.5); + gtk_box_pack_start(GTK_BOX(bottom_hb), snap_lb, FALSE, FALSE, 6); + gtk_widget_show(snap_lb); + + adj = (GtkAdjustment *) gtk_adjustment_new((float) cf.snap, 1.0, 4096.0, + 1.0, 10.0, 0.0); + snap_sb = gtk_spin_button_new (adj, 0, 0); + gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (snap_sb), TRUE); + gtk_widget_set_usize (snap_sb, 80, 0); + gtk_box_pack_start (GTK_BOX(bottom_hb), snap_sb, FALSE, FALSE, 3); + gtk_widget_show(snap_sb); + + /* Button row: OK and cancel buttons */ + bbox = gtk_hbutton_box_new(); + gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END); + gtk_container_add(GTK_CONTAINER(main_vb), bbox); + gtk_widget_show(bbox); + + ok_bt = gtk_button_new_with_label ("OK"); + gtk_signal_connect_object(GTK_OBJECT(ok_bt), "clicked", + GTK_SIGNAL_FUNC(capture_prep_ok_cb), GTK_OBJECT(cap_open_w)); + gtk_container_add(GTK_CONTAINER(bbox), ok_bt); +/* GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT); + gtk_widget_grab_default(ok_bt); */ + gtk_widget_show(ok_bt); + + cancel_bt = gtk_button_new_with_label ("Cancel"); + gtk_signal_connect_object(GTK_OBJECT(cancel_bt), "clicked", + GTK_SIGNAL_FUNC(capture_prep_close_cb), GTK_OBJECT(cap_open_w)); + gtk_container_add(GTK_CONTAINER(bbox), cancel_bt); + gtk_widget_show(cancel_bt); + + /* Attach pointers to needed widges to the capture prefs window/object */ + gtk_object_set_data(GTK_OBJECT(cap_open_w), cap_iface_key, if_cb); + gtk_object_set_data(GTK_OBJECT(cap_open_w), cap_file_key, file_te); + gtk_object_set_data(GTK_OBJECT(cap_open_w), cap_count_key, count_cb); + gtk_object_set_data(GTK_OBJECT(cap_open_w), cap_open_key, capfile_ck); + gtk_object_set_data(GTK_OBJECT(cap_open_w), cap_snap_key, snap_sb); + + gtk_widget_show(cap_open_w); +} + +void +capture_prep_file_cb(GtkWidget *w, gpointer te) { + GtkWidget *fs; + + fs = gtk_file_selection_new ("Ethereal: Open Save File"); + + gtk_object_set_data(GTK_OBJECT(w), prep_fs_key, fs); + gtk_object_set_data(GTK_OBJECT(w), prep_te_key, (GtkWidget *) te); + + gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", (GtkSignalFunc) cap_prep_fs_ok_cb, w); + + /* Connect the cancel_button to destroy the widget */ + gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", (GtkSignalFunc) cap_prep_fs_cancel_cb, w); + + gtk_widget_show(fs); +} + +void +cap_prep_fs_ok_cb(GtkWidget *w, gpointer data) { + GtkWidget *fs, *te; + + fs = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(data), prep_fs_key); + te = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(data), prep_te_key); + + gtk_entry_set_text(GTK_ENTRY(te), + gtk_file_selection_get_filename (GTK_FILE_SELECTION(fs))); + cap_prep_fs_cancel_cb(w, data); +} + +void +cap_prep_fs_cancel_cb(GtkWidget *w, gpointer data) { + GtkWidget *fs; + + fs = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(data), prep_fs_key); + + gtk_widget_destroy(fs); +} + +void +capture_prep_ok_cb(GtkWidget *w, gpointer data) { + GtkWidget *if_cb, *file_te, *count_cb, *open_ck, *snap_sb; + gchar *file; + gint open; + + if_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(data), cap_iface_key); + file_te = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(data), cap_file_key); + count_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(data), cap_count_key); + open_ck = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(data), cap_open_key); + snap_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(data), cap_snap_key); + + if (cf.iface) g_free(cf.iface); + cf.iface = + g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry))); + if (cf.save_file) g_free(cf.save_file); + cf.save_file = g_strdup(gtk_entry_get_text(GTK_ENTRY(file_te))); + cf.count = + atoi(g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(count_cb)->entry)))); + open = GTK_TOGGLE_BUTTON(open_ck)->active; + cf.snap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb)); + if (cf.snap < 1) + cf.snap = 4096; + else if (cf.snap < 68) + cf.snap = 68; + + gtk_widget_destroy(GTK_WIDGET(data)); + + capture(open); +} + +void +capture_prep_close_cb(GtkWidget *w, gpointer win) { + + gtk_grab_remove(GTK_WIDGET(win)); + gtk_widget_destroy(GTK_WIDGET(win)); +} + +void +capture(gint open) { + GtkWidget *cap_w, *main_vb, *count_lb, *tcp_lb, *udp_lb, *other_lb, + *stop_bt; + pcap_t *pch; + gchar err_str[PCAP_ERRBUF_SIZE], label_str[32]; + loop_data ld; + bpf_u_int32 netnum, netmask; + time_t upd_time, cur_time; + + ld.go = TRUE; + ld.count = 0; + ld.max = cf.count; + ld.tcp = 0; + ld.udp = 0; + ld.other = 0; + ld.pdh = NULL; + + close_cap_file(&cf, info_bar, file_ctx); + + pch = pcap_open_live(cf.iface, cf.snap, 1, 250, err_str); + + if (pch) { + if (cf.save_file[0]) { + ld.pdh = pcap_dump_open(pch, cf.save_file); + if (ld.pdh == NULL) { /* We have an error */ + snprintf(err_str, PCAP_ERRBUF_SIZE, "Error trying to open dump " + "file:\n%s", pcap_geterr(pch)); + simple_dialog(ESD_TYPE_WARN, NULL, err_str); + g_free(cf.save_file); + cf.save_file = NULL; + pcap_close(pch); + return; + } + } + + if (cf.filter) { + if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) { + simple_dialog(ESD_TYPE_WARN, NULL, + "Can't use filter: Couldn't obtain netmask info."); + return; + } else if (pcap_compile(pch, &cf.fcode, cf.filter, 1, netmask) < 0) { + simple_dialog(ESD_TYPE_WARN, NULL, "Unable to parse filter string."); + return; + } else if (pcap_setfilter(pch, &cf.fcode) < 0) { + simple_dialog(ESD_TYPE_WARN, NULL, "Can't install filter."); + return; + } + } + + cap_w = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(cap_w), "Ethereal: Capture / Playback"); + + /* Container for capture display widgets */ + main_vb = gtk_vbox_new(FALSE, 1); + gtk_container_border_width(GTK_CONTAINER(main_vb), 5); + gtk_container_add(GTK_CONTAINER(cap_w), main_vb); + gtk_widget_show(main_vb); + + count_lb = gtk_label_new("Count: 0"); + gtk_box_pack_start(GTK_BOX(main_vb), count_lb, FALSE, FALSE, 3); + gtk_widget_show(count_lb); + + tcp_lb = gtk_label_new("TCP: 0 (0.0%)"); + gtk_box_pack_start(GTK_BOX(main_vb), tcp_lb, FALSE, FALSE, 3); + gtk_widget_show(tcp_lb); + + udp_lb = gtk_label_new("UDP: 0 (0.0%)"); + gtk_box_pack_start(GTK_BOX(main_vb), udp_lb, FALSE, FALSE, 3); + gtk_widget_show(udp_lb); + + other_lb = gtk_label_new("Other: 0 (0.0%)"); + gtk_box_pack_start(GTK_BOX(main_vb), other_lb, FALSE, FALSE, 3); + gtk_widget_show(other_lb); + + stop_bt = gtk_button_new_with_label ("Stop"); + gtk_signal_connect(GTK_OBJECT(stop_bt), "clicked", + GTK_SIGNAL_FUNC(capture_stop_cb), (gpointer) &ld); + gtk_box_pack_end(GTK_BOX(main_vb), stop_bt, FALSE, FALSE, 3); + GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT); + gtk_widget_grab_default(stop_bt); + GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT); + gtk_widget_grab_default(stop_bt); + gtk_widget_show(stop_bt); + + gtk_widget_show(cap_w); + gtk_grab_add(cap_w); + + upd_time = time(NULL); + while (ld.go) { + while (gtk_events_pending()) gtk_main_iteration(); + pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld); + /* Only update once a second so as not to overload slow displays */ + cur_time = time(NULL); + if (cur_time > upd_time) { + upd_time = cur_time; + sprintf(label_str, "Count: %d", ld.count); + gtk_label_set(GTK_LABEL(count_lb), label_str); + sprintf(label_str, "TCP: %d (%.1f%%)", ld.tcp, pct(ld.tcp, ld.count)); + gtk_label_set(GTK_LABEL(tcp_lb), label_str); + sprintf(label_str, "UDP: %d (%.1f%%)", ld.udp, pct(ld.udp, ld.count)); + gtk_label_set(GTK_LABEL(udp_lb), label_str); + sprintf(label_str, "Other: %d (%.1f%%)", ld.other, + pct(ld.other, ld.count)); + gtk_label_set(GTK_LABEL(other_lb), label_str); + } + } + + if (ld.pdh) pcap_dump_close(ld.pdh); + pcap_close(pch); + + gtk_grab_remove(GTK_WIDGET(cap_w)); + gtk_widget_destroy(GTK_WIDGET(cap_w)); + } else { + while (gtk_events_pending()) gtk_main_iteration(); + simple_dialog(ESD_TYPE_WARN, NULL, + "The capture session could not be initiated. Please\n" + "check to make sure you have sufficient permissions, and\n" + "that you have the proper interface specified."); + g_free(cf.save_file); + cf.save_file = NULL; + } + + if (cf.save_file && open) load_cap_file(cf.save_file, &cf); +} + +float +pct(gint num, gint denom) { + if (denom) { + return (float) num * 100.0 / (float) denom; + } else { + return 0.0; + } +} + +void +capture_stop_cb(GtkWidget *w, gpointer data) { + loop_data *ld = (loop_data *) data; + + ld->go = FALSE; +} + +void +capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr, + const u_char *pd) { + + guint16 etype; + guint8 iptype = 0; + gint offset = 14; + + loop_data *ld = (loop_data *) user; + + if ((++ld->count >= ld->max) && (ld->max > 0)) ld->go = FALSE; + /* Currently, pcap_dumper_t is a FILE *. Let's hope that doesn't change. */ + if (ld->pdh) pcap_dump((u_char *) ld->pdh, phdr, pd); + + etype = etype = (pd[12] << 8) | pd[13]; + if (etype <= IEEE_802_3_MAX_LEN) { + etype = (pd[20] << 8) | pd[21]; + offset = 22; + } + + if (etype == ETHERTYPE_IP) { + iptype = pd[offset + 9]; + switch (iptype) { + case 6: + ld->tcp++; + break; + case 17: + ld->udp++; + break; + default: + ld->other++; + } + } else { + ld->other++; + } +} diff --git a/capture.h b/capture.h new file mode 100644 index 0000000000..ae6bdebd54 --- /dev/null +++ b/capture.h @@ -0,0 +1,49 @@ +/* capture.h + * Definitions for packet capture windows + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __CAPTURE_H__ +#define __CAPTURE_H__ + +typedef struct _loop_data { + gint go; + gint count; + gint max; + gint tcp; + gint udp; + gint other; + pcap_dumper_t *pdh; +} loop_data; + +GList *get_interface_list(); +void capture_prep_cb(GtkWidget *, gpointer); +void capture_prep_file_cb(GtkWidget *, gpointer); +void cap_prep_fs_ok_cb(GtkWidget *, gpointer); +void cap_prep_fs_cancel_cb(GtkWidget *, gpointer); +void capture_prep_ok_cb(GtkWidget *, gpointer); +void capture_prep_close_cb(GtkWidget *, gpointer); +void capture(gint); +float pct(gint, gint); +void capture_stop_cb(GtkWidget *, gpointer); +void capture_pcap_cb(u_char *, const struct pcap_pkthdr *, const u_char *); + +#endif /* capture.h */ diff --git a/config.h b/config.h new file mode 100644 index 0000000000..d1a798900c --- /dev/null +++ b/config.h @@ -0,0 +1,24 @@ +/* config.h. Generated automatically by configure. */ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +#define PACKAGE "ethereal" + +#define VERSION "0.3.15" + +/* #undef HAVE_SOCKADDR_SA_LEN */ + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the pcap library (-lpcap). */ +#define HAVE_LIBPCAP 1 diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000000..67cd0c40ae --- /dev/null +++ b/config.h.in @@ -0,0 +1,23 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + +#undef PACKAGE + +#undef VERSION + +#undef HAVE_SOCKADDR_SA_LEN + +/* Define if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SOCKIO_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define if you have the pcap library (-lpcap). */ +#undef HAVE_LIBPCAP diff --git a/configure b/configure new file mode 100755 index 0000000000..65548f4945 --- /dev/null +++ b/configure @@ -0,0 +1,2075 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --with-gtk-prefix=PFX Prefix where GTK is installed (optional)" +ac_help="$ac_help + --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)" +ac_help="$ac_help + --disable-gtktest Do not try to compile and run a test GTK program" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=etypes.h + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:559: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + for ac_prog in ginstall installbsd scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + # OSF/1 installbsd also uses dspmsg, but is usable. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure:612: checking whether build environment is sane" >&5 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +rm -f conftest* +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:669: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=ethereal + +VERSION=0.3.15 + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } +fi +cat >> confdefs.h <> confdefs.h <&6 +echo "configure:715: checking for working aclocal" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal + echo "$ac_t""found" 1>&6 +else + ACLOCAL="$missing_dir/missing aclocal" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 +echo "configure:728: checking for working autoconf" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$ac_t""found" 1>&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working automake""... $ac_c" 1>&6 +echo "configure:741: checking for working automake" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake + echo "$ac_t""found" 1>&6 +else + AUTOMAKE="$missing_dir/missing automake" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 +echo "configure:754: checking for working autoheader" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$ac_t""found" 1>&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 +echo "configure:767: checking for working makeinfo" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$ac_t""found" 1>&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$ac_t""missing" 1>&6 +fi + + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:784: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:813: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:861: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:895: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:900: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS= + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:924: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + elif test $ac_cv_prog_cc_g = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-O2" + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi + + +# If LD_LIBRARY_PATH is defined, add it as a link directory. +# This should help Solaris users. +if test x$LD_LIBRARY_PATH != x ; then + LIBS="$LIBS -R$LD_LIBRARY_PATH" +fi + +# GTK checks +# Check whether --with-gtk-prefix or --without-gtk-prefix was given. +if test "${with_gtk_prefix+set}" = set; then + withval="$with_gtk_prefix" + gtk_config_prefix="$withval" +else + gtk_config_prefix="" +fi + +# Check whether --with-gtk-exec-prefix or --without-gtk-exec-prefix was given. +if test "${with_gtk_exec_prefix+set}" = set; then + withval="$with_gtk_exec_prefix" + gtk_config_exec_prefix="$withval" +else + gtk_config_exec_prefix="" +fi + +# Check whether --enable-gtktest or --disable-gtktest was given. +if test "${enable_gtktest+set}" = set; then + enableval="$enable_gtktest" + : +else + enable_gtktest=yes +fi + + + if test x$gtk_config_exec_prefix != x ; then + gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix" + if test x${GTK_CONFIG+set} != xset ; then + GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config + fi + fi + if test x$gtk_config_prefix != x ; then + gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix" + if test x${GTK_CONFIG+set} != xset ; then + GTK_CONFIG=$gtk_config_prefix/bin/gtk-config + fi + fi + + # Extract the first word of "gtk-config", so it can be a program name with args. +set dummy gtk-config; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1000: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GTK_CONFIG'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GTK_CONFIG" in + /*) + ac_cv_path_GTK_CONFIG="$GTK_CONFIG" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GTK_CONFIG="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GTK_CONFIG" && ac_cv_path_GTK_CONFIG="no" + ;; +esac +fi +GTK_CONFIG="$ac_cv_path_GTK_CONFIG" +if test -n "$GTK_CONFIG"; then + echo "$ac_t""$GTK_CONFIG" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + min_gtk_version=1.0.0 + echo $ac_n "checking for GTK - version >= $min_gtk_version""... $ac_c" 1>&6 +echo "configure:1031: checking for GTK - version >= $min_gtk_version" >&5 + no_gtk="" + if test "$GTK_CONFIG" = "no" ; then + no_gtk=yes + else + GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags` + GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs` + gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` + gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` + gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` + if test "x$enable_gtktest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GTK_CFLAGS" + LIBS="$LIBS $GTK_LIBS" + rm -f conf.gtktest + if test "$cross_compiling" = yes; then + echo $ac_n "cross compiling; assumed OK... $ac_c" +else + cat > conftest.$ac_ext < +#include + +int +main () +{ + int major, minor, micro; + + system ("touch conf.gtktest"); + + if (sscanf("$min_gtk_version", "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_gtk_version"); + exit(1); + } + + if ((gtk_major_version != $gtk_config_major_version) || + (gtk_minor_version != $gtk_config_minor_version) || + (gtk_micro_version != $gtk_config_micro_version)) + { + printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n", + $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version, + gtk_major_version, gtk_minor_version, gtk_micro_version); + printf ("*** was found! If gtk-config was correct, then it is best\n"); + printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n"); + printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); + printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); + printf("*** required on your system.\n"); + printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n"); + printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n"); + printf("*** before re-running configure\n"); + } + else + { + if ((gtk_major_version > major) || + ((gtk_major_version == major) && (gtk_minor_version > minor)) || + ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n", + gtk_major_version, gtk_minor_version, gtk_micro_version); + printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n", + major, minor, micro); + printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the gtk-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n"); + printf("*** correct copy of gtk-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + } + return 1; +} + +EOF +if { (eval echo configure:1117: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + no_gtk=yes +fi +rm -fr conftest* +fi + + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_gtk" = x ; then + echo "$ac_t""yes" 1>&6 + CFLAGS="$CFLAGS $GTK_CFLAGS" LIBS="$LIBS $GTK_LIBS" + else + echo "$ac_t""no" 1>&6 + if test "$GTK_CONFIG" = "no" ; then + echo "*** The gtk-config script installed by GTK could not be found" + echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the GTK_CONFIG environment variable to the" + echo "*** full path to gtk-config." + else + if test -f conf.gtktest ; then + : + else + echo "*** Could not run GTK test program, checking why..." + CFLAGS="$CFLAGS $GTK_CFLAGS" + LIBS="$LIBS $GTK_LIBS" + cat > conftest.$ac_ext < +#include + +int main() { + return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); +; return 0; } +EOF +if { (eval echo configure:1161: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GTK or finding the wrong" + echo "*** version of GTK. If it is not finding GTK, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" + echo "***" + echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that" + echo "*** came with the system with the command" + echo "***" + echo "*** rpm --erase --nodeps gtk gtk-devel" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GTK was incorrectly installed" + echo "*** or that you have moved GTK since it was installed. In the latter case, you" + echo "*** may want to edit the gtk-config script: $GTK_CONFIG" +fi +rm -f conftest* + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GTK_CFLAGS="" + GTK_LIBS="" + { echo "configure: error: GTK+ distribution not found." 1>&2; exit 1; } + fi + + + rm -f conf.gtktest + + +# Pcap checks +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1202: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1223: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1240: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +ac_safe=`echo "pcap.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for pcap.h""... $ac_c" 1>&6 +echo "configure:1264: checking for pcap.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1274: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +{ echo "configure: error: Header file pcap.h not found." 1>&2; exit 1; } +fi + +ac_safe=`echo "net/bpf.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for net/bpf.h""... $ac_c" 1>&6 +echo "configure:1298: checking for net/bpf.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1308: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +{ echo "configure: error: Header file net/bpf.h not found." 1>&2; exit 1; } +fi + +echo $ac_n "checking for pcap_open_offline in -lpcap""... $ac_c" 1>&6 +echo "configure:1331: checking for pcap_open_offline in -lpcap" >&5 +ac_lib_var=`echo pcap'_'pcap_open_offline | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lpcap $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo pcap | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +{ echo "configure: error: Library libpcap not found." 1>&2; exit 1; } +fi + + +# AC_HEADER_STDC +# AC_CHECK_HEADERS(fcntl.h strings.h sys/ioctl.h sys/time.h unistd.h) + +for ac_hdr in sys/sockio.h sys/types.h netinet/in.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1386: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1396: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + +# AC_C_CONST + +# We need libpcap's AC_LBL_SOCKADDR_SA_LEN test for get_interface_list(). + +echo $ac_n "checking if sockaddr struct has sa_len member""... $ac_c" 1>&6 +echo "configure:1428: checking if sockaddr struct has sa_len member" >&5 + if eval "test \"`echo '$''{'ac_cv_lbl_sockaddr_has_sa_len'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +# include +int main() { +u_int i = sizeof(((struct sockaddr *)0)->sa_len) +; return 0; } +EOF +if { (eval echo configure:1442: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_lbl_sockaddr_has_sa_len=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_lbl_sockaddr_has_sa_len=no +fi +rm -f conftest* +fi + + echo "$ac_t""$ac_cv_lbl_sockaddr_has_sa_len" 1>&6 + if test $ac_cv_lbl_sockaddr_has_sa_len = yes ; then + cat >> confdefs.h <<\EOF +#define HAVE_SOCKADDR_SA_LEN 1 +EOF + + fi + +# We must know our byte order +echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 +echo "configure:1464: checking whether byte ordering is bigendian" >&5 +if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_bigendian=unknown +# See if sys/param.h defines the BYTE_ORDER macro. +cat > conftest.$ac_ext < +#include +int main() { + +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif +; return 0; } +EOF +if { (eval echo configure:1482: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + # It does; now see whether it defined to BIG_ENDIAN or not. +cat > conftest.$ac_ext < +#include +int main() { + +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif +; return 0; } +EOF +if { (eval echo configure:1497: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_bigendian=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_bigendian=no +fi +rm -f conftest* +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +if test $ac_cv_c_bigendian = unknown; then +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_c_bigendian=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_bigendian=yes +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_c_bigendian" 1>&6 +if test $ac_cv_c_bigendian = yes; then + cat >> confdefs.h <<\EOF +#define WORDS_BIGENDIAN 1 +EOF + +fi + + +if test $ac_cv_prog_gcc = yes; then + echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6 +echo "configure:1556: checking whether ${CC-cc} needs -traditional" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_pattern="Autoconf.*'x'" + cat > conftest.$ac_ext < +Autoconf TIOCGETP +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "$ac_pattern" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_prog_gcc_traditional=yes +else + rm -rf conftest* + ac_cv_prog_gcc_traditional=no +fi +rm -f conftest* + + + if test $ac_cv_prog_gcc_traditional = no; then + cat > conftest.$ac_ext < +Autoconf TCGETA +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "$ac_pattern" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_prog_gcc_traditional=yes +fi +rm -f conftest* + + fi +fi + +echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6 + if test $ac_cv_prog_gcc_traditional = yes; then + CC="$CC -traditional" + fi +fi + +echo $ac_n "checking for socket""... $ac_c" 1>&6 +echo "configure:1602: checking for socket" >&5 +if eval "test \"`echo '$''{'ac_cv_func_socket'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char socket(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_socket) || defined (__stub___socket) +choke me +#else +socket(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1630: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_socket=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_socket=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +{ echo "configure: error: Function 'socket' not found." 1>&2; exit 1; } +fi + +# If there's a system out there that has snprintf and _doesn't_ have vsnprintf, +# then this won't work. +echo $ac_n "checking for snprintf""... $ac_c" 1>&6 +echo "configure:1653: checking for snprintf" >&5 +if eval "test \"`echo '$''{'ac_cv_func_snprintf'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char snprintf(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_snprintf) || defined (__stub___snprintf) +choke me +#else +snprintf(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1681: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_snprintf=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_snprintf=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'snprintf`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SNPRINTF_C="" SNPRINTF_O="" +else + echo "$ac_t""no" 1>&6 +SNPRINTF_C="snprintf.c" SNPRINTF_O="snprintf.o" +fi + + + + + + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@ACLOCAL@%$ACLOCAL%g +s%@AUTOCONF@%$AUTOCONF%g +s%@AUTOMAKE@%$AUTOMAKE%g +s%@AUTOHEADER@%$AUTOHEADER%g +s%@MAKEINFO@%$MAKEINFO%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CC@%$CC%g +s%@GTK_CONFIG@%$GTK_CONFIG%g +s%@GTK_CFLAGS@%$GTK_CFLAGS%g +s%@GTK_LIBS@%$GTK_LIBS%g +s%@CPP@%$CPP%g +s%@SNPRINTF_C@%$SNPRINTF_C%g +s%@SNPRINTF_O@%$SNPRINTF_O%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/configure.in b/configure.in new file mode 100644 index 0000000000..266ba4cd89 --- /dev/null +++ b/configure.in @@ -0,0 +1,51 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(etypes.h) + +AM_INIT_AUTOMAKE(ethereal, 0.3.15) + +dnl Checks for programs. +AC_PROG_CC + +# If LD_LIBRARY_PATH is defined, add it as a link directory. +# This should help Solaris users. +if test x$LD_LIBRARY_PATH != x ; then + LIBS="$LIBS -R$LD_LIBRARY_PATH" +fi + +# GTK checks +AM_PATH_GTK(1.0.0, CFLAGS="$CFLAGS $GTK_CFLAGS" LIBS="$LIBS $GTK_LIBS", + AC_MSG_ERROR(GTK+ distribution not found.)) + +# Pcap checks +AC_CHECK_HEADER(pcap.h,, AC_MSG_ERROR(Header file pcap.h not found.)) +AC_CHECK_HEADER(net/bpf.h,, AC_MSG_ERROR(Header file net/bpf.h not found.)) +AC_CHECK_LIB(pcap, pcap_open_offline,, AC_MSG_ERROR(Library libpcap not found.)) + +dnl Checks for header files. +# AC_HEADER_STDC +# AC_CHECK_HEADERS(fcntl.h strings.h sys/ioctl.h sys/time.h unistd.h) + +AC_CHECK_HEADERS(sys/sockio.h sys/types.h netinet/in.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +# AC_C_CONST + +# We need libpcap's AC_LBL_SOCKADDR_SA_LEN test for get_interface_list(). + +AC_LBL_SOCKADDR_SA_LEN + +# We must know our byte order +AC_C_BIGENDIAN + +dnl Checks for library functions. +AC_PROG_GCC_TRADITIONAL +AC_CHECK_FUNC(socket,, AC_MSG_ERROR(Function 'socket' not found.)) +# If there's a system out there that has snprintf and _doesn't_ have vsnprintf, +# then this won't work. +AC_CHECK_FUNC(snprintf, SNPRINTF_C="" SNPRINTF_O="", + SNPRINTF_C="snprintf.c" SNPRINTF_O="snprintf.o") +AC_SUBST(SNPRINTF_C) +AC_SUBST(SNPRINTF_O) + +AM_CONFIG_HEADER(config.h) +AC_OUTPUT(Makefile) diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000000..6105c9ca05 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,5 @@ +../ethereal.1: ethereal.pod + pod2man ethereal.pod \ + --center="The Ethereal Network Analyzer" \ + --release=`cat ../VERSION` \ + > ../ethereal.1 diff --git a/doc/ethereal.pod b/doc/ethereal.pod new file mode 100644 index 0000000000..f987e7103a --- /dev/null +++ b/doc/ethereal.pod @@ -0,0 +1,233 @@ + +=head1 NAME + +Ethereal - Interactively browse network traffic + +=head1 SYNOPSYS + +B +S<[ B<-v> ]> +S<[ B<-B> byte view height ]> +S<[ B<-c> count ]> +S<[ B<-i> interface ]> +S<[ B<-P> packet list height ]> +S<[ B<-r> infile ]> +S<[ B<-s> snaplen ]> +S<[ B<-T> tree view height ]> +S<[ B<-w> savefile]> + +=head1 DESCRIPTION + +B is a network protocol analyzer based on the B GUI toolkit. It lets +you interactively browse packet data from a live network or from a B +/ B formatted capture file. + +=head1 OPTIONS + +=over 4 + +=item -B + +Sets the initial height of the byte view (bottom) pane + +=item -c + +The default number of packets to read when capturing live data. + +=item -i + +The name of the interface to use for live packet capture. It should match +one of the names listed in "B" or "B". + +=item -P + +Sets the initial height of the packet list (top) pane + +=item -r + +Read packet data from I. Currently, B only understands +B / B formatted files. + +=item -s + +The default snapshot length to use when capturing live data. No more than +I bytes of each network packet will be read into memory, or saved +to disk. + +=item -T + +Sets the initial height of the tree view (top) pane + +=item -v + +Prints the version and exits. + +=item -w + +Sets the default capture file name. + +=back + +=head1 INTERFACE + +=head2 MENU ITEMS + +=over 4 + +=item File:Open, File:Close + +Open or close a capture file. + +=item File:Print Packet + +Print a description of each protocol header found in the packet, followed +by the packet data itself. Printing options can be set with the +I menu item. + +=item File:Quit + +Exits the application. + +=item Edit:Printer Options + +Sets the packet printing options (see L<"Printer Options"> below). + +=item Tools:Capture + +Initiates a live packet capture (see L<"Capture Preferences"> below). + +=item Tools:Filter + +Sets the filter preferences (see L<"Filters"> below). + +=back + +=head2 WINDOWS + +=over 4 + +=item Main Window + +The main window is split into three sections. You can resize each section +using a "thumb" at the right end of each divider line. An informational +message is also displayed at the bottom of the main window. + +The top section contains the list of network packets that you can scroll +through and select. The packet number, source and destination addresses, +protocol, and description are printed for each packet. An effort is made +to display information as high up the protocol stack as possible, e.g. IP +addresses are displayed for IP packets, but the MAC layer address is +displayed for unknown packet types. + +The middle section contains a I for the currently-selected +packet. The tree displays each field and its value in each protocol header +in the stack. + +The bottom section contains a hex dump of the actual packet data. +Selecting a field in the I highlights the appropriate bytes +in this section. + +=item Printer Options + +The I dialog lets you select the output format of packets +printed using the I menu item. + +The radio buttons at the top of the dialog allow you choose between +printing the packets as text or PostScript, and sending the output +directly to a command or saving it to a file. The I text entry +box is the command to send files to (usually B), and the I +entry box lets you enter the name of the file you wish to save to. +Additinally, you can select the I button to browse the file system +for a particular save file. + +=item Capture Preferences + +The I dialog lets you specify various parameters for +capturing live packet data. + +The I entry box lets you specify the interface from which to +capture packet data. The I entry specifies the number of packets +to capture. Entering 0 will capture packets indefinitely. The I +entry specifies the file to save to, as in the I dialog +above. You can choose to open the file after capture, and you can also +specify the maximum number of bytes to capture per packet with the +I entry. + +=item Filters + +The I dialog lets you create and modify filters, and set the +default filter to use when capturing data or opening a capture file. + +The I entry specifies a descriptive name for a filter, e.g. +B. The I entry is the text that +actually describes the filtering action to take. It must have the same +format as B filter strings, since both programs use the same +underlying library. A filter for HTTP, HTTPS, and DNS traffic might look +like this: + + tcp port 80 or tcp port 443 or port 53 + +The dialog buttons perform the following actions: + +=over 8 + +=item New + +If there is text in the two entry boxes, it creates a new associated list +item. + +=item Change + +Modifies the currently selected list item to match what's in the entry +boxes. + +=item Copy + +Makes a copy of the currently selected list item. + +=item Delete + +Deletes the currently selected list item. + +=item OK + +Sets the currently selected list item as the active filter. If nothing +is selected, turns filtering off. + +=item Save + +Saves the current filter list in F<$HOME/.ethereal/filters>. + +=item Cancel + +Closes the dialog without making any changes. + +=head1 SEE ALSO + +L, L + +=head1 NOTES + +The latest version of B can be found at +B. + +=head1 AUTHORS + + Original Author + -------- ------ + Gerald Combs + + + Contributors + ------------ + Gilbert Ramirez Jr. + Hannes R. Boehm + Mike Hall + cpg + + +Theo de Raadt was kind enough to give his +permission to use his version of snprintf.c. + +Dan Lasley gave permission for his dumpit() hex-dump +routine to be used. diff --git a/ethereal.1 b/ethereal.1 new file mode 100644 index 0000000000..9381c89c5b --- /dev/null +++ b/ethereal.1 @@ -0,0 +1,427 @@ +.rn '' }` +''' $RCSfile: ethereal.1,v $$Revision: 1.1 $$Date: 1998/09/16 02:39:18 $ +''' +''' $Log: ethereal.1,v $ +''' Revision 1.1 1998/09/16 02:39:18 gerald +''' Initial revision +''' +''' Revision 1.1.1.1 1998/08/30 17:53:24 gerald +''' Imported sources +''' +''' +.de Sh +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp +.if t .sp .5v +.if n .sp +.. +.de Ip +.br +.ie \\n(.$>=3 .ne \\$3 +.el .ne 3 +.IP "\\$1" \\$2 +.. +.de Vb +.ft CW +.nf +.ne \\$1 +.. +.de Ve +.ft R + +.fi +.. +''' +''' +''' Set up \*(-- to give an unbreakable dash; +''' string Tr holds user defined translation string. +''' Bell System Logo is used as a dummy character. +''' +.tr \(*W-|\(bv\*(Tr +.ie n \{\ +.ds -- \(*W- +.ds PI pi +.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +.ds L" "" +.ds R" "" +''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of +''' \*(L" and \*(R", except that they are used on ".xx" lines, +''' such as .IP and .SH, which do another additional levels of +''' double-quote interpretation +.ds M" """ +.ds S" """ +.ds N" """"" +.ds T" """"" +.ds L' ' +.ds R' ' +.ds M' ' +.ds S' ' +.ds N' ' +.ds T' ' +'br\} +.el\{\ +.ds -- \(em\| +.tr \*(Tr +.ds L" `` +.ds R" '' +.ds M" `` +.ds S" '' +.ds N" `` +.ds T" '' +.ds L' ` +.ds R' ' +.ds M' ` +.ds S' ' +.ds N' ` +.ds T' ' +.ds PI \(*p +'br\} +.\" If the F register is turned on, we'll generate +.\" index entries out stderr for the following things: +.\" TH Title +.\" SH Header +.\" Sh Subsection +.\" Ip Item +.\" X<> Xref (embedded +.\" Of course, you have to process the output yourself +.\" in some meaninful fashion. +.if \nF \{ +.de IX +.tm Index:\\$1\t\\n%\t"\\$2" +.. +.nr % 0 +.rr F +.\} +.TH ETHEREAL 1 "0.3.8" "24/Aug/98" "The Ethereal Network Analyzer" +.UC +.if n .hy 0 +.if n .na +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.de CQ \" put $1 in typewriter font +.ft CW +'if n "\c +'if t \\&\\$1\c +'if n \\&\\$1\c +'if n \&" +\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7 +'.ft R +.. +.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2 +. \" AM - accent mark definitions +.bd B 3 +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds ? ? +. ds ! ! +. ds / +. ds q +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10' +. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#] +.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u' +.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u' +.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#] +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +.ds oe o\h'-(\w'o'u*4/10)'e +.ds Oe O\h'-(\w'O'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds v \h'-1'\o'\(aa\(ga' +. ds _ \h'-1'^ +. ds . \h'-1'. +. ds 3 3 +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +. ds oe oe +. ds Oe OE +.\} +.rm #[ #] #H #V #F C +.SH "NAME" +Ethereal \- Interactively browse network traffic +.SH "SYNOPSYS" +\fBethereal\fR +[\ \fB\-v\fR\ ] +[\ \fB\-B\fR\ byte\ view\ height\ ] +[\ \fB\-c\fR\ count\ ] +[\ \fB\-i\fR\ interface\ ] +[\ \fB\-P\fR\ packet\ list\ height\ ] +[\ \fB\-r\fR\ infile\ ] +[\ \fB\-s\fR\ snaplen\ ] +[\ \fB\-T\fR\ tree\ view\ height\ ] +[\ \fB\-w\fR\ savefile] +.SH "DESCRIPTION" +\fBEthereal\fR is a network protocol analyzer based on the \fBGTK+\fR GUI toolkit. It lets +you interactively browse packet data from a live network or from a \fBpcap\fR +/ \fBtcpdump()\fR formatted capture file. +.SH "OPTIONS" +.Ip "-B" 4 +Sets the initial height of the byte view (bottom) pane +.Ip "-c" 4 +The default number of packets to read when capturing live data. +.Ip "-i" 4 +The name of the interface to use for live packet capture. It should match +one of the names listed in \*(L"\fBnetstat \-i\fR\*(R" or \*(L"\fBifconfig \-a\fR\*(R". +.Ip "-P" 4 +Sets the initial height of the packet list (top) pane +.Ip "-r" 4 +Read packet data from \fIfile\fR. Currently, \fBEthereal\fR only understands +\fBpcap\fR / \fBtcpdump\fR formatted files. +.Ip "-s" 4 +The default snapshot length to use when capturing live data. No more than +\fIsnaplen\fR bytes of each network packet will be read into memory, or saved +to disk. +.Ip "-T" 4 +Sets the initial height of the tree view (top) pane +.Ip "-v" 4 +Prints the version and exits. +.Ip "-w" 4 +Sets the default capture file name. +.SH "INTERFACE" +.Sh "\s-1MENU\s0 \s-1ITEMS\s0" +.Ip "File:Open, File:Close" 4 +Open or close a capture file. +.Ip "File:Print Packet" 4 +Print a description of each protocol header found in the packet, followed +by the packet data itself. Printing options can be set with the +\fIEdit:Menu Options\fR menu item. +.Ip "File:Quit" 4 +Exits the application. +.Ip "Edit:Printer Options" 4 +Sets the packet printing options (see the section on \fIPrinter Options\fR below). +.Ip "Tools:Capture" 4 +Initiates a live packet capture (see the section on \fICapture Preferences\fR below). +.Ip "Tools:Filter" 4 +Sets the filter preferences (see the section on \fIFilters\fR below). +.Sh "\s-1WINDOWS\s0" +.Ip "Main Window" 4 +The main window is split into three sections. You can resize each section +using a \*(L"thumb\*(R" at the right end of each divider line. An informational +message is also displayed at the bottom of the main window. +.Sp +The top section contains the list of network packets that you can scroll +through and select. The packet number, source and destination addresses, +protocol, and description are printed for each packet. An effort is made +to display information as high up the protocol stack as possible, e.g. \s-1IP\s0 +addresses are displayed for \s-1IP\s0 packets, but the \s-1MAC\s0 layer address is +displayed for unknown packet types. +.Sp +The middle section contains a \fIprotocol tree\fR for the currently-selected +packet. The tree displays each field and its value in each protocol header +in the stack. +.Sp +The bottom section contains a hex dump of the actual packet data. +Selecting a field in the \fIprotocol tree\fR highlights the appropriate bytes +in this section. +.Ip "Printer Options" 4 +The \fIPrinter Options\fR dialog lets you select the output format of packets +printed using the \fIFile:Print Packet\fR menu item. +.Sp +The radio buttons at the top of the dialog allow you choose between +printing the packets as text or PostScript, and sending the output +directly to a command or saving it to a file. The \fICommand:\fR text entry +box is the command to send files to (usually \fBlpr\fR), and the \fIFile:\fR +entry box lets you enter the name of the file you wish to save to. +Additinally, you can select the \fIFile:\fR button to browse the file system +for a particular save file. +.Ip "Capture Preferences" 4 +The \fICapture Preferences\fR dialog lets you specify various parameters for +capturing live packet data. +.Sp +The \fIInterface:\fR entry box lets you specify the interface from which to +capture packet data. The \fICount:\fR entry specifies the number of packets +to capture. Entering 0 will capture packets indefinitely. The \fIFile:\fR +entry specifies the file to save to, as in the \fIPrinter Options\fR dialog +above. You can choose to open the file after capture, and you can also +specify the maximum number of bytes to capture per packet with the +\fICapture length\fR entry. +.Ip "Filters" 4 +The \fIFilters\fR dialog lets you create and modify filters, and set the +default filter to use when capturing data or opening a capture file. +.Sp +The \fIFilter name\fR entry specifies a descriptive name for a filter, e.g. +\fBWeb and \s-1DNS\s0 traffic\fR. The \fIFilter string\fR entry is the text that +actually describes the filtering action to take. It must have the same +format as \fBtcpdump\fR filter strings, since both programs use the same +underlying library. A filter for \s-1HTTP\s0, \s-1HTTPS\s0, and \s-1DNS\s0 traffic might look +like this: +.Sp +.Vb 1 +\& tcp port 80 or tcp port 443 or port 53 +.Ve +The dialog buttons perform the following actions: +.Ip "New" 12 +If there is text in the two entry boxes, it creates a new associated list +item. +.Ip "Change" 12 +Modifies the currently selected list item to match what's in the entry +boxes. +.Ip "Copy" 12 +Makes a copy of the currently selected list item. +.Ip "Delete" 12 +Deletes the currently selected list item. +.Ip "\s-1OK\s0" 12 +Sets the currently selected list item as the active filter. If nothing +is selected, turns filtering off. +.Ip "Save" 12 +Saves the current filter list in \fI$\s-1HOME\s0/.ethereal/filters\fR. +.Ip "Cancel" 12 +Closes the dialog without making any changes. +.SH "SEE ALSO" +the \fItcpdump(1)\fR manpage, the \fIpcap(3)\fR manpage +.SH "NOTES" +The latest version of \fBethereal\fR can be found at +\fBhttp://ethereal.zing.org\fR. +.SH "AUTHORS" +.Sp +.Vb 3 +\& Original Author +\& -------- ------ +\& Gerald Combs +.Ve +.Vb 6 +\& Contributors +\& ------------ +\& Gilbert Ramirez Jr. +\& Hannes R. Boehm +\& Mike Hall +\& cpg +.Ve +Theo de Raadt was kind enough to give his +permission to use his version of snprintf.c. +.Sp +Dan Lasley gave permission for his \fIdumpit()\fR hex-dump +routine to be used. + +.rn }` '' +.IX Title "ETHEREAL 1" +.IX Name "Ethereal - Interactively browse network traffic" + +.IX Header "NAME" + +.IX Header "SYNOPSYS" + +.IX Header "DESCRIPTION" + +.IX Header "OPTIONS" + +.IX Item "-B" + +.IX Item "-c" + +.IX Item "-i" + +.IX Item "-P" + +.IX Item "-r" + +.IX Item "-s" + +.IX Item "-T" + +.IX Item "-v" + +.IX Item "-w" + +.IX Header "INTERFACE" + +.IX Subsection "\s-1MENU\s0 \s-1ITEMS\s0" + +.IX Item "File:Open, File:Close" + +.IX Item "File:Print Packet" + +.IX Item "File:Quit" + +.IX Item "Edit:Printer Options" + +.IX Item "Tools:Capture" + +.IX Item "Tools:Filter" + +.IX Subsection "\s-1WINDOWS\s0" + +.IX Item "Main Window" + +.IX Item "Printer Options" + +.IX Item "Capture Preferences" + +.IX Item "Filters" + +.IX Item "New" + +.IX Item "Change" + +.IX Item "Copy" + +.IX Item "Delete" + +.IX Item "\s-1OK\s0" + +.IX Item "Save" + +.IX Item "Cancel" + +.IX Header "SEE ALSO" + +.IX Header "NOTES" + +.IX Header "AUTHORS" + diff --git a/ethereal.c b/ethereal.c new file mode 100644 index 0000000000..5705b8fda5 --- /dev/null +++ b/ethereal.c @@ -0,0 +1,440 @@ +/* ethereal.c + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * To do: + * - Add time stamps to packet list? + * - Live browser/capture display + * - Graphs + * - Prefs dialog + * - Get AIX to work + * - Fix PPP support. + * - Check for end of packet in dissect_* routines. + * - Playback window + * - Multiple window support + * - Add cut/copy/paste + * - Handle snoop files + * - Fix progress/status bar glitches? (GTK+ bug?) + * - Create header parsing routines + * - Check fopens, freads, fwrites + * - Make byte view scrollbars automatic? + * - Make byte view selections more fancy? + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "packet.h" +#include "file.h" +#include "ethereal.h" +#include "menu.h" +#include "etypes.h" +#include "print.h" +#include "resolv.h" + +capture_file cf; +GtkWidget *file_sel, *packet_list, *tree_view, *byte_view, *prog_bar, + *info_bar; +GdkFont *m_r_font, *m_b_font; +guint main_ctx, file_ctx; +frame_data *fd; +gint start_capture = 0; + +const gchar *list_item_data_key = "list_item_data"; + +extern pr_opts printer_opts; + +/* Things to do when the OK button is pressed */ +void +file_sel_ok_cb(GtkWidget *w, GtkFileSelection *fs) { + gchar *cf_name; + int err; + + cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs))); + gtk_widget_hide(GTK_WIDGET (fs)); + gtk_widget_destroy(GTK_WIDGET (fs)); + + if ((err = load_cap_file(cf_name, &cf)) == 0) + chdir(cf_name); + g_free(cf_name); +} + +/* Update the progress bar */ +gint +file_progress_cb(gpointer p) { + gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), + (gfloat) ftell(cf.fh) / (gfloat) cf.f_len); + return TRUE; +} + +/* Open a file */ +void +file_open_cmd_cb(GtkWidget *widget, gpointer data) { + file_sel = gtk_file_selection_new ("Ethereal: Open Capture File"); + + /* Connect the ok_button to file_ok_sel_cb function */ + gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button), + "clicked", (GtkSignalFunc) file_sel_ok_cb, file_sel ); + + /* Connect the cancel_button to destroy the widget */ + gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION + (file_sel)->cancel_button), "clicked", (GtkSignalFunc) + gtk_widget_destroy, GTK_OBJECT (file_sel)); + + gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), ""); + + gtk_widget_show(file_sel); +} + +/* Close a file */ +void +file_close_cmd_cb(GtkWidget *widget, gpointer data) { + close_cap_file(&cf, info_bar, file_ctx); + set_menu_sensitivity("
/File/Close", FALSE); +} + +/* Print a packet */ +void +file_print_cmd_cb(GtkWidget *widget, gpointer data) { + print_tree(cf.pd, fd, GTK_TREE(tree_view)); +} + +/* What to do when a list item is selected/unselected */ +void +packet_list_select_cb(GtkWidget *w, gint row, gint col, gpointer evt) { + GList *l; + + gtk_text_freeze(GTK_TEXT(byte_view)); + gtk_text_set_point(GTK_TEXT(byte_view), 0); + gtk_text_forward_delete(GTK_TEXT(byte_view), + gtk_text_get_length(GTK_TEXT(byte_view))); + l = g_list_nth(cf.plist, row); + if (l) { + fd = (frame_data *) l->data; + fseek(cf.fh, fd->file_off, SEEK_SET); + fread(cf.pd, sizeof(guint8), fd->cap_len, cf.fh); + dissect_packet(cf.pd, fd, GTK_TREE(tree_view)); + packet_hex_print(GTK_TEXT(byte_view), cf.pd, fd->cap_len, -1, -1); + } + gtk_text_thaw(GTK_TEXT(byte_view)); +} + +void +packet_list_unselect_cb(GtkWidget *w, gint row, gint col, gpointer evt) { + gtk_text_freeze(GTK_TEXT(byte_view)); + gtk_text_set_point(GTK_TEXT(byte_view), 0); + gtk_text_forward_delete(GTK_TEXT(byte_view), + gtk_text_get_length(GTK_TEXT(byte_view))); + gtk_text_thaw(GTK_TEXT(byte_view)); + gtk_tree_clear_items(GTK_TREE(tree_view), 0, + g_list_length(GTK_TREE(tree_view)->children)); +} + +void +tree_view_cb(GtkWidget *w) { + gint start = -1, len = -1; + guint32 tinfo = 0; + + if (GTK_TREE(w)->selection) { + tinfo = (guint32) gtk_object_get_user_data(GTK_TREE(w)->selection->data); + start = (tinfo >> 16) & 0xffff; + len = tinfo & 0xffff; + } + + gtk_text_freeze(GTK_TEXT(byte_view)); + gtk_text_set_point(GTK_TEXT(byte_view), 0); + gtk_text_forward_delete(GTK_TEXT(byte_view), + gtk_text_get_length(GTK_TEXT(byte_view))); + packet_hex_print(GTK_TEXT(byte_view), cf.pd, fd->cap_len, start, len); + gtk_text_thaw(GTK_TEXT(byte_view)); +} + +void +file_quit_cmd_cb (GtkWidget *widget, gpointer data) { + gtk_exit(0); +} + +/* Things to do when the OK button is pressed */ +void +main_realize_cb(GtkWidget *w, gpointer data) { + gchar *cf_name = (gchar *) data; + int err; + + if (cf_name) { + err = load_cap_file(cf_name, &cf); + cf_name[0] = '\0'; + } + if (start_capture) { + if (cf.save_file) + capture(1); + else + capture(0); + start_capture = 0; + } +} + +void +print_usage(void) { + + fprintf(stderr, "This is GNU %s %s\n", PACKAGE, VERSION); + fprintf(stderr, "%s [-v] [-b bold font] [-B byte view height] [-c count] [-h]\n", + PACKAGE); + fprintf(stderr, " [-i interface] [-m medium font] [-n] [-P packet list height]\n"); + fprintf(stderr, " [-r infile] [-s snaplen] [-T tree view height]\n"); + fprintf(stderr, " [-w savefile] \n"); +} + +int +main(int argc, char *argv[]) +{ + int opt; + extern char *optarg; + GtkWidget *window, *main_vbox, *menubar, *u_pane, *l_pane, + *bv_table, *bv_hscroll, *bv_vscroll, *stat_hbox, + *tv_scrollw; + GtkStyle *pl_style; + GtkAcceleratorTable *accel; + gint col_width, pl_size = 280, tv_size = 95, bv_size = 75; + gchar *rc_file, *cf_name = NULL; + gchar *cl_title[] = {"No.", "Source", "Destination", + "Protocol", "Info"}; + gchar *medium_font = MONO_MEDIUM_FONT; + gchar *bold_font = MONO_BOLD_FONT; + + /* Initialize the capture file struct */ + cf.plist = NULL; + cf.pfh = NULL; + cf.fh = NULL; + cf.filter = NULL; + cf.iface = NULL; + cf.save_file = NULL; + cf.snap = 68; + cf.count = 0; + + /* Let GTK get its args */ + gtk_init (&argc, &argv); + + /* Now get our args */ + while ((opt = getopt(argc, argv, "b:B:c:hi:m:nP:r:s:T:w:v")) != EOF) { + switch (opt) { + case 'b': /* Bold font */ + bold_font = g_strdup(optarg); + break; + case 'B': /* Byte view pane height */ + bv_size = atoi(optarg); + break; + case 'c': /* Capture xxx packets */ + cf.count = atoi(optarg); + break; + case 'h': /* Print help and exit */ + print_usage(); + exit(0); + break; + case 'i': /* Use interface xxx */ + cf.iface = g_strdup(optarg); + break; + case 'm': /* Medium font */ + medium_font = g_strdup(optarg); + break; + case 'n': /* No name resolution */ + g_resolving_actif = 0; + break; + case 'k': /* Start capture immediately */ + start_capture = 1; + break; + case 'P': /* Packet list pane height */ + pl_size = atoi(optarg); + break; + case 'r': /* Read capture file xxx */ + cf_name = g_strdup(optarg); + break; + case 's': /* Set the snapshot (capture) length */ + cf.snap = atoi(optarg); + break; + case 'T': /* Tree view pane height */ + tv_size = atoi(optarg); + break; + case 'v': /* Show version and exit */ + printf("%s %s\n", PACKAGE, VERSION); + exit(0); + break; + case 'w': /* Write capture file xxx */ + cf.save_file = g_strdup(optarg); + break; + } + } + + if (cf.snap < 1) + cf.snap = 4096; + else if (cf.snap < 68) + cf.snap = 68; + + rc_file = (gchar *) g_malloc(strlen(getenv("HOME")) + strlen(RC_FILE) + 4); + sprintf(rc_file, "%s/%s", getenv("HOME"), RC_FILE); + gtk_rc_parse(rc_file); + + /* initialize printer options. temporary! we should only initialize + * if the options are not set in some ethereal initialization file */ + printer_opts.output_format = 0; + printer_opts.output_dest = 0; + printer_opts.file = g_strdup("ethereal.out"); + printer_opts.cmd = g_strdup("lpr"); + + if ((m_r_font = gdk_font_load(medium_font)) == NULL) { + fprintf(stderr, "Error font %s not found (use -m option)\n", medium_font); + exit(1); + } + + if ((m_b_font = gdk_font_load(bold_font)) == NULL) { + fprintf(stderr, "Error font %s not found (use -b option)\n", bold_font); + exit(1); + } + + /* Main window */ + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_widget_set_name(window, "main window"); + gtk_signal_connect(GTK_OBJECT(window), "delete_event", + GTK_SIGNAL_FUNC(file_quit_cmd_cb), "WM destroy"); + gtk_signal_connect(GTK_OBJECT(window), "destroy", + GTK_SIGNAL_FUNC(file_quit_cmd_cb), "WM destroy"); + gtk_signal_connect(GTK_OBJECT (window), "realize", + GTK_SIGNAL_FUNC(main_realize_cb), cf_name); + gtk_window_set_title(GTK_WINDOW(window), "The Ethereal Network Analyzer"); + gtk_widget_set_usize(GTK_WIDGET(window), DEF_WIDTH, -1); + + /* Container for menu bar, paned windows and progress/info box */ + main_vbox = gtk_vbox_new(FALSE, 1); + gtk_container_border_width(GTK_CONTAINER(main_vbox), 1); + gtk_container_add(GTK_CONTAINER(window), main_vbox); + gtk_widget_show(main_vbox); + + /* Menu bar */ + get_main_menu(&menubar, &accel); + gtk_window_add_accelerator_table(GTK_WINDOW(window), accel); + gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0); + gtk_widget_show(menubar); + + /* Panes for the packet list, tree, and byte view */ + u_pane = gtk_vpaned_new(); + l_pane = gtk_vpaned_new(); + gtk_container_add(GTK_CONTAINER(main_vbox), u_pane); + gtk_widget_show(u_pane); + gtk_paned_add2 (GTK_PANED(u_pane), l_pane); + gtk_widget_show(l_pane); + + /* Packet list */ + packet_list = gtk_clist_new_with_titles(5, cl_title); + pl_style = gtk_style_new(); + gdk_font_unref(pl_style->font); + pl_style->font = m_r_font; + gtk_widget_set_style(packet_list, pl_style); + gtk_widget_set_name(packet_list, "packet list"); + gtk_signal_connect(GTK_OBJECT(packet_list), "select_row", + GTK_SIGNAL_FUNC(packet_list_select_cb), NULL); + gtk_signal_connect(GTK_OBJECT(packet_list), "unselect_row", + GTK_SIGNAL_FUNC(packet_list_unselect_cb), NULL); + gtk_clist_set_column_justification(GTK_CLIST(packet_list), 0, + GTK_JUSTIFY_RIGHT); + col_width = (gdk_string_width(pl_style->font, "0") * 7) + 2; + gtk_clist_set_column_width(GTK_CLIST(packet_list), 0, col_width); + col_width = gdk_string_width(pl_style->font, "00:00:00:00:00:00") + 2; + gtk_clist_set_column_width(GTK_CLIST(packet_list), 1, col_width); + gtk_clist_set_column_width(GTK_CLIST(packet_list), 2, col_width); + col_width = gdk_string_width(pl_style->font, "AppleTalk") + 2; + gtk_clist_set_column_width(GTK_CLIST(packet_list), 3, col_width); + gtk_widget_set_usize(packet_list, -1, pl_size); + gtk_paned_add1(GTK_PANED(u_pane), packet_list); + gtk_widget_show(packet_list); + + /* Tree view */ + tv_scrollw = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(tv_scrollw), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_paned_add1(GTK_PANED(l_pane), tv_scrollw); + gtk_widget_set_usize(tv_scrollw, -1, tv_size); + gtk_widget_show(tv_scrollw); + + tree_view = gtk_tree_new(); + gtk_container_add(GTK_CONTAINER(tv_scrollw), tree_view); + gtk_tree_set_selection_mode(GTK_TREE(tree_view), GTK_SELECTION_SINGLE); + gtk_tree_set_view_lines(GTK_TREE(tree_view), FALSE); + gtk_tree_set_view_mode(GTK_TREE(tree_view), TRUE); + gtk_signal_connect(GTK_OBJECT(tree_view), "selection_changed", + GTK_SIGNAL_FUNC(tree_view_cb), NULL); + gtk_widget_show(tree_view); + + /* Byte view */ + bv_table = gtk_table_new (2, 2, FALSE); + gtk_paned_add2(GTK_PANED(l_pane), bv_table); + gtk_widget_set_usize(bv_table, -1, bv_size); + gtk_widget_show(bv_table); + + byte_view = gtk_text_new(NULL, NULL); + gtk_text_set_editable(GTK_TEXT(byte_view), FALSE); + gtk_text_set_word_wrap(GTK_TEXT(byte_view), FALSE); + gtk_table_attach (GTK_TABLE (bv_table), byte_view, 0, 1, 0, 1, + GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0); + gtk_widget_show(byte_view); + + bv_hscroll = gtk_hscrollbar_new(GTK_TEXT(byte_view)->hadj); + gtk_table_attach(GTK_TABLE(bv_table), bv_hscroll, 0, 1, 1, 2, + GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (bv_hscroll); + + bv_vscroll = gtk_vscrollbar_new(GTK_TEXT(byte_view)->vadj); + gtk_table_attach(GTK_TABLE(bv_table), bv_vscroll, 1, 2, 0, 1, + GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0); + gtk_widget_show(bv_vscroll); + + /* Progress/info box */ + stat_hbox = gtk_hbox_new(FALSE, 1); + gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0); + gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0); + gtk_widget_show(stat_hbox); + + prog_bar = gtk_progress_bar_new(); + gtk_box_pack_start(GTK_BOX(stat_hbox), prog_bar, FALSE, TRUE, 0); + gtk_widget_show(prog_bar); + + info_bar = gtk_statusbar_new(); + main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main"); + file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file"); + gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE); + gtk_box_pack_start(GTK_BOX(stat_hbox), info_bar, TRUE, TRUE, 0); + gtk_widget_show(info_bar); + + gtk_widget_show(window); + gtk_main(); + + exit(0); +} diff --git a/ethereal.h b/ethereal.h new file mode 100644 index 0000000000..067f079a55 --- /dev/null +++ b/ethereal.h @@ -0,0 +1,79 @@ +/* ethereal.h + * Global defines, etc. + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __ETHEREAL_H__ +#define __ETHEREAL_H__ + +#include "config.h" + +#define RC_FILE ".etherealrc" +#define MONO_MEDIUM_FONT "-*-lucidatypewriter-medium-r-normal-*-*-120-*-*-*-*-iso8859-1" +#define MONO_BOLD_FONT "-*-lucidatypewriter-bold-r-normal-*-*-120-*-*-*-*-iso8859-1" +#define DEF_WIDTH 750 +#define DEF_HEIGHT 550 +#define DEF_READY_MESSAGE " Ready to load or capture" + +/* Byte swapping routines */ +#define SWAP16(x) \ + ( (((x) & 0x00ff) << 8) | \ + (((x) & 0xff00) >> 8) ) +#define SWAP32(x) \ + ( (((x) & 0x000000ff) << 24) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0xff000000) >> 24) ) + +/* Byte ordering */ +#ifndef BYTE_ORDER + #define LITTLE_ENDIAN 1234 + #define BIG_ENDIAN 1234 + #ifdef WORDS_BIGENDIAN + #define BYTE_ORDER BIG_ENDIAN + #else + #define BYTE_ORDER LITTLE_ENDIAN + #endif +#endif + +/* From the K&R book, p. 89 */ +#ifndef MAX + #define MAX(x, y) ((x) > (y) ? (x) : (y)) +#endif + +#ifndef MIN + #define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif + +typedef struct _selection_info { + GtkWidget *tree; + GtkWidget *text; +} selection_info; + +void file_sel_ok_cb(GtkWidget *, GtkFileSelection *); +gint file_progress_cb(gpointer); +void file_open_cmd_cb(GtkWidget *, gpointer); +void file_close_cmd_cb(GtkWidget *, gpointer); +void file_quit_cmd_cb(GtkWidget *, gpointer); +void file_print_cmd_cb(GtkWidget *, gpointer); +void main_realize_cb(GtkWidget *, gpointer); + +#endif /* ethereal.h */ diff --git a/ethertype.c b/ethertype.c new file mode 100644 index 0000000000..55fe9bebbb --- /dev/null +++ b/ethertype.c @@ -0,0 +1,107 @@ +/* ethertype.c + * Routines for calling the right protocol for the ethertype. + * This is called by both packet-eth.c (Ethernet II) and packet-llc.c (SNAP) + * + * Gilbert Ramirez + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include + +#include + +#include "packet.h" +#include "ethereal.h" +#include "etypes.h" + +void +ethertype(guint16 etype, int offset, + const u_char *pd, frame_data *fd, GtkTree *tree, GtkWidget + *fh_tree) +{ + gchar etype_str[][10] = {"IP", "ARP", "RARP", "AppleTalk", "AARP"}; + + switch (etype) { + case ETHERTYPE_IP: + if (tree) { + add_item_to_tree(fh_tree, offset - 2, 2, "Type: IP (0x%04x)", + etype); + } + dissect_ip(pd, offset, fd, tree); + break; + case ETHERTYPE_IPv6: + if (tree) { + add_item_to_tree(fh_tree, offset - 2, 2, "Type: IPv6 (0x%04x)", + etype); + } + dissect_ipv6(pd, offset, fd, tree); + break; + case ETHERTYPE_ARP: + if (tree) { + add_item_to_tree(fh_tree, offset - 2, 2, + "Type: ARP (0x%04x)", etype); + } + dissect_arp(pd, offset, fd, tree); + break; + case ETHERTYPE_REVARP: + if (tree) { + add_item_to_tree(fh_tree, offset - 2, 2, + "Type: RARP (0x%04x)", etype); + } + dissect_arp(pd, offset, fd, tree); + break; + case ETHERTYPE_ATALK: + if (tree) { + add_item_to_tree(fh_tree, offset - 2, 2, + "Type: AppleTalk (0x%04x)", etype); + } + if (fd->win_info[0]) { strcpy(fd->win_info[3], etype_str[3]); } + break; + case ETHERTYPE_AARP: + if (tree) { + add_item_to_tree(fh_tree, offset - 2, 2, + "Type: AARP (0x%04x)", etype); + } + if (fd->win_info[0]) { strcpy(fd->win_info[3], etype_str[4]); } + break; + case ETHERTYPE_IPX: + if (tree) { + add_item_to_tree(fh_tree, offset - 2, 2, + "Type: Netware IPX/SPX (0x%04x)", etype); + } + dissect_ipx(pd, offset, fd, tree); + break; + default: + if (tree) { + add_item_to_tree(fh_tree, offset - 2, 2, + "Type: Unknown (0x%04x)", etype); + dissect_data(pd, offset, fd, tree); + } + if (fd->win_info[0]) { sprintf(fd->win_info[3], "0x%04x", etype); } + break; + } + } diff --git a/etypes.h b/etypes.h new file mode 100644 index 0000000000..8b8ea1c2ab --- /dev/null +++ b/etypes.h @@ -0,0 +1,67 @@ +/* etypes.h + * Defines ethernet packet types, similar to tcpdump's ethertype.h + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __ETYPES_H__ +#define __ETYPES_H__ + +#ifndef ETHERTYPE_UNK +#define ETHERTYP_UNK 0x0000 +#endif + +/* Sources: + * http://www.isi.edu/in-notes/iana/assignments/ethernet-numbers + * TCP/IP Illustrated, Volume 1 + * RFCs 894, 1042, 826 + * tcpdump's ethertype.h + * http://www.cavebear.com/CaveBear/Ethernet/ + */ + +#ifndef ETHERTYPE_IP +#define ETHERTYPE_IP 0x0800 +#endif + +#ifndef ETHERTYPE_IPv6 +#define ETHERTYPE_IPv6 0x086dd +#endif + +#ifndef ETHERTYPE_ARP +#define ETHERTYPE_ARP 0x0806 +#endif + +#ifndef ETHERTYPE_REVARP +#define ETHERTYPE_REVARP 0x8035 +#endif + +#ifndef ETHERTYPE_ATALK +#define ETHERTYPE_ATALK 0x809b +#endif + +#ifndef ETHERTYPE_AARP +#define ETHERTYPE_AARP 0x80f3 +#endif + +#ifndef ETHERTYPE_IPX +#define ETHERTYPE_IPX 0x8137 +#endif + +#endif /* etypes.h */ diff --git a/file.c b/file.c new file mode 100644 index 0000000000..5ee508b0b9 --- /dev/null +++ b/file.c @@ -0,0 +1,356 @@ +/* file.c + * File I/O routines + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + + +#include "packet.h" +#include "file.h" +#include "ethereal.h" +#include "util.h" + +extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view; +extern guint file_ctx; + +guint32 ssec, susec; + +int +open_cap_file(char *fname, capture_file *cf) { + guint32 magic[2]; + char err_str[PCAP_ERRBUF_SIZE]; + struct stat cf_stat; + + /* First, make sure the file is valid */ + if (stat(fname, &cf_stat)) { + simple_dialog(ESD_TYPE_WARN, NULL, "File does not exist."); + return 1; + } + if (! S_ISREG(cf_stat.st_mode) && ! S_ISFIFO(cf_stat.st_mode)) { + simple_dialog(ESD_TYPE_WARN, NULL, "The file you have chosen is invalid."); + return 1; + } + + /* Next, try to open the file */ + cf->fh = fopen(fname, "r"); + if (cf->fh == NULL) + return (errno); + + fseek(cf->fh, 0L, SEEK_END); + cf->f_len = ftell(cf->fh); + fseek(cf->fh, 0L, SEEK_SET); + fread(magic, sizeof(guint32), 2, cf->fh); + fseek(cf->fh, 0L, SEEK_SET); + fclose(cf->fh); + cf->fh = NULL; + + /* Next, find out what type of file we're dealing with */ + + cf->cd_t = CD_UNKNOWN; + cf->lnk_t = DLT_NULL; + cf->swap = 0; + cf->count = 0; + cf->drops = 0; + cf->esec = 0; + cf->eusec = 0; + cf->snap = 0; + if (cf->plist == NULL) { + cf->plist = g_list_alloc(); + cf->plist->data = (frame_data *) g_malloc(sizeof(frame_data)); + } else { + cf->plist = g_list_first(cf->plist); + } + ssec = 0, susec = 0; + + if (magic[0] == PCAP_MAGIC || magic[0] == SWAP32(PCAP_MAGIC)) { + + /* Pcap/Tcpdump file */ + cf->pfh = pcap_open_offline(fname, err_str); + if (cf->pfh == NULL) { + simple_dialog(ESD_TYPE_WARN, NULL, "Could not open file."); + return 1; + } + + if (cf->filter) { + if (pcap_compile(cf->pfh, &cf->fcode, cf->filter, 1, 0) < 0) { + simple_dialog(ESD_TYPE_WARN, NULL, "Unable to parse filter string."); + } else if (pcap_setfilter(cf->pfh, &cf->fcode) < 0) { + simple_dialog(ESD_TYPE_WARN, NULL, "Can't install filter."); + } + } + + cf->fh = pcap_file(cf->pfh); + cf->swap = pcap_is_swapped(cf->pfh); + if ((cf->swap && BYTE_ORDER == BIG_ENDIAN) || + (!cf->swap && BYTE_ORDER == LITTLE_ENDIAN)) { + /* Data is big-endian */ + cf->cd_t = CD_PCAP_BE; + } else { + cf->cd_t = CD_PCAP_LE; + } + cf->vers = ( ((pcap_major_version(cf->pfh) & 0x0000ffff) << 16) | + pcap_minor_version(cf->pfh) ); + cf->snap = pcap_snapshot(cf->pfh); + cf->lnk_t = pcap_datalink(cf->pfh); + } else if (ntohl(magic[0]) == SNOOP_MAGIC_1 && ntohl(magic[1]) == SNOOP_MAGIC_2) { + /* Snoop file */ + simple_dialog(ESD_TYPE_WARN, NULL, "The snoop format is not yet supported."); + return 1; + /* + fread(&sfh, sizeof(snoop_file_hdr), 1, cf->fh); + cf->cd_t = CD_SNOOP; + cf->vers = ntohl(sfh.vers); + if (cf->vers < SNOOP_MIN_VERSION || cf->vers > SNOOP_MAX_VERSION) { + g_warning("ethereal:open_cap_file:%s:bad snoop file version(%d)", + fname, cf->vers); + return 1; + } + switch (ntohl(sfh.s_lnk_t)) { + case 4: + cf->lnk_t = DLT_EN10MB; + break; + } + */ + } + + if (cf->cd_t == CD_UNKNOWN) { + simple_dialog(ESD_TYPE_WARN, NULL, "Can't determine file type."); + return 1; + } + return 0; +} + +/* Reset everything to a pristine state */ +void +close_cap_file(capture_file *cf, GtkWidget *w, guint context) { + if (cf->fh) { + fclose(cf->fh); + cf->fh = NULL; + } + if (cf->pfh) { + pcap_close(cf->pfh); + cf->pfh = NULL; + } + gtk_text_freeze(GTK_TEXT(byte_view)); + gtk_text_set_point(GTK_TEXT(byte_view), 0); + gtk_text_forward_delete(GTK_TEXT(byte_view), + gtk_text_get_length(GTK_TEXT(byte_view))); + gtk_text_thaw(GTK_TEXT(byte_view)); + gtk_tree_clear_items(GTK_TREE(tree_view), 0, + g_list_length(GTK_TREE(tree_view)->children)); + + gtk_clist_freeze(GTK_CLIST(packet_list)); + gtk_clist_clear(GTK_CLIST(packet_list)); + gtk_clist_thaw(GTK_CLIST(packet_list)); + gtk_statusbar_pop(GTK_STATUSBAR(w), context); +} + +int +load_cap_file(char *fname, capture_file *cf) { + gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s..."; + gchar *done_fmt = " File: %s Packets: %d Drops: %d Elapsed: %d.%06ds"; + gchar *err_fmt = " Error: Could not load '%s'"; + gint timeout; + size_t msg_len; + int err; + + close_cap_file(cf, info_bar, file_ctx); + + if ((name_ptr = (gchar *) strrchr(fname, '/')) == NULL) + name_ptr = fname; + else + name_ptr++; + load_msg = g_malloc(strlen(name_ptr) + strlen(load_fmt) + 2); + sprintf(load_msg, load_fmt, name_ptr); + gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg); + + timeout = gtk_timeout_add(250, file_progress_cb, (gpointer) &cf); + + err = open_cap_file(fname, cf); + if ((err == 0) && (cf->cd_t != CD_UNKNOWN)) { + gtk_clist_freeze(GTK_CLIST(packet_list)); + pcap_loop(cf->pfh, 0, pcap_dispatch_cb, (u_char *) cf); + pcap_close(cf->pfh); + cf->pfh = NULL; + cf->plist = g_list_first(cf->plist); + cf->fh = fopen(fname, "r"); + gtk_clist_thaw(GTK_CLIST(packet_list)); + } + + gtk_timeout_remove(timeout); + gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0); + + gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx); + + if (err == 0) { + msg_len = strlen(name_ptr) + strlen(load_fmt) + 64; + load_msg = g_realloc(load_msg, msg_len); + snprintf(load_msg, msg_len, done_fmt, name_ptr, cf->count, cf->drops, + cf->esec, cf->eusec); + gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg); + g_free(load_msg); + + name_ptr[-1] = '\0'; + set_menu_sensitivity("
/File/Close", TRUE); + } else { + msg_len = strlen(name_ptr) + strlen(err_fmt) + 2; + load_msg = g_realloc(load_msg, msg_len); + snprintf(load_msg, msg_len, err_fmt, name_ptr); + gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg); + g_free(load_msg); + set_menu_sensitivity("
/File/Close", FALSE); + } + + return err; +} + +void +pcap_dispatch_cb(u_char *user, const struct pcap_pkthdr *phdr, + const u_char *buf) { + frame_data *fdata; + /* To do: make sure this is big enough. */ + gchar p_info[5][256]; + gint i, row; + capture_file *cf = (capture_file *) user; + + while (gtk_events_pending()) + gtk_main_iteration(); + + fdata = cf->plist->data; + cf->cur = fdata; + cf->count++; + + fdata->pkt_len = phdr->len; + fdata->cap_len = phdr->caplen; + fdata->file_off = ftell(cf->fh) - phdr->caplen; + fdata->secs = phdr->ts.tv_sec; + fdata->usecs = phdr->ts.tv_usec; + + for (i = 0; i < 5; i++) { fdata->win_info[i] = &p_info[i][0]; } + sprintf(fdata->win_info[0], "%d", cf->count); + dissect_packet(buf, fdata, NULL); + row = gtk_clist_append(GTK_CLIST(packet_list), fdata->win_info); + for (i = 0; i < 5; i++) { fdata->win_info[i] = NULL; } + + if (!ssec && !susec) { + ssec = fdata->secs; + susec = fdata->usecs; + } + cf->esec = fdata->secs - ssec; + if (susec < fdata->usecs) { + cf->eusec = fdata->usecs - susec; + } else { + cf->eusec = susec - fdata->usecs; + cf->esec--; + } + + /* Make sure we always have an available list entry */ + if (cf->plist->next == NULL) { + fdata = (frame_data *) g_malloc(sizeof(frame_data)); + g_list_append(cf->plist, (gpointer) fdata); + } + cf->plist = cf->plist->next; +} + +/* Uncomment when we handle snoop files again. + +size_t +read_frame_header(capture_file *cf) { + snoop_frame_hdr shdr; + pcap_frame_hdr phdr; + gint16 pkt_len, cap_len; + guint32 secs, usecs; + frame_data *fdata; + size_t err; + + if ((cf->cd_t == CD_PCAP_BE) || (cf->cd_t == CD_PCAP_LE)) { + err = fread((char *)&phdr, sizeof(pcap_frame_hdr), 1, cf->fh); + if (!err) { return err; } + fdata = (frame_data *) g_malloc(sizeof(frame_data)); + if (cf->swap) { + pkt_len = SWAP32(phdr.pkt_len); + cap_len = SWAP32(phdr.cap_len); + secs = SWAP32(phdr.tm.tv_sec); + usecs = SWAP32(phdr.tm.tv_usec); + } else { + pkt_len = phdr.pkt_len; + cap_len = phdr.cap_len; + secs = phdr.tm.tv_sec; + usecs = phdr.tm.tv_usec; + } + } else if (cf->cd_t == CD_SNOOP) { + err = fread(&shdr, sizeof(snoop_frame_hdr), 1, cf->fh); + fdata = (frame_data *) g_malloc(sizeof(frame_data)); + if (!err) { return err; } + pkt_len = ntohl(shdr.inc_len); + cap_len = ntohl(shdr.pr_len) - 24; + secs = ntohl(shdr.secs); + usecs = ntohl(shdr.usecs); + shdr.drops = ntohl(shdr.drops); + if (!ssec && !susec) { ssec = secs; susec = usecs; } + cf->drops = shdr.drops; + cf->esec = secs - ssec; + if (susec < shdr.usecs) { + cf->eusec = usecs - susec; + } else { + cf->eusec = susec - usecs; + cf->esec--; + } + } + cf->cur = fdata; + fdata->pkt_len = pkt_len; + fdata->cap_len = cap_len; + fdata->secs = secs; + fdata->usecs = usecs; + g_list_append(cf->plist, (gpointer) fdata); + if (!ssec && !susec) { + ssec = secs; + susec = usecs; + } + cf->esec = secs - ssec; + if (susec < usecs) { + cf->eusec = usecs - susec; + } else { + cf->eusec = susec - usecs; + cf->esec--; + } + return err; +} +*/ diff --git a/file.h b/file.h new file mode 100644 index 0000000000..8f1ef9b0dc --- /dev/null +++ b/file.h @@ -0,0 +1,99 @@ +/* file.h + * Definitions for file structures and routines + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __FILE_H__ +#define __FILE_H__ + +#include +#include + +#include + +/* Data file formats */ +#define CD_UNKNOWN 0 +#define CD_WIRE 1 +#define CD_SNOOP 2 +#define CD_PCAP_BE 3 +#define CD_PCAP_LE 4 +#define CD_NA_UNCOMPR 5 + +/* Data file magic info */ +#define SNOOP_MAGIC_1 0x736e6f6f /* 'snoop' in ASCII */ +#define SNOOP_MAGIC_2 0x70000000 +#define PCAP_MAGIC 0xa1b2c3d4 + +/* Data file format versions we can handle */ +#define SNOOP_MIN_VERSION 2 +#define SNOOP_MAX_VERSION 2 + +/* Link types (removed in favor of the DLT_* defines from bpf.h */ + +typedef struct bpf_program bpf_prog; + +typedef struct _capture_file { + FILE *fh; /* Capture file */ + long f_len; /* File length */ + int swap; /* Swap data bytes? */ + guint16 cd_t; /* Capture data type */ + guint32 vers; /* Version. For tcpdump minor is appended to major */ + guint32 lnk_t; /* Network link type */ + guint32 count; /* Packet count */ + guint32 drops; /* Dropped packets */ + guint32 esec; /* Elapsed seconds */ + guint32 eusec; /* Elapsed microseconds */ + guint32 snap; /* Captured packet length */ + gchar *iface; /* Interface */ + gchar *save_file; /* File to write capture data */ + pcap_t *pfh; /* Pcap session */ + gchar *filter; /* Pcap filter string */ + bpf_prog fcode; /* Compiled filter program */ + guint8 pd[4096]; /* Packet data */ + GList *plist; /* Packet list */ + frame_data *cur; /* Current list item */ +} capture_file; + +/* Taken from RFC 1761 */ + +typedef struct _snoop_file_hdr { + guint32 magic1; + guint32 magic2; + guint32 vers; + guint32 s_lnk_t; +} snoop_file_hdr; + +typedef struct _snoop_frame_hdr { + guint32 orig_len; + guint32 inc_len; + guint32 pr_len; + guint32 drops; + guint32 secs; + guint32 usecs; +} snoop_frame_hdr; + +int open_cap_file(char *, capture_file *); +void close_cap_file(capture_file *, GtkWidget *, guint); +int load_cap_file(char *, capture_file *); +void pcap_dispatch_cb(u_char *, const struct pcap_pkthdr *, const u_char *); +/* size_t read_frame_header(capture_file *); */ + +#endif /* file.h */ diff --git a/filter.c b/filter.c new file mode 100644 index 0000000000..d3ea96f896 --- /dev/null +++ b/filter.c @@ -0,0 +1,472 @@ +/* filter.c + * Routines for managing filter sets + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include +#include +#include + +#include "filter.h" +#include "packet.h" +#include "file.h" +#include "menu.h" + +extern capture_file cf; + +const gchar *fn_key = "filter_name"; +const gchar *fl_key = "filter_label"; +GtkWidget *filter_l, *chg_bt, *copy_bt, *del_bt, *name_te, *filter_te; +gint in_cancel = FALSE; +GList *fl = NULL; + +GList * +read_filter_list() { + filter_def *filt; + FILE *ff; + gchar *ff_path, *ff_name = ".ethereal/filters", f_buf[256]; + gchar *name_begin, *name_end, *filt_begin; + int len, line = 0; + + in_cancel = FALSE; + + /* To do: generalize this */ + ff_path = (gchar *) g_malloc(strlen(getenv("HOME")) + strlen(ff_name) + 4); + sprintf(ff_path, "%s/%s", getenv("HOME"), ff_name); + + if ((ff = fopen(ff_path, "r")) == NULL) { + g_free(ff_path); + return NULL; + } + + while (fgets(f_buf, 256, ff)) { + line++; + len = strlen(f_buf); + if (f_buf[len - 1] = '\n') { + len--; + f_buf[len] = '\0'; + } + name_begin = strchr(f_buf, '"'); + /* Empty line */ + if (name_begin == NULL) + continue; + name_end = strchr(name_begin + 1, '"'); + /* No terminating quote */ + if (name_end == NULL) { + g_warning("Malformed filter in '%s' line %d.", ff_path, line); + continue; + } + name_begin++; + name_end[0] = '\0'; + filt_begin = name_end + 1; + while(isspace(filt_begin[0])) filt_begin++; + /* No filter string */ + if (filt_begin[0] == '\0') { + g_warning("Malformed filter in '%s' line %d.", ff_path, line); + continue; + } + filt = (filter_def *) g_malloc(sizeof(filter_def)); + filt->name = g_strdup(name_begin); + filt->strval = g_strdup(filt_begin); + fl = g_list_append(fl, filt); + } + fclose(ff); + g_free(ff_path); + return fl; +} + +/* filter_sel_cb - Create and display the filter selection dialog. */ +/* Called when the 'Filter' menu item is selected. */ +void +filter_sel_cb(GtkWidget *w, gpointer d) { + GtkWidget *filter_w, *main_vb, *top_hb, *list_bb, *bbox, + *new_bt, *ok_bt, *save_bt, *cancel_bt, *filter_sc, *nl_item, + *nl_lb, *middle_hb, *name_lb, *bottom_hb, *filter_lb; + GtkWidget *l_select = NULL; + GList *flp = NULL, *nl = NULL; + filter_def *filt; + + fl = read_filter_list(); + + filter_w = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(filter_w), "Ethereal: Filters"); + + /* Container for each row of widgets */ + main_vb = gtk_vbox_new(FALSE, 5); + gtk_container_border_width(GTK_CONTAINER(main_vb), 5); + gtk_container_add(GTK_CONTAINER(filter_w), main_vb); + gtk_widget_show(main_vb); + + /* Top row: Filter list and buttons */ + top_hb = gtk_hbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(main_vb), top_hb); + gtk_widget_show(top_hb); + + list_bb = gtk_vbutton_box_new(); + gtk_button_box_set_layout (GTK_BUTTON_BOX (list_bb), GTK_BUTTONBOX_START); + gtk_container_add(GTK_CONTAINER(top_hb), list_bb); + gtk_widget_show(list_bb); + + new_bt = gtk_button_new_with_label ("New"); + gtk_signal_connect(GTK_OBJECT(new_bt), "clicked", + GTK_SIGNAL_FUNC(filter_sel_new_cb), NULL); + gtk_container_add(GTK_CONTAINER(list_bb), new_bt); + gtk_widget_show(new_bt); + + chg_bt = gtk_button_new_with_label ("Change"); + gtk_widget_set_sensitive(chg_bt, FALSE); + gtk_signal_connect(GTK_OBJECT(chg_bt), "clicked", + GTK_SIGNAL_FUNC(filter_sel_chg_cb), NULL); + gtk_container_add(GTK_CONTAINER(list_bb), chg_bt); + gtk_widget_show(chg_bt); + + copy_bt = gtk_button_new_with_label ("Copy"); + gtk_widget_set_sensitive(copy_bt, FALSE); + gtk_signal_connect(GTK_OBJECT(copy_bt), "clicked", + GTK_SIGNAL_FUNC(filter_sel_copy_cb), NULL); + gtk_container_add(GTK_CONTAINER(list_bb), copy_bt); + gtk_widget_show(copy_bt); + + del_bt = gtk_button_new_with_label ("Delete"); + gtk_widget_set_sensitive(del_bt, FALSE); + gtk_signal_connect(GTK_OBJECT(del_bt), "clicked", + GTK_SIGNAL_FUNC(filter_sel_del_cb), NULL); + gtk_container_add(GTK_CONTAINER(list_bb), del_bt); + gtk_widget_show(del_bt); + + filter_sc = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(filter_sc), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_widget_set_usize(filter_sc, 250, 150); + gtk_container_add(GTK_CONTAINER(top_hb), filter_sc); + gtk_widget_show(filter_sc); + + filter_l = gtk_list_new(); + gtk_signal_connect(GTK_OBJECT(filter_l), "selection_changed", + GTK_SIGNAL_FUNC(filter_sel_list_cb), NULL); + gtk_container_add(GTK_CONTAINER(filter_sc), filter_l); + gtk_widget_show(filter_l); + + flp = g_list_first(fl); + while (flp) { + filt = (filter_def *) flp->data; + nl_lb = gtk_label_new(filt->name); + nl_item = gtk_list_item_new(); + gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5); + gtk_container_add(GTK_CONTAINER(nl_item), nl_lb); + gtk_widget_show(nl_lb); + gtk_container_add(GTK_CONTAINER(filter_l), nl_item); + gtk_widget_show(nl_item); + gtk_object_set_data(GTK_OBJECT(nl_item), fl_key, nl_lb); + gtk_object_set_data(GTK_OBJECT(nl_item), fn_key, flp); + if (cf.filter && filt->strval) + if (strcmp(cf.filter, filt->strval) == 0) + l_select = nl_item; + flp = flp->next; + } + + /* Middle row: Filter name entry */ + middle_hb = gtk_hbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(main_vb), middle_hb); + gtk_widget_show(middle_hb); + + name_lb = gtk_label_new("Filter name:"); + gtk_box_pack_start(GTK_BOX(middle_hb), name_lb, FALSE, FALSE, 3); + gtk_widget_show(name_lb); + + name_te = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(middle_hb), name_te, TRUE, TRUE, 3); + gtk_widget_show(name_te); + + /* Bottom row: Filter text entry */ + bottom_hb = gtk_hbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(main_vb), bottom_hb); + gtk_widget_show(bottom_hb); + + filter_lb = gtk_label_new("Filter string:"); + gtk_box_pack_start(GTK_BOX(bottom_hb), filter_lb, FALSE, FALSE, 3); + gtk_widget_show(filter_lb); + + filter_te = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(bottom_hb), filter_te, TRUE, TRUE, 3); + gtk_widget_show(filter_te); + + /* Button row: OK and cancel buttons */ + bbox = gtk_hbutton_box_new(); + gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END); + gtk_container_add(GTK_CONTAINER(main_vb), bbox); + gtk_widget_show(bbox); + + ok_bt = gtk_button_new_with_label ("OK"); + gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked", + GTK_SIGNAL_FUNC(filter_sel_ok_cb), (gpointer) filter_w); + gtk_container_add(GTK_CONTAINER(bbox), ok_bt); + GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT); + gtk_widget_grab_default(ok_bt); + gtk_widget_show(ok_bt); + + save_bt = gtk_button_new_with_label ("Save"); + gtk_signal_connect(GTK_OBJECT(save_bt), "clicked", + GTK_SIGNAL_FUNC(filter_sel_save_cb), (gpointer) fl); + gtk_container_add(GTK_CONTAINER(bbox), save_bt); + gtk_widget_show(save_bt); + + cancel_bt = gtk_button_new_with_label ("Cancel"); + gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked", + GTK_SIGNAL_FUNC(filter_sel_cancel_cb), (gpointer) filter_w); + gtk_container_add(GTK_CONTAINER(bbox), cancel_bt); + gtk_widget_show(cancel_bt); + + gtk_widget_show(filter_w); + + if (l_select) + gtk_list_select_child(GTK_LIST(filter_l), l_select); +} + +void +filter_sel_list_cb(GtkWidget *l, gpointer data) { + filter_def *filt; + gchar *name = "", *strval = ""; + GList *sl, *flp; + GtkObject *l_item; + gint sensitivity = FALSE; + + sl = GTK_LIST(l)->selection; + + if (sl) { /* Something was selected */ + l_item = GTK_OBJECT(sl->data); + flp = (GList *) gtk_object_get_data(l_item, fn_key); + if (flp) { + filt = (filter_def *) flp->data; + name = filt->name; + strval = filt->strval; + sensitivity = TRUE; + } + } + + /* Did you know that this function is called when the window is destroyed? */ + /* Funny, that. */ + if (!in_cancel) { + gtk_entry_set_text(GTK_ENTRY(name_te), name); + gtk_entry_set_text(GTK_ENTRY(filter_te), strval); + gtk_widget_set_sensitive(chg_bt, sensitivity); + gtk_widget_set_sensitive(copy_bt, sensitivity); + gtk_widget_set_sensitive(del_bt, sensitivity); + } +} + +/* To do: add input checking to each of these callbacks */ + +void +filter_sel_new_cb(GtkWidget *w, gpointer data) { + GList *nl = NULL; + filter_def *filt; + gchar *name, *strval; + GtkWidget *nl_item, *nl_lb; + + name = gtk_entry_get_text(GTK_ENTRY(name_te)); + strval = gtk_entry_get_text(GTK_ENTRY(filter_te)); + + if (strlen(name) > 0 && strlen(strval) > 0) { + filt = (filter_def *) g_malloc(sizeof(filter_def)); + filt->name = g_strdup(name); + filt->strval = g_strdup(strval); + fl = g_list_append(fl, filt); + nl_lb = gtk_label_new(filt->name); + nl_item = gtk_list_item_new(); + gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5); + gtk_container_add(GTK_CONTAINER(nl_item), nl_lb); + gtk_widget_show(nl_lb); + gtk_container_add(GTK_CONTAINER(filter_l), nl_item); + gtk_widget_show(nl_item); + gtk_object_set_data(GTK_OBJECT(nl_item), fl_key, nl_lb); + gtk_object_set_data(GTK_OBJECT(nl_item), fn_key, g_list_last(fl)); + } +} + +void +filter_sel_chg_cb(GtkWidget *w, gpointer data) { + filter_def *filt; + gchar *name = "", *strval = ""; + GList *sl, *flp; + GtkObject *l_item; + GtkLabel *nl_lb; + gint sensitivity = FALSE; + + sl = GTK_LIST(filter_l)->selection; + name = gtk_entry_get_text(GTK_ENTRY(name_te)); + strval = gtk_entry_get_text(GTK_ENTRY(filter_te)); + + if (sl) { /* Something was selected */ + l_item = GTK_OBJECT(sl->data); + flp = (GList *) gtk_object_get_data(l_item, fn_key); + nl_lb = (GtkLabel *) gtk_object_get_data(l_item, fl_key); + if (flp && nl_lb) { + filt = (filter_def *) flp->data; + + if (strlen(name) > 0 && strlen(strval) > 0 && filt) { + g_free(filt->name); + g_free(filt->strval); + filt->name = g_strdup(name); + filt->strval = g_strdup(strval); + gtk_label_set(nl_lb, filt->name); + } + } + } +} + +void +filter_sel_copy_cb(GtkWidget *w, gpointer data) { + GList *nl = NULL, *sl, *flp; + filter_def *filt, *nfilt; + gchar *name, *strval, *prefix = "Copy of "; + GtkObject *l_item; + GtkWidget *nl_item, *nl_lb; + + sl = GTK_LIST(filter_l)->selection; + if (sl) { /* Something was selected */ + l_item = GTK_OBJECT(sl->data); + flp = (GList *) gtk_object_get_data(l_item, fn_key); + if (flp) { + filt = (filter_def *) flp->data; + nfilt = (filter_def *) g_malloc(sizeof(filter_def)); + nfilt->name = g_malloc(strlen(prefix) + strlen(filt->name) + 1); + sprintf(nfilt->name, "%s%s", prefix, filt->name); + nfilt->strval = g_strdup(filt->strval); + fl = g_list_append(fl, nfilt); + nl_lb = gtk_label_new(nfilt->name); + nl_item = gtk_list_item_new(); + gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5); + gtk_container_add(GTK_CONTAINER(nl_item), nl_lb); + gtk_widget_show(nl_lb); + gtk_container_add(GTK_CONTAINER(filter_l), nl_item); + gtk_widget_show(nl_item); + gtk_object_set_data(GTK_OBJECT(nl_item), fl_key, nl_lb); + gtk_object_set_data(GTK_OBJECT(nl_item), fn_key, g_list_last(fl)); + } + } +} + +void +filter_sel_del_cb(GtkWidget *w, gpointer data) { + GList *sl, *flp; + filter_def *filt; + GtkObject *l_item; + GtkWidget *nl_item; + gint pos; + + sl = GTK_LIST(filter_l)->selection; + if (sl) { /* Something was selected */ + l_item = GTK_OBJECT(sl->data); + pos = gtk_list_child_position(GTK_LIST(filter_l), + GTK_WIDGET(l_item)); + flp = (GList *) gtk_object_get_data(l_item, fn_key); + if (flp) { + filt = (filter_def *) flp->data; + g_free(filt->name); + g_free(filt->strval); + g_free(filt); + fl = g_list_remove_link(fl, flp); + gtk_list_clear_items(GTK_LIST(filter_l), pos, pos + 1); + } + } +} + +void +filter_sel_ok_cb(GtkWidget *w, gpointer data) { + GList *flp, *sl; + GtkObject *l_item; + filter_def *filt; + + if (cf.filter) { + g_free(cf.filter); + cf.filter = NULL; + } + + sl = GTK_LIST(filter_l)->selection; + if (sl) { /* Something was selected */ + l_item = GTK_OBJECT(sl->data); + flp = (GList *) gtk_object_get_data(l_item, fn_key); + if (flp) { + filt = (filter_def *) flp->data; + cf.filter = g_strdup(filt->strval); + } + } + + filter_sel_cancel_cb(w, data); +} + +void +filter_sel_save_cb(GtkWidget *w, gpointer data) { + GList *flp; + filter_def *filt; + gchar *ff_path, *ff_dir = ".ethereal", *ff_name = "filters"; + FILE *ff; + struct stat s_buf; + + ff_path = (gchar *) g_malloc(strlen(getenv("HOME")) + strlen(ff_dir) + + strlen(ff_name) + 4); + sprintf(ff_path, "%s/%s", getenv("HOME"), ff_dir); + + if (stat(ff_path, &s_buf) != 0) + mkdir(ff_path, 0755); + + sprintf(ff_path, "%s/%s/%s", getenv("HOME"), ff_dir, ff_name); + + if ((ff = fopen(ff_path, "w")) != NULL) { + flp = g_list_first(fl); + while (flp) { + filt = (filter_def *) flp->data; + fprintf(ff, "\"%s\" %s\n", filt->name, filt->strval); + flp = flp->next; + } + fclose(ff); + } + + g_free(ff_path); +} + +void +filter_sel_cancel_cb(GtkWidget *w, gpointer win) { + filter_def *filt; + GList *sl; + + while (fl) { + if (fl->data) { + filt = (filter_def *) fl->data; + g_free(filt->name); + g_free(filt->strval); + g_free(filt); + } + fl = g_list_remove_link(fl, fl); + } + + /* Let the list cb know we're about to destroy the widget tree, so it */ + /* doesn't operate on widgets that don't exist. */ + in_cancel = TRUE; + gtk_widget_destroy(GTK_WIDGET(win)); +} diff --git a/filter.h b/filter.h new file mode 100644 index 0000000000..4508ed3000 --- /dev/null +++ b/filter.h @@ -0,0 +1,55 @@ +/* filter.h + * Definitions for packet filter window + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __FILTER_H__ +#define __FILTER_H__ + +typedef struct _filter_def { + char *name; + char *strval; +} filter_def; + +typedef struct _filter_cb_data { + GList *fl; + GtkWidget *win; +} filter_cb_data; + +GList *read_filter_list(); +void filter_sel_cb(GtkWidget *, gpointer); +void filter_sel_list_cb(GtkWidget *, gpointer); +void filter_sel_new_cb(GtkWidget *, gpointer); +void filter_sel_chg_cb(GtkWidget *, gpointer); +void filter_sel_copy_cb(GtkWidget *, gpointer); +void filter_sel_del_cb(GtkWidget *, gpointer); +void filter_sel_ok_cb(GtkWidget *, gpointer); +void filter_sel_save_cb(GtkWidget *, gpointer); +void filter_sel_cancel_cb(GtkWidget *, gpointer); + +/* GList *get_interface_list(); +void capture_prep_file_cb(GtkWidget *, gpointer); +void cap_prep_fs_ok_cb(GtkWidget *, gpointer); +void cap_prep_fs_cancel_cb(GtkWidget *, gpointer); +void capture_prep_ok_cb(GtkWidget *, gpointer); +void capture_prep_close_cb(GtkWidget *, gpointer); + */ +#endif /* capture.h */ diff --git a/image/icon-excl.xpm b/image/icon-excl.xpm new file mode 100644 index 0000000000..dfd3ecb57b --- /dev/null +++ b/image/icon-excl.xpm @@ -0,0 +1,88 @@ +/* XPM */ +static char * icon_excl_xpm[] = { +"64 64 21 1", +" c None", +". c #FFFFFF", +"+ c #A95454", +"@ c #7F0000", +"# c #9B3838", +"$ c #A95555", +"% c #D4A9A9", +"& c #B77171", +"* c #8D1C1C", +"= c #D3A9A9", +"- c #F0E2E2", +"; c #A85353", +"> c #C68D8D", +", c #B77070", +"' c #E2C6C6", +") c #8D1D1D", +"! c #C58D8D", +"~ c #D3A8A8", +"{ c #E2C5C5", +"] c #A85252", +"^ c #C58C8C", +" ", +" ", +" ", +" ", +" ", +" ............ ", +" .................... ", +" ......................... ", +" ............................. ", +" .............+@#$%............. ", +" .............&@@@@@*=............ ", +" ..............-@@@@@@@;............. ", +" ................>@@@@@@@,............. ", +" .................*@@@@@@@'.............. ", +" .................>@@@@@@@#............... ", +" ..................*@@@@@@@'............... ", +" ..................>@@@@@@@+................ ", +" ...................*@@@@@@@-................ ", +" ...................%@@@@@@@&................. ", +" ....................#@@@@@@@-................. ", +" ...................'@@@@@@@&.................. ", +" ....................#@@@@@@).................... ", +" ....................-@@@@@@@>................... ", +" ....................&@@@@@@*.................... ", +" ....................-@@@@@@@>.................... ", +" ....................>@@@@@@*..................... ", +" .....................*@@@@@@>..................... ", +" ....................'@@@@@@*..................... ", +" ....................+@@@@@@>..................... ", +" ...................-@@@@@@*...................... ", +" ....................&@@@@@@>..................... ", +" ....................*@@@@@*...................... ", +" ...................%@@@@@@!...................... ", +" ....................#@@@@@*...................... ", +" ...................-@@@@@@!...................... ", +" ...................&@@@@@*...................... ", +" ...................@@@@@@>...................... ", +" ..................>@@@@@)...................... ", +" ..................#@@@@@&...................... ", +" ..................@@@@@@'..................... ", +" ..................*@@@@@%..................... ", +" ..................%@@@@@'.................... ", +" ...................=@@@#..................... ", +" ....................-!!..................... ", +" .................'~{........................ ", +" ................!@@@]...................... ", +" ..............'@@@@@^.................... ", +" ..............+@@@@@@................... ", +" ..............@@@@@@@................... ", +" .............%@@@@@@@.................. ", +" .............&@@@@@@@................. ", +" ............+@@@@@@#................ ", +" ............+@@@@@@>............... ", +" ...........+@@@@@*............... ", +" ..........{@@@@@%.............. ", +" ...........'#@*%.............. ", +" ........................... ", +" ......................... ", +" ...................... ", +" ................. ", +" .......... ", +" ", +" ", +" "}; diff --git a/install-sh b/install-sh new file mode 100755 index 0000000000..e8436696c1 --- /dev/null +++ b/install-sh @@ -0,0 +1,250 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/menu.c b/menu.c new file mode 100644 index 0000000000..be9a3c4fed --- /dev/null +++ b/menu.c @@ -0,0 +1,215 @@ +/* menu.c + * Menu routines + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include +#include + +#include + +#include "menu.h" +#include "ethereal.h" +#include "capture.h" +#include "filter.h" +#include "packet.h" +#include "print.h" + +/* Much of this was take from the GTK+ tuturial at http://www.gtk.org */ + +static void menus_remove_accel (GtkWidget *, gchar *, gchar *); +static gint menus_install_accel (GtkWidget *, gchar *, gchar, gchar, gchar *); + +/* this is the GtkMenuEntry structure used to create new menus. The + * first member is the menu definition string. The second, the + * default accelerator key used to access this menu function with + * the keyboard. The third is the callback function to call when + * this menu item is selected (by the accelerator key, or with the + * mouse.) The last member is the data to pass to your callback function. + */ + +static GtkMenuEntry menu_items[] = +{ + {"
/File/Open", "O", file_open_cmd_cb, NULL}, + {"
/File/Close", "W", file_close_cmd_cb, NULL}, + {"
/File/Save", "S", NULL, NULL}, + {"
/File/Save as", NULL, NULL, NULL}, + {"
/File/", NULL, NULL, NULL}, + {"
/File/Print Packet", "P", file_print_cmd_cb, NULL}, + {"
/File/", NULL, NULL, NULL}, + {"
/File/Quit", "Q", file_quit_cmd_cb, NULL}, + {"
/Edit/Cut", "X", NULL, NULL}, + {"
/Edit/Copy", "C", NULL, NULL}, + {"
/Edit/Paste", "V", NULL, NULL}, + {"
/Edit/", NULL, NULL, NULL}, + {"
/Edit/Find", "F", NULL, NULL}, + {"
/Edit/", NULL, NULL, NULL}, + {"
/Edit/Printer Options", NULL, printer_opts_cb, NULL}, + {"
/Tools/Capture", "K", capture_prep_cb, NULL}, + {"
/Tools/Filter", NULL, filter_sel_cb, NULL}, + {"
/Tools/Graph", NULL, NULL, NULL}, + {"
/Help/About Ethereal", NULL, NULL, NULL} +}; + +/* calculate the number of menu_items */ +static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]); + +static int initialize = TRUE; +static GtkMenuFactory *factory = NULL; +static GtkMenuFactory *subfactory[1]; +static GHashTable *entry_ht = NULL; + +void +get_main_menu(GtkWidget ** menubar, GtkAcceleratorTable ** table) { + if (initialize) + menus_init(); + + if (menubar) + *menubar = subfactory[0]->widget; + if (table) + *table = subfactory[0]->table; +} + +void +menus_init(void) { + GtkMenuPath *mp; + + if (initialize) { + initialize = FALSE; + + factory = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR); + subfactory[0] = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR); + + gtk_menu_factory_add_subfactory(factory, subfactory[0], "
"); + menus_create(menu_items, nmenu_items); + + set_menu_sensitivity("
/File/Close", FALSE); + set_menu_sensitivity("
/File/Save", FALSE); + set_menu_sensitivity("
/File/Save as", FALSE); + set_menu_sensitivity("
/Edit/Cut", FALSE); + set_menu_sensitivity("
/Edit/Copy", FALSE); + set_menu_sensitivity("
/Edit/Paste", FALSE); + set_menu_sensitivity("
/Edit/Find", FALSE); + set_menu_sensitivity("
/Tools/Graph", FALSE); + set_menu_sensitivity("
/Help/About Ethereal", FALSE); + if ((mp = gtk_menu_factory_find(factory, "
/Help")) != NULL) { + gtk_menu_item_right_justify((GtkMenuItem *) mp->widget); + } + } +} + +void +set_menu_sensitivity (gchar *path, gint val) { + GtkMenuPath *mp; + + if ((mp = gtk_menu_factory_find(factory, path)) != NULL) { + gtk_widget_set_sensitive(mp->widget, val); + } +} + +void +menus_create(GtkMenuEntry * entries, int nmenu_entries) { + char *accelerator; + int i; + + if (initialize) + menus_init(); + + if (entry_ht) + for (i = 0; i < nmenu_entries; i++) { + accelerator = g_hash_table_lookup(entry_ht, entries[i].path); + if (accelerator) { + if (accelerator[0] == '\0') + entries[i].accelerator = NULL; + else + entries[i].accelerator = accelerator; + } + } + gtk_menu_factory_add_entries(factory, entries, nmenu_entries); + + for (i = 0; i < nmenu_entries; i++) + if (entries[i].widget) { + gtk_signal_connect(GTK_OBJECT(entries[i].widget), "install_accelerator", + (GtkSignalFunc) menus_install_accel, entries[i].path); + gtk_signal_connect(GTK_OBJECT(entries[i].widget), "remove_accelerator", + (GtkSignalFunc) menus_remove_accel, entries[i].path); + } +} + +static gint +menus_install_accel(GtkWidget * widget, gchar * signal_name, gchar key, gchar modifiers, gchar * path) { + char accel[64]; + char *t1, t2[2]; + + accel[0] = '\0'; + if (modifiers & GDK_CONTROL_MASK) + strcat(accel, ""); + if (modifiers & GDK_SHIFT_MASK) + strcat(accel, ""); + if (modifiers & GDK_MOD1_MASK) + strcat(accel, ""); + + t2[0] = key; + t2[1] = '\0'; + strcat(accel, t2); + + if (entry_ht) { + t1 = g_hash_table_lookup(entry_ht, path); + g_free(t1); + } else + entry_ht = g_hash_table_new(g_str_hash, g_str_equal); + + g_hash_table_insert(entry_ht, path, g_strdup(accel)); + + return TRUE; +} + +static void +menus_remove_accel(GtkWidget * widget, gchar * signal_name, gchar * path) { + char *t; + + if (entry_ht) { + t = g_hash_table_lookup(entry_ht, path); + g_free(t); + + g_hash_table_insert(entry_ht, path, g_strdup("")); + } +} + +void +menus_set_sensitive(char *path, int sensitive) { + GtkMenuPath *menu_path; + + if (initialize) + menus_init(); + + menu_path = gtk_menu_factory_find(factory, path); + if (menu_path) + gtk_widget_set_sensitive(menu_path->widget, sensitive); + else + g_warning("Unable to set sensitivity for menu which doesn't exist: %s", path); +} diff --git a/menu.h b/menu.h new file mode 100644 index 0000000000..268c98527c --- /dev/null +++ b/menu.h @@ -0,0 +1,41 @@ +/* menu.h + * Menu definitions + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __MENU_H__ +#define __MENU_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void menus_init (void); +void get_main_menu (GtkWidget **, GtkAcceleratorTable **); +void set_menu_sensitivity (gchar *, gint); +void menus_create (GtkMenuEntry *, int); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __MENU_H__ */ diff --git a/missing b/missing new file mode 100755 index 0000000000..cbe2b0ef0e --- /dev/null +++ b/missing @@ -0,0 +1,188 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright (C) 1996, 1997 Free Software Foundation, Inc. +# Franc,ois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing - GNU libit 0.0" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`configure.in'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`configure.in'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`configure.in'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER([^):]*:\([^)]*\)).*/\1/p' configure.in` + if test -z "$files"; then + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^):]*\)).*/\1/p' configure.in` + test -z "$files" || files="$files.in" + else + files=`echo "$files" | sed -e 's/:/ /g'` + fi + test -z "$files" && files="config.h.in" + touch $files + ;; + + automake) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print \ + | sed 's/^\(.*\).am$/touch \1.in/' \ + | sh + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100755 index 0000000000..14845e07de --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id: mkinstalldirs,v 1.1 1998/09/16 02:39:16 gerald Exp $ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" 1>&2 + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/packet-arp.c b/packet-arp.c new file mode 100644 index 0000000000..c989b6a89b --- /dev/null +++ b/packet-arp.c @@ -0,0 +1,122 @@ +/* packet-arp.c + * Routines for ARP packet disassembly + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include "ethereal.h" +#include "packet.h" +#include "etypes.h" + +void +dissect_arp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + e_ether_arp *ea; + guint16 ar_hrd, ar_pro, ar_op; + gchar *req_type[] = { "ARP request", "ARP reply", + "RARP request", "RARP reply" }; + GtkWidget *arp_tree, *ti; + + /* To do: Check for {cap len,pkt len} < struct len */ + ea = (e_ether_arp *) &pd[offset]; + ar_hrd = ntohs(ea->ar_hrd); + ar_pro = ntohs(ea->ar_pro); + /* To do: Check for bounds on ar_op */ + ar_op = ntohs(ea->ar_op); + + if (fd->win_info[0]) { strcpy(fd->win_info[3], "ARP"); } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, 28, req_type[ar_op - 1]); + arp_tree = gtk_tree_new(); + add_subtree(ti, arp_tree, ETT_ARP); + add_item_to_tree(arp_tree, offset, 2, + "Hardware type: 0x%04x", ar_hrd); + add_item_to_tree(arp_tree, offset + 2, 2, + "Protocol type: 0x%04x", ar_pro); + add_item_to_tree(arp_tree, offset + 4, 1, + "Hardware size: 0x%02x", ea->ar_hln); + add_item_to_tree(arp_tree, offset + 5, 1, + "Protocol size: 0x%02x", ea->ar_pln); + add_item_to_tree(arp_tree, offset + 6, 2, + "Opcode: 0x%04x", ar_op); + add_item_to_tree(arp_tree, offset + 8, 6, + "Sender ether: %s", ether_to_str((guint8 *) ea->arp_sha)); + add_item_to_tree(arp_tree, offset + 14, 4, + "Sender IP: %s", ip_to_str((guint8 *) ea->arp_spa)); + add_item_to_tree(arp_tree, offset + 18, 6, + "Target ether: %s", ether_to_str((guint8 *) ea->arp_tha)); + add_item_to_tree(arp_tree, offset + 24, 4, + "Target IP: %s", ip_to_str((guint8 *) ea->arp_tpa)); + } + + if (ar_pro != ETHERTYPE_IP && fd->win_info[0]) { + sprintf(fd->win_info[4], "h/w %d (%d) prot %d (%d) op 0x%04x", + ar_hrd, ea->ar_hln, ar_pro, ea->ar_pln, ar_op); + return; + } + switch (ar_op) { + case ARPOP_REQUEST: + if (fd->win_info[0]) { + sprintf(fd->win_info[4], "Who has %s? Tell %s", + ip_to_str((guint8 *) ea->arp_tpa), ip_to_str((guint8 *) ea->arp_spa)); + } + break; + case ARPOP_REPLY: + if (fd->win_info[0]) { + sprintf(fd->win_info[4], "%s is at %s", + ip_to_str((guint8 *) ea->arp_spa), + ether_to_str((guint8 *) ea->arp_sha)); + } + break; + case ARPOP_RREQUEST: + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "RARP"); + sprintf(fd->win_info[4], "Who is %s? Tell %s", + ether_to_str((guint8 *) ea->arp_tha), + ether_to_str((guint8 *) ea->arp_sha)); + } + break; + case ARPOP_RREPLY: + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "RARP"); + sprintf(fd->win_info[4], "%s is at %s", + ether_to_str((guint8 *) ea->arp_sha), + ip_to_str((guint8 *) ea->arp_spa)); + } + break; + } +} diff --git a/packet-bootp.c b/packet-bootp.c new file mode 100644 index 0000000000..f3dc4092f9 --- /dev/null +++ b/packet-bootp.c @@ -0,0 +1,487 @@ +/* packet-bootp.c + * Routines for BOOTP/DHCP packet disassembly + * Gilbert Ramirez + * + * The information used comes from: + * RFC 2132: DHCP Options and BOOTP Vendor Extensions + * RFC 1542: Clarifications and Extensions for the Bootstrap Protocol + * RFC 2131: Dynamic Host Configuration Protocol + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#include "packet.h" +#include "ethereal.h" +#include "etypes.h" + +enum field_type { none, ipv4, string, toggle, yes_no, special, opaque, + val_u_byte, val_u_short, val_u_long, + val_s_long }; + +struct opt_info { + char *text; + enum field_type ftype; +}; + +#define NUM_OPT_INFOS 77 + +/* returns the number of bytes consumed by this option */ +int +bootp_option(const u_char *pd, GtkWidget *bp_tree, int voff, int eoff) +{ + char *text; + enum field_type ftype; + u_char code = pd[voff]; + int vlen = pd[voff+1]; + int i, consumed; + GtkWidget *vti, *v_tree; + + char *opt53_text[] = { + "Unknown Message Type", + "Discover", + "Offer", + "Request", + "Decline", + "ACK", + "NAK", + "Release", + "Inform" + }; + + static struct opt_info opt[] = { + /* 0 */ { "Padding", none }, + /* 1 */ { "Subnet Mask", ipv4 }, + /* 2 */ { "Time Offset", val_s_long }, + /* 3 */ { "Router", ipv4 }, + /* 4 */ { "Time Server", ipv4 }, + /* 5 */ { "Name Server", ipv4 }, + /* 6 */ { "Domain Name Server", ipv4 }, + /* 7 */ { "Log Server", ipv4 }, + /* 8 */ { "Cookie Server", ipv4 }, + /* 9 */ { "LPR Server", ipv4 }, + /* 10 */ { "Impress Server", ipv4 }, + /* 11 */ { "Resource Location Server", ipv4 }, + /* 12 */ { "Host Name", string }, + /* 13 */ { "Boot File Size", val_u_short }, + /* 14 */ { "Merit Dump File", string }, + /* 15 */ { "Domain Name", string }, + /* 16 */ { "Swap Server", ipv4 }, + /* 17 */ { "Root Path", string }, + /* 18 */ { "Extensions Path", string }, + /* 19 */ { "IP Forwarding", toggle }, + /* 20 */ { "Non-Local Source Routing", toggle }, + /* 21 */ { "Policy Filter", special }, + /* 22 */ { "Maximum Datagram Reassembly Size", val_u_short }, + /* 23 */ { "Default IP Time-to-Live", val_u_byte }, + /* 24 */ { "Path MTU Aging Timeout", val_u_long }, + /* 25 */ { "Path MTU Plateau Table", val_u_short }, + /* 26 */ { "Interface MTU", val_u_short }, + /* 27 */ { "All Subnets are Local", yes_no }, + /* 28 */ { "Broadcast Address", ipv4 }, + /* 29 */ { "Perform Mask Discovery", toggle }, + /* 30 */ { "Mask Supplier", yes_no }, + /* 31 */ { "Perform Router Discover", toggle }, + /* 32 */ { "Router Solicitation Address", ipv4 }, + /* 33 */ { "Static Route", special }, + /* 34 */ { "Trailer Encapsulation", toggle }, + /* 35 */ { "ARP Cache Timeout", val_u_long }, + /* 36 */ { "Ethernet Encapsulation", toggle }, + /* 37 */ { "TCP Default TTL", val_u_byte }, + /* 38 */ { "TCP Keepalive Interval", val_u_long }, + /* 39 */ { "TCP Keepalive Garbage", toggle }, + /* 40 */ { "Network Information Service Domain", string }, + /* 41 */ { "Network Information Service Servers", ipv4 }, + /* 42 */ { "Network Time Protocol Servers", ipv4 }, + /* 43 */ { "Vendor-Specific Information", special }, + /* 44 */ { "NetBIOS over TCP/IP Name Server", ipv4 }, + /* 45 */ { "NetBIOS over TCP/IP Datagram Distribution Name Server", ipv4 }, + /* 46 */ { "NetBIOS over TCP/IP Node Type", special }, + /* 47 */ { "NetBIOS over TCP/IP Scope", string }, + /* 48 */ { "X Window System Font Server", ipv4 }, + /* 49 */ { "X Window System Display Manager", ipv4 }, + /* 50 */ { "Requested IP Address", ipv4 }, + /* 51 */ { "IP Address Lease Time", val_u_long }, + /* 52 */ { "Option Overload", special }, + /* 53 */ { "DHCP Message Type", special }, + /* 54 */ { "Server Identifier", ipv4 }, + /* 55 */ { "Parameter Request List", opaque }, + /* 56 */ { "Message", string }, + /* 57 */ { "Maximum DHCP Message Size", val_u_short }, + /* 58 */ { "Renewal Time Value", val_u_long }, + /* 59 */ { "Rebinding Time Value", val_u_long }, + /* 60 */ { "Vendor class identifier", opaque }, + /* 61 */ { "Client identifier", special }, + /* 64 */ { "Network Information Service+ Domain", string }, + /* 65 */ { "Network Information Service+ Servers", ipv4 }, + /* 66 */ { "TFTP Server Name", string }, + /* 67 */ { "Bootfile name", string }, + /* 68 */ { "Mobile IP Home Agent", ipv4 }, + /* 69 */ { "SMTP Server", ipv4 }, + /* 70 */ { "POP3 Server", ipv4 }, + /* 71 */ { "NNTP Server", ipv4 }, + /* 72 */ { "Default WWW Server", ipv4 }, + /* 73 */ { "Default Finger Server", ipv4 }, + /* 74 */ { "Default IRC Server", ipv4 }, + /* 75 */ { "StreetTalk Server", ipv4 }, + /* 76 */ { "StreetTalk Directory Assistance Server", ipv4 } + }; + + text = opt[code].text; + /* Special cases */ + switch (code) { + /* Padding */ + case 0: + /* check how much padding we have */ + for (i = voff + 1; i < eoff; i++ ) { + if (pd[i] != 0) { + break; + } + } + i = i - voff; + add_item_to_tree(bp_tree, voff, i, "Padding"); + consumed = i; + return consumed; + + /* Policy Filter */ + case 21: + /* one IP address pair */ + if (vlen == 8) { + add_item_to_tree(bp_tree, voff, consumed, + "Option %d: %s = %s/%s", code, text, + ip_to_str((guint8*)&pd[voff+2]), + ip_to_str((guint8*)&pd[voff+6])); + } + /* > 1 IP address pair. Let's make a sub-tree */ + else { + + vti = add_item_to_tree(GTK_WIDGET(bp_tree), voff, + consumed, "Option %d: %s", code, text); + v_tree = gtk_tree_new(); + add_subtree(vti, v_tree, ETT_BOOTP_OPTION); + for (i = voff + 2; i < voff + consumed; i += 8) { + add_item_to_tree(v_tree, i, 4, "IP Address/Mask: %s/%s", + ip_to_str((guint8*)&pd[i]), + ip_to_str((guint8*)&pd[i+4])); + } + } + + /* Static Route */ + case 33: + /* one IP address pair */ + if (vlen == 8) { + add_item_to_tree(bp_tree, voff, consumed, + "Option %d: %s = %s/%s", code, text, + ip_to_str((guint8*)&pd[voff+2]), + ip_to_str((guint8*)&pd[voff+6])); + } + /* > 1 IP address pair. Let's make a sub-tree */ + else { + + vti = add_item_to_tree(GTK_WIDGET(bp_tree), voff, + consumed, "Option %d: %s", code, text); + v_tree = gtk_tree_new(); + add_subtree(vti, v_tree, ETT_BOOTP_OPTION); + for (i = voff + 2; i < voff + consumed; i += 8) { + add_item_to_tree(v_tree, i, 4, + "Destination IP Address/Router: %s/%s", + ip_to_str((guint8*)&pd[i]), + ip_to_str((guint8*)&pd[i+4])); + } + } + + /* DHCP Message Type */ + case 53: + if (pd[voff+2] > 0 && pd[voff+2] < 9) { + i = pd[voff + 2]; + } + else { + i = 0; + } + add_item_to_tree(bp_tree, voff, 3, "Option %d: %s = DHCP %s", + code, text, opt53_text[i]); + return vlen + 2; + + /* Client Identifier */ + case 61: + consumed = vlen + 2; + /* We *MAY* use hwtype/hwaddr. If we have 7 bytes, I'll + guess that the first is the hwtype, and the last 6 are + the hw addr */ + if (pd[voff+1] == 7) { + vti = add_item_to_tree(GTK_WIDGET(bp_tree), voff, + consumed, "Option %d: %s", code, text); + v_tree = gtk_tree_new(); + add_subtree(vti, v_tree, ETT_BOOTP_OPTION); + add_item_to_tree(v_tree, voff+2, 1, + "Hardware type: 0x%02x", pd[voff+2]); + add_item_to_tree(v_tree, voff+3, 6, + "Client hardware address: %s", + ether_to_str((guint8*)&pd[voff+3])); + } + /* otherwise, it's opaque data */ + else { + add_item_to_tree(bp_tree, voff, consumed, + "Option %d: %s (%d bytes)", code, text, vlen); + } + return consumed; + + /* End Option */ + case 255: + add_item_to_tree(bp_tree, voff, 1, "End Option", code); + consumed = 1; + return consumed; + + default: + /* nothing */ + } + + /* Normal cases */ + if (code < NUM_OPT_INFOS) { + consumed = vlen + 2; + text = opt[code].text; + ftype = opt[code].ftype; + + switch (ftype) { + case ipv4: + /* one IP address */ + if (vlen == 4) { + add_item_to_tree(bp_tree, voff, consumed, + "Option %d: %s = %s", code, text, + ip_to_str((guint8*)&pd[voff+2])); + } + /* > 1 IP addresses. Let's make a sub-tree */ + else { + + vti = add_item_to_tree(GTK_WIDGET(bp_tree), voff, + consumed, "Option %d: %s", code, text); + v_tree = gtk_tree_new(); + add_subtree(vti, v_tree, ETT_BOOTP_OPTION); + for (i = voff + 2; i < voff + consumed; i += 4) { + add_item_to_tree(v_tree, i, 4, "IP Address: %s", + ip_to_str((guint8*)&pd[i])); + } + } + break; + + case string: + add_item_to_tree(bp_tree, voff, consumed, + "Option %d: %s = %s", code, text, &pd[voff+2]); + break; + + case opaque: + add_item_to_tree(bp_tree, voff, consumed, + "Option %d: %s = %s (%d bytes)", + code, text, &pd[voff+2], vlen); + break; + + case val_u_short: + /* one IP address */ + if (vlen == 2) { + add_item_to_tree(bp_tree, voff, consumed, + "Option %d: %s = %d", code, text, + pntohs(&pd[voff+2])); + } + /* > 1 u_short */ + else { + vti = add_item_to_tree(GTK_WIDGET(bp_tree), voff, + consumed, "Option %d: %s", code, text); + v_tree = gtk_tree_new(); + add_subtree(vti, v_tree, ETT_BOOTP_OPTION); + for (i = voff + 2; i < voff + consumed; i += 2) { + add_item_to_tree(v_tree, i, 4, "Value: %d", + pntohs(&pd[i])); + } + } + break; + + case val_u_long: + add_item_to_tree(bp_tree, voff, consumed, + "Option %d: %s = %d", code, text, + pntohl(&pd[voff+2])); + break; + + case val_u_byte: + add_item_to_tree(bp_tree, voff, consumed, + "Option %d: %s = %d", code, text, pd[voff+2]); + break; + + case toggle: + i = pd[voff+2]; + if (i != 0 && i != 1) { + add_item_to_tree(bp_tree, voff, consumed, + "Option %d: %s = Invalid Value %d", code, text, + pd[voff+2]); + } + else { + add_item_to_tree(bp_tree, voff, consumed, + "Option %d: %s = %s", code, text, + pd[voff+2] == 0 ? "Disabled" : "Enabled"); + } + break; + + case yes_no: + i = pd[voff+2]; + if (i != 0 && i != 1) { + add_item_to_tree(bp_tree, voff, consumed, + "Option %d: %s = Invalid Value %d", code, text, + pd[voff+2]); + } + else { + add_item_to_tree(bp_tree, voff, consumed, + "Option %d: %s = %s", code, text, + pd[voff+2] == 0 ? "No" : "Yes"); + } + break; + + default: + add_item_to_tree(bp_tree, voff, consumed, "Option %d: %s", + code, text); + } + } + else { + add_item_to_tree(bp_tree, voff, 1, "Unknown Option Code: %d", code); + } + + return consumed; +} + +void +dissect_bootp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) +{ + GtkWidget *bp_tree, *ti; + int voff, eoff; /* vender offset, end offset */ + int vlen; + + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "BOOTP"); + + /* if hwaddr is 6 bytes, assume MAC */ + if (pd[offset] == 1 && pd[offset+2] == 6) { + sprintf(fd->win_info[4], "Boot Request from %s", + ether_to_str((guint8*)&pd[offset+28])); + } + else { + strcpy(fd->win_info[4], pd[offset] == 1 ? "Boot Request" : + "Boot Reply"); + } + } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, fd->cap_len - offset, + "Bootstrap Protocol"); + bp_tree = gtk_tree_new(); + add_subtree(ti, bp_tree, ETT_BOOTP); + + add_item_to_tree(bp_tree, offset, 1, pd[offset] == 1 ? + "Boot Request" : "Boot Reply"); + add_item_to_tree(bp_tree, offset + 1, 1, + "Hardware type: 0x%02x", pd[offset+1]); + add_item_to_tree(bp_tree, offset + 2, 1, + "Hardware address length: %d", pd[offset+2]); + add_item_to_tree(bp_tree, offset + 3, 1, + "Hops: %d", pd[offset+3]); + add_item_to_tree(bp_tree, offset + 4, 4, + "Transaction ID: 0x%08x", pntohl(&pd[offset+4])); + add_item_to_tree(bp_tree, offset + 8, 2, + "Seconds elapsed: %d", pntohs(&pd[offset+8])); + add_item_to_tree(bp_tree, offset + 10, 2, + "Broadcast flag: %d", pd[offset+10] & 1); + add_item_to_tree(bp_tree, offset + 12, 4, + "Client IP address: %s", ip_to_str((guint8*)&pd[offset+12])); + add_item_to_tree(bp_tree, offset + 16, 4, + "Your (client) IP address: %s", ip_to_str((guint8*)&pd[offset+16])); + add_item_to_tree(bp_tree, offset + 20, 4, + "Next server IP address: %s", ip_to_str((guint8*)&pd[offset+20])); + add_item_to_tree(bp_tree, offset + 24, 4, + "Relay agent IP address: %s", ip_to_str((guint8*)&pd[offset+24])); + + /* If HW address is 6 bytes, assume MAC. */ + if (pd[offset+2] == 6) { + add_item_to_tree(bp_tree, offset + 28, 6, + "Client hardware address: %s", + ether_to_str((guint8*)&pd[offset+28])); + } + else { + add_item_to_tree(bp_tree, offset + 28, 16, + "Client hardware address: %02x:%02x%02x:%02x:%02x:%02x:%02x:%02x%02x:%02x%02x:%02x:%02x:%02x:%02x:%02x", + pd[offset+28], pd[offset+29], pd[offset+30], pd[offset+31], + pd[offset+32], pd[offset+33], pd[offset+34], pd[offset+35], + pd[offset+36], pd[offset+37], pd[offset+38], pd[offset+39], + pd[offset+40], pd[offset+41], pd[offset+42], pd[offset+43]); + } + + /* The server host name is optional */ + if (pd[offset+44]) { + add_item_to_tree(bp_tree, offset + 44, 64, + "Server host name: %s", &pd[offset+44]); + } + else { + add_item_to_tree(bp_tree, offset + 44, 64, + "Server host name not given"); + } + + /* Boot file */ + if (pd[offset+108]) { + add_item_to_tree(bp_tree, offset + 108, 128, + "Boot file nme: %s", &pd[offset+108]); + } + else { + add_item_to_tree(bp_tree, offset + 108, 128, + "Boot file name not given"); + } + + if (pntohl(&pd[offset+236]) == 0x63538263) { + add_item_to_tree(bp_tree, offset + 236, 4, + "Magic cookie: %s (generic)", + ip_to_str((guint8*)&pd[offset+236])); + } + else { + add_item_to_tree(bp_tree, offset + 236, 4, + "Magic cookie: %s", + ip_to_str((guint8*)&pd[offset+236])); + } + + voff = offset+240; + eoff = fd->cap_len; + + while (voff < eoff) { + voff += bootp_option(pd, bp_tree, voff, eoff); + } + } +} + diff --git a/packet-data.c b/packet-data.c new file mode 100644 index 0000000000..5437bd3e47 --- /dev/null +++ b/packet-data.c @@ -0,0 +1,51 @@ + +/* packet-data.c + * Routines for raw data (default case) + * Gilbert Ramirez + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#include "ethereal.h" +#include "packet.h" + + +void +dissect_data(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + + if (fd->cap_len > offset && tree) { + (void) add_item_to_tree(GTK_WIDGET(tree), offset, fd->cap_len - offset, + "Data"); + } +} + diff --git a/packet-dns.c b/packet-dns.c new file mode 100644 index 0000000000..c4ef11f7ce --- /dev/null +++ b/packet-dns.c @@ -0,0 +1,442 @@ +/* packet-dns.c + * Routines for DNS packet disassembly + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include "packet.h" + + +/* DNS structs and definitions */ + +typedef struct _e_dns { + guint16 dns_id; + guint16 dns_flags; + guint16 dns_quest; + guint16 dns_ans; + guint16 dns_auth; + guint16 dns_add; +} e_dns; + +#define MAXDNAME 1025 /* maximum domain name */ + +/* type values */ +#define T_A 1 /* host address */ +#define T_NS 2 /* authoritative server */ +#define T_CNAME 5 /* canonical name */ +#define T_SOA 6 /* start of authority zone */ +#define T_WKS 11 /* well known service */ +#define T_PTR 12 /* domain name pointer */ +#define T_HINFO 13 /* host information */ +#define T_MX 15 /* mail routing information */ +#define T_TXT 16 /* text strings */ +#define T_AAAA 28 /* IP6 Address */ + + +static const u_char *dns_data_ptr; + +static char * +dns_type_name (int type) +{ + char *type_names[36] = { + "unused", "A", "NS", "MD", "MF", "CNAME", "SOA", "MB", "MG", "MR", + "NULL", "WKS", "PTR", "HINFO", "MINFO", "MX", "TXT", "RP", "AFSDB", + "X25", "ISDN", "RT", "NSAP", "NSAP_PTR", "SIG", "KEY", "PX", "GPOS", + "AAAA", "LOC", "NXT", "EID", "NIMLOC", "SRV", "ATMA", "NAPTR" + }; + + if (type <= 35) + return type_names[type]; + + /* special cases */ + switch (type) + { + /* non standard */ + case 100: + return "UINFO"; + case 101: + return "UID"; + case 102: + return "GID"; + case 103: + return "UNSPEC"; + + /* queries */ + case 251: + return "IXFR"; + case 252: + return "AXFR"; + case 253: + return "MAILB"; + case 254: + return "MAILA"; + case 255: + return "ANY"; + } + + return "unknown"; +} + + +static char * +dns_class_name(int class) +{ + char *class_name; + + switch (class) { + case 1: + class_name = "inet"; + break; + case 3: + class_name = "chaos"; + break; + case 4: + class_name = "hesiod"; + break; + default: + class_name = "unknown"; + } + + return class_name; +} + + +static int +is_compressed_name(const u_char *foo) +{ + return (0xc0 == (*foo & 0xc0)); +} + + +static int +get_compressed_name_offset(const u_char *ptr) +{ + return ((*ptr & ~0xc0) << 8) | *(ptr+1); +} + + +static int +copy_one_name_component(const u_char *dataptr, char *nameptr) +{ + int len; + int n; + + len = n = *dataptr++; + if (0 == len) + return 0; + + while (n-- > 0) + *nameptr++ = *dataptr++; + + return len; +} + + +static int +copy_name_component_rec(const u_char *dataptr, char *nameptr, int *real_string_len) +{ + int len = 0; + int str_len; + int offset; + int compress = 0; + + if (is_compressed_name(dataptr)) { + compress = 1; + offset = get_compressed_name_offset(dataptr); + dataptr = dns_data_ptr + offset; + copy_name_component_rec(dataptr, nameptr, &str_len); + *real_string_len += str_len; + nameptr += str_len; + len = 2; + } + else { + str_len = copy_one_name_component(dataptr, nameptr); + *real_string_len = str_len; + dataptr += str_len + 1; + len += str_len + 1; + nameptr += str_len; + } + + if (compress) + return len; + + (*real_string_len)++; + + if (*dataptr > 0) { + *nameptr++ = '.'; + len += copy_name_component_rec(dataptr, nameptr, &str_len); + *real_string_len += str_len; + return len; + } + + return len + 1; +} + + +static int +get_dns_name(const u_char *pd, int offset, char *nameptr, int maxname) +{ + int len; + const u_char *dataptr = pd + offset; + int str_len = 0; + + memset (nameptr, 0, maxname); + len = copy_name_component_rec(dataptr, nameptr, &str_len); + + return len; +} + + +static int +get_dns_name_type_class (const u_char *pd, + int offset, + char *name_ret, + int *type_ret, + int *class_ret) +{ + int len; + int name_len; + int type; + int class; + char name[MAXDNAME]; + const u_char *pd_save; + + name_len = get_dns_name(pd, offset, name, sizeof(name)); + pd += offset; + pd_save = pd; + pd += name_len; + + type = (*pd << 8) | *(pd + 1); + pd += 2; + class = (*pd << 8) | *(pd + 1); + pd += 2; + + strcpy (name_ret, name); + *type_ret = type; + *class_ret = class; + + len = pd - pd_save; + return len; +} + + +static int +dissect_dns_query(const u_char *pd, int offset, GtkWidget *dns_tree) +{ + int len; + char name[MAXDNAME]; + int type; + int class; + char *class_name; + char *type_name; + + len = get_dns_name_type_class (pd, offset, name, &type, &class); + + type_name = dns_type_name(type); + class_name = dns_class_name(class); + + add_item_to_tree(dns_tree, offset, len, "%s: type %s, class %s", + name, type_name, class_name ); + + return len; +} + + +static int +dissect_dns_answer(const u_char *pd, int offset, GtkWidget *dns_tree) +{ + int len; + char name[MAXDNAME]; + int type; + int class; + char *class_name; + char *type_name; + const u_char *dptr; + const u_char *data_start; + const u_char *res_ptr; + u_int ttl; + u_short data_len; + + data_start = dptr = pd + offset; + + len = get_dns_name_type_class (pd, offset, name, &type, &class); + dptr += len; + + /* this works regardless of the alignment */ + ttl = (*dptr << 24) | *(dptr + 1) << 16 | *(dptr + 2) << 8 | *(dptr + 3); + dptr += 4; + data_len = (*dptr << 8) | *(dptr + 1); + dptr += 2; + + type_name = dns_type_name(type); + class_name = dns_class_name(class); + res_ptr = dptr; + + /* skip the resource data */ + dptr += data_len; + + len = dptr - data_start; + + switch (type) { + case T_A: /* "A" record */ + add_item_to_tree(dns_tree, offset, len, + "%s: type %s, class %s, addr %d.%d.%d.%d", + name, type_name, class_name, + *res_ptr, *(res_ptr+1), *(res_ptr+2), *(res_ptr+3)); + break; + + case T_NS: /* "NS" record */ + { + char ns_name[MAXDNAME]; + + get_dns_name(res_ptr, 0, ns_name, sizeof(ns_name)); + add_item_to_tree(dns_tree, offset, len, + "%s: %s, type %s, class %s", + name, ns_name, type_name, class_name); + + } + break; + + /* TODO: parse more record types */ + + default: + add_item_to_tree(dns_tree, offset, len, "%s: type %s, class %s", + name, type_name, class_name); + } + + return len; +} + + +static int +dissect_answer_records(int count, const u_char *pd, int cur_off, + GtkWidget *dns_tree, char *name) +{ + int start_off; + GtkWidget *qatree, *ti; + + qatree = gtk_tree_new(); + start_off = cur_off; + + while (count-- > 0) + cur_off += dissect_dns_answer(pd, cur_off, qatree); + ti = add_item_to_tree(GTK_WIDGET(dns_tree), start_off, cur_off - start_off, name); + add_subtree(ti, qatree, ETT_DNS_ANS); + + return cur_off - start_off; +} + + +static int +dissect_query_records(int count, const u_char *pd, + int cur_off, GtkWidget *dns_tree) +{ + int start_off; + GtkWidget *qatree, *ti; + + qatree = gtk_tree_new(); + start_off = cur_off; + + while (count-- > 0) + cur_off += dissect_dns_query(pd, cur_off, qatree); + ti = add_item_to_tree(GTK_WIDGET(dns_tree), + start_off, cur_off - start_off, "Queries"); + add_subtree(ti, qatree, ETT_DNS_QRY); + + return cur_off - start_off; +} + + + +void +dissect_dns(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + e_dns *dh; + GtkWidget *dns_tree, *ti; + guint16 id, flags, quest, ans, auth, add; + int query = 0; + int cur_off; + + dns_data_ptr = &pd[offset]; + dh = (e_dns *) dns_data_ptr; + + /* To do: check for runts, errs, etc. */ + id = ntohs(dh->dns_id); + flags = ntohs(dh->dns_flags); + quest = ntohs(dh->dns_quest); + ans = ntohs(dh->dns_ans); + auth = ntohs(dh->dns_auth); + add = ntohs(dh->dns_add); + + query = ! (flags & (1 << 15)); + + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "DNS (UDP)"); + strcpy(fd->win_info[4], query ? "Query" : "Response"); + } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, 4, + query ? "DNS query" : "DNS response"); + + dns_tree = gtk_tree_new(); + add_subtree(ti, dns_tree, ETT_DNS); + + add_item_to_tree(dns_tree, offset, 2, "ID: 0x%04x", id); + + add_item_to_tree(dns_tree, offset + 2, 2, "Flags: 0x%04x", flags); + add_item_to_tree(dns_tree, offset + 4, 2, "Questions: %d", quest); + add_item_to_tree(dns_tree, offset + 6, 2, "Answer RRs: %d", ans); + add_item_to_tree(dns_tree, offset + 8, 2, "Authority RRs: %d", auth); + add_item_to_tree(dns_tree, offset + 10, 2, "Additional RRs: %d", add); + + cur_off = offset + 12; + + if (quest > 0) + cur_off += dissect_query_records(quest, pd, cur_off, dns_tree); + + if (ans > 0) + cur_off += dissect_answer_records(ans, pd, cur_off, dns_tree, "Answers"); + + if (auth > 0) + cur_off += dissect_answer_records(auth, pd, cur_off, dns_tree, + "Authoritative nameservers"); + + if (add > 0) + cur_off += dissect_answer_records(add, pd, cur_off, dns_tree, + "Additional records"); + } +} diff --git a/packet-eth.c b/packet-eth.c new file mode 100644 index 0000000000..cc5c1154b1 --- /dev/null +++ b/packet-eth.c @@ -0,0 +1,125 @@ +/* packet-eth.c + * Routines for ethernet packet disassembly + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include + +#include + +#include "packet.h" +#include "ethereal.h" +#include "etypes.h" + +/* These are the Netware-ish names for the different Ethernet frame types. + EthernetII: The ethernet with a Type field instead of a length field + Ethernet802.2: An 802.3 header followed by an 802.3 header + Ethernet802.3: A raw 802.3 packet. IPX/SPX can be the only payload. + There's not 802.2 hdr in this. + EthernetSNAP: Basically 802.2, just with 802.2SNAP. For our purposes, + there's no difference between 802.2 and 802.2SNAP, since we just + pass it down to dissect_llc(). -- Gilbert +*/ +#define ETHERNET_II 0 +#define ETHERNET_802_2 1 +#define ETHERNET_802_3 2 +#define ETHERNET_SNAP 3 + +void +dissect_eth(const u_char *pd, frame_data *fd, GtkTree *tree) { + guint16 etype, length; + int offset = 14; + GtkWidget *fh_tree, *ti; + int ethhdr_type; /* the type of ethernet frame */ + + if (fd->win_info[0]) { + strcpy(fd->win_info[2], ether_to_str((guint8 *)&pd[0])); + strcpy(fd->win_info[1], ether_to_str((guint8 *)&pd[6])); + strcpy(fd->win_info[4], "Ethernet II"); + } + + etype = (pd[12] << 8) | pd[13]; + + /* either ethernet802.3 or ethernet802.2 */ + if (etype <= IEEE_802_3_MAX_LEN) { + length = etype; + + /* Is there an 802.2 layer? I can tell by looking at the first 2 + bytes after the 802.3 header. If they are 0xffff, then what + follows the 802.3 header is an IPX payload, meaning no 802.2. + (IPX/SPX is they only thing that can be contained inside a + straight 802.3 packet). A non-0xffff value means that there's an + 802.2 layer inside the 802.3 layer */ + if (pd[14] == 0xff && pd[15] == 0xff) { + ethhdr_type = ETHERNET_802_3; + } + else { + ethhdr_type = ETHERNET_802_2; + } + + if (fd->win_info[0]) { sprintf(fd->win_info[4], "802.3"); } + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), 0, offset, + "IEEE 802.3 %s(%d on wire, %d captured)", + (ethhdr_type == ETHERNET_802_3 ? "Raw " : ""), + fd->pkt_len, fd->cap_len); + + fh_tree = gtk_tree_new(); + add_subtree(ti, fh_tree, ETT_IEEE8023); + add_item_to_tree(fh_tree, 0, 6, "Destination: %s", + ether_to_str((guint8 *) &pd[0])); + add_item_to_tree(fh_tree, 6, 6, "Source: %s", + ether_to_str((guint8 *) &pd[6])); + add_item_to_tree(fh_tree, 12, 2, "Length: %d", length); + } + + } else if (tree) { + ethhdr_type = ETHERNET_II; + ti = add_item_to_tree(GTK_WIDGET(tree), 0, 14, + "Ethernet II (%d on wire, %d captured)", fd->pkt_len, fd->cap_len); + fh_tree = gtk_tree_new(); + add_subtree(ti, fh_tree, ETT_ETHER2); + add_item_to_tree(fh_tree, 0, 6, "Destination: %s", + ether_to_str((guint8 *) &pd[0])); + add_item_to_tree(fh_tree, 6, 6, "Source: %s", + ether_to_str((guint8 *) &pd[6])); + } + + /* either ethernet802.3 or ethernet802.2 */ + switch (ethhdr_type) { + case ETHERNET_802_3: + dissect_ipx(pd, offset, fd, tree); + return; + case ETHERNET_802_2: + dissect_llc(pd, offset, fd, tree); + return; + } + + /* Ethernet_II */ + ethertype(etype, offset, pd, fd, tree, fh_tree); +} + diff --git a/packet-ip.c b/packet-ip.c new file mode 100644 index 0000000000..3675e28a8f --- /dev/null +++ b/packet-ip.c @@ -0,0 +1,319 @@ +/* packet-ip.c + * Routines for IP and miscellaneous IP protocol packet disassembly + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include "ethereal.h" +#include "packet.h" +#include "etypes.h" +#include "resolv.h" + +void +dissect_ip(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + e_ip iph; + GtkWidget *ip_tree, *ti; + gchar tos_str[32]; + + /* To do: check for runts, errs, etc. */ + /* Avoids alignment problems on many architectures. */ + memcpy(&iph, &pd[offset], sizeof(e_ip)); + iph.ip_len = ntohs(iph.ip_len); + iph.ip_id = ntohs(iph.ip_id); + iph.ip_off = ntohs(iph.ip_off); + iph.ip_sum = ntohs(iph.ip_sum); + + if (fd->win_info[0]) { + switch (iph.ip_p) { + case IP_PROTO_ICMP: + case IP_PROTO_IGMP: + case IP_PROTO_TCP: + case IP_PROTO_UDP: + case IP_PROTO_OSPF: + /* Names are set in the associated dissect_* routines */ + break; + default: + strcpy(fd->win_info[3], "IP"); + sprintf(fd->win_info[4], "Unknown IP protocol (%02x)", iph.ip_p); + } + + strcpy(fd->win_info[1], get_hostname(iph.ip_src)); + strcpy(fd->win_info[2], get_hostname(iph.ip_dst)); + } + + iph.ip_tos = IPTOS_TOS(iph.ip_tos); + switch (iph.ip_tos) { + case IPTOS_NONE: + strcpy(tos_str, "None"); + break; + case IPTOS_LOWDELAY: + strcpy(tos_str, "Minimize delay"); + break; + case IPTOS_THROUGHPUT: + strcpy(tos_str, "Maximize throughput"); + break; + case IPTOS_RELIABILITY: + strcpy(tos_str, "Maximize reliability"); + break; + case IPTOS_LOWCOST: + strcpy(tos_str, "Minimize cost"); + break; + default: + strcpy(tos_str, "Unknon. Malformed?"); + break; + } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, (iph.ip_hl * 4), + "Internet Protocol"); + ip_tree = gtk_tree_new(); + add_subtree(ti, ip_tree, ETT_IP); + add_item_to_tree(ip_tree, offset, 1, "Version: %d", iph.ip_v); + add_item_to_tree(ip_tree, offset, 1, "Header length: %d", iph.ip_hl); + add_item_to_tree(ip_tree, offset + 1, 1, "Type of service: 0x%02x (%s)", + iph.ip_tos, tos_str); + add_item_to_tree(ip_tree, offset + 2, 2, "Total length: %d", iph.ip_len); + add_item_to_tree(ip_tree, offset + 4, 2, "Identification: 0x%04x", + iph.ip_id); + /* To do: add flags */ + add_item_to_tree(ip_tree, offset + 6, 2, "Fragment offset: %d", + iph.ip_off & 0x1fff); + add_item_to_tree(ip_tree, offset + 8, 1, "Time to live: %d", + iph.ip_ttl); + add_item_to_tree(ip_tree, offset + 9, 1, "Protocol: 0x%02x", + iph.ip_p); + add_item_to_tree(ip_tree, offset + 10, 2, "Header checksum: 0x%04x", + iph.ip_sum); + add_item_to_tree(ip_tree, offset + 12, 4, "Source address: %s", + get_hostname(iph.ip_src)); + add_item_to_tree(ip_tree, offset + 16, 4, "Destination address: %s", + get_hostname(iph.ip_dst)); + } + + offset += iph.ip_hl * 4; + switch (iph.ip_p) { + case IP_PROTO_ICMP: + dissect_icmp(pd, offset, fd, tree); + break; + case IP_PROTO_IGMP: + dissect_igmp(pd, offset, fd, tree); + break; + case IP_PROTO_TCP: + dissect_tcp(pd, offset, fd, tree); + break; + case IP_PROTO_UDP: + dissect_udp(pd, offset, fd, tree); + break; + case IP_PROTO_OSPF: + dissect_ospf(pd, offset, fd, tree); + break; + } +} + + +const gchar *unreach_str[] = {"Network unreachable", + "Host unreachable", + "Protocol unreachable", + "Port unreachable", + "Fragmentation needed", + "Source route failed", + "Administratively prohibited", + "Network unreachable for TOS", + "Host unreachable for TOS", + "Communication administratively filtered", + "Host precedence violation", + "Precedence cutoff in effect"}; + +const gchar *redir_str[] = {"Redirect for network", + "Redirect for host", + "Redirect for TOS and network", + "Redirect for TOS and host"}; + +const gchar *ttl_str[] = {"TTL equals 0 during transit", + "TTL equals 0 during reassembly"}; + +const gchar *par_str[] = {"IP header bad", "Required option missing"}; + +void +dissect_icmp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + e_icmp *ih; + GtkWidget *icmp_tree, *ti; + guint16 cksum; + gchar type_str[64], code_str[64] = ""; + + ih = (e_icmp *) &pd[offset]; + /* To do: check for runts, errs, etc. */ + cksum = ntohs(ih->icmp_cksum); + + switch (ih->icmp_type) { + case ICMP_ECHOREPLY: + strcpy(type_str, "Echo (ping) reply"); + break; + case ICMP_UNREACH: + strcpy(type_str, "Destination unreachable"); + if (ih->icmp_code < 12) { + sprintf(code_str, "(%s)", unreach_str[ih->icmp_code]); + } else { + strcpy(code_str, "(Unknown - error?)"); + } + break; + case ICMP_SOURCEQUENCH: + strcpy(type_str, "Source quench (flow control)"); + break; + case ICMP_REDIRECT: + strcpy(type_str, "Redirect"); + if (ih->icmp_code < 4) { + sprintf(code_str, "(%s)", redir_str[ih->icmp_code]); + } else { + strcpy(code_str, "(Unknown - error?)"); + } + break; + case ICMP_ECHO: + strcpy(type_str, "Echo (ping) request"); + break; + case ICMP_TIMXCEED: + strcpy(type_str, "Time-to-live exceeded"); + if (ih->icmp_code < 2) { + sprintf(code_str, "(%s)", ttl_str[ih->icmp_code]); + } else { + strcpy(code_str, "(Unknown - error?)"); + } + break; + case ICMP_PARAMPROB: + strcpy(type_str, "Parameter problem"); + if (ih->icmp_code < 2) { + sprintf(code_str, "(%s)", par_str[ih->icmp_code]); + } else { + strcpy(code_str, "(Unknown - error?)"); + } + break; + case ICMP_TSTAMP: + strcpy(type_str, "Timestamp request"); + break; + case ICMP_TSTAMPREPLY: + strcpy(type_str, "Timestamp reply"); + break; + case ICMP_MASKREQ: + strcpy(type_str, "Address mask request"); + break; + case ICMP_MASKREPLY: + strcpy(type_str, "Address mask reply"); + break; + default: + strcpy(type_str, "Unknown ICMP (obsolete or malformed?)"); + } + + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "ICMP"); + strcpy(fd->win_info[4], type_str); + } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, 4, + "Internet Control Message Protocol"); + icmp_tree = gtk_tree_new(); + add_subtree(ti, icmp_tree, ETT_ICMP); + add_item_to_tree(icmp_tree, offset, 1, "Type: %d (%s)", + ih->icmp_type, type_str); + add_item_to_tree(icmp_tree, offset + 1, 1, "Code: %d %s", + ih->icmp_code, code_str); + add_item_to_tree(icmp_tree, offset + 2, 2, "Checksum: 0x%04x", + ih->icmp_cksum); + } +} + +void +dissect_igmp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + e_igmp *ih; + GtkWidget *igmp_tree, *ti; + guint16 cksum; + gchar type_str[64] = ""; + + ih = (e_igmp *) &pd[offset]; + /* To do: check for runts, errs, etc. */ + cksum = ntohs(ih->igmp_cksum); + + switch (ih->igmp_t) { + case IGMP_M_QRY: + strcpy(type_str, "Router query"); + break; + case IGMP_V1_M_RPT: + strcpy(type_str, "Host response (v1)"); + break; + case IGMP_V2_LV_GRP: + strcpy(type_str, "Leave group (v2)"); + break; + case IGMP_DVMRP: + strcpy(type_str, "DVMRP"); + break; + case IGMP_PIM: + strcpy(type_str, "PIM"); + break; + case IGMP_V2_M_RPT: + strcpy(type_str, "Host reponse (v2)"); + break; + case IGMP_MTRC_RESP: + strcpy(type_str, "Traceroute response"); + break; + case IGMP_MTRC: + strcpy(type_str, "Traceroute message"); + break; + default: + strcpy(type_str, "Unknown IGMP"); + } + + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "IGMP"); + } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, 4, + "Internet Group Management Protocol"); + igmp_tree = gtk_tree_new(); + add_subtree(ti, igmp_tree, ETT_IGMP); + add_item_to_tree(igmp_tree, offset, 1, "Version: %d", + ih->igmp_v); + add_item_to_tree(igmp_tree, offset , 1, "Type: %d (%s)", + ih->igmp_t, type_str); + add_item_to_tree(igmp_tree, offset + 1, 1, "Unused: 0x%02x", + ih->igmp_unused); + add_item_to_tree(igmp_tree, offset + 2, 2, "Checksum: 0x%04x", + ih->igmp_cksum); + add_item_to_tree(igmp_tree, offset + 4, 4, "Group address: %s", + ip_to_str((guint8 *) &ih->igmp_gaddr)); + } +} diff --git a/packet-ipv6.c b/packet-ipv6.c new file mode 100644 index 0000000000..c2a84b6678 --- /dev/null +++ b/packet-ipv6.c @@ -0,0 +1,105 @@ +/* packet-ipv6.c + * Routines for IPv6 packet disassembly + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include "ethereal.h" +#include "packet.h" +#include "packet-ipv6.h" +#include "etypes.h" + +void +dissect_ipv6(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + GtkWidget *ipv6_tree, *ti; + + e_ipv6_header ipv6; + + memcpy(&ipv6, (void *) &pd[offset], 8); + + if (fd->win_info[0]) { + switch(ipv6.next_header){ + /* + case IP_PROTO_ICMP: + case IP_PROTO_IGMP: + case IP_PROTO_TCP: + case IP_PROTO_UDP: + case IP_PROTO_OSPF: + */ + /* Names are set in the associated dissect_* routines */ + /* break; */ + default: + strcpy(fd->win_info[3], "IPv6"); + sprintf(fd->win_info[4], "IPv6 support is still under development (%d)", ipv6.next_header); + } + } + if (tree) { + /* !!! specify length */ + ti = add_item_to_tree(GTK_WIDGET(tree), offset, 40, + "Internet Protocol Version 6"); + ipv6_tree = gtk_tree_new(); + add_subtree(ti, ipv6_tree, ETT_IPv6); + + /* !!! warning: version also contains 4 Bit priority */ + add_item_to_tree(ipv6_tree, offset, 1, "Version: %d Priority: %d", ipv6.version >> 4 , ipv6.version & 15); + add_item_to_tree(ipv6_tree, offset + 6, 1, "Next Header: %d", ipv6.next_header); + add_item_to_tree(ipv6_tree, offset + 4, 2, "Payload Length: %d", ntohs(ipv6.payload_length)); + } + + /* start of the new header (could be a extension header) */ + offset += 40; + switch (ipv6.next_header) { + case IP_PROTO_ICMP: + dissect_icmp(pd, offset, fd, tree); + break; + case IP_PROTO_IGMP: + dissect_igmp(pd, offset, fd, tree); + break; + case IP_PROTO_TCP: + dissect_tcp(pd, offset, fd, tree); + break; + case IP_PROTO_UDP: + dissect_udp(pd, offset, fd, tree); + break; + case IP_PROTO_OSPF: + dissect_ospf(pd, offset, fd, tree); + break; + default: + dissect_data(pd, offset, fd, tree); + } +} + diff --git a/packet-ipv6.h b/packet-ipv6.h new file mode 100644 index 0000000000..75ac3d9dd0 --- /dev/null +++ b/packet-ipv6.h @@ -0,0 +1,8 @@ +typedef struct _e_ipv6_header{ + /* the version contains 4-bit version and 4-bit priority */ + guint8 version; + guint8 flow_label[3]; + guint16 payload_length; + guint8 next_header; + guint8 hop_limit; +} e_ipv6_header; diff --git a/packet-ipx.c b/packet-ipx.c new file mode 100644 index 0000000000..53c3f3f770 --- /dev/null +++ b/packet-ipx.c @@ -0,0 +1,492 @@ +/* packet-ipx.c + * Routines for NetWare's IPX + * Gilbert Ramirez + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include "ethereal.h" +#include "packet.h" + +/* The information in this module (IPX, SPX, NCP) comes from: + NetWare LAN Analysis, Second Edition + Laura A. Chappell and Dan E. Hakes + (c) 1994 Novell, Inc. + Novell Press, San Jose. + ISBN: 0-7821-1362-1 +*/ + +static void +dissect_spx(const u_char *pd, int offset, frame_data *fd, GtkTree *tree); +static void +dissect_ncp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree); + + +struct port_info { + u_short port; + char *text; +}; + +struct conn_info { + u_char ctrl; + char *text; +}; + +struct req_info { + u_short req; + char *text; +}; + +/* ================================================================= */ +/* IPX */ +/* ================================================================= */ +static char* +port_text(u_short port) { + int i=0; + + static struct port_info ports[] = { + { 0x0451, "NCP" }, + { 0x0452, "SAP" }, + { 0x0453, "RIP" }, + { 0x0455, "NetBIOS" }, + { 0x0456, "Diagnostic" }, + { 0x0457, "Serialization" }, + { 0x0000, NULL } + }; + + while (ports[i].text != NULL) { + if (ports[i].port == port) { + return ports[i].text; + } + i++; + } + return "Unknown"; +} + +char * +ipx_packet_type(u_char val) +{ + if (val == 0) { + return "IPX"; + } + else if (val == 5) { + return "SPX"; + } + else if (val == 17) { + return "NCP"; + } + else if (val == 20) { + return "NetBIOS"; + } + else if (val >= 16 && val <= 31) { + return "Experimental Protocol"; + } + else { + return "Unknown"; + } +} + +gchar* +network_to_string(const guint8 *ad) +{ + static gchar str[3][12]; + static gchar *cur; + + if (cur == &str[0][0]) { + cur = &str[1][0]; + } else if (cur == &str[1][0]) { + cur = &str[2][0]; + } else { + cur = &str[0][0]; + } + + sprintf(cur, "%02X %02X %02X %02X", ad[0], ad[1], ad[2], ad[3]); + return cur; +} + +void +dissect_ipx(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + + GtkWidget *ipx_tree, *ti; + u_char ipx_type; + + char *dnet, *snet; + guint16 dsocket, ssocket; + + /* Calculate here for use in win_info[] and in tree */ + dnet = network_to_string((guint8*)&pd[offset+6]); + snet = network_to_string((guint8*)&pd[offset+18]); + dsocket = pntohs(&pd[offset+16]); + + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "IPX"); + /*sprintf(fd->win_info[4], "Network %s --> %s", snet, dnet);*/ + sprintf(fd->win_info[4], "%s (0x%04X)", port_text(dsocket), dsocket); + } + + ipx_type = pd[offset+5]; + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, 30, + "Internetwork Packet Exchange"); + ipx_tree = gtk_tree_new(); + add_subtree(ti, ipx_tree, ETT_IPX); + add_item_to_tree(ipx_tree, offset, 2, "Checksum: 0x%04X", + (pd[offset] << 8) | pd[offset+1]); + add_item_to_tree(ipx_tree, offset+2, 2, "Length: %d bytes", + (pd[offset+2] << 8) | pd[offset+3]); + add_item_to_tree(ipx_tree, offset+4, 1, "Transport Control: %d hops", + pd[offset+4]); + add_item_to_tree(ipx_tree, offset+5, 1, "Packet Type: %s", + ipx_packet_type(ipx_type)); + add_item_to_tree(ipx_tree, offset+6, 4, "Destination Network: %s", + dnet); + add_item_to_tree(ipx_tree, offset+10, 6, "Destination Node: %s", + ether_to_str((guint8*)&pd[offset+10])); + /*dsocket = ntohs(*((guint16*)&pd[offset+16]));*/ + add_item_to_tree(ipx_tree, offset+16, 2, + "Destination Socket: %s (0x%04X)", port_text(dsocket), dsocket); + add_item_to_tree(ipx_tree, offset+18, 4, "Source Network: %s", + snet); + add_item_to_tree(ipx_tree, offset+22, 6, "Source Node: %s", + ether_to_str((guint8*)&pd[offset+22])); + ssocket = pntohs(&pd[offset+28]); + add_item_to_tree(ipx_tree, offset+28, 2, + "Source Socket: %s (0x%04X)", port_text(ssocket), ssocket); + } + offset += 30; + + switch (ipx_type) { + case 0: /* IPX */ + dissect_data(pd, offset, fd, tree); /* the IPX payload */ + break; + case 5: /* SPX */ + dissect_spx(pd, offset, fd, tree); + break; + case 17: /* NCP */ + dissect_ncp(pd, offset, fd, tree); + break; + case 20: /* NetBIOS */ + dissect_data(pd, offset, fd, tree); /* until implemented */ + break; + default: + dissect_data(pd, offset, fd, tree); + break; + } +} + + +/* ================================================================= */ +/* SPX */ +/* ================================================================= */ +static char* +spx_conn_ctrl(u_char ctrl) +{ + int i=0; + + static struct conn_info conns[] = { + { 0x10, "End-of-Message" }, + { 0x20, "Attention" }, + { 0x40, "Acknowledgment Required"}, + { 0x80, "System Packet"} + }; + + while (conns[i].text != NULL) { + if (conns[i].ctrl == ctrl) { + return conns[i].text; + } + i++; + } + return "Unknown"; +} + +static char* +datastream(u_char type) +{ + switch (type) { + case 0xfe: + return "End-of-Connection"; + case 0xff: + return "End-of-Connection Acknowledgment"; + default: + return "Client-Defined"; + } +} + +static void +dissect_spx(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + + GtkWidget *spx_tree, *ti; + + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "SPX"); + strcpy(fd->win_info[4], "SPX"); + } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, 12, + "Sequenced Packet Exchange"); + spx_tree = gtk_tree_new(); + add_subtree(ti, spx_tree, ETT_SPX); + + add_item_to_tree(spx_tree, offset, 1, + "Connection Control: %s (0x%02X)", + spx_conn_ctrl(pd[offset]), pd[offset]); + + add_item_to_tree(spx_tree, offset+1, 1, + "Datastream Type: %s (0x%02X)", + datastream(pd[offset+1]), pd[offset+1]); + + add_item_to_tree(spx_tree, offset+2, 2, + "Source Connection ID: %d", pntohs( &pd[offset+2] ) ); + + add_item_to_tree(spx_tree, offset+4, 2, + "Destination Connection ID: %d", pntohs( &pd[offset+4] ) ); + + add_item_to_tree(spx_tree, offset+6, 2, + "Sequence Number: %d", pntohs( &pd[offset+6] ) ); + + add_item_to_tree(spx_tree, offset+8, 2, + "Acknowledgment Number: %d", pntohs( &pd[offset+8] ) ); + + add_item_to_tree(spx_tree, offset+10, 2, + "Allocation Number: %d", pntohs( &pd[offset+10] ) ); + + offset += 12; + dissect_data(pd, offset, fd, tree); + } +} + +/* ================================================================= */ +/* NCP */ +/* ================================================================= */ +static char* +req_text(u_short req) { + int i=0; + + static struct req_info reqs[] = { + { 0x1111, "Create a service connection" }, + { 0x2222, "Service request" }, + { 0x3333, "Service reply" }, + { 0x5555, "Destroy service connection" }, + { 0x7777, "Burst mode transfer" }, + { 0x9999, "Request being processed" }, + { 0x0000, NULL } + }; + + while (reqs[i].text != NULL) { + if (reqs[i].req == req) { + return reqs[i].text; + } + i++; + } + return "Unknown"; +} + +static char* +ncp2222_func(u_short func) { + int i=0; + + static struct req_info ncp[] = { + { 17, "Print and Queue Services" }, + { 21, "Message Services" }, + { 22, "File and Directory Services" }, + { 23, "Binding and Rights Services" }, + { 34, "Transaction Tacking Services" }, + { 35, "Apple File Services" }, + { 86, "Extended Attributes Services" }, + { 87, "File and Directory Services" }, + { 88, "Auditing Services" }, + { 104, "Netware Directory Services" }, + { 123, "Netware 4.x Statistical Information Services" }, + { 0, NULL } + }; + + while (ncp[i].text != NULL) { + if (ncp[i].req == func) { + return ncp[i].text; + } + i++; + } + return "Unknown"; +} + +static char* +ncp2222_subfunc(u_short func, u_short subfunc) { + int i=0; + struct req_info *info_ptr = NULL; + + /* Accounting Services */ + static struct req_info ncp_23[] = { + { 150, "Get Current Account Status" }, + { 151, "Submit Account Charge" }, + { 152, "Submit Account Hold" }, + { 153, "Submit Account Note" }, + { 0, NULL } + }; + + /* Apple File Services */ + static struct req_info ncp_35[] = { + { 1, "AFP Create Directory" }, + { 2, "AFP Create File" }, + { 3, "AFP Delete" }, + { 4, "AFP Get Entry ID from Name" }, + { 5, "AFP Get File Information" }, + { 6, "AFP Get Entry ID From NetWare Handle" }, + { 7, "AFP Rename" }, + { 8, "AFP Open File Fork" }, + { 9, "AFP Set File Information" }, + { 10, "AFP Scan File Information" }, + { 11, "AFP 2.0 Alloc Temporary Directory Handle" }, + { 12, "AFP Get Entry ID from Name Path" }, + { 13, "AFP 2.0 Create Directory" }, + { 14, "AFP 2.0 Create File" }, +/* ??? { 15, "AFP 2.0 Delete File" }, just guessing */ + { 16, "AFP 2.0 Set File Information" }, + { 17, "AFP 2.0 Scan File Information" }, + { 18, "AFP Get DOS Name from Entry ID" }, + { 19, "AFP Get Macintosh Info on Deleted File" }, + { 0, NULL } + }; + + /* Auditing Services */ + static struct req_info ncp_88[] = { + { 1, "Query Volume Audit Status" }, + { 2, "Add Audit Property" }, + { 3, "Add Auditor Access" }, + + { 0, NULL } + }; + + switch (func) { + case 23: + info_ptr = ncp_23; + break; + case 35: + info_ptr = ncp_35; + break; + case 88: + info_ptr = ncp_88; + break; + default: + return "Unkown function"; + } + + + while (info_ptr[i].text != NULL) { + if (info_ptr[i].req == subfunc) { + printf("subfunc=%s\n", info_ptr[i].text); + return info_ptr[i].text; + } + i++; + } + return "Unknown"; +} + + +static void +dissect_ncp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + + GtkWidget *ncp_tree, *ti; + guint16 ncp_type; + int ncp_hdr; + + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "NCP"); + strcpy(fd->win_info[4], "NCP"); + } + + ncp_type = pntohs(&pd[offset]); + + if (ncp_type == 0x1111 || ncp_type == 0x2222 || ncp_type == 0x5555 || + ncp_type == 0x7777) { + ncp_hdr = 6; + } + else if (ncp_type == 0x3333 || ncp_type == 0x9999) { + ncp_hdr = 8; + } + else { + ncp_hdr = 1; /* ? */ + } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, ncp_hdr, + "NetWare Core Protocol"); + ncp_tree = gtk_tree_new(); + add_subtree(ti, ncp_tree, ETT_NCP); + + add_item_to_tree(ncp_tree, offset, 2, + "Type: %s", req_text( pntohs( &pd[offset] ) ) ); + + add_item_to_tree(ncp_tree, offset+2, 1, + "Sequence Number: %d", pd[offset+2]); + + add_item_to_tree(ncp_tree, offset+3, 1, + "Connection Number Low: %d", pd[offset+3]); + + add_item_to_tree(ncp_tree, offset+4, 1, + "Task Number: %d", pd[offset+4]); + + add_item_to_tree(ncp_tree, offset+5, 1, + "Connection Number High: %d", pd[offset+5]); + + if (ncp_hdr == 8) { + add_item_to_tree(ncp_tree, offset+6, 1, + "Completion Code: %d", pd[offset+6]); + + add_item_to_tree(ncp_tree, offset+7, 1, + "Connection Status: %d", pd[offset+7]); + } + + offset += ncp_hdr; + + if (ncp_type == 0x2222) { + /* my offset is different now */ + add_item_to_tree(ncp_tree, offset, 1, + "Function Code: %s (%d)", + ncp2222_func(pd[offset]), pd[offset]); + + add_item_to_tree(ncp_tree, offset+2, 1, + "Subfunction Code: %s (%d)", + ncp2222_subfunc(pd[offset], pd[offset+2]), pd[offset+2]); + + offset += 3; + } + + dissect_data(pd, offset, fd, tree); + } +} diff --git a/packet-llc.c b/packet-llc.c new file mode 100644 index 0000000000..2385cda7b6 --- /dev/null +++ b/packet-llc.c @@ -0,0 +1,163 @@ +/* packet-llc.c + * Routines for IEEE 802.2 LLC layer + * Gilbert Ramirez + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include + +#include + +#include "packet.h" +#include "ethereal.h" +#include "etypes.h" + +struct sap_info { + u_char sap; + char *text; +}; + +static char* +sap_text(u_char sap) { + int i=0; + + static struct sap_info saps[] = { + { 0x00, "NULL LSAP" }, + { 0x02, "LLC Sub-Layer Management Individual" }, + { 0x03, "LLC Sub-Layer Management Group" }, + { 0x04, "SNA Path Control Individual" }, + { 0x05, "SNA Path Control Group" }, + { 0x06, "TCP/IP" }, + { 0x08, "SNA" }, + { 0x0C, "SNA" }, + { 0x42, "Spanning Tree BPDU" }, + { 0x7F, "ISO 802.2" }, + { 0x80, "XNS" }, + { 0xAA, "SNAP" }, + { 0xBA, "Banyan Vines" }, + { 0xBC, "Banyan Vines" }, + { 0xE0, "NetWare" }, + { 0xF0, "NetBIOS" }, + { 0xF4, "IBM Net Management Individual" }, + { 0xF5, "IBM Net Management Group" }, + { 0xF8, "Remote Program Load" }, + { 0xFC, "Remote Program Load" }, + { 0xFE, "ISO Network Layer" }, + { 0xFF, "Global LSAP" }, + { 0x00, NULL } + }; + + while (saps[i].text != NULL) { + if (saps[i].sap == sap) { + return saps[i].text; + } + i++; + } + return "Unknown"; +} + +static char* +llc_org(const u_char *ptr) { + + unsigned long org = (ptr[0] << 16) | (ptr[1] << 8) | ptr[2]; + char *llc_org[1] = { + "Encapsulated Ethernet"}; + + if (org > 0) { + return "Unknown"; + } + else { + return llc_org[org]; + } +} + +void +dissect_llc(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + + GtkWidget *llc_tree, *ti; + guint16 etype; + int is_snap; + + /* LLC Strings */ + char *llc_ctrl[4] = { + "Information Transfer", "Supervisory", + "", "Unnumbered Information" }; + + is_snap = (pd[offset] == 0xAA) && (pd[offset+1] == 0xAA); + + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "LLC"); + } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, (is_snap ? 8 : 3), + "Logical-Link Control"); + llc_tree = gtk_tree_new(); + add_subtree(ti, llc_tree, ETT_LLC); + add_item_to_tree(llc_tree, offset, 1, "DSAP: %s (0x%02X)", + sap_text(pd[offset]), pd[offset]); + add_item_to_tree(llc_tree, offset+1, 1, "SSAP: %s (0x%02X)", + sap_text(pd[offset+1]), pd[offset+1]); + add_item_to_tree(llc_tree, offset+2, 1, "Control: %s", + llc_ctrl[pd[offset+2] & 3]); + } + + if (is_snap) { + if (fd->win_info[0]) { + strcpy(fd->win_info[4], "802.2 LLC (SNAP)"); + } + if (tree) { + add_item_to_tree(llc_tree, offset+3, 3, + "Organization Code: %s (%02X-%02X-%02X)", + llc_org(&pd[offset+3]), + pd[offset+3], pd[offset+4], pd[offset+5]); + } + etype = (pd[offset+6] << 8) | pd[offset+7]; + offset += 8; + ethertype(etype, offset, pd, fd, tree, llc_tree); + } + else { + if (fd->win_info[0]) { + sprintf(fd->win_info[4], "802.2 LLC (%s)", sap_text(pd[offset])); + } + + /* non-SNAP */ + offset += 3; + + switch (pd[offset-3]) { + case 0x06: /* TCP/IP */ + dissect_ip(pd, offset, fd, tree); + break; + case 0xe0: /* NetWare (IPX) */ + dissect_ipx(pd, offset, fd, tree); + break; + default: + dissect_data(pd, offset, fd, tree); + break; + } + } +} diff --git a/packet-lpd.c b/packet-lpd.c new file mode 100644 index 0000000000..0cc52128e6 --- /dev/null +++ b/packet-lpd.c @@ -0,0 +1,154 @@ +/* packet-lpr.c + * Routines for LPR and LPRng packet disassembly + * Gilbert Ramirez + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#include "packet.h" +#include "ethereal.h" +#include "etypes.h" + +enum lpr_type { request, response }; + +void +dissect_lpd(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) +{ + GtkWidget *lpd_tree, *ti; + enum lpr_type lpr_packet_type; + char *newline, *printer, *line_pos; + int substr_len, curr_offset; + + /* This information comes from the LPRng HOWTO, which also describes + RFC 1179. http://www.astart.com/lprng/LPRng-HOWTO.html */ + char *lpd_client_code[] = { + "Unknown command", + "LPC: start print", + "LPR: transfer a printer job", + "LPQ: print short form of queue status", + "LPQ: print long form of queue status", + "LPRM: remove jobs", + "LPRng lpc: do control operation", + "LPRng lpr: transfer a block format print job", + "LPRng lpc: secure command transfer", + "LPRng lpq: verbose status information" + }; + char *lpd_server_code[] = { + "Success: accepted, proceed", + "Queue not accepting jobs", + "Queue temporarily full, retry later", + "Bad job format, do not retry" + }; + + + if (pd[offset+1] == '\n') { + lpr_packet_type = response; + } + else if (pd[offset] <= 9) { + lpr_packet_type = request; + } + else { + lpr_packet_type = response; + } + + + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "LPD"); + if (lpr_packet_type == request) { + strcpy(fd->win_info[4], lpd_client_code[pd[offset]]); + } + else { + strcpy(fd->win_info[4], "LPD response"); + } + } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, fd->cap_len - offset, + "Line Printer Daemon Protocol"); + lpd_tree = gtk_tree_new(); + add_subtree(ti, lpd_tree, ETT_LPD); + + if (lpr_packet_type == request) { + if (pd[offset] <= 9) { + add_item_to_tree(lpd_tree, offset, 1, + lpd_client_code[pd[offset]]); + } + else { + add_item_to_tree(lpd_tree, offset, 1, + lpd_client_code[0]); + } + printer = strdup(&pd[offset+1]); + + /* get rid of the new-line so that the tree prints out nicely */ + if (printer[fd->cap_len - offset - 2] == 0x0a) { + printer[fd->cap_len - offset - 2] = 0; + } + add_item_to_tree(lpd_tree, offset+1, fd->cap_len - (offset+1), + /*"Printer/options: %s", &pd[offset+1]);*/ + "Printer/options: %s", printer); + free(printer); + } + else { + if (pd[offset] <= 3) { + add_item_to_tree(lpd_tree, offset, 2, "Response: %s", + lpd_server_code[pd[offset]]); + } + else { + printer = strdup(&pd[offset]); + line_pos = printer; + curr_offset = offset; + while (fd->cap_len > curr_offset) { + newline = strchr(line_pos, '\n'); + if (!newline) { + add_item_to_tree(lpd_tree, curr_offset, + fd->cap_len - offset, "Text: %s", line_pos); + break; + } + *newline = 0; + substr_len = strlen(line_pos); + add_item_to_tree(lpd_tree, curr_offset, substr_len + 1, + "Text: %s", line_pos); + curr_offset += substr_len + 1; + line_pos = newline + 1; + } + } + } + } +} + diff --git a/packet-ospf.c b/packet-ospf.c new file mode 100644 index 0000000000..46529dc95e --- /dev/null +++ b/packet-ospf.c @@ -0,0 +1,550 @@ +/* packet-ospf.c + * Routines for OSPF packet disassembly + * (c) Copyright Hannes R. Boehm + * + * At this time, this module is able to analyze OSPF + * packets as specified in RFC2328. MOSPF (RFC1584) and other + * OSPF Extensions which introduce new Packet types + * (e.g the External Atributes LSA) are not supported. + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include "ethereal.h" +#include "packet.h" +#include "packet-ospf.h" + + +void +dissect_ospf(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + e_ospfhdr *ospfh; + + GtkWidget *ospf_tree = NULL, *ti; + GtkWidget *ospf_header_tree; + char auth_data[9]=""; + char *packet_type; + + ospfh = (e_ospfhdr *) &pd[offset]; + + switch(ospfh->packet_type) { + case OSPF_HELLO: + packet_type="Hello Packet"; + break; + case OSPF_DB_DESC: + packet_type="DB Descr."; + break; + case OSPF_LS_REQ: + packet_type="LS Request"; + break; + case OSPF_LS_UPD: + packet_type="LS Update"; + break; + case OSPF_LS_ACK: + packet_type="LS Acknowledge"; + break; + default: + } + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "OSPF"); + sprintf(fd->win_info[4], "%s", packet_type); + } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, ntohs(ospfh->length), "Open Shortest Path First"); + ospf_tree = gtk_tree_new(); + add_subtree(ti, ospf_tree, ETT_OSPF); + + ti = add_item_to_tree(GTK_WIDGET(ospf_tree), offset, OSPF_HEADER_LENGTH, "OSPF Header"); + ospf_header_tree = gtk_tree_new(); + add_subtree(ti, ospf_header_tree, ETT_OSPF_HDR); + + add_item_to_tree(ospf_header_tree, offset, 1, "OSPF Version: %d", ospfh->version); + add_item_to_tree(ospf_header_tree, offset + 1 , 1, "OSPF Packet Type: %d (%s)", + ospfh->packet_type, packet_type); + add_item_to_tree(ospf_header_tree, offset + 2 , 2, "Packet Legth: %d", + ntohs(ospfh->length)); + add_item_to_tree(ospf_header_tree, offset + 4 , 4, "Source OSPF Router ID: %s", + + ip_to_str((guint8 *) &(ospfh->routerid))); + if (!(ospfh->area)) { + add_item_to_tree(ospf_header_tree, offset + 8 , 4, "Area ID: Backbone"); + } else { + add_item_to_tree(ospf_header_tree, offset + 8 , 4, "Area ID: %s", ip_to_str((guint8 *) &(ospfh->area))); + } + add_item_to_tree(ospf_header_tree, offset + 12 , 2, "Packet Checksum"); + switch( ntohs(ospfh->auth_type) ) { + case OSPF_AUTH_NONE: + add_item_to_tree(ospf_header_tree, offset + 14 , 2, "Auth Type: none"); + add_item_to_tree(ospf_header_tree, offset + 16 , 8, "Auth Data (none)"); + break; + case OSPF_AUTH_SIMPLE: + add_item_to_tree(ospf_header_tree, offset + 14 , 2, "Auth Type: simple"); + strncpy(auth_data, &(ospfh->auth_data), 8); + add_item_to_tree(ospf_header_tree, offset + 16 , 8, "Auth Data: %s", auth_data); + break; + case OSPF_AUTH_CRYPT: + add_item_to_tree(ospf_header_tree, offset + 14 , 2, "Auth Type: crypt"); + add_item_to_tree(ospf_header_tree, offset + 16 , 8, "Auth Data (crypt)"); + break; + default: + add_item_to_tree(ospf_header_tree, offset + 14 , 2, "Auth Type (unknown)"); + add_item_to_tree(ospf_header_tree, offset + 16 , 8, "Auth Data (unknown)"); + } + + } + + /* Skip over header */ + offset += OSPF_HEADER_LENGTH; + switch(ospfh->packet_type){ + case OSPF_HELLO: + dissect_ospf_hello(pd, offset, fd, (GtkTree *) ospf_tree); + break; + case OSPF_DB_DESC: + dissect_ospf_db_desc(pd, offset, fd, (GtkTree *) ospf_tree); + break; + case OSPF_LS_REQ: + dissect_ospf_ls_req(pd, offset, fd, (GtkTree *) ospf_tree); + break; + case OSPF_LS_UPD: + dissect_ospf_ls_upd(pd, offset, fd, (GtkTree *) ospf_tree); + break; + case OSPF_LS_ACK: + dissect_ospf_ls_ack(pd, offset, fd, (GtkTree *) ospf_tree); + break; + default: + dissect_data(pd, offset, fd, tree); + } +} + +void +dissect_ospf_hello(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + e_ospf_hello *ospfhello; + guint32 *ospfneighbor; + char options[20]=""; + int options_offset; + + GtkWidget *ospf_hello_tree, *ti; + + ospfhello = (e_ospf_hello *) &pd[offset]; + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, (fd->cap_len - offset) , "OSPF Hello Packet"); + ospf_hello_tree = gtk_tree_new(); + add_subtree(ti, ospf_hello_tree, ETT_OSPF_HELLO); + + + add_item_to_tree(ospf_hello_tree, offset , 4, "Network Mask: %s", ip_to_str((guint8 *) &ospfhello->network_mask)); + add_item_to_tree(ospf_hello_tree, offset + 4, 2, "Hello Intervall: %d seconds", ntohs(ospfhello->hellointervall)); + + /* ATTENTION !!! no check for length of options string */ + options_offset=0; + if(( ospfhello->options & OSPF_OPTIONS_E ) == OSPF_OPTIONS_E){ + strcpy( (char *)(options + options_offset), "E"); + options_offset+=1; + } + if(( ospfhello->options & OSPF_OPTIONS_MC ) == OSPF_OPTIONS_MC){ + strcpy((char *) (options + options_offset), "/MC"); + options_offset+=3; + } + if(( ospfhello->options & OSPF_OPTIONS_NP ) == OSPF_OPTIONS_NP){ + strcpy((char *) (options + options_offset), "/NP"); + options_offset+=3; + } + if(( ospfhello->options & OSPF_OPTIONS_EA ) == OSPF_OPTIONS_EA){ + strcpy((char *) (options + options_offset) , "/EA"); + options_offset+=3; + } + if(( ospfhello->options & OSPF_OPTIONS_DC ) == OSPF_OPTIONS_DC){ + strcpy((char *) (options + options_offset) , "/DC"); + options_offset+=3; + } + + add_item_to_tree(ospf_hello_tree, offset + 6, 1, "Options: %d (%s)", ospfhello->options, options); + add_item_to_tree(ospf_hello_tree, offset + 7, 1, "Router Priority: %d", ospfhello->priority); + add_item_to_tree(ospf_hello_tree, offset + 8, 4, "RouterDeadIntervall: %d seconds", ntohl(ospfhello->dead_interval)); + add_item_to_tree(ospf_hello_tree, offset + 12, 4, "Designated Router: %s", ip_to_str((guint8 *) &ospfhello->drouter)); + add_item_to_tree(ospf_hello_tree, offset + 16, 4, "Backup Designated Router: %s", ip_to_str((guint8 *) &ospfhello->bdrouter)); + + + offset+=20; + while(((int)(fd->cap_len - offset)) >= 4){ + printf("%d", fd->cap_len - offset); + ospfneighbor=(guint32 *) &pd[offset]; + add_item_to_tree(ospf_hello_tree, offset, 4, "Active Neighbor: %s", ip_to_str((guint8 *) ospfneighbor)); + offset+=4; + } + } +} + +void +dissect_ospf_db_desc(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + e_ospf_dbd *ospf_dbd; + char options[20]=""; + int options_offset; + char flags[20]=""; + int flags_offset; + + GtkWidget *ospf_db_desc_tree=NULL, *ti; + + ospf_dbd = (e_ospf_dbd *) &pd[offset]; + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, (fd->cap_len - offset) , "OSPF DB Description"); + ospf_db_desc_tree = gtk_tree_new(); + add_subtree(ti, ospf_db_desc_tree, ETT_OSPF_DESC); + + add_item_to_tree(ospf_db_desc_tree, offset, 2, "Interface MTU: %d", ntohs(ospf_dbd->interface_mtu) ); + + + options_offset=0; + if(( ospf_dbd->options & OSPF_OPTIONS_E ) == OSPF_OPTIONS_E){ + strcpy( (char *)(options + options_offset), "_E_"); + options_offset+=1; + } + if(( ospf_dbd->options & OSPF_OPTIONS_MC ) == OSPF_OPTIONS_MC){ + strcpy((char *) (options + options_offset), "_MC_"); + options_offset+=3; + } + if(( ospf_dbd->options & OSPF_OPTIONS_NP ) == OSPF_OPTIONS_NP){ + strcpy((char *) (options + options_offset), "_NP_"); + options_offset+=3; + } + if(( ospf_dbd->options & OSPF_OPTIONS_EA ) == OSPF_OPTIONS_EA){ + strcpy((char *) (options + options_offset) , "_EA_"); + options_offset+=3; + } + if(( ospf_dbd->options & OSPF_OPTIONS_DC ) == OSPF_OPTIONS_DC){ + strcpy((char *) (options + options_offset) , "_DC_"); + options_offset+=3; + } + + add_item_to_tree(ospf_db_desc_tree, offset + 2 , 1, "Options: %d (%s)", ospf_dbd->options, options ); + + + flags_offset=0; + if(( ospf_dbd->flags & OSPF_DBD_FLAG_MS ) == OSPF_DBD_FLAG_MS){ + strcpy( (char *)(flags + flags_offset), "_I_"); + flags_offset+=1; + } + if(( ospf_dbd->flags & OSPF_DBD_FLAG_M ) == OSPF_DBD_FLAG_M){ + strcpy((char *) (flags + flags_offset), "_M_"); + flags_offset+=3; + } + if(( ospf_dbd->flags & OSPF_DBD_FLAG_I ) == OSPF_DBD_FLAG_I){ + strcpy((char *) (flags + flags_offset), "_I_"); + flags_offset+=3; + } + + add_item_to_tree(ospf_db_desc_tree, offset + 3 , 1, "Flags: %d (%s)", ospf_dbd->flags, flags ); + add_item_to_tree(ospf_db_desc_tree, offset + 4 , 4, "DD Sequence: %d", ntohl(ospf_dbd->dd_sequence) ); + } + /* LS Headers will be processed here */ + /* skip to the end of DB-Desc header */ + offset+=8; + while( ((int) (fd->cap_len - offset)) >= OSPF_LSA_HEADER_LENGTH ) { + dissect_ospf_lsa(pd, offset, fd, (GtkTree *) tree, FALSE); + offset+=OSPF_LSA_HEADER_LENGTH; + } +} + +void +dissect_ospf_ls_req(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + e_ospf_ls_req *ospf_lsr; + + GtkWidget *ospf_lsr_tree, *ti; + + + /* zero or more LS requests may be within a LS Request */ + /* we place every request for a LSA in a single subtree */ + if (tree) { + while( ((int) ( fd->cap_len - offset)) >= OSPF_LS_REQ_LENGTH ){ + ospf_lsr = (e_ospf_ls_req *) &pd[offset]; + ti = add_item_to_tree(GTK_WIDGET(tree), offset, OSPF_LS_REQ_LENGTH, "Link State Request"); + ospf_lsr_tree = gtk_tree_new(); + add_subtree(ti, ospf_lsr_tree, ETT_OSPF_LSR); + + switch( ntohl( ospf_lsr->ls_type ) ){ + case OSPF_LSTYPE_ROUTER: + add_item_to_tree(ospf_lsr_tree, offset, 4, "LS Type: Router-LSA (%d)", + ntohl( ospf_lsr->ls_type ) ); + break; + case OSPF_LSTYPE_NETWORK: + add_item_to_tree(ospf_lsr_tree, offset, 4, "LS Type: Network-LSA (%d)", + ntohl( ospf_lsr->ls_type ) ); + break; + case OSPF_LSTYPE_SUMMERY: + add_item_to_tree(ospf_lsr_tree, offset, 4, "LS Type: Summary-LSA (IP network) (%d)", + ntohl( ospf_lsr->ls_type ) ); + break; + case OSPF_LSTYPE_ASBR: + add_item_to_tree(ospf_lsr_tree, offset, 4, "LS Type: Summary-LSA (ASBR) (%d)", + ntohl( ospf_lsr->ls_type ) ); + break; + case OSPF_LSTYPE_ASEXT: + add_item_to_tree(ospf_lsr_tree, offset, 4, "LS Type: AS-External-LSA (ASBR) (%d)", + ntohl( ospf_lsr->ls_type ) ); + break; + default: + add_item_to_tree(ospf_lsr_tree, offset, 4, "LS Type: %d (unknown)", + ntohl( ospf_lsr->ls_type ) ); + } + + add_item_to_tree(ospf_lsr_tree, offset + 4, 4, "Link State ID : %s", + ip_to_str((guint8 *) &(ospf_lsr->ls_id))); + add_item_to_tree(ospf_lsr_tree, offset + 8, 4, "Advertising Router : %s", + ip_to_str((guint8 *) &(ospf_lsr->adv_router))); + + offset+=12; + } + } +} +void +dissect_ospf_ls_upd(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + e_ospf_lsa_upd_hdr *upd_hdr; + guint32 lsa_counter; + + GtkWidget *ospf_lsa_upd_tree=NULL, *ti; + + upd_hdr = (e_ospf_lsa_upd_hdr *) &pd[offset]; + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, (fd->cap_len - offset) , "LS Update Packet"); + ospf_lsa_upd_tree = gtk_tree_new(); + add_subtree(ti, ospf_lsa_upd_tree, ETT_OSPF_LSA_UPD); + + add_item_to_tree(ospf_lsa_upd_tree, offset, 4, "Nr oF LSAs: %d", ntohl(upd_hdr->lsa_nr) ); + } + /* skip to the beginning of the first LSA */ + offset+=4; /* the LS Upd PAcket contains only a 32 bit #LSAs field */ + + lsa_counter = 0; + while(lsa_counter < ntohl(upd_hdr->lsa_nr)){ + offset+=dissect_ospf_lsa(pd, offset, fd, (GtkTree *) ospf_lsa_upd_tree, TRUE); + lsa_counter += 1; + } +} + +void +dissect_ospf_ls_ack(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + + /* the body of a LS Ack packet simply contains zero or more LSA Headers */ + while( ((int)(fd->cap_len - offset)) >= OSPF_LSA_HEADER_LENGTH ) { + dissect_ospf_lsa(pd, offset, fd, (GtkTree *) tree, FALSE); + offset+=OSPF_LSA_HEADER_LENGTH; + } + +} + +int +dissect_ospf_lsa(const u_char *pd, int offset, frame_data *fd, GtkTree *tree, int disassemble_body) { + e_ospf_lsa_hdr *lsa_hdr; + char *lsa_type; + + /* data strutures for the router LSA */ + e_ospf_router_lsa *router_lsa; + e_ospf_router_data *router_data; + e_ospf_router_metric *tos_data; + guint16 link_counter; + guint8 tos_counter; + char *link_type; + char *link_id; + + /* data structures for the network lsa */ + e_ospf_network_lsa *network_lsa; + guint32 *attached_router; + + /* data structures for the summary and ASBR LSAs */ + e_ospf_summary_lsa *summary_lsa; + guint8 *tos; + guint16 *tos_metric; + + + + GtkWidget *ospf_lsa_tree, *ti; + + lsa_hdr = (e_ospf_lsa_hdr *) &pd[offset]; + + + switch(lsa_hdr->ls_type) { + case OSPF_LSTYPE_ROUTER: + lsa_type="Router LSA"; + break; + case OSPF_LSTYPE_NETWORK: + lsa_type="Network LSA"; + break; + case OSPF_LSTYPE_SUMMERY: + lsa_type="Summery LSA"; + break; + case OSPF_LSTYPE_ASBR: + lsa_type="ASBR LSA"; + break; + case OSPF_LSTYPE_ASEXT: + lsa_type="AS-external-LSA"; + break; + default: + lsa_type="unknown"; + } + + if (tree) { + if(disassemble_body){ + ti = add_item_to_tree(GTK_WIDGET(tree), offset, ntohs(lsa_hdr->length), + "%s (Type: %d)", lsa_type, lsa_hdr->ls_type); + } else { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, OSPF_LSA_HEADER_LENGTH, "LSA Header"); + } + ospf_lsa_tree = gtk_tree_new(); + add_subtree(ti, ospf_lsa_tree, ETT_OSPF_LSA); + + + add_item_to_tree(ospf_lsa_tree, offset, 2, "LS Age: %d seconds", ntohs(lsa_hdr->ls_age)); + add_item_to_tree(ospf_lsa_tree, offset + 2, 1, "Options: %d ", lsa_hdr->options); + add_item_to_tree(ospf_lsa_tree, offset + 3, 1, "LSA Type: %d (%s)", lsa_hdr->ls_type, lsa_type); + + add_item_to_tree(ospf_lsa_tree, offset + 4, 4, "Linke State ID: %s ", + ip_to_str((guint8 *) &(lsa_hdr->ls_id))); + + add_item_to_tree(ospf_lsa_tree, offset + 8, 4, "Advertising Router: %s ", + ip_to_str((guint8 *) &(lsa_hdr->adv_router))); + add_item_to_tree(ospf_lsa_tree, offset + 12, 4, "LS Sequence Number: 0x%04x ", + ntohl(lsa_hdr->ls_seq)); + add_item_to_tree(ospf_lsa_tree, offset + 16, 2, "LS Checksum: %d ", ntohs(lsa_hdr->ls_checksum)); + + add_item_to_tree(ospf_lsa_tree, offset + 18, 2, "Length: %d ", ntohs(lsa_hdr->length)); + + if(!disassemble_body){ + return OSPF_LSA_HEADER_LENGTH; + } + + /* the LSA body starts afte 20 bytes of LSA Header */ + offset+=20; + + switch(lsa_hdr->ls_type){ + case(OSPF_LSTYPE_ROUTER): + router_lsa = (e_ospf_router_lsa *) &pd[offset]; + + /* again: flags should be secified in detail */ + add_item_to_tree(ospf_lsa_tree, offset, 1, "Flags: 0x%02x ", router_lsa->flags); + add_item_to_tree(ospf_lsa_tree, offset + 2, 2, "Nr. of Links: %d ", + ntohs(router_lsa->nr_links)); + offset += 4; + /* router_lsa->nr_links links follow + * maybe we should put each of the links into its own subtree ??? + */ + for(link_counter = 1 ; link_counter <= ntohs(router_lsa->nr_links); link_counter++){ + + router_data = (e_ospf_router_data *) &pd[offset]; + /* check the Link Type and ID */ + switch(router_data->link_type) { + case OSPF_LINK_PTP: + link_type="Point-to-point connection to another router"; + link_id="Neighboring router's Router ID"; + break; + case OSPF_LINK_TRANSIT: + link_type="Connection to a transit network"; + link_id="IP address of Designated Router"; + break; + case OSPF_LINK_STUB: + link_type="Connection to a stub network"; + link_id="IP network/subnet number"; + break; + case OSPF_LINK_VIRTUAL: + link_type="Virtual link"; + link_id="Neighboring router's Router ID"; + break; + default: + link_type="unknown link type"; + link_id="unknown link id"; + } + + add_item_to_tree(ospf_lsa_tree, offset, 4, "%s: %s", link_id, + ip_to_str((guint8 *) &(router_data->link_id))); + + /* link_data should be specified in detail (e.g. network mask) (depends on link type)*/ + add_item_to_tree(ospf_lsa_tree, offset + 4, 4, "Link Data: %s", + ip_to_str((guint8 *) &(router_data->link_data))); + + add_item_to_tree(ospf_lsa_tree, offset + 8, 1, "Link Type: %d - %s", + router_data->link_type, link_type); + add_item_to_tree(ospf_lsa_tree, offset + 9, 1, "Nr. of TOS metrics: %d", router_data->nr_tos); + add_item_to_tree(ospf_lsa_tree, offset + 10, 2, "TOS 0 metric: %d", ntohs( router_data->tos0_metric )); + + offset += 12; + + /* router_data->nr_tos metrics may follow each link + * ATTENTION: TOS metrics are not tested (I don't have TOS based routing) + * please send me a mail if it is/isn't working + */ + + for(tos_counter = 1 ; link_counter <= ntohs(router_data->nr_tos); tos_counter++){ + tos_data = (e_ospf_router_metric *) &pd[offset]; + add_item_to_tree(ospf_lsa_tree, offset, 1, "TOS: %d, Metric: %d", + tos_data->tos, ntohs(tos_data->metric)); + offset += 4; + } + } + break; + case(OSPF_LSTYPE_NETWORK): + network_lsa = (e_ospf_network_lsa *) &pd[offset]; + add_item_to_tree(ospf_lsa_tree, offset, 4, "Netmask: %s", + ip_to_str((guint8 *) &(network_lsa->network_mask))); + offset += 4; + + while( ((int) (fd->cap_len - offset)) >= 4){ + attached_router = (guint32 *) &pd[offset]; + add_item_to_tree(ospf_lsa_tree, offset, 4, "Attached Router: %s", + ip_to_str((guint8 *) attached_router)); + offset += 4; + } + break; + case(OSPF_LSTYPE_SUMMERY): + /* Type 3 and 4 LSAs have the same format */ + case(OSPF_LSTYPE_ASBR): + summary_lsa = (e_ospf_summary_lsa *) &pd[offset]; + add_item_to_tree(ospf_lsa_tree, offset, 4, "Netmask: %s", + ip_to_str((guint8 *) &(summary_lsa->network_mask))); + break; + case(OSPF_LSTYPE_ASEXT): + /* not yet implemented */ + add_item_to_tree(ospf_lsa_tree, offset, (fd->cap_len - offset), "AS-external-LSA not yet implemented"); + break; + default: + /* unknown LSA type */ + add_item_to_tree(ospf_lsa_tree, offset, (fd->cap_len - offset), "Unknown LSA Type"); + } + } + /* return the length of this LSA */ + return ntohs(lsa_hdr->length); +} diff --git a/packet-ospf.h b/packet-ospf.h new file mode 100644 index 0000000000..8e3b6af377 --- /dev/null +++ b/packet-ospf.h @@ -0,0 +1,127 @@ +/* packet-ospf.h (c) 1998 Hannes Boehm */ + +#define OSPF_HEADER_LENGTH 24 + +#define OSPF_HELLO 1 +#define OSPF_DB_DESC 2 +#define OSPF_LS_REQ 3 +#define OSPF_LS_UPD 4 +#define OSPF_LS_ACK 5 + +#define OSPF_AUTH_NONE 0 +#define OSPF_AUTH_SIMPLE 1 +#define OSPF_AUTH_CRYPT 2 + +#define OSPF_OPTIONS_E 2 +#define OSPF_OPTIONS_MC 4 +#define OSPF_OPTIONS_NP 8 +#define OSPF_OPTIONS_EA 16 +#define OSPF_OPTIONS_DC 32 + +#define OSPF_DBD_FLAG_MS 1 +#define OSPF_DBD_FLAG_M 2 +#define OSPF_DBD_FLAG_I 4 + +#define OSPF_LS_REQ_LENGTH 12 + +#define OSPF_LSTYPE_ROUTER 1 +#define OSPF_LSTYPE_NETWORK 2 +#define OSPF_LSTYPE_SUMMERY 3 +#define OSPF_LSTYPE_ASBR 4 +#define OSPF_LSTYPE_ASEXT 5 + +#define OSPF_LINK_PTP 1 +#define OSPF_LINK_TRANSIT 2 +#define OSPF_LINK_STUB 3 +#define OSPF_LINK_VIRTUAL 4 + +#define OSPF_LSA_HEADER_LENGTH 20 + +typedef struct _e_ospfhdr { + guint8 version; + guint8 packet_type; + guint16 length; + guint32 routerid; + guint32 area; + guint16 checksum; + guint16 auth_type; + char auth_data[8]; +} e_ospfhdr; + +typedef struct _e_ospf_hello { + guint32 network_mask; + guint16 hellointervall; + guint8 options; + guint8 priority; + guint32 dead_interval; + guint32 drouter; + guint32 bdrouter; +} e_ospf_hello ; + +typedef struct _e_ospf_dbd { + guint16 interface_mtu; + guint8 options; + guint8 flags; + guint32 dd_sequence; +} e_ospf_dbd; + +typedef struct _e_ospf_ls_req { + guint32 ls_type; + guint32 ls_id; + guint32 adv_router; +} e_ospf_ls_req; + +typedef struct _e_ospf_lsa_hdr { + guint16 ls_age; + guint8 options; + guint8 ls_type; + guint32 ls_id; + guint32 adv_router; + guint32 ls_seq; + guint16 ls_checksum; + guint16 length; +} e_ospf_lsa_hdr; + +typedef struct _e_ospf_router_lsa { + guint8 flags; + guint8 empfty; + guint16 nr_links; +} e_ospf_router_lsa; + +typedef struct _e_ospf_router_data { + guint32 link_id; + guint32 link_data; + guint8 link_type; + guint8 nr_tos; + guint16 tos0_metric; +} e_ospf_router_data; + +typedef struct _e_ospf_router_metric { + guint8 tos; + guint8 empty; + guint16 metric; +} e_ospf_router_metric; + +typedef struct _e_ospf_network_lsa { + guint32 network_mask; +} e_ospf_network_lsa; + +typedef struct _e_ospf_lsa_upd_hdr { + guint32 lsa_nr; +} e_ospf_lsa_upd_hdr; + +typedef struct _e_ospf_summary_lsa { + guint32 network_mask; +} e_ospf_summary_lsa; + +void dissect_ospf_hello(const u_char*, int, frame_data*, GtkTree*); +void dissect_ospf_db_desc(const u_char*, int, frame_data*, GtkTree*); +void dissect_ospf_ls_req(const u_char*, int, frame_data*, GtkTree*); +void dissect_ospf_ls_upd(const u_char*, int, frame_data*, GtkTree*); +void dissect_ospf_ls_ack(const u_char*, int, frame_data*, GtkTree*); + +/* dissect_ospf_lsa returns the length of the LSA + * if disassemble_body is set to FALSE (e.g. in LSA ACK + * packets), the header length is returned + */ +int dissect_ospf_lsa(const u_char*, int, frame_data*, GtkTree*, int disassemble_body); diff --git a/packet-ppp.c b/packet-ppp.c new file mode 100644 index 0000000000..cce8fd677e --- /dev/null +++ b/packet-ppp.c @@ -0,0 +1,79 @@ +/* packet-ppp.c + * Routines for ppp packet disassembly + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * + * This file created and by Mike Hall + * Copyright 1998 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "packet.h" +#include "ethereal.h" + +void +dissect_ppp( const u_char *pd, frame_data *fd, GtkTree *tree ) { + e_ppphdr ph; + GtkWidget *ti, *fh_tree; + + guchar flag, addr, control; + guint protocol; + + ph.ppp_flag = pd[0]; + ph.ppp_addr = pd[1]; + ph.ppp_ctl = pd[2]; + ph.ppp_prot = pntohs(&pd[3]); + + /* load the top pane info. This should be overwritten by + the next protocol in the stack */ + if(fd->win_info[0]) { + strcpy(fd->win_info[1], "N/A" ); + strcpy(fd->win_info[2], "N/A" ); + strcpy(fd->win_info[4], "PPP" ); + } + + /* populate a tree in the second pane with the status of the link + layer (ie none) */ + if(tree) { + ti = add_item_to_tree( GTK_WIDGET(tree), 0, 5, + "Point-to-Point Protocol (%d on link, %d captured)", fd->pkt_len, + fd->cap_len ); + fh_tree = gtk_tree_new(); + add_subtree(ti, fh_tree, ETT_PPP); + add_item_to_tree(fh_tree, 0, 1, "Flag: %02x", ph.ppp_flag); + add_item_to_tree(fh_tree, 1, 1, "Address: %02x", ph.ppp_addr); + add_item_to_tree(fh_tree, 2, 1, "Control: %02x", ph.ppp_ctl); + add_item_to_tree(fh_tree, 3, 2, "Protocol: %04x", ph.ppp_prot); + } + + switch (ph.ppp_prot) { + case 0x0021: + dissect_ip(pd, 5, fd, tree); + break; + default: + dissect_data(pd, 5, fd, tree); + break; + } +} diff --git a/packet-raw.c b/packet-raw.c new file mode 100644 index 0000000000..d666bd8b62 --- /dev/null +++ b/packet-raw.c @@ -0,0 +1,72 @@ +/* packet-raw.c + * Routines for raw packet disassembly + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * + * This file created and by Mike Hall + * Copyright 1998 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "packet.h" +#include "ethereal.h" + +void +dissect_raw( const u_char *pd, frame_data *fd, GtkTree *tree ) { + GtkWidget *ti, *fh_tree; + + /* load the top pane info. This should be overwritten by + the next protocol in the stack */ + if(fd->win_info[0]) { + strcpy(fd->win_info[1], "N/A" ); + strcpy(fd->win_info[2], "N/A" ); + strcpy(fd->win_info[4], "Raw packet data" ); + } + + /* populate a tree in the second pane with the status of the link + layer (ie none) */ + if(tree) { + ti = add_item_to_tree( GTK_WIDGET(tree), 0, 0, + "Raw packet data (%d on link, %d captured)", + fd->pkt_len, fd->cap_len ); + fh_tree = gtk_tree_new(); + add_subtree(ti, fh_tree, ETT_RAW); + add_item_to_tree(fh_tree, 0, 0, "No link information available"); + } + + /* So far, the only time we get raw connection types are with Linux and + * Irix PPP connections. We can't tell what type of data is coming down + * the line, so our safest bet is IP. - GCC + */ + + /* Currently, the Linux 2.1.xxx PPP driver passes back some of the header + * sometimes. This check should be removed when 2.2 is out. + */ + if (pd[0] == 0xff && pd[1] == 0x03) + dissect_ip(pd, 4, fd, tree); + else + dissect_ip(pd, 0, fd, tree); +} + diff --git a/packet-rip.c b/packet-rip.c new file mode 100644 index 0000000000..d0e0bbe337 --- /dev/null +++ b/packet-rip.c @@ -0,0 +1,144 @@ +/* packet-ospf.c + * Routines for RIPv1 and RIPv2 packet disassembly + * (c) Copyright Hannes R. Boehm + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#include "ethereal.h" +#include "packet.h" +#include "packet-rip.h" + + +void +dissect_rip(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + e_riphdr *rip_header; + e_rip_vektor rip_vektor; + int auth = FALSE; + + GtkWidget *rip_tree = NULL, *ti; + GtkWidget *rip_vektor_tree; + + + /* we do the range checking of the index when checking wether or not this is a RIP packet */ + char *packet_type[8] = { "never used", "Request", "Response", + "Traceon", "Traceoff", "Vendor specific (Sun)" }; + char *version[3] = { "RIP", "RIPv1", "RIPv2" }; + + + rip_header = (e_riphdr *) &pd[offset]; + /* Check if we 've realy got a RIP packet */ + + switch(rip_header->version) { + case RIPv1: + /* the domain field has to be set to zero for RIPv1 */ + if(!(rip_header->domain == 0)){ + dissect_data(pd, offset, fd, tree); + return; + } + /* the RIPv2 checks are also made for v1 packets */ + case RIPv2: + /* check wether or not command nr. is between 1-7 + * (range checking for index of char* packet_type is done at the same time) + */ + if( !( (rip_header->command > 0) && (rip_header->command <= 7) )){ + dissect_data(pd, offset, fd, tree); + return; + } + break; + default: + /* we only know RIPv1 and RIPv2 */ + dissect_data(pd, offset, fd, tree); + return; + } + + + if (fd->win_info[0]) { + strcpy(fd->win_info[3], version[rip_header->version] ); + sprintf(fd->win_info[4], "%s", packet_type[rip_header->command]); + } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, (fd->cap_len - offset), "Routing Information Protocol"); + rip_tree = gtk_tree_new(); + add_subtree(ti, rip_tree, ETT_RIP); + + add_item_to_tree(rip_tree, offset + 1, 1, "Version: %d", rip_header->version); + add_item_to_tree(rip_tree, offset, 1, "Command: %d (%s)", rip_header->command, packet_type[rip_header->command]); + switch(ntohs(rip_header->family)){ + case 2: /* IP */ + add_item_to_tree(rip_tree, offset + 4 , 2, "Address Family ID: IP"); + break; + case 0xFFFF: + add_item_to_tree(rip_tree, offset + 4 , 2, "Authenticated Packet"); + auth = TRUE; + break; + default: + /* return; */ + } + + if(rip_header->version == RIPv2) { + add_item_to_tree(rip_tree, offset + 2 , 2, "Routing Domain: %d", ntohs(rip_header->domain)); + add_item_to_tree(rip_tree, offset + 6 , 2, "Route Tag: %d", ntohs(rip_header->tag)); + } + /* skip header */ + offset += RIP_HEADER_LENGTH; + + /* if present, skip the authentication */ + if(auth){ + offset += RIP_VEKTOR_LENGTH; + } + /* zero or more distance vektors */ + + while((fd->cap_len - offset) >= RIP_VEKTOR_LENGTH){ + ti = add_item_to_tree(GTK_WIDGET(rip_tree), offset, RIP_VEKTOR_LENGTH, "RIP Vektor"); + rip_vektor_tree = gtk_tree_new(); + add_subtree(ti, rip_vektor_tree, ETT_RIP_VEC); + + memcpy(&rip_vektor, &pd[offset], sizeof(rip_vektor)); /* avoid alignment problem */ + add_item_to_tree(rip_vektor_tree, offset, 4, "IP Address: %s", ip_to_str((guint8 *) &(rip_vektor.ip))); + + if(rip_header->version == RIPv2) { + add_item_to_tree(rip_vektor_tree, offset + 4 , 4, "Netmask: %s", + ip_to_str((guint8 *) &(rip_vektor.mask))); + add_item_to_tree(rip_vektor_tree, offset + 8 , 4, "Next Hop: %s", + ip_to_str((guint8 *) &(rip_vektor.next_hop))); + } + + add_item_to_tree(rip_vektor_tree, offset + 12 , 4, "Metric: %d", ntohl(rip_vektor.metric)); + + offset += RIP_VEKTOR_LENGTH; + }; + } +} diff --git a/packet-rip.h b/packet-rip.h new file mode 100644 index 0000000000..59606fc254 --- /dev/null +++ b/packet-rip.h @@ -0,0 +1,23 @@ +/* packet-rip.h (c) 1998 Hannes Boehm */ + +#define RIPv1 1 +#define RIPv2 2 + +#define RIP_HEADER_LENGTH 8 +#define RIP_VEKTOR_LENGTH 16 + +typedef struct _e_riphdr { + guint8 command; + guint8 version; + guint16 domain; + guint16 family; + guint16 tag; +} e_riphdr; + + +typedef struct _e_rip_vektor { + guint32 ip; + guint32 mask; + guint32 next_hop; + guint32 metric; +} e_rip_vektor; diff --git a/packet-tcp.c b/packet-tcp.c new file mode 100644 index 0000000000..66dbacd733 --- /dev/null +++ b/packet-tcp.c @@ -0,0 +1,116 @@ +/* packet-tcp.c + * Routines for TCP packet disassembly + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include "ethereal.h" +#include "packet.h" + +void +dissect_tcp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + e_tcphdr th; + GtkWidget *tcp_tree, *ti; + gchar flags[64] = ""; + gchar *fstr[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG"}; + gint fpos = 0, i; + guint bpos; + + /* To do: Check for {cap len,pkt len} < struct len */ + /* Avoids alignment problems on many architectures. */ + memcpy(&th, &pd[offset], sizeof(e_tcphdr)); + th.th_sport = ntohs(th.th_sport); + th.th_dport = ntohs(th.th_dport); + th.th_win = ntohs(th.th_win); + th.th_sum = ntohs(th.th_sum); + th.th_urp = ntohs(th.th_urp); + th.th_seq = ntohl(th.th_seq); + th.th_ack = ntohl(th.th_ack); + + for (i = 0; i < 6; i++) { + bpos = 1 << i; + if (th.th_flags & bpos) { + if (fpos) { + strcpy(&flags[fpos], ", "); + fpos += 2; + } + strcpy(&flags[fpos], fstr[i]); + fpos += 3; + } + } + flags[fpos] = '\0'; + + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "TCP"); + sprintf(fd->win_info[4], "Source port: %d Destination port: %d", + th.th_sport, th.th_dport); + } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, 20, + "Transmission Control Protocol"); + tcp_tree = gtk_tree_new(); + add_subtree(ti, tcp_tree, ETT_TCP); + add_item_to_tree(tcp_tree, offset, 2, "Source port: %d", th.th_sport); + add_item_to_tree(tcp_tree, offset + 2, 2, "Destination port: %d", th.th_dport); + add_item_to_tree(tcp_tree, offset + 4, 4, "Sequence number: 0x%08x", + th.th_seq); + add_item_to_tree(tcp_tree, offset + 8, 4, "Acknowledgement number: 0x%08x", + th.th_ack); + add_item_to_tree(tcp_tree, offset + 12, 1, "Header length: %d", th.th_off); + add_item_to_tree(tcp_tree, offset + 13, 1, "Flags: %s", flags); + add_item_to_tree(tcp_tree, offset + 14, 2, "Window size: %d", th.th_win); + add_item_to_tree(tcp_tree, offset + 16, 2, "Checksum: 0x%04x", th.th_sum); + add_item_to_tree(tcp_tree, offset + 18, 2, "Urgent pointer: 0x%04x", + th.th_urp); + /* To do: TCP options */ + + } + /* Skip over header + options */ + offset += 4 * th.th_off; + + /* until we decode those options, I'll check the packet length + to see if there's more data. -- gilbert */ + if (fd->cap_len > offset) { + switch(MIN(th.th_sport, th.th_dport)) { + case TCP_PORT_PRINTER: + dissect_lpd(pd, offset, fd, tree); + break; + default: + dissect_data(pd, offset, fd, tree); + } + } +} diff --git a/packet-tr.c b/packet-tr.c new file mode 100644 index 0000000000..7615d87003 --- /dev/null +++ b/packet-tr.c @@ -0,0 +1,253 @@ +/* packet-tr.c + * Routines for Token-Ring packet disassembly + * Gilbert Ramirez + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#include "packet.h" +#include "ethereal.h" +#include "etypes.h" + +static void +add_ring_bridge_pairs(int rcf_len, const u_char *pd, GtkWidget *tree); + +static char* +sr_broadcast(u_char val) { + + if (val < 4) { + return "Non-broadcast"; + } + else if (val < 6) { + return "All-routes broadcast"; + } + else { + return "Single-route broadcast"; + } +} + +static int +sr_frame(u_char val) { + + int rc_frame[7] = { 516, 1500, 2052, 4472, 8144, 11407, 17800 }; + + if (val > 6) { + return -1; + } + else return rc_frame[val]; +} + +void +dissect_tr(const u_char *pd, frame_data *fd, GtkTree *tree) { + + GtkWidget *fh_tree, *ti; + int offset = 14; + int source_routed = 0; + int rif_bytes = 0; + guint8 nonsr_hwaddr[8]; + int frame_type = (pd[1] & 192) >> 6; /* I use this value a lot */ + #ifdef linux + int silly_linux = 0; + #endif + + /* Token-Ring Strings */ + char *fc[] = { "MAC", "LLC", "Reserved" }; + char *fc_pcf[] = { + "Normal buffer", "Express buffer", "Purge", + "Claim Token", "Beacon", "Active Monitor Present", + "Standby Monitor Present" }; + char *rc_arrow[] = { "-->", "<--" }; + char *rc_direction[] = { "From originating station", + "To originating station" }; + + /* if the high bit on the first byte of src hwaddr is 1, then + this packet is source-routed */ + source_routed = pd[8] & 128; + + /* sometimes we have a RCF but no RIF... half source-routed? */ + /* I'll check for 2 bytes of RIF and the 0x70 byte */ + if (!source_routed) { + if ((pd[14] & 31) == 2 && pd[15] == 0x70) { + source_routed = 1; + } + } + + if (source_routed) { + rif_bytes = pd[14] & 31; + } + /* this is a silly hack for Linux 2.0.x. Read the comment below, + in front of the other #ifdef linux */ + #ifdef linux + if ((source_routed && rif_bytes == 2 && frame_type == 1) || + (!source_routed && frame_type == 1)) { + /* look for SNAP or IPX only */ + if ( (pd[0x20] == 0xaa && pd[0x21] == 0xaa && pd[0x22] == 03) || + (pd[0x20] == 0xe0 && pd[0x21] == 0xe0) ) { + silly_linux = 1; + rif_bytes = 18; + } + } + #endif + offset += rif_bytes; + + /* Make a copy of the src hwaddr, w/o source routing. I'll do this + for all packets, even non-sr packets */ + memcpy(nonsr_hwaddr, &pd[8], 6); + nonsr_hwaddr[0] &= 127; + + if (fd->win_info[0]) { + strcpy(fd->win_info[2], ether_to_str((guint8 *)&pd[2])); + strcpy(fd->win_info[1], ether_to_str(nonsr_hwaddr)); + strcpy(fd->win_info[3], "TR"); + sprintf(fd->win_info[4], "Token-Ring %s", fc[frame_type]); + } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), 0, 14 + rif_bytes, + "Token-Ring (%d on wire, %d captured)", fd->pkt_len, fd->cap_len); + fh_tree = gtk_tree_new(); + add_subtree(ti, fh_tree, ETT_TOKEN_RING); + add_item_to_tree(fh_tree, 0, 1, + "Access Control: %s, Priority=%d, Monitor Count=%d, " + "Priority Reservation=%d", + ((pd[0] & 16) >> 4) ? "Frame" : "Token", /* frame/token */ + ((pd[0] & 224) >> 5), /* priority */ + ((pd[0] & 8) >> 3), /* monitor count */ + ((pd[0] & 7))); /* priority reserv. */ + + add_item_to_tree(fh_tree, 1, 1, + "Frame Control: %s, Physical Control=%d (%s)", + fc[frame_type], (pd[1] & 15), + fc_pcf[(pd[1] & 15)]); + + add_item_to_tree(fh_tree, 2, 6, "Destination: %s", + ether_to_str((guint8 *) &pd[2])); + add_item_to_tree(fh_tree, 8, 6, "Source: %s", + ether_to_str((guint8 *) &pd[8])); + + if (source_routed) { + add_item_to_tree(fh_tree, 14, 1, "RIF length: %d bytes", + pd[14] & 31); /* not rif_bytes because of silly_linux */ + + add_item_to_tree(fh_tree, 15, 1, + "%s, up to %d bytes in frame (LF=%d)", + sr_broadcast((pd[14] & 224) >> 5), + sr_frame((pd[15] & 112) >> 4), + (pd[15] & 112) >> 4); + + add_item_to_tree(fh_tree, 15, 1, + "Direction: %s (%s)", + rc_direction[(pd[15] & 128) >> 7], + rc_arrow[(pd[15] & 128) >> 7]); + + /* if we have more than 2 bytes of RIF, then we have + ring/bridge pairs */ + if ((pd[14] & 31) > 2) { /* not rif_bytes because of silly_linux */ + add_ring_bridge_pairs(rif_bytes, pd, fh_tree); + } + } + + /* Linux 2.0.x has a problem in that the 802.5 code creates + an emtpy full (18-byte) RIF area. It's up to the tr driver to + either fill it in or remove it before sending the bytes out + to the wire. If you run tcpdump on a Linux 2.0.x machine running + token-ring, tcpdump will capture these 18 filler bytes. They + are filled with garbage. The best way to detect this problem is + to know the src hwaddr of the machine from which you were running + tcpdump. W/o that, however, I'm guessing that DSAP == SSAP if the + frame type is LLC. It's very much a hack. -- Gilbert Ramirez */ + #ifdef linux + if ( (source_routed && ((pd[14] & 31) == 2) && silly_linux) || + (!source_routed) && silly_linux ) { + add_item_to_tree(fh_tree, 14, 18, + "Empty RIF from Linux 2.0.x driver. The sniffing NIC " + "is also running a protocol stack."); + } + #endif + } + + /* The package is either MAC or LLC */ + switch (frame_type) { + /* MAC */ + case 0: + /* dissect_trmac(pd, offset, fd, tree) */ + dissect_trmac(pd, offset, fd, tree); + break; + case 1: + dissect_llc(pd, offset, fd, tree); + break; + default: + /* non-MAC, non-LLC, i.e., "Reserved" */ + dissect_data(pd, offset, fd, tree); + break; + } +} + +/* this routine is taken from the Linux net/802/tr.c code, which shows +ring-bridge paires in the /proc/net/tr_rif virtual file. */ +static void +add_ring_bridge_pairs(int rcf_len, const u_char *pd, GtkWidget *tree) +{ + int j, size; + int segment, brdgnmb; + char buffer[50]; + int buff_offset=0; + + rcf_len -= 2; + + if (rcf_len) + rcf_len >>= 1; + + for(j = 1; j < rcf_len; j++) { + if (j==1) { + segment=ntohs(*((unsigned short*)&pd[16])) >> 4; + size = sprintf(buffer,"%03X",segment); + buff_offset += size; + } + segment=ntohs(*((unsigned short*)&pd[17+j])) >> 4; + brdgnmb=pd[16+j] & 0x0f; + size = sprintf(buffer+buff_offset,"-%01X-%03X",brdgnmb,segment); + buff_offset += size; + } + + add_item_to_tree(tree, 16, rcf_len << 1, + "Ring-Bridge Pairs: %s", + buffer); + +} + diff --git a/packet-trmac.c b/packet-trmac.c new file mode 100644 index 0000000000..b0c6ce6c97 --- /dev/null +++ b/packet-trmac.c @@ -0,0 +1,322 @@ +/* packet-trmac.c + * Routines for Token-Ring Media Access Control + * Gilbert Ramirez + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include + +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include "packet.h" +#include "ethereal.h" +#include "etypes.h" + +struct vec_info { + u_char cmd; + char *text; +}; + +/* Major Vector */ +static void +mv_text(u_char cmd, int offset, frame_data *fd, GtkWidget *tree) { + int i=0; + + static struct vec_info mv[] = { + { 0x00, "Response" }, + { 0x02, "Beacon" }, + { 0x03, "Claim Token" }, + { 0x04, "Ring Purge" }, + { 0x05, "Active Monitor Present" }, + { 0x06, "Standby Monitor Present" }, + { 0x07, "Duplicate Address Test" }, + { 0x09, "Transmit Forward" }, + { 0x0B, "Remove Ring Station" }, + { 0x0C, "Change Parameters" }, + { 0x0D, "Initialize Ring Station" }, + { 0x0E, "Request Ring Station Address" }, + { 0x0F, "Request Ring Station Address" }, + { 0x10, "Request Ring Station Attachments" }, + { 0x20, "Request Initialization" }, + { 0x22, "Report Ring Station Address" }, + { 0x23, "Report Ring Station State" }, + { 0x24, "Report Ring Station Attachments" }, + { 0x25, "Report New Active Monitor" }, + { 0x26, "Report NAUN Change" }, + { 0x27, "Report Poll Error" }, + { 0x28, "Report Monitor Errors" }, + { 0x29, "Report Error" }, + { 0x2A, "Report Transmit Forward" }, + { 0x00, NULL } + }; + + while (mv[i].text != NULL) { + if (mv[i].cmd == cmd) { + if (fd->win_info[0]) { + /* I can do this because no higher-level dissect() + will strcpy onto me. */ + fd->win_info[4] = mv[i].text; + } + if (tree) { + add_item_to_tree(tree, offset, 1, "Major Vector Command: %s", + mv[i].text); + } + return; + } + i++; + } + /* failure */ + add_item_to_tree(tree, offset, 1, "Major Vector Command: %02X (Unknown)", + cmd); +} + +/* Sub-vectors */ +static int +sv_text(const u_char *pd, int pkt_offset, GtkWidget *tree) +{ + int sv_length = pd[0]; + + char *beacon[] = {"Recovery mode set", "Signal loss error", + "Streaming signal not Claim Token MAC frame", + "Streaming signal, Claim Token MAC frame"}; + + GtkWidget *sv_tree, *ti; + + u_char errors[6]; /* isolating or non-isolating */ + + /* this just adds to the clutter on the screen... + add_item_to_tree(tree, pkt_offset, 1, + "Subvector Length: %d bytes", sv_length);*/ + + switch(pd[1]) { + case 0x01: /* Beacon Type */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Beacon Type: %s", beacon[ pntohs( &pd[2] ) ] ); + break; + + case 0x02: /* NAUN */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "NAUN: %s", ether_to_str((guint8*)&pd[2])); + break; + + case 0x03: /* Local Ring Number */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Local Ring Number: 0x%04X (%d)", + pntohs( &pd[2] ), pntohs( &pd[2] )); + break; + + case 0x04: /* Assign Physical Location */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Assign Physical Location: 0x%08X", pntohl( &pd[2] ) ); + break; + + case 0x05: /* Soft Error Report Value */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Soft Error Report Value: %d ms", 10 * pntohs( &pd[2] ) ); + break; + + case 0x06: /* Enabled Function Classes */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Enabled Function Classes: %04X", pntohs( &pd[2] ) ); + break; + + case 0x07: /* Allowed Access Priority */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Allowed Access Priority: %04X", pntohs( &pd[2] ) ); + break; + + case 0x09: /* Correlator */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Correlator: %04X", pntohs( &pd[2] ) ); + break; + + case 0x0A: /* Address of last neighbor notification */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Address of Last Neighbor Notification: %s", + ether_to_str((guint8*)&pd[2])); + break; + + case 0x0B: /* Physical Location */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Physical Location: 0x%08X", pntohl( &pd[2] ) ); + break; + + case 0x20: /* Response Code */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Response Code: 0x%04X 0x%04X", pntohl( &pd[2] ), + pntohl( &pd[4] ) ); + break; + + case 0x21: /* Reserved */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Reserved: 0x%04X", pntohs( &pd[2] ) ); + break; + + case 0x22: /* Product Instance ID */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Product Instance ID: ..."); + break; + + case 0x23: /* Ring Station Microcode Level */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Ring Station Microcode Level: ..."); + break; + + case 0x26: /* Wrap data */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Wrap Data: ... (%d bytes)", sv_length - 2); + break; + + case 0x27: /* Frame Forward */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Frame Forward: ... (%d bytes)", sv_length - 2); + break; + + case 0x29: /* Ring Station Status Subvector */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Ring Station Status Subvector: ..."); + break; + + case 0x2A: /* Transmit Status Code */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Transmit Status Code: %04X", pntohs( &pd[2] ) ); + break; + + case 0x2B: /* Group Address */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Group Address: %08X", pntohl( &pd[2] ) ); + break; + + case 0x2C: /* Functional Address */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Functional Address: %08X", pntohl( &pd[2] ) ); + break; + + case 0x2D: /* Isolating Error Counts */ + memcpy(errors, &pd[2], 6); + ti = add_item_to_tree(GTK_WIDGET(tree), pkt_offset+1, sv_length-1, + "Isolating Error Counts (%d total)", + errors[0] + errors[1] + errors[2] + errors[3] + errors[4]); + sv_tree = gtk_tree_new(); + add_subtree(ti, sv_tree, ETT_TR_IERR_CNT); + + add_item_to_tree(sv_tree, pkt_offset+2, 1, + "Line Errors: %d", errors[0]); + add_item_to_tree(sv_tree, pkt_offset+3, 1, + "Internal Errors: %d", errors[1]); + add_item_to_tree(sv_tree, pkt_offset+4, 1, + "Burst Errors: %d", errors[2]); + add_item_to_tree(sv_tree, pkt_offset+5, 1, + "A/C Errors: %d", errors[3]); + add_item_to_tree(sv_tree, pkt_offset+6, 1, + "Abort delimiter transmitted: %d", errors[4]); + + break; + + case 0x2E: /* Non-Isolating Error Counts */ + memcpy(errors, &pd[2], 6); + ti = add_item_to_tree(GTK_WIDGET(tree), pkt_offset+1, sv_length-1, + "Non-Isolating Error Counts (%d total)", + errors[0] + errors[1] + errors[2] + errors[3] + errors[4]); + sv_tree = gtk_tree_new(); + add_subtree(ti, sv_tree, ETT_TR_NERR_CNT); + + add_item_to_tree(sv_tree, pkt_offset+2, 1, + "Lost Frame Errors: %d", errors[0]); + add_item_to_tree(sv_tree, pkt_offset+3, 1, + "Receiver Congestion: %d", errors[1]); + add_item_to_tree(sv_tree, pkt_offset+4, 1, + "Frame-Copied Congestion: %d", errors[2]); + add_item_to_tree(sv_tree, pkt_offset+5, 1, + "Frequency Errors: %d", errors[3]); + add_item_to_tree(sv_tree, pkt_offset+6, 1, + "Token Errors: %d", errors[4]); + break; + + case 0x30: /* Error Code */ + add_item_to_tree(tree, pkt_offset+1, sv_length-1, + "Error Code: %04X", pntohs( &pd[2] ) ); + break; + + default: /* Unknown */ + add_item_to_tree(tree, pkt_offset+1, 1, + "Unknown Sub-Vector: 0x%02X", pd[1]); + } + return sv_length; +} + +void +dissect_trmac(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + + GtkWidget *mac_tree = NULL, *ti; + int mv_length, sv_length, sv_offset; + char *class[] = { "Ring Station", "LLC Manager", "", "", + "Configuration Report Server", "Ring Parameter Server", + "Ring Error Monitor" }; + + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "TR MAC"); + } + + mv_length = ntohs(*((guint16*)&pd[offset])); + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, mv_length, + "Media Access Control"); + mac_tree = gtk_tree_new(); + add_subtree(ti, mac_tree, ETT_TR_MAC); + } + + /* Interpret the major vector */ + mv_text(pd[offset+3], offset+3, fd, mac_tree); + + if (tree) { + add_item_to_tree(mac_tree, offset, 2, "Total Length: %d bytes", + mv_length); + add_item_to_tree(mac_tree, offset+2, 1, "Source Class: %s", + class[ pd[offset+2] & 0x0f ]); + add_item_to_tree(mac_tree, offset+2, 1, "Destination Class: %s", + class[ pd[offset+2] >> 4 ]); + + /* interpret the subvectors */ + sv_offset = 0; + offset += 4; + sv_length = mv_length - 4; + while (sv_offset < sv_length) { + sv_offset += sv_text(&pd[offset + sv_offset], offset + sv_offset, + mac_tree); + } + } +} diff --git a/packet-udp.c b/packet-udp.c new file mode 100644 index 0000000000..f9d37c71fb --- /dev/null +++ b/packet-udp.c @@ -0,0 +1,92 @@ +/* packet-udp.c + * Routines for UDP packet disassembly + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include "ethereal.h" +#include "packet.h" +#include "resolv.h" + +void +dissect_udp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { + e_udphdr *uh; + guint16 uh_sport, uh_dport, uh_ulen, uh_sum; + GtkWidget *udp_tree, *ti; + + /* To do: Check for {cap len,pkt len} < struct len */ + uh = (e_udphdr *) &pd[offset]; + uh_sport = ntohs(uh->uh_sport); + uh_dport = ntohs(uh->uh_dport); + uh_ulen = ntohs(uh->uh_ulen); + uh_sum = ntohs(uh->uh_sum); + + if (fd->win_info[0]) { + strcpy(fd->win_info[3], "UDP"); + sprintf(fd->win_info[4], "Source port: %s Destination port: %s", + get_udp_port(uh_sport), get_udp_port(uh_dport)); + } + + if (tree) { + ti = add_item_to_tree(GTK_WIDGET(tree), offset, 8, + "User Datagram Protocol"); + udp_tree = gtk_tree_new(); + add_subtree(ti, udp_tree, ETT_UDP); + add_item_to_tree(udp_tree, offset, 2, "Source port: %s", get_udp_port(uh_sport)); + add_item_to_tree(udp_tree, offset + 2, 2, "Destination port: %s", get_udp_port(uh_dport)); + add_item_to_tree(udp_tree, offset + 4, 2, "Length: %d", uh_ulen); + add_item_to_tree(udp_tree, offset + 6, 2, "Checksum: 0x%04x", uh_sum); + } + + /* Skip over header */ + offset += 8; + + /* To do: make sure we aren't screwing ourselves with the MIN call. */ + switch (MIN(uh_sport, uh_dport)) { + case UDP_PORT_BOOTPS: + dissect_bootp(pd, offset, fd, tree); + break; + case UDP_PORT_DNS: + dissect_dns(pd, offset, fd, tree); + break; + case UDP_PORT_RIP: + /* we should check the source port too (RIP: UDP src and dst port 520) */ + dissect_rip(pd, offset, fd, tree); + break; + default: + dissect_data(pd, offset, fd, tree); + } +} diff --git a/packet.c b/packet.c new file mode 100644 index 0000000000..ef30704d1f --- /dev/null +++ b/packet.c @@ -0,0 +1,216 @@ +/* packet.c + * Routines for packet disassembly + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include +#include +#include + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include "packet.h" +#include "ethereal.h" +#include "etypes.h" +#include "file.h" + +extern GtkWidget *byte_view; +extern GdkFont *m_r_font, *m_b_font; +extern capture_file cf; + +gchar * +ether_to_str(guint8 *ad) { + static gchar str[3][18]; + static gchar *cur; + + if (cur == &str[0][0]) { + cur = &str[1][0]; + } else if (cur == &str[1][0]) { + cur = &str[2][0]; + } else { + cur = &str[0][0]; + } + sprintf(cur, "%02x:%02x:%02x:%02x:%02x:%02x", ad[0], ad[1], ad[2], + ad[3], ad[4], ad[5]); + return cur; +} + +gchar * +ip_to_str(guint8 *ad) { + static gchar str[3][16]; + static gchar *cur; + + if (cur == &str[0][0]) { + cur = &str[1][0]; + } else if (cur == &str[1][0]) { + cur = &str[2][0]; + } else { + cur = &str[0][0]; + } + sprintf(cur, "%d.%d.%d.%d", ad[0], ad[1], ad[2], ad[3]); + return cur; +} + +void +packet_hex_print(GtkText *bv, guchar *pd, gint len, gint bstart, gint blen) { + gint i = 0, j, k, cur; + gchar line[128], hexchars[] = "0123456789abcdef"; + GdkFont *cur_font, *new_font; + + while (i < len) { + /* Print the line number */ + sprintf(line, "%04x ", i); + gtk_text_insert(bv, m_r_font, NULL, NULL, line, -1); + /* Do we start in bold? */ + cur_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font; + j = i; + k = i + BYTE_VIEW_WIDTH; + cur = 0; + /* Print the hex bit */ + while (i < k) { + if (i < len) { + line[cur++] = hexchars[(pd[i] & 0xf0) >> 4]; + line[cur++] = hexchars[pd[i] & 0x0f]; + } else { + line[cur++] = ' '; line[cur++] = ' '; + } + line[cur++] = ' '; + i++; + /* Did we cross a bold/plain boundary? */ + new_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font; + if (cur_font != new_font) { + gtk_text_insert(bv, cur_font, NULL, NULL, line, cur); + cur_font = new_font; + cur = 0; + } + } + line[cur++] = ' '; + gtk_text_insert(bv, cur_font, NULL, NULL, line, cur); + cur = 0; + i = j; + /* Print the ASCII bit */ + cur_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font; + while (i < k) { + if (i < len) { + line[cur++] = (isgraph(pd[i])) ? pd[i] : '.'; + } else { + line[cur++] = ' '; + } + i++; + /* Did we cross a bold/plain boundary? */ + new_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font; + if (cur_font != new_font) { + gtk_text_insert(bv, cur_font, NULL, NULL, line, cur); + cur_font = new_font; + cur = 0; + } + } + line[cur++] = '\n'; + line[cur] = '\0'; + gtk_text_insert(bv, cur_font, NULL, NULL, line, -1); + } +} + +GtkWidget * +add_item_to_tree(GtkWidget *tree, gint start, gint len, + gchar *format, ...) { + GtkWidget *ti; + va_list ap; + gchar label_str[256]; + guint32 t_info; + + /* This limits us to a max packet size of 65535 bytes. */ + /* Are there any systems out there with < 32-bit pointers? */ + /* To do: use gtk_object_set_data instead, now that I know it exists. */ + t_info = ((start & 0xffff) << 16) | (len & 0xffff); + va_start(ap, format); + vsnprintf(label_str, 256, format, ap); + ti = gtk_tree_item_new_with_label(label_str); + gtk_object_set_user_data(GTK_OBJECT(ti), (gpointer) t_info); + gtk_tree_append(GTK_TREE(tree), ti); + gtk_widget_show(ti); + + return ti; +} + +void +add_subtree(GtkWidget *ti, GtkWidget *subtree, gint idx) { + static gint tree_type[NUM_TREE_TYPES]; + + gtk_tree_item_set_subtree(GTK_TREE_ITEM(ti), subtree); + if (tree_type[idx]) + gtk_tree_item_expand(GTK_TREE_ITEM(ti)); + gtk_signal_connect(GTK_OBJECT(ti), "expand", (GtkSignalFunc) expand_tree, + (gpointer) &tree_type[idx]); + gtk_signal_connect(GTK_OBJECT(ti), "collapse", (GtkSignalFunc) collapse_tree, + (gpointer) &tree_type[idx]); +} + +void +expand_tree(GtkWidget *w, gpointer data) { + gint *val = (gint *) data; + *val = 1; +} + +void +collapse_tree(GtkWidget *w, gpointer data) { + gint *val = (gint *) data; + *val = 0; +} + +/* decodes the protocol start and length thare are encoded into + the t_info field in add_item_to_tree. */ +void +decode_start_len(GtkTreeItem *ti, gint *pstart, gint *plen) +{ + guint32 t_info; + int start, len; + + t_info = (guint32) gtk_object_get_user_data(GTK_OBJECT(ti)); + *pstart = t_info >> 16; + *plen = t_info & 0xffff; +} + + +/* this routine checks the frame type from the cf structure */ +void +dissect_packet(const u_char *pd, frame_data *fd, GtkTree *tree) { + + switch (cf.lnk_t) { + case DLT_EN10MB : + dissect_eth(pd, fd, tree); + break; + case DLT_IEEE802 : + dissect_tr(pd, fd, tree); + break; + case DLT_RAW : + dissect_raw(pd, fd, tree); + break; + } +} diff --git a/packet.h b/packet.h new file mode 100644 index 0000000000..9cc9b57139 --- /dev/null +++ b/packet.h @@ -0,0 +1,354 @@ +/* packet.h + * Definitions for packet disassembly structures and routines + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#ifndef __PACKET_H__ +#define __PACKET_H__ + +/* Pointer versions of ntohs and ntohl. Given a pointer to a member of a + * byte array, returns the value of the two or four bytes at the pointer. + * Handy for + */ + +#if BYTE_ORDER == LITTLE_ENDIAN +#define pntohs(p) ((guint16) \ + ((guint16)*((guint8 *)p+0)<<8| \ + (guint16)*((guint8 *)p+1)<<0)) + +#define pntohl(p) ((guint32)*((guint8 *)p+0)<<24| \ + (guint32)*((guint8 *)p+1)<<16| \ + (guint32)*((guint8 *)p+2)<<8| \ + (guint32)*((guint8 *)p+3)<<0) +#else /* BIG_ENDIAN */ +#define pntohs(p) ((guint16) \ + ((guint16)*((guint8 *)p+1)<<8| \ + (guint16)*((guint8 *)p+0)<<0)) + +#define pntohl(p) ((guint32)*((guint8 *)p+3)<<24| \ + (guint32)*((guint8 *)p+2)<<16| \ + (guint32)*((guint8 *)p+1)<<8| \ + (guint32)*((guint8 *)p+0)<<0) +#endif /* LITTLE_ENDIAN */ + +#define IEEE_802_3_MAX_LEN 1500 +#define BYTE_VIEW_WIDTH 16 + +typedef struct _frame_data { + guint32 pkt_len; /* Packet length */ + guint32 cap_len; /* Amount actually captured */ + guint32 secs; /* Seconds */ + guint32 usecs; /* Microseconds */ + long file_off; /* File offset */ + gchar *win_info[5]; /* Packet list text */ +} frame_data; + +/* Many of the structs and definitions below were taken from include files + * in the Linux distribution. */ + +/* ARP / RARP structs and definitions */ + +typedef struct _e_ether_arp { + guint16 ar_hrd; + guint16 ar_pro; + guint8 ar_hln; + guint8 ar_pln; + guint16 ar_op; + guint8 arp_sha[6]; + guint8 arp_spa[4]; + guint8 arp_tha[6]; + guint8 arp_tpa[4]; +} e_ether_arp; + +#ifndef ARPOP_REQUEST +#define ARPOP_REQUEST 1 /* ARP request. */ +#endif +#ifndef ARPOP_REPLY +#define ARPOP_REPLY 2 /* ARP reply. */ +#endif +/* Some OSes have different names, or don't define these at all */ +#ifndef ARPOP_RREQUEST +#define ARPOP_RREQUEST 3 /* RARP request. */ +#endif +#ifndef ARPOP_RREPLY +#define ARPOP_RREPLY 4 /* RARP reply. */ +#endif + +/* ICMP structs and definitions */ + +typedef struct _e_icmp { + guint8 icmp_type; + guint8 icmp_code; + guint16 icmp_cksum; + union { + struct { /* Address mask request/reply */ + guint16 id; + guint16 seq; + guint32 sn_mask; + } am; + struct { /* Timestap request/reply */ + guint16 id; + guint16 seq; + guint32 orig; + guint32 recv; + guint32 xmit; + } ts; + guint32 zero; /* Unreachable */ + } opt; +} e_icmp; + +#define ICMP_ECHOREPLY 0 +#define ICMP_UNREACH 3 +#define ICMP_SOURCEQUENCH 4 +#define ICMP_REDIRECT 5 +#define ICMP_ECHO 8 +#define ICMP_TIMXCEED 11 +#define ICMP_PARAMPROB 12 +#define ICMP_TSTAMP 13 +#define ICMP_TSTAMPREPLY 14 +#define ICMP_IREQ 15 +#define ICMP_IREQREPLY 16 +#define ICMP_MASKREQ 17 +#define ICMP_MASKREPLY 18 + +/* IGMP structs and definitions */ + +typedef struct _e_igmp { +#if BYTE_ORDER == BIG_ENDIAN + guint8 igmp_v:4; + guint8 igmp_t:4; +#else /* Little endian */ + guint8 igmp_t:4; + guint8 igmp_v:4; +#endif + guint8 igmp_unused; + guint16 igmp_cksum; + guint32 igmp_gaddr; +} e_igmp; + +#define IGMP_M_QRY 0x01 +#define IGMP_V1_M_RPT 0x02 +#define IGMP_V2_LV_GRP 0x07 +#define IGMP_DVMRP 0x03 +#define IGMP_PIM 0x04 +#define IGMP_V2_M_RPT 0x06 +#define IGMP_MTRC_RESP 0x1e +#define IGMP_MTRC 0x1f + +/* IP structs and definitions */ + +typedef struct _e_ip { +#if BYTE_ORDER == BIG_ENDIAN + guint8 ip_v:4; + guint8 ip_hl:4; +#else /* Little endian */ + guint8 ip_hl:4; + guint8 ip_v:4; +#endif + guint8 ip_tos; + guint16 ip_len; + guint16 ip_id; + guint16 ip_off; + guint8 ip_ttl; + guint8 ip_p; + guint16 ip_sum; + guint32 ip_src; + guint32 ip_dst; +} e_ip; + +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) +#define IPTOS_NONE 0x00 +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_LOWCOST 0x02 + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_IGMP 2 +#define IP_PROTO_TCP 6 +#define IP_PROTO_UDP 17 +#define IP_PROTO_OSPF 89 + +/* PPP structs and definitions */ + +typedef struct _e_ppphdr { + guint8 ppp_flag; + guint8 ppp_addr; + guint8 ppp_ctl; + guint16 ppp_prot; +} e_ppphdr; + +/* TCP structs and definitions */ + +typedef struct _e_tcphdr { + guint16 th_sport; + guint16 th_dport; + guint32 th_seq; + guint32 th_ack; +#if BYTE_ORDER == LITTLE_ENDIAN + guint8 th_x2:4; + guint8 th_off:4; +#else + guint8 th_off:4; + guint8 th_x2:4; +#endif + guint8 th_flags; +#define TH_FIN 0x01 +#define TH_SYN 0x02 +#define TH_RST 0x04 +#define TH_PUSH 0x08 +#define TH_ACK 0x10 +#define TH_URG 0x20 + guint16 th_win; + guint16 th_sum; + guint16 th_urp; +} e_tcphdr; + +/* UDP structs and definitions */ + +typedef struct _e_udphdr { + guint16 uh_sport; + guint16 uh_dport; + guint16 uh_ulen; + guint16 uh_sum; +} e_udphdr; + +/* UDP Ports -> should go in packet-udp.h */ + +#define UDP_PORT_DNS 53 +#define UDP_PORT_BOOTPS 67 +#define UDP_PORT_RIP 520 + +/* TCP Ports */ + +#define TCP_PORT_PRINTER 515 + +/* Tree types. Each dissect_* routine should have one for each + add_subtree() call. */ + +#define ETT_IEEE8023 0 +#define ETT_ETHER2 1 +#define ETT_LLC 2 +#define ETT_TOKEN_RING 3 +#define ETT_TR_IERR_CNT 4 +#define ETT_TR_NERR_CNT 5 +#define ETT_TR_MAC 6 +#define ETT_PPP 7 +#define ETT_ARP 8 +#define ETT_IP 9 +#define ETT_UDP 10 +#define ETT_TCP 11 +#define ETT_ICMP 12 +#define ETT_IGMP 13 +#define ETT_IPX 14 +#define ETT_SPX 15 +#define ETT_NCP 16 +#define ETT_DNS 17 +#define ETT_DNS_ANS 18 +#define ETT_DNS_QRY 19 +#define ETT_RIP 20 +#define ETT_RIP_VEC 21 +#define ETT_OSPF 22 +#define ETT_OSPF_HDR 23 +#define ETT_OSPF_HELLO 24 +#define ETT_OSPF_DESC 25 +#define ETT_OSPF_LSR 26 +#define ETT_OSPF_LSA_UPD 27 +#define ETT_OSPF_LSA 28 +#define ETT_LPD 29 +#define ETT_RAW 30 +#define ETT_BOOTP 31 +#define ETT_BOOTP_OPTION 32 +#define ETT_IPv6 33 + +/* Should be the last item number plus one */ +#define NUM_TREE_TYPES 34 + +/* The version of pcap.h that comes with some systems is missing these + * #defines. + */ + +#ifndef DLT_RAW +#define DLT_RAW 12 +#endif + +#ifndef DLT_SLIP_BSDOS +#define DLT_SLIP_BSDOS 13 +#endif + +#ifndef DLT_PPP_BSDOS +#define DLT_PPP_BSDOS 14 +#endif + +/* Utility routines used by packet*.c */ +gchar* ether_to_str(guint8 *); +gchar* ip_to_str(guint8 *); +void packet_hex_print(GtkText *, guint8 *, gint, gint, gint); +GtkWidget* add_item_to_tree(GtkWidget *, gint, gint, gchar *, ...); +void decode_start_len(GtkTreeItem *, gint*, gint*); + +/* Routines in packet.c */ +void dissect_packet(const u_char *, frame_data *, GtkTree *); +void add_subtree(GtkWidget *, GtkWidget*, gint); +void expand_tree(GtkWidget *, gpointer); +void collapse_tree(GtkWidget *, gpointer); + +/* + * Routines in packet-*.c + * Routines should take three args: packet data *, frame_data *, tree * + * They should never modify the packet data. + */ +void dissect_eth(const u_char *, frame_data *, GtkTree *); +void dissect_ppp(const u_char *, frame_data *, GtkTree *); +void dissect_raw(const u_char *, frame_data *, GtkTree *); +void dissect_tr(const u_char *, frame_data *, GtkTree *); + +/* + * Routines in packet-*.c + * Routines should take four args: packet data *, offset, frame_data *, + * tree * + * They should never modify the packet data. + */ +void dissect_arp(const u_char *, int, frame_data *, GtkTree *); +void dissect_bootp(const u_char *, int, frame_data *, GtkTree *); +void dissect_data(const u_char *, int, frame_data *, GtkTree *); +void dissect_dns(const u_char *, int, frame_data *, GtkTree *); +void dissect_icmp(const u_char *, int, frame_data *, GtkTree *); +void dissect_igmp(const u_char *, int, frame_data *, GtkTree *); +void dissect_ip(const u_char *, int, frame_data *, GtkTree *); +void dissect_ipv6(const u_char *, int, frame_data *, GtkTree *); +void dissect_ipx(const u_char *, int, frame_data *, GtkTree *); +void dissect_llc(const u_char *, int, frame_data *, GtkTree *); +void dissect_lpd(const u_char *, int, frame_data *, GtkTree *); +void dissect_ospf(const u_char *, int, frame_data *, GtkTree *); +void dissect_ospf_hello(const u_char *, int, frame_data *, GtkTree *); +void dissect_tcp(const u_char *, int, frame_data *, GtkTree *); +void dissect_trmac(const u_char *, int, frame_data *, GtkTree *); +void dissect_udp(const u_char *, int, frame_data *, GtkTree *); + +/* This function is in ethertype.c */ +void ethertype(guint16 etype, int offset, + const u_char *pd, frame_data *fd, GtkTree *tree, + GtkWidget *fh_tree); + +#endif /* packet.h */ diff --git a/print.c b/print.c new file mode 100644 index 0000000000..4ec296f8ea --- /dev/null +++ b/print.c @@ -0,0 +1,509 @@ +/* print.c + * Routines for printing packet analysis trees. + * + * Gilbert Ramirez + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#include "packet.h" +#include "print.h" + +static void printer_opts_file_cb(GtkWidget *w, gpointer te); +static void printer_opts_fs_cancel_cb(GtkWidget *w, gpointer data); +static void printer_opts_fs_ok_cb(GtkWidget *w, gpointer data); +static void printer_opts_ok_cb(GtkWidget *w, gpointer data); +static void printer_opts_close_cb(GtkWidget *w, gpointer win); +static void printer_opts_toggle_format(GtkWidget *widget, gpointer data); +static void printer_opts_toggle_dest(GtkWidget *widget, gpointer data); +static void dumpit (FILE *fh, register const u_char *cp, register u_int length); +static void dumpit_ps (FILE *fh, register const u_char *cp, register u_int length); +static void ps_clean_string(unsigned char *out, const unsigned char *in, + int outbuf_size); + +/* #include "ps.c" */ + +pr_opts printer_opts; + +void printer_opts_cb(GtkWidget *w, gpointer d) +{ + GtkWidget *propt_w, *main_vb, *button; + GtkWidget *format_hb, *format_lb; + GtkWidget *dest_hb, *dest_lb; + GtkWidget *cmd_hb, *cmd_lb, *cmd_te; + GtkWidget *file_hb, *file_bt, *file_te; + GtkWidget *bbox, *ok_bt, *cancel_bt; + GSList *format_grp, *dest_grp; + pr_opts *temp_pr_opts = g_malloc(sizeof(pr_opts)); + + /* Make a working copy of the printer data */ + memcpy(temp_pr_opts, &printer_opts, sizeof(pr_opts)); +/* temp_pr_opts->cmd = g_strdup(printer_opts->cmd); + temp_pr_opts->file = g_strdup(printer_opts->file);*/ + + propt_w = gtk_window_new(GTK_WINDOW_TOPLEVEL); + temp_pr_opts->window = propt_w; + + /* Container for each row of widgets */ + main_vb = gtk_vbox_new(FALSE, 3); + gtk_container_border_width(GTK_CONTAINER(main_vb), 5); + gtk_container_add(GTK_CONTAINER(propt_w), main_vb); + gtk_widget_show(main_vb); + + /* Output format */ + format_hb = gtk_hbox_new(FALSE, 1); + gtk_container_add(GTK_CONTAINER(main_vb), format_hb); + gtk_widget_show(format_hb); + + format_lb = gtk_label_new("Format:"); + gtk_box_pack_start(GTK_BOX(format_hb), format_lb, FALSE, FALSE, 3); + gtk_widget_show(format_lb); + + button = gtk_radio_button_new_with_label(NULL, "Plain Text"); + if (printer_opts.output_format == 0) { + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE); + } + format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(button)); + gtk_box_pack_start(GTK_BOX(format_hb), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_radio_button_new_with_label(format_grp, "PostScript"); + if (printer_opts.output_format == 1) { + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE); + } + gtk_signal_connect(GTK_OBJECT(button), "toggled", + GTK_SIGNAL_FUNC(printer_opts_toggle_format), + (gpointer)temp_pr_opts); + gtk_box_pack_start(GTK_BOX(format_hb), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + /* Output destination */ + dest_hb = gtk_hbox_new(FALSE, 1); + gtk_container_add(GTK_CONTAINER(main_vb), dest_hb); + gtk_widget_show(dest_hb); + + dest_lb = gtk_label_new("Print to:"); + gtk_box_pack_start(GTK_BOX(dest_hb), dest_lb, FALSE, FALSE, 3); + gtk_widget_show(dest_lb); + + button = gtk_radio_button_new_with_label(NULL, "Command"); + if (printer_opts.output_dest == 0) { + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE); + } + dest_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(button)); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE); + gtk_box_pack_start(GTK_BOX(dest_hb), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_radio_button_new_with_label(dest_grp, "File"); + if (printer_opts.output_dest == 1) { + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE); + } + gtk_signal_connect(GTK_OBJECT(button), "toggled", + GTK_SIGNAL_FUNC(printer_opts_toggle_dest), + (gpointer)temp_pr_opts); + gtk_box_pack_start(GTK_BOX(dest_hb), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + /* Command text entry */ + cmd_hb = gtk_hbox_new(FALSE, 1); + gtk_container_add(GTK_CONTAINER(main_vb), cmd_hb); + gtk_widget_show(cmd_hb); + + cmd_lb = gtk_label_new("Command:"); + gtk_box_pack_start(GTK_BOX(cmd_hb), cmd_lb, FALSE, FALSE, 3); + gtk_widget_show(cmd_lb); + + cmd_te = gtk_entry_new(); + temp_pr_opts->cmd_te = cmd_te; + gtk_entry_set_text(GTK_ENTRY(cmd_te), printer_opts.cmd); + gtk_box_pack_start(GTK_BOX(cmd_hb), cmd_te, TRUE, TRUE, 3); + gtk_widget_show(cmd_te); + + /* File button and text entry */ + file_hb = gtk_hbox_new(FALSE, 1); + gtk_container_add(GTK_CONTAINER(main_vb), file_hb); + gtk_widget_show(file_hb); + + file_bt = gtk_button_new_with_label("File:"); + gtk_box_pack_start(GTK_BOX(file_hb), file_bt, FALSE, FALSE, 3); + gtk_widget_show(file_bt); + + file_te = gtk_entry_new(); + temp_pr_opts->file_te = file_te; + gtk_entry_set_text(GTK_ENTRY(file_te), printer_opts.file); + gtk_box_pack_start(GTK_BOX(file_hb), file_te, TRUE, TRUE, 3); + gtk_widget_show(file_te); + + gtk_signal_connect_object(GTK_OBJECT(file_bt), "clicked", + GTK_SIGNAL_FUNC(printer_opts_file_cb), GTK_OBJECT(file_te)); + + + /* Button row: OK and cancel buttons */ + bbox = gtk_hbutton_box_new(); + gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END); + gtk_container_add(GTK_CONTAINER(main_vb), bbox); + gtk_widget_show(bbox); + + ok_bt = gtk_button_new_with_label ("OK"); + gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked", + GTK_SIGNAL_FUNC(printer_opts_ok_cb), (gpointer)temp_pr_opts); + gtk_container_add(GTK_CONTAINER(bbox), ok_bt); + gtk_widget_show(ok_bt); + + cancel_bt = gtk_button_new_with_label ("Cancel"); + gtk_signal_connect_object(GTK_OBJECT(cancel_bt), "clicked", + GTK_SIGNAL_FUNC(printer_opts_close_cb), (gpointer)temp_pr_opts); + gtk_container_add(GTK_CONTAINER(bbox), cancel_bt); + gtk_widget_show(cancel_bt); + + /* Show the completed window */ + gtk_widget_show(propt_w); +} + + +static void +printer_opts_file_cb(GtkWidget *w, gpointer te) { + GtkWidget *fs, **w_list; + + w_list = g_malloc(2 * sizeof(GtkWidget *)); + + fs = gtk_file_selection_new ("Ethereal: Print to a File"); + w_list[0] = fs; + w_list[1] = (GtkWidget *) te; + + gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", (GtkSignalFunc) printer_opts_fs_ok_cb, w_list); + + /* Connect the cancel_button to destroy the widget */ + gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", (GtkSignalFunc) printer_opts_fs_cancel_cb, w_list); + + gtk_widget_show(fs); +} + +static void +printer_opts_fs_ok_cb(GtkWidget *w, gpointer data) { + GtkWidget **w_list = (GtkWidget **) data; + + gtk_entry_set_text(GTK_ENTRY(w_list[1]), + gtk_file_selection_get_filename (GTK_FILE_SELECTION(w_list[0]))); + printer_opts_fs_cancel_cb(w, data); +} + +static void +printer_opts_fs_cancel_cb(GtkWidget *w, gpointer data) { + GtkWidget **w_list = (GtkWidget **) data; + + gtk_widget_destroy(w_list[0]); + g_free(data); +} + +static void +printer_opts_ok_cb(GtkWidget *w, gpointer data) +{ + printer_opts.output_format = ((pr_opts*)data)->output_format; + printer_opts.output_dest = ((pr_opts*)data)->output_dest; + + free(printer_opts.cmd); + printer_opts.cmd = + g_strdup(gtk_entry_get_text(GTK_ENTRY(((pr_opts*)data)->cmd_te))); + + free(printer_opts.file); + printer_opts.file = + g_strdup(gtk_entry_get_text(GTK_ENTRY(((pr_opts*)data)->file_te))); + + gtk_widget_destroy(GTK_WIDGET(((pr_opts*)data)->window)); + g_free(data); +} + +static void +printer_opts_close_cb(GtkWidget *w, gpointer data) +{ + gtk_widget_destroy(GTK_WIDGET(((pr_opts*)data)->window)); + g_free(data); +} + +static void +printer_opts_toggle_format(GtkWidget *widget, gpointer data) +{ + if (GTK_TOGGLE_BUTTON (widget)->active) { + ((pr_opts*)data)->output_format = 1; + /* toggle file/cmd */ + } + else { + ((pr_opts*)data)->output_format = 0; + /* toggle file/cmd */ + } +} + +static void +printer_opts_toggle_dest(GtkWidget *widget, gpointer data) +{ + if (GTK_TOGGLE_BUTTON (widget)->active) { + ((pr_opts*)data)->output_dest = 1; + } + else { + ((pr_opts*)data)->output_dest = 0; + } +} + +/* ========================================================== */ +void print_tree(const u_char *pd, frame_data *fd, GtkTree *tree) +{ + FILE *fh; + char *out; + + /* Open the file or command for output */ + if (printer_opts.output_dest == 0) { + out = printer_opts.cmd; + fh = popen(printer_opts.cmd, "w"); + } + else { + out = printer_opts.file; + fh = fopen(printer_opts.file, "w"); + } + + if (!fh) { + g_error("Cannot open %s for output.\n", out); + return; + } + + /* Create the output */ + if (printer_opts.output_format == 0) { + print_tree_text(fh, pd, fd, tree); + } + else { + print_ps_preamble(fh); + print_tree_ps(fh, pd, fd, tree); + print_ps_finale(fh); + } + + /* Close the file or command */ + if (printer_opts.output_dest == 0) { + pclose(fh); + } + else { + fclose(fh); + } +} + +/* Print a tree's data in plain text */ +void print_tree_text(FILE *fh, const u_char *pd, frame_data *fd, GtkTree *tree) +{ + GList *children, *child, *widgets, *label; + GtkWidget *subtree; + int num_children, i, j; + char *text; + int num_spaces; + char space[41]; + gint data_start, data_len; + + /* Prepare the tabs for printing, depending on tree level */ + num_spaces = tree->level * 4; + if (num_spaces > 40) { + num_spaces = 40; + } + for (i = 0; i < num_spaces; i++) { + space[i] = ' '; + } + /* The string is NUL-terminated */ + space[num_spaces] = 0; + + /* Get the children of this tree */ + children = tree->children; + num_children = g_list_length(children); + + for (i = 0; i < num_children; i++) { + /* Each child of the tree is a widget container */ + child = g_list_nth(children, i); + widgets = gtk_container_children(GTK_CONTAINER(child->data)); + + /* And the container holds a label object, which holds text */ + label = g_list_nth(widgets, 0); + gtk_label_get(GTK_LABEL(label->data), &text); + + /* Print the text */ + fprintf(fh, "%s%s\n", space, text); + + /* Recurse into the subtree, if it exists */ + subtree = (GTK_TREE_ITEM(child->data))->subtree; + if (subtree) { + print_tree_text(fh, pd, fd, GTK_TREE(subtree)); + } + else if (strcmp("Data", text) == 0) { + decode_start_len(GTK_TREE_ITEM(child->data), &data_start, &data_len); + dumpit(fh, &pd[data_start], data_len); + } + } +} + +/* This routine was created by Dan Lasley , and +only slightly modified for ethereal by Gilbert Ramirez. */ +static +void dumpit (FILE *fh, register const u_char *cp, register u_int length) +{ + register int ad, i, j, k; + u_char c; + u_char line[60]; + static u_char binhex[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + memset (line, ' ', sizeof line); + line[sizeof (line)-1] = 0; + for (ad=i=j=k=0; i>4]; + line[j++] = binhex[c&0xf]; + if (i&1) j++; + line[42+k++] = c >= ' ' && c < 0x7f ? c : '.'; + if ((i & 15) == 15) { + fprintf (fh, "\n%4x %s", ad, line); + /*if (i==15) printf (" %d", length);*/ + memset (line, ' ', sizeof line); + line[sizeof (line)-1] = j = k = 0; + ad += 16; + } + } + + if (line[0] != ' ') fprintf (fh, "\n%4x %s", ad, line); + fprintf(fh, "\n"); + return; + +} + +#define MAX_LINE_LENGTH 256 + +static +void dumpit_ps (FILE *fh, register const u_char *cp, register u_int length) +{ + register int ad, i, j, k; + u_char c; + u_char line[60]; + static u_char binhex[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + u_char psline[MAX_LINE_LENGTH]; + + memset (line, ' ', sizeof line); + line[sizeof (line)-1] = 0; + for (ad=i=j=k=0; i>4]; + line[j++] = binhex[c&0xf]; + if (i&1) j++; + line[42+k++] = c >= ' ' && c < 0x7f ? c : '.'; + if ((i & 15) == 15) { + ps_clean_string(psline, line, MAX_LINE_LENGTH); + fprintf (fh, "(%4x %s) hexdump\n", ad, psline); + memset (line, ' ', sizeof line); + line[sizeof (line)-1] = j = k = 0; + ad += 16; + } + } + + if (line[0] != ' ') { + ps_clean_string(psline, line, MAX_LINE_LENGTH); + fprintf (fh, "(%4x %s) hexdump\n", ad, psline); + } + return; + +} + +/* Print a tree's data in PostScript */ +void print_tree_ps(FILE *fh, const u_char *pd, frame_data *fd, GtkTree *tree) +{ + GList *children, *child, *widgets, *label; + GtkWidget *subtree; + int num_children, i, j; + char *text; + gint data_start, data_len; + char psbuffer[MAX_LINE_LENGTH]; /* static sized buffer! */ + + /* Get the children of this tree */ + children = tree->children; + num_children = g_list_length(children); + + for (i = 0; i < num_children; i++) { + /* Each child of the tree is a widget container */ + child = g_list_nth(children, i); + widgets = gtk_container_children(GTK_CONTAINER(child->data)); + + /* And the container holds a label object, which holds text */ + label = g_list_nth(widgets, 0); + gtk_label_get(GTK_LABEL(label->data), &text); + + /* Print the text */ + ps_clean_string(psbuffer, text, MAX_LINE_LENGTH); + fprintf(fh, "%d (%s) putline\n", tree->level, psbuffer); + + /* Recurse into the subtree, if it exists */ + subtree = (GTK_TREE_ITEM(child->data))->subtree; + if (subtree) { + print_tree_ps(fh, pd, fd, GTK_TREE(subtree)); + } + else if (strcmp("Data", text) == 0) { + decode_start_len(GTK_TREE_ITEM(child->data), &data_start, &data_len); + print_ps_hex(fh); + dumpit_ps(fh, &pd[data_start], data_len); + } + } +} + +static +void ps_clean_string(unsigned char *out, const unsigned char *in, + int outbuf_size) +{ + int rd, wr; + char c; + + for (rd = 0, wr = 0 ; wr < outbuf_size; rd++, wr++ ) { + c = in[rd]; + switch (c) { + case '(': + case ')': + case '\\': + out[wr] = '\\'; + out[++wr] = c; + break; + + default: + out[wr] = c; + break; + } + + if (c == 0) { + break; + } + } +} diff --git a/print.h b/print.h new file mode 100644 index 0000000000..07b5a4d086 --- /dev/null +++ b/print.h @@ -0,0 +1,47 @@ +/* print.h + * Definitions for printing packet analysis trees. + * + * Gilbert Ramirez + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PRINT_H__ +#define __PRINT_H__ + +typedef struct pr_opts { + int output_format; /* 0=text, 1=postscript */ + int output_dest; /* 0=cmd, 1=file */ + char *file; + char *cmd; + + /* for the dialogue box */ + GtkWidget *window; + GtkWidget *cmd_te; + GtkWidget *file_te; +} pr_opts; + +/* Functions in print.h */ + +void printer_opts_cb(GtkWidget *, gpointer); +void print_tree_text(FILE *fh, const u_char *pd, frame_data *fd, GtkTree *tree); +void print_tree_ps(FILE *fh, const u_char *pd, frame_data *fd, GtkTree *tree); + +#endif /* print.h */ diff --git a/print.ps b/print.ps new file mode 100644 index 0000000000..b1277df79f --- /dev/null +++ b/print.ps @@ -0,0 +1,100 @@ +%! +% +% Code between start/end remarks is put into ps.c +% Anything else is thrown away, and is for testing only. +% +% ---- ethereal preamble start ---- % +%! +%!PS-Adobe-2.0 +% +% Ethereal - Network traffic analyzer +% By Gerald Combs +% Copyright 1998 Gerald Combs +% +%%Creator: Ethereal +%%Title: ethereal.ps +%%DocumentFonts: Helvetica Courier +%%EndComments +%! + +% Get the Imagable Area of the page +clippath pathbbox + +% Set vmax to the vertical size of the page, +% hmax to the horizontal size of the page. +/vmax exch def +/hmax exch def +pop pop % junk + +% 1-inch margins +/lmargin 72 def +/tmargin vmax 72 sub def +/bmargin 72 def + +% Counters +/vpos vmax 70 sub def + +/putline { + exch 10 mul lmargin add % X + vpos % Y + moveto + show + + /vpos vpos 10 sub def + + vpos bmargin le % is vpos <= bottom margin? + {showpage + /vpos tmargin def} + if % then formfeed and start at top +} def + +/hexdump { + lmargin % X + vpos % Y + moveto + show + + /vpos vpos 10 sub def + + vpos bmargin le % is vpos <= bottom margin? + {showpage + /vpos tmargin def} + if % then formfeed and start at top +} def + +% Set the font to 10 point +/Helvetica findfont 10 scalefont setfont + +% Display our output lines. +% ---- ethereal preamble end ---- % +0 (Ethernet II \(98 on wire, 68 captured\)) putline +1 (Destination: 00:00:0c:36:00:2a) putline +1 (Source: 00:c0:4f:c7:eb:c0) putline +1 (Type: IP \(0x0800\)) putline +0 (Ethernet II \(98 on wire, 68 captured\)) putline +1 (Source: 00:c0:4f:c7:eb:c0) putline +1 (Type: IP \(0x0800\)) putline +0 (Source: 00:c0:4f:c7:eb:c0) putline + +% ---- ethereal hex start ---- % +% Set the font to 10 point +/Courier findfont 10 scalefont setfont +() hexdump +% ---- ethereal hex end ---- % + +( 0 cc00 0000 0000 0702 0000 0000 0000 0000 ................ ) hexdump +( 10 0000 bd0e fe16 0100 3e00 0308 584c 2038 ........>...XL 8 ) hexdump +( 20 3020 494d 3300 1601 0034 0016 0101 3500 0 IM3....4....5. ) hexdump +( 30 1601 0236 0016 0103 6e00 1601 ff6f 0016 ...6....n....o.. ) hexdump +( 40 01ff 7000 1601 ff71 0016 01ff 4800 0104 ..p....q....H... ) hexdump +( 50 ff03 0700 2400 0101 0525 0001 0105 2600 ....$....%....&. ) hexdump +( 60 0101 0527 0001 0105 6a00 0101 006b 0001 ...'....j....k.. ) hexdump +( 70 0100 6c00 0101 006d 0001 0100 3d00 0102 ..l....m....=... ) hexdump +( 80 0200 c000 0308 8000 0000 0000 0000 b400 ................ ) hexdump +( 90 0104 c0a8 42ef 3900 1608 0505 0505 0000 ....B.9......... ) hexdump +( a0 0000 0003 2036 4120 5269 6e67 0000 0000 .... 6A Ring.... ) hexdump +( b0 0000 0000 0000 ...... ) hexdump + +% ---- ethereal finale start ---- % +showpage +% ---- ethereal finale end ---- % diff --git a/ps.c b/ps.c new file mode 100644 index 0000000000..2de8f706e4 --- /dev/null +++ b/ps.c @@ -0,0 +1,87 @@ +/* Created by rdps.c. Do not edit! */ + +#include + +#include + +/* Created by rdps.c. Do not edit! */ +void print_ps_preamble(FILE *fd) { + fprintf(fd, "%%!\n"); + fprintf(fd, "%%!PS-Adobe-2.0\n"); + fprintf(fd, "%%\n"); + fprintf(fd, "%% Ethereal - Network traffic analyzer\n"); + fprintf(fd, "%% By Gerald Combs \n"); + fprintf(fd, "%% Copyright 1998 Gerald Combs\n"); + fprintf(fd, "%%\n"); + fprintf(fd, "%%%%Creator: Ethereal\n"); + fprintf(fd, "%%%%Title: ethereal.ps\n"); + fprintf(fd, "%%%%DocumentFonts: Helvetica Courier\n"); + fprintf(fd, "%%%%EndComments\n"); + fprintf(fd, "%%!\n"); + fprintf(fd, "\n"); + fprintf(fd, "%% Get the Imagable Area of the page\n"); + fprintf(fd, "clippath pathbbox\n"); + fprintf(fd, "\n"); + fprintf(fd, "%% Set vmax to the vertical size of the page,\n"); + fprintf(fd, "%% hmax to the horizontal size of the page.\n"); + fprintf(fd, "/vmax exch def\n"); + fprintf(fd, "/hmax exch def\n"); + fprintf(fd, "pop pop %% junk\n"); + fprintf(fd, "\n"); + fprintf(fd, "%% 1-inch margins\n"); + fprintf(fd, "/lmargin 72 def\n"); + fprintf(fd, "/tmargin vmax 72 sub def\n"); + fprintf(fd, "/bmargin 72 def\n"); + fprintf(fd, "\n"); + fprintf(fd, "%% Counters\n"); + fprintf(fd, "/vpos vmax 70 sub def\n"); + fprintf(fd, "\n"); + fprintf(fd, "/putline {\n"); + fprintf(fd, " exch 10 mul lmargin add %% X\n"); + fprintf(fd, " vpos %% Y\n"); + fprintf(fd, " moveto\n"); + fprintf(fd, " show\n"); + fprintf(fd, "\n"); + fprintf(fd, " /vpos vpos 10 sub def\n"); + fprintf(fd, "\n"); + fprintf(fd, " vpos bmargin le %% is vpos <= bottom margin?\n"); + fprintf(fd, " {showpage\n"); + fprintf(fd, " /vpos tmargin def}\n"); + fprintf(fd, " if %% then formfeed and start at top\n"); + fprintf(fd, "} def\n"); + fprintf(fd, "\n"); + fprintf(fd, "/hexdump {\n"); + fprintf(fd, " lmargin %% X\n"); + fprintf(fd, " vpos %% Y\n"); + fprintf(fd, " moveto\n"); + fprintf(fd, " show\n"); + fprintf(fd, "\n"); + fprintf(fd, " /vpos vpos 10 sub def\n"); + fprintf(fd, "\n"); + fprintf(fd, " vpos bmargin le %% is vpos <= bottom margin?\n"); + fprintf(fd, " {showpage\n"); + fprintf(fd, " /vpos tmargin def}\n"); + fprintf(fd, " if %% then formfeed and start at top\n"); + fprintf(fd, "} def\n"); + fprintf(fd, "\n"); + fprintf(fd, "%% Set the font to 10 point\n"); + fprintf(fd, "/Helvetica findfont 10 scalefont setfont\n"); + fprintf(fd, "\n"); + fprintf(fd, "%% Display our output lines.\n"); +} + + +/* Created by rdps.c. Do not edit! */ +void print_ps_hex(FILE *fd) { + fprintf(fd, "%% Set the font to 10 point\n"); + fprintf(fd, "/Courier findfont 10 scalefont setfont\n"); + fprintf(fd, "() hexdump\n"); +} + + +/* Created by rdps.c. Do not edit! */ +void print_ps_finale(FILE *fd) { + fprintf(fd, "showpage\n"); +} + + diff --git a/ps.h b/ps.h new file mode 100644 index 0000000000..8a1a06adb6 --- /dev/null +++ b/ps.h @@ -0,0 +1,35 @@ +/* ps.h + * Definitions for generating PostScript(R) packet output. + * + * Gilbert Ramirez + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PS_H__ +#define __PS_H__ + +/* Functions in ps.c; automatically generated by rdps */ + +void print_ps_preamble(FILE *); +void print_ps_hex(FILE *); +void print_ps_finale(FILE *); + +#endif /* ps.h */ diff --git a/rdps.c b/rdps.c new file mode 100644 index 0000000000..a15cb72edc --- /dev/null +++ b/rdps.c @@ -0,0 +1,185 @@ +/* rdps.c + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* takes the file listed as the first argument and creates the file listed +as the second argument. It takes a PostScript file and creates a C program +with 3 functions: + print_ps_preamble() + print_ps_hex() + print_ps_finale() + +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#define BUFFER_SIZE 1024 + +void start_code(FILE *fd, char *func); +void write_code(FILE *fd, char *string); +void end_code(FILE *fd); +void ps_clean_string(unsigned char *out, const unsigned char *in, + int outbuf_size); + +enum ps_state { null, preamble, hex, finale }; + +int main(int argc, char **argv) +{ + FILE *input; + FILE *output; + char buf[BUFFER_SIZE]; /* static sized buffer! */ + enum ps_state state = null; + + if (argc != 3) { + fprintf(stderr, "%s: input_file output_file\n", argv[0]); + exit(-1); + } + + if (!(input = fopen(argv[1], "r"))) { + fprintf(stderr, "%s: cannot open %s for input.\n", argv[0], argv[1]); + exit(-1); + } + + if (!(output = fopen(argv[2], "w"))) { + fprintf(stderr, "%s: cannot open %s for output.\n", argv[0], argv[2]); + exit(-1); + } + + fprintf(output, "/* Created by rdps.c. Do not edit! */\n\n" + "#include \n\n" + "#include \n\n"); + + while (fgets(buf, BUFFER_SIZE - 1, input)) { + + if (state == null) { + if (strcmp(buf, "% ---- ethereal preamble start ---- %\n") == 0) { + state = preamble; + start_code(output, "preamble"); + continue; + } + else if (strcmp(buf, "% ---- ethereal hex start ---- %\n") == 0) { + state = hex; + start_code(output, "hex"); + continue; + } + else if (strcmp(buf, "% ---- ethereal finale start ---- %\n") == 0) { + state = finale; + start_code(output, "finale"); + continue; + } + } + else if (state == preamble) { + if (strcmp(buf, "% ---- ethereal preamble end ---- %\n") == 0) { + state = null; + end_code(output); + continue; + } + else { + write_code(output, buf); + } + } + else if (state == hex) { + if (strcmp(buf, "% ---- ethereal hex end ---- %\n") == 0) { + state = null; + end_code(output); + continue; + } + else { + write_code(output, buf); + } + } + else if (state == finale) { + if (strcmp(buf, "% ---- ethereal finale end ---- %\n") == 0) { + state = null; + end_code(output); + continue; + } + else { + write_code(output, buf); + } + } + else { + fprintf(stderr, "NO MATCH:%s", buf); + exit(-1); + } + } + exit(0); +} + +void start_code(FILE *fd, char *func) +{ + fprintf(fd, "/* Created by rdps.c. Do not edit! */\n"); + fprintf(fd, "void print_ps_%s(FILE *fd) {\n", func); +} + +void write_code(FILE *fd, char *string) +{ + char psbuf[BUFFER_SIZE]; + ps_clean_string(psbuf, string, BUFFER_SIZE); + fprintf(fd, "\tfprintf(fd, \"%s\");\n", psbuf); +} + +void end_code(FILE *fd) +{ + fprintf(fd, "}\n\n\n"); +} + +void ps_clean_string(unsigned char *out, const unsigned char *in, + int outbuf_size) +{ + int rd, wr; + char c; + + for (rd = 0, wr = 0 ; wr < outbuf_size; rd++, wr++ ) { + c = in[rd]; + switch (c) { + case '\\': + out[wr] = '\\'; + out[++wr] = '\\'; + out[++wr] = c; + break; + + case '%': + out[wr] = '%'; + out[++wr] = '%'; + break; + + case '\n': + out[wr] = '\\'; + out[++wr] = 'n'; + break; + + default: + out[wr] = c; + break; + } + + if (c == 0) { + break; + } + } +} diff --git a/resolv.c b/resolv.c new file mode 100644 index 0000000000..bcc9211a68 --- /dev/null +++ b/resolv.c @@ -0,0 +1,269 @@ +/* resolv.c + * Routines for network object lookup + * + * Laurent Deniel + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * To do: + * + * - Add ethernet address resolution + * - In a future live capture and decode mode, + * add hostname entries in hash table from DNS packet decoding. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef AVOID_DNS_TIMEOUT +#define AVOID_DNS_TIMEOUT +#endif + +#include +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include +#include +#include + +#ifdef AVOID_DNS_TIMEOUT +# include +#endif + +#include "packet.h" +#include "resolv.h" + +#define MAXNAMELEN 64 /* max name length (hostname and port name) */ +#define HASHHOSTSIZE 1024 +#define HASHPORTSIZE 256 + +/* hash table used for host and port lookup */ + +typedef struct hashname { + u_int addr; + u_char name[MAXNAMELEN]; + struct hashname *next; +} hashname_t; + +static hashname_t *host_table[HASHHOSTSIZE]; +static hashname_t *udp_port_table[HASHPORTSIZE]; +static hashname_t *tcp_port_table[HASHPORTSIZE]; + +/* global variable that indicates if name resolving is actif */ + +int g_resolving_actif = 1; /* routines are active by default */ + +/* local function definitions */ + +static u_char *serv_name_lookup(u_int port, u_int proto) +{ + + hashname_t *tp; + hashname_t **table; + char *serv_proto = NULL; + struct servent *servp; + int i; + + switch(proto) { + case IPPROTO_UDP: + table = udp_port_table; + serv_proto = "udp"; + break; + case IPPROTO_TCP: + table = tcp_port_table; + serv_proto = "tcp"; + break; + default: + /* not yet implemented */ + return NULL; + /*NOTREACHED*/ + break; + } /* proto */ + + i = port & (HASHPORTSIZE - 1); + tp = table[ i & (HASHPORTSIZE - 1)]; + + if( tp == NULL ) { + tp = table[ i & (HASHPORTSIZE - 1)] = + (hashname_t *)g_malloc(sizeof(hashname_t)); + } else { + while(1) { + if( tp->addr == port ) { + return tp->name; + } + if (tp->next == NULL) { + tp->next = (hashname_t *)g_malloc(sizeof(hashname_t)); + tp = tp->next; + break; + } + tp = tp->next; + } + } + + /* fill in a new entry */ + tp->addr = port; + tp->next = NULL; + + if ((servp = getservbyport(htons(port), serv_proto)) == NULL) { + /* unknown port */ + sprintf(tp->name, "%d", port); + } else { + strncpy(tp->name, servp->s_name, MAXNAMELEN); + } + + return (tp->name); + +} /* serv_name_lookup */ + +#ifdef AVOID_DNS_TIMEOUT + +#define DNS_TIMEOUT 5 /* max sec per call */ + +jmp_buf hostname_env; + +static void abort_network_query(int sig) +{ + longjmp(hostname_env, 1); +} +#endif /* AVOID_DNS_TIMEOUT */ + +static u_char *host_name_lookup(u_int addr) +{ + + hashname_t *tp; + hashname_t **table = host_table; + struct hostent *hostp; + + tp = table[ addr & (HASHHOSTSIZE - 1)]; + + if( tp == NULL ) { + tp = table[ addr & (HASHHOSTSIZE - 1)] = + (hashname_t *)g_malloc(sizeof(hashname_t)); + } else { + while(1) { + if( tp->addr == addr ) { + return tp->name; + } + if (tp->next == NULL) { + tp->next = (hashname_t *)g_malloc(sizeof(hashname_t)); + tp = tp->next; + break; + } + tp = tp->next; + } + } + + /* fill in a new entry */ + tp->addr = addr; + tp->next = NULL; + +#ifdef AVOID_DNS_TIMEOUT + + /* Quick hack to avoid DNS/YP timeout */ + + if (!setjmp(hostname_env)) { + signal(SIGALRM, abort_network_query); + alarm(DNS_TIMEOUT); +#endif + hostp = gethostbyaddr((char *)&addr, 4, AF_INET); +#ifdef AVOID_DNS_TIMEOUT + alarm(0); +#endif + if (hostp != NULL) { + strncpy(tp->name, hostp->h_name, MAXNAMELEN); + return tp->name; + } +#ifdef AVOID_DNS_TIMEOUT + } +#endif + + /* unknown host or DNS timeout */ + + sprintf(tp->name, "%s", ip_to_str((guint8 *)&addr)); + return (tp->name); + +} /* host_name_lookup */ + +/* external functions */ + +extern u_char *get_hostname(u_int addr) +{ + if (!g_resolving_actif) + return ip_to_str((guint8 *)&addr); + + return host_name_lookup(addr); +} + +extern u_char *get_udp_port(u_int port) +{ + static gchar str[3][MAXNAMELEN]; + static gchar *cur; + + if (!g_resolving_actif) { + if (cur == &str[0][0]) { + cur = &str[1][0]; + } else if (cur == &str[1][0]) { + cur = &str[2][0]; + } else { + cur = &str[0][0]; + } + sprintf(cur, "%d", port); + return cur; + } + + return serv_name_lookup(port, IPPROTO_UDP); + +} /* get_udp_port */ + + +extern u_char *get_tcp_port(u_int port) +{ + static gchar str[3][MAXNAMELEN]; + static gchar *cur; + + if (!g_resolving_actif) { + if (cur == &str[0][0]) { + cur = &str[1][0]; + } else if (cur == &str[1][0]) { + cur = &str[2][0]; + } else { + cur = &str[0][0]; + } + sprintf(cur, "%d", port); + return cur; + } + + return serv_name_lookup(port, IPPROTO_TCP); + +} /* get_tcp_port */ + diff --git a/resolv.h b/resolv.h new file mode 100644 index 0000000000..d34f977e68 --- /dev/null +++ b/resolv.h @@ -0,0 +1,39 @@ +/* resolv.h + * Definitions for network object lookup + * + * Laurent Deniel + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __RESOLV_H__ +#define __RESOLV_H__ + +/* global variable */ + +extern int g_resolving_actif; + +/* Functions in resolv.c */ + +extern u_char *get_udp_port(u_int port); +extern u_char *get_tcp_port(u_int port); +extern u_char *get_hostname(u_int addr); + +#endif /* __RESOLV_H__ */ diff --git a/snprintf.c b/snprintf.c new file mode 100644 index 0000000000..f131ca4dfb --- /dev/null +++ b/snprintf.c @@ -0,0 +1,822 @@ + +/* + Unix snprintf implementation. + Version 1.2 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + It can be redistribute also under the terms of GNU Library General + Public Lincense. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Revision History: + + 1.2: + * put the program under LGPL. + 1.1: + * added changes from Miles Bader + * corrected a bug with %f + * added support for %#g + * added more comments :-) + 1.0: + * supporting must ANSI syntaxic_sugars + 0.0: + * suppot %s %c %d + + THANKS(for the patches and ideas): + Miles Bader + Cyrille Rustom + Jacek Slabocewiz + Mike Parker(mouse) + +*/ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "snprintf.h" + +/* + * Find the nth power of 10 + */ +PRIVATE double +#ifdef __STDC__ +pow_10(int n) +#else +pow_10(n) +int n; +#endif +{ + int i; + double P; + + if (n < 0) + for (i = 1, P = 1., n = -n ; i <= n ; i++) {P *= .1;} + else + for (i = 1, P = 1. ; i <= n ; i++) {P *= 10.0;} + return P; +} + +/* + * Find the integral part of the log in base 10 + * Note: this not a real log10() + I just need and approximation(integerpart) of x in: + 10^x ~= r + * log_10(200) = 2; + * log_10(250) = 2; + */ +PRIVATE int +#ifdef __STDC__ +log_10(double r) +#else +log_10(r) +double r; +#endif +{ + int i = 0; + double result = 1.; + + if (r < 0.) + r = -r; + + if (r < 1.) { + while (result >= r) {result *= .1; i++;} + return (-i); + } else { + while (result <= r) {result *= 10.; i++;} + return (i - 1); + } +} + +/* + * This function return the fraction part of a double + * and set in ip the integral part. + * In many ways it resemble the modf() found on most Un*x + */ +PRIVATE double +#ifdef __STDC__ +integral(double real, double * ip) +#else +integral(real, ip) +double real; +double * ip; +#endif +{ + int j; + double i, s, p; + double real_integral = 0.; + +/* take care of the obvious */ +/* equal to zero ? */ + if (real == 0.) { + *ip = 0.; + return (0.); + } + +/* negative number ? */ + if (real < 0.) + real = -real; + +/* a fraction ? */ + if ( real < 1.) { + *ip = 0.; + return real; + } +/* the real work :-) */ + for (j = log_10(real); j >= 0; j--) { + p = pow_10(j); + s = (real - real_integral)/p; + i = 0.; + while (i + 1. <= s) {i++;} + real_integral += i*p; + } + *ip = real_integral; + return (real - real_integral); +} + +#define PRECISION 1.e-6 +/* + * return an ascii representation of the integral part of the number + * and set fract to be an ascii representation of the fraction part + * the container for the fraction and the integral part or staticly + * declare with fix size + */ +PRIVATE char * +#ifdef __STDC__ +numtoa(double number, int base, int precision, char ** fract) +#else +numtoa(number, base, precision, fract) +double number; +int base; +int precision; +char ** fract; +#endif +{ + register int i, j; + double ip, fp; /* integer and fraction part */ + double fraction; + int digits = MAX_INT - 1; + static char integral_part[MAX_INT]; + static char fraction_part[MAX_FRACT]; + double sign; + int ch; + +/* taking care of the obvious case: 0.0 */ + if (number == 0.) { + integral_part[0] = '0'; + integral_part[1] = '\0'; + fraction_part[0] = '0'; + fraction_part[1] = '\0'; + return integral_part; + } + +/* for negative numbers */ + if ((sign = number) < 0.) { + number = -number; + digits--; /* sign consume one digit */ + } + + fraction = integral(number, &ip); + number = ip; +/* do the integral part */ + if ( ip == 0.) { + integral_part[0] = '0'; + i = 1; + } else { + for ( i = 0; i < digits && number != 0.; ++i) { + number /= base; + fp = integral(number, &ip); + ch = (int)((fp + PRECISION)*base); /* force to round */ + integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10; + if (! isxdigit(integral_part[i])) /* bail out overflow !! */ + break; + number = ip; + } + } + +/* Oh No !! out of bound, ho well fill it up ! */ + if (number != 0.) + for (i = 0; i < digits; ++i) + integral_part[i] = '9'; + +/* put the sign ? */ + if (sign < 0.) + integral_part[i++] = '-'; + + integral_part[i] = '\0'; + +/* reverse every thing */ + for ( i--, j = 0; j < i; j++, i--) + SWAP_INT(integral_part[i], integral_part[j]); + +/* the fractionnal part */ + for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision-- ) { + fraction_part[i] = (int)((fp + PRECISION)*10. + '0'); + if (! isdigit(fraction_part[i])) /* underflow ? */ + break; + fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.); + } + fraction_part[i] = '\0'; + + if (fract != (char **)0) + *fract = fraction_part; + + return integral_part; + +} + +/* for %d and friends, it puts in holder + * the representation with the right padding + */ +PRIVATE void +#ifdef __STDC__ +decimal(struct DATA *p, double d) +#else +decimal(p, d) +struct DATA *p; +double d; +#endif +{ + char *tmp; + + tmp = itoa(d); + p->width -= strlen(tmp); + PAD_RIGHT(p); + PUT_PLUS(d, p); + PUT_SPACE(d, p); + while (*tmp) { /* the integral */ + PUT_CHAR(*tmp, p); + tmp++; + } + PAD_LEFT(p); +} + +/* for %o octal representation */ +PRIVATE void +#ifdef __STDC__ +octal(struct DATA *p, double d) +#else +octal(p, d) +struct DATA *p; +double d; +#endif +{ + char *tmp; + + tmp = otoa(d); + p->width -= strlen(tmp); + PAD_RIGHT(p); + if (p->square == FOUND) /* had prefix '0' for octal */ + PUT_CHAR('0', p); + while (*tmp) { /* octal */ + PUT_CHAR(*tmp, p); + tmp++; + } + PAD_LEFT(p); +} + +/* for %x %X hexadecimal representation */ +PRIVATE void +#ifdef __STDC__ +hexa(struct DATA *p, double d) +#else +hexa(p, d) +struct DATA *p; +double d; +#endif +{ + char *tmp; + + tmp = htoa(d); + p->width -= strlen(tmp); + PAD_RIGHT(p); + if (p->square == FOUND) { /* prefix '0x' for hexa */ + PUT_CHAR('0', p); PUT_CHAR(*p->pf, p); + } + while (*tmp) { /* hexa */ + PUT_CHAR((*p->pf == 'X' ? toupper(*tmp) : *tmp), p); + tmp++; + } + PAD_LEFT(p); +} + +/* %s strings */ +PRIVATE void +#ifdef __STDC__ +strings(struct DATA *p, char *tmp) +#else +strings(p, tmp) +struct DATA *p; +char *tmp; +#endif +{ + int i; + + i = strlen(tmp); + if (p->precision != NOT_FOUND) /* the smallest number */ + i = (i < p->precision ? i : p->precision); + p->width -= i; + PAD_RIGHT(p); + while (i-- > 0) { /* put the sting */ + PUT_CHAR(*tmp, p); + tmp++; + } + PAD_LEFT(p); +} + +/* %f or %g floating point representation */ +PRIVATE void +#ifdef __STDC__ +floating(struct DATA *p, double d) +#else +floating(p, d) +struct DATA *p; +double d; +#endif +{ + char *tmp, *tmp2; + int i; + + DEF_PREC(p); + d = ROUND(d, p); + tmp = dtoa(d, p->precision, &tmp2); + /* calculate the padding. 1 for the dot */ + p->width = p->width - + ((d > 0. && p->justify == RIGHT) ? 1:0) - + ((p->space == FOUND) ? 1:0) - + strlen(tmp) - p->precision - 1; + PAD_RIGHT(p); + PUT_PLUS(d, p); + PUT_SPACE(d, p); + while (*tmp) { /* the integral */ + PUT_CHAR(*tmp, p); + tmp++; + } + if (p->precision != 0 || p->square == FOUND) + PUT_CHAR('.', p); /* put the '.' */ + if (*p->pf == 'g' || *p->pf == 'G') /* smash the trailing zeros */ + for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--) + tmp2[i] = '\0'; + for (; *tmp2; tmp2++) + PUT_CHAR(*tmp2, p); /* the fraction */ + + PAD_LEFT(p); +} + +/* %e %E %g exponent representation */ +PRIVATE void +#ifdef __STDC__ +exponent(struct DATA *p, double d) +#else +exponent(p, d) +struct DATA *p; +double d; +#endif +{ + char *tmp, *tmp2; + int j, i; + + DEF_PREC(p); + j = log_10(d); + d = d / pow_10(j); /* get the Mantissa */ + d = ROUND(d, p); + tmp = dtoa(d, p->precision, &tmp2); + /* 1 for unit, 1 for the '.', 1 for 'e|E', + * 1 for '+|-', 3 for 'exp' */ + /* calculate how much padding need */ + p->width = p->width - + ((d > 0. && p->justify == RIGHT) ? 1:0) - + ((p->space == FOUND) ? 1:0) - p->precision - 7; + PAD_RIGHT(p); + PUT_PLUS(d, p); + PUT_SPACE(d, p); + while (*tmp) {/* the integral */ + PUT_CHAR(*tmp, p); + tmp++; + } + if (p->precision != 0 || p->square == FOUND) + PUT_CHAR('.', p); /* the '.' */ + if (*p->pf == 'g' || *p->pf == 'G') /* smash the trailing zeros */ + for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--) + tmp2[i] = '\0'; + for (; *tmp2; tmp2++) + PUT_CHAR(*tmp2, p); /* the fraction */ + + if (*p->pf == 'g' || *p->pf == 'e') { /* the exponent put the 'e|E' */ + PUT_CHAR('e', p); + } else + PUT_CHAR('E', p); + if (j > 0) { /* the sign of the exp */ + PUT_CHAR('+', p); + } else { + PUT_CHAR('-', p); + j = -j; + } + tmp = itoa((double)j); + if (j < 9) { /* need to pad the exponent with 0 '000' */ + PUT_CHAR('0', p); PUT_CHAR('0', p); + } else if (j < 99) + PUT_CHAR('0', p); + while (*tmp) { /* the exponent */ + PUT_CHAR(*tmp, p); + tmp++; + } + PAD_LEFT(p); +} + +/* initialize the conversion specifiers */ +PRIVATE void +#ifdef __STDC__ +conv_flag(char * s, struct DATA * p) +#else +conv_flag(s, p) +char * s; +struct DATA * p; +#endif +{ + char number[MAX_FIELD/2]; + int i; + + p->precision = p->width = NOT_FOUND; + p->star_w = p->star_p = NOT_FOUND; + p->square = p->space = NOT_FOUND; + p->a_long = p->justify = NOT_FOUND; + p->pad = ' '; + + for(;s && *s ;s++) { + switch(*s) { + case ' ': p->space = FOUND; break; + case '#': p->square = FOUND; break; + case '*': if (p->width == NOT_FOUND) + p->width = p->star_w = FOUND; + else + p->precision = p->star_p = FOUND; + break; + case '+': p->justify = RIGHT; break; + case '-': p->justify = LEFT; break; + case '.': if (p->width == NOT_FOUND) + p->width = 0; + break; + case '0': p->pad = '0'; break; + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': /* gob all the digits */ + for (i = 0; isdigit(*s); i++, s++) + if (i < MAX_FIELD/2 - 1) + number[i] = *s; + number[i] = '\0'; + if (p->width == NOT_FOUND) + p->width = atoi(number); + else + p->precision = atoi(number); + s--; /* went to far go back */ + break; + } + } +} + +PUBLIC int +#ifdef __STDC__ +vsnprintf(char *string, size_t length, const char * format, va_list args) +#else +vsnprintf(string, length, format, args) +char *string; +size_t length; +char * format; +va_list args; +#endif +{ + struct DATA data; + char conv_field[MAX_FIELD]; + double d; /* temporary holder */ + int state; + int i; + + data.length = length - 1; /* leave room for '\0' */ + data.holder = string; + data.pf = format; + data.counter = 0; + + +/* sanity check, the string must be > 1 */ + if (length < 1) + return -1; + + + for (; *data.pf && (data.counter < data.length); data.pf++) { + if ( *data.pf == '%' ) { /* we got a magic % cookie */ + conv_flag((char *)0, &data); /* initialise format flags */ + for (state = 1; *data.pf && state;) { + switch (*(++data.pf)) { + case '\0': /* a NULL here ? ? bail out */ + *data.holder = '\0'; + return data.counter; + break; + case 'f': /* float, double */ + STAR_ARGS(&data); + d = va_arg(args, double); + floating(&data, d); + state = 0; + break; + case 'g': + case 'G': + STAR_ARGS(&data); + DEF_PREC(&data); + d = va_arg(args, double); + i = log_10(d); + /* + * for '%g|%G' ANSI: use f if exponent + * is in the range or [-4,p] exclusively + * else use %e|%E + */ + if (-4 < i && i < data.precision) + floating(&data, d); + else + exponent(&data, d); + state = 0; + break; + case 'e': + case 'E': /* Exponent double */ + STAR_ARGS(&data); + d = va_arg(args, double); + exponent(&data, d); + state = 0; + break; + case 'u': + case 'd': /* decimal */ + STAR_ARGS(&data); + if (data.a_long == FOUND) + d = va_arg(args, long); + else + d = va_arg(args, int); + decimal(&data, d); + state = 0; + break; + case 'o': /* octal */ + STAR_ARGS(&data); + if (data.a_long == FOUND) + d = va_arg(args, long); + else + d = va_arg(args, int); + octal(&data, d); + state = 0; + break; + case 'x': + case 'X': /* hexadecimal */ + STAR_ARGS(&data); + if (data.a_long == FOUND) + d = va_arg(args, long); + else + d = va_arg(args, int); + hexa(&data, d); + state = 0; + break; + case 'c': /* character */ + d = va_arg(args, int); + PUT_CHAR(d, &data); + state = 0; + break; + case 's': /* string */ + STAR_ARGS(&data); + strings(&data, va_arg(args, char *)); + state = 0; + break; + case 'n': + *(va_arg(args, int *)) = data.counter; /* what's the count ? */ + state = 0; + break; + case 'l': + data.a_long = FOUND; + break; + case 'h': + break; + case '%': /* nothing just % */ + PUT_CHAR('%', &data); + state = 0; + break; + case '#': case ' ': case '+': case '*': + case '-': case '.': case '0': case '1': + case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + /* initialize width and precision */ + for (i = 0; isflag(*data.pf); i++, data.pf++) + if (i < MAX_FIELD - 1) + conv_field[i] = *data.pf; + conv_field[i] = '\0'; + conv_flag(conv_field, &data); + data.pf--; /* went to far go back */ + break; + default: + /* is this an error ? maybe bail out */ + state = 0; + break; + } /* end switch */ + } /* end of for state */ + } else { /* not % */ + PUT_CHAR(*data.pf, &data); /* add the char the string */ + } + } + + *data.holder = '\0'; /* the end ye ! */ + + return data.counter; +} + +#ifndef HAVE_SNPRINTF + +PUBLIC int +#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__ +snprintf(char *string, size_t length, const char * format, ...) +#else +snprintf(string, length, format, va_alist) +char *string; +size_t length; +char * format; +va_dcl +#endif +{ + int rval; + va_list args; + +#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__ + va_start(args, format); +#else + va_start(args); +#endif + + rval = vsnprintf (string, length, format, args); + + va_end(args); + + return rval; +} + +#endif /* HAVE_SNPRINTF */ + + +#ifdef DRIVER + +#include + +/* set of small tests for snprintf() */ +void main() +{ + char holder[100]; + int i; + +/* + printf("Suite of test for snprintf:\n"); + printf("a_format\n"); + printf("printf() format\n"); + printf("snprintf() format\n\n"); +*/ +/* Checking the field widths */ + + printf("/%%d/, 336\n"); + snprintf(holder, sizeof holder, "/%d/\n", 336); + printf("/%d/\n", 336); + printf("%s\n", holder); + + printf("/%%2d/, 336\n"); + snprintf(holder, sizeof holder, "/%2d/\n", 336); + printf("/%2d/\n", 336); + printf("%s\n", holder); + + printf("/%%10d/, 336\n"); + snprintf(holder, sizeof holder, "/%10d/\n", 336); + printf("/%10d/\n", 336); + printf("%s\n", holder); + + printf("/%%-10d/, 336\n"); + snprintf(holder, sizeof holder, "/%-10d/\n", 336); + printf("/%-10d/\n", 336); + printf("%s\n", holder); + + +/* floating points */ + + printf("/%%f/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%f/\n", 1234.56); + printf("/%f/\n", 1234.56); + printf("%s\n", holder); + + printf("/%%e/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%e/\n", 1234.56); + printf("/%e/\n", 1234.56); + printf("%s\n", holder); + + printf("/%%4.2f/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56); + printf("/%4.2f/\n", 1234.56); + printf("%s\n", holder); + + printf("/%%3.1f/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56); + printf("/%3.1f/\n", 1234.56); + printf("%s\n", holder); + + printf("/%%10.3f/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56); + printf("/%10.3f/\n", 1234.56); + printf("%s\n", holder); + + printf("/%%10.3e/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56); + printf("/%10.3e/\n", 1234.56); + printf("%s\n", holder); + + printf("/%%+4.2f/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56); + printf("/%+4.2f/\n", 1234.56); + printf("%s\n", holder); + + printf("/%%010.2f/, 1234.56\n"); + snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56); + printf("/%010.2f/\n", 1234.56); + printf("%s\n", holder); + +#define BLURB "Outstanding acting !" +/* strings precisions */ + + printf("/%%2s/, \"%s\"\n", BLURB); + snprintf(holder, sizeof holder, "/%2s/\n", BLURB); + printf("/%2s/\n", BLURB); + printf("%s\n", holder); + + printf("/%%22s/ %s\n", BLURB); + snprintf(holder, sizeof holder, "/%22s/\n", BLURB); + printf("/%22s/\n", BLURB); + printf("%s\n", holder); + + printf("/%%22.5s/ %s\n", BLURB); + snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB); + printf("/%22.5s/\n", BLURB); + printf("%s\n", holder); + + printf("/%%-22.5s/ %s\n", BLURB); + snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB); + printf("/%-22.5s/\n", BLURB); + printf("%s\n", holder); + +/* see some flags */ + + printf("%%x %%X %%#x, 31, 31, 31\n"); + snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31); + printf("%x %X %#x\n", 31, 31, 31); + printf("%s\n", holder); + + printf("**%%d**%% d**%% d**, 42, 42, -42\n"); + snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42); + printf("**%d**% d**% d**\n", 42, 42, -42); + printf("%s\n", holder); + +/* other flags */ + + printf("/%%g/, 31.4\n"); + snprintf(holder, sizeof holder, "/%g/\n", 31.4); + printf("/%g/\n", 31.4); + printf("%s\n", holder); + + printf("/%%.6g/, 31.4\n"); + snprintf(holder, sizeof holder, "/%.6g/\n", 31.4); + printf("/%.6g/\n", 31.4); + printf("%s\n", holder); + + printf("/%%.1G/, 31.4\n"); + snprintf(holder, sizeof holder, "/%.1G/\n", 31.4); + printf("/%.1G/\n", 31.4); + printf("%s\n", holder); + + printf("abc%%n\n"); + printf("abc%n", &i); printf("%d\n", i); + snprintf(holder, sizeof holder, "abc%n", &i); + printf("%s", holder); printf("%d\n\n", i); + + printf("%%*.*s --> 10.10\n"); + snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB); + printf("%*.*s\n", 10, 10, BLURB); + printf("%s\n", holder); + + printf("%%%%%%%%\n"); + snprintf(holder, sizeof holder, "%%%%\n"); + printf("%%%%\n"); + printf("%s\n", holder); + +#define BIG "Hello this is a too big string for the buffer" +/* printf("A buffer to small of 10, trying to put this:\n");*/ + printf("<%%>, %s\n", BIG); + i = snprintf(holder, 10, "%s\n", BIG); + printf("<%s>\n", BIG); + printf("<%s>\n", holder); +} +#endif diff --git a/snprintf.h b/snprintf.h new file mode 100644 index 0000000000..245739541e --- /dev/null +++ b/snprintf.h @@ -0,0 +1,232 @@ +/* + Unix snprintf implementation. + Version 1.2 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + It can be redistribute also under the terms of GNU Library General + Public Lincense. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Revision History: + + 1.2: + * put under LGPL. + 1.1: + * added changes from Miles Bader + * corrected a bug with %f + * added support for %#g + * added more comments :-) + 1.0: + * supporting must ANSI syntaxic_sugars(see below) + 0.0: + * suppot %s %c %d + + it understands: + Integer: + %lu %lu %u + %hd %ld %d decimal + %ho %lo %o octal + %hx %lx %x %X hexa + Floating points: + %g %G %e %E %f double + Strings: + %s %c string + %% % + + Formating conversion flags: + - justify left + + Justify right or put a plus if number + # prefix 0x, 0X for hexa and 0 for octal + * precision/witdth is specify as an (int) in the arguments + ' ' leave a blank for number with no sign + l the later should be a long + h the later should be a short + +format: + snprintf(holder, sizeof_holder, format, ...) + +Return values: + (sizeof_holder - 1) + + + THANKS(for the patches and ideas): + Miles Bader + Cyrille Rustom + Jacek Slabocewiz + Mike Parker(mouse) + +Alain Magloire: alainm@rcsm.ee.mcgill.ca +*/ + +#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__ +#include +#else +#include +#endif + +#include /* for atoi() */ +#include + + +/* + * For the FLOATING POINT FORMAT : + * the challenge was finding a way to + * manipulate the Real numbers without having + * to resort to mathematical function(it + * would require to link with -lm) and not + * going down to the bit pattern(not portable) + * + * so a number, a real is: + + real = integral + fraction + + integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0 + fraction = b(1)*10^-1 + b(2)*10^-2 + ... + + where: + 0 <= a(i) => 9 + 0 <= b(i) => 9 + + from then it was simple math + */ + +/* + * size of the buffer for the integral part + * and the fraction part + */ +#define MAX_INT 99 + 1 /* 1 for the null */ +#define MAX_FRACT 29 + 1 + +/* + * numtoa() uses PRIVATE buffers to store the results, + * So this function is not reentrant + */ +#define itoa(n) numtoa(n, 10, 0, (char **)0) +#define otoa(n) numtoa(n, 8, 0, (char **)0) +#define htoa(n) numtoa(n, 16, 0, (char **)0) +#define dtoa(n, p, f) numtoa(n, 10, p, f) + +#define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;} + +/* this struct holds everything we need */ +struct DATA { + int length; + char *holder; + int counter; +#ifdef __STDC__ + const char *pf; +#else + char *pf; +#endif +/* FLAGS */ + int width, precision; + int justify; char pad; + int square, space, star_w, star_p, a_long ; +}; + +#define PRIVATE static +#define PUBLIC +/* signature of the functions */ +#ifdef __STDC__ +/* the floating point stuff */ + PRIVATE double pow_10(int); + PRIVATE int log_10(double); + PRIVATE double integral(double, double *); + PRIVATE char * numtoa(double, int, int, char **); + +/* for the format */ + PRIVATE void conv_flag(char *, struct DATA *); + PRIVATE void floating(struct DATA *, double); + PRIVATE void exponent(struct DATA *, double); + PRIVATE void decimal(struct DATA *, double); + PRIVATE void octal(struct DATA *, double); + PRIVATE void hexa(struct DATA *, double); + PRIVATE void strings(struct DATA *, char *); + +#else +/* the floating point stuff */ + PRIVATE double pow_10(); + PRIVATE int log_10(); + PRIVATE double integral(); + PRIVATE char * numtoa(); + +/* for the format */ + PRIVATE void conv_flag(); + PRIVATE void floating(); + PRIVATE void exponent(); + PRIVATE void decimal(); + PRIVATE void octal(); + PRIVATE void hexa(); + PRIVATE void strings(); +#endif + +/* those are defines specific to snprintf to hopefully + * make the code clearer :-) + */ +#define RIGHT 1 +#define LEFT 0 +#define NOT_FOUND -1 +#define FOUND 1 +#define MAX_FIELD 15 + +/* the conversion flags */ +#define isflag(c) ((c) == '#' || (c) == ' ' || \ + (c) == '*' || (c) == '+' || \ + (c) == '-' || (c) == '.' || \ + isdigit(c)) + +/* round off to the precision */ +#define ROUND(d, p) \ + (d < 0.) ? \ + d - pow_10(-(p)->precision) * 0.5 : \ + d + pow_10(-(p)->precision) * 0.5 + +/* set default precision */ +#define DEF_PREC(p) \ + if ((p)->precision == NOT_FOUND) \ + (p)->precision = 6 + +/* put a char */ +#define PUT_CHAR(c, p) \ + if ((p)->counter < (p)->length) { \ + *(p)->holder++ = (c); \ + (p)->counter++; \ + } + +#define PUT_PLUS(d, p) \ + if ((d) > 0. && (p)->justify == RIGHT) \ + PUT_CHAR('+', p) + +#define PUT_SPACE(d, p) \ + if ((p)->space == FOUND && (d) > 0.) \ + PUT_CHAR(' ', p) + +/* pad right */ +#define PAD_RIGHT(p) \ + if ((p)->width > 0 && (p)->justify != LEFT) \ + for (; (p)->width > 0; (p)->width--) \ + PUT_CHAR((p)->pad, p) + +/* pad left */ +#define PAD_LEFT(p) \ + if ((p)->width > 0 && (p)->justify == LEFT) \ + for (; (p)->width > 0; (p)->width--) \ + PUT_CHAR((p)->pad, p) + +/* if width and prec. in the args */ +#define STAR_ARGS(p) \ + if ((p)->star_w == FOUND) \ + (p)->width = va_arg(args, int); \ + if ((p)->star_p == FOUND) \ + (p)->precision = va_arg(args, int) diff --git a/stamp-h.in b/stamp-h.in new file mode 100644 index 0000000000..9788f70238 --- /dev/null +++ b/stamp-h.in @@ -0,0 +1 @@ +timestamp diff --git a/util.c b/util.c new file mode 100644 index 0000000000..50d38a9726 --- /dev/null +++ b/util.c @@ -0,0 +1,125 @@ +/* util.c + * Utility routines + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include + +#include + +#include "util.h" + +const gchar *bm_key = "button mask"; + +/* Simple dialog function - Displays a dialog box with the supplied message + * text. + * + * Args: + * type : One of ESD_TYPE_*. Currently ignored. + * btn_mask : The address of a gint. The value passed in determines if + * the 'Cancel' button is displayed. The button pressed by the + * user is passed back. + * message : The text displayed in the dialog. + * + * To do: + * - Switch to variable args + */ +void +simple_dialog(gint type, gint *btn_mask, gchar *message) { + GtkWidget *win, *main_vb, *top_hb, *type_pm, *msg_label, + *bbox, *ok_btn, *cancel_btn; + GdkPixmap *pixmap; + GdkBitmap *mask; + GtkStyle *style; + GdkColormap *cmap; + + /* Main window */ + win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_border_width(GTK_CONTAINER(win), 7); + gtk_window_set_title(GTK_WINDOW(win), "Ethereal: Warning"); + gtk_object_set_data(GTK_OBJECT(win), bm_key, btn_mask); + + /* Container for our rows */ + main_vb = gtk_vbox_new(FALSE, 5); + gtk_container_border_width(GTK_CONTAINER(main_vb), 5); + gtk_container_add(GTK_CONTAINER(win), main_vb); + gtk_widget_show(main_vb); + + /* Top row: Icon and message text */ + top_hb = gtk_hbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(main_vb), top_hb); + gtk_widget_show(top_hb); + + style = gtk_widget_get_style(win); + cmap = gdk_colormap_get_system(); + pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL, cmap, &mask, + &style->bg[GTK_STATE_NORMAL], icon_excl_xpm); + type_pm = gtk_pixmap_new(pixmap, mask); + gtk_container_add(GTK_CONTAINER(top_hb), type_pm); + gtk_widget_show(type_pm); + + msg_label = gtk_label_new(message); + gtk_label_set_justify(GTK_LABEL(msg_label), GTK_JUSTIFY_FILL); + gtk_container_add(GTK_CONTAINER(top_hb), msg_label); + gtk_widget_show(msg_label); + + /* Button row */ + bbox = gtk_hbutton_box_new(); + gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END); + gtk_container_add(GTK_CONTAINER(main_vb), bbox); + gtk_widget_show(bbox); + + ok_btn = gtk_button_new_with_label ("OK"); + gtk_signal_connect_object(GTK_OBJECT(ok_btn), "clicked", + GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT (win)); + gtk_container_add(GTK_CONTAINER(bbox), ok_btn); + GTK_WIDGET_SET_FLAGS(ok_btn, GTK_CAN_DEFAULT); + gtk_widget_grab_default(ok_btn); + gtk_widget_show(ok_btn); + + if (btn_mask && *btn_mask == ESD_BTN_CANCEL) { + cancel_btn = gtk_button_new_with_label("Cancel"); + gtk_signal_connect(GTK_OBJECT(cancel_btn), "clicked", + GTK_SIGNAL_FUNC(simple_dialog_cancel_cb), (gpointer) win); + gtk_container_add(GTK_CONTAINER(bbox), cancel_btn); + gtk_widget_show(cancel_btn); + } + + if (btn_mask) + *btn_mask = ESD_BTN_OK; + + gtk_widget_show(win); +} + +void +simple_dialog_cancel_cb(GtkWidget *w, gpointer win) { + gint *btn_mask = (gint *) gtk_object_get_data(win, bm_key); + + if (btn_mask) + *btn_mask = ESD_BTN_CANCEL; + gtk_widget_destroy(GTK_WIDGET(win)); +} diff --git a/util.h b/util.h new file mode 100644 index 0000000000..40425c7af3 --- /dev/null +++ b/util.h @@ -0,0 +1,49 @@ +/* util.h + * Utility definitions + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __UTIL_H__ +#define __UTIL_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "image/icon-excl.xpm" + +/* Dialog type. Currently, only ESD_TYPE_WARN is supported. */ +#define ESD_TYPE_INFO 0 +#define ESD_TYPE_WARN 1 +#define ESD_TYPE_CRIT 2 + +/* Which buttons to display. */ +#define ESD_BTN_OK 0 +#define ESD_BTN_CANCEL 1 + +void simple_dialog(gint, gint *, gchar *); +void simple_dialog_cancel_cb(GtkWidget *, gpointer); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __UTIL_H__ */ -- cgit v1.2.3