diff --git a/plugins/mate/AUTHORS b/plugins/mate/AUTHORS new file mode 100644 index 0000000000..e37df0dd7d --- /dev/null +++ b/plugins/mate/AUTHORS @@ -0,0 +1,3 @@ +Author: +Luis E. Garcia Ontanon + diff --git a/plugins/mate/COPYING b/plugins/mate/COPYING new file mode 100644 index 0000000000..d60c31a97a --- /dev/null +++ b/plugins/mate/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. + + + Copyright (C) + + 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. + + , 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/mate/INSTALL b/plugins/mate/INSTALL new file mode 100644 index 0000000000..e69de29bb2 diff --git a/plugins/mate/Makefile.am b/plugins/mate/Makefile.am new file mode 100644 index 0000000000..2b6fd02673 --- /dev/null +++ b/plugins/mate/Makefile.am @@ -0,0 +1,44 @@ +# Makefile.am +# Automake file for MATE Ethereal plugin +# +# $Id$ +# +# Ethereal - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +INCLUDES = -I$(top_srcdir) + +plugindir = @plugindir@ + +plugin_LTLIBRARIES = mate.la +mate_la_SOURCES = moduleinfo.h mate.h mate_util.h packet-mate.c mate_runtime.c mate_setup.c mate_util.c mate_plugin.c +mate_la_LDFLAGS = -module -avoid-version +mate_la_LIBADD = @PLUGIN_LIBS@ + +# 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 = \ + mate \ + *~ + +EXTRA_DIST = \ + Makefile.nmake diff --git a/plugins/mate/Makefile.nmake b/plugins/mate/Makefile.nmake new file mode 100644 index 0000000000..e627b24a5b --- /dev/null +++ b/plugins/mate/Makefile.nmake @@ -0,0 +1,30 @@ +# +# $Id$ +# + +include ..\..\config.nmake + +############### no need to modify below this line ######### + +CFLAGS=/DHAVE_CONFIG_H /I../.. /I../../wiretap $(GLIB_CFLAGS) \ + /I$(PCAP_DIR)\include -D_U_="" $(LOCAL_CFLAGS) + +LDFLAGS = /NOLOGO /INCREMENTAL:no /MACHINE:I386 $(LOCAL_LDFLAGS) + +!IFDEF LINK_PLUGINS_WITH_LIBETHEREAL +LINK_PLUGIN_WITH=..\..\epan\libethereal.lib +CFLAGS=/DHAVE_WIN32_LIBETHEREAL_LIB /D_NEED_VAR_IMPORT_ $(CFLAGS) +!ELSE +LINK_PLUGIN_WITH=..\plugin_api.obj +!ENDIF + +OBJECTS=packet-mate.obj mate_setup.obj mate_runtime.obj mate_util.obj mate_plugin.obj + +mate.dll mate.exp mate.lib : $(OBJECTS) $(LINK_PLUGIN_WITH) + link -dll /out:mate.dll $(LDFLAGS) $(OBJECTS) $(LINK_PLUGIN_WITH) \ + $(GLIB_LIBS) + +clean: + rm -f $(OBJECTS) mate.dll mate.exp mate.lib *.pdb + +distclean: clean diff --git a/plugins/mate/NEWS b/plugins/mate/NEWS new file mode 100644 index 0000000000..e69de29bb2 diff --git a/plugins/mate/examples/call.thing b/plugins/mate/examples/call.thing new file mode 100644 index 0000000000..46fc1e2f9d --- /dev/null +++ b/plugins/mate/examples/call.thing @@ -0,0 +1,4 @@ +# call.thing + +Action=Include; Filename=/Users/lego/things/call.mate; + diff --git a/plugins/mate/examples/cmplx_call.thing b/plugins/mate/examples/cmplx_call.thing new file mode 100644 index 0000000000..c2befd91fb --- /dev/null +++ b/plugins/mate/examples/cmplx_call.thing @@ -0,0 +1,78 @@ +# call_tracing.thing +# +# This config works with most of the ViG's call scenarios +# +# To work well with the Vig needs the following: +# a user to calling mapping to map emails to calling numbers (this only if calls begin towards an e-mail not a number) +# a opc:cic to term mapping to represent the MGw config (if you want to see megaco) +# + +Action=PDU; Proto=sip; Transport=ip; addr=ip.addr; sip_method=sip.Method; sip_callid=sip.Call-ID; calling=sdp.owner.username; +Action=LegKey; On=sip; sip_callid; addr; addr; +Action=LegStart; On=sip; sip_method=INVITE; +Action=LegStop; On=sip; sip_method=BYE; + +#Action=Include; Filename=users.thing; +# will contain: +Action=Transform; On=sip; Method=Every; calling=merlia; +Action=Transform; On=sip; Method=Insert; calling=1793900802; + +Action=PDU; Proto=q931; Transport=ip; addr=ip.addr; call_ref=q931.call_ref; q931_msg=q931.message_type; guid=h225.guid; called=q931.called_party_number.digits; calling=q931.calling_party_number.digits; q931_cause=q931.cause_value; h225_cause=h225.ReleaseCompleteReason; +Action=LegKey; On=q931; call_ref; addr; addr; +Action=LegStart; On=q931; q931_msg=5; +Action=LegStop; On=q931; q931_msg=90; + +Action=PDU; Proto=isup; Transport=mtp3; mtp3pc=mtp3.dpc; mtp3pc=mtp3.opc; cic=isup.cic; isup_msg=isup.message_type; called=isup.called; calling=isup.calling; isup_cause=isup.cause_indicator; +Action=LegKey; On=isup; cic; mtp3pc; mtp3pc; +Action=LegStart; On=isup; isup_msg=1; +Action=LegStop; On=isup; isup_msg=16; + +Action=PDU; Proto=h225.RasMessage; Transport=ip; ras_msg=h225.RasMessage; addr=ip.addr; guid=h225.guid; seqnum=h225.RequestSeqNum; +Action=LegKey; On=h225.RasMessage; addr; addr; seqnum; +Action=LegStart; On=h225.RasMessage; ras_msg|0|3|6|9|12|15|18|21|26|30; +Action=LegStop; On=h225.RasMessage; ras_msg|1|2|4|5|7|8|10|11|13|14|16|17|19|20|22|24|27|28|29|31; + +Action=PDU; Proto=megaco; Transport=ip; addr=ip.addr; megaco_ctx=megaco.context; megaco_trx=megaco.transid; megaco_msg=megaco.transaction; term=megaco.termid; +Action=LegKey; On=megaco; addr; addr; megaco_trx; +Action=LegStart; On=megaco; megaco_msg|Request|Notify; +Action=LegStop; On=megaco; megaco_msg=Reply; + +#Action=Include; Filename=mgw.thing; +# will contain the whole list of dpc:cic -> ds1_term mappings like the following +Action=Transform; On=isup; Method=Every; mtp3pc=1921; cic=1; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/1; +Action=Transform; On=isup; Method=Every; mtp3pc=1921; cic=2; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/2; +Action=Transform; On=isup; Method=Every; mtp3pc=1921; cic=14; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/14; + + +Action=PDU; Proto=rtsp; Transport=ip; isup_msg=isup.message_type; calling=X_Vig_Msisdn; rtsp_method=rtsp.method; rtsp_ses=rtsp.session; addr=ip.addr; rtsp_url=rtsp.url; +Action=LegKey; On=rtsp; rtsp_ses; +Action=LegStart; On=rtsp; rtsp_method=SETUP; +Action=LegStop; On=rtsp; rtsp_method=TEARDOWN; + +Action=PDU; Proto=radius; Transport=ip; radius_id=radius.id; radius_code=radius.code; class=radius.class; addr=ip.addr; calling=radius.calling; rad_sesid=radius.acct.sessionid; +Action=LegKey; On=radius; addr; addr; radius_id; +Action=LegStart; On=radius; radius_code|1|4; +Action=LegStop; On=radius; radius_code|2|3|5; + +Action=LegExtra; On=radius; calling; rad_sesid; + +Action=LegExtra; On=sip; calling!-; +Action=LegExtra; On=q931; called; calling; guid; q931_cause; h225_cause; +Action=LegExtra; On=h225.RasMessage; guid; +Action=LegExtra; On=isup; called; calling; isup_cause; term; +Action=LegExtra; On=megaco; term^DS1; megaco_ctx!Choose one; +Action=LegExtra; On=rtsp; rtsp_url; calling; +Action=LegExtra; On=radius; calling; + +Action=SesKey; Name=call; On=sip; calling; sip_callid; +Action=SesKey; Name=call; On=isup; calling; +Action=SesKey; Name=call; On=q931; calling; +Action=SesKey; Name=call; On=megaco; term^DS1; +Action=SesKey; Name=call; On=megaco; megaco_ctx; +Action=SesKey; Name=call; On=rtsp; calling; +Action=SesKey; Name=call; On=h225.RasMessage; guid; + +Action=SesExtra; On=call; called; term^DS1; megaco_ctx; guid; q931_cause; h225_cause; isup_cause; rtsp_url; diff --git a/plugins/mate/examples/ftp.thing b/plugins/mate/examples/ftp.thing new file mode 100644 index 0000000000..8cafd66a3a --- /dev/null +++ b/plugins/mate/examples/ftp.thing @@ -0,0 +1,38 @@ +# ftp.thing +Action=Settings; Debug_PDU=9; +# at every packet mate will try match the PDUS in order +# if Proto exists for the current frame a mate's PDU will be created. +# for attributes to be imported from the tree they must be inside +# either in the span of the the Proto +# or in that of any of the protocols in the Transport stack +# +# The PDU's AVPL will contain all the remaining attributes +Action=PDU; Name=FTP; Proto=ftp; Transport=tcp/ip; ftp_addr=ip.addr; tcp_port=tcp.port; addr=ftp.passive.ip; port=ftp.passive.port; ftp_cmd=ftp.request.command; +Action=PDU; Name=TCP; Proto=tcp; Transport=ip; addr=ip.addr; port=tcp.port; tcp_start=tcp.flags.syn; tcp_stop=tcp.flags.reset; tcp_stop=tcp.flags.fin; + +# once all PDUs for a packet have being created +# they will be matched against their relative LegKeys +# the attribute On specifies for which type of PDU the leg will be created +# the remaining of the AVPL will be used to create the key of the leg +# the matched attributes will become attributes of the leg +Action=LegKey; On=FTP; ftp_addr; ftp_addr; tcp_port; tcp_port; +Action=LegKey; On=TCP; addr; addr; port; port; + +# LegExtra is used to copy into the leg any other attributes from the PDU +# that may be usefull later in the analysis +Action=LegExtra; On=FTP; addr; port; +Action=LegExtra; On=TCP; tcp_start; tcp_stop; + + +# Legs are created when a PDU that belongs to them matches the LegStart AVPL +Action=LegStart; On=FTP; ftp_cmd=USER; +Action=LegStart; On=TCP; tcp_start=1; + +# and stopped when the PDU matches the LegStop AVPL +Action=LegStop; On=FTP; ftp_cmd=QUIT; +Action=LegStop; On=TCP; tcp_stop=1; + +Action=SesKey; Name=ftp_session; On=FTP; ftp_addr; ftp_addr; ftp_port; ftp_port; +Action=SesKey; Name=ftp_session; On=TCP; addr; port; + +Action=SesExtra; On=ftp_session; addr; port; diff --git a/plugins/mate/examples/mgw.thing b/plugins/mate/examples/mgw.thing new file mode 100644 index 0000000000..6535664807 --- /dev/null +++ b/plugins/mate/examples/mgw.thing @@ -0,0 +1,261 @@ +# the transformations example file + +# the match (Method=extact|Method=loose|Method=Every) +# must precede the replace (Method=replace|Method=Insert) + +# the list is going to be applied in order + +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=1; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/1; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=2; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/2; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=3; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/3; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=4; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/4; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=5; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/5; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=6; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/6; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=7; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/7; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=8; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/8; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=9; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/9; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=10; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/10; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=11; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/11; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=12; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/12; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=13; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/13; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=14; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/14; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=15; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/15; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=16; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/16; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=17; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/17; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=18; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/18; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=19; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/19; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=20; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/20; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=21; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/21; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=22; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/22; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=23; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/23; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=24; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/24; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=25; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/25; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=26; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/26; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=27; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/27; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=28; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/28; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=29; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/29; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=30; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/30; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=31; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/31; + +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=32; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/0; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=33; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/1; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=34; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/2; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=35; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/3; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=36; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/4; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=37; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/5; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=38; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/6; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=39; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/7; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=40; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/8; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=41; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/9; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=42; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/10; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=43; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/11; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=44; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/12; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=45; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/13; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=46; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/14; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=47; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/15; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=48; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/16; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=49; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/17; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=50; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/18; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=51; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/19; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=52; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/20; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=53; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/21; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=54; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/22; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=55; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/23; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=56; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/24; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=57; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/25; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=58; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/26; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=59; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/27; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=60; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/28; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=61; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/29; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=62; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/30; + + +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=1; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/1; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=2; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/2; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=3; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/3; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=4; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/4; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=5; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/5; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=6; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/6; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=7; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/7; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=8; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/8; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=9; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/9; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=10; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/10; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=11; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/11; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=12; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/12; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=13; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/13; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=14; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/14; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=15; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/15; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=16; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/16; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=17; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/17; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=18; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/18; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=19; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/19; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=20; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/20; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=21; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/21; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=22; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/22; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=23; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/23; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=24; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/24; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=25; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/25; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=26; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/26; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=27; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/27; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=28; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/28; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=29; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/29; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=30; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/30; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=31; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/31; + +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=32; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/0; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=33; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/1; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=34; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/2; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=35; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/3; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=36; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/4; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=37; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/5; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=38; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/6; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=39; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/7; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=40; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/8; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=41; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/9; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=42; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/10; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=43; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/11; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=44; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/12; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=45; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/13; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=46; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/14; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=47; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/15; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=48; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/16; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=49; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/17; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=50; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/18; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=51; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/19; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=52; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/20; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=53; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/21; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=54; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/22; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=55; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/23; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=56; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/24; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=57; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/25; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=58; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/26; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=59; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/27; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=60; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/28; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=61; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/29; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=62; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/30; + + diff --git a/plugins/mate/examples/mgw2.thing b/plugins/mate/examples/mgw2.thing new file mode 100644 index 0000000000..b07f53d370 --- /dev/null +++ b/plugins/mate/examples/mgw2.thing @@ -0,0 +1,18 @@ +# the transformations example file + +# the match (Method=extact|Method=loose|Method=Every) +# must precede the replace (Method=replace|Method=Insert) + +# the list is going to be applied in order + +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=49; +Action=Transform; On=isup; Method=Insert; term=DS1/3/2/1; + +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=61; +Action=Transform; On=isup; Method=Insert; term=DS1/2/2/29; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=61; +Action=Transform; On=isup; Method=Insert; term=DS1/2/2/29; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=63; +Action=Transform; On=isup; Method=Insert; term=DS1/2/2/31; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=109; +Action=Transform; On=isup; Method=Insert; term=DS1/2/3/13; diff --git a/plugins/mate/examples/mgw_mi.thing b/plugins/mate/examples/mgw_mi.thing new file mode 100644 index 0000000000..d76851b484 --- /dev/null +++ b/plugins/mate/examples/mgw_mi.thing @@ -0,0 +1,248 @@ +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=1; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/1; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=2; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/2; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=3; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/3; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=4; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/4; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=5; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/5; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=6; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/6; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=7; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/7; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=8; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/8; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=9; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/9; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=10; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/10; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=11; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/11; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=12; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/12; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=13; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/13; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=14; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/14; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=15; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/15; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=16; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/16; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=17; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/17; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=18; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/18; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=19; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/19; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=20; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/20; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=21; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/21; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=22; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/22; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=23; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/23; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=24; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/24; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=25; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/25; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=26; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/26; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=27; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/27; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=28; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/28; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=29; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/29; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=30; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/30; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=31; +Action=Transform; On=isup; Method=Insert; term=DS1/0/1/31; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=33; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/1; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=34; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/2; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=35; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/3; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=36; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/4; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=37; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/5; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=38; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/6; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=39; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/7; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=40; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/8; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=41; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/9; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=42; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/10; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=43; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/11; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=44; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/12; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=45; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/13; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=46; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/14; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=47; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/15; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=48; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/16; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=49; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/17; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=50; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/18; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=51; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/19; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=52; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/20; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=53; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/21; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=54; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/22; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=55; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/23; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=56; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/24; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=57; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/25; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=58; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/26; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=59; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/27; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=60; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/28; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=61; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/29; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=62; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/30; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=63; +Action=Transform; On=isup; Method=Insert; term=DS1/3/1/31; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=33; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/1; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=34; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/2; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=35; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/3; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=36; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/4; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=37; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/5; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=38; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/6; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=39; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/7; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=40; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/8; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=41; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/9; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=42; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/10; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=43; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/11; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=44; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/12; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=45; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/13; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=46; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/14; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=47; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/15; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=48; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/16; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=49; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/17; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=50; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/18; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=51; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/19; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=52; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/20; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=53; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/21; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=54; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/22; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=55; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/23; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=56; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/24; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=57; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/25; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=58; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/26; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=59; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/27; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=60; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/28; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=61; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/29; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=62; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/30; +Action=Transform; On=isup; Method=Every; mtp3pc=5378; cic=63; +Action=Transform; On=isup; Method=Insert; term=DS1/1/1/31; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=1; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/1; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=2; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/2; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=3; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/3; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=4; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/4; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=5; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/5; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=6; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/6; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=7; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/7; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=8; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/8; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=9; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/9; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=10; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/10; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=11; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/11; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=12; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/12; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=13; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/13; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=14; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/14; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=15; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/15; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=16; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/16; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=17; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/17; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=18; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/18; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=19; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/19; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=20; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/20; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=21; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/21; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=22; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/22; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=23; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/23; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=24; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/24; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=25; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/25; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=26; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/26; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=27; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/27; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=28; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/28; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=29; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/29; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=30; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/30; +Action=Transform; On=isup; Method=Every; mtp3pc=11522; cic=31; +Action=Transform; On=isup; Method=Insert; term=DS1/1/2/31; diff --git a/plugins/mate/examples/newcall.mate b/plugins/mate/examples/newcall.mate new file mode 100644 index 0000000000..4158c0b9a9 --- /dev/null +++ b/plugins/mate/examples/newcall.mate @@ -0,0 +1,22 @@ +Action=Settings; Debug_Cfg=1; Debug_Leg=5; +#Debug_PDU=9; + +Action=PDU; Name=Q931; Proto=q931; Transport=ip; addr=ip.addr; call_ref=q931.call_ref; q931_msg=q931.message_type; guid=h225.guid; called=q931.called_party_number.digits; calling=q931.calling_party_number.digits; q931_cause=q931.cause_value; h225_cause=h225.ReleaseCompleteReason; +Action=PDU; Name=ISUP; Proto=isup; Transport=mtp3; mtp3pc=mtp3.dpc; mtp3pc=mtp3.opc; cic=isup.cic; isup_msg=isup.message_type; called=isup.called; calling=isup.calling; isup_cause=isup.cause_indicator; +Action=PDU; Name=RAS; Proto=h225; Transport=ip; udp_port=udp.port; ras_msg=h225.RasMessage; addr=ip.addr; guid=h225.guid; seqnum=h225.RequestSeqNum; + +Action=Grp; Grp=isup; On=ISUP; cic; mtp3pc; mtp3pc; +Action=GrpStart; Grp=isup; isup_msg=1; +Action=GrpStop; Grp=isup; isup_msg=16; +Action=GrpExtra; Grp=isup; called; calling; isup_cause; + +Action=GrpKey; Name=q931; On=Q931; call_ref; addr; addr; +Action=GrpStart; Grp=q931; q931_msg=5; +Action=GrpStop; Grp=q931; q931_msg=90; +Action=GrpExtra; Grp=q931; guid; called; calling; q931_cause; h225_cause; + +Action=GrpKey; Name=ras; On=RAS; seqnum; addr; addr; +Action=GrpStart; Grp=ras; ras_msg|0|3|6|9|12|15|18|21|26|30; +Action=GrpStop; Grp=ras; ras_msg|1|2|4|5|7|8|10|11|13|14|16|17|19|20|22|24|27|28|29|31; +Action=GrpExtra; Grp=ras; guid; + diff --git a/plugins/mate/examples/nrg_sms.thing b/plugins/mate/examples/nrg_sms.thing new file mode 100644 index 0000000000..038deed5a2 --- /dev/null +++ b/plugins/mate/examples/nrg_sms.thing @@ -0,0 +1,20 @@ +# nrg_sms.thing +# (c) 2004, Luis E. Garcia Ontanon +# Distributed under GPL see http://www.gno.org/gpl.html for licencing info + +#Action=Settings; DiscardPduData=TRUE; Debug_Leak=3; Filename=/Users/lego/Desktop/call_thing.log; + +Action=PDU; Proto=ucp; Transport=ip; addr=ip.addr; ucp_trn=ucp.hdr.TRN; ucp_ot=ucp.hdr.OT; ucp_type=ucp.hdr.O_R; e164=ucp.parm.AdC; +Action=LegKey; On=ucp; ucp_trn; addr; addr; +Action=LegStart; On=ucp; ucp_type=79; +Action=LegStop; On=ucp; ucp_type=82; + +Action=LegExtra; On=ucp; e164; ucp_ot; + +Action=PDU; Proto=giop; Transport=ip; addr=ip.addr; giop_id=giop.request_id; giop_op=giop.request_op; giop_type=giop.type; +Action=LegKey; On=giop; giop_id; addr; addr; +Action=LegStart; On=giop; giop_type=0; +Action=LegStop; On=giop; giop_type=1; + +Action=LegExtra; On=giop; giop_op; + diff --git a/plugins/mate/examples/rad.thing b/plugins/mate/examples/rad.thing new file mode 100644 index 0000000000..55b7801d44 --- /dev/null +++ b/plugins/mate/examples/rad.thing @@ -0,0 +1,11 @@ +Action=Settings; SessionExpire=300; + +Action=PDU; Proto=radius; Transport=ip; radius_id=radius.id; radius_code=radius.code; class=radius.class; addr=ip.addr; calling=radius.calling; rad_sesid=radius.acct.sessionid; +Action=LegKey; On=radius; addr; addr; radius_id; +Action=LegStart; On=radius; radius_code|1|4; +Action=LegStop; On=radius; radius_code|2|3|5; + +Action=LegExtra; On=radius; calling; class; rad_sesid; + +Action=SesExtra; On=radses; calling; class; +Action=SesKey; Name=radses; On=radius; rad_sesid; diff --git a/plugins/mate/mate.h b/plugins/mate/mate.h new file mode 100644 index 0000000000..9b6de5f71b --- /dev/null +++ b/plugins/mate/mate.h @@ -0,0 +1,295 @@ +/* mate.h +* MATE -- Meta Analysis and Tracing Engine +* +* Copyright 2004, Luis E. Garcia Ontanon +* +* $Id$ +* +* Ethereal - Network traffic analyzer +* By Gerald Combs +* Copyright 1998 Gerald Combs +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#ifndef __MATE_H_ +#define __MATE_H_ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "plugins/plugin_api.h" +#include "moduleinfo.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mate_util.h" +#include "plugins/plugin_api_defs.h" + + +/* defaults */ + +#define DEFAULT_MAX_MATE_ITEMS 0 +#define DEFAULT_GOG_EXPIRATION 2.0 + +#ifdef WIN32 +#define DIR_SEP '\\' +#else +#define DIR_SEP '/' +#endif + +#define DEFAULT_MATE_LIB_PATH "matelib" + +#define MATE_ITEM_ID_SIZE 24 + +/* Config AVP Names */ +#define KEYWORD_ACTION "Action" +#define KEYWORD_SETTINGS "Settings" +#define KEYWORD_INCLUDE "Include" +#define KEYWORD_TRANSFORM "Transform" +#define KEYWORD_PDU "PduDef" +#define KEYWORD_PDUCRITERIA "PduCriteria" +#define KEYWORD_PDUEXTRA "PduExtra" +#define KEYWORD_PDUTRANSFORM "PduTransform" +#define KEYWORD_GOP "GopDef" +#define KEYWORD_GOPSTART "GopStart" +#define KEYWORD_GOPSTOP "GopStop" +#define KEYWORD_GOPEXTRA "GopExtra" +#define KEYWORD_GOPTRANSFORM "GopTransform" +#define KEYWORD_GOGDEF "GogDef" +#define KEYWORD_GOGKEY "GogKey" +#define KEYWORD_GOGEXTRA "GogExtra" +#define KEYWORD_GOGTRANSFORM "GogTransform" +#define KEYWORD_NAME "Name" +#define KEYWORD_ON "On" +#define KEYWORD_FOR "For" +#define KEYWORD_FROM "From" +#define KEYWORD_TO "To" +#define KEYWORD_MATCH "Match" +#define KEYWORD_MODE "Mode" +#define KEYWORD_FILENAME "Filename" +#define KEYWORD_PROTO "Proto" +#define KEYWORD_METHOD "Method" +#define KEYWORD_TRANSPORT "Transport" +#define KEYWORD_STRICT "Strict" +#define KEYWORD_LOOSE "Loose" +#define KEYWORD_EVERY "Every" +#define KEYWORD_REPLACE "Replace" +#define KEYWORD_INSERT "Insert" +#define KEYWORD_MAP "Map" +#define KEYWORD_GOGEXPIRE "GogExpiration" +#define KEYWORD_DISCARDPDU "DiscardPduData" +#define KEYWORD_LIBPATH "ThingLibPath" +#define KEYWORD_SHOWPDUTREE "ShowPduTree" +#define KEYWORD_SHOWGOPTIMES "ShowGopTimes" +#define KEYWORD_STOP "Stop" +#define KEYWORD_DROPGOP "DiscardUnassignedGop" +#define KEYWORD_DROPPDU "DiscardUnassignedPdu" + +#define KEYWORD_DEBUGFILENAME "Debug_File" +#define KEYWORD_DBG_GENERAL "Debug_General" +#define KEYWORD_DBG_CFG "Debug_Cfg" +#define KEYWORD_DBG_PDU "Debug_PDU" +#define KEYWORD_DBG_GOP "Debug_Gop" +#define KEYWORD_DBG_GOG "Debug_Gog" +#ifdef _AVP_DEBUGGING +#define KEYWORD_DBG_AVPLIB "Debug_AVP_Lib" +#define KEYWORD_DBG_AVP "Debug_AVP" +#define KEYWORD_DBG_AVP_OP "Debug_AVP_Op" +#define KEYWORD_DBG_AVPL "Debug_AVPL" +#define KEYWORD_DBG_AVPL_OP "Debug_AVPL_Op" +#endif + +#define VALUE_TOO ((void*)1) + +typedef enum _mate_item_type { + MATE_UNK_TYPE, + MATE_PDU_TYPE, + MATE_GOP_TYPE, + MATE_GOG_TYPE +} mate_item_type; + +typedef struct _mate_cfg_item mate_cfg_pdu; +typedef struct _mate_cfg_item mate_cfg_gop; +typedef struct _mate_cfg_item mate_cfg_gog; + +typedef struct _mate_item mate_item; +typedef struct _mate_item mate_pdu; +typedef struct _mate_item mate_gop; +typedef struct _mate_item mate_gog; + +typedef struct _mate_cfg_item { + guint8* name; + mate_item_type type; + GPtrArray* transforms; /* transformations to be applied */ + AVPL* extra; /* attributes to be added */ + guint last_id; /* keeps the last id given to an item of this kind */ + int hfid; + GHashTable* my_hfids; /* for creating register info */ + + /* pdu */ + gboolean discard_pdu_attributes; + gboolean last_to_be_created; + int hfid_proto; + GPtrArray* hfid_ranges; /* hfids of candidate ranges from which to extract attributes */ + GHashTable* hfids_attr; /* k=hfid v=avp_name */ + gboolean drop_pdu; + avpl_match_mode criterium_match_mode; + AVPL* criterium; /* must match to be created */ + int hfid_pdu_rel_time; + + /* gop */ + AVPL* start; /* start candidate avpl */ + AVPL* stop; /* stop candidate avpl */ + AVPL* key; /* key candidate avpl */ + gboolean show_pdu_tree; + gboolean show_gop_times; + gboolean drop_gop; + int hfid_gop_pdu; + int hfid_gop_start_time; + int hfid_gop_stop_time; + int hfid_gop_last_time; + int hfid_gop_num_pdus; + + /* gog */ + LoAL* keys; + float expiration; + int hfid_gog_num_of_gops; + int hfid_gog_gop; + +} mate_cfg_item; + +typedef struct _mate_config { + /* current defaults */ + float gog_expiration; /* default expirations for gogs if undefined in gog */ + gboolean discard_pdu_attributes; /* destroy the pdu's avpl once analyzed */ + gboolean drop_pdu; /* destroy the pdu if not assign to a gop */ + gboolean drop_gop; /* destroy the gop if not assign to a gog */ + guint8* mate_lib_path; /* where to look for "Include" files first */ + gboolean show_pdu_tree; + gboolean show_gop_times; + gboolean last_to_be_created; + avpl_match_mode match_mode; + avpl_replace_mode replace_mode; + + /* what to dbgprint */ + int dbg_lvl; + int dbg_cfg_lvl; + int dbg_pdu_lvl; + int dbg_gop_lvl; + int dbg_gog_lvl; + + guint8* mate_config_file; /* name of the config file */ + GString* mate_attrs_filter; /* "ip.addr || dns.id || ... " for the tap */ + GString* mate_protos_filter; /* "dns || ftp || ..." for the tap */ + FILE* dbg_facility; /* where to dump dbgprint output g_message if null */ + guint8* tap_filter; + + GHashTable* pducfgs; /* k=pducfg->name v=pducfg */ + GHashTable* gopcfgs; /* k=gopcfg->name v=gopcfg */ + GHashTable* gogcfgs; /* k=gogcfg->name v=gogcfg */ + GHashTable* transfs; /* k=transform->name v=transform */ + + GPtrArray* pducfglist; /* pducfgs in order of "execution" */ + GHashTable* gops_by_pduname; /* k=pducfg->name v=gopcfg */ + GHashTable* gogs_by_gopname; /* k=gopname v=loal where avpl->name == matchedgop->name */ + + GArray* hfrs; +} mate_config; + +typedef struct _mate_runtime_data { + guint current_items; /* a count of items */ + GMemChunk* mate_items; + float now; + guint highest_analyzed_frame; + + GHashTable* frames; /* k=frame.num v=pdus */ + GHashTable* items; /* k=item->id v=item */ + GHashTable* gops; /* k=gop_key_match v=gop */ + GHashTable* gogs; /* k=gog_key_match v=gog */ + +} mate_runtime_data; + +/* these are used to contain information regarding pdus, gops and gogs */ +struct _mate_item { + /* all three of them */ + guint8 id[MATE_ITEM_ID_SIZE]; /* 1:1 -> saving a g_malloc */ + mate_cfg_item* cfg; /* the type of this item */ + + AVPL* avpl; /* the attributes of the pdu/gop/gog */ + + /* these two have different uses in pdu and gop/gog */ + gint start; /* start of the pdu in the tvb / framenum of the start of a gop */ + gint end; /* end of the pdu in the tvb / framenum of the stop of a gop */ + + mate_item* next; /* in pdu: next in gop; in gop: next in gog; in gog this doesn't make any sense yet */ + + /* union _payload { */ + /* struct _pdu { */ + guint32 frame; /* wich frame I belog to? */ + mate_gop* gop; /* the gop the pdu belongs to (if any) */ + gboolean first; /* is this the first pdu in this frame? */ + gboolean is_start; /* this is the start pdu for this gop */ + gboolean is_stop; /* this is the stop pdu for this gop */ + gboolean after_release; /* this pdu comes after the stop */ + float rel_time; /* time since gop start if in gop or start of capture if unassigned */ + mate_pdu* next_in_frame; /* points to the next pdu in this frame */ + /* } pdu; */ + + /* struct _gop { */ + mate_gog* gog; /* the gog of a gop */ + mate_pdu* pdus; /* pdus that belong to a gop (NULL in gog) */ + float expiration; /* when will it expire once released? */ + gboolean released; /* has this gop been released? */ + int num_of_pdus; /* how many gops a gog has? */ + int num_of_after_release_pdus; /* how many pdus have arrived since it's been released */ + float start_time; /* time of start */ + float release_time; /* when this gop was released */ + float last_time; /* the rel time at which the last pdu/gop has been added */ + guint8* gop_key; /* used by gop */ + mate_pdu* last_pdu; /* last pdu in pdu's list */ + /* } gop; */ + + /* struct _gog { */ + mate_gop* gops; /* gops that belong to a gog (NULL in gop) */ + int num_of_gops; /* how many gops a gog has? */ + int num_of_released_gops; /* how many of them have already been released */ + guint last_n; /* the number of attributes the avpl had the last time we checked */ + GPtrArray* gog_keys; /* the keys under which this gog is stored in the gogs hash */ + mate_gop* last_gop; /* last gop in gop's list */ + /* } gog; */ + /* } o; */ +}; + +/* from mate_runtime.c */ +extern void init_mate_runtime_data(void); +extern mate_pdu* mate_get_pdus(guint32 framenum); +extern int mate_packet(void *prs _U_, packet_info *pinfo, epan_dissect_t *edt, void *dummy _U_); + +/* from mate_setup.c */ +extern mate_config* mate_make_config(guint8* filename); +extern mate_config* mate_cfg(); + +#endif diff --git a/plugins/mate/mate_plugin.c b/plugins/mate/mate_plugin.c new file mode 100644 index 0000000000..bbdfce6583 --- /dev/null +++ b/plugins/mate/mate_plugin.c @@ -0,0 +1,62 @@ +/* mate_plugin.c +* MATE -- Meta Analysis Tracing Engine +* +* Copyright 2004, Luis E. Garcia Ontanon +* +* $Id$ +* +* Ethereal - Network traffic analyzer +* By Gerald Combs +* Copyright 1998 Gerald Combs +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* this file is used temporarily to buid it as a plugin */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "plugins/plugin_api.h" +#include "moduleinfo.h" +#include +#include "plugins/plugin_api_defs.h" + + +/* these two are in packet-mate.c */ +void proto_register_mate(void); +void proto_reg_handoff_mate(void); +static gboolean initialized = FALSE; + +#ifndef ENABLE_STATIC +G_MODULE_EXPORT const gchar version[] = VERSION; + +G_MODULE_EXPORT void plugin_init(plugin_address_table_t *pat _U_ ) { + /* initialise the table of pointers needed in Win32 DLLs */ + plugin_address_table_init(pat); + + /* register the new protocol, protocol fields, and subtrees */ + if (! initialized ) { /* execute protocol initialization only once */ + proto_register_mate(); + initialized = 1; + } +} + +G_MODULE_EXPORT void plugin_reg_handoff(void) +{ + proto_reg_handoff_mate(); +} +#endif diff --git a/plugins/mate/mate_runtime.c b/plugins/mate/mate_runtime.c new file mode 100644 index 0000000000..1b753a8354 --- /dev/null +++ b/plugins/mate/mate_runtime.c @@ -0,0 +1,742 @@ +/* mate_runtime.c +* MATE -- Meta Analysis Tracing Engine +* +* Copyright 2004, Luis E. Garcia Ontanon +* +* $Id$ +* +* Ethereal - Network traffic analyzer +* By Gerald Combs +* Copyright 1998 Gerald Combs +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* TODO: + + fix debug_print levels + - timers + - on gops + - on gogs? + - on pdu? + + transformations + + maps +*/ + +#include "mate.h" + +typedef struct _mate_range mate_range; + +struct _mate_range { + guint start; + guint end; +}; + +typedef struct _tmp_pdu_data { + GPtrArray* ranges; + GHashTable* interesting; + mate_pdu* pdu; +} tmp_pdu_data; + + +mate_runtime_data* rd = NULL; +static mate_config* mc = NULL; + +static int zero = 0; + +static int* dbg = &zero; +static int* dbg_pdu = &zero; +static int* dbg_gop = &zero; +static int* dbg_gog = &zero; +static FILE* dbg_facility = NULL; + + +static gboolean destroy_mate_items(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_item* mi = (mate_item*) v; + + if (mi->gop_key) g_free(mi->gop_key); + if (mi->gog_keys) g_ptr_array_free (mi->gog_keys,TRUE); + delete_avpl(mi->avpl,TRUE); + + return TRUE; +} + +static void delete_mate_runtime_data(mate_runtime_data* rdat) { + g_hash_table_destroy(rdat->gops); + g_hash_table_destroy(rdat->frames); + g_hash_table_destroy(rdat->gogs); + + g_hash_table_foreach_remove(rdat->items,destroy_mate_items,FALSE); + g_hash_table_destroy(rdat->items); + + g_mem_chunk_destroy (rdat->mate_items); + + g_free(rdat); +} + + +extern void init_mate_runtime_data(void) { + + if (rd) { + delete_mate_runtime_data(rd); + } + + rd = g_malloc(sizeof(mate_runtime_data)); + + mc = mate_cfg(); + + rd->current_items = 0; + rd->now = -1.0; + rd->frames = g_hash_table_new(g_direct_hash,g_direct_equal); + rd->items = g_hash_table_new(g_str_hash,g_str_equal); + rd->gops = g_hash_table_new(g_str_hash,g_str_equal); + rd->gogs = g_hash_table_new(g_str_hash,g_str_equal); + rd->mate_items = g_mem_chunk_new("mate_items",sizeof(mate_item),1024,G_ALLOC_AND_FREE); +} + +/* creates a mate_item*/ +static mate_item* new_mate_item(mate_cfg_item* cfg) { + mate_item* it = g_mem_chunk_alloc(rd->mate_items); + + it->cfg = cfg; + cfg->last_id++; + + g_snprintf(it->id,MATE_ITEM_ID_SIZE,"%s:%i",cfg->name,cfg->last_id); + + it->avpl = NULL ; + it->start = 0 ; + it->end = 0 ; + it->frame = 0 ; + it->next = NULL ; + it->released = FALSE ; + it->expiration = 0.0; + + rd->current_items++; + + return it; +} + +/* a new gop */ +static mate_gop* new_gop(mate_cfg_gop* cfg, mate_pdu* pdu, guint8* key) { + mate_gop* gop = new_mate_item(cfg); + + dbg_print (dbg_gop,1,dbg_facility,"new_gop: %s: ``%s''",gop->id,key); + + gop->avpl = new_avpl("attributes"); + + gop->gog = NULL; + gop->pdus = pdu; + gop->last_pdu = pdu; + gop->gop_key = key; + gop->next = NULL; + gop->start_time = pdu->rel_time; + gop->release_time = 0.0; + gop->last_time = 0.0; + + pdu->gop = gop; + pdu->next = NULL; + pdu->is_start = TRUE; + pdu->rel_time = 0.0; + + return gop; +} + + +static void adopt_gop(mate_gog* gog, mate_gop* gop) { + dbg_print (dbg_gog,5,dbg_facility,"adopt_gop: gog=%X gop=%X",gog,gop); + + gop->gog = gog; + gop->next = NULL; + + gog->num_of_gops++; + + if (gog->last_gop) { + gog->last_gop->next = gop; + } + + gog->last_gop = gop; + + if (! gog->gops ) { + gog->gops = gop; + } + +} + +/* a new gog */ +static mate_gog* new_gog(mate_cfg_gog* cfg, mate_gop* gop) { + mate_gog* gog = new_mate_item(cfg); + + dbg_print (dbg_gog,1,dbg_facility,"new_gog: %s for %s",gog->id,gop->id); + + gog->cfg = cfg; + gog->avpl = new_avpl(""); + gog->gops = NULL; + gog->last_n = 0; + gog->gog_keys = g_ptr_array_new(); + gog->last_gop = NULL; + + gog->start_time = gop->rel_time; + + adopt_gop(gog,gop); + + return gog; +} + + +static void apply_transforms(mate_item* item) { + AVPL_Transf* transform = NULL; + guint i; + + for (i = 0; i < item->cfg->transforms->len; i++) { + transform = g_ptr_array_index(item->cfg->transforms,i); + avpl_transform(item->avpl, transform); + } +} + + +/* applies the extras for which type to what avpl */ +static void apply_extras(AVPL* from, AVPL* to, mate_cfg_item* cfg) { + AVPL* our_extras = NULL; + + if (cfg->extra) { + dbg_print (dbg,3,dbg_facility,"apply_extras: entering: from='%s' to='%s' for='%s'\n",from->name,to->name,cfg->name); + + our_extras = new_avpl_loose_match("",from, cfg->extra, FALSE) ; + + if (our_extras) { + merge_avpl(to,our_extras,TRUE); + delete_avpl(our_extras,FALSE); + } + } +} + +static void gog_remove_keys (mate_gog* gog) { + guint8* k; + + while (gog->gog_keys->len) { + k = (guint8*) g_ptr_array_remove_index_fast(gog->gog_keys,0); + g_hash_table_remove(rd->gogs,k); + g_free(k); + } +} + +static void reanalyze_gop(mate_gop* gop) { + LoAL* gog_keys = NULL; + AVPL* curr_gogkey = NULL; + void* cookie = NULL; + AVPL* gogkey_match = NULL; + mate_gog* gog = gop->gog; + guint8* key; + + if ( ! gog ) return; + + dbg_print (dbg_gog,1,dbg_facility,"reanalize_gop: gop=%s gog=%s\n",gop->id,gog->id); + + apply_extras(gop->avpl,gog->avpl,gog->cfg); + + if (gog->last_n != gog->avpl->len) { + + dbg_print (dbg_gog,2,dbg_facility,"analize_gop: gog has new attributes let's look for new keys\n"); + + gog_keys = gog->cfg->keys; + + while (( curr_gogkey = get_next_avpl(gog_keys,&cookie) )) { + if (( gogkey_match = new_avpl_exact_match("",gog->avpl,curr_gogkey,FALSE) )) { + key = avpl_to_str(gogkey_match); + if ( g_hash_table_lookup(rd->gogs,key) ) { + g_free(key); + } else { + dbg_print (dbg_gog,1,dbg_facility,"analize_gop: new key for gog=%s : %s\n",gog->id,key); + g_hash_table_insert(rd->gogs,key,gog); + g_ptr_array_add(gog->gog_keys,key); + } + delete_avpl(gogkey_match,FALSE); + } + } + gog->last_n = gog->avpl->len; + } + + if (gog->num_of_released_gops == gog->num_of_gops) { + gog->released = TRUE; + gog->expiration = gog->cfg->expiration + rd->now; + } else { + gog->released = FALSE; + } +} + +static void analize_gop(mate_gop* gop) { + mate_cfg_gog* cfg = NULL; + LoAL* gog_keys = NULL; + AVPL* curr_gogkey = NULL; + void* cookie = NULL; + AVPL* gogkey_match = NULL; + mate_gog* gog = NULL; + guint8* key = NULL; + + if ( ! ( gog = gop->gog ) ) { + /* no gog, let's either find one or create it if due */ + dbg_print (dbg_gog,1,dbg_facility,"analize_gop: no gog\n"); + + gog_keys = g_hash_table_lookup(mc->gogs_by_gopname,gop->cfg->name); + + if ( ! gog_keys ) { + dbg_print (dbg_gog,1,dbg_facility,"analize_gop: no gog_keys for this gop\n"); + return; + } + + /* We'll look for any matching gogkeys */ + + dbg_print (dbg_gog,1,dbg_facility,"analize_gop: got gog_keys\n"); + + while (( curr_gogkey = get_next_avpl(gog_keys,&cookie) )) { + + dbg_print (dbg_gog,2,dbg_facility,"analize_gop: about to match\n"); + + if (( gogkey_match = new_avpl_exact_match(curr_gogkey->name,gop->avpl,curr_gogkey,TRUE) )) { + + key = avpl_to_str(gogkey_match); + + dbg_print (dbg_gog,1,dbg_facility,"analize_gop: got gogkey_match: %s\n",key); + + if (( gog = g_hash_table_lookup(rd->gogs,key) )) { + dbg_print (dbg_gog,1,dbg_facility,"analize_gop: got already a matching gog\n"); + + if (gog->num_of_gops == gog->num_of_released_gops && gog->expiration < rd->now) { + dbg_print (dbg_gog,1,dbg_facility,"analize_gop: this is a new gog, not the old one, let's create it\n"); + + gog_remove_keys(gog); + + gog = new_gog(gog->cfg,gop); + gog->num_of_gops = 1; + + break; + } else { + dbg_print (dbg_gog,1,dbg_facility,"analize_gop: this is our gog\n"); + + g_free(key); + + if (! gop->gog ) adopt_gop(gog,gop); + + break; + } + } else { + dbg_print (dbg_gog,1,dbg_facility,"analize_gop: no such gog in hash, let's create a new one\n"); + + cfg = g_hash_table_lookup(mc->gogcfgs,curr_gogkey->name); + + gog = new_gog(cfg,gop); + gog->num_of_gops = 1; + } + + delete_avpl(gogkey_match,TRUE); + gogkey_match = NULL; + } + dbg_print (dbg_gog,1,dbg_facility,"analize_gop: no gogkey_match: %s\n",key); + } + + if (gogkey_match) delete_avpl(gogkey_match,TRUE); + + reanalyze_gop(gop); + } +} + + + +static void analize_pdu(mate_pdu* pdu) { + /* TODO: + return a g_boolean to tell we've destroyed the pdu when the pdu is unnassigned + destroy the unassigned pdu + */ + mate_cfg_gop* cfg = NULL; + mate_gop* gop = NULL; + guint8* gop_key; + guint8* orig_gop_key = NULL; + AVPL* candidate_gop_key_match = NULL; + AVPL* candidate_start = NULL; + AVPL* candidate_stop = NULL; + AVPL* our_extras = NULL; + AVPL* is_start = NULL; + AVPL* is_stop = NULL; + AVPL* gopkey_match = NULL; + guint8* avpl_str = NULL; + + dbg_print (dbg_gop,1,dbg_facility,"analize_pdu: %s\n",pdu->cfg->name); + + apply_transforms(pdu); + + cfg = g_hash_table_lookup(mc->gops_by_pduname,pdu->cfg->name); + + if (!cfg) return; + + + + candidate_gop_key_match = cfg->key; + + if (! candidate_gop_key_match) return; + avpl_str = avpl_to_str(candidate_gop_key_match); + dbg_print (dbg_gop,1,dbg_facility,"analize_pdu: got candidate key: %s\n",avpl_str); + g_free(avpl_str); + + gopkey_match = new_avpl_exact_match("",pdu->avpl,candidate_gop_key_match, TRUE); + + if (gopkey_match) { + gop_key = avpl_to_str(gopkey_match); + + candidate_start = cfg->start; + + if (candidate_start) { + avpl_str = avpl_to_str(candidate_start); + dbg_print (dbg_gop,1,dbg_facility,"analize_pdu: got candidate start: %s\n",avpl_str); + g_free(avpl_str); + is_start = new_avpl_exact_match("",pdu->avpl, candidate_start, FALSE); + } + + if (is_start) { + avpl_str = avpl_to_str(is_start); + dbg_print (dbg_gop,1,dbg_facility,"analize_pdu: got start match: %s\n",avpl_str); + g_free(avpl_str); + delete_avpl(is_start,FALSE); + } + + g_hash_table_lookup_extended(rd->gops,gop_key,(gpointer*)&orig_gop_key,(gpointer*)&gop); + + if ( gop ) { + g_free(gop_key); + + gop_key = orig_gop_key; + + dbg_print (dbg_gop,1,dbg_facility,"analize_pdu: got gop: %s\n",gop_key); + + if (is_start) { + if ( gop->released ) { + + dbg_print (dbg_gop,1,dbg_facility,"analize_pdu: new gop on released key before key expiration\n"); + + g_hash_table_remove(rd->gops,gop_key); + gop = new_gop(cfg,pdu,gop_key); + g_hash_table_insert(rd->gops,gop_key,gop); + } + + dbg_print (dbg_gop,1,dbg_facility,"analize_pdu: duplicate start on gop\n"); + + } + + pdu->gop = gop; + + if (gop->last_pdu) gop->last_pdu->next = pdu; + gop->last_pdu = pdu; + pdu->next = NULL; + pdu->rel_time -= gop->start_time; + if (gop->released) pdu->after_release = TRUE; + + } else { + + dbg_print (dbg_gop,1,dbg_facility,"analize_pdu: no gop\n"); + + if (is_start) { + gop = new_gop(cfg,pdu,gop_key); + + g_hash_table_insert(rd->gops,gop_key,gop); + } else { + dbg_print (dbg_gop,1,dbg_facility,"analize_pdu: an unassigned pdu\n"); + + pdu->gop = NULL; + pdu->next = NULL; + + return; + } + } + + if ( gop ) gop->num_of_pdus++; + + dbg_print (dbg_gop,4,dbg_facility,"analize_pdu: merge with key\n"); + + merge_avpl(gop->avpl,gopkey_match,TRUE); + delete_avpl(gopkey_match,TRUE); + + dbg_print (dbg_gop,4,dbg_facility,"analize_pdu: apply extras\n"); + + apply_extras(pdu->avpl,gop->avpl,gop->cfg); + + avpl_str = avpl_to_str(gop->avpl); + dbg_print (dbg_gop,1,dbg_facility,"analize_pdu: Gop Attributes: %s\n",avpl_str); + g_free(avpl_str); + + gop->last_time = pdu->rel_time; + + if ( ! gop->released) { + candidate_stop = cfg->stop; + if (candidate_stop) { + dbg_print (dbg_gop,4,dbg_facility,"analize_pdu: got candidate stop\n"); + is_stop = new_avpl_exact_match("",pdu->avpl, candidate_stop,FALSE); + } + + if(is_stop) { + avpl_str = avpl_to_str(is_stop); + dbg_print (dbg_gop,1,dbg_facility,"analize_pdu: is_stop: %s\n",avpl_str); + g_free(avpl_str); + delete_avpl(is_stop,FALSE); + + if (! gop->released) { + gop->released = TRUE; + gop->release_time = pdu->rel_time; + if (gop->gog) gop->gog->num_of_released_gops++; + } + + pdu->is_stop = TRUE; + } else { + dbg_print (dbg_gop,4,dbg_facility,"analize_pdu: is not a stop\n"); + } + } + + if (gop->last_n != gop->avpl->len) apply_transforms(gop); + + gop->last_n = gop->avpl->len; + + if (gop->gog) { + reanalyze_gop(gop); + } else { + analize_gop(gop); + } + + } else { + dbg_print (dbg_gop,4,dbg_facility,"analize_pdu: no gop_key\n"); + + pdu->gop = NULL; + } +} + +static void get_pdu_fields(gpointer k, gpointer v, gpointer p) { + int hfid = *((int*) k); + guint8* name = (guint8*) v; + tmp_pdu_data* data = (tmp_pdu_data*) p; + GPtrArray* fis; + field_info* fi; + guint i,j; + mate_range* curr_range; + guint start; + guint end; + AVP* avp; + guint8* s; + + /* no warning */ + k = p; + + fis = (GPtrArray*) g_hash_table_lookup(data->interesting,(gpointer) hfid); + + if (fis) { + for (i = 0; i < fis->len; i++) { + fi = (field_info*) g_ptr_array_index(fis,i); + + + start = fi->start; + end = fi->start + fi->length; + + dbg_print(dbg_pdu,6,dbg_facility,"get_pdu_fields: found field %i-%i\n",start,end); + + for (j = 0; j < data->ranges->len; j++) { + + curr_range = (mate_range*) g_ptr_array_index(data->ranges,j); + + dbg_print(dbg_pdu,6,dbg_facility,"get_pdu_fields: check if in range %i-%i\n",curr_range->start,curr_range->end); + + if (curr_range->end >= end && curr_range->start <= start) { + avp = new_avp_from_finfo(name, fi); + + s = avp_to_str(avp); + dbg_print(dbg_pdu,5,dbg_facility,"get_pdu_fields: got %s\n",s); + g_free(s); + + if (! insert_avp(data->pdu->avpl,avp) ) { + delete_avp(avp); + } + + } + } + } + } +} + +static mate_pdu* new_pdu(mate_cfg_pdu* cfg, guint32 framenum, field_info* proto, GHashTable* interesting) { + mate_pdu* pdu = new_mate_item(cfg); + field_info* cfi; + GPtrArray* ptrs; + mate_range* range; + mate_range* proto_range; + tmp_pdu_data data; + guint i,j; + gint min_dist; + field_info* range_fi; + gint32 last_start; + int hfid; + + dbg_print (dbg_pdu,2,dbg_facility,"new_pdu: type=%s framenum=%i\n",cfg->name,framenum); + + pdu->avpl = new_avpl(pdu->id); + pdu->cfg = cfg; + pdu->gop = NULL; + pdu->next_in_frame = NULL; + pdu->next = NULL; + pdu->first = FALSE; + pdu->is_start = FALSE; + pdu->is_stop = FALSE; + pdu->after_release = FALSE; + pdu->start = proto->start; + pdu->end = pdu->start + proto->length; + pdu->frame = framenum; + pdu->rel_time = rd->now; + + data.ranges = g_ptr_array_new(); + data.pdu = pdu; + data.interesting = interesting; + + /* first we create the proto range */ + proto_range = g_malloc(sizeof(mate_range)); + proto_range->start = pdu->start; + proto_range->end = pdu->end; + g_ptr_array_add(data.ranges,proto_range); + + dbg_print(dbg_pdu,3,dbg_facility,"new_pdu: proto range %u-%u\n",proto_range->start,proto_range->end); + + last_start = proto_range->start; + + for (i = 0; i < cfg->hfid_ranges->len; i++) { + hfid = *((int*)g_ptr_array_index(cfg->hfid_ranges,i)); + ptrs = (GPtrArray*) g_hash_table_lookup(interesting,GINT_TO_POINTER(hfid)); + min_dist = 99999; + range_fi = NULL; + + if (ptrs) { + for (j=0; j < ptrs->len; j++) { + cfi = (field_info*) g_ptr_array_index(ptrs,j); + if (cfi->start < last_start && min_dist >= (last_start - cfi->start) ) { + range_fi = cfi; + min_dist = last_start - cfi->start; + } + } + + if ( range_fi ) { + range = g_malloc(sizeof(range)); + range->start = range_fi->start; + range->end = range_fi->start + range_fi->length; + g_ptr_array_add(data.ranges,range); + + last_start = range_fi->start; + + dbg_print(dbg_pdu,3,dbg_facility,"new_pdu: transport(%i) range %i-%i\n",hfid,range->start,range->end); + } else { + + /* what do I do if I miss a range? */ + } + + } + } + + g_hash_table_foreach(cfg->hfids_attr,get_pdu_fields,&data); + + g_ptr_array_free(data.ranges,TRUE); + + return pdu; +} + +extern int mate_packet(void *prs _U_, packet_info *pinfo, epan_dissect_t *edt, void *dummy _U_) { + mate_pdu* pdu = NULL; + mate_pdu* last = NULL; + proto_tree* tree = edt->tree; + mate_cfg_pdu* cfg; + GPtrArray* protos; + field_info* proto; + guint i,j; + + rd->now = (((float)pinfo->fd->rel_secs) + (((float)pinfo->fd->rel_usecs) / 1000000) ); + + dbg_print (dbg,3,dbg_facility,"mate_packet: got frame number: %i at %d\n",pinfo->fd->num,rd->now); + + if ( tree->tree_data && tree->tree_data->interesting_hfids ) { + for ( i = 0; i < mc->pducfglist->len; i++ ) { + + cfg = g_ptr_array_index(mc->pducfglist,i); + + dbg_print (dbg_pdu,4,dbg_facility,"mate_packet: tryning to extract: %s\n",cfg->name); + protos = (GPtrArray*) g_hash_table_lookup(tree->tree_data->interesting_hfids,(gpointer) cfg->hfid_proto); + + if (protos) { + pdu = NULL; + + for (j = 0; j < protos->len; j++) { + + dbg_print (dbg_pdu,3,dbg_facility,"mate_packet: found matching proto, extracting: %s\n",cfg->name); + + proto = (field_info*) g_ptr_array_index(protos,j); + pdu = new_pdu(cfg, pinfo->fd->num, proto, tree->tree_data->interesting_hfids); + + if (!last) { + g_hash_table_insert(rd->frames,(gpointer) pinfo->fd->num,pdu); + last = pdu; + } else { + last->next_in_frame = pdu; + last = pdu; + } + + analize_pdu(pdu); + + if ( cfg->discard_pdu_attributes ) { + delete_avpl(pdu->avpl,TRUE); + pdu->avpl = NULL; + } + + } + + if ( pdu && cfg->last_to_be_created ) break; + } + } + + + } + + + rd->highest_analyzed_frame = pinfo->fd->num; + + dbg_print (dbg,6,dbg_facility,"do_mate: make_pdus done\n"); + + return 0; +} + +extern mate_pdu* mate_get_pdus(guint32 framenum) { + + if (rd) { + return (mate_pdu*) g_hash_table_lookup(rd->frames,GUINT_TO_POINTER(framenum)); + } else { + return NULL; + } +} + +/* this will be called when the mate's dissector is initialized */ +extern void initialize_mate(guint8* configuration_filename) { + dbg_print (dbg,5,dbg_facility,"initialize_mate: entering"); + + if (( mc = mate_cfg() )) { + + dbg_pdu = &(mc->dbg_pdu_lvl); + dbg_gop = &(mc->dbg_gop_lvl); + dbg_gog = &(mc->dbg_gog_lvl); + + } else { + return; + } + + return; +} + + diff --git a/plugins/mate/mate_setup.c b/plugins/mate/mate_setup.c new file mode 100644 index 0000000000..93def5120f --- /dev/null +++ b/plugins/mate/mate_setup.c @@ -0,0 +1,1417 @@ +/* mate_setup.c +* MATE -- Meta Analysis Tracing Engine +* +* Copyright 2004, Luis E. Garcia Ontanon +* +* $Id$ +* +* Ethereal - Network traffic analyzer +* By Gerald Combs +* Copyright 1998 Gerald Combs +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "mate.h" + +/* FIXME: config names should be at most 8 chars! */ + +static int* dbg; + +static int dbg_cfg_lvl = 1; +static int* dbg_cfg = &dbg_cfg_lvl; + +FILE* dbg_facility; + +typedef gboolean config_action(AVPL* avpl); + +/* the current mate_config */ +static mate_config* matecfg = NULL; + +/* key: the name of the action +value: a pointer to an config_action */ +static GHashTable* actions = NULL; + +/* aestetics: I like keywords separated from user attributes */ +static AVPL* all_keywords = NULL; + +/* use as: setting = extract_named_xxx(avpl,keyword,default_value); */ +static int extract_named_int(AVPL* avpl, guint8* keyword, int value) { + AVP* avp = NULL; + + if(( avp = extract_avp_by_name(avpl,keyword) )) { + value = strtol(avp->v,NULL,10); + } + + return value; +} + +static float extract_named_float(AVPL* avpl, guint8* keyword, float value) { + AVP* avp = NULL; + + if(( avp = extract_avp_by_name(avpl,keyword) )) { + value = (float) strtod(avp->v,NULL); + } + + return value; +} + +static gboolean extract_named_bool(AVPL* avpl, guint8* keyword, gboolean value) { + AVP* avp = NULL; + if(( avp = extract_avp_by_name(avpl,keyword) )) { + value = ((g_strcasecmp(avp->v,"TRUE") == 0) ? TRUE : FALSE); + } + + return value; +} + +static guint8* extract_named_str(AVPL* avpl, guint8* keyword, guint8* value) { + AVP* avp = NULL; + + if(( avp = extract_avp_by_name(avpl,keyword) )) { + value = avp->v; + } + + return value; +} + +/* lookups for the string value of the given named attribute from a given hash */ +static gpointer lookup_using_index_avp(AVPL* avpl, guint8* keyword, GHashTable* table, guint8** avp_value) { + AVP* avp = extract_avp_by_name(avpl,keyword); + + if (avp) { + *avp_value = avp->v; + return g_hash_table_lookup(table,avp->v); + } else { + *avp_value = NULL; + return NULL; + } +} + + +/* creates and initializes a mate_cfg_item */ +static mate_cfg_item* new_mate_cfg_item(guint8* name) { + mate_cfg_pdu* new = g_malloc(sizeof(mate_cfg_item)); + + new->name = g_strdup(name); + new->type = MATE_UNK_TYPE; + new->transforms = g_ptr_array_new(); + new->extra = new_avpl(name); + new->hfid_proto = -1; + new->discard_pdu_attributes = matecfg->discard_pdu_attributes; + new->last_to_be_created = matecfg->last_to_be_created; + new->drop_pdu = matecfg->drop_pdu; + new->drop_gop = matecfg->drop_gop; + new->expiration = matecfg->gog_expiration; + new->show_pdu_tree = matecfg->show_pdu_tree; + new->show_gop_times = matecfg->show_gop_times; + new->last_id = 0; + new->hfid_ranges = NULL; + new->hfids_attr = NULL; + new->criterium = NULL; + new->start = NULL; + new->stop = NULL; + new->key = NULL; + new->keys = NULL; + + new->hfid = -1; + new->hfid_pdu_rel_time = -1; + new->my_hfids = g_hash_table_new(g_str_hash,g_str_equal); + + new->hfid_gop_pdu = -1; + new->hfid_gop_start_time = -1; + new->hfid_gop_stop_time = -1; + new->hfid_gop_last_time = -1; + new->hfid_gop_num_pdus = -1; + + new->hfid_gog_num_of_gops = -1; + new->hfid_gog_gop = -1; + + return new; +} + +/* for cleaning hashes */ +static gboolean free_both(gpointer k, gpointer v, gpointer p) { + g_free(k); + if (p) g_free(v); + return TRUE; +} + +static void delete_mate_cfg_item(mate_cfg_item* cfg, gboolean avp_items_too) { + + g_free(cfg->name); + + if (avp_items_too) { + if (cfg->extra) delete_avpl(cfg->extra,TRUE); + if (cfg->start) delete_avpl(cfg->start,TRUE); + if (cfg->stop) delete_avpl(cfg->stop,TRUE); + if (cfg->key) delete_avpl(cfg->key,TRUE); + if (cfg->criterium) delete_avpl(cfg->criterium,TRUE); + if (cfg->keys) delete_loal(cfg->keys,TRUE,TRUE); + } + + if (cfg->transforms) g_ptr_array_free(cfg->transforms,TRUE); + + if (cfg->hfid_ranges) + g_ptr_array_free(cfg->hfid_ranges,TRUE); + + if (cfg->hfids_attr) + g_hash_table_foreach_remove(cfg->hfids_attr,free_both, VALUE_TOO ); + +} + +static mate_cfg_pdu* new_pducfg(guint8* name) { + mate_cfg_pdu* new = new_mate_cfg_item(name); + + new->type = MATE_PDU_TYPE; + new->hfid_ranges = g_ptr_array_new(); + new->hfids_attr = g_hash_table_new(g_int_hash,g_int_equal); + + g_ptr_array_add(matecfg->pducfglist,(gpointer) new); + + g_hash_table_insert(matecfg->pducfgs,(gpointer) new->name,(gpointer) new); + + return new; +} + +static mate_cfg_gop* new_gopcfg(guint8* name) { + mate_cfg_gop* new = new_mate_cfg_item(name); + new->type = MATE_GOP_TYPE; + + g_hash_table_insert(matecfg->gopcfgs,(gpointer) new->name, (gpointer) new); + + return new; +} + +static mate_cfg_gog* new_gogcfg(guint8* name) { + mate_cfg_gog* new = new_mate_cfg_item(name); + new->type = MATE_GOG_TYPE; + + new->keys = new_loal(name); + new->expiration = matecfg->gog_expiration; + + g_hash_table_insert(matecfg->gogcfgs,new->name,new); + + return new; +} + +static gboolean free_cfgs(gpointer k _U_, gpointer v, gpointer p) { + delete_mate_cfg_item((mate_cfg_item*)v,(gboolean) p); + return TRUE; +} + +extern void destroy_mate_config(mate_config* mc , gboolean avplib_too) { + if (mc->dbg_facility) fclose(mc->dbg_facility); + if (mc->mate_lib_path) g_free(mc->mate_lib_path); + if (mc->mate_config_file) g_free(mc->mate_config_file); + if (mc->mate_attrs_filter) g_string_free(mc->mate_attrs_filter,TRUE); + if (mc->mate_protos_filter) g_string_free(mc->mate_protos_filter,TRUE); + if (mc->pducfglist) g_ptr_array_free(mc->pducfglist,FALSE); + + if (mc->gogs_by_gopname) { + g_hash_table_destroy(mc->gogs_by_gopname); + } + + if (mc->pducfgs) { + g_hash_table_foreach_remove(mc->pducfgs,free_cfgs,(gpointer) avplib_too); + g_hash_table_destroy(mc->pducfgs); + } + + if (mc->gopcfgs) { + g_hash_table_foreach_remove(mc->gopcfgs,free_cfgs,(gpointer) avplib_too); + g_hash_table_destroy(mc->gopcfgs); + } + + if (mc->gogcfgs) { + g_hash_table_foreach_remove(mc->gogcfgs,free_cfgs,(gpointer) avplib_too); + g_hash_table_destroy(mc->gogcfgs); + } + + if (mc->tap_filter) g_free(mc->tap_filter); + + if (mc->hfrs) g_array_free(mc->hfrs,TRUE); + g_free(mc); + +} + + +/* a configuration error */ +static void mate_config_error(LoAL* loal _U_ ,guint8* line _U_ , guint8* fmt, ...) { + va_list list; + guint8* desc; + + va_start( list, fmt ); + desc = g_strdup_vprintf(fmt, list); + va_end( list ); + + dbg_print (dbg,0,dbg_facility,"mate_config_error: %s",desc); + + g_warning(desc); + g_free(desc); + +} + + +static gboolean mate_load_config(guint8* filename) { + LoAL* loal = loal_from_file(filename); + AVPL* avpl; + guint8* line = NULL; + config_action* action; + guint8* name; + + if (loal) { + while(( avpl = extract_first_avpl(loal) )) { + line = avpl_to_str(avpl); + + dbg_print (dbg_cfg,3,dbg_facility,"mate_make_config: current line: %s",line); + + action = lookup_using_index_avp(avpl, KEYWORD_ACTION, actions,&name); + + if (action) { + if ( ! action(avpl) ) { + mate_config_error(loal,line,"mate: Error on AVPL: '%s'",name); + return FALSE; + } + } else { + mate_config_error(loal,line,"mate: Error: action '%s' unknown",name); + return FALSE; + } + + g_free(line); + } + + return TRUE; + } else { + g_warning("mate: could not load '%s'",filename); + return FALSE; + } +} + +static gboolean add_hfid(guint8* what, guint8* how, GHashTable* where) { + header_field_info* hfi = NULL; + header_field_info* first_hfi = NULL; + gboolean exists = FALSE; + guint8* as; + guint8* h; + int* ip; + + hfi = proto_registrar_get_byname(what); + + while(hfi) { + first_hfi = hfi; + hfi = hfi->same_name_prev; + } + + hfi = first_hfi; + + while (hfi) { + exists = TRUE; + ip = g_malloc(sizeof(int)); + + *ip = hfi->id; + + if (( as = g_hash_table_lookup(where,ip) )) { + g_free(ip); + if (! g_str_equal(as,how)) { + g_warning("Error: add_hfid: attempt to add %s(%i) as %s" + " failed: hfid already added as '%s'",what,hfi->id,how,as); + return FALSE; + } + } else { + h = g_strdup(how); + g_hash_table_insert(where,ip,h); + + + dbg_print (dbg,5,dbg_facility,"add_hfid: added hfid %s(%i) as %s",what,*ip,how); + } + + hfi = hfi->same_name_next; + + } + + if (! exists) { + g_warning("Error: add_hfid(%s): cannot find",what); + } + + return exists; +} + +static gboolean config_pdu(AVPL* avpl) { + guint8* name = NULL; + guint8* transport = extract_named_str(avpl,KEYWORD_TRANSPORT,NULL); + guint8* proto = extract_named_str(avpl,KEYWORD_PROTO,"no_protocol"); + mate_cfg_pdu* cfg = lookup_using_index_avp(avpl,KEYWORD_NAME,matecfg->pducfgs,&name); + header_field_info* hfi; + int* hfidp; + gchar** transports; + guint i; + AVP* attr_avp; + + if (! cfg) { + cfg = new_pducfg(name); + } else { + g_warning("MATE: PDU Config error: No such PDU: %s",cfg->name); + delete_avpl(avpl,TRUE); + return FALSE; + } + + cfg->last_to_be_created = extract_named_bool(avpl,KEYWORD_STOP,matecfg->last_to_be_created); + cfg->discard_pdu_attributes = extract_named_bool(avpl,KEYWORD_DISCARDPDU,matecfg->discard_pdu_attributes); + cfg->drop_pdu = extract_named_bool(avpl,KEYWORD_DROPPDU,matecfg->drop_pdu); + + hfi = proto_registrar_get_byname(proto); + + if (hfi) { + cfg->hfid_proto = hfi->id; + } else { + g_warning("mate: PDU Config error: no such proto: %s",proto); + delete_avpl(avpl,TRUE); + return FALSE; + } + + g_string_sprintfa(matecfg->mate_protos_filter,"||%s",proto); + + if ( transport ) { + + transports = g_strsplit(transport,"/",0); + + if (transports) { + for (i=0; transports[i]; i++) { + hfi = proto_registrar_get_byname(transports[i]); + if (hfi) { + hfidp = g_malloc(sizeof(int)); + *hfidp = hfi->id; + g_ptr_array_add(cfg->hfid_ranges,(gpointer)hfidp); + g_string_sprintfa(matecfg->mate_attrs_filter, "||%s",transports[i]); + } else { + g_warning("mate: PDU Config error: no such proto: %s for Transport",proto); + g_strfreev(transports); + delete_avpl(avpl,TRUE); + return FALSE; + } + } + + g_strfreev(transports); + } + } else { + g_warning("mate: PDU Config error: no Transport for %s",cfg->name); + return FALSE; + } + + while (( attr_avp = extract_first_avp(avpl) )) { + if ( ! add_hfid(attr_avp->v,attr_avp->n,cfg->hfids_attr) ) { + g_warning("mate: PDU Config error: failed to set PDU attribute '%s'",attr_avp->n); + delete_avpl(avpl,TRUE); + return FALSE; + } + g_string_sprintfa(matecfg->mate_attrs_filter, "||%s",attr_avp->v); + } + + delete_avpl(avpl,TRUE); + return TRUE; +} + +static gboolean config_pduextra(AVPL* avpl) { + guint8* name; + AVP* attr_avp; + mate_cfg_pdu* cfg = lookup_using_index_avp(avpl,KEYWORD_FOR,matecfg->pducfgs,&name); + + if (! cfg) { + g_warning("mate: PduExtra Config error: no such Pdu %s",name); + delete_avpl(avpl,TRUE); + return FALSE; + } + + cfg->last_to_be_created = extract_named_bool(avpl,KEYWORD_STOP,cfg->last_to_be_created); + cfg->discard_pdu_attributes = extract_named_bool(avpl,KEYWORD_DISCARDPDU,cfg->discard_pdu_attributes); + cfg->drop_pdu = extract_named_bool(avpl,KEYWORD_DROPPDU,cfg->drop_pdu); + + while (( attr_avp = extract_first_avp(avpl) )) { + if ( ! add_hfid(attr_avp->v,attr_avp->n,cfg->hfids_attr) ) { + g_warning("mate: PDU Config error: failed to set attr %s",attr_avp->n); + delete_avp(attr_avp); + delete_avpl(avpl,TRUE); + return FALSE; + } + g_string_sprintfa(matecfg->mate_attrs_filter, "||%s",attr_avp->v); + } + + delete_avpl(avpl,TRUE); + return TRUE; + +} + + + +static gboolean config_include(AVPL* avpl) { + guint8* filename = extract_named_str(avpl,KEYWORD_FILENAME,NULL); + + /* TODO: use library path */ + if( ! filename ) { + mate_config_error(NULL,NULL,"mate: Include file error: no filename"); + return FALSE; + } + + /* FIXME: stop recursion */ + if ( ! mate_load_config(filename) ) { + mate_config_error(NULL,NULL,"mate: Error Loading '%s'",filename); + return FALSE; + } + + return TRUE; +} + + +static gboolean config_settings(AVPL*avpl) { + AVP* avp; + +#ifdef _AVP_DEBUGGING + int debug_avp = 0; + int dbg_avp = 0; + int dbg_avp_op = 0; + int dbg_avpl = 0; + int dbg_avpl_op = 0; +#endif + + + matecfg->gog_expiration = extract_named_bool(avpl, KEYWORD_GOGEXPIRE,matecfg->gog_expiration); + matecfg->discard_pdu_attributes = extract_named_bool(avpl, KEYWORD_DISCARDPDU,matecfg->discard_pdu_attributes); + matecfg->drop_pdu = extract_named_bool(avpl, KEYWORD_DROPPDU,matecfg->drop_pdu); + matecfg->drop_gop = extract_named_bool(avpl, KEYWORD_DROPGOP,matecfg->drop_gop); + matecfg->show_pdu_tree = extract_named_bool(avpl, KEYWORD_SHOWPDUTREE,matecfg->show_pdu_tree); + matecfg->show_gop_times = extract_named_bool(avpl, KEYWORD_SHOWGOPTIMES,matecfg->show_gop_times); + + if(( avp = extract_avp_by_name(avpl,KEYWORD_DEBUGFILENAME) )) { + matecfg->dbg_facility = dbg_facility = fopen(avp->v,"w"); + delete_avp(avp); + avp = NULL; + } + + matecfg->dbg_lvl = extract_named_int(avpl, KEYWORD_DBG_GENERAL,0); + matecfg->dbg_cfg_lvl = extract_named_int(avpl, KEYWORD_DBG_CFG,0); + matecfg->dbg_gop_lvl = extract_named_int(avpl, KEYWORD_DBG_PDU,0); + matecfg->dbg_gop_lvl = extract_named_int(avpl, KEYWORD_DBG_GOP,0); + matecfg->dbg_gog_lvl = extract_named_int(avpl, KEYWORD_DBG_GOG,0); + +#ifdef _AVP_DEBUGGING + setup_avp_debug(dbg_facility, + extract_named_int(avpl, KEYWORD_DBG_AVPLIB,0), + extract_named_int(avpl, KEYWORD_DBG_AVP,0), + extract_named_int(avpl, KEYWORD_DBG_AVP_OP,0), + extract_named_int(avpl, KEYWORD_DBG_AVPL,0), + extract_named_int(avpl, KEYWORD_DBG_AVPL_OP,0)); +#endif + + dbg_cfg_lvl = matecfg->dbg_cfg_lvl; + + return TRUE; +} + +static gboolean config_transform(AVPL* avpl) { + guint8* name = extract_named_str(avpl, KEYWORD_NAME, NULL); + guint8* match = extract_named_str(avpl, KEYWORD_MATCH, NULL); + guint8* mode = extract_named_str(avpl, KEYWORD_MODE, NULL); + avpl_match_mode match_mode; + avpl_replace_mode replace_mode; + AVPL_Transf* t; + AVPL_Transf* last; + + if ( match ) { + if ( g_strcasecmp(match,KEYWORD_LOOSE) == 0 ) { + match_mode = AVPL_LOOSE; + } else if ( g_strcasecmp(match,KEYWORD_EVERY) == 0 ) { + match_mode = AVPL_EVERY; + } else if ( g_strcasecmp(match,KEYWORD_STRICT) == 0 ) { + match_mode = AVPL_STRICT; + } else { + g_warning("mate: Transform Config error: no such match mode: %s",match); + return FALSE; + } + } else { + match_mode = matecfg->match_mode; + } + + if ( mode ) { + if ( g_strcasecmp(mode,KEYWORD_INSERT) == 0 ) { + replace_mode = AVPL_INSERT; + } else if ( g_strcasecmp(mode,KEYWORD_REPLACE) == 0 ) { + replace_mode = AVPL_REPLACE; + } else { + g_warning("mate: Transform Config error: no such replace mode: %s",mode); + return FALSE; + } + + } else { + replace_mode = matecfg->replace_mode; + } + + if (! name) { + g_warning("mate: Transform Config error: no Name"); + return FALSE; + } + + t = new_avpl_transform(name,avpl, match_mode, replace_mode); + + if (( last = g_hash_table_lookup(matecfg->transfs,name) )) { + while (last->next) last = last->next; + last->next = t; + } else { + g_hash_table_insert(matecfg->transfs,t->name,t); + } + + return TRUE; +} + +static gboolean config_xxx_transform(AVPL* avpl, GHashTable* hash, guint8* keyword) { + guint8* pdu_name; + guint8* name; + AVPL_Transf* transf = lookup_using_index_avp(avpl,KEYWORD_NAME,matecfg->transfs,&name); + mate_cfg_pdu* cfg = lookup_using_index_avp(avpl,KEYWORD_FOR,hash,&pdu_name);; + + if (! name ) { + g_warning("mate: %s Config error: No Name",keyword); + return FALSE; + } + + if (! pdu_name ) { + g_warning("mate: %s Config error: No For",keyword); + return FALSE; + } + + if (! cfg ) { + g_warning("mate: %s Config error: %s doesn't exist",keyword,pdu_name); + return FALSE; + } + + if (!transf) { + g_warning("mate: %s Config error: Transform %s doesn't exist",keyword,name); + return FALSE; + } + + g_ptr_array_add(cfg->transforms,transf); + + return TRUE; +} + +static gboolean config_pdu_transform(AVPL* avpl) { + return config_xxx_transform(avpl, matecfg->pducfgs, KEYWORD_PDUTRANSFORM); +} + +static gboolean config_gop_transform(AVPL* avpl) { + return config_xxx_transform(avpl, matecfg->gopcfgs, KEYWORD_GOPTRANSFORM); +} + +static gboolean config_gog_transform(AVPL* avpl) { + return config_xxx_transform(avpl, matecfg->gogcfgs, KEYWORD_GOPTRANSFORM); +} + +static gboolean config_gop(AVPL* avpl) { + guint8* name = NULL; + mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_NAME,matecfg->gopcfgs,&name); + guint8* on = extract_named_str(avpl,KEYWORD_ON,NULL); + + if (!cfg) { + cfg = new_gopcfg(name); + } else { + g_warning("mate: GopDef Config error: Gop '%s' exists already",name); + delete_avpl(avpl,TRUE); + return FALSE; + } + + if (! on ) { + g_warning("mate: GopDef Config error: No 'On' AVP"); + delete_avpl(avpl,TRUE); + return FALSE; + } + + if (g_hash_table_lookup(matecfg->gops_by_pduname,on) ) { + g_warning("mate: GopDef Config error: Gop for Pdu '%s' exists already",on); + delete_avpl(avpl,TRUE); + return FALSE; + } else { + g_hash_table_insert(matecfg->gops_by_pduname,on,cfg); + } + + cfg->drop_gop = extract_named_bool(avpl, KEYWORD_DROPGOP,matecfg->drop_gop); + cfg->show_pdu_tree = extract_named_bool(avpl, KEYWORD_SHOWPDUTREE, matecfg->show_pdu_tree); + cfg->show_gop_times = extract_named_bool(avpl, KEYWORD_SHOWGOPTIMES,matecfg->show_gop_times); + + cfg->key = avpl; + + return TRUE; +} + +static gboolean config_start(AVPL* avpl) { + guint8* name; + mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gopcfgs,&name);; + + if (!cfg) { + g_warning("mate: GopStart Config error: Gop %s does not exist",name); + delete_avpl(avpl,TRUE); + return FALSE; + } + + if (cfg->start) { + /* FEATURE: more start conditions */ + g_warning("mate: GopStart Config error: GopStart alredy exists for %s",name); + delete_avpl(avpl,TRUE); + return FALSE; + } + + cfg->start = avpl; + + return TRUE; +} + +static gboolean config_stop(AVPL* avpl) { + guint8* name; + mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gopcfgs,&name);; + + if (!cfg) { + g_warning("mate: GopStop Config error: Gop %s does not exist",name); + delete_avpl(avpl,TRUE); + return FALSE; + } + + if (cfg->stop) { + /* FEATURE: more GopStop conditions */ + g_warning("mate: GopStart Config error: GopStop alredy exists for %s",name); + delete_avpl(avpl,TRUE); + return FALSE; + } + + cfg->stop = avpl; + + return TRUE; +} + +static gboolean config_gopextra(AVPL* avpl) { + guint8* name; + mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gopcfgs,&name);; + + if (!cfg) { + g_warning("mate: GopExtra Config error: Gop %s does not exist",name); + delete_avpl(avpl,TRUE); + return FALSE; + } + + cfg->drop_gop = extract_named_bool(avpl, KEYWORD_DROPGOP,cfg->drop_gop); + cfg->show_pdu_tree = extract_named_bool(avpl, KEYWORD_SHOWPDUTREE, cfg->show_pdu_tree); + cfg->show_gop_times = extract_named_bool(avpl, KEYWORD_SHOWGOPTIMES,cfg->show_gop_times); + + merge_avpl(cfg->extra,avpl,TRUE); + + delete_avpl(avpl,TRUE); + return TRUE; +} + +static gboolean config_gog(AVPL* avpl) { + guint8* name = extract_named_str(avpl, KEYWORD_NAME,NULL); + mate_cfg_gog* cfg = NULL; + + if (!name) { + g_warning("mate: GogDef Config error: no Name"); + return FALSE; + } + + if ( g_hash_table_lookup(matecfg->gogcfgs,name) ) { + g_warning("mate: GogDef Config error: Gog %s exists already", name); + return FALSE; + } + + cfg = new_gogcfg(name); + + cfg->expiration = extract_named_float(avpl, KEYWORD_GOGEXPIRE,matecfg->gog_expiration); + + return TRUE; +} + +static gboolean config_gogkey(AVPL* avpl) { + guint8* name; + mate_cfg_gog* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gogcfgs,&name); + AVPL* reverse_avpl; + LoAL* gogkeys; + guint8* on = extract_named_str(avpl,KEYWORD_ON,NULL); + + if ( ! name || ! cfg ) { + if ( ! name ) + g_warning("mate: GogKey Config error: no Name"); + else + g_warning("mate: GogKey Config error: no such Gop %s",name); + + return FALSE; + } + + if (! on ) { + g_warning("mate: GogKey Config error: no " KEYWORD_ON); + return FALSE; + } + + rename_avpl(avpl,name); + + gogkeys = (LoAL*) g_hash_table_lookup(matecfg->gogs_by_gopname,on); + + if (! gogkeys) { + gogkeys = new_loal("straight"); + g_hash_table_insert(matecfg->gogs_by_gopname,g_strdup(on),gogkeys); + } + + loal_append(gogkeys,avpl); + + reverse_avpl = new_avpl_from_avpl(on,avpl,TRUE); + + loal_append(cfg->keys,reverse_avpl); + + return TRUE; +} + +static gboolean config_gogextra(AVPL* avpl) { + guint8* name; + mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gogcfgs,&name); + + if ( ! name || ! cfg ) { + if ( ! name ) + g_warning("mate: GogExtra Config error: no Name"); + else + g_warning("mate: GogExtra Config error: no such Gop %s",name); + + return FALSE; + } + + cfg->expiration = extract_named_float(avpl, KEYWORD_GOGEXPIRE,cfg->expiration); + + merge_avpl(cfg->extra,avpl,TRUE); + + delete_avpl(avpl,TRUE); + return TRUE; +} + + +static void print_xxx_transforms(mate_cfg_item* cfg) { + guint8* tr_name; + guint8* cfg_name; + guint i; + + switch (cfg->type) { + case MATE_PDU_TYPE: + cfg_name = "PduTransform"; + break; + case MATE_GOP_TYPE: + cfg_name = "GopTransform"; + break; + case MATE_GOG_TYPE: + cfg_name = "GogTransform"; + break; + default: + cfg_name = "UnknownTransform"; + break; + } + + for (i=0; i < cfg->transforms->len; i++) { + tr_name = ((AVPL_Transf*) g_ptr_array_index(cfg->transforms,i))->name; + dbg_print (dbg_cfg,0,dbg_facility,"Action=%s; For=%s; Name=%s;\n",cfg_name,cfg->name,tr_name); + } + +} + +static void print_gog_config(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_cfg_gop* cfg = (mate_cfg_gop*) v; + guint8* avplstr = NULL; + void* cookie = NULL; + AVPL* avpl; + + dbg_print (dbg_cfg,0,dbg_facility,"Action=GogDef; Name=%s; Expiration=%f;\n",cfg->name,cfg->expiration); + + if (cfg->keys) { + while (( avpl = get_next_avpl(cfg->keys,&cookie) )) { + avplstr = avpl_to_str(avpl); + dbg_print (dbg_cfg,0,dbg_facility,"Action=GogKey; For=%s; On=%s; %s\n",cfg->name,avpl->name,avplstr); + g_free(avplstr); + } + } + + if (cfg->extra) { + avplstr = avpl_to_str(cfg->extra); + dbg_print (dbg_cfg,0,dbg_facility,"Action=GogExtra; For=%s; %s\n",cfg->name,avplstr); + g_free(avplstr); + } + + print_xxx_transforms(cfg); + +} + + + +static void print_gop_config(gpointer k _U_ , gpointer v, gpointer p _U_) { + mate_cfg_gop* cfg = (mate_cfg_gop*) v; + guint8* avplstr = NULL; + guint8* show_pdu_tree; + GString* gopdef; + + gopdef = g_string_new("Action=GopDef; "); + + show_pdu_tree = cfg->show_pdu_tree ? "TRUE" : "FALSE"; + g_string_sprintfa(gopdef,"Name=%s; ShowPduTree=%s;",cfg->name,show_pdu_tree); + + if (cfg->key) { + avplstr = avpl_to_str(cfg->key); + g_string_sprintfa(gopdef," %s",avplstr); + g_free(avplstr); + } + + dbg_print (dbg_cfg,0,dbg_facility,"%s\n",gopdef->str); + + + if (cfg->start) { + avplstr = avpl_to_str(cfg->start); + dbg_print (dbg_cfg,0,dbg_facility,"Action=GopStart; For=%s; %s\n",cfg->name,avplstr); + g_free(avplstr); + } + + if (cfg->stop) { + avplstr = avpl_to_str(cfg->stop); + dbg_print (dbg_cfg,0,dbg_facility,"Action=GopStop; For=%s; %s\n",cfg->name,avplstr); + g_free(avplstr); + } + + if (cfg->extra) { + avplstr = avpl_to_str(cfg->extra); + dbg_print (dbg_cfg,0,dbg_facility,"Action=GopExtra; For=%s; %s\n",cfg->name,avplstr); + g_free(avplstr); + } + + print_xxx_transforms(cfg); + + g_string_free(gopdef,TRUE); + +} + +static guint8* my_protoname(int proto_id) { + if (proto_id) { + return proto_registrar_get_abbrev(proto_id); + } else { + return "*"; + } +} + +static void print_hfid_hash(gpointer k, gpointer v, gpointer p _U_) { + g_string_sprintfa((GString*)p," %s=%s;",(guint8*)v,my_protoname(*(int*)k)); +} + + +static void print_transforms(gpointer k, gpointer v, gpointer p _U_) { + AVPL_Transf* t = NULL; + guint8* match; + guint8* mode; + guint8* match_s; + guint8* replace_s; + + for (t = v; t; t = t->next) { + match_s = avpl_to_str(t->match); + replace_s = avpl_to_dotstr(t->replace); + + switch (t->match_mode) { + case AVPL_STRICT: + match = "Strict"; + break; + case AVPL_LOOSE: + match = "Loose"; + break; + case AVPL_EVERY: + match = "Every"; + break; + default: + match = "None"; + break; + } + + switch (t->replace_mode) { + case AVPL_INSERT: + mode = "Insert"; + break; + case AVPL_REPLACE: + mode = "Replace"; + break; + default: + mode = "None"; + break; + } + + dbg_print (dbg,0,dbg_facility,"\tAction=Transform; Name=%s; Match=%s; Mode=%s; %s %s\n",(guint8*) k,match,mode,match_s,replace_s); + + g_free(match_s); + g_free(replace_s); + } +} + +static void print_pdu_config(mate_cfg_pdu* cfg) { + guint i; + int hfid; + guint8* discard; + guint8* stop; + GString* s = g_string_new("Action=PduDef; "); + + discard = cfg->discard_pdu_attributes ? "TRUE": "FALSE"; + stop = cfg->last_to_be_created ? "TRUE" : "FALSE"; + + g_string_sprintfa(s, "Name=%s; Proto=%s; DiscartAttribs=%s; Stop=%s; Transport=", + cfg->name,my_protoname(cfg->hfid_proto),discard,stop); + + for (i = 0; i < cfg->hfid_ranges->len; i++) { + hfid = *((int*) g_ptr_array_index(cfg->hfid_ranges,i)); + g_string_sprintfa(s,"%s/",my_protoname(hfid)); + } + + *(s->str + s->len - 1) = ';'; + + g_hash_table_foreach(cfg->hfids_attr,print_hfid_hash,s); + + dbg_print(dbg_cfg,0,dbg_facility,"%s",s->str); + + print_xxx_transforms(cfg); + + g_string_free(s,TRUE); +} + + + +static void print_gogs_by_gopname(gpointer k, gpointer v, gpointer p _U_) { + void* cookie = NULL; + guint8* str = NULL; + AVPL* avpl; + + while(( avpl = get_next_avpl((LoAL*)v,&cookie) )) { + str = avpl_to_str(avpl); + dbg_print(dbg_cfg,0,dbg_facility,"Gop=%s; Gog=%s; --> %s\n",(guint8*)k,avpl->name,str); + g_free(str); + } + +} + +static void print_gops_by_pduname(gpointer k, gpointer v, gpointer p _U_) { + dbg_print(dbg_cfg,0,dbg_facility, + "PduName=%s; GopName=%s;\n", (guint8*)k,((mate_cfg_gop*)v)->name); +} + +static void print_config() { + guint i; + + /* FIXME: print the settings */ + + dbg_print(dbg_cfg,0,dbg_facility,"###########################" + " CURRENT CONFIGURATION " "###########################"); + + g_hash_table_foreach(matecfg->transfs,print_transforms,NULL); + + for (i=0; ipducfglist->len; i++) { + print_pdu_config((mate_cfg_pdu*) g_ptr_array_index(matecfg->pducfglist,i)); + } + + g_hash_table_foreach(matecfg->gopcfgs,print_gop_config,NULL); + g_hash_table_foreach(matecfg->gogcfgs,print_gog_config,NULL); + + dbg_print(dbg_cfg,0,dbg_facility,"###########################" + " END OF CURRENT CONFIGURATION " "###########################"); + + if (*dbg_cfg > 1) { + dbg_print(dbg_cfg,0,dbg_facility,"******* Config Hashes"); + dbg_print(dbg_cfg,0,dbg_facility,"*** Gops by PduName"); + g_hash_table_foreach(matecfg->gops_by_pduname,print_gops_by_pduname,NULL); + dbg_print(dbg_cfg,0,dbg_facility,"*** GogKeys by GopName"); + g_hash_table_foreach(matecfg->gogs_by_gopname,print_gogs_by_gopname,NULL); + } +} + + +static void new_attr_hfri(mate_cfg_item* cfg, guint8* name) { + int* p_id = g_malloc(sizeof(int)); + + hf_register_info hfri = { + p_id, + { + g_strdup_printf("%s",name), + g_strdup_printf("mate.%s.%s",cfg->name,name), + FT_STRING,BASE_NONE,NULL,0, + g_strdup_printf("%s attribute of %s",name,cfg->name),HFILL + }}; + + *p_id = -1; + g_hash_table_insert(cfg->my_hfids,name,p_id); + g_array_append_val(matecfg->hfrs,hfri); + +} + +static void analyze_pdu_hfids(gpointer k, gpointer v, gpointer p) { + new_attr_hfri((mate_cfg_pdu*) p,(guint8*) v); +} + +static void analyze_transform_hfrs(mate_cfg_item* cfg) { + guint i; + void* cookie = NULL; + AVPL_Transf* t; + AVP* avp; + + for (i=0; i < cfg->transforms->len;i++) { + for (t = g_ptr_array_index(cfg->transforms,i); t; t=t->next ) { + cookie = NULL; + while(( avp = get_next_avp(t->replace,&cookie) )) { + if (! g_hash_table_lookup(cfg->my_hfids,avp->n)) { + new_attr_hfri(cfg,avp->n); + } + } + } + } +} + +static void analyze_pdu_config(mate_cfg_pdu* cfg) { + hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}}; + + hfri.p_id = &(cfg->hfid); + hfri.hfinfo.name = g_strdup_printf("%s",cfg->name); + hfri.hfinfo.abbrev = g_strdup_printf("mate.%s",cfg->name); + hfri.hfinfo.blurb = g_strdup_printf("PDU of type %s",cfg->name); + + g_array_append_val(matecfg->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_pdu_rel_time); + hfri.hfinfo.name = g_strdup_printf("%s time",cfg->name); + hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.RelativeTime",cfg->name); + hfri.hfinfo.type = FT_FLOAT; + hfri.hfinfo.display = BASE_DEC; + hfri.hfinfo.blurb = "Seconds passed since the start of the GOP or capture if the PDU is unnassigned"; + + g_array_append_val(matecfg->hfrs,hfri); + + g_hash_table_foreach(cfg->hfids_attr,analyze_pdu_hfids,cfg); + + analyze_transform_hfrs(cfg); +} + +static void analyze_gop_config(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_cfg_gop* cfg = v; + void* cookie = NULL; + AVP* avp; + hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}}; + + hfri.p_id = &(cfg->hfid); + hfri.hfinfo.name = g_strdup_printf("%s",cfg->name); + hfri.hfinfo.abbrev = g_strdup_printf("mate.%s",cfg->name); + hfri.hfinfo.blurb = g_strdup_printf("GOP of type %s",cfg->name); + + g_array_append_val(matecfg->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_gop_start_time); + hfri.hfinfo.name = g_strdup_printf("%s start time",cfg->name); + hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.StartTime",cfg->name); + hfri.hfinfo.type = FT_FLOAT; + hfri.hfinfo.display = BASE_DEC; + hfri.hfinfo.blurb = g_strdup_printf("Seconds passed since the begining of caputre to the start of this %s",cfg->name); + + g_array_append_val(matecfg->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_gop_stop_time); + hfri.hfinfo.name = g_strdup_printf("%s hold time",cfg->name); + hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Time",cfg->name); + hfri.hfinfo.blurb = g_strdup_printf("Duration in seconds from start to stop of this %s",cfg->name); + + g_array_append_val(matecfg->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_gop_last_time); + hfri.hfinfo.name = g_strdup_printf("%s current time",cfg->name); + hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Duration",cfg->name); + hfri.hfinfo.blurb = g_strdup_printf("Time passed between the start of this %s and the last pdu assigned to it",cfg->name); + + g_array_append_val(matecfg->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_gop_num_pdus); + hfri.hfinfo.name = g_strdup_printf("%s number of PDUs",cfg->name); + hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.NumOfPdus",cfg->name); + hfri.hfinfo.blurb = g_strdup_printf("Number of PDUs assigned to this %s",cfg->name); + hfri.hfinfo.type = FT_UINT32; + + g_array_append_val(matecfg->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_gop_pdu); + hfri.hfinfo.name = g_strdup_printf("A PDU of %s",cfg->name); + hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Pdu",cfg->name); + hfri.hfinfo.blurb = g_strdup_printf("A PDU assigned to this %s",cfg->name); + hfri.hfinfo.type = FT_FRAMENUM; + + g_array_append_val(matecfg->hfrs,hfri); + + while(( avp = get_next_avp(cfg->key,&cookie) )) { + if (! g_hash_table_lookup(cfg->my_hfids,avp->n)) { + new_attr_hfri(cfg,avp->n); + } + } + + cookie = NULL; + while(( avp = get_next_avp(cfg->start,&cookie) )) { + if (! g_hash_table_lookup(cfg->my_hfids,avp->n)) { + new_attr_hfri(cfg,avp->n); + } + } + + cookie = NULL; + while(( avp = get_next_avp(cfg->stop,&cookie) )) { + if (! g_hash_table_lookup(cfg->my_hfids,avp->n)) { + new_attr_hfri(cfg,avp->n); + } + } + + cookie = NULL; + while(( avp = get_next_avp(cfg->extra,&cookie) )) { + if (! g_hash_table_lookup(cfg->my_hfids,avp->n)) { + new_attr_hfri(cfg,avp->n); + } + } + + analyze_transform_hfrs(cfg); +} + + +static void analyze_gog_config(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_cfg_gop* cfg = v; + void* avp_cookie; + void* avpl_cookie; + AVP* avp; + AVPL* avpl; + hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}}; + + hfri.p_id = &(cfg->hfid); + hfri.hfinfo.name = g_strdup_printf("%s",cfg->name); + hfri.hfinfo.abbrev = g_strdup_printf("mate.%s",cfg->name); + hfri.hfinfo.blurb = g_strdup_printf("GOG of type %s",cfg->name); + + g_array_append_val(matecfg->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_gog_num_of_gops); + hfri.hfinfo.name = "number of GOPs"; + hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.NumOfGops",cfg->name); + hfri.hfinfo.type = FT_UINT32; + hfri.hfinfo.display = BASE_DEC; + hfri.hfinfo.blurb = g_strdup_printf("Number of GOPs assigned to this %s",cfg->name); + + g_array_append_val(matecfg->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_gog_gop); + hfri.hfinfo.name = "a GOP"; + hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Gop",cfg->name); + hfri.hfinfo.type = FT_STRING; + hfri.hfinfo.display = BASE_DEC; + hfri.hfinfo.blurb = g_strdup_printf("a GOPs assigned to this %s",cfg->name); + + g_array_append_val(matecfg->hfrs,hfri); + + avpl_cookie = NULL; + while (( avpl = get_next_avpl(cfg->keys,&avpl_cookie) )) { + avp_cookie = NULL; + while (( avp = get_next_avp(avpl,&avp_cookie) )) { + if (! g_hash_table_lookup(cfg->my_hfids,avp->n)) { + new_attr_hfri(cfg,avp->n); + } + } + } + + avp_cookie = NULL; + while (( avp = get_next_avp(cfg->extra,&avp_cookie) )) { + if (! g_hash_table_lookup(cfg->my_hfids,avp->n)) { + new_attr_hfri(cfg,avp->n); + } + } + + analyze_transform_hfrs(cfg); +} + +static size_t analyze_config() { + guint i; + + for (i=0; ipducfglist->len; i++) { + analyze_pdu_config((mate_cfg_pdu*) g_ptr_array_index(matecfg->pducfglist,i)); + } + + g_hash_table_foreach(matecfg->gopcfgs,analyze_gop_config,matecfg); + g_hash_table_foreach(matecfg->gogcfgs,analyze_gog_config,matecfg); + +} + +static void new_action(guint8* name, config_action* action) { + g_hash_table_insert(actions,name,action); + +} + +static void init_actions() { + + all_keywords = new_avpl("all_keywords"); + insert_avp(all_keywords,new_avp(KEYWORD_ACTION,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_SETTINGS,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_INCLUDE,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_TRANSFORM,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_PDU,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_PDUCRITERIA,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_PDUEXTRA,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_PDUTRANSFORM,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_GOP,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_GOPSTART,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_GOPSTOP,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_GOPEXTRA,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_GOPTRANSFORM,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_GOGDEF,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_GOGKEY,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_GOGEXTRA,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_GOGTRANSFORM,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_NAME,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_ON,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_FOR,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_FROM,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_TO,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_MATCH,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_MODE,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_FILENAME,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_PROTO,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_METHOD,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_TRANSPORT,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_METHOD,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_STRICT,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_LOOSE,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_EVERY,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_REPLACE,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_INSERT,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_MAP,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_GOGEXPIRE,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_DISCARDPDU,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_LIBPATH,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_SHOWPDUTREE,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_SHOWGOPTIMES,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_STOP,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_DROPPDU,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_DROPGOP,"",'=')); + + insert_avp(all_keywords,new_avp(KEYWORD_DBG_GENERAL,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_DBG_CFG,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_DBG_PDU,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_DBG_GOP,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_DBG_GOG,"",'=')); + +#ifdef _AVP_DEBUGGING + insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVPLIB,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVP,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVP_OP,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVPL,"",'=')); + insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVPL_OP,"",'=')); +#endif + + if (actions) { + g_hash_table_destroy(actions); + } + + actions = g_hash_table_new(g_str_hash,g_str_equal); + + new_action(KEYWORD_SETTINGS,config_settings); + new_action(KEYWORD_PDU,config_pdu); + new_action(KEYWORD_PDUEXTRA,config_pduextra); + /* new_action(KEYWORD_PDUCRITERIA,config_pdu); */ + new_action(KEYWORD_GOP,config_gop); + new_action(KEYWORD_GOGDEF,config_gog); + new_action(KEYWORD_GOGKEY,config_gogkey); + new_action(KEYWORD_GOPSTART,config_start); + new_action(KEYWORD_GOPSTOP,config_stop); + new_action(KEYWORD_GOPEXTRA,config_gopextra); + new_action(KEYWORD_GOGEXTRA,config_gogextra); + new_action(KEYWORD_INCLUDE,config_include); + new_action(KEYWORD_TRANSFORM,config_transform); + new_action(KEYWORD_PDUTRANSFORM,config_pdu_transform); + new_action(KEYWORD_GOPTRANSFORM,config_gop_transform); + new_action(KEYWORD_GOGTRANSFORM,config_gog_transform); + +} + +void reset_cfg(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_cfg_item* c = v; + c->last_id = 0; +} + +extern mate_config* mate_cfg() { + + g_hash_table_foreach(matecfg->pducfgs,reset_cfg,NULL); + g_hash_table_foreach(matecfg->gopcfgs,reset_cfg,NULL); + g_hash_table_foreach(matecfg->gogcfgs,reset_cfg,NULL); + + return matecfg; +} + +extern mate_config* mate_make_config(guint8* filename) { + + avp_init(); + init_actions(); + + matecfg = g_malloc(sizeof(mate_config)); + + matecfg->gog_expiration = DEFAULT_GOG_EXPIRATION; + matecfg->discard_pdu_attributes = FALSE; + matecfg->drop_pdu = FALSE; + matecfg->drop_gop = FALSE; + matecfg->show_pdu_tree = TRUE; + matecfg->show_gop_times = TRUE; + matecfg->last_to_be_created = FALSE; + matecfg->match_mode = AVPL_STRICT; + matecfg->replace_mode = AVPL_INSERT; + matecfg->mate_lib_path = g_strdup_printf("%s%c%s",get_datafile_dir(),DIR_SEP,DEFAULT_MATE_LIB_PATH); + matecfg->mate_config_file = g_strdup(filename); + matecfg->mate_attrs_filter = g_string_new(""); + matecfg->mate_protos_filter = g_string_new(""); + matecfg->dbg_facility = NULL; + matecfg->dbg_lvl = 0; + matecfg->dbg_cfg_lvl = 0; + matecfg->dbg_pdu_lvl = 0; + matecfg->dbg_gop_lvl = 0; + matecfg->dbg_gog_lvl = 0; + matecfg->pducfglist = g_ptr_array_new(); + matecfg->pducfgs = g_hash_table_new(g_str_hash,g_str_equal); + matecfg->gopcfgs = g_hash_table_new(g_str_hash,g_str_equal); + matecfg->gogcfgs = g_hash_table_new(g_str_hash,g_str_equal); + matecfg->transfs = g_hash_table_new(g_str_hash,g_str_equal); + matecfg->gops_by_pduname = g_hash_table_new(g_str_hash,g_str_equal); + matecfg->gogs_by_gopname = g_hash_table_new(g_str_hash,g_str_equal); + + matecfg->hfrs = g_array_new(FALSE,TRUE,sizeof(hf_register_info)); + + dbg = &matecfg->dbg_lvl; + + if ( mate_load_config(filename) ) { + analyze_config(); + dbg_print (dbg_cfg,3,dbg_facility,"mate_make_config: OK"); + if (dbg_cfg_lvl > 0) print_config(); + } else { + if (matecfg) destroy_mate_config(matecfg,FALSE); + matecfg = NULL; + return NULL; + } + + if (matecfg->mate_attrs_filter->len > 1) { + g_string_erase(matecfg->mate_attrs_filter,0,2); + g_string_erase(matecfg->mate_protos_filter,0,2); + } else { + mate_config_error(NULL,NULL,"mate: Failed: nothing left to tap on"); + if (matecfg) destroy_mate_config(matecfg,FALSE); + matecfg = NULL; + return NULL; + } + + matecfg->tap_filter = g_strdup_printf("(%s) && (%s)",matecfg->mate_protos_filter->str,matecfg->mate_attrs_filter->str); + + return matecfg; +} + diff --git a/plugins/mate/mate_util.c b/plugins/mate/mate_util.c new file mode 100644 index 0000000000..953f3fbc9a --- /dev/null +++ b/plugins/mate/mate_util.c @@ -0,0 +1,1861 @@ +/* mate_util.c +* MATE -- Meta Analysis Tracing Engine +* Utility Library: Single Copy Strings and Attribute Value Pairs +* +* Copyright 2004, Luis E. Garcia Ontanon +* +* $Id$ +* +* Ethereal - Network traffic analyzer +* By Gerald Combs +* Copyright 1998 Gerald Combs +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "config.h" +#include +#include +#include +#include "mate.h" +#include "mate_util.h" + +/* TODO: ++ fix debug_print levels ++ chunks for scs_strings (do I realy need em??) + + checking bounds in (almost) every operator +- operators + + rethink '&' operator + - bounds check on op_match() + ? change &{} into [] + ? add {xxx} to get avps named xxxx from the src avpl + ? add (yyy) to do aaa+31 or and similar stuff + - add perlre operator? + - transform + + map (N->M hash) +*/ + + +/*************************************************************************** +* dbg_print +*************************************************************************** +* This is the debug facility of the thing. +***************************************************************************/ + +/* dbg_print: + * which: a pointer to the current level of debugging for a feature + * how: the level over which this message should be printed out + * where: the file on which to print (g_message if null) + * fmt, ...: what to print + */ + +void dbg_print(const guint* which, guint how, FILE* where, guint8* fmt, ... ) { + static guint8 debug_buffer[DEBUG_BUFFER_SIZE]; + va_list list; + + if ( ! which || *which < how ) return; + + va_start( list, fmt ); + g_vsnprintf(debug_buffer,DEBUG_BUFFER_SIZE,fmt,list); + va_end( list ); + + if (! where) { + g_message(debug_buffer); + } else { + fputs(debug_buffer,where); + } + +} + + +/*************************************************************************** + * single copy strings + *************************************************************************** + * In order to save memory and since strings repeat more often than don't, + * we'll keep only one copy of each as key to a hash with a count of + * subscribers as value. + ***************************************************************************/ +/* FIXME: use hash fom glib 1.X not 2.X */ + +/** + * scs_init: + * @collection: the scs hash + * + * Initializes the scs hash. + **/ + +void scs_init(GHashTable** hash) { + /* key: a string + value: guint number of subscribers */ + + if (*hash) g_hash_table_destroy(*hash); + + *hash = g_hash_table_new_full(g_str_hash,g_str_equal,g_free,g_free); + +} + + +/** + * subscribe: + * @collection: the scs hash + * @s: a string + * + * Checks if the given string exists already and if so it increases the count of + * subsscribers and returns a pointer to the stored string. If not It will copy + * the given string store it in the hash and return the pointer to the copy. + * Remember, containment is handled internally, take care of your own strings. + * + * Return value: a pointer to the subscribed string. + **/ +guint8* scs_subscribe(GHashTable* collection, guint8* s) { + guint8* ok = NULL; + guint* ip = NULL; + + g_hash_table_lookup_extended(collection,s,(gpointer*)&ok,(gpointer*)&ip); + + if (ip) { + (*ip)++; + s = ok; + } else { + ip = g_malloc(sizeof(int)); + *ip = 0; + s = g_strdup(s); + g_hash_table_insert(collection,s,ip); + } + + return s; +} + +/** + * unsubscribe: + * @collection: the scs hash + * @s: a string. + * + * decreases the count of subscribers, if zero frees the internal copy of + * the string. + **/ +void scs_unsubscribe(GHashTable* collection, guint8* s) { + guint8* ok = NULL; + guint* ip = NULL; + + g_hash_table_lookup_extended(collection,s,(gpointer*)&ok,(gpointer*)&ip); + + if (ip) { + if (*ip == 0) g_hash_table_remove(collection,ok); + else (*ip)--; + } else { + g_warning("unsusbcribe: already deleted: '%s'?",s); + } +} + +/** + * scs_subscribe_printf: + * @fmt: a format string ... + * + * Formats the input and subscribes it. + * + * Return value: the stored copy of the formated string. + * + **/ +extern guint8* scs_subscribe_printf(GHashTable* collection, guint8* fmt, ...) { + va_list list; + guint8* ok = NULL; + guint8* s = NULL; + guint* ip = NULL; + + va_start( list, fmt ); + s = g_strdup_vprintf(fmt, list); + va_end( list ); + + g_hash_table_lookup_extended(collection,s,(gpointer*)&ok,(gpointer*)&ip); + + if (ip) { + (*ip)++; + g_free(s); + s = ok; + } else { + ip = g_malloc0(sizeof(int)); + *ip = 0; + g_hash_table_insert(collection,s,ip); + } + + return s; +} + + +/*************************************************************************** +* AVPs & Co. +*************************************************************************** +* The Thing operates mainly on avps, avpls and loals +* - attribute value pairs (two strings: the name and the value and an opeartor) +* - avp lists a somehow sorted list of avps +* - loal (list of avp lists) an arbitrarily sorted list of avpls +* +* +***************************************************************************/ + + +typedef union _any_avp_type { + AVP avp; + AVPN avpn; + AVPL avpl; + LoAL loal; + LoALnode loaln; +} any_avp_type; + + +static GMemChunk* avp_chunk = NULL; +static GHashTable* avp_strings = NULL; + +#ifdef _AVP_DEBUGGING +static FILE* dbg_fp = NULL; + +static int dbg_level = 0; +static int* dbg = &dbg_level; + +static int dbg_avp_level = 0; +static int* dbg_avp = &dbg_avp_level; + +static int dbg_avp_op_level = 0; +static int* dbg_avp_op = &dbg_avp_op_level; + +static int dbg_avpl_level = 0; +static int* dbg_avpl = &dbg_avpl_level; + +static int dbg_avpl_op_level = 0; +static int* dbg_avpl_op = &dbg_avpl_op_level; + +/** + * setup_avp_debug: + * @fp: the file in which to send debugging output. + * @general: a pointer to the level of debugging of facility "general" + * @avp: a pointer to the level of debugging of facility "avp" + * @avp_op: a pointer to the level of debugging of facility "avp_op" + * @avpl: a pointer to the level of debugging of facility "avpl" + * @avpl_op: a pointer to the level of debugging of facility "avpl_op" + * + * (If enabled set's up the debug facilities for the avp library. + * + **/ +extern void setup_avp_debug(FILE* fp, int* general, int* avp, int* avp_op, int* avpl, int* avpl_op) { + dbg_fp = fp; + dbg = general; + dbg_avp = avp; + dbg_avp_op = avp_op; + dbg_avpl = avpl; + dbg_avpl_op = avpl_op; +} + +#endif /* _AVP_DEBUGGING */ + +/** + * avp_init: + * @chunk_size: the initial chunk's size. + * + * (Re)Initializes the avp library. + * + **/ +extern void avp_init(void) { + + scs_init(&avp_strings); + + + if ( avp_chunk ) { + g_mem_chunk_destroy(avp_chunk); + } + + avp_chunk = g_mem_chunk_new("avp_chunk", sizeof(any_avp_type), + AVP_CHUNK_SIZE, G_ALLOC_AND_FREE); + +} + + +/** + * new_avp_from_finfo: + * @name: the name the avp will have. + * @finfo: the field_info from which to fetch the data. + * + * Creates an avp from a field_info record. + * + * Return value: a pointer to the newly created avp. + * + **/ +extern AVP* new_avp_from_finfo(guint8* name, field_info* finfo) { + AVP* new = g_mem_chunk_alloc(avp_chunk); + guint8* value; + guint8* str; + new->n = scs_subscribe(avp_strings, name); + + if (finfo->value.ftype->get_value_integer) { + value = scs_subscribe_printf(avp_strings, "%i",fvalue_get_integer(&finfo->value)); +#ifdef _AVP_DEBUGGING + dbg_print (dbg_avp,2,dbg_fp,"new_avp_from_finfo: from integer: %s",value); +#endif + } else if (finfo->value.ftype->val_to_string_repr) { + str = fvalue_to_string_repr(&finfo->value,FTREPR_DISPLAY,NULL); + value = scs_subscribe(avp_strings, str); +#ifdef _AVP_DEBUGGING + dbg_print (dbg_avp,2,dbg_fp,"new_avp_from_finfo: from string: %s",value); +#endif + } else if (finfo->value.ftype->get_value_floating) { + value = scs_subscribe_printf(avp_strings, "%f",fvalue_get_floating(&finfo->value)); +#ifdef _AVP_DEBUGGING + dbg_print (dbg_avp,2,dbg_fp,"new_avp_from_finfo: from float: %s",value); +#endif + } else { +#ifdef _AVP_DEBUGGING + dbg_print (dbg_avp,2,dbg_fp,"new_avp_from_finfo: a proto: %s",finfo->hfinfo->abbrev); +#endif + value = scs_subscribe(avp_strings, finfo->hfinfo->abbrev); + } + + new->v = value; + + new->o = '='; + +#ifdef _AVP_DEBUGGING + dbg_print (dbg_avp,1,dbg_fp,"new_avp_from_finfo: %X %s%c%s;",(guint32) new,new->n,new->o,new->v); +#endif + + return new; +} + + +/** + * new_avp: + * @name: the name the avp will have. + * @value: the value the avp will have. + * @o: the operator of this avp. + * + * Creates an avp given every parameter. + * + * Return value: a pointer to the newly created avp. + * + **/ +extern AVP* new_avp(guint8* name, guint8* value, guint8 o) { + AVP* new = g_mem_chunk_alloc(avp_chunk); + + new->n = scs_subscribe(avp_strings, name); + new->v = scs_subscribe(avp_strings, value); + new->o = o; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avp,1,dbg_fp,"new_avp: %X %s%c%s;",(guint32) new,new->n,new->o,new->v); +#endif + return new; +} + + +/** +* delete_avp: + * @avp: the avp to delete. + * + * Destroys an avp and releases the resources it uses. + * + **/ +extern void delete_avp(AVP* avp) { +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avp,1,dbg_fp,"delete_avp: %X %s%c%s;",(guint32) avp,avp->n,avp->o,avp->v); +#endif + + scs_unsubscribe(avp_strings, avp->n); + scs_unsubscribe(avp_strings, avp->v); + g_mem_chunk_free(avp_chunk,avp); +} + + +/** +* avp_copy: + * @from: the avp to be copied. + * + * Creates an avp whose name op and value are copyes of the given one. + * + * Return value: a pointer to the newly created avp. + * + **/ +extern AVP* avp_copy(AVP* from) { + AVP* new = g_mem_chunk_alloc(avp_chunk); + + new->n = scs_subscribe(avp_strings, from->n); + new->v = scs_subscribe(avp_strings, from->v); + new->o = from->o; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avp,1,dbg_fp,"copy_avp: %X %s%c%s;",(guint32) new,new->n,new->o,new->v); +#endif + + return new; +} + + +extern void rename_avp(AVP* avp, guint8* name) { + guint8* s = avp->n; + avp->n = scs_subscribe(avp_strings,name); + scs_unsubscribe(avp_strings,s); +} + +/** + * new_avpl: + * @name: the name the avpl will have. + * + * Creates an empty avpl. + * + * Return value: a pointer to the newly created avpl. + * + **/ +extern AVPL* new_avpl(guint8* name) { + AVPL* new_avpl = g_mem_chunk_alloc(avp_chunk); + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,7,dbg_fp,"new_avpl: %X name=%s",new_avpl,name); +#endif + + new_avpl->name = scs_subscribe(avp_strings, name); + new_avpl->len = 0; + new_avpl->null.avp = NULL; + new_avpl->null.next = &new_avpl->null; + new_avpl->null.prev = &new_avpl->null; + + + return new_avpl; +} + +extern void rename_avpl(AVPL* avpl, guint8* name) { + scs_unsubscribe(avp_strings,avpl->name); + avpl->name = scs_subscribe(avp_strings,name); +} + +/** + * insert_avp: + * @avpl: the avpl in which to insert. + * @avp: the avp to be inserted. + * + * Inserts the given AVP into the given AVPL if an identical one isn't yet there. + * + * Return value: whether it was inserted or not. + * + * BEWARE: Check the return value, you might need to delete the avp if + * it is not inserted. + **/ +extern gboolean insert_avp(AVPL* avpl, AVP* avp) { + AVPN* new = g_mem_chunk_alloc(avp_chunk); + AVPN* c; + + new->avp = avp; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,7,dbg_fp,"new_avpn: %X",new); + dbg_print(dbg_avpl_op,4,dbg_fp,"insert_avp: %X %X %s%c%s;",avpl,avp,avp->n,avp->o,avp->v); +#endif + + /* get to the insertion point */ + for(c=avpl->null.next; c->avp; c = c->next) { + + if ( avp->n == c->avp->n ) { + + if (avp->v > c->avp->v) { + break; + } + + if (avp->v == c->avp->v) { + if (avp->o == AVP_OP_EQUAL) { +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,7,dbg_fp,"delete_avpn: %X",new); +#endif + g_mem_chunk_free(avp_chunk,new); + return FALSE; + } + } + } + + if (avp->n > c->avp->n) { + break; + } + } + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl,5,dbg_fp,"insert_avp: inserting %X in %X before %X;",avp,avpl,c); +#endif + + new->next = c; + new->prev = c->prev; + c->prev->next = new; + c->prev = new; + + avpl->len++; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl,4,dbg_fp,"avpl: %X new len: %i",avpl,avpl->len); +#endif + + return TRUE; +} + +/** + * get_avp_by_name: + * @avpl: the avpl from which to try to get the avp. + * @name: the name of the avp we are looking for. + * @cookie: variable in which to store the state between calls. + * + * Gets pointer to the next avp whose name is given; uses cookie to store its + * state between calls. + * + * Return value: a pointer to the next matching avp if there's one, else NULL. + * + **/ +extern AVP* get_avp_by_name(AVPL* avpl, guint8* name, void** cookie) { + AVPN* curr; + AVPN* start = (AVPN*) *cookie; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,7,dbg_fp,"get_avp_by_name: entering: %X %s %X",avpl,name,*cookie); +#endif + + name = scs_subscribe(avp_strings, name); + + if (!start) start = avpl->null.next; + + for ( curr = start; curr->avp; curr = curr->next ) { + if ( curr->avp->n == name ) { + break; + } + } + + *cookie = curr; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,5,dbg_fp,"get_avp_by_name: got avp: %X",curr); +#endif + + scs_unsubscribe(avp_strings, name); + + return curr->avp; +} + +/** + * extract_avp_by_name: + * @avpl: the avpl from which to try to extract the avp. + * @name: the name of the avp we are looking for. + * + * Extracts from the avpl the next avp whose name is given; + * + * Return value: a pointer to extracted avp if there's one, else NULL. + * + **/ +extern AVP* extract_avp_by_name(AVPL* avpl, guint8* name) { + AVPN* curr; + AVP* avp = NULL; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,7,dbg_fp,"extract_avp_by_name: entering: %X %s",avpl,name); +#endif + + name = scs_subscribe(avp_strings, name); + + for ( curr = avpl->null.next; curr->avp; curr = curr->next ) { + if ( curr->avp->n == name ) { + break; + } + } + + scs_unsubscribe(avp_strings, name); + + if( ! curr->avp ) return NULL; + + curr->next->prev = curr->prev; + curr->prev->next = curr->next; + + avp = curr->avp; + + g_mem_chunk_free(avp_chunk,curr); + + (avpl->len)--; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl,4,dbg_fp,"avpl: %X new len: %i",avpl,avpl->len); +#endif + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,5,dbg_fp,"extract_avp_by_name: got avp: %X",avp); +#endif + + return avp; +} + + +/** + * extract_first_avp: + * @avpl: the avpl from which to try to extract the avp. + * + * Extracts the fisrt avp from the avpl. + * + * Return value: a pointer to extracted avp if there's one, else NULL. + * + **/ +extern AVP* extract_first_avp(AVPL* avpl) { + AVP* avp; + AVPN* node; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,7,dbg_fp,"extract_first_avp: %X",avpl); +#endif + + node = avpl->null.next; + + avpl->null.next->prev = &avpl->null; + avpl->null.next = node->next; + + avp = node->avp; + + if (avp) { + g_mem_chunk_free(avp_chunk,node); + (avpl->len)--; +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl,4,dbg_fp,"avpl: %X new len: %i",avpl,avpl->len); +#endif + } + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,5,dbg_fp,"extract_first_avp: got avp: %X",avp); +#endif + + return avp; + +} + + +/** + * extract_last_avp: + * @avpl: the avpl from which to try to extract the avp. + * + * Extracts the last avp from the avpl. + * + * Return value: a pointer to extracted avp if there's one, else NULL. + * + **/ +extern AVP* extract_last_avp(AVPL* avpl) { + AVP* avp; + AVPN* node; + + node = avpl->null.prev; + + avpl->null.prev->next = &avpl->null; + avpl->null.prev = node->prev; + + avp = node->avp; + + if (avp) { + g_mem_chunk_free(avp_chunk,node); + (avpl->len)--; +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl,4,dbg_fp,"avpl: %X new len: %i",avpl,avpl->len); +#endif + } + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,5,dbg_fp,"extract_last_avp: got avp: %X",avp); +#endif + + return avp; + +} + + +/** + * delete_avpl: + * @avpl: the avpl from which to try to extract the avp. + * @avps_too: whether or not it should delete the avps as well. + * + * Destroys an avpl and releases the resources it uses. If told to do + * so releases the avps as well. + * + **/ +extern void delete_avpl(AVPL* avpl, gboolean avps_too) { + AVP* avp; +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl,3,dbg_fp,"delete_avpl: %X",avpl); +#endif + + while(( avp = extract_last_avp(avpl))) { + if (avps_too) { + delete_avp(avp); + } + } + + scs_unsubscribe(avp_strings,avpl->name); + g_mem_chunk_free(avp_chunk,avpl); +} + + + +/** + * get_next_avp: + * @avpl: the avpl from which to try to get the avps. + * @cookie: variable in which to store the state between calls. + * + * Iterates on an avpl to get its avps. + * + * Return value: a pointer to the next avp if there's one, else NULL. + * + **/ +extern AVP* get_next_avp(AVPL* avpl, void** cookie) { + AVPN* node; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,5,dbg_fp,"get_next_avp: avpl: %X avpn: %X",avpl,*cookie); +#endif + + if (*cookie) { + node = (AVPN*) *cookie; + } else { + node = avpl->null.next; + } + + *cookie = node->next; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,5,dbg_fp,"extract_last_avp: got avp: %X",node->avp); +#endif + + return node->avp; +} + +/** + * avpl_to_str: + * @avpl: the avpl to represent. + * + * Creates a newly allocated string containing a representation of an avpl. + * + * Return value: a pointer to the newly allocated string. + * + **/ +guint8* avpl_to_str(AVPL* avpl) { + AVPN* c; + GString* s = g_string_new(""); + guint8* avp_s; + guint8* r; + + for(c=avpl->null.next; c->avp; c = c->next) { + avp_s = avp_to_str(c->avp); + g_string_sprintfa(s," %s;",avp_s); + g_free(avp_s); + } + + r = s->str; + g_string_free(s,FALSE); + + /* g_strchug(r); ? */ + return r; +} + +extern guint8* avpl_to_dotstr(AVPL* avpl) { + AVPN* c; + GString* s = g_string_new(""); + guint8* avp_s; + guint8* r; + + for(c=avpl->null.next; c->avp; c = c->next) { + avp_s = avp_to_str(c->avp); + g_string_sprintfa(s," .%s;",avp_s); + g_free(avp_s); + } + + r = s->str; + g_string_free(s,FALSE); + + /* g_strchug(r); ? */ + return r; +} + +/** +* merge_avpl: + * @dst: the avpl in which to merge the avps. + * @src: the avpl from which to get the avps. + * @copy: whether avps should be copied instead of referenced. + * + * Adds the avps of src that are not existent in dst into dst. + * + * Return value: a pointer to the newly allocated string. + * + **/ +extern void merge_avpl(AVPL* dst, AVPL* src, gboolean copy_avps) { + AVPN* cd = NULL; + AVPN* cs = NULL; + gint c; + AVP* copy; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"merge_avpl: %X %X",dst,src); +#endif + + cs = src->null.next; + cd = dst->null.next; + + while(cs->avp) { + + if(cd->avp) { + c = (guint) cd->avp->n - (guint) cs->avp->n; + } else { + c = -1; + } + + if (c > 0) { + if (cd->avp) cd = cd->next; + } else if (c < 0) { + if (copy_avps) { + copy = avp_copy(cs->avp); + if ( ! insert_avp(dst,copy) ) { + delete_avp(copy); + } + } else { + insert_avp(dst,cs->avp); + } + + cs = cs->next; + } else { + if ( ! cd->avp || ! (cd->avp->v == cs->avp->v) ) { + if (copy_avps) { + copy = avp_copy(cs->avp); + if ( ! insert_avp(dst,copy) ) { + delete_avp(copy); + } + } else { + insert_avp(dst,cs->avp); + } + } + cs = cs->next; + if (cd->avp) cd = cd->next; + } + } + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,8,dbg_fp,"merge_avpl: done"); +#endif + + return; +} + + +/** + * merge_avpl: + * @name: the name of the new avpl. + * @avpl: the avpl from which to get the avps. + * @copy_avps: whether avps should be copied instead of referenced. + * + * Creates a new avpl containing the same avps as the given avpl + * It will either reference or copie the avps. + * + * Return value: a pointer to the newly allocated string. + * + **/ +extern AVPL* new_avpl_from_avpl(guint8* name, AVPL* avpl, gboolean copy_avps) { + AVPL* newavpl = new_avpl(name); + void* cookie = NULL; + AVP* avp; + AVP* copy; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"new_avpl_from_avpl: %X from=%X name='%s'",newavpl,avpl,name); +#endif + + while(( avp = get_next_avp(avpl,&cookie) )) { + if (copy_avps) { + copy = avp_copy(avp); + if ( ! insert_avp(newavpl,copy) ) { + delete_avp(copy); + } + } else { + insert_avp(newavpl,avp); + } + } + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,8,dbg_fp,"new_avpl_from_avpl: done"); +#endif + + return newavpl; +} + + +#define TRANS_NUM '-': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0' + +/* BROKEN, makes no sense right now */ +/* FIXME: Use subscribe/unsubscribe */ +static AVP* avp_transform(AVP* src, AVP* op) { + unsigned int i; + guint8 c; + + GString* replace_str = NULL; + GString* num_str = NULL; + GString* return_str = NULL; + guint8* v; + long num = 0; + + enum _tranf_state { + START, + IN_NUM, + IN_REPLACE, + END + } state; + + state = START; + + for(i = 0; i < strlen(op->v); i++) { + c= op->v[i]; + + if (state == END) break; + + switch(state) { + case START: + switch(c) { + case '{': + num_str = g_string_new(""); + state = IN_NUM; + continue; + default: + continue; + }; + case IN_NUM: + switch(c) { + case TRANS_NUM: + g_string_append_c(num_str,c); + continue; + case ':': + num = strtol(num_str->str,NULL,10); + g_string_free(num_str,TRUE); + replace_str = g_string_new(""); + state = IN_REPLACE; + continue; + default: + /* will ignore any char that is not a number */ + continue; + }; + case IN_REPLACE: + switch(c) { + case '\\': + continue; + case '}': + state = END; + continue; + default : + g_string_append_c(replace_str,c); + continue; + } + case END: + /* it will never reach */ + continue; + } + + } + + v = src->v; + + if (num > 0) { + return_str = g_string_new(v); + g_string_erase(return_str,0,num); + g_string_prepend(return_str,replace_str->str); + } else if (num < 0) { + return_str = g_string_new(v); + g_string_truncate(return_str,return_str->len+num); + g_string_append(return_str,replace_str->str); + + } else { + return_str = g_string_new(replace_str->str); + } + + g_mem_chunk_free(avp_chunk,v); + g_string_free(replace_str,TRUE); + + src->o = '='; + src->v = return_str->str; + g_string_free(return_str,FALSE); + + return src; +} + + + +/** +* match_avp: + * @src: an src to be compared agains an "op" avp + * @op: the "op" avp that will be matched against the src avp + * + * Checks whether or not two avp's match. + * + * Return value: a pointer to the src avp if there's a match. + * + **/ +extern AVP* match_avp(AVP* src, AVP* op) { + gchar** splited; + int i; + gchar* p; + guint ls; + guint lo; + float fs = 0.0; + float fo = 0.0; + gboolean lower = FALSE; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"match_avp: %s%c%s; vs. %s%c%s;",src->n,src->o,src->v,op->n,op->o,op->v); +#endif + + if ( src->n != op->n ) { + return NULL; + } + + switch (op->o) { + case AVP_OP_EXISTS: + return src; + case AVP_OP_EQUAL: + return src->v == op->v ? src : NULL; + case AVP_OP_NOTEQUAL: + return !( src->v == op->v) ? src : NULL; + case AVP_OP_STARTS: + return strncmp(src->v,op->v,strlen(op->v)) == 0 ? src : NULL; + case AVP_OP_ONEOFF: + splited = g_strsplit(op->v,"|",0); + if (splited) { + for (i=0;splited[i];i++) { + if(g_str_equal(splited[i],src->v)) { + g_strfreev(splited); + return src; + } + } + g_strfreev(splited); + } + return NULL; + + case AVP_OP_LOWER: + lower = TRUE; + case AVP_OP_HIGHER: + + fs = strtof(src->v, NULL); + fo = strtof(src->v, NULL); + + if (lower) { + if (fsfo) return src; + else return NULL; + } + case AVP_OP_ENDS: + /* does this work? */ + ls = strlen(src->v); + lo = strlen(op->v); + + if ( ls < lo ) { + return NULL; + } else { + p = src->v + ( ls - lo ); + return g_str_equal(p,op->v) ? src : NULL; + } + + /* case AVP_OP_TRANSF: */ + /* return do_transform(src,op); */ + case AVP_OP_CONTAINS: + /* TODO */ + return NULL; + } + /* will never get here */ + return NULL; +} + + + +/* TODO: rename me */ +/** + * new_avpl_loose_match: + * @name: the name of the resulting avpl + * @src: avpl to be matched agains an "op" avpl + * @op: the "op" avpl that will be matched against the src avpl + * @copy_avps: whether the avps in the resulting avpl should be copied + * + * creates an avp list containing any avps in src matching any avps in op + * it will eventually create an empty list in none match + * + * Return value: a pointer to the newly created avpl containing the + * matching avps. + **/ +extern AVPL* new_avpl_loose_match(guint8* name, + AVPL* src, + AVPL* op, + gboolean copy_avps) { + + AVPL* newavpl = new_avpl(scs_subscribe(avp_strings, name)); + AVPN* co = NULL; + AVPN* cs = NULL; + gint c; + AVP* m; + AVP* copy; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"new_avpl_loose_match: %X src=%X op=%X name='%s'",newavpl,src,op,name); +#endif + + + cs = src->null.next; + co = op->null.next; + while(1) { + + if (!co->avp) { + return newavpl; + } + + if (!cs->avp) { + return newavpl; + } + + + c = (guint) co->avp->n - (guint) cs->avp->n; + + if ( c > 0 ) { + if (co->avp) co = co->next; + } else if (c < 0) { + if (cs->avp) cs = cs->next; + } else { + m = match_avp(cs->avp,co->avp); + if(m) { + + if (copy_avps) { + copy = avp_copy(m); + if ( ! insert_avp(newavpl,copy) ) { + delete_avp(copy); + } + } else { + insert_avp(newavpl,m); + } + + + } + + if (cs->avp) cs = cs->next; + + } + } + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,6,dbg_fp,"new_avpl_loose_match: done!"); +#endif + + return NULL; +} + +/* TODO: rename me */ +/** +* new_avpl_every_match: + * @name: the name of the resulting avpl + * @src: avpl to be matched agains an "op" avpl + * @op: the "op" avpl that will be matched against the src avpl + * @copy_avps: whether the avps in the resulting avpl should be copied + * + * creates an avp list containing any avps in src matching every avp in op + * it will not create a list if there is not a match for every attribute in op + * + * Return value: a pointer to the newly created avpl containing the + * matching avps. + **/ +extern AVPL* new_avpl_every_match(guint8* name, AVPL* src, AVPL* op, gboolean copy_avps) { + AVPL* newavpl = new_avpl(scs_subscribe(avp_strings, name)); + AVPN* co = NULL; + AVPN* cs = NULL; + gint c; + AVP* m; + AVP* copy; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"new_avpl_every_match: %X src=%X op=%X name='%s'",newavpl,src,op,name); +#endif + + gboolean matches = TRUE; + + cs = src->null.next; + co = op->null.next; + while(1) { + + if (!co->avp) { + break; + } + + if (!cs->avp) { + break; + } + + c = (guint) co->avp->n - (guint) cs->avp->n; + + if ( c > 0 ) { + delete_avpl(newavpl,TRUE); + return NULL; + } else if (c < 0) { + cs = cs->next; + if (! cs->avp ) { + break; + } + } else { + m = match_avp(cs->avp,co->avp); + + if(m) { + matches++; + cs = cs->next; + co = co->next; + + if (copy_avps) { + copy = avp_copy(m); + if ( ! insert_avp(newavpl,copy) ) { + delete_avp(copy); + } + } else { + insert_avp(newavpl,m); + } + + } else { + cs = cs->next; + } + } + + } + + if (matches) { + return newavpl; + } else { + delete_avpl(newavpl,TRUE); + return NULL; + } +} + + +/* TODO: rename me */ +/** + * new_avpl_exact_match: + * @name: the name of the resulting avpl + * @src: avpl to be matched agains an "op" avpl + * @op: the "op" avpl that will be matched against the src avpl + * @copy_avps: whether the avps in the resulting avpl should be copied + * + * creates an avp list containing every avp in src matching every avp in op + * it will not create a list unless every avp in op is matched only once + * to every avp in op. + * + * Return value: a pointer to the newly created avpl containing the + * matching avps. + **/ +extern AVPL* new_avpl_exact_match(guint8* name,AVPL* src, AVPL* op, gboolean copy_avps) { + AVPL* newavpl = new_avpl(name); + AVPN* co = NULL; + AVPN* cs = NULL; + gint c; + AVP* m; + AVP* copy; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"new_avpl_every_match: %X src=%X op=%X name='%s'",newavpl,src,op,name); +#endif + + cs = src->null.next; + co = op->null.next; + while(1) { + + c = (guint) co->avp->n - (guint) cs->avp->n; + + if ( c > 0 ) { + delete_avpl(newavpl,TRUE); + return NULL; + } else if (c < 0) { + cs = cs->next; + if (! cs->avp ) { + delete_avpl(newavpl,TRUE); + return NULL; + } + } else { + m = match_avp(cs->avp,co->avp); + + if(m) { + cs = cs->next; + co = co->next; + + if (copy_avps) { + copy = avp_copy(m); + if ( ! insert_avp(newavpl,copy) ) { + delete_avp(copy); + } + } else { + insert_avp(newavpl,m); + } + + + if (!co->avp) { + return newavpl; + } + if (!cs->avp) { + delete_avpl(newavpl,TRUE); + return NULL; + } + } else { + delete_avpl(newavpl,TRUE); + return NULL; + } + } + + } + + /* should never be reached */ + return NULL; +} + + +/** + * new_avpl_transform: + * + * creates an empty avpl transformation + * + * Return value: a pointer to the newly created avpl transformation + **/ +extern AVPL_Transf* new_avpl_transform(guint8* name, AVPL* mixed, avpl_match_mode match_mode, avpl_replace_mode replace_mode) { + AVPL_Transf* t = g_malloc(sizeof(AVPL_Transf)); + AVP* avp; + + t->name = g_strdup(name); + t->match = new_avpl("match"); + t->replace = new_avpl("replace"); + t->match_mode = match_mode; + t->replace_mode = replace_mode; + t->next = NULL; + t->map = NULL; + + while (( avp = extract_first_avp(mixed) )) { + if (*(avp->n) == '.') { + rename_avp(avp,(avp->n+1)); + insert_avp(t->replace, avp); + } else { + insert_avp(t->match, avp); + } + } + + return t; +} + + +/** + * delete_avpl_transform: + * @it: a pointer to the avpl transformation object + * + * Destroys an avpl transformation object and releases all the resources it + * uses. + * + **/ +extern void delete_avpl_transform(AVPL_Transf* op) { + AVPL_Transf* next; + + for (; op ; op = next) { + next = op->next; + + g_free(op->name); + + if (op->match) { + delete_avpl(op->match,TRUE); + } + + if (op->replace) { + delete_avpl(op->replace,TRUE); + } + + g_free(op); + } + +} + + +/** + * avpl_transform: + * @src: the source avpl for the transform operation. + * @op: a pointer to the avpl transformation object to apply. + * + * Applies the "op" transformation to an avpl, matches it and eventually + * replaces or inserts the transformed avps. + * + * Return value: whether the transformation was performed or not. + **/ +extern void avpl_transform(AVPL* src, AVPL_Transf* op) { + AVPL* avpl = NULL; + AVPN* cs; + AVPN* cm; + AVPN* n; + gboolean d; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"avpl_transform: src=%X op=%X",src,op); +#endif + + for ( ; op ; op = op->next) { + switch (op->match_mode) { + case AVPL_STRICT: + avpl = new_avpl_exact_match(src->name,src,op->match,TRUE); + break; + case AVPL_LOOSE: + avpl = new_avpl_loose_match(src->name,src,op->match,TRUE); + break; + case AVPL_EVERY: + avpl = new_avpl_every_match(src->name,src,op->match,TRUE); + break; + case AVPL_NO_MATCH: + avpl = new_avpl(src->name); + break; + } + + if (avpl) { + switch (op->replace_mode) { + case AVPL_NO_REPLACE: + delete_avpl(avpl,TRUE); + return; + case AVPL_INSERT: + merge_avpl(src,op->replace,TRUE); + delete_avpl(avpl,TRUE); + return; + case AVPL_REPLACE: + cs = src->null.next; + cm = avpl->null.next; + d = FALSE; + while(cs->avp) { + if (cs->avp == cm->avp) { + n = cs->next; + + cs->prev->next = cs->next; + cs->next->prev = cs->prev; + g_mem_chunk_free(avp_chunk,cs); + + cs = n; + cm = cm->next; + } else { + cs = cs->next; + } + } + + merge_avpl(src,avpl,TRUE); + delete_avpl(avpl,TRUE); + return; + } + } + } +} + + +/** + * new_loal: + * @name: the name the loal will take. + * + * Creates an empty list of avp lists. + * + * Return value: a pointer to the newly created loal. + **/ +extern LoAL* new_loal(guint8* name) { + LoAL* new_loal = g_mem_chunk_alloc(avp_chunk); + + if (! name) { + name = "anonymous"; + } + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"new_loal: %X name=%s",new_loal,name); +#endif + + new_loal->name = scs_subscribe(avp_strings,name); + new_loal->null.avpl = NULL; + new_loal->null.next = &new_loal->null; + new_loal->null.prev = &new_loal->null; + + return new_loal; +} + +/** + * loal_append: + * @loal: the loal on which to operate. + * @avpl: the avpl to append. + * + * Appends an avpl to a loal. + * + **/ +extern void loal_append(LoAL* loal, AVPL* avpl) { + LoALnode* node = g_mem_chunk_alloc(avp_chunk); + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"new_loal_node: %X",node); +#endif + + node->avpl = avpl; + node->next = &loal->null; + node->prev = loal->null.prev; + + loal->null.prev->next = node; + loal->null.prev = node; +} + + +/** + * extract_first_avpl: + * @loal: the loal on which to operate. + * + * Extracts the first avpl contained in a loal. + * + * Return value: a pointer to the extracted avpl. + * + **/ +extern AVPL* extract_first_avpl(LoAL* loal) { + LoALnode* node; + AVPL* avpl; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"extract_first_avpl: from: %s",loal->name); +#endif + + node = loal->null.next; + + loal->null.next->next->prev = &loal->null; + loal->null.next = node->next; + + loal->len--; + + avpl = node->avpl; + + if ( avpl ) { + g_mem_chunk_free(avp_chunk,node); + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"extract_first_avpl: got %s",avpl->name); + dbg_print(dbg_avpl_op,3,dbg_fp,"delete_loal_node: %X",node); +#endif + } + + return avpl; +} + +/** +* extract_first_avpl: + * @loal: the loal on which to operate. + * + * Extracts the last avpl contained in a loal. + * + * Return value: a pointer to the extracted avpl. + * + **/ +extern AVPL* extract_last_avpl(LoAL* loal){ + LoALnode* node; + AVPL* avpl; + + node = loal->null.prev; + + loal->null.prev->prev->next = &loal->null; + loal->null.prev = node->prev; + + loal->len--; + + avpl = node->avpl; + + if ( avpl ) { + g_mem_chunk_free(avp_chunk,node); +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"delete_loal_node: %X",node); +#endif + } + + return avpl; +} + +/** + * extract_first_avpl: + * @loal: the loal on which to operate. + * @cookie pointer to the pointer variable to contain the state between calls + * + * At each call will return the following avpl from a loal. The given cookie + * will be used to manatain the state between calls. + * + * Return value: a pointer to the next avpl. + * + **/ +extern AVPL* get_next_avpl(LoAL* loal,void** cookie) { + LoALnode* node; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"get_next_avpl: loal=%X node=%X",loal,*cookie); +#endif + + if (*cookie) { + node = (LoALnode*) *cookie; + } else { + node = loal->null.next; + } + + *cookie = node->next; + + return node->avpl; +} + +/** + * delete_loal: + * @loal: the loal to be deleted. + * @avpls_too: whether avpls contained by the loal should be deleted as well + * @avps_too: whether avps contained by the avpls should be also deleted + * + * Destroys a loal and eventually desstroys avpls and avps. + * + **/ +extern void delete_loal(LoAL* loal, gboolean avpls_too, gboolean avps_too) { + AVPL* avpl; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"delete_loal: %X",loal); +#endif + + while(( avpl = extract_last_avpl(loal) )) { + if (avpls_too) { + delete_avpl(avpl,avps_too); + } + } + + scs_unsubscribe(avp_strings,loal->name); + g_mem_chunk_free(avp_chunk,loal); +} + + + +/**************************************************************************** + ******************* the following are used in load_loal_from_file + ****************************************************************************/ + +/** + * load_loal_error: + * Used by loal_from_file to handle errors while loading. + **/ +void load_loal_error(FILE* fp, LoAL* loal, AVPL* curr, int linenum, guint8* fmt, ...) { + va_list list; + guint8* desc; + + + va_start( list, fmt ); + desc = g_strdup_vprintf(fmt, list); + va_end( list ); + + if (fp) fclose(fp); + if (loal) delete_loal(loal,TRUE,TRUE); + if (curr) delete_avpl(curr,TRUE); + + g_warning("Error Loading LoAL from file: at line: %i, %s",linenum,desc); + g_free(desc); + + return; +} + + +/* the maximum lenght allowed for a line */ +#define MAX_ITEM_LEN 8192 + +/* this two ugly things are used for tokenizing */ +#define AVP_OP_CHAR '=': case '^': case '$': case '~': case '<': case '>': case '?': case '|': case '&' : case '!' + +#define AVP_NAME_CHAR 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J':\ +case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':\ +case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case 'a': case 'b': case 'c': case 'd':\ +case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':\ +case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':\ +case 'y': case 'z': case '_': case '0': case '1': case '2': case '3': case '4': case '5': case '6':\ +case '7': case '8': case '9': case '.' + + +/** + * loal_from_file: + * @filename: the file containing a loals text representation. + * + * Given a filename it will attempt to load a loal containing a copy of + * the avpls represented in the file. + * + * Return value: if successful a pointer to the new populated loal, else NULL. + * + **/ +extern LoAL* loal_from_file(guint8* filename) { + FILE *fp; + guint8 c; + int i = 0; + guint32 linenum = 1; + guint8 name[MAX_ITEM_LEN]; + guint8 value[MAX_ITEM_LEN]; + guint8 op = '?'; + LoAL *loal = new_loal(filename); + AVPL* curr = NULL; + AVP* avp; + + enum _load_loal_states { + START, + BEFORE_NAME, + IN_NAME, + IN_VALUE, + MY_IGNORE + } state; + +#ifndef _WIN32 + if (! getuid()) { + g_warning( "MATE Will not run as root"); + return NULL; + } +#endif + + state = START; + + if (( fp = fopen(filename,"r") )) { + while(( c = (guint8) fgetc(fp) )){ + + if ( feof(fp) ) { + if ( ferror(fp) ) { + load_loal_error(fp,loal,curr,linenum,"Error while reading '%f'",filename); + return NULL; + } + break; + } + + if ( c == '\n' ) { + linenum++; + } + + if ( i >= MAX_ITEM_LEN - 1 ) { + load_loal_error(fp,loal,curr,linenum,"Maximum item lenght exceeded"); + return NULL; + } + + switch(state) { + case MY_IGNORE: + switch (c) { + case '\n': + state = START; + i = 0; + continue; + default: + continue; + } + continue; + case START: + switch (c) { + case ' ': case '\t': + /* ignore whitespace at line start */ + continue; + case '\n': + /* ignore empty lines */ + i = 0; + continue; + case AVP_NAME_CHAR: + state = IN_NAME; + i = 0; + name[i++] = c; + name[i] = '\0'; + + curr = new_avpl(""); + continue; + case '#': + state = MY_IGNORE; + continue; + default: + load_loal_error(fp,loal,curr,linenum,"expecting name got: '%c'",c); + return NULL; + } + case BEFORE_NAME: + i = 0; + name[0] = '\0'; + switch (c) { + case '\\': + c = fgetc(fp); + if (c != '\n') ungetc(c,fp); + continue; + case ' ': + case '\t': + continue; + case AVP_NAME_CHAR: + state = IN_NAME; + + name[i++] = c; + name[i] = '\0'; + continue; + case '\n': + loal_append(loal,curr); + state = START; + continue; + default: + load_loal_error(fp,loal,curr,linenum,"expecting name got: '%c'",c); + return NULL; + } + case IN_NAME: + switch (c) { + case ';': + state = BEFORE_NAME; + + op = '?'; + name[i] = '\0'; + value[0] = '\0'; + i = 0; + + avp = new_avp(name,value,op); + + if (! insert_avp(curr,avp) ) { + delete_avp(avp); + } + + continue; + case AVP_OP_CHAR: + name[i] = '\0'; + i = 0; + op = c; + state = IN_VALUE; + continue; + case AVP_NAME_CHAR: + name[i++] = c; + continue; + case '\n': + load_loal_error(fp,loal,curr,linenum,"operator expected found new line"); + return NULL; + default: + load_loal_error(fp,loal,curr,linenum,"name or match operator expected found '%c'",c); + return NULL; + } + case IN_VALUE: + switch (c) { + case '\\': + value[i++] = fgetc(fp); + continue; + case ';': + state = BEFORE_NAME; + + value[i] = '\0'; + i = 0; + + avp = new_avp(name,value,op); + + if (! insert_avp(curr,avp) ) { + delete_avp(avp); + } + continue; + case '\n': + load_loal_error(fp,loal,curr,linenum,"';' expected found new line"); + return NULL; + default: + value[i++] = c; + continue; + } + } + } + fclose (fp); + + return loal; + + } else { + load_loal_error(NULL,loal,NULL,0,"Cannot Open file '%s'",filename); + return NULL; + } +} diff --git a/plugins/mate/mate_util.h b/plugins/mate/mate_util.h new file mode 100644 index 0000000000..d029cd1adf --- /dev/null +++ b/plugins/mate/mate_util.h @@ -0,0 +1,284 @@ +/* mate_util.h +* +* Copyright 2004, Luis E. Garcia Ontanon +* +* $Id$ +* +* Ethereal - Network traffic analyzer +* By Gerald Combs +* Copyright 1998 Gerald Combs +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + +/* Note: + * Although for now it is used only by tracing.c + * I decided to make it into a separate module + * since one day in the near future I will be using it + * to reimplement packet-radius.c + */ + + +#ifndef __AVP_H_ +#define __AVP_H_ +#include "epan/proto.h" +#include +#ifdef HAVE_UNISTD_H +#include +#endif + + +/* #define _AVP_DEBUGGING */ + + +/******* dbg_print *********/ +#define DEBUG_BUFFER_SIZE 4096 +extern void dbg_print(const guint* which, guint how, FILE* where, guint8* fmt, ... ); + + +/******* single copy strings *********/ + +extern void scs_init(GHashTable** hash); +extern guint8* scs_subscribe(GHashTable* collection, guint8* s); +extern void scs_unsubscribe(GHashTable* collection, guint8* s); +extern guint8* scs_subscribe_printf(GHashTable* collection, guint8* fmt, ...); + +/******* AVPs & Co. *********/ +#define AVP_CHUNK_SIZE 4096 + +/* these are the defined oreators of avps */ +#define AVP_OP_EQUAL '=' +#define AVP_OP_NOTEQUAL '!' +#define AVP_OP_STARTS '^' +#define AVP_OP_ENDS '$' +#define AVP_OP_CONTAINS '~' +#define AVP_OP_LOWER '<' +#define AVP_OP_HIGHER '>' +#define AVP_OP_EXISTS '?' +#define AVP_OP_ONEOFF '|' +#define AVP_OP_TRANSF '&' + + +/* an avp is an object made of a name a value and an operator */ +typedef struct _avp { + guint8* n; + guint8* v; + guint8 o; +} AVP; + +/* avp nodes are used in avp lists */ +typedef struct _avp_node { + AVP* avp; + struct _avp_node* next; + struct _avp_node* prev; +} AVPN; + +/* an avp list is a sorted set of avps */ +typedef struct _avp_list { + guint8* name; + guint32 len; + AVPN null; +} AVPL; + + + +/* an avpl transformation operation */ +typedef enum _avpl_match_mode { + AVPL_NO_MATCH, + AVPL_STRICT, + AVPL_LOOSE, + AVPL_EVERY +} avpl_match_mode; + +typedef enum _avpl_replace_mode { + AVPL_NO_REPLACE, + AVPL_INSERT, + AVPL_REPLACE, +} avpl_replace_mode; + +typedef struct _avpl_transf AVPL_Transf; + +struct _avpl_transf { + guint8* name; + + AVPL* match; + AVPL* replace; + + avpl_match_mode match_mode; + avpl_replace_mode replace_mode; + + GHashTable* map; + AVPL_Transf* next; +}; + +/* loalnodes are used in LoALs */ +typedef struct _loal_node { + AVPL* avpl; + struct _loal_node *next; + struct _loal_node *prev; +} LoALnode; + + +/* a loal is a list of avp lists */ +typedef struct _loal { + guint8* name; + guint len; + LoALnode null; +} LoAL; + + +/* avp library (re)initialization */ +extern void avp_init(void); + +/* If enabled set's up the debug facilities for the avp library */ +#ifdef _AVP_DEBUGGING +extern void setup_avp_debug(FILE* fp, int* general, int* avp, int* avp_op, int* avpl, int* avpl_op); +#endif /* _AVP_DEBUGGING */ + +/* + * avp constructors + */ + +/* creates a new avp */ +extern AVP* new_avp(guint8* name, guint8* value, guint8 op); + +/* creates a copy od an avp */ +extern AVP* avp_copy(AVP* from); + +/* creates an avp from a field_info record */ +extern AVP* new_avp_from_finfo(guint8* name, field_info* finfo); + +/* + * avp destructor + */ +extern void delete_avp(AVP* avp); + +/* + * avp methods + */ +/* returns a newly allocated string containing a representation of the avp */ +#define avp_to_str(avp) (g_strdup_printf("%s%c%s",avp->n,avp->o,avp->v)) + +/* returns the src avp if the src avp matches(*) the op avp or NULL if it doesn't */ +extern AVP* match_avp(AVP* src, AVP* op); + + +/* + * avplist constructors + */ + +/* creates an empty avp list */ +extern AVPL* new_avpl(guint8* name); + + +/* creates a copy of an avp list */ +extern AVPL* new_avpl_from_avpl(guint8* name, AVPL* avpl, gboolean copy_avps); + +/* creates an avp list containing any avps in src matching any avps in op + it will eventually create an empty list in none match */ +extern AVPL* new_avpl_loose_match(guint8* name,AVPL* src, AVPL* op, gboolean copy_avps); + +/* creates an avp list containing any avps in src matching every avp in op + it will not create a list if there is not a match for every attribute in op */ +extern AVPL* new_avpl_every_match(guint8* name,AVPL* src, AVPL* op, gboolean copy_avps); + +/* creates an avp list containing every avp in src matching every avp in op + it will not create a list unless every avp in op is matched only once to avery avp in op */ +extern AVPL* new_avpl_exact_match(guint8* name,AVPL* src, AVPL* op, gboolean copy_avps); + +/* uses mode to call one of the former matches. NO_MATCH = merge(merge(copy(src),op)) */ +extern AVPL* new_avpl_from_match(avpl_match_mode mode, guint8* name,AVPL* src, AVPL* op, gboolean copy_avps); + + + +/* + * avplist destructor + */ +extern void delete_avpl(AVPL* avpl, gboolean avps_too); + +/* + * functions on avpls + */ + +/* it will insert an avp to an avpl */ +extern gboolean insert_avp(AVPL* avpl, AVP* avp); + +/* renames an avpl */ +extern void rename_avpl(AVPL* avpl, guint8* name); + +/* it will add all the avps in src which don't match(*) any attribute in dest */ +extern void merge_avpl(AVPL* dest, AVPL* src, gboolean copy); + +/* it will return the first avp in an avpl whose name matches the given name. + will return NULL if there is not anyone matching */ +extern AVP* get_avp_by_name(AVPL* avpl, guint8* name, void** cookie); + +/* it will get the next avp from an avpl, using cookie to keep state */ +extern AVP* get_next_avp(AVPL* avpl, void** cookie); + +/* it will extract the first avp from an avp list */ +extern AVP* extract_first_avp(AVPL* avpl); + +/* it will extract the last avp from an avp list */ +extern AVP* extract_last_avp(AVPL* avpl); + +/* it will extract the first avp in an avpl whose name matches the given name. + it will not extract any and return NULL if there is not anyone matching */ +extern AVP* extract_avp_by_name(AVPL* avpl, guint8* name); + +/* returns a newly allocated string containing a representation of the avp list */ +extern guint8* avpl_to_str(AVPL* avpl); +extern guint8* avpl_to_dotstr(AVPL*); + +/* deletes an avp list and eventually it's contents */ +extern void delete_avpl(AVPL* avpl, gboolean avps_too); + +/* + * AVPL transformations + */ +extern AVPL_Transf* new_avpl_transform(guint8* name, AVPL* mixed, avpl_match_mode match_mode, avpl_replace_mode replace_mode); +extern void delete_avpl_transform(AVPL_Transf* it); +extern void avpl_transform(AVPL* src, AVPL_Transf* op); + + +/* + * Lists of AVP lists + */ + +/* creates an empty list of avp lists */ +extern LoAL* new_loal(guint8* name); + +/* given a file loads all the avpls contained in it + every line is formatted as it is the output of avplist_to_string */ +extern LoAL* loal_from_file(guint8* filename); + +/* inserts an avplist into a LoAL */ +extern void loal_append(LoAL* loal, AVPL* avpl); + +/* extracts the first avp list from the loal */ +extern AVPL* extract_first_avpl(LoAL* loal); + +/* extracts the last avp list from the loal */ +extern AVPL* extract_last_avpl(LoAL* loal); + +/* it will get the next avp list from a LoAL, using cookie to keep state */ +extern AVPL* get_next_avpl(LoAL* loal,void** cookie); + +/* deletes a loal and eventually it's contents */ +extern void delete_loal(LoAL* loal, gboolean avpls_too, gboolean avps_too); + + +#endif diff --git a/plugins/mate/matelib/dns.mate b/plugins/mate/matelib/dns.mate new file mode 100644 index 0000000000..47db859544 --- /dev/null +++ b/plugins/mate/matelib/dns.mate @@ -0,0 +1,19 @@ +# dns.thing + +Action=Settings; SessionExpiration=300; + +Action=PDU; Proto=ftp; Transport=ip; addr=ip.addr; port=ftp.passive.port; +Action=LegKey; On=ftp; addr!65.; +Action=LegStart; On=ftp; addr!; + +Action=PDU; Proto=tcp; Transport=ip; addr=ip.addr; port=tcp.port; tcp_start=tcp.flags.syn; tcp_stop=tcp.flags.reset; tcp_stop=tcp.flags.fin; +Action=LegKey; On=tcp; addr!21; addr; port; port; +Action=LegStart; On=tcp; tcp_start=1; +Action=LegStop; On=tcp; tcp_stop=1; + +Action=PDU; Proto=dns; Transport=ip; addr=ip.addr; dns_id=dns.id; dns_rsp=dns.flags.response; dns_name=dns.name; +Action=LegKey; On=dns; addr; addr; dns_id; +Action=LegStart; On=dns; dns_rsp=0; +Action=LegStop; On=dns; dns_rsp=1; +Action=LegExtra; On=dns; dns_name; + diff --git a/plugins/mate/matelib/h225_ras.mate b/plugins/mate/matelib/h225_ras.mate new file mode 100644 index 0000000000..701e9b40fa --- /dev/null +++ b/plugins/mate/matelib/h225_ras.mate @@ -0,0 +1,7 @@ +# h225_ras.thing +# (c) 2004 Luis E. Garcia Ontanon + +Action=PDU; Proto=h225.RasMessage; Transport=ip; ras_msg=h225.RasMessage; addr=ip.addr; guid=h225.guid; seqnum=h225.RequestSeqNum; +Action=LegKey; On=h225.RasMessage; addr; addr; seqnum; +Action=LegStart; On=h225.RasMessage; ras_msg|0|3|6|9|12|15|18|21|26|30; +Action=LegStop; On=h225.RasMessage; ras_msg|1|2|4|5|7|8|10|11|13|14|16|17|19|20|22|24|27|28|29|31; diff --git a/plugins/mate/matelib/isup.mate b/plugins/mate/matelib/isup.mate new file mode 100644 index 0000000000..0f9fbe2832 --- /dev/null +++ b/plugins/mate/matelib/isup.mate @@ -0,0 +1,6 @@ +# isup.thing + +Action=PDU; Proto=isup; Transport=mtp3; mtp3pc=mtp3.dpc; mtp3pc=mtp3.opc; cic=isup.cic; isup_msg=isup.message_type; called=isup.called; calling=isup.calling; isup_cause=isup.cause_indicator; +Action=LegKey; On=isup; cic; mtp3pc; mtp3pc; +Action=LegStart; On=isup; isup_msg=1; +Action=LegStop; On=isup; isup_msg=16; diff --git a/plugins/mate/matelib/megaco.mate b/plugins/mate/matelib/megaco.mate new file mode 100644 index 0000000000..c8af030769 --- /dev/null +++ b/plugins/mate/matelib/megaco.mate @@ -0,0 +1,6 @@ +# megaco.thing + +Action=PDU; Proto=megaco; Transport=ip; addr=ip.addr; megaco_ctx=megaco.context; megaco_trx=megaco.transid; megaco_msg=megaco.transaction; term=megaco.termid; +Action=LegKey; On=megaco; addr; addr; megaco_trx; +Action=LegStart; On=megaco; megaco_msg|Request|Notify; +Action=LegStop; On=megaco; megaco_msg=Reply; diff --git a/plugins/mate/matelib/q931.mate b/plugins/mate/matelib/q931.mate new file mode 100644 index 0000000000..3d66e8a7a8 --- /dev/null +++ b/plugins/mate/matelib/q931.mate @@ -0,0 +1,6 @@ +# q931.thing + +Action=PDU; Proto=q931; Transport=ip; addr=ip.addr; call_ref=q931.call_ref; q931_msg=q931.message_type; guid=h225.guid; called=q931.called_party_number.digits; calling=q931.calling_party_number.digits; q931_cause=q931.cause_value; h225_cause=h225.ReleaseCompleteReason; +Action=LegKey; On=q931; call_ref; addr; addr; +Action=LegStart; On=q931; q931_msg=5; +Action=LegStop; On=q931; q931_msg=90; diff --git a/plugins/mate/matelib/radius.mate b/plugins/mate/matelib/radius.mate new file mode 100644 index 0000000000..0de9aab86e --- /dev/null +++ b/plugins/mate/matelib/radius.mate @@ -0,0 +1,7 @@ +# radius.thing + +Action=pdu; Proto=radius; Transport=ip; addr=ip.addr; radius_id=radius.id; radius_code=radius.code; calling=radius.calling; + +Action=pdukey; On=radius; radius_id; addr; addr; +Action=start; On=radius; radius_code=4; +Action=stop; On=radius; radius_code=5; diff --git a/plugins/mate/matelib/rtsp.mate b/plugins/mate/matelib/rtsp.mate new file mode 100644 index 0000000000..c25ebf5ef3 --- /dev/null +++ b/plugins/mate/matelib/rtsp.mate @@ -0,0 +1,5 @@ + +Action=PDU; Proto=rtsp; Transport=ip; isup_msg=isup.message_type; calling=X_Vig_Msisdn; rtsp_method=rtsp.method; rtsp_ses=rtsp.session; addr=ip.addr; rtsp_url=rtsp.url; +Action=LegKey; On=rtsp; rtsp_ses; +Action=LegStart; On=rtsp; rtsp_method=SETUP; +Action=LegStop; On=rtsp; rtsp_method=TEARDOWN; diff --git a/plugins/mate/matelib/sip.mate b/plugins/mate/matelib/sip.mate new file mode 100644 index 0000000000..4da296fff9 --- /dev/null +++ b/plugins/mate/matelib/sip.mate @@ -0,0 +1,6 @@ +# sip.thing + +Action=PDU; Proto=sip; Transport=ip; addr=ip.addr; sip_method=sip.Method; sip_callid=sip.Call-ID; calling=sdp.owner.username; +Action=LegKey; On=sip; sip_callid; addr; addr; +Action=LegStart; On=sip; sip_method=INVITE; +Action=LegStop; On=sip; sip_method=BYE; diff --git a/plugins/mate/moduleinfo.h b/plugins/mate/moduleinfo.h new file mode 100644 index 0000000000..569556f83d --- /dev/null +++ b/plugins/mate/moduleinfo.h @@ -0,0 +1,16 @@ +/* Included *after* config.h, in order to re-define these macros */ + +#ifdef PACKAGE +#undef PACKAGE +#endif + +/* Name of package */ +#define PACKAGE "mate" + +#ifdef VERSION +#undef VERSION +#endif + +/* Version number of package */ +#define VERSION "0.0.3" + diff --git a/plugins/mate/packet-mate.c b/plugins/mate/packet-mate.c new file mode 100644 index 0000000000..53b9b4557e --- /dev/null +++ b/plugins/mate/packet-mate.c @@ -0,0 +1,321 @@ +/* packet-mate.c + * Routines for the mate Facility's Pseudo-Protocol dissection + * + * Copyright 2004, Luis E. Garcia Ontanon + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +/************************************************************************** + * This is the pseudo protocol dissector for the mate module. *** + * It is intended for this to be just the user interface to the module. *** + **************************************************************************/ + +#include "mate.h" + +static int mate_tap_data = 0; +static mate_config* mc = NULL; + +static int proto_mate = -1; + +static gint ett_mate = -1; +static gint ett_mate_pdu = -1; +static gint ett_mate_pdu_attr = -1; + +static gint ett_mate_gop = -1; +static gint ett_mate_gop_attr = -1; +static gint ett_mate_gop_pdus = -1; +static gint ett_mate_gop_times = -1; + +static gint ett_mate_gog = -1; +static gint ett_mate_gog_attr = -1; +static gint ett_mate_gog_gops = -1; +static gint ett_mate_gop_in_gog = -1; + +static char* pref_mate_config_filename = "config.mate"; + +static proto_item *mate_i = NULL; + +void attrs_tree(proto_tree* tree, tvbuff_t *tvb,mate_item* item) { + AVPN* c; + proto_item *avpl_i; + proto_tree *avpl_t; + int* hfi_p; + + gint our_ett; + + switch (item->cfg->type) { + case MATE_PDU_TYPE: + our_ett = ett_mate_pdu_attr; + break; + case MATE_GOP_TYPE: + our_ett = ett_mate_pdu_attr; + break; + case MATE_GOG_TYPE: + our_ett = ett_mate_pdu_attr; + break; + default: + our_ett = ett_mate; + break; + } + + avpl_i = proto_tree_add_text(tree,tvb,0,0,"%s Attributes",item->cfg->name); + avpl_t = proto_item_add_subtree(avpl_i, our_ett); + + for ( c = item->avpl->null.next; c->avp; c = c->next) { + hfi_p = g_hash_table_lookup(item->cfg->my_hfids,c->avp->n); + + if (hfi_p) { + proto_tree_add_string(avpl_t,*hfi_p,tvb,0,0,c->avp->v); + } else { + g_warning("MATE: error: undefined attribute: mate.%s.%s",item->cfg->name,c->avp->n); + proto_tree_add_text(avpl_t,tvb,0,0,"Undefined attribute: %s=%s",c->avp->n, c->avp->v); + } + } +} + +void mate_gop_tree(proto_tree* pdu_tree, tvbuff_t *tvb, mate_gop* gop, gint ett); + +void mate_gog_tree(proto_tree* tree, tvbuff_t *tvb, mate_gog* gog, mate_gop* gop) { + proto_item *gog_item; + proto_tree *gog_tree; + proto_item *gog_gop_item; + proto_tree *gog_gop_tree; + mate_gop* gog_gops; +#ifdef _MATE_DEBUGGING + proto_item* gog_key_item; + proto_tree* gog_key_tree; + guint i; +#endif + + gog_item = proto_tree_add_string(tree,gog->cfg->hfid,tvb,0,0,gog->id); + gog_tree = proto_item_add_subtree(gog_item,ett_mate_gog); + + attrs_tree(gog_tree,tvb,gog); + + gog_gop_item = proto_tree_add_uint(gog_tree, gog->cfg->hfid_gog_num_of_gops, + tvb, 0, 0, gog->num_of_gops); + + gog_gop_tree = proto_item_add_subtree(gog_gop_item, ett_mate_gog_gops); + + for (gog_gops = gog->gops; gog_gops; gog_gops = gog_gops->next) { + + if (gop != gog_gops) { + mate_gop_tree(gog_gop_tree, tvb, gog_gops, ett_mate_gop_in_gog); + } else { + proto_tree_add_string_format(gog_gop_tree,gop->cfg->hfid,tvb,0,0,gop->id,"GOP of current frame: %s",gop->id); + } + } + +} + +void mate_gop_tree(proto_tree* tree, tvbuff_t *tvb, mate_gop* gop, gint gop_ett) { + proto_item *gop_item; + proto_tree *gop_time_tree; + proto_item *gop_time_item; + proto_tree *gop_tree; + proto_item *gop_pdu_item; + proto_tree *gop_pdu_tree; + mate_pdu* gop_pdus; + float rel_time; + float gop_time; + + gop_item = proto_tree_add_string(tree,gop->cfg->hfid,tvb,0,0,gop->id); + gop_tree = proto_item_add_subtree(gop_item, gop_ett); + + if (gop->gop_key) proto_tree_add_text(gop_tree,tvb,0,0,"GOP Key: %s",gop->gop_key); + + attrs_tree(gop_tree,tvb,gop); + + if (gop->cfg->show_gop_times) { + gop_time_item = proto_tree_add_text(gop_tree,tvb,0,0,"%s Times",gop->cfg->name); + gop_time_tree = proto_item_add_subtree(gop_time_item, ett_mate_gop_times); + + proto_tree_add_float(gop_time_tree, gop->cfg->hfid_gop_start_time, tvb, 0, 0, gop->start_time); + + if (gop->released) { + proto_tree_add_float(gop_time_tree, gop->cfg->hfid_gop_stop_time, tvb, 0, 0, gop->release_time); + if (gop->release_time != gop->last_time) { + proto_tree_add_float(gop_time_tree, gop->cfg->hfid_gop_last_time, tvb, 0, 0, gop->last_time); + } + } else { + proto_tree_add_float(gop_time_tree, gop->cfg->hfid_gop_last_time, tvb, 0, 0, gop->last_time); + } + } + + rel_time = gop_time = gop->start_time; + + gop_pdu_item = proto_tree_add_uint(gop_tree, gop->cfg->hfid_gop_num_pdus, tvb, 0, 0,gop->num_of_pdus); + gop_pdu_tree = proto_item_add_subtree(gop_pdu_item, ett_mate_gop_pdus); + + if (gop->cfg->show_pdu_tree) { + for (gop_pdus = gop->pdus; gop_pdus; gop_pdus = gop_pdus->next) { + if (gop_pdus->is_start) { + proto_tree_add_uint_format(gop_pdu_tree,gop->cfg->hfid_gop_pdu, + tvb,0,0,gop_pdus->frame, + "Start PDU: in frame %i", + gop_pdus->frame); + } else if (gop_pdus->is_stop) { + proto_tree_add_uint_format(gop_pdu_tree,gop->cfg->hfid_gop_pdu, + tvb,0,0,gop_pdus->frame, + "Stop PDU: in frame %i (%f : %f)", + gop_pdus->frame, + gop_pdus->rel_time, + gop_pdus->rel_time-rel_time); + + } else if (gop_pdus->after_release) { + proto_tree_add_uint_format(gop_pdu_tree,gop->cfg->hfid_gop_pdu, + tvb,0,0,gop_pdus->frame, + "After stop PDU: in frame %i (%f : %f)", + gop_pdus->frame, + gop_pdus->rel_time, + gop_pdus->rel_time-rel_time); + } else { + proto_tree_add_uint_format(gop_pdu_tree,gop->cfg->hfid_gop_pdu, + tvb,0,0,gop_pdus->frame, + "PDU: in frame %i (%f : %f)", + gop_pdus->frame, + gop_pdus->rel_time, + gop_pdus->rel_time-rel_time); + } + + rel_time = gop_pdus->rel_time; + + } + } +} + + +void mate_pdu_tree(mate_pdu *pdu, tvbuff_t *tvb, proto_tree* tree) { + proto_item *pdu_item; + proto_tree *pdu_tree; + guint32 len; + + if ( ! pdu ) return; + + if (pdu->gop && pdu->gop->gog) { + proto_item_append_text(mate_i," %s->%s->%s",pdu->id,pdu->gop->id,pdu->gop->gog->id); + } else if (pdu->gop) { + proto_item_append_text(mate_i," %s->%s",pdu->id,pdu->gop->id); + } else { + proto_item_append_text(mate_i," %s",pdu->id); + } + + len = pdu->end - pdu->start; + pdu_item = proto_tree_add_string(tree,pdu->cfg->hfid,tvb,pdu->start,len,pdu->id); + pdu_tree = proto_item_add_subtree(pdu_item, ett_mate_pdu); + proto_tree_add_float(pdu_tree,pdu->cfg->hfid_pdu_rel_time, tvb, 0, 0, pdu->rel_time); + + if (pdu->gop) { + mate_gop_tree(pdu_tree,tvb,pdu->gop,ett_mate_gop); + + if (pdu->gop->gog) + mate_gog_tree(pdu_tree,tvb,pdu->gop->gog,pdu->gop); + } + + if (pdu->avpl) { + attrs_tree(pdu_tree,tvb,pdu); + } +} + +extern void mate_tree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { + mate_pdu* pdus; + proto_tree *mate_t; + + if (! tree ) return; + + if (( pdus = mate_get_pdus(pinfo->fd->num) )) { + + mate_i = proto_tree_add_text(tree,tvb,0,0,"mate"); + + mate_t = proto_item_add_subtree(mate_i, ett_mate); + + for ( ; pdus; pdus = pdus->next_in_frame) { + mate_pdu_tree(pdus,tvb,mate_t); + } + } +} + +static void init_mate(void) { + GString* tap_error = NULL; + + tap_error = register_tap_listener("frame", &mate_tap_data, + mc->tap_filter, + NULL, + mate_packet, + NULL); + + if ( tap_error ) { + g_warning("mate: couldn't (re)register tap: %s",tap_error->str); + g_string_free(tap_error, TRUE); + mate_tap_data = 0; + return; + } else { + mate_tap_data = 1; + } + + init_mate_runtime_data(); +} + +extern +void +proto_reg_handoff_mate(void) +{ +} + + +extern +void +proto_register_mate(void) +{ + static gint *ett[] = { + &ett_mate, + &ett_mate_pdu, + &ett_mate_pdu_attr, + &ett_mate_gop, + &ett_mate_gop_attr, + &ett_mate_gop_times, + &ett_mate_gop_pdus, + &ett_mate_gog, + &ett_mate_gog_gops, + &ett_mate_gog_attr, + &ett_mate_gop_in_gog + }; + + mc = mate_make_config(pref_mate_config_filename); + + if (mc) { + + proto_mate = proto_register_protocol("Meta Analysis Tracing Engine", "mate", "mate"); + + + proto_register_field_array(proto_mate, (hf_register_info*) mc->hfrs->data, mc->hfrs->len ); + + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("mate",mate_tree,proto_mate); + + register_init_routine(init_mate); + + } +} + diff --git a/plugins/mate/presentation.txt b/plugins/mate/presentation.txt new file mode 100644 index 0000000000..d8205cbd3b --- /dev/null +++ b/plugins/mate/presentation.txt @@ -0,0 +1,91 @@ +Hi, + + I think this fifth rewrite has taken it out of prototype stage and makes it +look almost as "production" code, please tell me if it doesn't. I do not plan +to rewrite it again. I'm realy happy with what it has become. + +This has surpassed my initial goal by far. It had just to to be a filter for +packets of calls, using few protocols, based on the calling number. + +My original idea was just to rewrite inside ethereal a perl script I had +written to split calls. I needed to decode h225 and could not get Decode::ASN1 +to compile the h225 syntax, I thought that migrating it into ethereal would +had been easy. I was *VERY* wrong. + +At the begining it was ECTAF it extracted data from ISUP and Q931. I hard +coded the extraction code directly in the dissectors and did an ugly job +putting it into several hashes but kida threaded the PDUs. + +Later I wrote the AVP Lib for it. So that I would converge dealing with the +different protocols into a single mechanism. H225 got into the picture but +wasn't versatile enough. Still I used code in the dissectors to extract the +data. + +As I tried to get MEGACO into the picture I wrote a parser to import the +dpc+cic->term mapping. It took me a day to "see the light", ECTAF used the +AVPLs as a logical engine already, I had a parser for AVPLs, 1+1=2, so: +importing the logic from a config file wasa natuiral step for it. STTF was +the name then (I never got it to be usable, that's why I did not release then). + +At that point I started working into fetching data from the tree, getting it +into avpls match the avpls to group the pdus etc... the nice "thing" was that +it was configurable. I called it TTT. + +I released about a month ago something called "Thing" that was the result of +that metamorphosis. A configurable tool that allows to use ethereal to do +analysis at the session and application level. Not only on what the frames +carry but on how they interact. + +Now I release a nicelly wrapped version of it. I fixed many things and made +code that I believe to be versatile enough to be able to grow, clean enough to +be mantainable. + +Anyway today's MATE is just the core of an application in the application. It +has plenty of room to grow. + +There are still things I will be doing on MATE's code in the very next future: + +- add timers to gops so that if they expire before their stop condition the gop + gets "marked". + +- merge two gogs whenever a new gog matches keys of some previous unexpired gog + +- spawn pre-started "empty" gops if a pdu of a gop in the gogs matches + a given condition. + +- use mem_chunks to store most of the strings in the AVP library + * one for small strings (<16bytes) + * one for midsized strings (<32 bytes) + * one for large strings (<64 bytes) + * g_malloc for the remaining cases + +- the avpl transformations will be reimplemeted + * a contextual_avp_op(AVPL_Transf* ctx, AVPL* src, AVP* avp, AVP* op) + has to be written to allow to transform AVPs extracting its value from + the source avpl and/or manupulating its contents. + * a map method that uses a hash will replace the "extremely slow" long + sequence of very similar matches that is used right now + +- get rid of most of the dbg_print calls in the code and give sense to the + debug levels, which by now are almost randomic. + + +There are things other I cannot/"do not plan to" do that would be nice +if someone else did: + +- build it as a plugin on Win32. However it may be better to get it in epan and + forget about pluginizing it. + +- make it work with tethereal. This has frustrated me twice: + first because I meant it to be used as a filter on live capture to save only + packets of a call from a given number. And, second, because I tried very hard + and failed miserably. + +- GUI gizmos (I don't stand GUI programming, sorry) : + an pane for sessions, + a Graphical config tool + ? + +- tap it, that is, we got plenty of information on how frames interact why + don't we give the users the ability to do the math with it. +