diff options
author | Gilbert Ramirez <gram@alumni.rice.edu> | 2000-11-09 10:04:48 +0000 |
---|---|---|
committer | Gilbert Ramirez <gram@alumni.rice.edu> | 2000-11-09 10:04:48 +0000 |
commit | 2cb9d546206e31f30caa3fbfbfe69f3775fb48d2 (patch) | |
tree | d532574d587cbcfbae7a0dc66a749c0ee1a7bd3c | |
parent | f832ad5f8b95a04c107ca793171a351b5991332d (diff) |
Add MGCP dissector plugin from Ed Warnicke <hagbard@physics.rutgers.edu>.
svn path=/trunk/; revision=2588
-rw-r--r-- | AUTHORS | 4 | ||||
-rw-r--r-- | Makefile.am | 12 | ||||
-rw-r--r-- | configure.in | 6 | ||||
-rw-r--r-- | doc/ethereal.pod.template | 1 | ||||
-rw-r--r-- | plugins/Makefile.am | 4 | ||||
-rw-r--r-- | plugins/mgcp/AUTHORS | 3 | ||||
-rw-r--r-- | plugins/mgcp/COPYING | 340 | ||||
-rw-r--r-- | plugins/mgcp/ChangeLog | 0 | ||||
-rw-r--r-- | plugins/mgcp/INSTALL | 0 | ||||
-rw-r--r-- | plugins/mgcp/Makefile.am | 44 | ||||
-rw-r--r-- | plugins/mgcp/NEWS | 0 | ||||
-rw-r--r-- | plugins/mgcp/moduleinfo.h | 17 | ||||
-rw-r--r-- | plugins/mgcp/packet-mgcp.c | 1125 |
13 files changed, 1548 insertions, 8 deletions
@@ -430,6 +430,10 @@ Craig Rodrigues <rodrigc@mediaone.net> { GIOP 1.2 support and other GIOP enhancements } +Ed Warnicke <hagbard@physics.rutgers.edu> { + MGCP dissector plugin +} + Alain Magloire <alainm@rcsm.ece.mcgill.ca> was kind enough to give his permission to use his version of snprintf.c. diff --git a/Makefile.am b/Makefile.am index d733c723df..8b5b516708 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am # Automake file for Ethereal # -# $Id: Makefile.am,v 1.243 2000/11/06 14:14:01 nneul Exp $ +# $Id: Makefile.am,v 1.244 2000/11/09 10:04:46 gram Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@zing.org> @@ -348,7 +348,8 @@ ethereal_additional_libs = wiretap/libwiretap.a gtk/libui.a epan/libethereal.a ethereal_DEPENDENCIES = \ $(ethereal_optional_objects) \ $(ethereal_additional_libs) \ - plugins/gryphon/gryphon.la + plugins/gryphon/gryphon.la \ + plugins/mgcp/mgcp.la ethereal_static_DEPENDENCIES = \ $(ethereal_optional_objects) \ @@ -366,7 +367,8 @@ ethereal_LDADD = \ $(ethereal_additional_libs) \ @SNMP_LIBS@ \ "-dlopen" self \ - "-dlopen" plugins/gryphon/gryphon.la @PCAP_LIBS@ @GTK_LIBS@ + "-dlopen" plugins/gryphon/gryphon.la @PCAP_LIBS@ @GTK_LIBS@ \ + "-dlopen" plugins/mgcp/mgcp.la @PCAP_LIBS@ @GTK_LIBS@ ethereal_static_LDADD = \ $(ethereal_optional_objects) \ @@ -390,7 +392,8 @@ tethereal_additional_libs = wiretap/libwiretap.a epan/libethereal.a tethereal_DEPENDENCIES = \ $(ethereal_optional_objects) \ $(tethereal_additional_libs) \ - plugins/gryphon/gryphon.la + plugins/gryphon/gryphon.la \ + plugins/mgcp/mgcp.la # This automake variable adds to the link-line for the executable tethereal_LDADD = wiretap/libwiretap.a \ @@ -399,6 +402,7 @@ tethereal_LDADD = wiretap/libwiretap.a \ @SNMP_LIBS@ \ "-dlopen" self \ "-dlopen" plugins/gryphon/gryphon.la @GLIB_LIBS@ -lm \ + "-dlopen" plugins/mgcp/mgcp.la @GLIB_LIBS@ -lm \ @PCAP_LIBS@ @SOCKET_LIBS@ @NSL_LIBS@ tethereal_LDFLAGS = -export-dynamic diff --git a/configure.in b/configure.in index 749707afbc..06b9953db3 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -# $Id: configure.in,v 1.107 2000/10/27 02:22:04 gram Exp $ +# $Id: configure.in,v 1.108 2000/11/09 10:04:46 gram Exp $ dnl dnl Process this file with autoconf 2.13 or later to produce a dnl configure script; 2.12 doesn't generate a "configure" script that @@ -414,4 +414,6 @@ AC_OUTPUT( packaging/svr4/checkinstall packaging/svr4/pkginfo plugins/Makefile - plugins/gryphon/Makefile) + plugins/gryphon/Makefile + plugins/mgcp/Makefile) + diff --git a/doc/ethereal.pod.template b/doc/ethereal.pod.template index 759dd184dc..6d60850d6b 100644 --- a/doc/ethereal.pod.template +++ b/doc/ethereal.pod.template @@ -1002,6 +1002,7 @@ B<http://www.ethereal.com>. Neil Hunter <neil.hunter@energis-squared.com> Ralf Holzer <ralf@well.com> Craig Rodrigues <rodrigc@mediaone.net> + Ed Warnicke <hagbard@physics.rutgers.edu> Alain Magloire <alainm@rcsm.ece.mcgill.ca> was kind enough to give his permission to use his version of snprintf.c. diff --git a/plugins/Makefile.am b/plugins/Makefile.am index e31f0b99b9..9656bb34f0 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am # Automake file for Ethereal # -# $Id: Makefile.am,v 1.5 2000/03/15 19:09:16 guy Exp $ +# $Id: Makefile.am,v 1.6 2000/11/09 10:04:48 gram Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@zing.org> @@ -22,7 +22,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -SUBDIRS = gryphon +SUBDIRS = gryphon mgcp plugindir = @PLUGIN_DIR@ diff --git a/plugins/mgcp/AUTHORS b/plugins/mgcp/AUTHORS new file mode 100644 index 0000000000..867d6688eb --- /dev/null +++ b/plugins/mgcp/AUTHORS @@ -0,0 +1,3 @@ +Author : +Ed Warnicke <hagbard@physics.rutgers.edu> + diff --git a/plugins/mgcp/COPYING b/plugins/mgcp/COPYING new file mode 100644 index 0000000000..d60c31a97a --- /dev/null +++ b/plugins/mgcp/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/plugins/mgcp/ChangeLog b/plugins/mgcp/ChangeLog new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/plugins/mgcp/ChangeLog diff --git a/plugins/mgcp/INSTALL b/plugins/mgcp/INSTALL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/plugins/mgcp/INSTALL diff --git a/plugins/mgcp/Makefile.am b/plugins/mgcp/Makefile.am new file mode 100644 index 0000000000..dd83cc8ee8 --- /dev/null +++ b/plugins/mgcp/Makefile.am @@ -0,0 +1,44 @@ +# Makefile.am +# Automake file for Ethereal/Gryphon +# +# $Id: Makefile.am,v 1.1 2000/11/09 10:04:48 gram Exp $ +# +# Ethereal - Network traffic analyzer +# By Steve Limkemann <stevelim@dgtech.com> +# Copyright 1998 Steve Limkemann +# +# +# 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. +# + +INCLUDES = -I$(top_srcdir) -I$(includedir) + +plugindir = @PLUGIN_DIR@ + +plugin_LTLIBRARIES = mgcp.la +mgcp_la_SOURCES = packet-mgcp.c moduleinfo.h +mgcp_la_LDFLAGS = -module -avoid-version + +# Libs must be cleared, or else libtool won't create a shared module. +# If your module needs to be linked against any particular libraries, +# add them here. +LIBS = + +CLEANFILES = \ + mgcp \ + *~ + +EXTRA_DIST = \ + Makefile.nmake diff --git a/plugins/mgcp/NEWS b/plugins/mgcp/NEWS new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/plugins/mgcp/NEWS diff --git a/plugins/mgcp/moduleinfo.h b/plugins/mgcp/moduleinfo.h new file mode 100644 index 0000000000..133e12504e --- /dev/null +++ b/plugins/mgcp/moduleinfo.h @@ -0,0 +1,17 @@ +/* Included *after* config.h, in order to re-define these macros */ + +#ifdef PACKAGE +#undef PACKAGE +#endif + +/* Name of package */ +#define PACKAGE "mgcp" + + +#ifdef VERSION +#undef VERSION +#endif + +/* Version number of package */ +#define VERSION "0.0.1" + diff --git a/plugins/mgcp/packet-mgcp.c b/plugins/mgcp/packet-mgcp.c new file mode 100644 index 0000000000..45d55979c4 --- /dev/null +++ b/plugins/mgcp/packet-mgcp.c @@ -0,0 +1,1125 @@ +/* packet-mgcp.c + * Routines for mgcp packet disassembly + * RFC 2705 + * + * $Id: packet-mgcp.c,v 1.1 2000/11/09 10:04:48 gram Exp $ + * + * Copyright (c) 2000 by Ed Warnicke <hagbard@physics.rutgers.edu> + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 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 + +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <glib.h> +#include <ctype.h> +#include <time.h> +#include <string.h> +#include "packet.h" +#include "packet-sdp.h" +#include "resolv.h" +#include "prefs.h" +#include "strutil.h" + +/* Start includes and definitions for plugin stuff */ +#include "plugins/plugin_api.h" +#include "moduleinfo.h" +DLLEXPORT const gchar version[] = VERSION; +/* End includes and definitions for plugin stuff */ + + +#define TCP_PORT_MGCP_GATEWAY 2427 +#define UDP_PORT_MGCP_GATEWAY 2427 +#define TCP_PORT_MGCP_CALLAGENT 2727 +#define UDP_PORT_MGCP_CALLAGENT 2727 + +void proto_reg_handoff_mgcp(void); + + +/* Define the mgcp proto */ +static int proto_mgcp = -1; + +/* Define many many headers for mgcp */ +static int hf_mgcp_req = -1; +static int hf_mgcp_req_verb = -1; +static int hf_mgcp_req_endpoint = -1; +static int hf_mgcp_rsp = -1; +static int hf_mgcp_transid = -1; +static int hf_mgcp_version = -1; +static int hf_mgcp_rsp_rspcode = -1; +static int hf_mgcp_rsp_rspstring = -1; +static int hf_mgcp_param_rspack = -1; +static int hf_mgcp_param_bearerinfo = -1; +static int hf_mgcp_param_callid = -1; +static int hf_mgcp_param_connectionid = -1; +static int hf_mgcp_param_secondconnectionid = -1; +static int hf_mgcp_param_notifiedentity = -1; +static int hf_mgcp_param_requestid = -1; +static int hf_mgcp_param_localconnoptions = -1; +static int hf_mgcp_param_connectionmode = -1; +static int hf_mgcp_param_reqevents = -1; +static int hf_mgcp_param_restartmethod = -1; +static int hf_mgcp_param_restartdelay = -1; +static int hf_mgcp_param_signalreq = -1; +static int hf_mgcp_param_digitmap = -1; +static int hf_mgcp_param_observedevent = -1; +static int hf_mgcp_param_connectionparam = -1; +static int hf_mgcp_param_reasoncode = -1; +static int hf_mgcp_param_eventstates = -1; +static int hf_mgcp_param_specificendpoint = -1; +static int hf_mgcp_param_secondendpointid = -1; +static int hf_mgcp_param_reqinfo = -1; +static int hf_mgcp_param_quarantinehandling = -1; +static int hf_mgcp_param_detectedevents = -1; +static int hf_mgcp_param_capabilities = -1; +static int hf_mgcp_param_extention = -1; +static int hf_mgcp_param_invalid = -1; + +/* + * Define the trees for mgcp + * We need one for MGCP itself and one for the MGCP paramters + */ +static int ett_mgcp = -1; +static int ett_mgcp_param = -1; + + +/* + * Here are the global variables associated with + * the various user definable characteristics of the dissection + * + * MGCP has two kinds of "agents", gateways and callagents. Callagents + * control gateways in a master/slave sort of arrangement. Since gateways + * and callagents have different well known ports and could both + * operate under either udp or tcp we have rather a lot of port info to + * specify. + * + * global_mgcp_raw_text determines whether we are going to display + * the raw text of the mgcp message, much like the HTTP dissector does. + * + * global_mgcp_dissect_tree determines whether we are going to display + * a detailed tree that expresses a somewhat more semantically meaningful + * decode. + */ +static int global_mgcp_gateway_tcp_port = TCP_PORT_MGCP_GATEWAY; +static int global_mgcp_gateway_udp_port = UDP_PORT_MGCP_GATEWAY; +static int global_mgcp_callagent_tcp_port = TCP_PORT_MGCP_CALLAGENT; +static int global_mgcp_callagent_udp_port = UDP_PORT_MGCP_CALLAGENT; +static gboolean global_mgcp_raw_text = FALSE; +static gboolean global_mgcp_dissect_tree = TRUE; + + +/* + * Variables to allow for proper deletion of dissector registration when + * the user changes port from the gui. + */ +static int gateway_tcp_port = 0; +static int gateway_udp_port = 0; +static int callagent_tcp_port = 0; +static int callagent_udp_port = 0; + + +/* A simple MGCP type that is occasionally handy */ +typedef enum _mgcp_type { + MGCP_REQUEST, + MGCP_RESPONSE, + MGCP_OTHERS +} mgcp_type_t; + +/* Some basic utility functions that are specific to this dissector */ +static gboolean is_mgcp_verb(tvbuff_t *tvb, gint offset, gint maxlength); +static gboolean is_mgcp_rspcode(tvbuff_t *tvb, gint offset, gint maxlength); +static gint tvb_parse_param(tvbuff_t *tvb, gint offset, gint maxlength, + int** hf); + +/* + * The various functions that either dissect some + * subpart of MGCP. These aren't really proto dissectors but they + * are written in the same style. + */ +static void dissect_mgcp_firstline(tvbuff_t *tvb, + packet_info* pinfo, + proto_tree *tree); +static void dissect_mgcp_params(tvbuff_t *tvb, + packet_info* pinfo, + proto_tree *tree); +static void mgcp_raw_text_add(tvbuff_t *tvb, packet_info *pinfo, + proto_tree *tree); + +/* + * Some functions which should be moved to a library + * as I think that people may find them of general usefulness. + */ +static int tvb_crlf_strip(tvbuff_t *tvb, gint offset, gint maxlength); +static gint tvb_skip_wsp(tvbuff_t* tvb, gint offset, gint maxlength); +static gint tvb_find_null_line(tvbuff_t* tvb, gint offset, gint maxlength); +static gint tvb_section_length(tvbuff_t* tvb, gint tvb_sectionbegin, + gint tvb_sectionend); +static gboolean is_alpha(guint8 c); +static gboolean is_digit(guint8 c); + +/* + * dissect_mgcp - The dissector for the Media Gateway Control Protocol + */ + +static void +dissect_mgcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_tree *mgcp_tree, *ti; + gint sectionlen; + gint tvb_sectionend,tvb_sectionbegin, tvb_len, tvb_current_len; + tvbuff_t *next_tvb; + const guint8 *next_pd; + int next_offset; + + CHECK_DISPLAY_AS_DATA(proto_mgcp, tvb, pinfo, tree); + + pinfo->current_proto = "MGCP"; + + /* Initialize some "where are we now" stuff */ + + tvb_sectionend = 0; + tvb_sectionbegin = tvb_sectionend; + sectionlen = 0; + tvb_len = tvb_length(tvb); + tvb_current_len = tvb_len; + + /* + * Check to see whether we're really dealing with MGCP by looking + * for a valid MGCP verb or response code. + */ + if(is_mgcp_verb(tvb,0,tvb_len) || is_mgcp_rspcode(tvb,0,tvb_len)){ + + /* Build the info tree if we've been given a root */ + if (tree) { + + /* Create out mgcp subtree */ + ti = proto_tree_add_item(tree,proto_mgcp,tvb,0,0, FALSE); + mgcp_tree = proto_item_add_subtree(ti, ett_mgcp); + + /* dissect first line */ + tvb_sectionbegin = 0; + tvb_current_len = tvb_len; + tvb_sectionend = tvb_sectionbegin; + if( ( tvb_sectionend = tvb_find_guint8(tvb,tvb_sectionbegin, + tvb_current_len, '\n')) != -1){ + tvb_current_len = tvb_length_remaining(tvb,tvb_sectionbegin); + sectionlen = tvb_section_length(tvb,tvb_sectionbegin,tvb_sectionend); + dissect_mgcp_firstline(tvb_new_subset(tvb, tvb_sectionbegin, + sectionlen,-1) + , pinfo, mgcp_tree); + } + /* dissect params */ + tvb_sectionbegin = tvb_sectionend +1; + tvb_current_len = tvb_length_remaining(tvb,tvb_sectionbegin); + if( (tvb_sectionend = tvb_find_null_line(tvb, tvb_sectionbegin, + tvb_current_len)) != -1){ + tvb_sectionend--; + sectionlen = tvb_section_length(tvb,tvb_sectionbegin,tvb_sectionend); + dissect_mgcp_params(tvb_new_subset(tvb,tvb_sectionbegin, + sectionlen, -1), + pinfo, mgcp_tree); + tvb_sectionbegin = tvb_sectionend + 1; + + /* set the mgcp payload length correctly so we don't include the + * encapsulated SDP + */ + sectionlen = tvb_section_length(tvb,0,tvb_sectionend); + proto_item_set_len(ti,sectionlen); + } + else { + /* If somehow we didn't manage to find a null line, then assume + * we've lost the end of the message and count everything + * we do have as part of the body + */ + tvb_sectionend = tvb_len -1; + } + + /* Display the raw text of the mgcp message if desired */ + + /* Do we want to display the raw text of our MGCP packet? */ + if(global_mgcp_raw_text){ + sectionlen = tvb_section_length(tvb,0,tvb_sectionend); + mgcp_raw_text_add(tvb_new_subset(tvb,0,sectionlen,-1),pinfo, + mgcp_tree); + } + + /* dissect sdp payload */ + tvb_current_len = tvb_length_remaining(tvb,tvb_sectionbegin); + if( ( tvb_sectionbegin = tvb_find_guint8(tvb,tvb_sectionbegin, + tvb_current_len,'\n')) != -1){ + tvb_sectionbegin++; + next_tvb = tvb_new_subset(tvb, tvb_sectionbegin, -1, -1); + tvb_compat(next_tvb, &next_pd, &next_offset); + + dissect_sdp(next_pd, next_offset,pinfo->fd,tree); + } + } + } + /* + * Add our column information we do this after dissecting SDP + * in order to prevent the column info changing to reflect the SDP. + */ + tvb_sectionbegin = 0; + tvb_current_len = tvb_len; + if (check_col(pinfo->fd, COL_PROTOCOL)) + col_add_str(pinfo->fd, COL_PROTOCOL, "MGCP"); + if (check_col(pinfo->fd, COL_INFO) && + ((tvb_sectionend = tvb_find_guint8(tvb,tvb_sectionbegin, + tvb_current_len, '\n')) != -1)){ + sectionlen = tvb_section_length(tvb,tvb_sectionbegin,tvb_sectionend); + sectionlen = tvb_crlf_strip(tvb,tvb_sectionbegin,sectionlen); + col_add_fstr(pinfo->fd,COL_INFO, "%s", + tvb_format_text(tvb,tvb_sectionbegin,sectionlen)); + } +} + +/* + * Add the raw text of the message to the dissect tree if appropriate + * preferences are specified. + */ + +static void mgcp_raw_text_add(tvbuff_t *tvb, packet_info *pinfo, + proto_tree *tree){ + + gint tvb_linebegin,tvb_lineend,tvb_current_len,sectionlen; + + tvb_linebegin = 0; + tvb_current_len = tvb_length(tvb); + while((tvb_lineend = tvb_find_guint8(tvb,tvb_linebegin, + tvb_current_len, '\n')) != -1){ + sectionlen = tvb_section_length(tvb,tvb_linebegin,tvb_lineend); + proto_tree_add_text(tree, tvb, tvb_linebegin, sectionlen, + "%s", tvb_format_text(tvb,tvb_linebegin, + sectionlen)); + tvb_linebegin = tvb_lineend + 1; + tvb_current_len = tvb_length_remaining(tvb,tvb_linebegin); + } + if(tvb_linebegin < tvb_length(tvb)){ + proto_tree_add_text(tree, tvb, tvb_linebegin, tvb_current_len, + "%s", tvb_format_text(tvb,tvb_linebegin, + tvb_current_len)); + } +} + +/* Register all the bits needed with the filtering engine */ + +void +proto_register_mgcp(void) +{ + static hf_register_info hf[] = { + { &hf_mgcp_req, + { "Request", "mgcp.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "True if MGCP request" }}, + { &hf_mgcp_rsp, + { "Response", "mgcp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "TRUE if MGCP response" }}, + { &hf_mgcp_req_verb, + { "Verb", "mgcp.req.verb", FT_STRING, BASE_DEC, NULL, 0x0, + "Name of the verb"}}, + { &hf_mgcp_req_endpoint, + { "Endpoint", "mgcp.req.endpoint", FT_STRING, BASE_DEC, NULL, 0x0, + "Endpoint referenced by the message"}}, + { &hf_mgcp_transid, + { "Transaction ID", "mgcp.transid", FT_STRING, BASE_DEC, NULL, 0x0, + "Transaction ID of this message"}}, + { &hf_mgcp_version, + { "Version", "mgcp.version", FT_STRING, BASE_DEC, NULL, 0x0, + "MGCP Version"}}, + { &hf_mgcp_rsp_rspcode, + { "Response Code", "mgcp.rsp.rspcode", FT_STRING, BASE_DEC, NULL, 0x0, + "Response Code"}}, + { &hf_mgcp_rsp_rspstring, + { "Response String", "mgcp.rsp.rspstring", FT_STRING, BASE_DEC, NULL, + 0x0, "Response String"}}, + { &hf_mgcp_param_rspack, + { "ResponseAck (K)", "mgcp.param.rspack", FT_STRING, BASE_DEC, NULL, + 0x0, "Response Ack"}}, + { &hf_mgcp_param_bearerinfo, + { "BearerInformation (B)", "mgcp.param.bearerinfo", FT_STRING, BASE_DEC, + NULL, 0x0, "Bearer Information"}}, + { &hf_mgcp_param_callid, + { "CallId (C)", "mgcp.param.callid", FT_STRING, BASE_DEC, NULL, 0x0, + "Call Id"}}, + { &hf_mgcp_param_connectionid, + {"ConnectionIdentifier (I)", "mgcp.param.connectionid", FT_STRING, + BASE_DEC, NULL, 0x0, "Connection Identifier"}}, + { &hf_mgcp_param_secondconnectionid, + { "SecondConnectionID (I2)", "mgcp.param.secondconnectionid", FT_STRING, + BASE_DEC, NULL, 0x0, "Second Connection Identifier"}}, + { &hf_mgcp_param_notifiedentity, + { "NotifiedEntity (N)", "mgcp.param.notifiedentity", FT_STRING, BASE_DEC, + NULL, 0x0, "Notified Entity"}}, + { &hf_mgcp_param_requestid, + { "RequestIdentifier (X)", "mgcp.param.requestid", FT_STRING, BASE_DEC, + NULL, 0x0, "Request Identifier"}}, + { &hf_mgcp_param_localconnoptions, + { "LocalConnectionOptions (L)", "mgcp.param.localconnectionoptions", + FT_STRING, BASE_DEC, NULL, 0x0, "Local Connection Options"}}, + { &hf_mgcp_param_connectionmode, + { "ConnectionMode (M)", "mgcp.param.connectionmode", FT_STRING, BASE_DEC, + NULL, 0x0, "Connection Mode" }}, + { &hf_mgcp_param_reqevents, + { "RequestedEvents (R)", "mgcp.param.reqevents", FT_STRING, BASE_DEC, + NULL, 0x0, "Requested Events"}}, + { &hf_mgcp_param_signalreq, + { "SignalRequests (S)", "mgcp.param.signalreq", FT_STRING, BASE_DEC, + NULL, 0x0, "Signal Request"}}, + { &hf_mgcp_param_restartmethod, + { "RestartMethod (RM)", "mgcp.param.restartmethod", FT_STRING, BASE_DEC, + NULL, 0x0, "Restart Method"}}, + { &hf_mgcp_param_restartdelay, + { "RestartDelay (RD)", "mgcp.param.restartdelay", FT_STRING, BASE_DEC, + NULL, 0x0, "Restart Delay"}}, + { &hf_mgcp_param_digitmap, + { "DigitMap (D)", "mgcp.param.digitmap", FT_STRING, BASE_DEC, NULL, 0x0, + "Digit Map"}}, + { &hf_mgcp_param_observedevent, + { "ObservedEvents (O)", "mgcp.param.observedevents", FT_STRING, + BASE_DEC, NULL, 0x0, "Observed Events"}}, + { &hf_mgcp_param_connectionparam, + { "ConnectionParameters (P)", "mgcp.param.connectionparam", FT_STRING, + BASE_DEC, NULL, 0x0, "Connection Parameters"}}, + { &hf_mgcp_param_reasoncode, + { "ReasonCode (E)", "mgcp.param.reasoncode", FT_STRING, BASE_DEC, + NULL, 0x0, "Reason Code"}}, + { &hf_mgcp_param_eventstates, + { "EventStates (ES)", "mgcp.param.eventstates", FT_STRING, BASE_DEC, + NULL, 0x0, "Event States"}}, + { &hf_mgcp_param_specificendpoint, + { "SpecificEndpointID (Z)", "mgcp.param.specificendpointid", FT_STRING, + BASE_DEC, NULL, 0x0, "Specific Endpoint ID"}}, + { &hf_mgcp_param_secondendpointid, + { "SecondEndpointID (Z2)", "mgcp.param.secondendpointid", FT_STRING, + BASE_DEC, NULL, 0x0, "Second Endpoing ID"}}, + { &hf_mgcp_param_reqinfo, + { "RequestedInfo (F)", "mgcp.param.reqinfo", FT_STRING, BASE_DEC, + NULL, 0x0,"Requested Info"}}, + { &hf_mgcp_param_quarantinehandling, + { "QuarantineHandling (Q)", "mgcp.param.quarantinehandling", FT_STRING, + BASE_DEC, NULL, 0x0, "Quarantine Handling"}}, + { &hf_mgcp_param_detectedevents, + { "DetectedEvents (T)", "mgcp.param.detectedevents", FT_STRING, BASE_DEC, + NULL, 0x0, "Detected Events"}}, + { &hf_mgcp_param_capabilities, + { "Capabilities (A)", "mgcp.param.capabilities", FT_STRING, BASE_DEC, + NULL, 0x0, "Capabilities"}}, + { &hf_mgcp_param_extention, + { "Extention Parameter (X-*)", "mgcp.param.extention", FT_STRING, + BASE_DEC, NULL, 0x0, "Extension Parameter"}}, + { &hf_mgcp_param_invalid, + { "Invalid Parameter", "mgcp.param.invalid", FT_STRING, + BASE_DEC, NULL, 0x0, "Invalid Parameter"}}, + /* Add more fields here */ + }; + static gint *ett[] = { + &ett_mgcp, + &ett_mgcp_param, + }; + module_t *mgcp_module; + + /* Register our configuration options for , particularly our ports */ + + mgcp_module = prefs_register_module("mgcp", "MGCP", proto_reg_handoff_mgcp); + + prefs_register_uint_preference(mgcp_module, "tcp.port", + "MGCP Gateway TCP Port", + "Set the port for gateway messages (if other" + " than the default of 2427)", + 10, &global_mgcp_gateway_tcp_port); + + prefs_register_uint_preference(mgcp_module, "udp.port", + "MGCP UDP Gateway Port", + "Set the port for gateway messages (if other" + " than the default of 2427)", + 10, &global_mgcp_gateway_udp_port); + + prefs_register_uint_preference(mgcp_module, "tcp.port", + "MGCP Callagent TCP Port", + "Set the port for callagent messages" + "(if other than the default of 2727)", + 10, &global_mgcp_callagent_tcp_port); + + prefs_register_uint_preference(mgcp_module, "udp.port", + "MGCP UDP Gateway Port", + "Set the port for callagent messages " + "(if other than the default of 2727)", + 10, &global_mgcp_callagent_udp_port); + + + prefs_register_bool_preference(mgcp_module, "display raw text toggle", + "Display raw text for MGCP message", + "Specifies that the raw text of the " + "MGCP message should be displayed " + "instead of (or in addition to) the " + "dissection tree", + &global_mgcp_raw_text); + + prefs_register_bool_preference(mgcp_module, "display dissect tree", + "Display tree dissection for MGCP message", + "Specifies that the dissection tree of the " + "MGCP message should be displayed " + "instead of (or in addition to) the " + "raw text", + &global_mgcp_dissect_tree); + + proto_mgcp = proto_register_protocol("Media Gateway Control Protocol", + "mgcp"); + + proto_register_field_array(proto_mgcp, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + +} + +/* The registration hand-off routine */ +void +proto_reg_handoff_mgcp(void) +{ + static int mgcp_prefs_initialized = FALSE; + + if (mgcp_prefs_initialized) { + dissector_delete("tcp.port", gateway_tcp_port, dissect_mgcp); + dissector_delete("udp.port", gateway_udp_port, dissect_mgcp); + dissector_delete("tcp.port", callagent_tcp_port, dissect_mgcp); + dissector_delete("udp.port", callagent_udp_port, dissect_mgcp); + } + else { + mgcp_prefs_initialized = TRUE; + } + + /* Set our port number for future use */ + + gateway_tcp_port = global_mgcp_gateway_tcp_port; + gateway_udp_port = global_mgcp_gateway_udp_port; + + callagent_tcp_port = global_mgcp_callagent_tcp_port; + callagent_udp_port = global_mgcp_callagent_udp_port; + + dissector_add("tcp.port", global_mgcp_gateway_tcp_port, dissect_mgcp); + dissector_add("udp.port", global_mgcp_gateway_udp_port, dissect_mgcp); + dissector_add("tcp.port", global_mgcp_callagent_tcp_port, dissect_mgcp); + dissector_add("udp.port", global_mgcp_callagent_udp_port, dissect_mgcp); + +} + +/* + * is_mgcp_verb - A function for determining whether there is a + * MGCP verb at offset in tvb + * + * Parameter: + * tvb - The tvbuff in which we are looking for an MGCP verb + * offset - The offset in tvb at which we are looking for a MGCP verb + * maxlength - The maximum distance from offset we may look for the + * characters that make up a MGCP verb. + * + * Return: TRUE if there is an MGCP verb at offset in tvb, otherwise FALSE + */ + +static gboolean is_mgcp_verb(tvbuff_t *tvb, gint offset, gint maxlength){ + int returnvalue = FALSE; + guint8 word[5]; + + if(( maxlength >= 4) && tvb_get_nstringz0(tvb,offset,4,word)){ + if (strncasecmp(word, "EPCF", 4) == 0 || + strncasecmp(word, "CRCX", 4) == 0 || + strncasecmp(word, "MDCX", 4) == 0 || + strncasecmp(word, "DLCX", 4) == 0 || + strncasecmp(word, "RQNT", 4) == 0 || + strncasecmp(word, "NTFY", 4) == 0 || + strncasecmp(word, "AUEP", 4) == 0 || + strncasecmp(word, "AUCX", 4) == 0 || + strncasecmp(word, "RSIP", 4) == 0 || + (word[0] == 'X' && is_alpha(word[1]) && is_alpha(word[2]) && + is_alpha(word[3])) + ){ + returnvalue = TRUE; + } + } + if( returnvalue && maxlength >= 5 && + (word[0] = tvb_get_guint8(tvb,4)) != ' ' && word[0] != '\t'){ + returnvalue = FALSE; + } + return returnvalue; +} + +/* + * is_mgcp_rspcode - A function for determining whether something which + * looks roughly like a MGCP response code is at + * offset in tvb + * + * Parameters: + * tvb - The tvbuff in which we are looking for an MGCP response code + * offset - The offset in tvb at which we are looking for a MGCP response code + * maxlength - The maximum distance from offset we may look for the + * characters that make up a MGCP response code. + * + * Return: TRUE if there is an MGCP response code at offset in tvb, + * otherwise FALSE + */ + +static gboolean is_mgcp_rspcode(tvbuff_t *tvb, gint offset, gint maxlength){ + int returnvalue = FALSE; + guint8 word[4]; + if(maxlength >= 3){ + tvb_get_nstringz0(tvb,offset,3,word); + if( is_digit(word[0]) && + is_digit(word[1]) && + is_digit(word[2])){ + returnvalue = TRUE; + } + } + if( returnvalue && maxlength >= 4 && + (word[0] = tvb_get_guint8(tvb,3)) != ' ' && word[0] != '\t'){ + returnvalue = FALSE; + } + return returnvalue; +} + +/* + * tvb_crlf_strip - Subtracts from maxlength necessary to have maxlength + * to be the distance from offset to the first character + * before a CR or LF. The function assumes that the + * maxlength is the distance from offset to the end of + * the line and will scan back (decrementing maxlength) + * until it encounters a non ( CR or LF ) character. + * + * Parameters: + * tvb - The tvbuff in which we are scanning for the first instance of CR + * or LF. + * offset - The offset in tvb at which we begin looking for a CR or LF. + * maxlength - The distance from offset to the end of the line in tvb. + * + * Return: The distance in tvb from offset to the character immediately + * before the first instance of CR or LF. + * The utility of this is that if you have a line this gives you + * the length of that line sans the CRLF at the end thus effectively + * stripping the CRLF off the end. + */ +static gint tvb_crlf_strip(tvbuff_t *tvb, gint offset, gint maxlength){ + gint returnvalue; + guint8 tempchar; + + for(returnvalue = maxlength-1; + ( (returnvalue >= 0 ) && ( + ((tempchar = tvb_get_guint8(tvb,offset + returnvalue) ) == '\r') || + (tempchar == '\n'))); + returnvalue--); + return ( returnvalue + 1); +} + +/* + * is_alpha - Indicates whether the character c is an alphabetical character. + * + * Parameter: + * c - The character being checked for being an alphabetical character. + * + * Return: TRUE if c is an upper or lower case alphabetical character, + * FALSE otherwise. + */ +static gboolean is_digit(guint8 c){ + int returnvalue = FALSE; + if(c <= '9' && c >= '0'){ + returnvalue = TRUE; + } + return ( returnvalue ); +} + + +/* + * is_digit - Indicates whether the character c is a digit.. + * + * Parameter: + * c - The character being checked for being a digit. + * + * Return: TRUE if c is a digit 0-9, + * FALSE otherwise. + */ +static gboolean is_alpha(guint8 c){ + int returnvalue = FALSE; + if(( c <= 'Z' && c >= 'A' ) || (c <= 'z' && c >= 'a')){ + returnvalue = TRUE; + } + return returnvalue; +} + +/* + * tvb_parse_param - Parse the MGCP param into a type and a value. + * + * Parameters: + * tvb - The tvbuff containing the MGCP param we are to parse. + * offset - The offset in tvb at which we will begin looking for a + * MGCP parameter to parse. + * len - The maximum distance from offset in tvb that we can look for + * an MGCP parameter to parse. + * hf - The place to write a pointer to the integer representing the + * header field associated with the MGCP parameter parsed. + * + * Returns: The offset in tvb where the value of the MGCP parameter + * begins. + */ +static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf){ + gint returnvalue, tvb_current_offset,counter; + guint8 tempchar; + tvb_current_offset = offset; + returnvalue = -1; + *hf = NULL; + if(len > 0){ + tempchar = tvb_get_guint8(tvb,tvb_current_offset); + switch(tempchar){ + case 'K': + *hf = &hf_mgcp_param_rspack; + break; + case 'B': + *hf = &hf_mgcp_param_bearerinfo; + break; + case 'C': + *hf = &hf_mgcp_param_callid; + break; + case 'I': + tvb_current_offset++; + if(len > (tvb_current_offset - offset) && + (tempchar = tvb_get_guint8(tvb,tvb_current_offset)) == ':'){ + *hf = &hf_mgcp_param_connectionid; + tvb_current_offset--; + } + else if ( tempchar == '2'){ + *hf = &hf_mgcp_param_secondconnectionid; + } + break; + case 'N': + *hf = &hf_mgcp_param_notifiedentity; + break; + case 'X': + tvb_current_offset++; + if(len > (tvb_current_offset - offset) && + (tempchar = tvb_get_guint8(tvb,tvb_current_offset)) == ':'){ + *hf = &hf_mgcp_param_requestid; + } + else if(len > (tvb_current_offset - offset) && ( + (tempchar = tvb_get_guint8(tvb,tvb_current_offset)) == '-' || + tempchar == '+')){ + tvb_current_offset++; + for(counter = 1;(counter <= 6) && (len > (counter + tvb_current_offset + - offset)) + && ( is_alpha(tempchar = + tvb_get_guint8(tvb,tvb_current_offset+counter)) + || is_digit(tempchar));counter++); + if(tempchar == ':'){ + tvb_current_offset += counter; + *hf = &hf_mgcp_param_extention; + } + } + tvb_current_offset--; + break; + case 'L': + *hf = &hf_mgcp_param_localconnoptions; + break; + case 'M': + *hf = &hf_mgcp_param_connectionmode; + break; + case 'R': + tvb_current_offset++; + if(len > (tvb_current_offset - offset) && + (tempchar = tvb_get_guint8(tvb,tvb_current_offset)) == ':'){ + *hf = &hf_mgcp_param_reqevents; + tvb_current_offset--; + } + else if ( tempchar == 'M'){ + *hf = &hf_mgcp_param_restartmethod; + } + else if ( tempchar == 'D'){ + *hf = &hf_mgcp_param_restartdelay; + } + break; + case 'S': + *hf = &hf_mgcp_param_signalreq; + break; + case 'D': + *hf = &hf_mgcp_param_digitmap; + break; + case 'O': + *hf = &hf_mgcp_param_observedevent; + break; + case 'P': + *hf = &hf_mgcp_param_connectionparam; + break; + case 'E': + tvb_current_offset++; + if(len > (tvb_current_offset - offset) && + (tempchar = tvb_get_guint8(tvb,tvb_current_offset)) == ':'){ + *hf = &hf_mgcp_param_reasoncode; + tvb_current_offset--; + } + else if ( tempchar == 'S'){ + *hf = &hf_mgcp_param_eventstates; + } + break; + case 'Z': + tvb_current_offset++; + if(len > (tvb_current_offset - offset) && + (tempchar = tvb_get_guint8(tvb,tvb_current_offset)) == ':'){ + *hf = &hf_mgcp_param_specificendpoint; + tvb_current_offset--; + } + else if ( tempchar == '2'){ + *hf = &hf_mgcp_param_secondendpointid; + } + break; + case 'F': + *hf = &hf_mgcp_param_reqinfo; + break; + + case 'Q': + *hf = &hf_mgcp_param_quarantinehandling; + break; + + case 'T': + *hf = &hf_mgcp_param_detectedevents; + break; + + case 'A': + *hf = &hf_mgcp_param_capabilities; + break; + default: + *hf = &hf_mgcp_param_invalid; + break; + } + + tvb_current_offset++; + if(*hf != NULL && len > (tvb_current_offset - offset) && + (tempchar = tvb_get_guint8(tvb,tvb_current_offset)) == ':'){ + tvb_current_offset++; + tvb_current_offset = tvb_skip_wsp(tvb,tvb_current_offset, + (len - tvb_current_offset + offset)); + if(len > tvb_current_offset - offset){ + returnvalue = tvb_current_offset; + } + } + else { + *hf = &hf_mgcp_param_invalid; + } + } + if(*hf == &hf_mgcp_param_invalid){ + returnvalue = offset; + } + return returnvalue; +} + + +/* + * dissect_mgcp_firstline - Dissects the firstline of an MGCP message. + * Adds the appropriate headers fields to + * tree for the dissection of the first line + * of an MGCP message. + * + * Parameters: + * tvb - The tvb containing the first line of an MGCP message. This + * tvb is presumed to ONLY contain the first line of the MGCP + * message. + * pinfo - The packet info for the packet. This is not really used + * by this function but is passed through so as to retain the + * style of a dissector. + * tree - The tree from which to hang the structured information parsed + * from the first line of the MGCP message. + */ +static void dissect_mgcp_firstline(tvbuff_t *tvb, + packet_info *pinfo, + proto_tree *tree){ + gint tvb_current_offset,tvb_previous_offset,tvb_len,tvb_current_len; + gint tokennum, tokenlen; + mgcp_type_t mgcp_type = MGCP_OTHERS; + proto_item* (*my_proto_tree_add_string)(proto_tree*, int, tvbuff_t*, gint, + gint, const char*); + tvb_previous_offset = 0; + tvb_len = tvb_length(tvb); + tvb_current_len = tvb_len; + tvb_current_offset = tvb_previous_offset; + + if(tree){ + tokennum = 0; + + if(global_mgcp_dissect_tree){ + my_proto_tree_add_string = proto_tree_add_string; + } + else{ + my_proto_tree_add_string = proto_tree_add_string_hidden; + } + + tvb_current_offset = tvb_find_guint8(tvb,tvb_previous_offset, + tvb_current_len, ' '); + tvb_current_len = tvb_length_remaining(tvb,tvb_previous_offset); + tokenlen = tvb_current_offset - tvb_previous_offset; + + while( tvb_current_offset != -1){ + if(tokennum == 0){ + if(is_mgcp_verb(tvb,tvb_previous_offset,tvb_current_len)){ + mgcp_type = MGCP_REQUEST; + my_proto_tree_add_string(tree,hf_mgcp_req_verb, tvb, + tvb_previous_offset, tokenlen, + tvb_format_text(tvb,tvb_previous_offset + ,tokenlen)); + } + else if (is_mgcp_rspcode(tvb,tvb_previous_offset,tvb_current_len)){ + mgcp_type = MGCP_RESPONSE; + my_proto_tree_add_string(tree,hf_mgcp_rsp_rspcode, tvb, + tvb_previous_offset, tokenlen, + tvb_format_text(tvb,tvb_previous_offset + ,tokenlen)); + } + else { + break; + } + } + if(tokennum == 1){ + my_proto_tree_add_string(tree,hf_mgcp_transid, tvb, + tvb_previous_offset, tokenlen, + tvb_format_text(tvb,tvb_previous_offset, + tokenlen)); + } + if(tokennum == 2){ + if(mgcp_type == MGCP_REQUEST){ + my_proto_tree_add_string(tree,hf_mgcp_req_endpoint, tvb, + tvb_previous_offset, tokenlen, + tvb_format_text(tvb, tvb_previous_offset, + tokenlen)); + } + else if( (mgcp_type == MGCP_RESPONSE) && + (tvb_current_offset = tvb_find_guint8(tvb,tvb_previous_offset, + tvb_current_len, '\n')) + != -1){ + /* Is the following line used ?*/ + tvb_current_len = tvb_length_remaining(tvb,tvb_current_offset); + tokenlen = tvb_section_length(tvb, tvb_previous_offset, + tvb_current_offset); + tokenlen = tvb_crlf_strip(tvb,tvb_previous_offset,tokenlen); + my_proto_tree_add_string(tree,hf_mgcp_rsp_rspstring, tvb, + tvb_previous_offset, tokenlen, + tvb_format_text(tvb,tvb_previous_offset, + tokenlen)); + break; + } + } + if( (tokennum == 3 && mgcp_type == MGCP_REQUEST) && + (tvb_current_offset = tvb_find_guint8(tvb,tvb_previous_offset, + tvb_current_len, '\n')) + != -1){ + tokenlen = tvb_section_length(tvb,tvb_previous_offset, + tvb_current_offset); + tokenlen = tvb_crlf_strip(tvb, tvb_previous_offset, tokenlen); + my_proto_tree_add_string(tree,hf_mgcp_version, tvb, + tvb_previous_offset, tokenlen, + tvb_format_text(tvb,tvb_previous_offset, + tokenlen)); + break; + } + tvb_previous_offset = tvb_skip_wsp(tvb, tvb_current_offset, + tvb_current_len); + tvb_current_len = tvb_length_remaining(tvb,tvb_previous_offset); + tvb_current_offset = tvb_find_guint8(tvb,tvb_previous_offset, + tvb_current_len, ' '); + tokenlen = tvb_current_offset - tvb_previous_offset; + tokennum++; + } + + switch (mgcp_type){ + case MGCP_RESPONSE: + proto_tree_add_boolean_hidden(tree,hf_mgcp_rsp, NullTVB,0,0,1); + break; + case MGCP_REQUEST: + proto_tree_add_boolean_hidden(tree,hf_mgcp_req, NullTVB,0,0,1); + break; + default: + break; + } + } +} + +/* + * dissect_mgcp_params - Dissects the parameters of an MGCP message. + * Adds the appropriate headers fields to + * tree for the dissection of the parameters + * of an MGCP message. + * + * Parameters: + * tvb - The tvb containing the parameters of an MGCP message. This + * tvb is presumed to ONLY contain the part of the MGCP + * message which contains the MGCP parameters. + * pinfo - The packet info for the packet. This is not really used + * by this function but is passed through so as to retain the + * style of a dissector. + * tree - The tree from which to hang the structured information parsed + * from the parameters of the MGCP message. + */ +static void dissect_mgcp_params(tvbuff_t *tvb, packet_info *pinfo, + proto_tree *tree){ + int linelen, tokenlen, *my_param; + gint tvb_lineend,tvb_current_len, tvb_linebegin,tvb_len; + gint tvb_tokenbegin; + guint8 tempchar; + proto_tree *mgcp_param_ti, *mgcp_param_tree; + proto_item* (*my_proto_tree_add_string)(proto_tree*, int, tvbuff_t*, gint, + gint, const char*); + + tvb_len = tvb_length(tvb); + tvb_linebegin = 0; + tvb_current_len = tvb_length_remaining(tvb,tvb_linebegin); + tvb_lineend = tvb_linebegin; + + if(tree){ + if(global_mgcp_dissect_tree){ + my_proto_tree_add_string = proto_tree_add_string; + mgcp_param_ti = proto_tree_add_item(tree,proto_mgcp,tvb, + tvb_linebegin, tvb_len, FALSE); + proto_item_set_text(mgcp_param_ti,"Parameters"); + mgcp_param_tree = proto_item_add_subtree(mgcp_param_ti, ett_mgcp_param); + } + else{ + my_proto_tree_add_string = proto_tree_add_string_hidden; + mgcp_param_tree = tree; + mgcp_param_ti = NULL; + } + + /* Parse the parameters */ + tempchar = tvb_get_guint8(tvb,tvb_linebegin); + while((tvb_lineend = tvb_find_guint8(tvb,tvb_linebegin, + tvb_current_len, '\n')) != -1){ + linelen = tvb_section_length(tvb,tvb_linebegin,tvb_lineend); + tvb_tokenbegin = tvb_parse_param(tvb, tvb_linebegin, linelen, + &my_param); + if( tvb_lineend != -1 && my_param != NULL ){ + tokenlen = tvb_lineend - tvb_tokenbegin; + tokenlen = tvb_crlf_strip(tvb,tvb_tokenbegin,tokenlen); + linelen = tvb_crlf_strip(tvb,tvb_linebegin,linelen); + my_proto_tree_add_string(mgcp_param_tree,*my_param, tvb, + tvb_linebegin, linelen, + tvb_format_text(tvb,tvb_tokenbegin, + tokenlen)); + } + tvb_linebegin = tvb_lineend + 1; + tvb_current_len = tvb_length_remaining(tvb,tvb_linebegin); + } + } +} + +/* + * tvb_skip_wsp - Returns the position in tvb of the first non-whitespace + * character following offset or offset + maxlength -1 whichever + * is smaller. + * + * Parameters: + * tvb - The tvbuff in which we are skipping whitespace. + * offset - The offset in tvb from which we begin trying to skip whitespace. + * maxlength - The maximum distance from offset that we may try to skip + * whitespace. + * + * Returns: The position in tvb of the first non-whitespace + * character following offset or offset + maxlength -1 whichever + * is smaller. + */ +static gint tvb_skip_wsp(tvbuff_t* tvb, gint offset, gint maxlength){ + gint counter = offset; + gint end = offset + maxlength; + guint8 tempchar; + for(counter = offset; counter < end && + ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' || + tempchar == '\t');counter++); + return (counter); +} + +/* + * tvb_find_null_line - Returns the offset in tvb off the first null line + * encountered. A null line is a line begins with + * a CR or LF. + * + * Parameters: + * tvb - The tvbuff in which we are looking for a null line. + * offset - The offset in tvb at which we will begin looking for + * a null line. + * maxlength - The maximum distance from offset in tvb that we will look for + * a null line. + * + * Returns: The offset in tvb of the beginning of the first null line found. + */ +static gint tvb_find_null_line(tvbuff_t* tvb, gint offset, + gint maxlength){ + gint tvb_lineend,tvb_current_len,tvb_linebegin; + guint tempchar; + tvb_linebegin = offset; + tvb_current_len = maxlength; + tvb_lineend = tvb_linebegin; + + tempchar = tvb_get_guint8(tvb,tvb_linebegin); + + while( tempchar != '\r' && tempchar != '\n' && + (tvb_lineend = tvb_find_guint8(tvb,tvb_linebegin, + tvb_current_len, '\n')) + != -1 && + (tvb_linebegin = tvb_lineend + 1) <= maxlength + offset + ){ + tempchar = tvb_get_guint8(tvb,tvb_linebegin); + tvb_current_len = maxlength - ( tvb_linebegin - offset); + } + if( tvb_linebegin == offset || tvb_lineend == -1 ){ + tvb_linebegin = -1; + } + return (tvb_linebegin); +} + +static gint tvb_section_length(tvbuff_t* tvb, gint tvb_sectionbegin, + gint tvb_sectionend){ + gint sectionlen,remaininglen; + + sectionlen = tvb_sectionend - tvb_sectionbegin + 1; + remaininglen = tvb_length_remaining(tvb,tvb_sectionbegin); + g_assert(sectionlen <= remaininglen); + return sectionlen; +} + + +/* Start the functions we need for the plugin stuff */ +void plugin_reg_handoff(void){ + proto_reg_handoff_mgcp(); +} + +DLLEXPORT void plugin_init(plugin_address_table_t *pat){ + /* initialise the table of pointers needed in Win32 DLLs */ + plugin_address_table_init(pat); + /* destroy the dfilter tree */ + dfilter_cleanup(); + /* register the new protocol, protocol fields, and subtrees */ + if (proto_mgcp == -1) { /* execute protocol initialization only once */ + proto_register_mgcp(); + } + /* initialize the dfilter tree with all the header field and protocol + * abbrevs defined, including xxx */ + dfilter_init(); +} +/* End the functions we need for plugin stuff */ + + |