aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS36
-rw-r--r--COPYING482
-rw-r--r--ChangeLog0
-rw-r--r--INSTALL182
-rw-r--r--Makefile.am69
-rw-r--r--Makefile.in475
-rw-r--r--NEWS118
-rw-r--r--README112
-rw-r--r--acconfig.h5
-rw-r--r--aclocal.m4335
-rw-r--r--capture.c501
-rw-r--r--capture.h49
-rw-r--r--config.h24
-rw-r--r--config.h.in23
-rwxr-xr-xconfigure2075
-rw-r--r--configure.in51
-rw-r--r--doc/Makefile5
-rw-r--r--doc/ethereal.pod233
-rw-r--r--ethereal.1427
-rw-r--r--ethereal.c440
-rw-r--r--ethereal.h79
-rw-r--r--ethertype.c107
-rw-r--r--etypes.h67
-rw-r--r--file.c356
-rw-r--r--file.h99
-rw-r--r--filter.c472
-rw-r--r--filter.h55
-rw-r--r--image/icon-excl.xpm88
-rwxr-xr-xinstall-sh250
-rw-r--r--menu.c215
-rw-r--r--menu.h41
-rwxr-xr-xmissing188
-rwxr-xr-xmkinstalldirs40
-rw-r--r--packet-arp.c122
-rw-r--r--packet-bootp.c487
-rw-r--r--packet-data.c51
-rw-r--r--packet-dns.c442
-rw-r--r--packet-eth.c125
-rw-r--r--packet-ip.c319
-rw-r--r--packet-ipv6.c105
-rw-r--r--packet-ipv6.h8
-rw-r--r--packet-ipx.c492
-rw-r--r--packet-llc.c163
-rw-r--r--packet-lpd.c154
-rw-r--r--packet-ospf.c550
-rw-r--r--packet-ospf.h127
-rw-r--r--packet-ppp.c79
-rw-r--r--packet-raw.c72
-rw-r--r--packet-rip.c144
-rw-r--r--packet-rip.h23
-rw-r--r--packet-tcp.c116
-rw-r--r--packet-tr.c253
-rw-r--r--packet-trmac.c322
-rw-r--r--packet-udp.c92
-rw-r--r--packet.c216
-rw-r--r--packet.h354
-rw-r--r--print.c509
-rw-r--r--print.h47
-rw-r--r--print.ps100
-rw-r--r--ps.c87
-rw-r--r--ps.h35
-rw-r--r--rdps.c185
-rw-r--r--resolv.c269
-rw-r--r--resolv.h39
-rw-r--r--snprintf.c822
-rw-r--r--snprintf.h232
-rw-r--r--stamp-h.in1
-rw-r--r--util.c125
-rw-r--r--util.h49
69 files changed, 15015 insertions, 0 deletions
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 <gerald@zing.org>
+
+
+Contributors
+------------
+Gilbert Ramirez Jr. <gram@verdict.uthscsa.edu> {
+ /* add your info here */
+}
+
+Hannes R. Boehm <hannes@boehm.org> {
+ http://hannes.boehm.org/
+
+ OSPFv2
+ RIPv1, RIPv2
+ started IPv6 support
+}
+
+Mike Hall <mlh@io.com>{
+ /* add your info here */
+}
+
+Bobo Rajec <bobo@bsp-consulting.sk> {
+ /* add your info here */
+}
+
+Laurent Deniel <deniel@worldnet.fr> {
+ /* add your info here */
+}
+
+Alain Magloire <alainm@rcsm.ece.mcgill.ca> was kind enough to
+give his permission to use his version of snprintf.c.
+
+Dan Lasley <dlasley@promus.com> 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.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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
--- /dev/null
+++ b/ChangeLog
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 <gtk/gtk.h>
+#include <stdio.h>
+
+int
+main ()
+{
+ int major, minor, micro;
+
+ system ("touch conf.gtktest");
+
+ if (sscanf("$min_gtk_version", "%d.%d.%d", &major, &minor, &micro) != 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 <gtk/gtk.h>
+#include <stdio.h>
+], [ 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 <sys/types.h>
+# include <sys/socket.h>],
+ [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>>, <<[^ ]>>, <<>>), <<>>,
+<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
+<<am_indx=1
+for am_file in <<$1>>; 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 <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+#include <pcap.h>
+
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+
+#ifdef HAVE_SYS_SOCKIO_H
+# include <sys/sockio.h>
+#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 <gerald@zing.org>
+ * 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 <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define if you have the <sys/sockio.h> header file. */
+/* #undef HAVE_SYS_SOCKIO_H */
+
+/* Define if you have the <sys/types.h> 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 <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define if you have the <sys/types.h> 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 <<EOF
+#define PACKAGE "$PACKAGE"
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION "$VERSION"
+EOF
+
+
+
+missing_dir=`cd $ac_aux_dir && pwd`
+echo $ac_n "checking for working aclocal""... $ac_c" 1>&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 <<EOF
+#line 871 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+if { (eval echo configure:875: \"$ac_link\") 1>&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 <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:909: \"$ac_try\") 1>&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 <<EOF
+#line 1054 "configure"
+#include "confdefs.h"
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+
+int
+main ()
+{
+ int major, minor, micro;
+
+ system ("touch conf.gtktest");
+
+ if (sscanf("$min_gtk_version", "%d.%d.%d", &major, &minor, &micro) != 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 <<EOF
+#line 1151 "configure"
+#include "confdefs.h"
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+
+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 <<EOF
+#line 1217 "configure"
+#include "confdefs.h"
+#include <assert.h>
+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 <<EOF
+#line 1234 "configure"
+#include "confdefs.h"
+#include <assert.h>
+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
+#line 1269 "configure"
+#include "confdefs.h"
+#include <pcap.h>
+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
+#line 1303 "configure"
+#include "confdefs.h"
+#include <net/bpf.h>
+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 <<EOF
+#line 1339 "configure"
+#include "confdefs.h"
+/* 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 pcap_open_offline();
+
+int main() {
+pcap_open_offline()
+; return 0; }
+EOF
+if { (eval echo configure:1350: \"$ac_link\") 1>&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 <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lpcap $LIBS"
+
+else
+ echo "$ac_t""no" 1>&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
+#line 1391 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&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 <<EOF
+#line 1433 "configure"
+#include "confdefs.h"
+
+# include <sys/types.h>
+# include <sys/socket.h>
+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 <<EOF
+#line 1471 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+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 <<EOF
+#line 1486 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+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 <<EOF
+#line 1517 "configure"
+#include "confdefs.h"
+main () {
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long l;
+ char c[sizeof (long)];
+ } u;
+ u.l = 1;
+ exit (u.c[sizeof (long) - 1] == 1);
+}
+EOF
+if { (eval echo configure:1530: \"$ac_link\") 1>&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 <<EOF
+#line 1562 "configure"
+#include "confdefs.h"
+#include <sgtty.h>
+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 <<EOF
+#line 1580 "configure"
+#include "confdefs.h"
+#include <termio.h>
+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 <<EOF
+#line 1607 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char socket(); below. */
+#include <assert.h>
+/* 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 <<EOF
+#line 1658 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char snprintf(); below. */
+#include <assert.h>
+/* 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 <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/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 <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > 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 <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $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 <<EOF
+ CONFIG_HEADERS="config.h"
+EOF
+cat >> $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 <<CEOF' >> $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 <<EOF
+
+
+EOF
+cat >> $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<ethereal>
+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<Ethereal> is a network protocol analyzer based on the B<GTK+> GUI toolkit. It lets
+you interactively browse packet data from a live network or from a B<pcap>
+/ B<tcpdump()> 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<netstat -i>" or "B<ifconfig -a>".
+
+=item -P
+
+Sets the initial height of the packet list (top) pane
+
+=item -r
+
+Read packet data from I<file>. Currently, B<Ethereal> only understands
+B<pcap> / B<tcpdump> formatted files.
+
+=item -s
+
+The default snapshot length to use when capturing live data. No more than
+I<snaplen> 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<Edit:Menu Options> 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<protocol tree> 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<protocol tree> highlights the appropriate bytes
+in this section.
+
+=item Printer Options
+
+The I<Printer Options> dialog lets you select the output format of packets
+printed using the I<File:Print Packet> 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<Command:> text entry
+box is the command to send files to (usually B<lpr>), and the I<File:>
+entry box lets you enter the name of the file you wish to save to.
+Additinally, you can select the I<File:> button to browse the file system
+for a particular save file.
+
+=item Capture Preferences
+
+The I<Capture Preferences> dialog lets you specify various parameters for
+capturing live packet data.
+
+The I<Interface:> entry box lets you specify the interface from which to
+capture packet data. The I<Count:> entry specifies the number of packets
+to capture. Entering 0 will capture packets indefinitely. The I<File:>
+entry specifies the file to save to, as in the I<Printer Options> 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<Capture length> entry.
+
+=item Filters
+
+The I<Filters> dialog lets you create and modify filters, and set the
+default filter to use when capturing data or opening a capture file.
+
+The I<Filter name> entry specifies a descriptive name for a filter, e.g.
+B<Web and DNS traffic>. The I<Filter string> entry is the text that
+actually describes the filtering action to take. It must have the same
+format as B<tcpdump> 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<tcpdump(1)>, L<pcap(3)>
+
+=head1 NOTES
+
+The latest version of B<ethereal> can be found at
+B<http://ethereal.zing.org>.
+
+=head1 AUTHORS
+
+ Original Author
+ -------- ------
+ Gerald Combs <gerald@zing.org>
+
+
+ Contributors
+ ------------
+ Gilbert Ramirez Jr. <gram@verdict.uthscsa.edu>
+ Hannes R. Boehm <hannes@boehm.org>
+ Mike Hall <mlh@io.com>
+ cpg <cpg@rocketmail.com>
+
+
+Theo de Raadt <deraadt@cvs.openbsd.org> was kind enough to give his
+permission to use his version of snprintf.c.
+
+Dan Lasley <dlasley@promus.com> 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 <gerald@zing.org>
+.Ve
+.Vb 6
+\& Contributors
+\& ------------
+\& Gilbert Ramirez Jr. <gram@verdict.uthscsa.edu>
+\& Hannes R. Boehm <hannes@boehm.org>
+\& Mike Hall <mlh@io.com>
+\& cpg <cpg@rocketmail.com>
+.Ve
+Theo de Raadt <deraadt@cvs.openbsd.org> was kind enough to give his
+permission to use his version of snprintf.c.
+.Sp
+Dan Lasley <dlasley@promus.com> 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 <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+
+#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("<Main>/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 <gerald@zing.org>
+ * 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 <gram@verdict.uthscsa.edu>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+
+#include <stdio.h>
+
+#include <pcap.h>
+
+#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 <gerald@zing.org>
+ * 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 <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+#include <pcap.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#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("<Main>/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("<Main>/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 <gerald@zing.org>
+ * 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 <sys/types.h>
+#include <sys/time.h>
+
+#include <pcap.h>
+
+/* 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 <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#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 <gerald@zing.org>
+ * 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 <gerald@zing.org>
+ * 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 <glib.h>
+
+#include <gtk/gtk.h>
+#include <pcap.h>
+
+#include <strings.h>
+
+#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[] =
+{
+ {"<Main>/File/Open", "<control>O", file_open_cmd_cb, NULL},
+ {"<Main>/File/Close", "<control>W", file_close_cmd_cb, NULL},
+ {"<Main>/File/Save", "<control>S", NULL, NULL},
+ {"<Main>/File/Save as", NULL, NULL, NULL},
+ {"<Main>/File/<separator>", NULL, NULL, NULL},
+ {"<Main>/File/Print Packet", "<control>P", file_print_cmd_cb, NULL},
+ {"<Main>/File/<separator>", NULL, NULL, NULL},
+ {"<Main>/File/Quit", "<control>Q", file_quit_cmd_cb, NULL},
+ {"<Main>/Edit/Cut", "<control>X", NULL, NULL},
+ {"<Main>/Edit/Copy", "<control>C", NULL, NULL},
+ {"<Main>/Edit/Paste", "<control>V", NULL, NULL},
+ {"<Main>/Edit/<separator>", NULL, NULL, NULL},
+ {"<Main>/Edit/Find", "<control>F", NULL, NULL},
+ {"<Main>/Edit/<separator>", NULL, NULL, NULL},
+ {"<Main>/Edit/Printer Options", NULL, printer_opts_cb, NULL},
+ {"<Main>/Tools/Capture", "<control>K", capture_prep_cb, NULL},
+ {"<Main>/Tools/Filter", NULL, filter_sel_cb, NULL},
+ {"<Main>/Tools/Graph", NULL, NULL, NULL},
+ {"<Main>/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], "<Main>");
+ menus_create(menu_items, nmenu_items);
+
+ set_menu_sensitivity("<Main>/File/Close", FALSE);
+ set_menu_sensitivity("<Main>/File/Save", FALSE);
+ set_menu_sensitivity("<Main>/File/Save as", FALSE);
+ set_menu_sensitivity("<Main>/Edit/Cut", FALSE);
+ set_menu_sensitivity("<Main>/Edit/Copy", FALSE);
+ set_menu_sensitivity("<Main>/Edit/Paste", FALSE);
+ set_menu_sensitivity("<Main>/Edit/Find", FALSE);
+ set_menu_sensitivity("<Main>/Tools/Graph", FALSE);
+ set_menu_sensitivity("<Main>/Help/About Ethereal", FALSE);
+ if ((mp = gtk_menu_factory_find(factory, "<Main>/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, "<control>");
+ if (modifiers & GDK_SHIFT_MASK)
+ strcat(accel, "<shift>");
+ if (modifiers & GDK_MOD1_MASK)
+ strcat(accel, "<alt>");
+
+ 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 <gerald@zing.org>
+ * 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 <pinard@iro.umontreal.ca>, 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 <friedman@prep.ai.mit.edu>
+# 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 <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+#include <pcap.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#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 <gram@verdict.uthscsa.edu>
+ *
+ * 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 <gerald@unicom.net>
+ * 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 <gtk/gtk.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <pcap.h>
+
+#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 <gram@verdict.uthscsa.edu>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@unicom.net>
+ * 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 <gtk/gtk.h>
+#include <pcap.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#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 <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+#include <pcap.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#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 <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+
+#include <stdio.h>
+
+#include <pcap.h>
+
+#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 <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+#include <pcap.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#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 <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+#include <pcap.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#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 <gram@verdict.uthscsa.edu>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@unicom.net>
+ * 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 <gtk/gtk.h>
+#include <pcap.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#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 <gram@verdict.uthscsa.edu>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@unicom.net>
+ * 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 <pcap.h>
+
+#include <gtk/gtk.h>
+
+#include <stdio.h>
+
+#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 <gram@verdict.uthscsa.edu>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@unicom.net>
+ * 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 <gtk/gtk.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <pcap.h>
+
+#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 <hannes@boehm.org>
+ *
+ * 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 <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#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 <gerald@zing.org>
+ *
+ * This file created and by Mike Hall <mlh@io.com>
+ * 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 <gtk/gtk.h>
+#include <stdio.h>
+#include <pcap.h>
+
+#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 <gerald@zing.org>
+ *
+ * This file created and by Mike Hall <mlh@io.com>
+ * 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 <gtk/gtk.h>
+#include <stdio.h>
+#include <pcap.h>
+
+#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 <hannes@boehm.org>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#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 <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#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] = "<None>";
+ 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 <gram@verdict.uthscsa.edu>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@unicom.net>
+ * 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 <gtk/gtk.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <pcap.h>
+
+#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 <gram@verdict.uthscsa.edu>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@unicom.net>
+ * 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 <pcap.h>
+
+#include <gtk/gtk.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#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 <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#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 <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#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 <gerald@zing.org>
+ * 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 <gram@verdict.uthscsa.edu>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#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 <DLASLEY@PROMUS.com>, 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<length; i++) {
+ c = *cp++;
+ line[j++] = binhex[c>>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<length; i++) {
+ c = *cp++;
+ line[j++] = binhex[c>>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 <gram@verdict.uthscsa.edu>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * 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 <gerald@zing.org>
+% 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 <stdio.h>
+
+#include <ps.h>
+
+/* 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 <gerald@zing.org>\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 <gram@verdict.uthscsa.edu>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * 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 <gerald@zing.org>
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <stdio.h>\n\n"
+ "#include <ps.h>\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 <deniel@worldnet.fr>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * 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 <gtk/gtk.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <netdb.h>
+#include <signal.h>
+#include <sys/socket.h>
+
+#ifdef AVOID_DNS_TIMEOUT
+# include <setjmp.h>
+#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 <deniel@worldnet.fr>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * 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 <config.h>
+#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 <stdio.h>
+
+/* 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 <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include <stdlib.h> /* for atoi() */
+#include <ctype.h>
+
+
+/*
+ * 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 <gerald@zing.org>
+ * 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 <glib.h>
+
+#include <gtk/gtk.h>
+
+#include <strings.h>
+
+#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 <gerald@zing.org>
+ * 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__ */