argus-clients-2.0.6.fixes.1/0000775000076600007660000000000010047734056011340 5argus-clients-2.0.6.fixes.1/COPYING0000664000076600007660000004311007306722372012314 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. argus-clients-2.0.6.fixes.1/CREDITS0000664000076600007660000000137407637605145012314 CREDITS An amazing amount of work, comments and bug fixes were provided by the members of the argus mailing list. Kudos especially to: Russell Fulton (r.fulton@auckland.ac.nz) Peter Van Epp (vanepp@sfu.ca) David Brumley (dbrumley@rtfm.stanford.com) Neil Long (neil.long@computing-services.oxford.ac.uk) Olaf Gellert Clauss Strauch (Clauss_Strauch@aquila.fac.cs.cmu.edu) William Setzer (William_Setzer@ncsu.edu) Scott McIntyre (scott@xs4all.nl) Of course much thanks to the continued support of Mark Poepping (poepping@cmu.edu), Walter Wong (wcw+@cmu.edu) and Larry Greenfield (leg+@andrew.cmu.edu) at CMU for their help with all things, resources, configuration, SASL, and general comments about the architecture. argus-clients-2.0.6.fixes.1/ChangeLog0000664000076600007660000003773210047733774013054 Mon May 10 13:11:35 EDT 2004 argus-clients-2.0.6.fixes.1 Modified RaAutoCorrection to be off by default (fixes ragator). Turned off reporting ArgusAgrStruct in raxml(). Fri Dec 5 11:43:08 EST 2003 argus-clients-2.0.6 Minor modification for compat.h and BSD. Thu Sep 11 10:22:14 EDT 2003 argus-clients-2.0.6.beta.47 Modifications for BSD port in gencode.c and grammar.y Tue Sep 2 11:30:12 EDT 2003 argus-clients-2.0.6.beta.46 Modifications for HostSvc support in ramon. Renamed HostP to HostProto. Fixes for reading from stdin. Mods for BSD port. Wed Aug 27 12:01:19 EDT 2003 argus-clients-2.0.6.beta.45 More fixes for cisco cflowd/etc ... record reading. Mon Aug 25 16:00:15 EDT 2003 argus-clients-2.0.6.beta.44 Fixed issues with cisco record reading. Wed Aug 20 10:10:47 EDT 2003 argus-clients-2.0.6.beta.44 Updated config.[guess , sub]. Sun Aug 17 22:42:21 EDT 2003 argus-clients-2.0.6.beta.43 Mod to fix 'proto value' compiler error. Thu Jul 10 13:27:57 EDT 2003 argus-clients-2.0.6.beta.42 Mods to add support for ./configure --prefix='whatever' Wed Jul 9 17:11:01 EDT 2003 argus-clients-2.0.6.beta.41 Mods to add HostP mode to ramon.c Fri May 2 08:31:09 EDT 2003 argus-clients-2.0.6.beta.40 Mods to fix RTP loss reporting. Wed Mar 26 22:51:26 EST 2003 argus-clients-2.0.6.beta.39 Mods to fix 1.8 compatibility problem. Updated ragraph() and rahistogram() to include improvements. Updated rapolicy() to write out only records that match. Fixed parsing bug in rapolicy() for est as final directive. Mods to ramon() to fix segfault when output is less than N. Mon Mar 24 08:39:18 EST 2003 argus-clients-2.0.6.beta.39 Added back rapolicy.1 man page and fixed manpage installs in Makefile.in. Thu Jan 9 01:23:35 EST 2003 argus-clients-2.0.6.beta.38 Major problems with -t option parsing. Many fixes. Thu Oct 24 08:12:39 EDT 2002 argus-clients-2.0.6.beta.37 Updated ./configure.in and aclocal.m4 to do the right thing for large file support. Seems that old versions crept back into the distribution. updated ragraph to handle colors and labels correctly. Thu Oct 17 06:49:38 EDT 2002 argus-clients-2.0.6.beta.36 Updated racount to generate correct label when using ARGUS_RMON data. Tue Oct 15 22:25:10 EDT 2002 argus-clients-2.0.6.beta.36 Update ./config/config.guess and config.sub from gnu.org. Tue Oct 15 10:26:51 EDT 2002 argus-clients-2.0.6.beta.35 Modified ramon to support CIDR net masking on topn and matrix output. Also added output record filter matching. Defeat it with -a option. Tue Sep 24 07:41:16 EDT 2002 argus-clients-2.0.6.beta.34 Added default sorting to ratop, pkts then bytes. Added 'u' option to change window update rate. Mods to fix screen update for 'M'ode changes in ratop. Mods to fix wrap problems in ratop when resizing window. Wed Sep 11 08:47:33 EDT 2002 argus-clients-2.0.6.beta.32 mods to rastrip and the addition of rastrip man page. Tue Sep 10 07:48:45 EDT 2002 argus-clients-2.0.6.beta.31 mods to ragraph/rahistogram to improve performance. mods to fix rahosts() always reporting address 0.0.0.0 Tue Sep 3 11:45:39 EDT 2002 argus-clients-2.0.6.beta.30 mods to ragator for better histogram behavior. mods to add probe id to aggregation model. Fri Aug 16 14:19:15 EDT 2002 argus-clients-2.0.6.beta.26 Mods to fix bug in get_argus_string() where junk was left over between calls. Tue Aug 6 08:32:36 EDT 2002 argus-clients-2.0.6.beta.22 Improvements for -s option, so you can put multiple options at once. Same strategy as -r. Significant changes to ratop, and racast to improve curses performance. Looking for memory leaks. Fri Aug 2 17:45:42 EDT 2002 argus-clients-2.0.6.beta.21 fixed bug in compiler for fragment filter. Tue Jul 23 11:02:54 EDT 2002 argus-clients-2.0.6.beta.18 Added ./perl directory with beginnings of Argus perl module. Mon Jul 22 16:24:44 EDT 2002 argus-clients-2.0.6.beta.17 Fixed memory leak issues with more aggresive queue management. Fri Jun 28 18:37:53 EDT 2002 argus-clients-2.0.6.beta.6 Minor fixes for various problems with ratop for curses problems, but not good enough for Solaris, yet..... Fri May 24 17:09:11 EDT 2002 argus-clients-2.0.5 Increase the policy size from 128 to 2048 Thu May 23 16:40:07 EDT 2002 argus-clients-2.0.5 Fixed RaAutoCorrection issue with ragator configuration. Mon May 13 09:47:31 EDT 2002 argus-clients-2.0.5.beta.21 Removed pcap-int.h references. Mon Apr 29 12:01:24 EDT 2002 argus-clients-2.0.5.beta.20 Fixed labeling rtcp flows correctly Fri Apr 19 20:05:23 EDT 2002 argus-clients-2.0.5.beta.19 Added new syntax for -t option Thu Apr 18 11:29:40 EDT 2002 argus-clients-2.0.5.beta.19 Additions to ranonymize to strip out user data DSR. Additions to ranonymize to deal with ip_id anonymization and tcp base sequence number anonymization. Added ranonymize.5 manpage. Mon Apr 8 21:49:54 EDT 2002 argus-clients-2.0.5.beta.18 Modify codebase for better Solaris porting support. Renamed min, mean,max in many structures to xval. Better curses support. Thu Mar 28 09:45:50 EST 2002 argus-clients-2.0.5.beta.16 Added RAGATOR_AUTOCORRECTION switch to aggregation file parsing and control. Tue Mar 26 22:47:48 EST 2002 argus-clients-2.0.5.beta.15 Fix realpath() for -W option but not for -E option. Tue Mar 19 22:48:32 EST 2002 argus-clients-2.0.5.beta.14 Consistent treatment of flow configuration modifications. Thu Mar 7 11:43:48 EST 2002 argus-clients-2.0.5.beta.12 V5 netflow parsing fixed. fixed -E option. ratop filter fix. Tue Feb 26 17:30:54 EST 2002 argus-clients-2.0.5.beta.11 Fixed compiler for multicast and broadcast to default to Layer3 rather than Layer 2. Thu Feb 21 09:36:32 EST 2002 argus-clients-2.0.5.beta.10 Fixed idle stream problem by setting input->ArgusLastTime to ArgusRealTime. Wed Feb 20 18:30:11 EST 2002 argus-clients-2.0.5.beta.9 Modified idle stream test to use ArgusRealTime, not ArgusGlobalTime. Tue Feb 12 21:09:32 EST 2002 argus-clients-2.0.5.beta.6 Fixed little bug with idle timeouts. Added page up/down home and end support for ratop. Fri Feb 8 08:08:35 EST 2002 argus-clients-2.0.5.beta.5 Fixed trans counter and merge error in ra* aggregators. Fri Feb 1 08:38:32 EST 2002 argus-clients-2.0.5.beta.3 Fixed -s sbytes and dbytes. Fri Jan 27 08:38:32 EST 2002 argus-clients-2.0.5.beta.2 Fixed filter options in ratop Major issues with Solaris port, done Thu Jan 24 19:39:07 EST 2002 argus-clients-2.0.5.beta.1 Modified ratop to send filter when redefined. Minor changes to get started on MODEL: defintion for clients. Tue Jan 22 09:32:57 EST 2002 argus-clients-2.0.4 Release time. Update man pages (ragator.5) Changed name of ./support/Config/fmodel.conf to ragator.conf. Mon Jan 21 09:15:17 EST 2002 argus-clients-2.0.4.beta.17 Major modifications for Sasl code. Eliminated fdopen() to remove issues with using stream i/o at one point and raw i/o the next. Added config support for ragator() to turn aggregation reporting on and off. Also added field preservation as a default, but you can turn this off in the fmodel.conf. Wed Jan 16 10:35:08 EST 2002 argus-clients-2.0.4.beta.17 Fixed namespace collision with Cflow contrib package. Added LBL_ALIGN to configure testing Wed Jan 9 21:07:32 EST 2002 argus-clients-2.0.4.beta.16 mod to ramon() to add -M svc mode. Wed Jan 9 11:42:45 EST 2002 argus-clients-2.0.4.beta.16 mods to ratop() to make full field printing and sorting available. minor fixes to ratop() label formating etc... Tue Jan 8 21:48:38 EST 2002 argus-clients-2.0.4.beta.15 ranonymize.conf file improved. first attempt at specific network and host address translation Mon Jan 7 13:47:47 EST 2002 argus-clients-2.0.4.beta.14 ranonymize.conf file created. Some implemenation of ranonymize.conf support. Better aggregation support for records out of order. Remove TCP state specific aggregation conditional. Improved ICMP reverse flow modeling. TCP and ICMP aggregation still needs work for direction. Sat Jan 5 16:56:56 EST 2002 argus-clients-2.0.4.beta.13 Put in TCP state machine translation for Cisco netflow parsing. Also fixed some minor issues with netflow. Fri Jan 4 17:23:06 EST 2002 argus-clients-2.0.4.beta.12 Implemented -C [addr:]port option Fri Jan 4 08:28:35 EST 2002 argus-clients-2.0.4.beta.11 Corrected RaThisFlowRev assignment. Fixed aggregation for direction corrected flows. Removed errant '&' in source address aggregation. Thu Jan 3 13:12:43 EST 2002 argus-clients-2.0.4.beta.10 Fixed Cisco timestamp conversion algorithm. Enchanced TCP flag decoding for Cisco netflow conversion. Deprecated the -P option in all clients. Modified man pages. Changed RA_CISCONETFLOW_SERVER to RA_CISCONETFLOW_PORT. Wed Dec 26 15:46:44 EST 2001 argus-clients-2.0.4.beta.8 Added ICMP Cisco netflow record support. Added 'm' modify page in ratop(). Not functioning yet. Fri Dec 21 11:34:02 EST 2001 argus-clients-2.0.4.beta.8 Fixed Cisco netflow record support. (how did it ever work?) Added -s option support to all ra* programs and modified man pages. Changed rasort to use the -M option to pass the sort fields, since the -s is used for printing. Wed Dec 19 10:45:10 EST 2001 argus-clients-2.0.4.beta.7 Ported clients to Solaris 2.8 cc. argus-clients-2.0.4.beta.5 Modified authentication strategies to handle Kerberos. Basically get real remote hostname and use that as the basis for the authentication, rather than the localhost. Tue Dec 18 10:41:27 EST 2001 argus-clients-2.0.4.beta.4 Fixed problem with RaSortAlgorithms[] index shifted by one. Mon Dec 17 15:02:06 EST 2001 argus-clients-2.0.4.beta.3 Modified ragator to handle when the addr and ports don't change after merging. Fri Dec 14 10:51:52 EST 2001 argus-clients-2.0.4.beta.2 Modified ra* routines to handle TCP Out of Order indicators, and improved ra.1 man page a bit. Mon Dec 10 10:14:02 EST 2001 argus-clients-2.0.4.beta.1 Turned on upstream encryption for management data by enabling sasl_encode() in ArgusWriteConnection(). Wed Dec 5 17:14:26 EST 2001 argus-clients-2.0.2.beta.22 Overhaul of raxml to get the XML stuff to actually work. Mods to correct ra() label alignment Mon Dec 3 19:59:16 EST 2001 argus-clients-2.0.2.beta.21 Added ranonymize.c to anonymize argus data. still needs some work. Sat Nov 17 11:29:41 EST 2001 argus-clients-2.0.2.beta.20 Modified ArgusAdjustGlobalTime to do adjustments when using the -S option. That last one was a mistake. Wed Nov 14 13:57:57 EST 2001 argus-clients-2.0.2.beta.19 Modified ArgusAdjustGlobalTime to not do adjustments when using the -S option. Tue Nov 13 11:56:09 EST 2001 argus-clients-2.0.2.beta.18 Fixes for sasl_decode() major bug when read more than one record from the remote server. Fix for ArgusGlobalTime when there is no argus record input. Mon Nov 12 18:01:44 EST 2001 argus-clients-2.0.2.beta.17 Added remote idle timeout logic. Fixed fd left open on ArgusReadConnection failures. Fri Nov 9 08:30:58 EST 2001 argus-clients-2.0.2.beta.16 *Fixed gencode.c to handle new multicast and broadcast issues where the broadcast addr could be in the source addr. *Fixed coredump dealing with poorly formed argus records on input. Wed Nov 7 17:58:54 EST 2001 (carter@qosient.com) argus-clients-2.0.2.beta.15 *Fixed ratop field printing. Thu Sep 27 08:43:47 EDT 2001 (carter@qosient.com) argus-clients-2.0.2.beta.3 * Added -s option for specifying print fields for all ra* clients. This adds some issues for rasort() as it uses the -s option to specify the sort fields, so, we'll have to figure this out, and it breaks ratop(), which uses a different method for deciding what fields to print. * Fix some minor issues with ramon processing, label printing. * Fix a tiny ragator issue with label printing. * Change distribution statement in all client programs. Still need to add to rest of distribution. Sun Sep 2 21:26:16 EDT 2001 (carter@qosient.com) argus-clients-2.0.1.alpha.15 * Changed calling strategy from main library to call RaProcessRecord, rather than the protocol specific routines. * ported rapath(). * fixed the histogram strategies in ragator and rasrvstats. Mon Aug 13 09:13:54 EDT 2001 (carter@qosient.com) argus-clients-2.0.1.alpha.14 * Lots of ratop() additions and fixes. Fri Jul 27 12:17:40 EDT 2001 (carter@qosient.com) argus-clients-2.0.1.alpha.12 * fixed MAJOR bug in get_argus_string(). * port for Cygwin Wed Jul 25 14:55:07 EDT 2001 (carter@qosient.com) argus-clients-2.0.1.alpha.11 * ./configure support for SASL libraries. Thu Jul 19 11:47:21 EDT 2001 (carter@qosient.com) argus-clients-2.0.1.alpha.10 * ratop bugs fixed. calling ratop with no arguements works now. also fixed 'o' input files loading problems. Cleared flow queue before reattaching to remote or reading new input file. Fixed solaris curses initialization problem. * ramon problem with RA_MAXQSIZE and Merge state problems. * Fixed some Solaris, NetBSD, and FreeBSD Makefile issues. Tue Jul 17 09:12:41 EDT 2001 (carter@qosient.com) argus-clients-2.0.1.alpha.9 * Fixed some Solaris, NetBSD, and FreeBSD Makefile issues. * update ./bin/config.quess and ./bin/config.sub. Wed Jul 11 11:56:22 EDT 2001 (carter@qosient.com) argus-clients-2.0.1.alpha.8 * Finished port of ra* clients. Support nonip record printing. * Modified rahistogram() to do 2 passes instead of one, so no need to copy records. Improved memory model extensively. Tue Jul 10 14:13:21 EDT 2001 (carter@qosient.com) argus-clients-2.0.1.alpha.7 * Finished port of rasort and ramon * Modifies ratop to use RaSortQueue routines from rasort * Mods for FreeBSD endian fixes from argus-2.0.2.beta.3 Wed Jun 20 15:32:49 EDT 2001 (carter@qosient.com) argus-clients-2.0.1.alpha.6 * Finished port of ratop and ragrep to Solaris. Mon Jun 18 11:41:56 EDT 2001 argus-clients-2.0.1.alpha.5 * Modified Makefile to remove HAVE_CONFIG_H in ragrep * Modified ragrep.c to remove getopt.h references. * Fixed segfault condition in ragator(). * Implemented fix memory model for ragator(). * Implemented LRU queue management for ragator(). Sat Jun 9 13:18:17 EDT 2001 (carter@qosient.com) argus-clients-2.0.1.alpha.4 * Fixed problem with keywork 'loop' in filter expression * Made changes for OpenBSD port. * Fix client memory management problem when dealing with archive. * Made additions to ragraph() in preparation for transaction duration graphing. Thu Jun 7 15:27:04 EDT 2001 (carter@qosient.com) argus-clients-2.0.1.alpha.3 * Added ragrep() to distribution * Moved ragraph.pl and rahistogram.[ch] to ./ragraph directory * Modifications to ratop() added support to dis- and re-connect servers on the fly using the 'd' and 'c' keys. Changed 'D' and 'U' keys to be '+' and '-'. Mon Jun 4 15:39:55 EDT 2001 (carter@qosient.com) argus-clients-2.0.1.alpha.2 * Fixed configure.in so that it actually works. * Updated all Makefiles, etc to handle new configure.in * Added ./config and ./lib directory to make this stuff work. * Converted to GPL license for clients distribution Sat Mar 24 00:36:28 EST 2001 (carter@qosient.com) argus-clients-2.0.1.alpha.1 * argus-clients started using argus-2.0.1 as base argus-clients-2.0.6.fixes.1/INSTALL0000664000076600007660000001501507640476614012323 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ QUICK MAKE If all things are ready, distribution untarred, and you have flex and bison installed on your system, you should be able to make argus by simply typing: % ./configure % make If you have any problems with this procedure, read further, if not congratulations. You can proceed to INSTALLATION. DEPENDENCIES The Argus client package is dependant on two public domain packages; flex and bison(). Both of these packages must be installed in order to compile argus. The official site for flex is: http://www.gnu.org/software/flex The official site for bison is: http://www.gnu.org/software/bison Because Argus is dependant on flex and bison, you will need to have installed it prior to building the Argus client software. Please refer to the individual packages for installation instructions. Some argi require cryptographic authentication in order to access it report access port. Argus clients can be compiled to support this strong authentication strategy by compiling with ARGUS_SASL support and linking to the cryptographic package SASL, the Simple Authentication and Security Layer, which provides strong authentication and wireline confidentiality for argus data. Because of its features and flexibility, we highly recommend using SASL, and becoming experienced with its administration. cyrus-sasl-1.5.24 Carnegie Mellon Univeristy http://asg.web.cmu.edu/sasl ftp://ftp.andrew.cmu.edu/pub/cyrus-mail CONFIGURE The program, ./configure, will scan the file system, looking for the flex and bison and make some assumptions about the platform which will allow ./configure to choose between gcc, acc, and cc. There really isn't anything else to it. BUILDING ARGUS So, after all that, to build Argus on a supported platform, first run ./configure. ./configure will determine your system attributes and generate subdirectories and the appropriate Makefiles from the Makefile.in files found in the distribution. After running ./configure, run "make". If everything goes well, appropriate libraries and binaries will be found in the ./bin and ./lib subdirectories. So, .... % ./configure % make The argus clients will be found as ./bin/ra*. So, at this point you should have all the execuables needed. But, if you are having problems, it may be related to your compiler or the flex and bison utilities. So, ... You will need an ANSI C compiler to build argus. If your compiler is not ANSI compliant, we highly recommend using the GNU C compiler, available via anonymous ftp: ftp://prep.ai.mit.edu/pub/gnu/gcc-*.tar.gz Argus requires bison and flex. For flex, version 2.4.6 or higher is recommended. The current version of flex and bison are available via anonymous ftp: ftp://prep.ai.mit.edu/pub/gnu/bison-*.tar.gz ftp://prep.ai.mit.edu/pub/non-gnu/flex/flex-*.tar.gz Now, if you are still having problems, ..., well its hard to say from here what it might be. So, you may want to send us some mail. INSTALLATION QUICK INSTALL If all things are well at this point, and you will be using the installation strategy that we use, all you need do now is: # make install This will install the argus-client executables into /usr/local/bin, by default, man pages into /usr/local/man and documenation into /usr/share/doc. If you are unsure about the standard installtion, run % make -n install to review what make will try to do. If you would like to do something other than the standard install, then please continue to read through this file. Argus-clients do not have any installation retrictions, so you can install them anywhere. There are some conventions that have been established, and I'll present them here, but you can, of course, do your own thing. I have found it useful to have an argus home directory to hold the binaries, client configuration files, and hold my argus data archive. If you would like to use this strategy, create your directory, and create the environment variable ARGUSHOME and set it to this directory. I use /usr/argus. I prefer putting the ra* client binaries in /usr/argus/bin. When associated with an argus distribution, the argus is my scheme is in /usr/argus/sbin. After making, as root, I just: # mkdir /usr/argus /usr/argus/bin # cp bin/ra* /usr/argus/bin # cp bin/argusbug /usr/argus/bin Argus-clients have a rc style configuration strategy, to set things like the output date format, what columns to print out etc .. You can have a system wide configuration file that would reside as /etc/ra.conf. Clients will look here by default for its base configuration, and then look for a .rarc file in your home directory. So you don't have to have a system wide configuration file, unless you prefer it. # cp ./support/Config/ra.conf /etc/ra.conf You will want to edit this file to choose values of your liking. The sample has all the common values set and is a good suggestion. Please refer to the sample to make your personal changes. Copying the man and doc directories is nice. # tar cf - doc man | (cd /usr/argus; tar xvpf -) This should handle the basic installion. Any comments, patches, bug reports or additions should be sent to argus@lists.andrew.cmu.edu. PORTABILITY Argus-clients have been developed on Sparc architectures under SunOS 4.1.x and Solaris 2.7, and have been successfully ported to Solaris, SGI, Ultrix, Linux, OpenBSD and FreeBSD platforms, as well as Cygwin. No claim is made as to the portability of argus-clients to other platforms, although it is much easier now that we've addressed the big endian little endian issues. If you make any modifications to support installing and running argus-clients in any other environment, please send us comments and/or patches. We will be most grateful. argus-clients-2.0.6.fixes.1/MANIFEST0000664000076600007660000003756510047734027012427 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ Argus Clients distribution. .: total 328 -rw-rw-r-- 1 argus argus 17992 Jun 4 2001 COPYING -rw-rw-r-- 1 argus argus 764 Mar 24 2003 CREDITS -rw-rw-r-- 1 argus argus 16346 May 10 13:12 ChangeLog -rw-rw-r-- 1 argus argus 6669 Mar 26 2003 INSTALL -rw-rw-r-- 1 argus argus 16245 May 6 09:39 MANIFEST -rw-rw-r-- 1 argus argus 6096 Jul 10 2003 Makefile.in -rw-rw-r-- 1 argus argus 3658 Mar 26 2003 README -rw-rw-r-- 1 argus argus 6 Dec 5 11:46 VERSION -rw-rw-r-- 1 argus argus 14644 May 6 09:39 aclocal.m4 -rwxrwxr-x 1 argus argus 173518 May 6 09:39 configure -rw-rw-r-- 1 argus argus 2240 Oct 24 2002 configure.in drwxrwxr-x 3 argus argus 4096 May 10 13:12 bin drwxrwxr-x 3 argus argus 4096 May 10 13:12 clients drwxrwxr-x 3 argus argus 4096 May 10 13:12 common drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 config drwxrwxr-x 5 argus argus 4096 Dec 5 21:49 contrib drwxrwxr-x 4 argus argus 4096 Dec 5 21:49 doc drwxrwxr-x 5 argus argus 4096 May 10 11:40 include drwxrwxr-x 3 argus argus 4096 May 10 13:12 lib drwxrwxr-x 6 argus argus 4096 Dec 5 21:49 man drwxrwxr-x 3 argus argus 4096 May 10 13:12 ragraph drwxrwxr-x 4 argus argus 4096 May 10 13:12 ragrep drwxrwxr-x 3 argus argus 4096 May 10 13:12 ratop drwxrwxr-x 8 argus argus 4096 Dec 5 21:49 support ./bin: total 16 -rwxrwxr-x 1 argus argus 9323 Jun 3 2001 argusbug -rwxrwxr-x 1 argus argus 2350 Jun 3 2001 mkdep ./clients: total 440 -rw-rw-r-- 1 argus argus 6801 Jul 10 2003 Makefile.in -rw-rw-r-- 1 argus argus 13233 May 4 11:56 ra.c -rw-rw-r-- 1 argus argus 11115 Mar 27 2003 racount.c -rw-rw-r-- 1 argus argus 29014 Mar 27 2003 ragator.c -rw-rw-r-- 1 argus argus 1165 Mar 26 2003 ragator.h -rw-rw-r-- 1 argus argus 14462 Mar 27 2003 rahosts.c -rw-rw-r-- 1 argus argus 1355 Mar 26 2003 rahosts.h -rw-rw-r-- 1 argus argus 40175 Sep 2 2003 ramon.c -rw-rw-r-- 1 argus argus 1161 Mar 26 2003 ramon.h -rw-rw-r-- 1 argus argus 66751 Sep 2 2003 ranonymize.c -rw-rw-r-- 1 argus argus 1680 Mar 26 2003 ranonymize.h -rw-rw-r-- 1 argus argus 26981 Mar 27 2003 rapath.c -rw-rw-r-- 1 argus argus 1362 Mar 26 2003 rapath.h -rw-rw-r-- 1 argus argus 27721 Mar 27 2003 rapolicy.c -rw-rw-r-- 1 argus argus 2483 Mar 26 2003 rapolicy.h -rw-rw-r-- 1 argus argus 22473 Mar 27 2003 rarpwatch.c -rw-rw-r-- 1 argus argus 1170 Mar 27 2003 rarpwatch.h -rw-rw-r-- 1 argus argus 6977 Mar 27 2003 raseq.c -rw-rw-r-- 1 argus argus 1234 Mar 26 2003 raseq.h -rw-rw-r-- 1 argus argus 8077 Mar 27 2003 rasort.c -rw-rw-r-- 1 argus argus 1319 Mar 27 2003 rasort.h -rw-rw-r-- 1 argus argus 41458 Mar 27 2003 rasrvstats.c -rw-rw-r-- 1 argus argus 1745 Mar 27 2003 rasrvstats.h -rw-rw-r-- 1 argus argus 15501 Mar 27 2003 rastrip.c -rw-rw-r-- 1 argus argus 1375 Mar 26 2003 rastrip.h -rw-rw-r-- 1 argus argus 8090 Mar 27 2003 ratemplate.c -rw-rw-r-- 1 argus argus 35058 May 10 11:46 raxml.c ./common: total 636 -rwxrwxr-x 1 argus argus 4517 Jul 10 2003 Makefile.in -rw-rw-r-- 1 argus argus 16122 Dec 6 12:47 argus_auth.c -rw-rw-r-- 1 argus argus 137439 May 10 09:41 argus_client.c -rw-rw-r-- 1 argus argus 134325 Mar 26 2003 argus_filter.c -rw-rw-r-- 1 argus argus 143199 Dec 6 12:42 argus_parse.c -rw-rw-r-- 1 argus argus 110901 Dec 6 12:43 argus_util.c -rw-rw-r-- 1 argus argus 49995 Apr 26 12:30 gencode.c -rw-rw-r-- 1 argus argus 9511 Dec 6 12:46 grammar.y -rwxrwxr-x 1 argus argus 5918 Dec 6 12:47 scanner.l ./config: total 88 -rwxrwxr-x 1 argus argus 40969 Aug 20 2003 config.guess -rwxrwxr-x 1 argus argus 29636 Aug 20 2003 config.sub -rwxrwxr-x 1 argus argus 5585 Jun 4 2001 install-sh -rwxrwxr-x 1 argus argus 616 Jun 4 2001 mkinstalldirs ./contrib: total 8 drwxrwxr-x 6 argus argus 4096 Dec 5 21:49 Argus-perl-2.00 drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 hostpairs.dist ./contrib/Argus-perl-2.00: total 116 -rw-rw-r-- 1 argus argus 3594 Oct 9 2002 Argus.pm -rw-rw-r-- 1 argus argus 387 Oct 9 2002 HISTORY -rw-rw-r-- 1 argus argus 1075 Oct 9 2002 INSTALL -rw-rw-r-- 1 argus argus 245 Oct 9 2002 MANIFEST -rw-rw-r-- 1 argus argus 1104 Oct 9 2002 Makefile.PL -rw-rw-r-- 1 argus argus 4268 Oct 9 2002 README -rw-rw-r-- 1 argus argus 197 Oct 9 2002 TODO -rwxrwxr-x 1 argus argus 454 Oct 9 2002 fix-script.PL -rw-rw-r-- 1 argus argus 1575 Oct 9 2002 look_for -rwxrwxr-x 1 argus argus 1546 Oct 9 2002 look_for.pp -rw-rw-r-- 1 argus argus 96 Oct 9 2002 ra.conf -rw-rw-r-- 1 argus argus 8867 Oct 9 2002 slowscan -rw-rw-r-- 1 argus argus 8840 Oct 9 2002 slowscan.pp -rw-rw-r-- 1 argus argus 14335 Oct 9 2002 watcher -rwxrwxr-x 1 argus argus 14306 Oct 9 2002 watcher.pp drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 Argus drwxrwxr-x 7 argus argus 4096 Dec 5 21:49 blib drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 t ./contrib/Argus-perl-2.00/Argus: total 28 -rw-rw-r-- 1 argus argus 4863 Oct 9 2002 Archive.pm -rw-rw-r-- 1 argus argus 1990 Oct 9 2002 SlowScan.pm -rw-rw-r-- 1 argus argus 8672 Oct 9 2002 Support.pm -rw-rw-r-- 1 argus argus 1497 Oct 9 2002 Watcher.pm ./contrib/Argus-perl-2.00/blib: total 16 drwxrwxr-x 4 argus argus 4096 Dec 5 21:49 arch drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 lib drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 man1 drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 script ./contrib/Argus-perl-2.00/blib/arch: total 4 drwxrwxr-x 4 argus argus 4096 Dec 5 21:49 auto ./contrib/Argus-perl-2.00/blib/arch/auto: total 4 drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 Argus ./contrib/Argus-perl-2.00/blib/arch/auto/Argus: total 0 ./contrib/Argus-perl-2.00/blib/lib: total 0 ./contrib/Argus-perl-2.00/blib/man1: total 0 ./contrib/Argus-perl-2.00/blib/script: total 0 ./contrib/Argus-perl-2.00/t: total 12 -rwxrwxr-x 1 argus argus 394 Oct 9 2002 archive_get_archive_dir.t -rwxrwxr-x 1 argus argus 479 Oct 9 2002 archive_get_files.t -rwxrwxr-x 1 argus argus 55 Oct 9 2002 runtests ./contrib/hostpairs.dist: total 0 ./doc: total 52 -rw-rw-r-- 1 argus argus 1822 Jun 3 2001 CHANGES -rw-rw-r-- 1 argus argus 24434 Jun 3 2001 FAQ -rw-rw-r-- 1 argus argus 13448 Jun 3 2001 HOW-TO -rw-rw-r-- 1 argus argus 1455 Jun 3 2001 README drwxrwxr-x 4 argus argus 4096 Dec 5 21:49 html ./doc/html: total 4 drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 man ./doc/html/man: total 184 -rw-rw-r-- 1 argus argus 5414 Jun 3 2001 argus.5.html -rw-rw-r-- 1 argus argus 9828 Jun 3 2001 argus.8.html -rw-rw-r-- 1 argus argus 10321 Jun 3 2001 argus.conf.5.html -rw-rw-r-- 1 argus argus 18312 Jun 3 2001 hosts_access.5.html -rw-rw-r-- 1 argus argus 8874 Jun 3 2001 hosts_options.5.html -rw-rw-r-- 1 argus argus 28840 Jun 3 2001 ra.1.html -rw-rw-r-- 1 argus argus 3633 Jun 3 2001 racount.1.html -rw-rw-r-- 1 argus argus 2961 Jun 3 2001 ragator.1.html -rw-rw-r-- 1 argus argus 2430 Jun 3 2001 ramon.1.html -rw-rw-r-- 1 argus argus 11137 Jun 3 2001 rarc.5.html -rw-rw-r-- 1 argus argus 4348 Jun 3 2001 rasort.1.html -rw-rw-r-- 1 argus argus 2409 Jun 3 2001 raxml.1.html -rw-rw-r-- 1 argus argus 9170 Jun 3 2001 tcpd.8.html -rw-rw-r-- 1 argus argus 38278 Jun 3 2001 tcpdump.1.html ./include: total 284 -rw-rw-r-- 1 argus argus 17956 Oct 9 2002 CflowdFlowPdu.h -rw-rw-r-- 1 argus argus 4036 Mar 26 2003 argus-namedb.h -rw-rw-r-- 1 argus argus 42631 May 10 11:40 argus_client.h -rw-rw-r-- 1 argus argus 11614 Mar 26 2003 argus_def.h -rw-rw-r-- 1 argus argus 8082 Mar 26 2003 argus_filter.h -rw-rw-r-- 1 argus argus 9203 Mar 26 2003 argus_out.h -rw-rw-r-- 1 argus argus 55118 Aug 25 2003 argus_parse.h -rw-rw-r-- 1 argus argus 12592 Aug 25 2003 argus_util.h -rw-rw-r-- 1 argus argus 3724 Oct 9 2002 bootp.h -rw-rw-r-- 1 argus argus 4532 Jan 13 17:40 compat.h -rw-rw-r-- 1 argus argus 4533 Mar 26 2003 cons_def.h -rw-rw-r-- 1 argus argus 5140 Mar 26 2003 cons_out.h -rw-rw-r-- 1 argus argus 10367 Mar 26 2003 ethernames.h -rw-rw-r-- 1 argus argus 3474 Oct 9 2002 ethertype.h -rw-rw-r-- 1 argus argus 2885 Mar 26 2003 extract.h -rw-rw-r-- 1 argus argus 7135 Dec 6 12:51 gencode.h -rw-rw-r-- 1 argus argus 5256 Mar 26 2003 interface.h -rw-rw-r-- 1 argus argus 4029 Jun 3 2001 llc.h -rw-rw-r-- 1 argus argus 4434 Mar 26 2003 os.h -rw-rw-r-- 1 argus argus 3391 Jun 3 2001 pcap-int.h -rw-rw-r-- 1 argus argus 4913 Oct 9 2002 pcap.h -rw-rw-r-- 1 argus argus 2414 Oct 9 2002 ppp.h -rw-rw-r-- 1 argus argus 4700 Jul 25 2001 saslint.h drwxrwxr-x 3 argus argus 4096 Dec 6 12:40 net drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 netinet ./include/net: total 16 -rw-rw-r-- 1 argus argus 14689 Dec 6 12:51 bpf.h ./include/netinet: total 4 -rw-rw-r-- 1 argus argus 1521 Jun 6 2001 rtp.h ./lib: total 0 ./man: total 12 drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 man1 drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 man5 drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 man8 ./man/man1: total 108 -rw-rw-r-- 1 argus argus 27541 Aug 17 2003 ra.1 -rw-rw-r-- 1 argus argus 2836 Aug 17 2003 racount.1 -rw-rw-r-- 1 argus argus 1845 Aug 17 2003 ragator.1 -rw-rw-r-- 1 argus argus 3614 Mar 27 2003 ragraph.1 -rw-rw-r-- 1 argus argus 2618 Aug 17 2003 rahosts.1 -rw-rw-r-- 1 argus argus 2990 Sep 2 2003 ramon.1 -rw-rw-r-- 1 argus argus 1753 Aug 17 2003 ranonymize.1 -rwxrwxr-x 1 argus argus 4061 Aug 17 2003 rapolicy.1 -rw-rw-r-- 1 argus argus 3039 Aug 17 2003 rasort.1 -rw-rw-r-- 1 argus argus 4553 Aug 17 2003 rastrip.1 -rw-rw-r-- 1 argus argus 1672 Aug 17 2003 raxml.1 -rw-rw-r-- 1 argus argus 35474 Aug 17 2003 tcpdump.1 ./man/man5: total 28 -rw-rw-r-- 1 argus argus 12054 Oct 9 2002 ragator.5 -rw-rw-r-- 1 argus argus 7442 Oct 9 2002 ranonymize.5 -rw-rw-r-- 1 argus argus 7952 Oct 9 2002 rarc.5 ./man/man8: total 0 ./ragraph: total 136 -rw-rw-r-- 1 argus argus 3761 Jul 10 2003 Makefile.in -rwxrwxr-x 1 argus argus 23811 Dec 5 11:47 ragraph.pl -rw-rw-r-- 1 argus argus 101258 Mar 27 2003 rahistogram.c -rw-rw-r-- 1 argus argus 1092 Mar 27 2003 rahistogram.h ./ragrep: total 472 -rw-rw-r-- 1 argus argus 17992 Jun 8 2001 COPYING -rw-rw-r-- 1 argus argus 354 Jun 8 2001 INSTALL -rw-rw-r-- 1 argus argus 14524 Jul 10 2003 Makefile.in -rw-rw-r-- 1 argus argus 1638 Jun 8 2001 README -rw-rw-r-- 1 argus argus 68651 Jul 11 2001 dfa.c -rw-rw-r-- 1 argus argus 14892 Jun 8 2001 dfa.h -rw-rw-r-- 1 argus argus 120 Jun 8 2001 egrepmat.c -rw-rw-r-- 1 argus argus 759 Jun 8 2001 getpagesize.h -rw-rw-r-- 1 argus argus 108 Jun 8 2001 grepmat.c -rw-rw-r-- 1 argus argus 21052 Oct 9 2002 kwset.c -rw-rw-r-- 1 argus argus 2440 Jun 8 2001 kwset.h -rw-rw-r-- 1 argus argus 18108 Jan 7 2003 obstack.c -rw-rw-r-- 1 argus argus 22927 Jun 19 2001 obstack.h -rw-rw-r-- 1 argus argus 28489 Mar 27 2003 ragrep.c -rw-rw-r-- 1 argus argus 1720 Jun 8 2001 ragrep.h -rw-rw-r-- 1 argus argus 188709 Sep 2 2003 regex.c -rw-rw-r-- 1 argus argus 1730 Sep 2 2003 regex.h -rw-rw-r-- 1 argus argus 270 Jun 8 2001 savedir.h -rw-rw-r-- 1 argus argus 10846 Jun 9 2001 search.c -rw-rw-r-- 1 argus argus 5129 Oct 9 2002 system.h drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 posix ./ragrep/posix: total 24 -rw-rw-r-- 1 argus argus 20679 Sep 2 2003 regex.h ./ratop: total 100 -rw-rw-r-- 1 argus argus 3669 Jul 10 2003 Makefile.in -rw-rw-r-- 1 argus argus 87890 Sep 2 2003 ratop.c -rw-rw-r-- 1 argus argus 1870 Mar 27 2003 ratop.h ./support: total 24 -rw-rw-r-- 1 argus argus 2569 Mar 26 2003 README drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 Archive drwxrwxr-x 3 argus argus 4096 May 10 09:39 Config drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 System drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 Tools drwxrwxr-x 3 argus argus 4096 Dec 5 21:49 Xml ./support/Archive: total 4 -rw-rw-r-- 1 argus argus 3325 Mar 26 2003 argusarchive ./support/Config: total 20 -rw-rw-r-- 1 argus argus 1294 Mar 26 2003 excel.rc -rw-rw-r-- 1 argus argus 1745 Oct 9 2002 policy.conf -rw-rw-r-- 1 argus argus 3774 Mar 26 2003 ragator.conf -rw-rw-r-- 1 argus argus 6984 Mar 26 2003 rarc ./support/System: total 8 -rw-rw-r-- 1 argus argus 1152 Mar 26 2003 crontab -rw-rw-r-- 1 argus argus 1406 Mar 26 2003 magic ./support/Tools: total 292 -rw-rw-r-- 1 argus argus 279948 Mar 26 2003 ArgusPortNum.dat -rw-rw-r-- 1 argus argus 4033 Mar 26 2003 Makefile -rw-rw-r-- 1 argus argus 5137 Mar 26 2003 parsePortNum.c ./support/Xml: total 352 -rw-rw-r-- 1 argus argus 17601 Oct 9 2002 ArgusRecord.biz -rw-rw-r-- 1 argus argus 12331 Oct 9 2002 ArgusRecord.dtd -rw-rw-r-- 1 argus argus 10418 Sep 17 2001 ArgusRecord.sox -rw-rw-r-- 1 argus argus 17491 Oct 9 2002 ArgusRecord.xdr -rw-rw-r-- 1 argus argus 19316 Oct 9 2002 ArgusRecord.xsd -rw-rw-r-- 1 argus argus 259123 Oct 9 2002 ArgusRecordSample.xml -rw-rw-r-- 1 argus argus 1458 Mar 26 2003 README argus-clients-2.0.6.fixes.1/Makefile.in0000664000076600007660000001372007703321075013326 # Makefile for GNU hello. -*- Indented-Text -*- # Copyright (C) 1992, 1993 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #### Start of system configuration section. #### CC = @CC@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ DEFS = @DEFS@ LIBS = @LIBS@ CFLAGS = -g LDFLAGS = -g prefix = $(DESTDIR)@prefix@ exec_prefix = @exec_prefix@ srcdir = @srcdir@ docdir = $(prefix)/share/doc/argus-2.0 #### End of system configuration section. #### SHELL = /bin/sh DIRS = ./common ./clients ./ragraph ./ragrep ./ratop DISTFILES = COPYING CREDITS ChangeLog INSTALL MANIFEST Makefile.in \ README VERSION bin clients common ragrep ragraph ratop \ contrib doc include lib man support aclocal.m4 \ config configure configure.in .c.o: $(CC) -c $(CPPFLAGS) $(DEFS) $(CFLAGS) $< .PHONY: install installdirs all: force @for i in $(DIRS) ; do \ if [ -d $$i ] ; then \ echo "making in $$i"; \ cd $$i; \ make; \ cd ..; \ fi; \ done .PHONY: all install: force make installdirs [ -d $(prefix) ] || \ (mkdir -p $(prefix); chmod 755 $(prefix)) [ -d @sbindir@ ] || \ (mkdir -p @sbindir@; chmod 755 @sbindir@) [ -d @bindir@ ] || \ (mkdir -p @bindir@; chmod 755 @bindir@) [ -d $(exec_prefix)/argus ] || \ (mkdir -p $(exec_prefix)/argus; chmod 755 $(exec_prefix)/argus) [ -d $(exec_prefix)/argus/archive ] || \ (mkdir -p $(exec_prefix)/argus/archive; chmod 755 $(exec_prefix)/argus/archive) [ -d $(docdir) ] || \ (mkdir -p $(docdir); chmod 755 $(docdir)) [ -d $(docdir)/html ] || \ (mkdir -p $(docdir)/html; chmod 755 $(docdir)/html) [ -d $(docdir)/html/man ] || \ (mkdir -p $(docdir)/html/man; chmod 755 $(docdir)/html/man) @for i in $(DIRS) ; do \ if [ -d $$i ] ; then \ echo "making in $$i"; \ cd $$i; \ make install; \ cd ..; \ fi; \ done $(INSTALL) -m 0644 $(srcdir)/doc/FAQ $(docdir) $(INSTALL) -m 0644 $(srcdir)/doc/HOW-TO $(docdir) $(INSTALL) -m 0644 $(srcdir)/doc/html/man/*.html $(docdir)/html/man $(INSTALL) -m 0644 $(srcdir)/README $(prefix)/argus $(INSTALL) -m 0644 $(srcdir)/README $(docdir) $(INSTALL) -m 0644 $(srcdir)/COPYING $(prefix)/argus $(INSTALL) -m 0644 $(srcdir)/COPYING $(docdir) $(INSTALL) -m 0755 $(srcdir)/bin/argusbug @bindir@/argusbug [ -d @mandir@ ] || \ (mkdir -p @mandir@; chmod 755 @mandir@) [ -d @mandir@/man1 ] || \ (mkdir -p @mandir@/man1; chmod 755 @mandir@/man1) $(INSTALL) -m 0644 $(srcdir)/man/man1/ra.1 \ @mandir@/man1/ra.1 $(INSTALL) -m 0644 $(srcdir)/man/man1/racount.1 \ @mandir@/man1/racount.1 $(INSTALL) -m 0644 $(srcdir)/man/man1/ragator.1 \ @mandir@/man1/ragator.1 $(INSTALL) -m 0644 $(srcdir)/man/man1/rahosts.1 \ @mandir@/man1/rahosts.1 $(INSTALL) -m 0644 $(srcdir)/man/man1/ramon.1 \ @mandir@/man1/ramon.1 $(INSTALL) -m 0644 $(srcdir)/man/man1/ranonymize.1 \ @mandir@/man1/ranonymize.1 $(INSTALL) -m 0644 $(srcdir)/man/man1/rapolicy.1 \ @mandir@/man1/rapolicy.1 $(INSTALL) -m 0644 $(srcdir)/man/man1/rasort.1 \ @mandir@/man1/rasort.1 $(INSTALL) -m 0644 $(srcdir)/man/man1/rastrip.1 \ @mandir@/man1/rastrip.1 $(INSTALL) -m 0644 $(srcdir)/man/man1/raxml.1 \ @mandir@/man1/raxml.1 [ -d @mandir@/man5 ] || \ (mkdir -p @mandir@/man5; chmod 755 @mandir@/man5) $(INSTALL) -m 0644 $(srcdir)/man/man5/rarc.5 \ @mandir@/man5/rarc.5 uninstall: rm -f @bindir@/argusbug rm -f @bindir@/ra rm -f @bindir@/racount rm -f @bindir@/ragator rm -f @bindir@/rahistogram rm -f @bindir@/rahosts rm -f @bindir@/rarpwatch rm -f @bindir@/raseq rm -f @bindir@/rasrvstats rm -f @bindir@/ratop rm -f @bindir@/raxml rm -f @mandir@/man1/ra.1 rm -f @mandir@/man1/racount.1 rm -f @mandir@/man1/ragator.1 rm -f @mandir@/man1/rasort.1 rm -f @mandir@/man1/raxml.1 rm -f @mandir@/man1/tcpdump.1 rm -f @mandir@/man5/argus.5 rm -f @mandir@/man5/argus.conf.5 rm -f @mandir@/man5/rarc.5 rm -rf $(docdir) rm -f $(exec_prefix)/argus/COPYING rm -f $(exec_prefix)/argus/README installdirs: ${srcdir}/config/mkinstalldirs $(bindir) $(infodir) Makefile: Makefile.in config.status $(SHELL) config.status config.status: configure $(srcdir)/configure --no-create TAGS: $(SRCS) etags $(SRCS) .PHONY: clean mostlyclean distclean realclean dist clean: force rm -f config.log @for i in $(DIRS) ; do \ if [ -d $$i ] ; then \ cd $$i; \ make clean; \ cd ..; \ fi; \ done mostlyclean: clean distclean: clean rm -f config.* rm -f TAGS rm -f lib/*.a rm -f include/config.h rm -f include/tm.h rm -f bin/ra* @for i in $(DIRS) ; do \ if [ -d $$i ] ; then \ cd $$i; \ make clean; \ rm -f Makefile; \ cd ..; \ fi; \ done clobber realclean: force rm -f TAGS rm -f lib/*.a rm -f include/config.h rm -f include/tm.h rm -f bin/ra* rm -rf log @for i in $(DIRS) ; do \ if [ -d $$i ] ; then \ cd $$i; \ make clean; \ rm -f Makefile; \ cd ..; \ fi; \ done rm -f ./Makefile config.* dist: $(DISTFILES) distclean echo argus-clients-`cat VERSION` > .fname rm -rf `cat .fname` mkdir `cat .fname` tar cf - $(DISTFILES) | (cd `cat .fname`; tar xpf -) ls -lR `cat .fname` | fgrep CVS: | sed 's/:$///' > exfile tar -X exfile -chozf `cat .fname`.tar.gz `cat .fname` rm -rf `cat .fname` .fname exfile force: /tmp depend: $(GENSRC) force @for i in $(DIRS) ; do \ if [ -d $$i ] ; then \ cd $$i; \ make depend; \ cd ..; \ fi; \ done # Prevent GNU make v3 from overflowing arg limit on SysV. .NOEXPORT: argus-clients-2.0.6.fixes.1/README0000664000076600007660000000711207640476614012151 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (C) 2000-2003 QoSient, LLC. * * 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 */ Argus Clients 2.0 QoSient, LLC argus-info@lists.andrew.cmu.edu http:/qosient.com/argus/src ftp:/qosient.com/pub/argus This directory contains source code for programs that read, parse and process Argus data, and comprise the client part of the Audit Record Generation and Utilization System. Argus is an IP network transaction auditing tool, that generates a persistent audit of all network transactions and their performance. The data that Argus generates can be used for a wide range of tasks including Network Operations, Security, Assurance and Performance Management. To install the software and get started, see the ./INSTALL file. For answers to many questions, please see the ./docs/FAQ file. Argus 2.0 clients are capable of process argus-1.7, 1.8 and 2.0 data, as well as Cisco Netflow data. Some key modifications from the base argus-2.0 clients include: 1. Additional programs Ranonymize - anonymize argus data. Rastrip - remove unwanted argus data sections. Ratop - curses based 'top' program for argus data. Rahosts - example program for printing out addresses. Rahosts - example program for printing out addresses. Raseq - program for printing out missing sequence numbers. Rasrvstats - program for printing out service oriented stats. 2. More control over output fields and their formats. specify fields to print using -s option. Problems, bugs, questions, desirable enhancements, source code contributions, etc., should be sent to the Argus mailing list email address, "argus@lists.andrew.cmu.edu". ************************************************************ IMPORTANT: Send bug (error) reports, questions and comments to the mailing list at argus@lists.andrew.cmu.edu. Please use the './bin/argusbug' script when posting bug reports about Argus. Argusbug will gather some information about your system and start your editor with a form in which you can describe your problem. Delete information that you consider non-relevant to your problem. Bug reports not generated by Argusbug might be silently ignored by the Argus maintainers, so please use the tool. A report that says 'Argus does not work. Why?' will not be considered a valid bug report. ************************************************************ Comprehensive network transaction auditing is an extremely powerful network management tool, and a large number of sites can benefit from the prototype work that has been done through the Argus Project. Argus 2.0 is an open source project, and you are invited to become a part of the Argus project. Please become a member by joining the argus mailing list today. Again, thank you for your interest in Argus. I hope that you find the software useful. Carter Bullard carter@qosient.com argus-clients-2.0.6.fixes.1/VERSION0000664000076600007660000000001610047734036012323 2.0.6.fixes.1 argus-clients-2.0.6.fixes.1/bin/0000775000076600007660000000000010047734004012101 5argus-clients-2.0.6.fixes.1/bin/argusbug0000775000076600007660000002215307306460332013575 #!/bin/sh # Create a bug report and mail it to the argus mailing list # A completely plagaristic move on my part by using the # mysql bug reporting script. Thanks guys!!!! echo "Finding system information for a Argus bug report" VERSION="2.0" BUGARGUS="argus@lists.andrew.cmu.edu" LIBC_INFO="" for pat in /lib/libc.* /lib/libc-* /usr/lib/libc.* /usr/lib/libc-* do TMP=`ls -l $pat 2>/dev/null` if test $? = 0 then LIBC_INFO="$LIBC_INFO $TMP" fi done PATH=../:$PATH:/bin:/usr/bin:/usr/local/bin export PATH BUGADDR=${1-$BUGARGUS} ENVIRONMENT=`uname -a` : ${USER=${LOGNAME-`whoami`}} COMMAND=`echo $0|sed 's%.*/\([^/]*\)%\1%'` # Try to create a secure tmpfile umask 077 TEMPDIR=/tmp/argusbug-$$ mkdir $TEMPDIR || (echo "can not create directory in /tmp, aborting"; exit 1;) TEMP=${TEMPDIR}/argusbug trap 'rm -f $TEMP $TEMP.x; rmdir $TEMPDIR; exit 1' 1 2 3 13 15 trap 'rm -f $TEMP $TEMP.x; rmdir $TEMPDIR' 0 # How to read the passwd database. PASSWD="cat /etc/passwd" if test -f /usr/lib/sendmail then MAIL_AGENT="/usr/lib/sendmail -oi -t" elif test -f /usr/sbin/sendmail then MAIL_AGENT="/usr/sbin/sendmail -oi -t" else MAIL_AGENT="rmail $BUGARGUS" fi # Figure out how to echo a string without a trailing newline N=`echo 'hi there\c'` case "$N" in *c) ECHON1='echo -n' ECHON2= ;; *) ECHON1=echo ECHON2='\c' ;; esac # Find out the name of the originator of this PR. if test -n "$NAME" then ORIGINATOR="$NAME" elif test -f $HOME/.fullname then ORIGINATOR="`sed -e '1q' $HOME/.fullname`" else # Must use temp file due to incompatibilities in quoting behavior # and to protect shell metacharacters in the expansion of $LOGNAME $PASSWD | grep "^$LOGNAME:" | awk -F: '{print $5}' | sed -e 's/,.*//' > $TEMP ORIGINATOR="`cat $TEMP`" rm -f $TEMP fi if test -n "$ORGANIZATION" then if test -f "$ORGANIZATION" then ORGANIZATION="`cat $ORGANIZATION`" fi else if test -f $HOME/.organization then ORGANIZATION="`cat $HOME/.organization`" elif test -f $HOME/.signature then ORGANIZATION=`sed -e "s/^/ /" $HOME/.signature; echo ">"` fi fi PATH_DIRS=`echo $PATH | sed -e 's/^:/. /' -e 's/:$/ ./' -e 's/::/ . /g' -e 's/:/ /g' ` which_1 () { for cmd do # Absolute path ?. if expr "x$cmd" : "x/" > /dev/null then echo "$cmd" exit 0 else for d in $PATH_DIRS do file="$d/$cmd" if test -x "$file" -a ! -d "$file" then echo "$file" exit 0 fi done fi done exit 1 } change_editor () { echo "You can change editor by setting the environment variable VISUAL." echo "If your shell is a bourne shell (sh) do" echo "VISUAL=your_editors_name; export VISUAL" echo "If your shell is a C shell (csh) do" echo "setenv VISUAL your_editors_name" } # If they don't have a preferred editor set, then use emacs if test -z "$VISUAL" then if test -z "$EDITOR" then EDIT=emacs else EDIT="$EDITOR" fi else EDIT="$VISUAL" VISUALSET="true" fi #which_1 $EDIT used_editor=`which_1 $EDIT` echo "test -x $used_editor" if test -x "$used_editor" then echo "Using editor $used_editor"; change_editor sleep 2 else echo "Could not find a text editor. (tried $EDIT)" change_editor exit 1 fi # Find out some information. SYSTEM=`( test -f /bin/uname && /bin/uname -a ) || \ ( test -f /usr/bin/uname && /usr/bin/uname -a ) || echo ""` ARCH=`test -f /bin/arch && /bin/arch` MACHINE=`test -f /bin/machine && /bin/machine` FILE_PATHS= for cmd in argus ra tcpdump libpcap.a make gmake gcc cc do file=`which_1 $cmd` if test $? = 0 then if test $cmd = "argus" then ARGUS_INFO=`$file -h 2>&1 | grep -i version 2>&1` elif test $cmd = "ra" then RA_INFO=`$file -h 2>&1 | grep -i version 2>&1` elif test $cmd = "tcpdump" then TCPDUMP_INFO=`$file -h 2>&1 | grep -i version 2>&1 | tr "\n" " "` elif test $cmd = "gcc" then GCC_INFO=`$file -v 2>&1` fi FILE_PATHS="$FILE_PATHS $file" fi done SUBJECT_C="ArgusBug <50 character or so descriptive subject here (for reference)>" ORGANIZATION_C='' LICENCE_C='[none | licence | email support | extended email support ]' SYNOPSIS_C='' SEVERITY_C='<[ non-critical | serious | critical ] (one line)>' PRIORITY_C='<[ low | medium | high ] (one line)>' CLASS_C='<[ install-bug | sw-bug | doc-bug | change-request | support ] (one line)>' PRODUCT_C='<[ argus | ra | ragator | ramon | rapath | rasort | racount | rasrvstats | raxml] (one line)>' RELEASE_C='' ENVIRONMENT_C='' DESCRIPTION_C='' INSTALL_C='' HOW_TO_REPEAT_C='' FIX_C='' cat > $TEMP <'). SEND-PR: From: ${USER} To: ${BUGADDR} Subject: $SUBJECT_C >Description: $DESCRIPTION_C $INSTALL_C >How-To-Repeat: $HOW_TO_REPEAT_C >Fix: $FIX_C >Submitter-Id: >Originator: ${ORIGINATOR} >Organization: ${ORGANIZATION- $ORGANIZATION_C} >Argus support: $LICENCE_C >Release: argus-${VERSION} >Product: $PRODUCT_C >Synopsis: $SYNOPSIS_C >Class: $CLASS_C >Severity: $SEVERITY_C >Priority: $PRIORITY_C >Environment: $ENVIRONMENT_C `test -n "$SYSTEM" && echo "System: $SYSTEM"` `test -n "$ARCH" && echo "Arch: $ARCH"` `test -n "$MACHINE" && echo "Mach: $MACHINE"` `test -n "$FILE_PATHS" && echo "Paths: $FILE_PATHS"` `test -n "$ARGUS_INFO" && echo "ARGUS: $ARGUS_INFO"` `test -n "$RA_INFO" && echo "RA: $RA_INFO"` `test -n "$TCPDUMP_INFO" && echo "TCPDUMP: $TCPDUMP_INFO"` `test -n "$GCC_INFO" && echo "GCC: $GCC_INFO"` `test -n "$LIBC_INFO" && echo "LIBC: $LIBC_INFO"` EOF chmod u+w $TEMP cp $TEMP $TEMP.x eval $EDIT $TEMP if cmp -s $TEMP $TEMP.x then echo "File not changed, no bug report submitted." echo "File saved as /tmp/argus-bugreport-template." mv $TEMP /tmp/argus-bugreport-template exit 1 fi # # Check the enumeration fields # This is a "sed-subroutine" with one keyword parameter # (with workaround for Sun sed bug) # SED_CMD=' /$PATTERN/{ s||| s|<.*>|| s|^[ ]*|| s|[ ]*$|| p q }' while :; do CNT=0 # # 1) Severity # PATTERN=">Severity:" SEVERITY=`eval sed -n -e "\"$SED_CMD\"" $TEMP` case "$SEVERITY" in ""|non-critical|serious|critical) CNT=`expr $CNT + 1` ;; *) echo "$COMMAND: \`$SEVERITY' is not a valid value for \`Severity'." esac # # 2) Priority # PATTERN=">Priority:" PRIORITY=`eval sed -n -e "\"$SED_CMD\"" $TEMP` case "$PRIORITY" in ""|low|medium|high) CNT=`expr $CNT + 1` ;; *) echo "$COMMAND: \`$PRIORITY' is not a valid value for \`Priority'." esac # # 3) Class # PATTERN=">Class:" CLASS=`eval sed -n -e "\"$SED_CMD\"" $TEMP` case "$CLASS" in ""|install-bug|sw-bug|doc-bug|change-request|support) CNT=`expr $CNT + 1` ;; *) echo "$COMMAND: \`$CLASS' is not a valid value for \`Class'." esac # # 4) Synopsis # VALUE=`grep "^>Synopsis:" $TEMP | sed 's/>Synopsis:[ ]*//'` case "$VALUE" in "$SYNOPSIS_C") echo "$COMMAND: \`$VALUE' is not a valid value for \`Synopsis'." ;; *) CNT=`expr $CNT + 1` esac test $CNT -lt 4 && echo "Errors were found with the problem report." # Check if subject of mail was changed, if not, use Synopsis field # subject=`grep "^Subject" $TEMP| sed 's/^Subject:[ ]*//'` if [ X"$subject" = X"$SUBJECT_C" -o X"$subject" = X"$SYNOPSIS_C" ]; then subject=`grep Synopsis $TEMP | sed 's/>Synopsis:[ ]*//'` sed "s/^Subject:[ ]*.*/Subject: $subject/" $TEMP > $TEMP.tmp mv -f $TEMP.tmp $TEMP fi while :; do $ECHON1 "a)bort, e)dit or s)end? $ECHON2" read input case "$input" in a*) echo "$COMMAND: problem report saved in $HOME/dead.argusbug." cat $TEMP >> $HOME/dead.argusbug xs=1; exit ;; e*) eval $EDIT $TEMP continue 2 ;; s*) break 2 ;; esac done done # # Remove comments and send the problem report # (we have to use patterns, where the comment contains regex chars) # # /^>Originator:/s;$ORIGINATOR;; sed -e " /^SEND-PR:/d /^>Organization:/,/^>[A-Za-z-]*:/s;$ORGANIZATION_C;; /^>Confidential:/s;<.*>;; /^>Synopsis:/s;$SYNOPSIS_C;; /^>Severity:/s;<.*>;; /^>Priority:/s;<.*>;; /^>Class:/s;<.*>;; /^>Release:/,/^>[A-Za-z-]*:/s;$RELEASE_C;; /^>Environment:/,/^>[A-Za-z-]*:/s;$ENVIRONMENT_C;; /^>Description:/,/^>[A-Za-z-]*:/s;$DESCRIPTION_C;; /^>How-To-Repeat:/,/^>[A-Za-z-]*:/s;$HOW_TO_REPEAT_C;; /^>Fix:/,/^>[A-Za-z-]*:/s;$FIX_C;; " $TEMP > $TEMP.x if $MAIL_AGENT < $TEMP.x then echo "$COMMAND: problem report sent" xs=0; exit else echo "$COMMAND: mysterious mail failure, report not sent." echo "$COMMAND: problem report saved in $HOME/dead.argusbug." cat $TEMP >> $HOME/dead.argusbug fi exit 0 argus-clients-2.0.6.fixes.1/bin/mkdep0000775000076600007660000000445607306460332013064 #!/bin/sh - # # Copyright (c) 1994, 1996 # The Regents of the University of California. All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # @(#)mkdep.sh 5.11 (Berkeley) 5/5/88 # PATH=/bin:/usr/bin:/usr/ucb:/usr/local:/usr/local/bin export PATH MAKE=Makefile # default makefile name is "Makefile" CC=cc # default C compiler is "cc" while : do case "$1" in # -c allows you to specify the C compiler -c) CC=$2 shift; shift ;; # -f allows you to select a makefile name -f) MAKE=$2 shift; shift ;; # the -p flag produces "program: program.c" style dependencies # so .o's don't get produced -p) SED='s;\.o;;' shift ;; *) break ;; esac done if [ $# = 0 ] ; then echo 'usage: mkdep [-p] [-c cc] [-f makefile] [flags] file ...' exit 1 fi if [ ! -w $MAKE ]; then echo "mkdep: no writeable file \"$MAKE\"" exit 1 fi TMP=/tmp/mkdep$$ trap 'rm -f $TMP ; exit 1' 1 2 3 13 15 cp $MAKE ${MAKE}.bak sed -e '/DO NOT DELETE THIS LINE/,$d' < $MAKE > $TMP cat << _EOF_ >> $TMP # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. _EOF_ # If your compiler doesn't have -M, add it. If you can't, the next two # lines will try and replace the "cc -M". The real problem is that this # hack can't deal with anything that requires a search path, and doesn't # even try for anything using bracket (<>) syntax. # # egrep '^#include[ ]*".*"' /dev/null $* | # sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' -e 's/\.c/.o/' | # XXX this doesn't work with things like "-DDECLWAITSTATUS=union\ wait" $CC -M $* | sed " s; \./; ;g $SED" | awk '{ if ($1 != prev) { if (rec != "") print rec; rec = $0; prev = $1; } else { if (length(rec $2) > 78) { print rec; rec = $0; } else rec = rec " " $2 } } END { print rec }' >> $TMP cat << _EOF_ >> $TMP # IF YOU PUT ANYTHING HERE IT WILL GO AWAY _EOF_ # copy to preserve permissions cp $TMP $MAKE rm -f ${MAKE}.bak $TMP exit 0 argus-clients-2.0.6.fixes.1/clients/0000775000076600007660000000000010047734056013001 5argus-clients-2.0.6.fixes.1/clients/Makefile.in0000664000076600007660000001522107703321100014752 # # Argus Client Software. Tools to read, analyze and manage Argus data. # Copyright (c) 2000-2003 QoSient, LLC # All rights reserved. # # 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 # # # Copyright (c) 1993, 1994, 1995, 1996 # The Regents of the University of California. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that: (1) source code distributions # retain the above copyright notice and this paragraph in its entirety, (2) # distributions including binary code include the above copyright notice and # this paragraph in its entirety in the documentation or other materials # provided with the distribution, and (3) all advertising materials mentioning # features or use of this software display the following acknowledgement: # ``This product includes software developed by the University of California, # Lawrence Berkeley Laboratory and its contributors.'' Neither the name of # the University nor the names of its contributors may be used to endorse # or promote products derived from this software without specific prior # written permission. # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # @(#) $Header: /usr/local/cvsroot/argus-clients/clients/Makefile.in,v 1.13 2003/07/10 17:28:32 argus Exp $ (LBL) # # Various configurable paths (remember to edit Makefile.in, not Makefile) # # Top level hierarchy prefix = $(DESTDIR)@prefix@ exec_prefix = @exec_prefix@ # Pathname of install directory # Pathname of directory to install the system binaries SBINDIR = @sbindir@ # Pathname of directory to install the system binaries BINDIR = @bindir@ # Pathname of directory to install the include files INCLDEST = @includedir@ # Pathname of directory to install the library LIBDEST = @libdir@ # Pathname of directory to install the man page MANDEST = @mandir@ # VPATH srcdir = @srcdir@ VPATH = @srcdir@ # # You shouldn't need to edit anything below. # CC = @CC@ CCOPT = @V_CCOPT@ INCLS = -I . -I../include -I../common @V_INCLS@ DEFS = @DEFS@ COMPATLIB = @COMPATLIB@ @LIB_SASL@ # Standard CFLAGS CFLAGS = $(CCOPT) $(INCLS) $(DEFS) INSTALL = @INSTALL@ RANLIB = @V_RANLIB@ # # Flex and bison allow you to specify the prefixes of the global symbols # used by the generated parser. This allows programs to use lex/yacc # and link against libpcap. If you don't have flex or bison, get them. # LEX = @V_LEX@ YACC = @V_YACC@ # Explicitly define compilation rule since SunOS 4's make doesn't like gcc. # Also, gcc does not remove the .o before forking 'as', which can be a # problem if you don't own the file but can write to the directory. .c.o: @rm -f $@ $(CC) $(CFLAGS) -c $(srcdir)/$*.c LIB = @INSTALL_LIB@/argus_parse.a @INSTALL_LIB@/argus_common.a @INSTALL_LIB@/argus_client.a SRC = rahosts.c rasrvstats.c rarpwatch.c raseq.c \ ra.c ragator.c racount.c raxml.c rapolicy.c \ rasort.c ramon.c rapath.c rastrip.c ranonymize.c PROGS = @INSTALL_BIN@/rahosts @INSTALL_BIN@/rasrvstats \ @INSTALL_BIN@/rarpwatch @INSTALL_BIN@/raseq \ @INSTALL_BIN@/ragator @INSTALL_BIN@/ra @INSTALL_BIN@/racount \ @INSTALL_BIN@/raxml @INSTALL_BIN@/rapolicy @INSTALL_BIN@/ramon \ @INSTALL_BIN@/rasort @INSTALL_BIN@/rapath @INSTALL_BIN@/rastrip \ @INSTALL_BIN@/ranonymize all: $(PROGS) @INSTALL_BIN@/rastrip: rastrip.o $(LIB) $(CC) $(CCOPT) -o $@ rastrip.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/ranonymize: ranonymize.o $(LIB) $(CC) $(CCOPT) -o $@ ranonymize.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/rarpwatch: rarpwatch.o $(LIB) $(CC) $(CCOPT) -o $@ rarpwatch.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/rasrvstats: rasrvstats.o $(LIB) $(CC) $(CCOPT) -o $@ rasrvstats.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/rahosts: rahosts.o $(LIB) $(CC) $(CCOPT) -o $@ rahosts.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/raseq: raseq.o $(LIB) $(CC) $(CCOPT) -o $@ raseq.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/ramatch: ramatch.o $(LIB) $(CC) $(CCOPT) -o $@ ramatch.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/ra: ra.o $(LIB) $(CC) $(CCOPT) -o $@ ra.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/ragator: ragator.o $(LIB) $(CC) $(CCOPT) -o $@ ragator.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/rapath: rapath.o $(LIB) $(CC) $(CCOPT) -o $@ rapath.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/rasort: rasort.o $(LIB) $(CC) $(CCOPT) -o $@ rasort.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/racount: racount.o $(LIB) $(CC) $(CCOPT) -o $@ racount.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/raxml: raxml.o $(LIB) $(CC) $(CCOPT) -o $@ raxml.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/rapolicy: rapolicy.o $(LIB) $(CC) $(CCOPT) -o $@ rapolicy.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/ramon: ramon.o $(LIB) $(CC) $(CCOPT) -o $@ ramon.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/ratemplate: ratemplate.o $(LIB) $(CC) $(CCOPT) -o $@ ratemplate.o $(LIB) $(COMPATLIB) -lm # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot # hack the extra indirection OBJ = $(SRC:.c=.o) CLEANFILES = $(OBJ) $(PROGS) install: force [ -d $(prefix) ] || \ (mkdir -p $(prefix); chmod 755 $(prefix)) [ -d $(BINDIR) ] || \ (mkdir -p $(BINDIR); chmod 755 $(BINDIR)) $(INSTALL) $(srcdir)/../bin/ra* $(BINDIR) clean: rm -f $(CLEANFILES) distclean: rm -f $(CLEANFILES) Makefile config.cache config.log config.status \ gnuc.h os-proto.h bpf_filter.c net tags: $(TAGFILES) ctags -wtd $(TAGFILES) tar: force @cwd=`pwd` ; dir=`basename $$cwd` ; name=libpcap-`cat VERSION` ; \ list="" ; tar="tar chFFf" ; \ for i in `cat FILES` ; do list="$$list $$name/$$i" ; done; \ echo \ "rm -f ../$$name; ln -s $$dir ../$$name" ; \ rm -f ../$$name; ln -s $$dir ../$$name ; \ echo \ "(cd .. ; $$tar - [lots of files]) | compress > /tmp/$$name.tar.Z" ; \ (cd .. ; $$tar - $$list) | compress > /tmp/$$name.tar.Z ; \ echo \ "rm -f ../$$name" ; \ rm -f ../$$name force: /tmp depend: $(GENSRC) force ../bin/mkdep -c $(CC) $(DEFS) $(INCLS) $(SRC) argus-clients-2.0.6.fixes.1/clients/ra.c0000664000076600007660000003166110045736457013503 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * * ra - Read Argus * This program read argus output streams, either through a socket, * a piped stream, or in a file, filters and optionally writes the * output to a file, its stdout or prints the binary records to * stdout in ASCII. */ #include #include #include extern int ArgusSrcUserDataLen; extern int ArgusDstUserDataLen; int RaInitialized = 0; void ArgusClientInit () { if (!(RaInitialized)) { (void) signal (SIGHUP, (void (*)(int)) RaParseComplete); (void) signal (SIGTERM, (void (*)(int)) RaParseComplete); (void) signal (SIGQUIT, (void (*)(int)) RaParseComplete); (void) signal (SIGINT, (void (*)(int)) RaParseComplete); RaInitialized++; } } void RaParseComplete (int sig) { long long total_count, total_dst_count, total_src_count; long long total_bytes, total_dst_bytes, total_src_bytes; if ((sig >= 0) && aflag) { putchar ('\n'); total_src_count = tcp_src_count + udp_src_count + icmp_src_count + ip_src_count + arp_src_count + nonip_src_count; total_dst_count = tcp_dst_count + udp_dst_count + icmp_dst_count + ip_dst_count + arp_dst_count + nonip_dst_count; total_count = total_dst_count + total_src_count; total_src_bytes = tcp_src_bytes + udp_src_bytes + icmp_src_bytes + ip_src_bytes + arp_src_bytes + nonip_src_bytes; total_dst_bytes = tcp_dst_bytes + udp_dst_bytes + icmp_dst_bytes + ip_dst_bytes + arp_dst_bytes + nonip_dst_bytes; total_bytes = total_dst_bytes + total_src_bytes; if (total_count) { printf (" total_pkts src_pkts dst_pkts total_bytes src_bytes dst_bytes\n"); printf ("tcp %16lld %16lld %16lld %16lld %16lld %16lld\n", tcp_dst_count + tcp_src_count, tcp_src_count, tcp_dst_count, tcp_dst_bytes + tcp_src_bytes, tcp_src_bytes, tcp_dst_bytes); printf ("udp %16lld %16lld %16lld %16lld %16lld %16lld\n", udp_dst_count + udp_src_count, udp_src_count, udp_dst_count, udp_dst_bytes + udp_src_bytes, udp_src_bytes, udp_dst_bytes); printf ("icmp %16lld %16lld %16lld %16lld %16lld %16lld\n", icmp_dst_count + icmp_src_count, icmp_src_count, icmp_dst_count, icmp_dst_bytes + icmp_src_bytes, icmp_src_bytes, icmp_dst_bytes); printf ("ip %16lld %16lld %16lld %16lld %16lld %16lld\n", ip_dst_count + ip_src_count, ip_src_count, ip_dst_count, ip_dst_bytes + ip_src_bytes, ip_src_bytes, ip_dst_bytes); printf ("arp %16lld %16lld %16lld %16lld %16lld %16lld\n", arp_dst_count + arp_src_count, arp_src_count, arp_dst_count, arp_dst_bytes + arp_src_bytes, arp_src_bytes, arp_dst_bytes); printf ("non-ip %16lld %16lld %16lld %16lld %16lld %16lld\n", nonip_dst_count + nonip_src_count, nonip_src_count, nonip_dst_count, nonip_dst_bytes + nonip_src_bytes, nonip_src_bytes, nonip_dst_bytes); printf ("sum %16lld %16lld %16lld %16lld %16lld %16lld", total_count, total_src_count, total_dst_count, total_bytes, total_src_bytes, total_dst_bytes); printf ("\n\n"); } else printf ("No data seen.\n"); fflush (stdout); } if (sig == SIGINT) _exit(0); } void ArgusClientTimeout () { #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusClientTimeout()\n"); #endif } void parse_arg (int argc, char**argv) {} void usage () { extern char version[]; fprintf (stderr, "Ra Version %s\n", version); fprintf (stderr, "usage: %s \n", ArgusProgramName); fprintf (stderr, "usage: %s [options] -S remoteServer [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "usage: %s [options] -r argusDataFile [- filter-expression]\n\n", ArgusProgramName); fprintf (stderr, "options: -a print record summaries on termination.\n"); fprintf (stderr, " -A print application bytes.\n"); fprintf (stderr, " -b dump packet-matching code.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); fprintf (stderr, " -d print number of from user data capture buffer.\n"); fprintf (stderr, " format: num | s | d | s:d\n"); #if defined (ARGUSDEBUG) fprintf (stderr, " -D specify debug level\n"); #endif fprintf (stderr, " -e convert user data using method.\n"); fprintf (stderr, " Supported types are and .\n"); fprintf (stderr, " -E write records that are rejected by the filter into \n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -n don't convert numbers to names.\n"); fprintf (stderr, " -p print fractional time with precision.\n"); fprintf (stderr, " -q quiet mode. don't print record outputs.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -R print out response data when availabile.\n"); fprintf (stderr, " -s [-][+[#]]field specify fields to print.\n"); fprintf (stderr, " fields: startime, lasttime, count, dur, avgdur,\n"); fprintf (stderr, " saddr, daddr, proto, sport, dport, ipid,\n"); fprintf (stderr, " stos, dtos, sttl, dttl, bytes, sbytes, dbytes,\n"); fprintf (stderr, " pkts, spkts, dpkts, load, loss, rate,\n"); fprintf (stderr, " srcid, ind, mac, dir, jitter, status, user,\n"); fprintf (stderr, " win, trans, seq, vlan, mpls.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [[[yyyy/]mm/]dd.]hh[:mm[:ss]]\n"); fprintf (stderr, " [yyyy/]mm/dd\n"); fprintf (stderr, " -%%d{yMdhms}\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); fprintf (stderr, " -u print time in Unix time format.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif fprintf (stderr, " -w write output to . '-' denotes stdout.\n"); fprintf (stderr, " -z print Argus TCP state changes.\n"); fprintf (stderr, " -Z print actual TCP flag values.<'s'rc | 'd'st | 'b'oth>\n"); exit(1); } int RaLabelCounter = 0; void RaProcessRecord (struct ArgusRecord *argus) { if (Lflag && !(qflag)) { if (RaLabel == NULL) RaLabel = RaGenerateLabel(argus); if (!(RaLabelCounter++ % Lflag)) { printf ("%s\n", RaLabel); fflush (stdout); } if (Lflag < 0) Lflag = 0; } if (argus->ahdr.type & ARGUS_MAR) RaProcessManRecord (argus); else { switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: RaProcessTCPRecord (argus); break; case IPPROTO_UDP: RaProcessUDPRecord (argus); break; case IPPROTO_ICMP: RaProcessICMPRecord (argus); break; default: RaProcessIPRecord (argus); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: RaProcessARPRecord (argus); break; default: RaProcessNonIPRecord (argus); break; } } if (Nflag > 0) { if (--Nflag == 0) { RaParseComplete(SIGINT); } } } void RaProcessManRecord (struct ArgusRecord *argus) { char *str = NULL; if (!(qflag || wfile)) { str = get_man_string (argus); (void) printf ("%s", str); printf ("\n"); fflush (stdout); } } void RaProcessFragRecord (struct ArgusRecord *argus) { } void RaProcessTCPRecord (struct ArgusRecord *argus) { if (aflag) { tcp_src_count += argus->argus_far.src.count; tcp_dst_count += argus->argus_far.dst.count; if (Aflag) { tcp_src_bytes += argus->argus_far.src.appbytes; tcp_dst_bytes += argus->argus_far.dst.appbytes; } else { tcp_src_bytes += argus->argus_far.src.bytes; tcp_dst_bytes += argus->argus_far.dst.bytes; } } if (!qflag) { printf ("%s", get_tcp_string (argus)); printf ("\n"); } fflush(stdout); } void RaProcessICMPRecord (struct ArgusRecord *argus) { if (aflag) { icmp_src_count += argus->argus_far.src.count; icmp_dst_count += argus->argus_far.dst.count; if (Aflag) { icmp_src_bytes += argus->argus_far.src.appbytes; icmp_dst_bytes += argus->argus_far.dst.appbytes; } else { icmp_src_bytes += argus->argus_far.src.bytes; icmp_dst_bytes += argus->argus_far.dst.bytes; } } if (!qflag) { printf ("%s", get_icmp_string (argus)); printf ("\n"); } fflush(stdout); } void RaProcessUDPRecord (struct ArgusRecord *argus) { if (aflag) { udp_src_count += argus->argus_far.src.count; udp_dst_count += argus->argus_far.dst.count; if (Aflag) { udp_src_bytes += argus->argus_far.src.appbytes; udp_dst_bytes += argus->argus_far.dst.appbytes; } else { udp_src_bytes += argus->argus_far.src.bytes; udp_dst_bytes += argus->argus_far.dst.bytes; } } if (!qflag) { printf ("%s", get_ip_string (argus)); printf ("\n"); } fflush(stdout); } void RaProcessIPRecord (struct ArgusRecord *argus) { if (aflag) { ip_src_count += argus->argus_far.src.count; ip_dst_count += argus->argus_far.dst.count; if (Aflag) { ip_src_bytes += argus->argus_far.src.appbytes; ip_dst_bytes += argus->argus_far.dst.appbytes; } else { ip_src_bytes += argus->argus_far.src.bytes; ip_dst_bytes += argus->argus_far.dst.bytes; } } if (!qflag) { printf ("%s", get_ip_string (argus)); printf ("\n"); } fflush(stdout); } void RaProcessARPRecord (struct ArgusRecord *argus) { if (aflag) { arp_src_count += argus->argus_far.src.count; arp_dst_count += argus->argus_far.dst.count; if (Aflag) { arp_src_bytes += argus->argus_far.src.appbytes; arp_dst_bytes += argus->argus_far.dst.appbytes; } else { arp_src_bytes += argus->argus_far.src.bytes; arp_dst_bytes += argus->argus_far.dst.bytes; } } if (!qflag) { printf ("%s", get_arp_string (argus)); printf ("\n"); } fflush(stdout); } void RaProcessNonIPRecord (struct ArgusRecord *argus) { if (aflag) { nonip_src_count += argus->argus_far.src.count; nonip_dst_count += argus->argus_far.dst.count; if (Aflag) { nonip_src_bytes += argus->argus_far.src.appbytes; nonip_dst_bytes += argus->argus_far.dst.appbytes; } else { nonip_src_bytes += argus->argus_far.src.bytes; nonip_dst_bytes += argus->argus_far.dst.bytes; } } if (!qflag) { printf ("%s", get_nonip_string (argus)); printf ("\n"); } fflush(stdout); } int RaSendArgusRecord(struct ArgusRecordStore *argus) {return 0;} argus-clients-2.0.6.fixes.1/clients/racount.c0000664000076600007660000002555307640610353014550 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * racount - argus data counting program. * * written by Carter Bullard * QoSient, LLC * */ #include long long totalflowrecords = 0; long long totaltcpflowrecs = 0; long long totaludpflowrecs = 0; long long totalicmpflowrecs = 0; long long totalipflowrecs = 0; long long totalarpflowrecs = 0; long long totalnonipflowrecs = 0; int RaInitialized = 0; void ArgusClientInit () { if (!(RaInitialized)) { RaInitialized++; } } int RaMonSource = 0; void RaParseComplete (int sig) { long long total_count, total_dst_count, total_src_count; long long total_bytes, total_dst_bytes, total_src_bytes; char *printStr = NULL; if (sig >= 0) { total_src_count = tcp_src_count + udp_src_count + icmp_src_count + ip_src_count + arp_src_count + nonip_src_count; total_dst_count = tcp_dst_count + udp_dst_count + icmp_dst_count + ip_dst_count + arp_dst_count + nonip_dst_count; total_count = total_dst_count + total_src_count; total_src_bytes = tcp_src_bytes + udp_src_bytes + icmp_src_bytes + ip_src_bytes + arp_src_bytes + nonip_src_bytes; total_dst_bytes = tcp_dst_bytes + udp_dst_bytes + icmp_dst_bytes + ip_dst_bytes + arp_dst_bytes + nonip_dst_bytes; total_bytes = total_dst_bytes + total_src_bytes; if (total_count) { if (RaMonSource) { printf ("%-10s records total_pkts in_pkts out_pkts ", ArgusProgramName); printf ("total_bytes in_bytes out_bytes\n"); } else { printf ("%-10s records total_pkts src_pkts dst_pkts ", ArgusProgramName); printf ("total_bytes src_bytes dst_bytes\n"); } #if defined(HAVE_SOLARIS) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(CYGWIN) printStr = "%7s %10lld %16lld %16lld %16lld %16lld %16lld %16lld\n"; #else printStr = "%7s %10Ld %16Ld %16Ld %16Ld %16Ld %16Ld %16Ld\n"; #endif if (aflag) { if ((tcp_src_count + tcp_dst_count) > 0) { printf (printStr, "tcp", totaltcpflowrecs, tcp_dst_count + tcp_src_count, tcp_src_count, tcp_dst_count, tcp_dst_bytes + tcp_src_bytes, tcp_src_bytes, tcp_dst_bytes); if ((tcp_src_count + tcp_dst_count) == total_count) goto racount_done; } if ((udp_src_count + udp_dst_count) > 0) { printf (printStr, "udp", totaludpflowrecs, udp_dst_count + udp_src_count, udp_src_count, udp_dst_count, udp_dst_bytes + udp_src_bytes, udp_src_bytes, udp_dst_bytes); if ((udp_src_count + udp_dst_count) == total_count) goto racount_done; } if ((icmp_src_count + icmp_dst_count) > 0) { printf (printStr, "icmp", totalicmpflowrecs, icmp_dst_count + icmp_src_count, icmp_src_count, icmp_dst_count, icmp_dst_bytes + icmp_src_bytes, icmp_src_bytes, icmp_dst_bytes); if ((icmp_src_count + icmp_dst_count) == total_count) goto racount_done; } if ((ip_src_count + ip_dst_count) > 0) { printf (printStr, "ip", totalipflowrecs, ip_dst_count + ip_src_count, ip_src_count, ip_dst_count, ip_dst_bytes + ip_src_bytes, ip_src_bytes, ip_dst_bytes); if ((ip_src_count + ip_dst_count) == total_count) goto racount_done; } if ((arp_src_count + arp_dst_count) > 0) { printf (printStr, "arp", totalarpflowrecs, arp_dst_count + arp_src_count, arp_src_count, arp_dst_count, arp_dst_bytes + arp_src_bytes, arp_src_bytes, arp_dst_bytes); if ((arp_src_count + arp_dst_count) == total_count) goto racount_done; } if ((nonip_src_count + nonip_dst_count) > 0) { printf (printStr, "non-ip", totalnonipflowrecs, nonip_dst_count + nonip_src_count, nonip_src_count, nonip_dst_count, nonip_dst_bytes + nonip_src_bytes, nonip_src_bytes, nonip_dst_bytes); if ((nonip_src_count + nonip_dst_count) == total_count) goto racount_done; } } printf (printStr, "sum", totalflowrecords, total_count, total_src_count, total_dst_count, total_bytes, total_src_bytes, total_dst_bytes); } else printf ("No data seen.\n"); racount_done: fflush (stdout); _exit(0); } } void ArgusClientTimeout () { } void parse_arg (int argc, char**argv) { } void usage () { extern char version[]; fprintf (stderr, "Racount Version %s\n", version); fprintf (stderr, "usage: %s \n", ArgusProgramName); fprintf (stderr, "usage: %s [ra-options] [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "ra-options: -b dump packet-matching code.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); fprintf (stderr, " -D specify debug level\n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -P specify remote argus (tcp/561).\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [mm/dd[/yy].]hh[:mm[:ss]]\n"); fprintf (stderr, " mm/dd[/yy]\n"); fprintf (stderr, " -%%d{yMhdms}\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif fprintf (stderr, " -T attach to remote server for T seconds.\n"); exit(1); } void RaProcessRecord (struct ArgusRecord *argus) { totalflowrecords++; if (argus->ahdr.type & ARGUS_MAR) { RaProcessManRecord (argus); } else { if (argus->ahdr.type & ARGUS_RMON) RaMonSource++; else RaMonSource = 0; switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: RaProcessTCPRecord (argus); break; case IPPROTO_UDP: RaProcessUDPRecord (argus); break; case IPPROTO_ICMP: RaProcessICMPRecord (argus); break; default: RaProcessIPRecord (argus); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: RaProcessARPRecord (argus); break; default: RaProcessNonIPRecord (argus); break; } } } void RaProcessManRecord (struct ArgusRecord *argus) { } void RaProcessTCPRecord (struct ArgusRecord *argus) { totaltcpflowrecs++; tcp_src_count += argus->argus_far.src.count; tcp_dst_count += argus->argus_far.dst.count; if (Aflag) { tcp_src_bytes += argus->argus_far.src.appbytes; tcp_dst_bytes += argus->argus_far.dst.appbytes; } else { tcp_src_bytes += argus->argus_far.src.bytes; tcp_dst_bytes += argus->argus_far.dst.bytes; } } void RaProcessICMPRecord (struct ArgusRecord *argus) { totalicmpflowrecs++; icmp_src_count += argus->argus_far.src.count; icmp_dst_count += argus->argus_far.dst.count; if (Aflag) { icmp_src_bytes += argus->argus_far.src.appbytes; icmp_dst_bytes += argus->argus_far.dst.appbytes; } else { icmp_src_bytes += argus->argus_far.src.bytes; icmp_dst_bytes += argus->argus_far.dst.bytes; } } void RaProcessUDPRecord (struct ArgusRecord *argus) { totaludpflowrecs++; udp_src_count += argus->argus_far.src.count; udp_dst_count += argus->argus_far.dst.count; if (Aflag) { udp_src_bytes += argus->argus_far.src.appbytes; udp_dst_bytes += argus->argus_far.dst.appbytes; } else { udp_src_bytes += argus->argus_far.src.bytes; udp_dst_bytes += argus->argus_far.dst.bytes; } } void RaProcessIPRecord (struct ArgusRecord *argus) { totalipflowrecs++; ip_src_count += argus->argus_far.src.count; ip_dst_count += argus->argus_far.dst.count; if (Aflag) { ip_src_bytes += argus->argus_far.src.appbytes; ip_dst_bytes += argus->argus_far.dst.appbytes; } else { ip_src_bytes += argus->argus_far.src.bytes; ip_dst_bytes += argus->argus_far.dst.bytes; } } void RaProcessARPRecord (struct ArgusRecord *argus) { totalarpflowrecs++; arp_src_count += argus->argus_far.src.count; arp_dst_count += argus->argus_far.dst.count; if (Aflag) { arp_src_bytes += argus->argus_far.src.appbytes; arp_dst_bytes += argus->argus_far.dst.appbytes; } else { arp_src_bytes += argus->argus_far.src.bytes; arp_dst_bytes += argus->argus_far.dst.bytes; } } void RaProcessNonIPRecord (struct ArgusRecord *argus) { totalnonipflowrecs++; nonip_src_count += argus->argus_far.src.count; nonip_dst_count += argus->argus_far.dst.count; if (Aflag) { nonip_src_bytes += argus->argus_far.src.appbytes; nonip_dst_bytes += argus->argus_far.dst.appbytes; } else { nonip_src_bytes += argus->argus_far.src.bytes; nonip_dst_bytes += argus->argus_far.dst.bytes; } } int RaSendArgusRecord(struct ArgusRecordStore *argus) {return 0;} argus-clients-2.0.6.fixes.1/clients/ragator.c0000664000076600007660000007052607640610353014534 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * ragator - argus record aggregator with flow model manipulation. * * written by Carter Bullard * QoSient, LLC * */ #include #include #include #include int RaLabelCounter = 0; void RaProcessRecord (struct ArgusRecord *argus) { if (argus->ahdr.type & ARGUS_MAR) RaProcessManRecord (argus); else { switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: RaProcessTCPRecord (argus); break; case IPPROTO_UDP: RaProcessUDPRecord (argus); break; case IPPROTO_ICMP: RaProcessICMPRecord (argus); break; default: RaProcessIPRecord (argus); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: RaProcessARPRecord (argus); break; default: RaProcessNonIPRecord (argus); break; } } if (Nflag > 0) { if (Nflag-- == 1) { RaParseComplete(SIGINT); } } } void RaProcessSrvRecord (struct ArgusServiceRecord *); int RaInitialized = 0; int RaTimeout = 0x1FFFFFFF; int RaIdleTimeout = 0; int RaPrintSVGOutput = 0; struct RaFlowModelStruct *RaFlowModel = NULL; void ArgusClientInit () { struct ArgusModeStruct *mode = NULL; if (!(RaInitialized)) { RaWriteOut = 0; RaCumulativeMerge = 1; if ((mode = ArgusModeList) != NULL) { while (mode) { if (!(strcasecmp (mode->mode, "svg"))) RaPrintSVGOutput++; mode = mode->nxt; } } if (ArgusFlowModelFile) { if ((RaFlowModel = RaReadFlowModelFile(NULL)) == NULL) ArgusLog (LOG_ERR, "RaReadFlowModelFile failed %s\n", strerror(errno)); if (aflag) RaFlowModel->report = 1; } if ((RaModelerQueue = RaNewQueue()) == NULL) ArgusLog (LOG_ERR, "RaNewQueue failed %s\n", strerror(errno)); if ((RaHashTable.array = (struct RaHashTableHeader **) ArgusCalloc (RA_HASHTABLESIZE, sizeof (struct RaHashTableHeader *))) != NULL) { RaHashTable.size = RA_HASHTABLESIZE; } if (Hflag) { if (!(RaHistoTimeParse (Hstr))) usage(); } (void) signal (SIGHUP, (void (*)(int)) RaParseComplete); (void) signal (SIGTERM, (void (*)(int)) RaParseComplete); (void) signal (SIGQUIT, (void (*)(int)) RaParseComplete); (void) signal (SIGINT, (void (*)(int)) RaParseComplete); RaInitialized++; } } int RaParseCompleting = 0; void RaParseComplete (int sig) { if ((sig >= 0) && (!RaParseCompleting)) { RaParseCompleting++; if (RaModelerQueue) RaProcessQueue (RaModelerQueue, ARGUS_STOP); } if (sig == SIGINT) _exit(0); #ifdef ARGUSDEBUG ArgusDebug (1, "RaParseComplete: returning\n"); #endif } void ArgusClientTimeout () { RaProcessQueue (RaModelerQueue, ARGUS_STATUS); #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusClientTimeout: current time %s.\n", print_time(&ArgusGlobalTime)); if (ArgusMinuteUpdate++ == 60) { ArgusDebug (2, "ArgusClientTimeout: current time %s HashHdrs %d Hash %d Queue %d\n", print_time(&ArgusGlobalTime), RaAllocHashTableHeaders, RaHashTable.count, RaModelerQueue->count); ArgusMinuteUpdate = 1; } if (ArgusHourlyUpdate++ == 3600) { ArgusDebug (2, "ArgusClientTimeout: current time %s.\n", print_time(&ArgusGlobalTime)); ArgusHourlyUpdate = 1; } #endif } void parse_arg (int argc, char**argv) { } void usage () { extern char version[]; fprintf (stderr, "Ragator Version %s\n", version); fprintf (stderr, "usage: %s [-f flowfile]\n", ArgusProgramName); fprintf (stderr, "usage: %s [-f flowfile] [ra-options] [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "options: -f read flow model from .\n"); fprintf (stderr, "ra-options: -a print record summaries on termination.\n"); fprintf (stderr, " -A print application bytes.\n"); fprintf (stderr, " -b dump packet-matching code.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); fprintf (stderr, " -D specify debug level\n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -n don't convert numbers to names.\n"); fprintf (stderr, " -p print fractional time with precision.\n"); fprintf (stderr, " -q quiet mode. don't print record outputs.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -R print out response data when availabile.\n"); fprintf (stderr, " -s [-][+[#]]field specify fields to print.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [mm/dd[/yy].]hh[:mm[:ss]]\n"); fprintf (stderr, " mm/dd[/yy]\n"); fprintf (stderr, " -%%d{yMhdms}\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); fprintf (stderr, " -u print time in Unix time format.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif fprintf (stderr, " -w write output to . '-' denotes stdout.\n"); fprintf (stderr, " -z print Argus TCP state changes.\n"); fprintf (stderr, " -Z print actual TCP flag values.<'s'rc | 'd'st | 'b'oth>\n"); exit(1); } void RaProcessSrvRecord (struct ArgusServiceRecord *srv) { struct ArgusRecord *argus = srv->argus; struct ArgusRecordStore *store; struct RaPolicyStruct *rap; struct ArgusFlow *flow = &argus->argus_far.flow; extern int RaHistoStart; int i = 0; if (xflag && (srv->status == RA_SVCFAILED)) return; RaThisActiveDuration = RaGetActiveDuration(argus); RaThisActiveIndex = RaHistoTimeSeries; if (Hflag) { if (RaThisActiveDuration < RaHistoStart) return; for (i = 0; i < (RaHistoTimeSeries + 1); i++) { if (RaThisActiveDuration < RaHistoTimeValues[i]) { RaThisActiveIndex = i; break; } } if (i == RaHistoTimeSeries) return; } else RaThisActiveIndex = 0; bcopy((char *) flow, (char *) RaArgusFlow, sizeof(struct ArgusFlow)); if ((rap = RaFlowModelOverRides(argus, RaFlowModel)) != NULL) { RaModifyFlow(rap, argus, RaFlowModel); RaTimeout = rap->ArgusTimeout; RaIdleTimeout = rap->ArgusIdleTimeout; } else { RaModifyDefaultFlow(argus); } if ((store = RaFindArgusRecord(&RaHashTable, argus)) == NULL) if ((store = RaFindRevArgusRecord(&RaHashTable, argus)) != NULL) { } if (store) { RaThisArgusStore = store; RaCheckTimeout (store, argus); if ((srv->status & RA_SVCTEST) != (store->status & RA_SVCTEST)) { RaSendArgusRecord(store); store->status &= ~RA_SVCTEST; store->status |= (srv->status & RA_SVCTEST); } if (!(store->data[RaThisActiveIndex])) { struct ArgusRecordData *data = NULL; if ((data = RaNewArgusData(argus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; data->status |= srv->status & RA_SVCTEST; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *)&data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } store->data[RaThisActiveIndex] = data; } else ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); } else RaMergeArgusRecord(argus, store, RaThisActiveIndex); RaUpdateArgusStore(argus, store); } else { if ((store = RaNewArgusStore(argus)) != NULL) { struct ArgusRecordData *data = NULL; store->ArgusTimeout = RaTimeout; store->ArgusIdleTimeout = RaIdleTimeout; RaThisArgusStore = store; store->status |= RA_MODIFIED; store->status |= srv->status & RA_SVCTEST; if ((data = RaNewArgusData(argus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *)&data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } store->data[RaThisActiveIndex] = data; if ((store->rahtblhdr = RaAddHashEntry (&RaHashTable, store)) != NULL) RaAddToQueue(RaModelerQueue, &store->qhdr); } else ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); } else ArgusLog (LOG_ERR, "RaNewArgusStore failed %s\n", strerror(errno)); } RaIdleTimeout = 0; #ifdef ARGUSDEBUG ArgusDebug (7, "RaProcessSrvRecord: done\n"); #endif } void RaProcessManRecord (struct ArgusRecord *argus) { } struct ArgusServiceRecord ArgusThisSrv; void RaProcessTCPRecord (struct ArgusRecord *argus) { struct ArgusTCPObject *tcp = NULL; int srccount, dstcount; ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; srccount = argus->argus_far.src.count; dstcount = argus->argus_far.dst.count; RaIdleTimeout = 7200; if (Vflag) { if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) { if ((tcp = (struct ArgusTCPObject *) ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]) != NULL) { if (tcp->state & (ARGUS_SAW_SYN || ARGUS_SAW_SYN_SENT)) { if (tcp->state & ARGUS_RESET) { if (tcp->state & ARGUS_DST_RESET) if (argus->argus_far.src.count && argus->argus_far.dst.count) if (!(argus->argus_far.src.bytes && argus->argus_far.dst.bytes)) ArgusThisSrv.status = RA_SVCFAILED; if (tcp->state & ARGUS_SRC_RESET) if (argus->argus_far.src.count && !(argus->argus_far.dst.count)) ArgusThisSrv.status = RA_SVCFAILED; } } if (tcp->state & ARGUS_TIMEOUT) if (argus->argus_far.src.count && !(argus->argus_far.dst.count)) ArgusThisSrv.status = RA_SVCFAILED; } } } RaProcessSrvRecord (&ArgusThisSrv); RaIdleTimeout = 0; } void RaProcessICMPRecord (struct ArgusRecord *argus) { int srccount, dstcount; ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; srccount = argus->argus_far.src.count; dstcount = argus->argus_far.dst.count; if (Vflag) { if ((argus->argus_far.src.count > 0) && (argus->argus_far.dst.count == 0)) { ArgusThisSrv.status = RA_SVCFAILED; } else { ArgusThisSrv.status = RA_SVCPASSED; } } RaProcessSrvRecord (&ArgusThisSrv); } void RaProcessUDPRecord (struct ArgusRecord *argus) { int srccount, dstcount; ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; srccount = argus->argus_far.src.count; dstcount = argus->argus_far.dst.count; if (Vflag) if ((srccount == 0) || (dstcount == 0)) ArgusThisSrv.status = RA_SVCFAILED; if (argus->argus_far.flow.ip_flow.tp_p == ARGUS_RTP_FLOWTAG) if (!((argus->argus_far.src.count > 3) || (argus->argus_far.dst.count > 3))) argus->argus_far.flow.ip_flow.tp_p = 0; if (Rflag) if (!((srccount > 0) && (dstcount > 0))) ArgusThisSrv.status = RA_SVCFAILED; RaProcessSrvRecord (&ArgusThisSrv); } void RaProcessIPRecord (struct ArgusRecord *argus) { ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Vflag) { if ((argus->argus_far.src.count > 0) && (argus->argus_far.dst.count == 0)) { ArgusThisSrv.status = RA_SVCFAILED; } else { ArgusThisSrv.status = RA_SVCPASSED; } } if (Rflag) if (!((argus->argus_far.src.count == 1) && (argus->argus_far.dst.count == 1))) ArgusThisSrv.status = RA_SVCFAILED; RaProcessSrvRecord (&ArgusThisSrv); } void RaProcessARPRecord (struct ArgusRecord *argus) { ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Rflag) if (!((argus->argus_far.src.count == 1) && (argus->argus_far.dst.count == 1))) ArgusThisSrv.status = RA_SVCFAILED; RaProcessSrvRecord (&ArgusThisSrv); } void RaProcessNonIPRecord (struct ArgusRecord *argus) { ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Rflag) if (!((argus->argus_far.src.count == 1) && (argus->argus_far.dst.count == 1))) ArgusThisSrv.status = RA_SVCFAILED; RaProcessSrvRecord (&ArgusThisSrv); } #include #include #define RA_MAXQSCAN 25600 #define RA_MAXQSIZE 250000 void RaProcessQueue(struct RaQueueStruct *queue, unsigned char status) { struct ArgusRecordStore *obj = NULL; int cnt = 0; switch (status) { case ARGUS_STOP: while ((obj = (struct ArgusRecordStore *) RaPopQueue(queue)) != NULL) RaTimeoutArgusStore(obj); break; default: while (queue->count > RA_MAXQSIZE) { obj = (struct ArgusRecordStore *) RaRemoveFromQueue(RaModelerQueue, RaModelerQueue->start->prv); RaTimeoutArgusStore(obj); } if ((cnt = ((queue->count > RA_MAXQSCAN) ? RA_MAXQSCAN : queue->count)) != 0) { while (cnt--) { if ((obj = (struct ArgusRecordStore *) RaPopQueue(queue)) != NULL) { if (RaCheckTimeout(obj, NULL)) RaTimeoutArgusStore(obj); else RaAddToQueue(queue, &obj->qhdr); } else cnt++; } } break; } #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessQueue (0x%x, %d) returning\n", queue, status); #endif } int RaSendArgusRecord(struct ArgusRecordStore *store) { unsigned char buf[MAXSTRLEN]; struct ArgusRecordData *data; struct ArgusRecord *argus = NULL; struct ArgusFarHeaderStruct *farhdr; struct ArgusAGRStruct *agr = NULL; int i, retn = 0; for (i = 0; i < RaHistoTimeSeries; i++) { if ((data = store->data[i]) != NULL) { argus = data->argus; if ((Lflag > 0) && !(qflag)) { if (RaLabel == NULL) RaLabel = RaGenerateLabel(argus); if (!(RaLabelCounter++ % Lflag)) { if (!(wfile)) printf ("%s\n", RaLabel); fflush (stdout); } if (Lflag < 0) Lflag = 0; } if (argus && (data->status & RA_MODIFIED)) { if (data->act.n > 0) { data->agr.act.n = data->act.n; data->agr.act.meanval = data->act.sumtime/data->act.n; data->agr.act.stdev = sqrt (data->act.sumsqrd/data->act.n - pow (data->act.sumtime/data->act.n, 2.0)); } if (data->idle.n > 0) { data->agr.idle.n = data->idle.n; data->agr.idle.meanval = data->idle.sumtime/data->idle.n; data->agr.idle.stdev = sqrt (data->idle.sumsqrd/data->idle.n - pow (data->idle.sumtime/data->idle.n, 2.0)); } ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) != NULL) bcopy ((char *)&data->agr, (char *)agr, data->agr.length); bcopy ((char *) argus, buf, argus->ahdr.length); argus = (struct ArgusRecord *) buf; ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) == NULL) { if ((RaFlowModel && (RaFlowModel->report > 0)) || (Hflag != 0)) { bcopy ((char *)&data->agr, &buf[argus->ahdr.length], data->agr.length); argus->ahdr.length += data->agr.length; argus->ahdr.status |= ARGUS_MERGED; ArgusFree (data->argus); data->argus = RaCopyArgusRecord(argus); ArgusThisFarStatus = ArgusIndexRecord(data->argus, ArgusThisFarHdrs); } else argus->ahdr.status &= ~(ARGUS_MERGED); } if (RaPrintActualValues) { switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: if (!(data->status & ARGUS_FAR_SRCADDR_MODIFIED)) if (argus->argus_far.flow.ip_flow.ip_src != data->flow.ip_flow.ip_src) argus->argus_far.flow.ip_flow.ip_src = data->flow.ip_flow.ip_src; if (!(data->status & ARGUS_FAR_DSTADDR_MODIFIED)) if (argus->argus_far.flow.ip_flow.ip_dst != data->flow.ip_flow.ip_dst) argus->argus_far.flow.ip_flow.ip_dst = data->flow.ip_flow.ip_dst; if (!(data->status & ARGUS_FAR_PROTO_MODIFIED)) { if (argus->argus_far.flow.ip_flow.ip_p != data->flow.ip_flow.ip_p) argus->argus_far.flow.ip_flow.ip_p = data->flow.ip_flow.ip_p; switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: case IPPROTO_UDP: if (!(data->status & ARGUS_FAR_SRCPORT_MODIFIED)) { if (argus->argus_far.flow.ip_flow.sport != data->flow.ip_flow.sport) argus->argus_far.flow.ip_flow.sport = data->flow.ip_flow.sport; } if (!(data->status & ARGUS_FAR_DSTPORT_MODIFIED)) { if (argus->argus_far.flow.ip_flow.dport != data->flow.ip_flow.dport) argus->argus_far.flow.ip_flow.dport = data->flow.ip_flow.dport; } break; } } } } if ((ArgusWfileList != NULL) && (!(ArgusListEmpty(ArgusWfileList)))) { struct ArgusWfileStruct *wfile = NULL, *start = NULL; if ((wfile = ArgusFrontList(ArgusWfileList)) != NULL) { start = wfile; do { if ((exceptfile == NULL) || strcmp(wfile->filename, exceptfile)) { #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif ArgusWriteNewLogfile (wfile, argus); #ifdef _LITTLE_ENDIAN ArgusNtoH(argus); #endif } ArgusPopFrontList(ArgusWfileList); ArgusPushBackList(ArgusWfileList, wfile); wfile = ArgusFrontList(ArgusWfileList); } while (wfile != start); } } else { if (argus->ahdr.type & ARGUS_MAR) printf ("%s\n", get_man_string (argus)); else { ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: printf ("%s", get_tcp_string (argus)); break; case IPPROTO_ICMP: printf ("%s", get_icmp_string (argus)); break; default: printf ("%s", get_ip_string (argus)); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: printf ("%s", get_arp_string (argus)); break; default: printf ("%s", get_nonip_string (argus)); break; } printf ("\n"); } fflush (stdout); } argus = data->argus; if (argus->ahdr.type & ARGUS_FAR) { int farlen, length = argus->ahdr.length - sizeof(argus->ahdr); farhdr = (struct ArgusFarHeaderStruct *)((char *)argus + sizeof(argus->ahdr)); while (length > 0) { switch (farhdr->type) { case ARGUS_FAR: { struct ArgusFarStruct *far = (struct ArgusFarStruct *) farhdr; far->time.start.tv_sec = 0x7FFFFFFF; far->time.start.tv_usec = 0; far->time.last.tv_sec = 0; far->time.last.tv_usec = 0; far->src.count = 0; far->src.bytes = 0; far->dst.count = 0; far->dst.bytes = 0; break; } case ARGUS_TCP_DSR: { struct ArgusTCPObject *tcp = (struct ArgusTCPObject *) farhdr; tcp->state = 0; tcp->src.seqbase = 0; tcp->src.ackbytes = 0; tcp->src.rpkts = 0; tcp->src.win = 0; tcp->src.flags = 0; tcp->dst.seqbase = 0; tcp->dst.ackbytes = 0; tcp->dst.rpkts = 0; tcp->dst.win = 0; tcp->dst.flags = 0; break; } case ARGUS_TIME_DSR: { struct ArgusTimeStruct *time = (struct ArgusTimeStruct *) farhdr; time->src.act.n = 0; time->src.act.meanval = 0; time->src.act.stdev = 0; time->src.act.maxval = 0; time->src.act.minval = 0x7FFFFFFF; time->src.idle.n = 0; time->src.idle.meanval = 0; time->src.idle.stdev = 0; time->src.idle.maxval = 0; time->src.idle.minval = 0x7FFFFFFF; time->dst.act.n = 0; time->dst.act.meanval = 0; time->dst.act.stdev = 0; time->dst.act.maxval = 0; time->dst.act.minval = 0x7FFFFFFF; time->dst.idle.n = 0; time->dst.idle.meanval = 0; time->dst.idle.stdev = 0; time->dst.idle.maxval = 0; time->dst.idle.minval = 0x7FFFFFFF; break; } case ARGUS_VLAN_DSR: { struct ArgusVlanStruct *vlan = (struct ArgusVlanStruct *) farhdr; vlan->status &= ~(ARGUS_SRC_CHANGED | ARGUS_DST_CHANGED); break; } case ARGUS_MPLS_DSR: { struct ArgusMplsStruct *mpls = (struct ArgusMplsStruct *) farhdr; mpls->status &= ~(ARGUS_SRC_CHANGED | ARGUS_DST_CHANGED); break; } case ARGUS_AGR_DSR: { struct ArgusAGRStruct *agr = (struct ArgusAGRStruct *) farhdr; agr->count = 0; agr->act.n = 0; agr->act.minval = 0x7FFFFFFF; agr->act.meanval = 0; agr->act.stdev = 0; agr->act.maxval = 0; agr->idle.n = 0; agr->idle.minval = 0x7FFFFFFF; agr->idle.meanval = 0; agr->idle.stdev = 0; agr->idle.maxval = 0; break; } } if ((farlen = farhdr->length) == 0) break; if ((farhdr->type == ARGUS_SRCUSRDATA_DSR) || (farhdr->type == ARGUS_DSTUSRDATA_DSR)) farlen = farlen * 4; length -= farlen; farhdr = (struct ArgusFarHeaderStruct *)((char *)farhdr + farlen); } } data->agr.count = 0; data->agr.act.n = 0; data->agr.act.meanval = 0; data->agr.act.stdev = 0; data->agr.act.maxval = 0; data->agr.act.minval = 0x7FFFFFFF; data->agr.idle.n = 0; data->agr.idle.meanval = 0; data->agr.idle.stdev = 0; data->agr.idle.maxval = 0; data->agr.idle.minval = 0x7FFFFFFF; data->act.n = 0; data->act.sumtime = 0; data->act.sumsqrd = 0; data->idle.n = 0; data->idle.sumtime = 0; data->idle.sumtime = 0; data->argus->ahdr.status &= ~ARGUS_MERGED; data->status &= ~RA_MODIFIED; } } } store->qhdr.logtime = ArgusGlobalTime; #ifdef ARGUSDEBUG ArgusDebug (4, "RaSendArgusRecord(0x%x) done.\n", store); #endif return (retn); } argus-clients-2.0.6.fixes.1/clients/ragator.h0000664000076600007660000000221507640476616014543 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 RaGator_h #define RaGator_h #include #include #include #include #include #include #include #include void RaProcessQueue(struct RaQueueStruct *, unsigned char state); #endif argus-clients-2.0.6.fixes.1/clients/rahosts.c0000664000076600007660000003417607640610353014561 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * rahosts - argus data client that printouts the unique IP addrs in * in data stream. * * written by Carter Bullard * QoSient, LLC * */ #include #include #define RAMAP_ETHER_MAC_ADDR 0x1 #define RAMAP_IP_ADDR 0x10 struct RaMapHashTableStruct { int size; struct RaMapHashTableHeader **array; }; struct RaMapHashTableHeader { struct ArgusQueueHeader qhdr; struct RaMapHashTableHeader *nxt, *prv; unsigned int hash; int type, len, value, mask; struct RaClassNets *net; void *obj, *sub; }; struct RaMapHashTableHeader *RaMapFindHashObject (struct RaMapHashTableStruct *, void *, int, int); struct RaMapHashTableHeader *RaMapAddHashEntry (struct RaMapHashTableStruct *, void *, int, int); void RaMapRemoveHashEntry (struct RaMapHashTableStruct *, struct RaMapHashTableHeader *); unsigned int RaMapCalcHash (void *, int, int); int RaSortThisDataRoutine (const void *, const void *); void RaSortThisQueue (struct RaQueueStruct *); struct RaQueueStruct *RaMapEtherAddrQueue = NULL; struct RaQueueStruct *RaMapIPAddrQueue = NULL; struct RaMapHashTableStruct RaMapHashTable; #define MAX_OBJ_SIZE 1024 int RaInitialized = 0; unsigned int RaMapHash = 0; unsigned int RaHashSize = 0; #define ARGUS_TRACK_CLASS_ADDR 1 #define ARGUS_TRACK_CLASS_AADDR 2 #define ARGUS_TRACK_CLASS_BADDR 3 #define ARGUS_TRACK_CLASS_CADDR 4 int ArgusTrackClassAddrs = 0; int ArgusTrackIPAddrs = 0; int ArgusTrackMacAddrs = 0; void ArgusClientInit () { struct ArgusModeStruct *mode; if (!(RaInitialized)) { RaWriteOut = 0; RaCumulativeMerge = 1; bzero ((char *) RaPrintAlgorithms, sizeof(RaPrintAlgorithms)); RaHashSize = 0x10000; if ((RaMapHashTable.array = (struct RaMapHashTableHeader **) ArgusCalloc (RaHashSize, sizeof (struct RaMapHashTableHeader))) == NULL) ArgusLog (LOG_ERR, "RaMapInit: ArgusCalloc error %s\n", strerror(errno)); RaMapHashTable.size = RaHashSize; if ((mode = ArgusModeList) != NULL) { while (mode) { if (!(strcasecmp (mode->mode, "ether"))) { ArgusTrackMacAddrs++; } else if (!(strcasecmp (mode->mode, "ip"))) { ArgusTrackIPAddrs++; } else if (!(strcasecmp (mode->mode, "all"))) { ArgusTrackMacAddrs++; ArgusTrackIPAddrs++; } if (!(strcasecmp (mode->mode, "class"))) ArgusTrackClassAddrs = ARGUS_TRACK_CLASS_ADDR; else if (!(strcasecmp (mode->mode, "classA"))) ArgusTrackClassAddrs = ARGUS_TRACK_CLASS_AADDR; else if (!(strcasecmp (mode->mode, "classB"))) ArgusTrackClassAddrs = ARGUS_TRACK_CLASS_BADDR; else if (!(strcasecmp (mode->mode, "classC"))) ArgusTrackClassAddrs = ARGUS_TRACK_CLASS_CADDR; mode = mode->nxt; } } if (!(ArgusTrackIPAddrs || ArgusTrackMacAddrs)) ArgusTrackIPAddrs++; } } int RaParseCompleting = 0; void RaParseComplete (int sig) { if ((sig >= 0) && (!RaParseCompleting)) { RaParseCompleting++; if (RaMapEtherAddrQueue) { struct RaMapHashTableHeader *retn = NULL; RaSortThisQueue(RaMapEtherAddrQueue); while ((retn = (struct RaMapHashTableHeader *) RaPopQueue(RaMapEtherAddrQueue)) != NULL) fprintf (stdout, "%s\n", etheraddr_string (retn->obj)); } if (RaMapIPAddrQueue) { struct RaMapHashTableHeader *retn = NULL; RaSortThisQueue(RaMapIPAddrQueue); while ((retn = (struct RaMapHashTableHeader *) RaPopQueue(RaMapIPAddrQueue)) != NULL) fprintf (stdout, "%s\n", ipaddr_string (retn->obj)); } fflush (stdout); } } void ArgusClientTimeout () { } void parse_arg (int argc, char**argv) { } void usage () { extern char version[]; fprintf (stderr, "Ratemplate Version %s\n", version); fprintf (stderr, "usage: %s \n", ArgusProgramName); fprintf (stderr, "usage: %s [options] -S remoteServer [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "usage: %s [options] -r argusDataFile [- filter-expression]\n\n", ArgusProgramName); fprintf (stderr, "options: -b dump packet-matching code.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); fprintf (stderr, " -D specify debug level\n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -n don't convert numbers to names.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [mm/dd[/yy].]hh[:mm[:ss]]\n"); fprintf (stderr, " mm/dd[/yy]\n"); fprintf (stderr, " -%%d{yMhdms}\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif exit(1); } void RaProcessRecord (struct ArgusRecord *argus) { if (argus->ahdr.type & ARGUS_MAR) { } else { if (ArgusTrackMacAddrs && (ArgusThisFarStatus & ARGUS_MAC_DSR_STATUS)) { struct ArgusMacStruct *mac = (struct ArgusMacStruct *) ArgusThisFarHdrs[ARGUS_MAC_DSR_INDEX]; RaMapInventory (&mac->phys_union.ether.ethersrc, RAMAP_ETHER_MAC_ADDR, 6); RaMapInventory (&mac->phys_union.ether.etherdst, RAMAP_ETHER_MAC_ADDR, 6); } if (ArgusTrackIPAddrs) { RaMapInventory((unsigned char *)&argus->argus_far.flow.ip_flow.ip_src, RAMAP_IP_ADDR, 4); RaMapInventory((unsigned char *)&argus->argus_far.flow.ip_flow.ip_dst, RAMAP_IP_ADDR, 4); } } } int RaSendArgusRecord(struct ArgusRecordStore *argus) {return 0;} #include void RaMapInventory (void *oid, int type, int len) { struct RaMapHashTableHeader *retn = NULL; unsigned int addr = *(unsigned int *)oid; if (ArgusTrackClassAddrs) { switch (ArgusTrackClassAddrs) { case ARGUS_TRACK_CLASS_ADDR: if (IN_CLASSA(addr)) addr &= IN_CLASSA_NET; else if (IN_CLASSB(addr)) addr &= IN_CLASSB_NET; else if (IN_CLASSC(addr)) addr &= IN_CLASSC_NET; break; case ARGUS_TRACK_CLASS_AADDR: addr &= IN_CLASSA_NET; break; case ARGUS_TRACK_CLASS_BADDR: addr &= IN_CLASSB_NET; break; case ARGUS_TRACK_CLASS_CADDR: addr &= IN_CLASSC_NET; break; } *(unsigned int *)oid = addr; } if (!(retn = RaMapFindHashObject (&RaMapHashTable, oid, type, len))) { if (!(retn = RaMapAddHashEntry (&RaMapHashTable, oid, type, len))) ArgusLog (LOG_ERR, "RaMapInventory: RaMapAddHashEntry error %s\n", strerror(errno)); switch (type) { case RAMAP_ETHER_MAC_ADDR: { if (!(RaMapEtherAddrQueue)) if ((RaMapEtherAddrQueue = RaNewQueue()) == NULL) ArgusLog (LOG_ERR, "RaNewQueue: error %s\n", strerror(errno)); RaAddToQueue(RaMapEtherAddrQueue, &retn->qhdr); break; } case RAMAP_IP_ADDR: { if (!(RaMapIPAddrQueue)) if ((RaMapIPAddrQueue = RaNewQueue()) == NULL) ArgusLog (LOG_ERR, "RaNewQueue: error %s\n", strerror(errno)); RaAddToQueue(RaMapIPAddrQueue, &retn->qhdr); break; } } } #ifdef ARGUSDEBUG ArgusDebug (3, "RaMapInventory (0x%x, %d, %d) returning\n", oid, type, len); #endif } unsigned int RaMapCalcHash (void *obj, int type, int len) { u_char buf[MAX_OBJ_SIZE]; unsigned int retn = 0; switch (type) { case RAMAP_ETHER_MAC_ADDR: len = 6; break; case RAMAP_IP_ADDR: len = 4; break; default: break; } bzero (buf, sizeof buf); if (RaHashSize <= 0x100) { unsigned char hash = 0, *ptr = (unsigned char *) buf; int i, nitems = len; bcopy ((char *) obj, (char *)&buf, len); for (i = 0; i < nitems; i++) hash += *ptr++; retn = hash; } else if (RaHashSize <= 0x10000) { unsigned short hash = 0, *ptr = (unsigned short *) buf; int i, nitems = (len / sizeof(unsigned short)) + 2; bcopy ((char *) obj, &buf[1], len); for (i = 0; i < nitems; i++) hash += *ptr++; retn = hash; } else { unsigned int hash = 0, *ptr = (unsigned int *) buf; int i, nitems = (len /sizeof(unsigned int)) + 2; bcopy ((char *) obj, &buf[3], len); for (i = 0; i < nitems; i++) hash += *ptr++; retn = hash; } return (retn); } struct RaMapHashTableHeader * RaMapFindHashObject (struct RaMapHashTableStruct *table, void *obj, int type, int len) { struct RaMapHashTableHeader *retn = NULL, *head = NULL, *target; int RaMapHash = 0; RaMapHash = RaMapCalcHash (obj, type, len); if ((target = table->array[RaMapHash % table->size]) != NULL) { head = target; do { if ((type == target->type) && (len == target->len)) { if (!(bcmp ((char *) obj, (char *) target->obj, len))) { retn = target; break; } } target = target->nxt; } while (target != head); } #ifdef TCPCLEANDEBUG RaMapDebug (6, "RaMapFindHashEntry () returning 0x%x RaMapHash %d\n", retn, RaMapHash); #endif return (retn); } struct RaMapHashTableHeader * RaMapAddHashEntry (struct RaMapHashTableStruct *table, void *oid, int type, int len) { struct RaMapHashTableHeader *retn = NULL, *start = NULL; if ((retn = (struct RaMapHashTableHeader *) ArgusCalloc (1, sizeof (struct RaMapHashTableHeader))) != NULL) { RaMapHash = RaMapCalcHash (oid, type, len); retn->hash = RaMapHash; retn->type = type; retn->len = len; if ((retn->obj = (void *) ArgusCalloc (1, len)) == NULL) ArgusLog (LOG_ERR, "RaMapAddHashEntry: ArgusCalloc error %s\n", strerror(errno)); else bcopy ((char *) oid, (char *)retn->obj, len); if ((start = table->array[RaMapHash % table->size]) != NULL) { retn->nxt = start; retn->prv = start->prv; retn->prv->nxt = retn; retn->nxt->prv = retn; } else retn->prv = retn->nxt = retn; table->array[RaMapHash % table->size] = retn; } #ifdef TCPCLEANDEBUG RaMapDebug (3, "RaMapAddHashEntry (0x%x, %d, %d) returning 0x%x\n", oid, type, len, retn); #endif return (retn); } void RaMapRemoveHashEntry (struct RaMapHashTableStruct *table, struct RaMapHashTableHeader *htblhdr) { unsigned short hash = htblhdr->hash; htblhdr->prv->nxt = htblhdr->nxt; htblhdr->nxt->prv = htblhdr->prv; if (htblhdr == table->array[hash % table->size]) { if (htblhdr == htblhdr->nxt) table->array[hash % table->size] = NULL; else table->array[hash % table->size] = htblhdr->nxt; } ArgusFree (htblhdr); #ifdef TCPCLEANDEBUG RaMapDebug (6, "RaMapRemoveHashEntry (0x%x) returning\n", htblhdr); #endif } int RaSortThisDataRoutine (const void *void1, const void *void2) { struct RaMapHashTableHeader *data1 = *(struct RaMapHashTableHeader **)void1; struct RaMapHashTableHeader *data2 = *(struct RaMapHashTableHeader **)void2; int retn = 0; if (data1->type == data2->type) switch (data1->type) { case RAMAP_ETHER_MAC_ADDR: retn = bcmp((char *)data2->obj, (char *)data1->obj, data1->len); break; case RAMAP_IP_ADDR: { unsigned int addr1, addr2; addr1 = *(unsigned int *)data1->obj; addr2 = *(unsigned int *)data2->obj; retn = (addr2 > addr1) ? 1 : ((addr2 == addr1) ? 0 : -1); break; } } return (retn); } void RaSortThisQueue (struct RaQueueStruct *queue) { int i = 0, cnt = queue->count; struct ArgusQueueHeader *qhdr; if (queue->array != NULL) { ArgusFree(queue->array); queue->array = NULL; } if (cnt > 0) { if ((queue->array = (struct ArgusQueueHeader **) ArgusCalloc(sizeof(struct ArgusQueueHeader *), cnt + 1)) != NULL) { while ((qhdr = RaPopQueue(queue)) != NULL) { queue->array[i] = qhdr; i++; } qsort ((char *) queue->array, i, sizeof (struct ArgusQueueHeader *), RaSortThisDataRoutine); for (i = 0 ; i < cnt; i++) RaPushQueue(queue, queue->array[i]); ArgusFree(queue->array); queue->array = NULL; } else ArgusLog (LOG_ERR, "RaSortQueue: ArgusCalloc(%d, %d) %s\n", sizeof(struct ArgusRecord *), cnt, strerror(errno)); } } argus-clients-2.0.6.fixes.1/clients/rahosts.h0000664000076600007660000000251307640476616014570 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* rahosts.h */ #ifndef RaHosts_h #define RaHosts_h #include #include #include #include #include #include #include #include #include #include #include #ifndef MAXSTRLEN #define MAXSTRLEN 1024 #endif #ifndef MAXPATHNAMELEN #define MAXPATHNAMELEN BUFSIZ #endif void RaMapInventory(void *, int, int); #endif /* RaHosts_h */ argus-clients-2.0.6.fixes.1/clients/ramon.c0000664000076600007660000011635707725253026014220 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * ramon - argus RMON group support. * * written by Carter Bullard * QoSient, LLC * */ #include #include #include #include void RaProcessSrvRecord (struct ArgusServiceRecord *); int RaInitialized = 0; int RaTimeout = 0x1FFFFFFF; int RaIdleTimeout = 0; int RaTopNModel = 0; int RaPrintMACAddress = 0; char *RaMonTopNModelString = "Model 200 ip %s 0.0.0.0 no no no"; char *RaMonMatrixModelString = "Model 200 ip %s %s no no no"; char *RaMonHostPModelString = "Model 200 ip %s 0.0.0.0 yes no no"; char *RaMonHostSvcModelString = "Model 200 ip %s 0.0.0.0 yes no yes"; char *RaMonMatrixFlowModelFile [] = { "Flow 100 ip * * * * * 200 3153600 3153600", "Model 200 ip 255.255.255.255 255.255.255.255 no no no", NULL, }; char *RaMonTopNFlowModelFile [] = { "Flow 100 ip * * * * * 200 3153600 3153600", "Model 200 ip 255.255.255.255 0.0.0.0 no no no", NULL, }; char *RaMonServicesFlowModelFile [] = { "Flow 10 ip * * tcp 20 * 100 3153600 3153600", "Flow 100 ip * * * * * 200 3153600 3153600", "Model 100 ip 0.0.0.0 0.0.0.0 yes yes yes", "Model 200 ip 0.0.0.0 0.0.0.0 yes no yes", NULL, }; char *RaMonHostProtoFlowModelFile [] = { "Flow 100 ip * * * * * 200 0 0", "Model 200 ip 255.255.255.255 0.0.0.0 yes no no", NULL, }; char *RaMonHostSvcFlowModelFile [] = { "Flow 100 ip * * * * * 200 0 0", "Model 200 ip 255.255.255.255 0.0.0.0 yes no yes", NULL, }; struct RaFlowModelStruct *RaFlowModel = NULL; int RaNetMode = 0; int RaMonMode = 0; int RaMonMask = 0; #define RAMON_TOPN 1 #define RAMON_MATRIX 2 #define RAMON_SVCS 3 #define RAMON_HOSTP 4 #define RAMON_HOSTSVC 5 extern int RaFlowMajorModified; void ArgusClientInit () { struct ArgusModeStruct *mode; char buf[MAXSTRLEN], *ptr = NULL; int i, x; if (!(RaInitialized)) { RaWriteOut = 0; RaCumulativeMerge = 1; hfield = 17; pfield = 8; (void) signal (SIGHUP, (void (*)(int)) RaParseComplete); (void) signal (SIGTERM, (void (*)(int)) RaParseComplete); (void) signal (SIGQUIT, (void (*)(int)) RaParseComplete); (void) signal (SIGINT, (void (*)(int)) RaParseComplete); bzero ((char *) buf, sizeof(buf)); bzero ((char *) RaPrintAlgorithms, sizeof(RaPrintAlgorithms)); if ((mode = ArgusModeList) == NULL) usage(); while (mode) { if (!(strcasecmp (mode->mode, "TopN"))) { ArgusFlowModelFile = *RaMonTopNFlowModelFile; RaTopNModel++; RaMonMode = RAMON_TOPN; bzero ((char *) RaPrintAlgorithms, sizeof(RaPrintAlgorithms)); RaPrintAlgorithms[0] = ArgusPrintStartDate; RaPrintAlgorithms[1] = ArgusPrintSrcAddr; RaPrintAlgorithms[2] = ArgusPrintCounts; RaPrintAlgorithms[3] = ArgusPrintBytes; } else if (!(strcasecmp (mode->mode, "Matrix"))) { RaMonMode = RAMON_MATRIX; ArgusFlowModelFile = *RaMonMatrixFlowModelFile; RaPrintAlgorithms[0] = ArgusPrintStartDate; RaPrintAlgorithms[1] = ArgusPrintSrcAddr; RaPrintAlgorithms[2] = ArgusPrintDstAddr; RaPrintAlgorithms[3] = ArgusPrintCounts; RaPrintAlgorithms[4] = ArgusPrintBytes; } else if (!(strcasecmp (mode->mode, "Svc"))) { RaMonMode = RAMON_SVCS; ArgusFlowModelFile = *RaMonMatrixFlowModelFile; RaPrintAlgorithms[0] = ArgusPrintStartDate; RaPrintAlgorithms[1] = ArgusPrintProto; RaPrintAlgorithms[2] = ArgusPrintDstPort; RaPrintAlgorithms[3] = ArgusPrintCounts; RaPrintAlgorithms[4] = ArgusPrintBytes; pfield = 16; } else if (!(strcasecmp (mode->mode, "HostProto"))) { RaTopNModel++; RaMonMode = RAMON_HOSTP; ArgusFlowModelFile = *RaMonHostProtoFlowModelFile; RaPrintAlgorithms[0] = ArgusPrintStartDate; RaPrintAlgorithms[1] = ArgusPrintSrcAddr; RaPrintAlgorithms[2] = ArgusPrintProto; RaPrintAlgorithms[3] = ArgusPrintCounts; RaPrintAlgorithms[4] = ArgusPrintBytes; } else if (!(strcasecmp (mode->mode, "HostSvc"))) { RaTopNModel++; RaMonMode = RAMON_HOSTSVC; ArgusFlowModelFile = *RaMonHostSvcFlowModelFile; RaPrintAlgorithms[0] = ArgusPrintStartDate; RaPrintAlgorithms[1] = ArgusPrintSrcAddr; RaPrintAlgorithms[2] = ArgusPrintProto; RaPrintAlgorithms[3] = ArgusPrintDstPort; RaPrintAlgorithms[4] = ArgusPrintCounts; RaPrintAlgorithms[5] = ArgusPrintBytes; } if (!(strncasecmp (mode->mode, "Net", 3))) { if ((ptr = strchr (mode->mode, '/')) != NULL) if (sscanf(&ptr[1], "%d", &RaMonMask) != 1) usage(); RaNetMode++; } mode = mode->nxt; } if (!RaNetMode) RaMonMask = 32; switch (RaMonMode) { case RAMON_TOPN: { char addrstr[128]; if (RaMonMask != 0) { sprintf (addrstr, "255.255.255.255/%d", RaMonMask); } else sprintf (addrstr, "class"); sprintf (buf, RaMonTopNModelString, addrstr); RaMonTopNFlowModelFile [1] = strdup(buf); RaFlowModel = RaReadFlowModelFile (RaMonTopNFlowModelFile); break; } case RAMON_MATRIX: { char addrstr[128]; if (RaMonMask != 0) { sprintf (addrstr, "255.255.255.255/%d", RaMonMask); } else sprintf (addrstr, "class"); sprintf (buf, RaMonMatrixModelString, addrstr, addrstr); RaMonTopNFlowModelFile [1] = strdup(buf); RaFlowModel = RaReadFlowModelFile (RaMonMatrixFlowModelFile); break; } case RAMON_SVCS: RaFlowModel = RaReadFlowModelFile (RaMonServicesFlowModelFile); break; case RAMON_HOSTP: { char addrstr[128]; if (RaMonMask != 0) { sprintf (addrstr, "255.255.255.255/%d", RaMonMask); } else sprintf (addrstr, "class"); sprintf (buf, RaMonHostPModelString, addrstr); RaMonHostProtoFlowModelFile [1] = strdup(buf); RaFlowModel = RaReadFlowModelFile (RaMonHostProtoFlowModelFile); RaFlowModel->preserve = 0; break; } case RAMON_HOSTSVC: { char addrstr[128]; if (RaMonMask != 0) { sprintf (addrstr, "255.255.255.255/%d", RaMonMask); } else sprintf (addrstr, "class"); sprintf (buf, RaMonHostSvcModelString, addrstr); RaMonHostSvcFlowModelFile [1] = strdup(buf); RaFlowModel = RaReadFlowModelFile (RaMonHostSvcFlowModelFile); RaFlowModel->preserve = 0; break; } default: break; } if (RaFlowModel == NULL) usage(); if ((RaModelerQueue = RaNewQueue()) == NULL) exit(0); if ((RaHashTable.array = (struct RaHashTableHeader **) ArgusCalloc (RA_HASHTABLESIZE, sizeof (struct RaHashTableHeader *))) != NULL) RaHashTable.size = RA_HASHTABLESIZE; if (Hflag) { RaHistoTimeSeries = ARGUS_TIMESERIES; } if (Bflag) { if ((RaHoldingBuffer = (struct ArgusHoldingBuffer *) ArgusCalloc (1, sizeof(*RaHoldingBuffer))) != NULL) { if ((RaHoldingBuffer->array = (struct ArgusListStruct **) ArgusCalloc (Bflag, sizeof(void *))) != NULL) { RaHoldingBuffer->size = Bflag; } else { ArgusFree (RaHoldingBuffer); RaHoldingBuffer = NULL; exit (-1); } } else exit (-1); } bzero ((char *) RaSortAlgorithms, sizeof(RaSortAlgorithms)); if (RaSOptionIndex > 0) { for (i = 0; i < ARGUS_MAX_S_OPTIONS; i++) { if (RaSOptionStrings[i] != NULL) { for (x = 0; x < MAX_SORT_ALG_TYPES; x++) { if (!strncmp (RaSortKeyWords[x], RaSOptionStrings[i], strlen(RaSortKeyWords[x]))) { RaSortAlgorithms[i] = RaSortAlgorithmTable[x]; break; } } if (x == MAX_SORT_ALG_TYPES) ArgusLog (LOG_ERR, "sort syntax error. \'%s\' not supported", RaSOptionStrings[i]); } else break; } } else RaSortAlgorithms[0] = RaSortAlgorithmTable[RASORTPKTSCOUNT]; RaInitialized++; } } int RaParseCompleting = 0; void RaParseComplete (int sig) { int i; if ((sig >= 0) && (!RaParseCompleting)) { RaParseCompleting++; if (ArgusInput != NULL) { ArgusInput->ArgusManStart.ahdr.type |= ARGUS_RMON; if (Nflag == 0) Nflag = RaModelerQueue->count; if (Nflag > 0) { RaSortQueue (RaModelerQueue); Nflag = (Nflag > RaModelerQueue->count) ? RaModelerQueue->count : Nflag; for (i = 0; i < Nflag; i++) { if (RaModelerQueue->array[i] != NULL) RaSendArgusRecord ((struct ArgusRecordStore *) RaModelerQueue->array[i]); } } } } #ifdef ARGUSDEBUG ArgusDebug (1, "RaParseComplete: returning\n"); #endif } void ArgusClientTimeout () { RaProcessQueue (RaModelerQueue, ARGUS_STATUS); #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusClientTimeout: current time %s.\n", print_time(&ArgusGlobalTime)); if (ArgusMinuteUpdate++ == 60) { ArgusDebug (2, "ArgusClientTimeout: current time %s HashHdrs %d Hash %d Queue %d\n", print_time(&ArgusGlobalTime), RaAllocHashTableHeaders, RaHashTable.count, RaModelerQueue->count); ArgusMinuteUpdate = 1; } if (ArgusHourlyUpdate++ == 3600) { ArgusDebug (2, "ArgusClientTimeout: current time %s.\n", print_time(&ArgusGlobalTime)); ArgusHourlyUpdate = 1; } #endif } void parse_arg (int argc, char**argv) { } void usage () { extern char version[]; fprintf (stderr, "Ramon Version %s\n", version); fprintf (stderr, "usage: %s -M mode [-f flowfile]\n", ArgusProgramName); fprintf (stderr, "usage: %s -M mode [-f flowfile] [ra-options] [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "options: -M specify TopN, Matrix, Svc, HostProto, or HostSvc mode, modify with Net.\n"); fprintf (stderr, " -f read flow model from .\n"); fprintf (stderr, "ra-options: -a print record summaries on termination.\n"); fprintf (stderr, " -A print application bytes.\n"); fprintf (stderr, " -b dump packet-matching code.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); fprintf (stderr, " -D specify debug level\n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -n don't convert numbers to names.\n"); fprintf (stderr, " -p print fractional time with precision.\n"); fprintf (stderr, " -q quiet mode. don't print record outputs.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -R print out response data when availabile.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [mm/dd[/yy].]hh[:mm[:ss]]\n"); fprintf (stderr, " mm/dd[/yy]\n"); fprintf (stderr, " -%%d{yMhdms}\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); fprintf (stderr, " -u print time in Unix time format.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif fprintf (stderr, " -w write output to . '-' denotes stdout.\n"); fprintf (stderr, " -z print Argus TCP state changes.\n"); fprintf (stderr, " -Z print actual TCP flag values.<'s'rc | 'd'st | 'b'oth>\n"); exit(1); } void RaProcessRecord (struct ArgusRecord *argus) { if (argus->ahdr.type & ARGUS_MAR) RaProcessManRecord (argus); else { switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: RaProcessTCPRecord (argus); break; case IPPROTO_UDP: RaProcessUDPRecord (argus); break; case IPPROTO_ICMP: RaProcessICMPRecord (argus); break; default: RaProcessIPRecord (argus); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: RaProcessARPRecord (argus); break; default: RaProcessNonIPRecord (argus); break; } } } struct ArgusRecord * RaRmonArgusRecord (struct ArgusRecord *); void RaProcessThisSrvRecord (struct ArgusServiceRecord *); void RaCreateEtherFlow (struct ArgusRecord *); void RaModifyEtherFlow(struct ArgusRecord *); void RaModifyEtherFlow (struct ArgusRecord *argus) { struct ArgusFlow *flow = &argus->argus_far.flow; bzero ((char *) &flow->mac_flow.ehdr.ether_dhost, 6); } void RaCreateEtherFlow (struct ArgusRecord *argus) { struct ArgusFlow *flow = &argus->argus_far.flow; struct ArgusMacStruct *mac = NULL; struct ArgusETHERObject *ether = NULL; if (ArgusThisFarStatus & ARGUS_MAC_DSR_STATUS) { if ((mac = (struct ArgusMacStruct *) ArgusThisFarHdrs[ARGUS_MAC_DSR_INDEX]) != NULL) { ether = &mac->ether_mac; bzero ((char *) flow, sizeof(*flow)); bcopy ((char *) ether, (char *) &flow->mac_flow.ehdr, 12); argus->ahdr.status &= ~0xFFFF; } } else { ArgusLog (LOG_ERR, "ether addrs not present"); } } struct ArgusRecord * RaRmonArgusRecord (struct ArgusRecord *argus) { struct ArgusRecord *retn = NULL; struct ArgusMeter meter; struct ArgusFlow *flow1, *flow2; struct ArgusFarHeaderStruct *a1farhdr[32], *a2farhdr[32]; unsigned int a1DSRStatus = 0, a2DSRStatus = 0; if (RaPrintMACAddress) RaCreateEtherFlow (argus); if ((retn = RaCopyArgusRecord (argus)) != NULL) { a1DSRStatus = ArgusIndexRecord (argus, a1farhdr); a2DSRStatus = ArgusIndexRecord (retn, a2farhdr); flow1 = &argus->argus_far.flow; flow2 = &retn->argus_far.flow; switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: flow2->ip_flow.ip_src = flow1->ip_flow.ip_dst; flow2->ip_flow.ip_dst = flow1->ip_flow.ip_src; switch (flow1->ip_flow.ip_p) { case IPPROTO_UDP: case IPPROTO_TCP: flow2->ip_flow.sport = flow1->ip_flow.dport; flow2->ip_flow.dport = flow1->ip_flow.sport; break; } meter = argus->argus_far.src; argus->argus_far.src = argus->argus_far.dst; argus->argus_far.dst = meter; break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: break; default: bcopy ((char *)&flow1->mac_flow.ehdr.ether_dhost, (char *)&flow2->mac_flow.ehdr.ether_shost, 6); bzero ((char *)&flow1->mac_flow.ehdr.ether_dhost, 6); bzero ((char *)&flow2->mac_flow.ehdr.ether_dhost, 6); meter = retn->argus_far.src; retn->argus_far.src = retn->argus_far.dst; retn->argus_far.dst = meter; break; } if ((a1DSRStatus & ARGUS_MAC_DSR_STATUS) && (a2DSRStatus & ARGUS_MAC_DSR_STATUS)) { struct ArgusMacStruct *mac1 = NULL, *mac2 = NULL; mac1 = (struct ArgusMacStruct *) a1farhdr[ARGUS_MAC_DSR_INDEX]; mac2 = (struct ArgusMacStruct *) a2farhdr[ARGUS_MAC_DSR_INDEX]; bcopy ((char *)&mac2->ether_mac.etherdst, (char *)&mac1->ether_mac.ethersrc, 6); bzero ((char *)&mac1->ether_mac.etherdst, 6); bzero ((char *)&mac2->ether_mac.etherdst, 6); } retn->ahdr.type |= ARGUS_RMON; argus->ahdr.type |= ARGUS_RMON; } return (retn); } void RaProcessThisSrvRecord (struct ArgusServiceRecord *srv) { struct ArgusRecord *arg2 = NULL; if (RaTopNModel) { arg2 = RaRmonArgusRecord(srv->argus); RaProcessSrvRecord(srv); srv->argus = arg2; RaProcessSrvRecord(srv); ArgusFree(arg2); } else RaProcessSrvRecord(srv); } void RaProcessSrvRecord (struct ArgusServiceRecord *srv) { struct ArgusRecord *argus = srv->argus; struct ArgusRecordStore *store; struct RaPolicyStruct *rap; struct ArgusFlow *flow = &argus->argus_far.flow; RaThisActiveDuration = RaGetActiveDuration(argus); if (Hflag) { RaThisActiveIndex = (RaThisActiveDuration < 100) ? 0 : (RaThisActiveDuration < 500) ? 1 : (RaThisActiveDuration < 1000) ? 2 : (RaThisActiveDuration < 5000) ? 3 : (RaThisActiveDuration < 10000) ? 4 : (RaThisActiveDuration < 50000) ? 4 : (RaThisActiveDuration < 100000) ? 5 : (RaThisActiveDuration < 500000) ? 6 : (RaThisActiveDuration < 100000) ? 7 : (RaThisActiveDuration < 250000) ? 8 : (RaThisActiveDuration < 500000) ? 9 : (RaThisActiveDuration < 750000) ? 10: (RaThisActiveDuration < 1000000) ? 11: (RaThisActiveDuration < 5000000) ? 12: (RaThisActiveDuration < 10000000) ? 13: (RaThisActiveDuration < 50000000) ? 14: 15; } else RaThisActiveIndex = 0; bcopy((char *) flow, (char *) RaArgusFlow, sizeof(struct ArgusFlow)); if (!(RaPrintMACAddress)) { if ((rap = RaFlowModelOverRides(argus, RaFlowModel)) != NULL) { RaModifyFlow(rap, argus, RaFlowModel); RaTimeout = rap->ArgusTimeout; RaIdleTimeout = rap->ArgusIdleTimeout; } else { RaModifyDefaultFlow(argus); } } else RaModifyEtherFlow(argus); if ((store = RaFindArgusRecord(&RaHashTable, argus)) == NULL) { } if (store) { RaThisArgusStore = store; RaCheckTimeout (store, argus); if ((srv->status & RA_SVCTEST) != (store->status & RA_SVCTEST)) { RaSendArgusRecord(store); store->status &= ~RA_SVCTEST; store->status |= (srv->status & RA_SVCTEST); } if (!(store->data[RaThisActiveIndex])) { struct ArgusRecordData *data = NULL; if ((data = RaNewArgusData(argus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; data->status |= srv->status & RA_SVCTEST; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *)&data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } store->data[RaThisActiveIndex] = data; } else ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); } else RaMergeArgusRecord(argus, store, RaThisActiveIndex); RaUpdateArgusStore(argus, store); } else { if ((store = RaNewArgusStore(argus)) != NULL) { struct ArgusRecordData *data = NULL; store->ArgusTimeout = RaTimeout; store->ArgusIdleTimeout = RaIdleTimeout; RaThisArgusStore = store; store->status |= RA_MODIFIED; store->status |= srv->status & RA_SVCTEST; if ((data = RaNewArgusData(argus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *)&data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } store->data[RaThisActiveIndex] = data; if ((store->rahtblhdr = RaAddHashEntry (&RaHashTable, store)) != NULL) RaAddToQueue(RaModelerQueue, &store->qhdr); } else ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); } else ArgusLog (LOG_ERR, "RaNewArgusStore failed %s\n", strerror(errno)); } RaIdleTimeout = 0; #ifdef ARGUSDEBUG ArgusDebug (7, "RaProcessSrvRecord: done\n"); #endif } void RaProcessManRecord (struct ArgusRecord *argus) { unsigned int status; struct ArgusRecord *initCon = &ArgusInput->ArgusInitCon; initCon->ahdr.type |= ARGUS_RMON; status = ntohl(initCon->ahdr.status); if (RaTopNModel) status |= ARGUS_TOPN; else status |= ARGUS_MATRIX; initCon->ahdr.status = htonl(status); } struct ArgusServiceRecord ArgusThisSrv; void RaProcessTCPRecord (struct ArgusRecord *argus) { struct ArgusTCPObject *tcp = NULL; ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Vflag) { if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) { if ((tcp = (struct ArgusTCPObject *) ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]) != NULL) { if (tcp->state & (ARGUS_SAW_SYN || ARGUS_SAW_SYN_SENT)) { if (tcp->state & ARGUS_RESET) { if (tcp->state & ARGUS_DST_RESET) if (argus->argus_far.src.count && argus->argus_far.dst.count) if (!(argus->argus_far.src.bytes && argus->argus_far.dst.bytes)) ArgusThisSrv.status = RA_SVCFAILED; if (tcp->state & ARGUS_SRC_RESET) if (argus->argus_far.src.count && !(argus->argus_far.dst.count)) ArgusThisSrv.status = RA_SVCFAILED; } } if (tcp->state & ARGUS_TIMEOUT) if (argus->argus_far.src.count && !(argus->argus_far.dst.count)) ArgusThisSrv.status = RA_SVCFAILED; } } } RaProcessThisSrvRecord (&ArgusThisSrv); } void RaProcessICMPRecord (struct ArgusRecord *argus) { ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Vflag) { if ((argus->argus_far.src.count > 0) && (argus->argus_far.dst.count == 0)) { ArgusThisSrv.status = RA_SVCFAILED; } else { ArgusThisSrv.status = RA_SVCPASSED; } } RaProcessThisSrvRecord (&ArgusThisSrv); } void RaProcessUDPRecord (struct ArgusRecord *argus) { ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Vflag) { if ((argus->argus_far.src.count > 0) && (argus->argus_far.dst.count == 0)) { ArgusThisSrv.status = RA_SVCFAILED; } else { ArgusThisSrv.status = RA_SVCPASSED; } } if (argus->argus_far.flow.ip_flow.tp_p == ARGUS_RTP_FLOWTAG) if (!((argus->argus_far.src.count > 3) || (argus->argus_far.dst.count > 3))) argus->argus_far.flow.ip_flow.tp_p = 0; if (Rflag) if (!((argus->argus_far.src.count == 1) && (argus->argus_far.dst.count == 1))) ArgusThisSrv.status = RA_SVCFAILED; RaProcessThisSrvRecord (&ArgusThisSrv); } void RaProcessIPRecord (struct ArgusRecord *argus) { ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Vflag) { if ((argus->argus_far.src.count > 0) && (argus->argus_far.dst.count == 0)) { ArgusThisSrv.status = RA_SVCFAILED; } else { ArgusThisSrv.status = RA_SVCPASSED; } } if (Rflag) if (!((argus->argus_far.src.count == 1) && (argus->argus_far.dst.count == 1))) ArgusThisSrv.status = RA_SVCFAILED; RaProcessThisSrvRecord (&ArgusThisSrv); } void RaProcessARPRecord (struct ArgusRecord *argus) { ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Rflag) if (!((argus->argus_far.src.count == 1) && (argus->argus_far.dst.count == 1))) ArgusThisSrv.status = RA_SVCFAILED; RaProcessThisSrvRecord (&ArgusThisSrv); } void RaProcessNonIPRecord (struct ArgusRecord *argus) { ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; RaProcessThisSrvRecord (&ArgusThisSrv); } #include #include #define RA_MAXQSCAN 25000 #define RA_MAXQSIZE 250000 void RaProcessQueue(struct RaQueueStruct *queue, unsigned char status) { struct ArgusRecordStore *obj = NULL; int cnt = 0; switch (status) { case ARGUS_STOP: while ((obj = (struct ArgusRecordStore *) RaPopQueue(queue)) != NULL) RaTimeoutArgusStore(obj); break; default: while (queue->count > RA_MAXQSIZE) { obj = (struct ArgusRecordStore *) RaRemoveFromQueue(RaModelerQueue, RaModelerQueue->start->prv); RaTimeoutArgusStore(obj); } if ((cnt = ((queue->count > RA_MAXQSCAN) ? RA_MAXQSCAN : queue->count)) != 0) { while (cnt--) { if ((obj = (struct ArgusRecordStore *) RaPopQueue(queue)) != NULL) { if (RaCheckTimeout(obj, NULL)) RaTimeoutArgusStore(obj); else RaAddToQueue(queue, &obj->qhdr); } else cnt++; } } break; } #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessQueue (0x%x, %d) returning\n", queue, status); #endif } extern struct ArgusCanonicalRecord *RaThisCanon; int RaLabelCounter = 0; int RaSendArgusRecord(struct ArgusRecordStore *store) { unsigned char buf[MAXSTRLEN]; struct ArgusRecordData *data; struct ArgusRecord *argus = NULL; struct ArgusFarHeaderStruct *farhdr; struct ArgusAGRStruct *agr = NULL; int retn = 0, i; for (i = 0; i < RaHistoTimeSeries; i++) { if ((data = store->data[i]) != NULL) { argus = data->argus; if (!aflag) { #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif ArgusGenerateCanonicalRecord (argus, RaThisCanon); #ifdef _LITTLE_ENDIAN ArgusNtoH(argus); #endif if ((retn = argus_filter (ArgusFilterCode.bf_insns, RaThisCanon)) == 0) return (retn); } if (argus && (data->status & RA_MODIFIED)) { if (data->act.n > 0) { data->agr.act.n = data->act.n; data->agr.act.meanval = data->act.sumtime/data->act.n; data->agr.act.stdev = sqrt (data->act.sumsqrd/data->act.n - pow (data->act.sumtime/data->act.n, 2.0)); } if (data->idle.n > 0) { data->agr.idle.n = data->idle.n; data->agr.idle.meanval = data->idle.sumtime/data->idle.n; data->agr.idle.stdev = sqrt (data->idle.sumsqrd/data->idle.n - pow (data->idle.sumtime/data->idle.n, 2.0)); } ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) != NULL) bcopy ((char *)&data->agr, (char *)agr, data->agr.length); bcopy ((char *) argus, buf, argus->ahdr.length); argus = (struct ArgusRecord *) buf; ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) == NULL) { if (ArgusFlowModelFile && (data->agr.count > 1)) { bcopy ((char *)&data->agr, &buf[argus->ahdr.length], data->agr.length); argus->ahdr.length += data->agr.length; argus->ahdr.status |= ARGUS_MERGED; ArgusFree (data->argus); data->argus = RaCopyArgusRecord(argus); ArgusThisFarStatus = ArgusIndexRecord(data->argus, ArgusThisFarHdrs); } else { argus->ahdr.status &= ~(ARGUS_MERGED); } } if ((ArgusWfileList != NULL) && (!(ArgusListEmpty(ArgusWfileList)))) { struct ArgusWfileStruct *wfile = NULL, *start = NULL; if ((wfile = ArgusFrontList(ArgusWfileList)) != NULL) { start = wfile; do { if ((exceptfile == NULL) || strcmp(wfile->filename, exceptfile)) { #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif ArgusWriteNewLogfile (wfile, argus); #ifdef _LITTLE_ENDIAN ArgusNtoH(argus); #endif } ArgusPopFrontList(ArgusWfileList); ArgusPushBackList(ArgusWfileList, wfile); wfile = ArgusFrontList(ArgusWfileList); } while (wfile != start); } } else { if (argus->ahdr.type & ARGUS_MAR) printf ("%s\n", get_man_string (argus)); else { if (Lflag && !(qflag)) { if (RaLabel == NULL) RaLabel = RaGenerateLabel(argus); if (!(RaLabelCounter++ % Lflag)) { printf ("%s\n", RaLabel); fflush (stdout); } if (Lflag < 0) Lflag = 0; } ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: { int srcportind = 0; if (argus->argus_far.flow.ip_flow.sport == 20) { if (RaPrintAlgorithms[3] == ArgusPrintDstPort) { RaPrintAlgorithms[3] = ArgusPrintSrcPort; srcportind++; } } printf ("%s", get_tcp_string (argus)); if (srcportind) RaPrintAlgorithms[3] = ArgusPrintDstPort; break; } case IPPROTO_ICMP: printf ("%s", get_icmp_string (argus)); break; default: printf ("%s", get_ip_string (argus)); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: printf ("%s", get_arp_string (argus)); break; default: printf ("%s", get_nonip_string (argus)); break; } printf ("\n"); } fflush (stdout); } argus = data->argus; if (argus->ahdr.type & ARGUS_FAR) { int farlen, length = argus->ahdr.length - sizeof(argus->ahdr); farhdr = (struct ArgusFarHeaderStruct *)((char *)argus + sizeof(argus->ahdr)); while (length > 0) { switch (farhdr->type) { case ARGUS_FAR: { struct ArgusFarStruct *far = (struct ArgusFarStruct *) farhdr; far->time.start.tv_sec = 0x7FFFFFFF; far->time.start.tv_usec = 0; far->time.last.tv_sec = 0; far->time.last.tv_usec = 0; far->src.count = 0; far->src.bytes = 0; far->dst.count = 0; far->dst.bytes = 0; break; } case ARGUS_TCP_DSR: { struct ArgusTCPObject *tcp = (struct ArgusTCPObject *) farhdr; tcp->state = 0; tcp->src.seqbase = 0; tcp->src.ackbytes = 0; tcp->src.rpkts = 0; tcp->src.win = 0; tcp->src.flags = 0; tcp->dst.seqbase = 0; tcp->dst.ackbytes = 0; tcp->dst.rpkts = 0; tcp->dst.win = 0; tcp->dst.flags = 0; break; } case ARGUS_TIME_DSR: { struct ArgusTimeStruct *time = (struct ArgusTimeStruct *) farhdr; time->src.act.n = 0; time->src.act.meanval = 0; time->src.act.stdev = 0; time->src.act.maxval = 0; time->src.act.minval = 0x7FFFFFFF; time->src.idle.n = 0; time->src.idle.meanval = 0; time->src.idle.stdev = 0; time->src.idle.maxval = 0; time->src.idle.minval = 0x7FFFFFFF; time->dst.act.n = 0; time->dst.act.meanval = 0; time->dst.act.stdev = 0; time->dst.act.maxval = 0; time->dst.act.minval = 0x7FFFFFFF; time->dst.idle.n = 0; time->dst.idle.meanval = 0; time->dst.idle.stdev = 0; time->dst.idle.maxval = 0; time->dst.idle.minval = 0x7FFFFFFF; break; } case ARGUS_VLAN_DSR: { struct ArgusVlanStruct *vlan = (struct ArgusVlanStruct *) farhdr; vlan->status &= ~(ARGUS_SRC_CHANGED | ARGUS_DST_CHANGED); break; } case ARGUS_MPLS_DSR: { struct ArgusMplsStruct *mpls = (struct ArgusMplsStruct *) farhdr; mpls->status &= ~(ARGUS_SRC_CHANGED | ARGUS_DST_CHANGED); break; } case ARGUS_AGR_DSR: { struct ArgusAGRStruct *agr = (struct ArgusAGRStruct *) farhdr; agr->count = 0; agr->act.n = 0; agr->act.minval = 0x7FFFFFFF; agr->act.meanval = 0; agr->act.stdev = 0; agr->act.maxval = 0; agr->idle.n = 0; agr->idle.minval = 0x7FFFFFFF; agr->idle.meanval = 0; agr->idle.stdev = 0; agr->idle.maxval = 0; break; } } if ((farlen = farhdr->length) == 0) break; if ((farhdr->type == ARGUS_SRCUSRDATA_DSR) || (farhdr->type == ARGUS_DSTUSRDATA_DSR)) farlen = farlen * 4; length -= farlen; farhdr = (struct ArgusFarHeaderStruct *)((char *)farhdr + farlen); } } data->agr.count = 0; data->agr.act.n = 0; data->agr.act.meanval = 0; data->agr.act.stdev = 0; data->agr.act.maxval = 0; data->agr.act.minval = 0x7FFFFFFF; data->agr.idle.n = 0; data->agr.idle.meanval = 0; data->agr.idle.stdev = 0; data->agr.idle.maxval = 0; data->agr.idle.minval = 0x7FFFFFFF; data->act.n = 0; data->act.sumtime = 0; data->act.sumsqrd = 0; data->idle.n = 0; data->idle.sumtime = 0; data->idle.sumtime = 0; data->argus->ahdr.status &= ~ARGUS_MERGED; data->status &= ~RA_MODIFIED; } } } store->qhdr.logtime = ArgusGlobalTime; #ifdef ARGUSDEBUG ArgusDebug (4, "RaSendArgusRecord(0x%x) done.\n", store); #endif return (retn); } argus-clients-2.0.6.fixes.1/clients/ramon.h0000664000076600007660000000221107640476616014214 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 RaMon_h #define RaMon_h #include #include #include #include #include #include #include #include void RaProcessQueue(struct RaQueueStruct *, unsigned char state); #endif argus-clients-2.0.6.fixes.1/clients/ranonymize.c0000664000076600007660000020227707725256545015305 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * ranonymize - argus data anonymization function. * * written by Carter Bullard * QoSient, LLC * */ #include #include #define MAX_OBJ_SIZE 1024 unsigned int RaMapHash = 0; unsigned int RaHashSize = 0; unsigned int RaMapOffsetValue = 0; unsigned int RaMapTransOffsetValue = 0; unsigned int RaMapSequenceOffsetValue = 0; unsigned int RaMapTimeSecOffsetValue = 0; unsigned int RaMapTimeuSecOffsetValue = 0; unsigned int RaPortMappingOffsetValue = 0; unsigned short RaMapIpIdValue = 0; struct RaMapHashTableStruct { int size; struct RaMapHashTableHeader **array; }; struct RaMapHashTableHeader { struct RaMapHashTableHeader *nxt, *prv; unsigned int hash; int type, len, value, mask; struct RaClassNets *net; void *obj, *sub; }; struct RaMapHashTableStruct RaMapHashTable; struct RaMapHashTableStruct RaMapNetTable; struct RaClassNets { struct RaClassNets *supernet; unsigned int net; unsigned int index; }; struct RaClassNets *RaClassANets[256]; struct RaPortStruct { struct ArgusQueueHeader qhdr; unsigned short value; }; #define RA_MAX_PORT 65535 unsigned short RaPortMapping [65536]; unsigned short RaPortRandom [65536]; unsigned short RaPortTemp [65536]; int RaMapConvert = 0; int RaNonParseResourceFile (char *); int RaPreserveBroadcastAddress = 1; int RaPreserveWellKnownPorts = 1; int RaPreserveRegisteredPorts = 0; int RaPreservePrivatePorts = 0; int RaPreserveIpId = 0; char *RaPortMappingOffset = "offset:random"; char *RaNonTransRefNumOffset = "random"; char *RaNonSeqNumOffset = "random"; char *RaNonTimeSecOffset = "random"; char *RaNonTimeuSecOffset = "random"; #define RANON_NONE 0 #define RANON_SUBNET 1 #define RANON_CLASS 2 #define RANON_CIDR 3 #define RANON_RANDOM 1 #define RANON_SHIFT 2 char *RaNonPreserveNetAddrHierarchy = "class"; unsigned int RaMapNetAddrHierarchy = RANON_CLASS; #include struct ArgusRecord * RaConstructArgusRecord (struct ArgusRecord *); int ArgusStripDown = 0; int RaFirstMOptionField = 1; #define RASTRIP_DSR_TYPES 19 #define RASTRIP_DSR_FAR 0 #define RASTRIP_DSR_MAC 1 #define RASTRIP_DSR_TCP 2 #define RASTRIP_DSR_ICMP 3 #define RASTRIP_DSR_RTP 4 #define RASTRIP_DSR_IGMP 5 #define RASTRIP_DSR_ARP 6 #define RASTRIP_DSR_FRG 7 #define RASTRIP_DSR_ESP 8 #define RASTRIP_DSR_MPLS 9 #define RASTRIP_DSR_VLAN 10 #define RASTRIP_DSR_PPPOE 11 #define RASTRIP_DSR_AGR 12 #define RASTRIP_DSR_TIME 13 #define RASTRIP_DSR_SRCTIME 14 #define RASTRIP_DSR_DSTTIME 15 #define RASTRIP_DSR_USRDATA 16 #define RASTRIP_DSR_SRCUSRDATA 17 #define RASTRIP_DSR_DSTUSRDATA 18 int RaDSRFields[RASTRIP_DSR_TYPES]; char *RaDSRKeyWords[RASTRIP_DSR_TYPES] = { "far", "mac", "tcp", "icmp", "rtp", "igmp", "arp", "frag", "esp", "mpls", "vlan", "pppoe", "agr", "jitter", "stime", "dtime", "user", "srcuser", "dstuser", }; void RaProcessMOptions(struct ArgusModeStruct *); #define RA_ADD_OPTION 1 #define RA_SUB_OPTION 2 void RaProcessMOptions(struct ArgusModeStruct *mode) { int x, RaOptionOperation, setValue = 0; char *ptr = NULL; char *endptr; if (mode != NULL) { while (mode) { if (isdigit(*mode->mode)) { ArgusStripDown = strtol(mode->mode, &endptr, 10); if (mode->mode == endptr) usage(); } else { if (*mode->mode == '-') { if (RaFirstMOptionField) { for (x = 0; x < RASTRIP_DSR_TYPES; x++) RaDSRFields[x] = 1; RaFirstMOptionField = 0; } ptr = mode->mode + 1; RaOptionOperation = RA_SUB_OPTION; } else if (*mode->mode == '+') { ptr = mode->mode + 1; RaOptionOperation = RA_ADD_OPTION; } else { if (RaFirstMOptionField) { bzero ((char *) RaDSRFields, sizeof(RaDSRFields)); RaFirstMOptionField = 0; } ptr = mode->mode; RaOptionOperation = RA_ADD_OPTION; } setValue = (RaOptionOperation == RA_ADD_OPTION) ? 1 : 0; for (x = 0; x < RASTRIP_DSR_TYPES; x++) { if (!strncmp (RaDSRKeyWords[x], ptr, strlen(RaPrintKeyWords[x]))) { switch (x) { case RASTRIP_DSR_USRDATA: { RaDSRFields[RASTRIP_DSR_SRCUSRDATA] = setValue; RaDSRFields[RASTRIP_DSR_DSTUSRDATA] = setValue; break; } default: RaDSRFields[x] = setValue; break; } } } mode = mode->nxt; } } } } void ArgusClientInit () { struct ArgusModeStruct *mode; struct timeval tvpbuf, *tvp = &tvpbuf; int retn, cnt, ind = 0, x, y, count = 0, shiftcount = 0, start; unsigned short i, value, startport = 0; char *ptr = NULL; if (!(RaInitialized)) { RaInitialized++; RaWriteOut = 0; RaCumulativeMerge = 1; RaMapConvert = 1; RaHashSize = 0x10000; bzero ((char *)RaDSRFields, sizeof(RaDSRFields)); RaDSRFields[RASTRIP_DSR_FAR] = 1; RaDSRFields[RASTRIP_DSR_TCP] = 1; if ((mode = ArgusModeList) != NULL) RaProcessMOptions(mode); if (!(ArgusStripDown)) ArgusStripDown++; if ((RaMapHashTable.array = (struct RaMapHashTableHeader **) ArgusCalloc (RaHashSize, sizeof (struct RaMapHashTableHeader))) == NULL) ArgusLog (LOG_ERR, "RaMapInit: ArgusCalloc error %s\n", strerror(errno)); RaMapHashTable.size = RaHashSize; if ((RaMapNetTable.array = (struct RaMapHashTableHeader **) ArgusCalloc (RaHashSize, sizeof (struct RaMapHashTableHeader))) == NULL) ArgusLog (LOG_ERR, "RaMapInit: ArgusCalloc error %s\n", strerror(errno)); RaMapNetTable.size = RaHashSize; if (ArgusFlowModelFile) if ((RaNonParseResourceFile (ArgusFlowModelFile)) < 0) exit(0); bzero ((char *)RaClassANets, sizeof(RaClassANets)); gettimeofday(tvp, 0L); srandom(tvp->tv_usec); if (!(strncmp(RaNonTransRefNumOffset, "random", 6))) RaMapTransOffsetValue = random() % 100000; else { if (!(strncmp(RaNonTransRefNumOffset, "fixed", 5))) { if ((ptr = strchr(RaNonTransRefNumOffset, ':')) != NULL) RaMapTransOffsetValue = atoi(++ptr); else ArgusLog(LOG_ERR, "RANON_TIME_SEC_OFFSET syntax error\n"); } else if (!(strncmp(RaNonTransRefNumOffset, "no", 2))) RaMapTransOffsetValue = 0; else ArgusLog(LOG_ERR, "RANON_TRANSREFNUM_OFFSET syntax error\n"); } if (!(strncmp(RaNonSeqNumOffset, "random", 6))) RaMapSequenceOffsetValue = random() % 1000000; else { if (!(strncmp(RaNonSeqNumOffset, "fixed", 5))) { if ((ptr = strchr(RaNonSeqNumOffset, ':')) != NULL) RaMapSequenceOffsetValue = atoi(++ptr); else ArgusLog(LOG_ERR, "RANON_TIME_SEC_OFFSET syntax error\n"); } else if (!(strncmp(RaNonSeqNumOffset, "no", 2))) RaMapSequenceOffsetValue = 0; else ArgusLog(LOG_ERR, "RANON_SEQNUM_OFFSET syntax error\n"); } if (!(strncmp(RaNonTimeSecOffset, "random", 6))) RaMapTimeSecOffsetValue = random() % (tvp->tv_sec / 2); else { if (!(strncmp(RaNonTimeSecOffset, "fixed", 5))) { if ((ptr = strchr(RaNonTimeSecOffset, ':')) != NULL) RaMapTimeSecOffsetValue = atoi(++ptr); else ArgusLog(LOG_ERR, "RANON_TIME_SEC_OFFSET syntax error\n"); } else if (!(strncmp(RaNonTimeSecOffset, "no", 2))) RaMapTimeSecOffsetValue = 0; else ArgusLog(LOG_ERR, "RANON_TIME_SEC_OFFSET syntax error\n"); } if (!(strncmp(RaNonTimeuSecOffset, "random", 6))) RaMapTimeuSecOffsetValue = random() % 500000; else { if (!(strncmp(RaNonTimeuSecOffset, "fixed", 5))) { if ((ptr = strchr(RaNonTimeuSecOffset, ':')) != NULL) RaMapTimeuSecOffsetValue = atoi(++ptr); else ArgusLog(LOG_ERR, "RANON_TIME_USEC_OFFSET syntax error\n"); } else if (!(strncmp(RaNonTimeuSecOffset, "no", 2))) RaMapTimeuSecOffsetValue = 0; else ArgusLog(LOG_ERR, "RANON_TIME_USEC_OFFSET syntax error\n"); } if (!(strncmp(RaNonPreserveNetAddrHierarchy, "cidr", 4))) { RaMapNetAddrHierarchy = RANON_CIDR; } else { if (!(strncmp(RaNonPreserveNetAddrHierarchy, "class", 5))) { RaMapNetAddrHierarchy = RANON_CLASS; } else { if (!(strncmp(RaNonPreserveNetAddrHierarchy, "subnet", 6))) RaMapNetAddrHierarchy = RANON_SUBNET; else { if (!(strncmp(RaNonPreserveNetAddrHierarchy, "no", 2))) RaMapNetAddrHierarchy = RANON_NONE; else ArgusLog(LOG_ERR, "RANON_PRESERVE_NET_ADDRESS_HIERARCHY syntax error\n"); } } } if (!(RaPreserveIpId)) RaMapIpIdValue = (unsigned short) (random() % 0x10000); bzero ((char *) RaPortMapping, sizeof(RaPortMapping)); bzero ((char *) RaPortRandom, sizeof(RaPortRandom)); for (i = 0; i < RA_MAX_PORT; i++) { RaPortMapping[i] = i; RaPortRandom[i] = i; } RaPortMapping[RA_MAX_PORT] = RA_MAX_PORT; RaPortMapping[RA_MAX_PORT] = RA_MAX_PORT; if (RaPreserveWellKnownPorts) { if (RaPreserveRegisteredPorts) { if (RaPreservePrivatePorts) { startport = RA_MAX_PORT - 1; } else startport = 49152; } else startport = 1024; } else startport = 1; if (!(strncmp(RaPortMappingOffset, "random", 6))) { for (i = startport, start = startport; i < RA_MAX_PORT; i++) { if (shiftcount > 5) { cnt = 0; shiftcount = 0; y = start; bzero ((char *) RaPortTemp, sizeof(RaPortTemp)); for (x = i; x < RA_MAX_PORT; x++) { while ((RaPortRandom[y] == 0) && (y < RA_MAX_PORT)) y++; if (RaPortRandom[y]) { RaPortTemp[x] = RaPortRandom[y]; RaPortRandom[y] = 0; cnt++; } else break; } bcopy ((char *)RaPortTemp, (char *) RaPortRandom, sizeof(RaPortRandom)); start = i; } retn = i + (random() % (RA_MAX_PORT - i)); ind = retn; while (RaPortRandom[ind] == 0) { if (retn & 0x01) { if (ind >= start) { ind--; } else { ind = retn++; shiftcount++; } } else { if (ind <= RA_MAX_PORT) { ind++; } else { ind = retn--; shiftcount++; } } } if ((value = RaPortRandom[ind])) { RaPortMapping[i] = value; RaPortRandom[ind] = 0; count++; } } } else { if (!(strncmp(RaPortMappingOffset, "offset:random", 13))) { RaPortMappingOffsetValue = (random() % RA_MAX_PORT); } else if (!(strncmp(RaPortMappingOffset, "offset:fixed", 12))) { if ((ptr = strchr(RaPortMappingOffset, ':')) != NULL) RaPortMappingOffsetValue = atoi(++ptr); else ArgusLog(LOG_ERR, "RANON_PORT_METHOD syntax error\n"); } else if (!(strncmp(RaPortMappingOffset, "no", 2))) RaPortMappingOffsetValue = 0; else ArgusLog(LOG_ERR, "RANON_PORT_METHOD syntax error\n"); if (RaPortMappingOffsetValue > 0) { for (i = startport, start = startport; i < RA_MAX_PORT; i++) { RaPortMapping[i] += RaPortMappingOffsetValue; if (RaPortMapping[i] < startport) RaPortMapping[i] += startport; } } } setuid(getuid()); } #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusClientInit: returning\n"); #endif } int RaParseCompleting = 0; int RaMapMacCounter = 0; int RaMapMacMultiCastCounter = 0; int RaMapClassACounter = 0; int RaMapClassBCounter = 0; int RaMapClassCCounter = 0; int RaMapClassANetCounter = 0; int RaMapClassBNetCounter = 0; int RaMapClassCNetCounter = 0; int RaMapMultiCastCounter = 0; struct ArgusListStruct *RaMapEtherAddrList = NULL; struct ArgusListStruct *RaMapIPAddrList = NULL; void RaParseComplete (int sig) { if ((sig >= 0) && (!RaParseCompleting)) { RaParseCompleting++; /* printf ("Total Records %9d\n", totalrecords); printf ("Total EtherNet Addrs %8d\n", RaMapMacCounter); printf ("Total EtherNet Multicast Addrs %8d\n", RaMapMacMultiCastCounter); printf ("Total Class A Nets %5d Addrs %8d\n", RaMapClassANetCounter, RaMapClassACounter); printf ("Total Class B Nets %5d Addrs %8d\n", RaMapClassBNetCounter, RaMapClassBCounter); printf ("Total Class C Nets %5d Addrs %8d\n", RaMapClassCNetCounter, RaMapClassCCounter); printf ("Total Multicast Addrs %8d\n\n", RaMapMultiCastCounter); printf ("Distributing %8d Hosts into %6d Nets\n", (RaMapClassACounter + RaMapClassBCounter + RaMapClassCCounter), (RaMapClassANetCounter + RaMapClassBNetCounter + RaMapClassCNetCounter)); if (RaMapEtherAddrList) { struct RaMapHashTableHeader *retn = NULL; while (!ArgusListEmpty (RaMapEtherAddrList)) { if ((retn = ArgusFrontList(RaMapEtherAddrList)) != NULL) { fprintf (stdout, " Address %17s ", etheraddr_string (retn->obj)); fprintf (stdout, " Converted to %17s\n", etheraddr_string (retn->sub)); ArgusPopFrontList(RaMapEtherAddrList); } } } if (RaMapIPAddrList) { struct RaMapHashTableHeader *retn = NULL; while (!ArgusListEmpty (RaMapIPAddrList)) { if ((retn = ArgusFrontList(RaMapIPAddrList)) != NULL) { fprintf (stdout, " Address %17s ", ipaddr_string (retn->obj)); fprintf (stdout, " Converted to %17s\n", ipaddr_string (retn->sub)); ArgusPopFrontList(RaMapIPAddrList); } } } */ } #ifdef ARGUSDEBUG ArgusDebug (2, "RaParseComplete: returning\n"); #endif } void ArgusClientTimeout () { #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusClientTimeout: returning\n"); #endif } void parse_arg (int argc, char**argv) { #ifdef ARGUSDEBUG ArgusDebug (6, "parse_arg: returning\n"); #endif } void usage () { extern char version[]; fprintf (stderr, "Ratemplate Version %s\n", version); fprintf (stderr, "usage: %s \n", ArgusProgramName); fprintf (stderr, "usage: %s [options] -S remoteServer [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "usage: %s [options] -r argusDataFile [- filter-expression]\n\n", ArgusProgramName); fprintf (stderr, "options: -a print record summaries on termination.\n"); fprintf (stderr, " -A print application bytes.\n"); fprintf (stderr, " -b dump packet-matching code.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); fprintf (stderr, " -D specify debug level\n"); fprintf (stderr, " -E write records that are rejected by the filter into \n"); fprintf (stderr, " -f read flow model from .\n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -n don't convert numbers to names.\n"); fprintf (stderr, " -p print fractional time with precision.\n"); fprintf (stderr, " -q quiet mode. don't print record outputs.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -R print out response data when availabile.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [mm/dd[/yy].]hh[:mm[:ss]]\n"); fprintf (stderr, " mm/dd[/yy]\n"); fprintf (stderr, " -%%d{yMhdms}\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); fprintf (stderr, " -u print time in Unix time format.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif fprintf (stderr, " -w write output to . '-' denotes stdout.\n"); fprintf (stderr, " -z print Argus TCP state changes.\n"); fprintf (stderr, " -Z print actual TCP flag values.<'s'rc | 'd'st | 'b'oth>\n"); exit(1); } #define RAMAP_ETHER_MAC_ADDR 0x1 #define RAMAP_IP_ADDR 0x10 int RaFirstRecord = 1; void RaProcessRecord (struct ArgusRecord *argus) { struct ArgusRecordStore *store = NULL; if (RaFirstRecord) { ArgusNtoH(&ArgusInput->ArgusInitCon); RaMapInventory(&ArgusInput->ArgusInitCon.argus_mar.localnet, RAMAP_IP_ADDR, 4); RaMapInventory(&ArgusInput->ArgusInitCon.argus_mar.argusid, RAMAP_IP_ADDR, 4); ArgusInput->ArgusInitCon.argus_mar.startime.tv_sec -= RaMapTimeSecOffsetValue; ArgusInput->ArgusInitCon.argus_mar.startime.tv_usec -= RaMapTimeuSecOffsetValue; if (ArgusInput->ArgusInitCon.argus_mar.startime.tv_usec < 0) { ArgusInput->ArgusInitCon.argus_mar.startime.tv_sec--; ArgusInput->ArgusInitCon.argus_mar.startime.tv_usec += 1000000; } ArgusInput->ArgusInitCon.argus_mar.now.tv_sec -= RaMapTimeSecOffsetValue; ArgusInput->ArgusInitCon.argus_mar.now.tv_usec -= RaMapTimeuSecOffsetValue; if (ArgusInput->ArgusInitCon.argus_mar.now.tv_usec < 0) { ArgusInput->ArgusInitCon.argus_mar.now.tv_sec--; ArgusInput->ArgusInitCon.argus_mar.now.tv_usec += 1000000; } ArgusHtoN(&ArgusInput->ArgusInitCon); RaFirstRecord = 0; } argus->ahdr.status |= ARGUS_ANON; if (argus->ahdr.type & ARGUS_MAR) RaProcessManRecord (argus); else { struct ArgusRecord *targus = NULL; if ((targus = RaConstructArgusRecord(argus)) != NULL) argus = targus; else ArgusLog (LOG_ERR, "RaProcessRecord: RaConstructArgusRecord(0x%x) %s", argus, strerror(errno)); ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); RaMapInventory (&argus->ahdr.argusid, RAMAP_IP_ADDR, 4); argus->ahdr.seqNumber += RaMapSequenceOffsetValue; argus->argus_far.ArgusTransRefNum += RaMapTransOffsetValue; argus->argus_far.time.start.tv_sec -= RaMapTimeSecOffsetValue; argus->argus_far.time.start.tv_usec -= RaMapTimeuSecOffsetValue; if (argus->argus_far.time.start.tv_usec < 0) { argus->argus_far.time.start.tv_sec--; argus->argus_far.time.start.tv_usec += 1000000; } argus->argus_far.time.last.tv_sec -= RaMapTimeSecOffsetValue; argus->argus_far.time.last.tv_usec -= RaMapTimeuSecOffsetValue; if (argus->argus_far.time.last.tv_usec < 0) { argus->argus_far.time.last.tv_sec--; argus->argus_far.time.last.tv_usec += 1000000; } if (ArgusThisFarStatus & ARGUS_MAC_DSR_STATUS) { struct ArgusMacStruct *mac = (struct ArgusMacStruct *) ArgusThisFarHdrs[ARGUS_MAC_DSR_INDEX]; RaMapInventory (&mac->phys_union.ether.ethersrc, RAMAP_ETHER_MAC_ADDR, 6); RaMapInventory (&mac->phys_union.ether.etherdst, RAMAP_ETHER_MAC_ADDR, 6); } switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: RaMapInventory (&argus->argus_far.flow.ip_flow.ip_src, RAMAP_IP_ADDR, 4); RaMapInventory (&argus->argus_far.flow.ip_flow.ip_dst, RAMAP_IP_ADDR, 4); switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: RaProcessTCPRecord (argus); break; case IPPROTO_UDP: RaProcessUDPRecord (argus); break; case IPPROTO_ICMP: RaProcessICMPRecord (argus); break; default: RaProcessIPRecord (argus); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: RaProcessARPRecord (argus); break; default: RaProcessNonIPRecord (argus); break; } } if (argus != NULL) { if ((store = RaNewArgusStore(argus)) != NULL) { if ((store->data[0] = RaNewArgusData(argus)) != NULL) { store->data[0]->status |= RA_MODIFIED; RaSendArgusRecord (store); RaDeleteArgusStore (store); } else ArgusLog (LOG_ERR, "RaProcessRecord: RaNewArgusData(0x%x) %s\n", argus, strerror(errno)); } else ArgusLog (LOG_ERR, "RaProcessRecord: RaNewArgusStore(0x%x) %s\n", argus, strerror(errno)); } #ifdef ARGUSDEBUG ArgusDebug (5, "RaProcessRecord (0x%x) returning\n", argus); #endif } struct RaMapHashTableHeader *RaMapAllocateEtherAddr (struct ether_header *, int, int); struct RaMapHashTableHeader *RaMapAllocateIPAddr (unsigned int *, int, int); struct RaMapHashTableHeader *RaMapAllocateNet (unsigned int, unsigned int); void RaProcessManRecord (struct ArgusRecord *argus) { RaMapInventory (&argus->argus_mar.localnet, RAMAP_IP_ADDR, 4); RaMapInventory (&argus->argus_mar.argusid, RAMAP_IP_ADDR, 4); argus->argus_mar.startime.tv_sec -= RaMapTimeSecOffsetValue; argus->argus_mar.startime.tv_usec -= RaMapTimeuSecOffsetValue; if (argus->argus_mar.startime.tv_usec < 0) { argus->argus_mar.startime.tv_sec--; argus->argus_mar.startime.tv_usec += 1000000; } argus->argus_mar.now.tv_sec -= RaMapTimeSecOffsetValue; argus->argus_mar.now.tv_usec -= RaMapTimeuSecOffsetValue; if (argus->argus_mar.now.tv_usec < 0) { argus->argus_mar.now.tv_sec--; argus->argus_mar.now.tv_usec += 1000000; } #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessManRecord (0x%x) returning\n", argus); #endif } void RaProcessTCPRecord (struct ArgusRecord *argus) { if (RaMapConvert) { struct ArgusTCPObject *tcp = NULL; if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) { if ((tcp = (struct ArgusTCPObject *) ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]) != NULL) { tcp->src.seqbase += RaMapSequenceOffsetValue; tcp->dst.seqbase += RaMapSequenceOffsetValue; } } argus->argus_far.flow.ip_flow.sport = RaPortMapping[argus->argus_far.flow.ip_flow.sport]; argus->argus_far.flow.ip_flow.dport = RaPortMapping[argus->argus_far.flow.ip_flow.dport]; argus->argus_far.flow.ip_flow.ip_id += RaMapIpIdValue; } #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessTCPRecord (0x%x) returning\n", argus); #endif } #if defined(__OpenBSD__) #include #include #endif #include void RaProcessICMPRecord (struct ArgusRecord *argus) { struct ArgusICMPFlow *icmpFlow = &argus->argus_far.flow.icmp_flow; struct ArgusICMPObject *icmp = NULL; unsigned char ra_icmp_type = 0, ra_icmp_code = 0; if (ArgusThisFarStatus & ARGUS_ICMP_DSR_STATUS) { icmp = (struct ArgusICMPObject *)ArgusThisFarHdrs[ARGUS_ICMP_DSR_INDEX]; RaMapInventory (&icmp->isrcaddr, RAMAP_IP_ADDR, 4); RaMapInventory (&icmp->idstaddr, RAMAP_IP_ADDR, 4); RaMapInventory (&icmp->igwaddr, RAMAP_IP_ADDR, 4); icmp->iseq += (unsigned short) RaMapSequenceOffsetValue; ra_icmp_type = icmp->icmp_type; ra_icmp_code = icmpFlow->code; } else { ra_icmp_type = icmpFlow->type; ra_icmp_code = icmpFlow->code; } if ((ra_icmp_type == ICMP_UNREACH) && (ra_icmp_code == ICMP_UNREACH_PORT)) icmpFlow->id = RaPortMapping[icmpFlow->id]; #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessICMPRecord (0x%x) returning\n", argus); #endif } void RaProcessUDPRecord (struct ArgusRecord *argus) { argus->argus_far.flow.ip_flow.sport = RaPortMapping[argus->argus_far.flow.ip_flow.sport]; argus->argus_far.flow.ip_flow.dport = RaPortMapping[argus->argus_far.flow.ip_flow.dport]; argus->argus_far.flow.ip_flow.ip_id += RaMapIpIdValue; #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessUDPRecord (0x%x) returning\n", argus); #endif } void RaProcessIPRecord (struct ArgusRecord *argus) { argus->argus_far.flow.ip_flow.ip_id += RaMapIpIdValue; #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessIPRecord (0x%x) returning\n", argus); #endif } void RaProcessARPRecord (struct ArgusRecord *argus) { RaMapInventory (&argus->argus_far.flow.arp_flow.arp_spa, RAMAP_IP_ADDR, 4); RaMapInventory (&argus->argus_far.flow.arp_flow.arp_tpa, RAMAP_IP_ADDR, 4); RaMapInventory (&argus->argus_far.flow.arp_flow.etheraddr, RAMAP_ETHER_MAC_ADDR, 6); RaMapInventory (&argus->argus_far.attr_arp.response, RAMAP_ETHER_MAC_ADDR, 6); #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessARPRecord (0x%x) returning\n", argus); #endif } void RaProcessNonIPRecord (struct ArgusRecord *argus) { #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessNonIPRecord (0x%x) returning\n", argus); #endif } #include int RaLabelCounter = 0; int RaSendArgusRecord(struct ArgusRecordStore *store) { struct ArgusRecordData *data; struct ArgusRecord *argus = NULL; int retn = 0; if ((data = store->data[0]) != NULL) { if ((argus = data->argus) == NULL) return (retn); if ((Lflag > 0) && !(qflag)) { if (RaLabel == NULL) RaLabel = RaGenerateLabel(argus); if (!(RaLabelCounter++ % Lflag)) { if (!(wfile)) printf ("%s\n", RaLabel); fflush (stdout); } if (Lflag < 0) Lflag = 0; } if ((ArgusWfileList != NULL) && (!(ArgusListEmpty(ArgusWfileList)))) { struct ArgusWfileStruct *wfile = NULL, *start = NULL; if ((wfile = ArgusFrontList(ArgusWfileList)) != NULL) { start = wfile; do { if ((exceptfile == NULL) || strcmp(wfile->filename, exceptfile)) { #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif ArgusWriteNewLogfile (wfile, argus); #ifdef _LITTLE_ENDIAN ArgusNtoH(argus); #endif } ArgusPopFrontList(ArgusWfileList); ArgusPushBackList(ArgusWfileList, wfile); wfile = ArgusFrontList(ArgusWfileList); } while (wfile != start); } } else { if (!(argus->ahdr.type & ARGUS_MAR)) ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); printf ("%s\n", get_argus_string (argus)); fflush (stdout); } } #ifdef ARGUSDEBUG ArgusDebug (4, "RaSendArgusRecord(0x%x) done.\n", store); #endif return (retn); } #ifndef RaMap #define RaMap #endif #ifndef RaMapUtil #define RaMapUtil #endif #include #include #include #define MAXSTRSIZE 1024 #define MAX_OBJ_SIZE 1024 struct RaMapHashTableStruct RaMapHashTable; #ifndef IN_CLASSD #define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000) #endif int RaPreserveEtherVendor = 0; int RaPreserveIPHierarchy = 1; int RaPreserveNoHierarchy = 0; unsigned int RaMapEtherAddrs = 2; unsigned int RaMapIPAddrs = 2; #define ETHER_INTERNET_BROADCAST 0x01005E00 #define RA_ETHER_VENDOR 0x00000001 struct RaMapHashTableHeader *RaMapFindHashObject (struct RaMapHashTableStruct *, void *, int, int); struct RaMapHashTableHeader *RaMapAddHashEntry (struct RaMapHashTableStruct *, void *, int, int); void RaMapRemoveHashEntry (struct RaMapHashTableStruct *, struct RaMapHashTableHeader *); unsigned int RaMapCalcHash (void *, int, int); struct RaMapHashTableHeader * RaMapAllocateEtherAddr (struct ether_header *src, int type, int len) { struct RaMapHashTableHeader *retn = NULL; struct ether_header dstbuf, *dst = &dstbuf; unsigned int RaMapEtherVendors = htonl(RA_ETHER_VENDOR); unsigned int tmp = htonl(ETHER_INTERNET_BROADCAST); unsigned char *ptr = (unsigned char *) src; int i = 0, broadcast = 1; if (src) { for (i = 0; i < 6; i++) if (ptr[i] != (unsigned char) 0xff) broadcast = 0; if (broadcast) { bcopy ((char *) src, (char *) dst, 6); } else { if (RaPreserveEtherVendor || (!(bcmp (((char *)src), (char *)&tmp, 3)))) { bcopy ((char *) src, (char *) dst, 3); } else { for (i = 0; i < (sizeof (int) - 1); i++) ((char *)dst)[i] = ((char *)&RaMapEtherVendors)[i + 1]; } ptr = &((unsigned char *) dst)[3]; RaMapEtherAddrs = ntohl(RaMapEtherAddrs); for (i = 0; i < (sizeof (int) - 1); i++) ptr[i] = ((char *)&RaMapEtherAddrs)[i + 1]; ptr = (unsigned char *) src; if (ptr[5] & 0x01) ((unsigned char *) dst)[5] |= 0x01; RaMapEtherAddrs = htonl(RaMapEtherAddrs); RaMapEtherAddrs += 2; } if (!(retn = RaMapAddHashEntry (&RaMapHashTable, src, type, len))) { ArgusLog (LOG_ERR, "RaMapInventory: RaMapAddHashEntry error %s\n", strerror(errno)); } else { if (((char *)src)[0] & 0x01) { RaMapMacMultiCastCounter++; #ifdef ARGUSDEBUG ArgusDebug (2, "RaMapInventory () adding multicast addr %s\n", etheraddr_string ((char *)src)); #endif } else { RaMapMacCounter++; #ifdef ARGUSDEBUG ArgusDebug (2, "RaMapInventory () adding %s\n", etheraddr_string ((char *)src)); #endif } if ((retn->sub = (void *) ArgusCalloc (1, len)) != NULL) bcopy ((char *) dst, (char *) retn->sub, len); } #ifdef ARGUSDEBUG { char sbuf1[32], sbuf2[32]; sprintf (sbuf1, "%s", etheraddr_string ((void *) dst)); sprintf (sbuf2, "%s", etheraddr_string ((void *) src)); ArgusDebug (2, "RaMapAllocateEtherAddr allocating %s for %s", sbuf1, sbuf2); } #endif } return (retn); } /* So available class A addresses for our algorithm are [0 1 2 5 10 23 27 31 36 37 39 41 42 58-60 69-79 82-127 197 220-223 240-254] we will start with 1.0.0 and move up to 254.0.0 */ #define RA_MAX_CLASS_VALUE 65535 #define RA_MAX_CLASS 109 int RaClassIndex = 0; int RaClassAddress[RA_MAX_CLASS] = { 1,2,5,10,23,27,31,36,37,39, 41,42,58,59,60,69,70,71,72,73, 74,75,76,77,78,79,82,83,84,85, 86,87,88,89,90,91,92,93,94,95, 96,97,98,99, 100,101,102,103,104,105,106,107,108,109, 110,111,112,113,114,115,116,117,118,119, 120,121,122,123,124,125,126,127, 197, 220,221,222,223,224,225,226,227,228,229, 230,231,232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247,248,249, 250,251,252,253,254,255, }; #define RA_MAX_CLASS_A 44 int RaClassAIndex = 0; int RaClassAAddress[RA_MAX_CLASS_A] = { 1,2,5,10,23,27,31,36,37,39, 41,42,58,59,60,69,70,71,72,73, 74,75,76,77,78,79,82,83,84,85, 86,87,88,89,90,91,92,93,94,95, 96,97,98,99, }; #define RA_MAX_CLASS_B 28 int RaClassBIndex = 0; int RaClassBAddress[RA_MAX_CLASS_B] = { 100,101,102,103,104,105,106,107,108,109, 110,111,112,113,114,115,116,117,118,119, 120,121,122,123,124,125,126,127, }; #define RA_MAX_CLASS_C 21 int RaClassCIndex = 0; int RaClassCAddress[RA_MAX_CLASS_C] = { 197,220,221,222,223,240,241,242,243,244, 245,246,247,248,249,250,251,252,253,254, 255, }; #define RA_MAX_CLASS_M 16 int RaClassMIndex = 0; int RaClassMAddress[RA_MAX_CLASS_M] = { 224,225,226,227,228,229,230,231,232,233, 234,235,236,237,238,239, }; /* in comes a request for a network alias */ #ifndef IN_CLASSD_NET #define IN_CLASSD_NET 0xffffffff #endif struct RaMapHashTableHeader *RaMapNewNetwork (unsigned int, unsigned int); unsigned int RaMapLocalNetwork = 0; #include #include #include #define RAMAP_CLASSA 1 #define RAMAP_CLASSB 2 #define RAMAP_CLASSC 3 #define RAMAP_CLASSM 4 struct RaMapHashTableHeader * RaMapNewNetwork (unsigned int host, unsigned int mask) { struct RaMapHashTableHeader *retn = NULL; struct RaClassNets *thisNet = NULL; char buf[MAXSTRLEN]; struct in_addr addrbuf, *addr = &addrbuf; struct hostent *hp; unsigned int **p; int hostclass; if (IN_CLASSA(host)) hostclass = RAMAP_CLASSA; else if (IN_CLASSB(host)) hostclass = RAMAP_CLASSB; else if (IN_CLASSC(host)) hostclass = RAMAP_CLASSC; else if (IN_CLASSD(host)) hostclass = RAMAP_CLASSM; else hostclass = RAMAP_CLASSC; bzero (buf, MAXSTRLEN); do { if (RaMapNetAddrHierarchy > RANON_SUBNET) { switch (hostclass) { case RAMAP_CLASSA: sprintf (buf, "%d.0.0.0", RaClassAAddress[RaClassAIndex]); break; case RAMAP_CLASSB: sprintf (buf, "%d.0.0.0", RaClassBAddress[RaClassBIndex]); break; default: case RAMAP_CLASSC: sprintf (buf, "%d.0.0.0", RaClassCAddress[RaClassCIndex]); break; case RAMAP_CLASSM: sprintf (buf, "%d.0.0.0", RaClassMAddress[RaClassMIndex]); break; } } else sprintf (buf, "%d.0.0.0", RaClassAddress[RaClassIndex]); if ((hp = gethostbyname(buf)) != NULL) { for (p = (unsigned int **)hp->h_addr_list; *p; ++p) **p = ntohl(**p); } else ArgusLog (LOG_ERR, "RaMapNewNetwork: gethostbyname(%s) error %s", optarg, strerror(errno)); addr->s_addr = **(unsigned int **)hp->h_addr_list; if ((retn = RaMapFindHashObject (&RaMapNetTable, &addr->s_addr, RAMAP_IP_ADDR, 4))) { if (retn->net->index >= RA_MAX_CLASS_VALUE) { if (RaMapNetAddrHierarchy > RANON_SUBNET) { switch (hostclass) { case RAMAP_CLASSA: if (RaClassAIndex < RA_MAX_CLASS_A) { RaClassAIndex++; break; } else hostclass = RAMAP_CLASSB; case RAMAP_CLASSB: if (RaClassBIndex < RA_MAX_CLASS_B) { RaClassBIndex++; break; } else hostclass = RAMAP_CLASSC; case RAMAP_CLASSC: if (RaClassCIndex < RA_MAX_CLASS_C) { RaClassCIndex++; break; } else ArgusLog (LOG_ERR, "RaMapNewNetwork: no addresses"); case RAMAP_CLASSM: if (RaClassMIndex < RA_MAX_CLASS_M) { RaClassMIndex++; } else ArgusLog (LOG_ERR, "RaMapNewNetwork: no multicast addresses"); } } } } } while (retn && (retn->net->index >= RA_MAX_CLASS_VALUE)); if (!(retn)) { if ((retn = RaMapAddHashEntry (&RaMapNetTable, &addr->s_addr, RAMAP_IP_ADDR, 4))) { if ((thisNet = (void *) ArgusCalloc (1, sizeof(struct RaClassNets))) != NULL) { thisNet->net = addr->s_addr; thisNet->index = 1; retn->net = thisNet; if ((retn->sub = (void *) ArgusCalloc (1, sizeof(addr->s_addr))) != NULL) bcopy ((char *)&addr->s_addr, (char *) retn->sub, sizeof(addr->s_addr)); else ArgusLog (LOG_ERR, "RaMapNewNetwork: ArgusCalloc() error %s", strerror(errno)); } else ArgusLog (LOG_ERR, "RaMapNewNetwork: ArgusCalloc() error %s", strerror(errno)); } else ArgusLog (LOG_ERR, "RaMapNewNetwork: RaMapAddHashEntry() error %s", strerror(errno)); } #ifdef ARGUSDEBUG { char sbuf1[32], sbuf2[32]; sprintf (sbuf1, "%s", ipaddr_string(&host)); sprintf (sbuf2, "%s", ipaddr_string(&mask)); ArgusDebug (2, "RaMapNewNetwork (%s, %s) returns 0x%x\n", sbuf1, sbuf2, retn); } #endif return (retn); } struct RaMapHashTableHeader * RaMapAllocateNet (unsigned int addr, unsigned int mask) { struct RaMapHashTableHeader *retn = NULL; struct RaMapHashTableHeader *net = NULL; unsigned int newaddr = 0; char buf[MAXSTRLEN]; bzero (buf, MAXSTRLEN); if (!(retn = RaMapFindHashObject (&RaMapNetTable, &addr, RAMAP_IP_ADDR, 4))) { switch (mask) { case IN_CLASSA_NET: break; case IN_CLASSB_NET: if (RaMapNetAddrHierarchy == RANON_CIDR) { return (RaMapAllocateNet (addr & IN_CLASSA_NET, IN_CLASSA_NET)); break; } break; case IN_CLASSC_NET: if (RaMapNetAddrHierarchy == RANON_CIDR) { return (RaMapAllocateNet (addr & IN_CLASSB_NET, IN_CLASSB_NET)); break; } break; case IN_CLASSD_NET: return (RaMapAllocateNet (addr & IN_CLASSC_NET, IN_CLASSC_NET)); break; } if (!(RaMapNetAddrHierarchy)) { } if (!(net) || (net->net->index >= RA_MAX_CLASS_VALUE)) net = RaMapNewNetwork(addr, mask); if ((retn = RaMapAddHashEntry (&RaMapNetTable, (void *)&addr, RAMAP_IP_ADDR, 4))) { if ((retn->net = (void *) ArgusCalloc (1, sizeof(struct RaClassNets))) != NULL) { retn->net->supernet = net->net; newaddr = net->net->net | (net->net->index++ << 8); retn->net->net = newaddr; retn->net->index = 1; } if (!(retn->sub)) { if ((retn->sub = (void *) ArgusCalloc (1, 4)) != NULL) { bcopy ((char *)&newaddr, (char *) retn->sub, 4); } else { ArgusLog (LOG_ERR, "RaMapAllocateNet: ArgusCalloc error %s", strerror(errno)); } #ifdef ARGUSDEBUG { char sbuf1[32], sbuf2[32], sbuf3[32]; sprintf (sbuf1, "%s", ipaddr_string(&addr)); sprintf (sbuf2, "%s", ipaddr_string(&mask)); sprintf (sbuf3, "%s", ipaddr_string(&newaddr)); ArgusDebug (2, "RaMapAllocateNet (%s, %s) maps to %s\n", sbuf1, sbuf2, sbuf3); } #endif } } else ArgusLog (LOG_ERR, "RaMapAllocateNet () RaMapAddHashEntry error %s\n", strerror(errno)); } #ifdef ARGUSDEBUG { char sbuf1[32], sbuf2[32]; sprintf (sbuf1, "%s", ipaddr_string(&addr)); sprintf (sbuf2, "%s", ipaddr_string(&mask)); ArgusDebug (2, "RaMapAllocateNet (%s, %s) return 0x%x\n", sbuf1, sbuf2, retn); } #endif return (retn); } struct RaMapHashTableHeader * RaMapAllocateIPAddr (unsigned int *addr, int type, int len) { struct RaMapHashTableHeader *retn = NULL, *net = NULL; unsigned int newaddr = 0; if (!(retn = RaMapFindHashObject (&RaMapHashTable, addr, type, len))) { if ((net = RaMapAllocateNet (*addr, IN_CLASSD_NET))) { if (((*addr & 0xff) == 0xff) && RaPreserveBroadcastAddress) newaddr = *((unsigned int *)net->sub) | 0xFF; else if (((*addr & 0xff) == 0x00) && RaPreserveBroadcastAddress) newaddr = *((unsigned int *)net->sub); else newaddr = *((unsigned int *)net->sub) + ((struct RaClassNets *)net->net)->index++; if ((retn = RaMapAddHashEntry (&RaMapHashTable, (void *)addr, type, len))) { retn->net = net->net; if ((retn->sub = (void *) ArgusCalloc (1, 4)) != NULL) { bcopy ((char *)&newaddr, (char *) retn->sub, 4); } else { ArgusLog (LOG_ERR, "RaMapAllocateNet: ArgusCalloc error %s", strerror(errno)); } } else ArgusLog (LOG_ERR, "RaAllocateIPAddr () RaMapAddHashEntry error %s\n", strerror(errno)); } else ArgusLog (LOG_ERR, "RaAllocateIPAddr () RaMapAllocateNet failed."); } else newaddr = *(unsigned int *)retn->sub; #ifdef ARGUSDEBUG { char sbuf1[32], sbuf2[32]; sprintf (sbuf1, "%s", ipaddr_string(addr)); sprintf (sbuf2, "%s", ipaddr_string(&newaddr)); ArgusDebug (2, "RaAllocateIPAddr (%s, %d, %d) converts to %s\n", sbuf1, type, len, sbuf2); } #endif return (retn); } void RaMapInventory (void *oid, int type, int len) { struct RaMapHashTableHeader *retn = NULL; switch (type) { case RAMAP_ETHER_MAC_ADDR: { if (!(retn = RaMapFindHashObject (&RaMapHashTable, oid, type, len))) { if (!(retn = RaMapAllocateEtherAddr (oid, type, len))) ArgusLog (LOG_ERR, "RaMapInventory: RaMapAllocateEtherAddr error %s\n", strerror(errno)); if (!(RaMapEtherAddrList)) RaMapEtherAddrList = ArgusNewList(); ArgusPushBackList(RaMapEtherAddrList, retn); } if (RaMapConvert) if (retn->sub) bcopy ((char *)retn->sub, (char *) oid, len); break; } case RAMAP_IP_ADDR: { if (!(retn = RaMapFindHashObject (&RaMapHashTable, oid, type, len))) { if (!(retn = RaMapAllocateIPAddr (oid, type, len))) ArgusLog (LOG_ERR, "RaMapInventory: RaMapAllocateIPAddr error %s\n", strerror(errno)); if (!(RaMapIPAddrList)) RaMapIPAddrList = ArgusNewList(); ArgusPushBackList(RaMapIPAddrList, retn); } if (RaMapConvert) if (retn->sub) bcopy ((char *)retn->sub, (char *) oid, len); break; } } #ifdef ARGUSDEBUG ArgusDebug (3, "RaMapInventory (0x%x, %d, %d) returning\n", oid, type, len); #endif } unsigned int RaMapCalcHash (void *obj, int type, int len) { u_char buf[MAX_OBJ_SIZE]; unsigned int retn = 0; switch (type) { case RAMAP_ETHER_MAC_ADDR: len = 6; break; case RAMAP_IP_ADDR: len = 4; break; default: break; } bzero (buf, sizeof buf); if (RaHashSize <= 0x100) { unsigned char hash = 0, *ptr = (unsigned char *) buf; int i, nitems = len; bcopy ((char *) obj, (char *) &buf, len); for (i = 0; i < nitems; i++) hash += *ptr++; retn = hash; } else if (RaHashSize <= 0x10000) { unsigned short hash = 0, *ptr = (unsigned short *) buf; int i, nitems = (len / sizeof(unsigned short)) + 2; bcopy ((char *) obj, &buf[1], len); for (i = 0; i < nitems; i++) hash += *ptr++; retn = hash; } else { unsigned int hash = 0, *ptr = (unsigned int *) buf; int i, nitems = (len /sizeof(unsigned int)) + 2; bcopy ((char *) obj, &buf[3], len); for (i = 0; i < nitems; i++) hash += *ptr++; retn = hash; } return (retn); } struct RaMapHashTableHeader * RaMapFindHashObject (struct RaMapHashTableStruct *table, void *obj, int type, int len) { struct RaMapHashTableHeader *retn = NULL, *head = NULL, *target; int RaMapHash = 0; RaMapHash = RaMapCalcHash (obj, type, len); if ((target = table->array[RaMapHash % table->size]) != NULL) { head = target; do { if ((type == target->type) && (len == target->len)) { if (!(bcmp ((char *) obj, (char *) target->obj, len))) { retn = target; break; } } target = target->nxt; } while (target != head); } #ifdef TCPCLEANDEBUG RaMapDebug (6, "RaMapFindHashEntry () returning 0x%x RaMapHash %d\n", retn, RaMapHash); #endif return (retn); } struct RaMapHashTableHeader * RaMapAddHashEntry (struct RaMapHashTableStruct *table, void *oid, int type, int len) { struct RaMapHashTableHeader *retn = NULL, *start = NULL; if ((retn = (struct RaMapHashTableHeader *) ArgusCalloc (1, sizeof (struct RaMapHashTableHeader))) != NULL) { RaMapHash = RaMapCalcHash (oid, type, len); retn->hash = RaMapHash; retn->type = type; retn->len = len; if ((retn->obj = (void *) ArgusCalloc (1, len)) == NULL) ArgusLog (LOG_ERR, "RaMapAddHashEntry: ArgusCalloc error %s\n", strerror(errno)); else bcopy ((char *) oid, (char *)retn->obj, len); if ((start = table->array[RaMapHash % table->size]) != NULL) { retn->nxt = start; retn->prv = start->prv; retn->prv->nxt = retn; retn->nxt->prv = retn; } else retn->prv = retn->nxt = retn; table->array[RaMapHash % table->size] = retn; } #ifdef TCPCLEANDEBUG RaMapDebug (3, "RaMapAddHashEntry (0x%x, %d, %d) returning 0x%x\n", oid, type, len, retn); #endif return (retn); } void RaMapRemoveHashEntry (struct RaMapHashTableStruct *table, struct RaMapHashTableHeader *htblhdr) { unsigned short hash = htblhdr->hash; htblhdr->prv->nxt = htblhdr->nxt; htblhdr->nxt->prv = htblhdr->prv; if (htblhdr == table->array[hash % table->size]) { if (htblhdr == htblhdr->nxt) table->array[hash % table->size] = NULL; else table->array[hash % table->size] = htblhdr->nxt; } ArgusFree (htblhdr); #ifdef TCPCLEANDEBUG RaMapDebug (6, "RaMapRemoveHashEntry (0x%x) returning\n", htblhdr); #endif } #define RANON_RCITEMS 23 #define RANON_TRANSREFNUM_OFFSET 0 #define RANON_SEQNUM_OFFSET 1 #define RANON_TIME_SEC_OFFSET 2 #define RANON_TIME_USEC_OFFSET 3 #define RANON_NET_ANONYMIZATION 4 #define RANON_HOST_ANONYMIZATION 5 #define RANON_PRESERVE_NET_ADDRESS_HIERARCHY 6 #define RANON_PRESERVE_BROADCAST_ADDRESS 7 #define RANON_SPECIFY_NET_TRANSLATION 8 #define RANON_SPECIFY_HOST_TRANSLATION 9 #define RANON_PRESERVE_WELLKNOWN_PORT_NUMS 10 #define RANON_PRESERVE_REGISTERED_PORT_NUMS 11 #define RANON_PRESERVE_PRIVATE_PORT_NUMS 12 #define RANON_PRESERVE_PORT_NUMS 13 #define RANON_PRESERVE_PORT_NUM 14 #define RANON_PRESERVE_IP_ID 15 #define RANON_CLASSA_NET_ADDRESS_LIST 16 #define RANON_CLASSB_NET_ADDRESS_LIST 17 #define RANON_CLASSC_NET_ADDRESS_LIST 18 #define RANON_CLASSM_NET_ADDRESS_LIST 19 #define RANON_MAP_DUMPFILE 20 #define RANON_PRESERVE_ETHERNET_VENDOR 21 #define RANON_PORT_METHOD 22 char *RaNonResourceFileStr [] = { "RANON_TRANSREFNUM_OFFSET=", "RANON_SEQNUM_OFFSET=", "RANON_TIME_SEC_OFFSET=", "RANON_TIME_USEC_OFFSET=", "RANON_NET_ANONYMIZATION=", "RANON_HOST_ANONYMIZATION=", "RANON_PRESERVE_NET_ADDRESS_HIERARCHY=", "RANON_PRESERVE_BROADCAST_ADDRESS=", "RANON_SPECIFY_NET_TRANSLATION=", "RANON_SPECIFY_HOST_TRANSLATION=", "RANON_PRESERVE_WELLKNOWN_PORT_NUMS=", "RANON_PRESERVE_REGISTERED_PORT_NUMS=", "RANON_PRESERVE_PRIVATE_PORT_NUMS=", "RANON_PRESERVE_PORT_NUMS=", "RANON_PRESERVE_PORT_NUM=", "RANON_PRESERVE_IP_ID=", "RANON_CLASSA_NET_ADDRESS_LIST=", "RANON_CLASSB_NET_ADDRESS_LIST=", "RANON_CLASSC_NET_ADDRESS_LIST=", "RANON_CLASSM_NET_ADDRESS_LIST=", "RANON_MAP_DUMPFILE=", "RANON_PRESERVE_ETHERNET_VENDOR=", "RANON_PORT_METHOD=", }; #include int RaNonParseResourceFile (char *file) { int retn = 0, i, len, found = 0, lines = 0; char strbuf[MAXSTRLEN], *str = strbuf, *optarg = NULL; FILE *fd; if (file) { if ((fd = fopen (file, "r")) != NULL) { retn = 1; while ((fgets(str, MAXSTRLEN, fd)) != NULL) { lines++; while (*str && isspace((int)*str)) str++; if (*str && (*str != '#') && (*str != '\n') && (*str != '!')) { found = 0; for (i = 0; i < RANON_RCITEMS; i++) { len = strlen(RaNonResourceFileStr[i]); if (!(strncmp (str, RaNonResourceFileStr[i], len))) { optarg = &str[len]; if (optarg[strlen(optarg) - 1] == '\n') optarg[strlen(optarg) - 1] = '\0'; if (*optarg == '\"') optarg++; if (optarg[strlen(optarg) - 1] == '\"') optarg[strlen(optarg) - 1] = '\0'; if (*optarg == '\0') optarg = NULL; if (optarg) { switch (i) { case RANON_TRANSREFNUM_OFFSET: RaNonTransRefNumOffset = strdup(optarg); break; case RANON_SEQNUM_OFFSET: RaNonSeqNumOffset = strdup(optarg); break; case RANON_TIME_SEC_OFFSET: RaNonTimeSecOffset = strdup(optarg); break; case RANON_TIME_USEC_OFFSET: RaNonTimeuSecOffset = strdup(optarg); break; case RANON_NET_ANONYMIZATION: break; case RANON_HOST_ANONYMIZATION: break; case RANON_PRESERVE_NET_ADDRESS_HIERARCHY: RaNonPreserveNetAddrHierarchy = strdup(optarg); break; case RANON_PRESERVE_BROADCAST_ADDRESS: if (!(strncasecmp(optarg, "yes", 3))) RaPreserveBroadcastAddress++; else RaPreserveBroadcastAddress = 0; break; case RANON_SPECIFY_NET_TRANSLATION: { struct RaClassNets *thisNet = NULL; struct RaMapHashTableHeader *mhdr = NULL; struct in_addr oaddrbuf, *oaddr = &oaddrbuf; struct in_addr naddrbuf, *naddr = &naddrbuf; struct hostent *hp; unsigned int **p; char *ptr; if ((ptr = strstr(optarg, "::")) == NULL) ArgusLog (LOG_ERR, "%s: syntax error line %d RANON_SPECIFY_HOST_TRANSLATION needs '::'\n", file, lines); *ptr = '\0'; ptr += 2; if ((hp = gethostbyname(optarg)) != NULL) { for (p = (unsigned int **)hp->h_addr_list; *p; ++p) **p = ntohl(**p); oaddr->s_addr = **(unsigned int **)hp->h_addr_list; } else ArgusLog (LOG_ERR, "RaNonParseResourceFile: gethostbyname(%s) error %s", optarg, strerror(errno)); if ((hp = gethostbyname(ptr)) != NULL) { for (p = (unsigned int **)hp->h_addr_list; *p; ++p) **p = ntohl(**p); } else ArgusLog (LOG_ERR, "RaNonParseResourceFile: gethostbyname(%s) error %s", ptr, strerror(errno)); naddr->s_addr = **(unsigned int **)hp->h_addr_list; if ((mhdr = RaMapAddHashEntry (&RaMapNetTable, &oaddr->s_addr, RAMAP_IP_ADDR, 4))) { if ((thisNet = (void *) ArgusCalloc (1, sizeof(struct RaClassNets))) != NULL) { thisNet->net = oaddr->s_addr; thisNet->index = 1; mhdr->net = thisNet; if ((mhdr->sub = (void *) ArgusCalloc (1, sizeof(naddr->s_addr))) != NULL) bcopy ((char *)&naddr->s_addr, (char *) mhdr->sub, sizeof(naddr->s_addr)); else ArgusLog (LOG_ERR, "RaMapNewNetwork: ArgusCalloc() error %s", strerror(errno)); } else ArgusLog (LOG_ERR, "RaMapNewNetwork: ArgusCalloc() error %s", strerror(errno)); } else ArgusLog (LOG_ERR, "RaMapNewNetwork: RaMapAddHashEntry() error %s", strerror(errno)); break; } case RANON_SPECIFY_HOST_TRANSLATION: { struct RaMapHashTableHeader *mhdr = NULL; struct in_addr oaddrbuf, *oaddr = &oaddrbuf; struct in_addr naddrbuf, *naddr = &naddrbuf; struct hostent *hp; unsigned int **p; char *ptr; if ((ptr = strstr(optarg, "::")) == NULL) ArgusLog (LOG_ERR, "%s: syntax error line %d RANON_SPECIFY_HOST_TRANSLATION needs '::'\n", file, lines); *ptr = '\0'; ptr += 2; if ((hp = gethostbyname(optarg)) != NULL) { for (p = (unsigned int **)hp->h_addr_list; *p; ++p) **p = ntohl(**p); oaddr->s_addr = **(unsigned int **)hp->h_addr_list; } else ArgusLog (LOG_ERR, "RaNonParseResourceFile: gethostbyname(%s) error %s", optarg, strerror(errno)); if ((hp = gethostbyname(ptr)) != NULL) { for (p = (unsigned int **)hp->h_addr_list; *p; ++p) **p = ntohl(**p); naddr->s_addr = **(unsigned int **)hp->h_addr_list; } else ArgusLog (LOG_ERR, "RaNonParseResourceFile: gethostbyname(%s) error %s", ptr, strerror(errno)); #ifdef ARGUSDEBUG ArgusDebug (1, "RaNonParseResourceFile: RANON_SPECIFY_HOST_TRANSLATION=%s::%s\n", optarg, ptr); #endif if (!(mhdr = RaMapFindHashObject (&RaMapHashTable, &oaddr->s_addr, RAMAP_IP_ADDR, 4))) { if ((mhdr = RaMapAddHashEntry (&RaMapHashTable, (void *)&oaddr->s_addr, RAMAP_IP_ADDR, 4))) { if ((mhdr->sub = (void *) ArgusCalloc (1, 4)) != NULL) { bcopy ((char *)&naddr->s_addr, (char *) mhdr->sub, 4); } else { ArgusLog (LOG_ERR, "RaNonParseResourceFile: ArgusCalloc error %s", strerror(errno)); } if (!(RaMapIPAddrList)) RaMapIPAddrList = ArgusNewList(); ArgusPushBackList(RaMapIPAddrList, mhdr); } else ArgusLog (LOG_ERR, "RaAllocateIPAddr () RaMapAddHashEntry error %s\n", strerror(errno)); } else ArgusLog (LOG_ERR, "RaNonParseResourceFile: line %d address %s already allocated\n", lines, optarg); break; } case RANON_PRESERVE_WELLKNOWN_PORT_NUMS: if (!(strncasecmp(optarg, "yes", 3))) RaPreserveWellKnownPorts++; else RaPreserveWellKnownPorts = 0; break; case RANON_PRESERVE_REGISTERED_PORT_NUMS: if (!(strncasecmp(optarg, "yes", 3))) RaPreserveRegisteredPorts++; else RaPreserveRegisteredPorts = 0; break; case RANON_PRESERVE_PRIVATE_PORT_NUMS: if (!(strncasecmp(optarg, "yes", 3))) RaPreservePrivatePorts++; else RaPreservePrivatePorts = 0; break; case RANON_PORT_METHOD: RaPortMappingOffset = strdup(optarg); break; case RANON_PRESERVE_PORT_NUMS: break; case RANON_PRESERVE_PORT_NUM: break; case RANON_PRESERVE_IP_ID: if (!(strncasecmp(optarg, "yes", 3))) RaPreserveIpId++; else RaPreserveIpId = 0; break; case RANON_CLASSA_NET_ADDRESS_LIST: break; case RANON_CLASSB_NET_ADDRESS_LIST: break; case RANON_CLASSC_NET_ADDRESS_LIST: break; case RANON_MAP_DUMPFILE: break; case RANON_PRESERVE_ETHERNET_VENDOR: if (!(strncasecmp(optarg, "yes", 3))) RaPreserveEtherVendor++; else RaPreserveEtherVendor = 0; break; } } found++; break; } } if (!found) { ArgusLog (LOG_ERR, "%s: syntax error line %d\n", file, lines); } } } } else { #ifdef ARGUSDEBUG ArgusDebug (2, "%s: %s\n", file, strerror(errno)); #endif } if (RaPrintStartTime && RaPrintLastTime) Gflag++; else if (RaPrintLastTime) lflag++; } #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusParseResourceFile (%s) returning %d\n", file, retn); #endif return (retn); } #include unsigned char argusBuf[2048]; extern struct ArgusCanonicalRecord *RaThisCanon; struct ArgusRecord * RaConstructArgusRecord (struct ArgusRecord *argus) { struct ArgusRecord *newarg = NULL; struct ArgusFarHeaderStruct **hdrs = NULL, *hdr; if (argus != NULL) { ArgusThisFarStatus = ArgusIndexRecord (argus, ArgusThisFarHdrs); hdrs = ArgusThisFarHdrs; bzero (argusBuf, sizeof(argusBuf)); newarg = (struct ArgusRecord *) argusBuf; bcopy ((char *)&argus->ahdr, (char *)&newarg->ahdr, sizeof (struct ArgusRecordHeader)); newarg->ahdr.length = sizeof (struct ArgusRecordHeader); if (argus->ahdr.type & ARGUS_MAR) { bcopy ((char *)&argus->argus_mar, (char *)&newarg->argus_mar, sizeof(struct ArgusMarStruct)); newarg->ahdr.length += sizeof(struct ArgusMarStruct); } else { if (((hdr = hdrs[ARGUS_FAR_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_FAR])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_MAC_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_MAC])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_TCP_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_TCP])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_VLAN_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_VLAN])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_MPLS_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_MPLS])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_AGR_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_AGR])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_TIME_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_TIME])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_ICMP_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_ICMP])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_RTP_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_RTP])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_IGMP_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_IGMP])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_ARP_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_ARP])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_FRG_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_FRG])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_ESP_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_ESP])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_SRCUSRDATA_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_SRCUSRDATA])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_DSTUSRDATA_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_DSTUSRDATA])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } } } return (newarg); } argus-clients-2.0.6.fixes.1/clients/ranonymize.h0000664000076600007660000000322007640476616015274 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* ranonymize.h */ #ifndef RaNonymize_h #define RaNonymize_h #include #include #include #include #include #include #include #include #include #include #include #ifndef MAXSTRLEN #define MAXSTRLEN 1024 #endif #ifndef MAXPATHNAMELEN #define MAXPATHNAMELEN BUFSIZ #endif #if defined(RaMap) void RaMapInit (void); void RaMapShutDown (void); int RaMapParseConversionFile (char *); void RaMapInventory(void *, int, int); #else /* defined(RaMap) */ extern void RaMapInit (void); extern void RaMapShutDown (void); int RaMapParseConversionFile (char *); extern void RaMapInventory(void *, int, int); #endif /* defined(RaMap) */ #endif /* RaMap_h */ argus-clients-2.0.6.fixes.1/clients/rapath.c0000664000076600007660000006454507640610353014360 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * rapath - print derivable path information from argus data. * * written by Carter Bullard * QoSient, LLC * */ #include #include #include void RaProcessSrvRecord (struct ArgusServiceRecord *); int RaInitialized = 0; int RaPrintSVGOutput = 0; extern int RaHistoStart; extern int RaHistoEnd; void ArgusClientInit () { struct ArgusModeStruct *mode = NULL; if (!(RaInitialized)) { RaWriteOut = 0; RaCumulativeMerge = 1; hfield = 17; pfield = 8; bzero ((char *) RaPrintAlgorithms, sizeof(RaPrintAlgorithms)); if ((mode = ArgusModeList) != NULL) { while (mode) { if (!(strcasecmp (mode->mode, "svg"))) RaPrintSVGOutput++; mode = mode->nxt; } } bzero ((char *) RaSortAlgorithms, sizeof(RaSortAlgorithms)); RaSortAlgorithms[0] = RaSortAlgorithmTable[RASORTSRCTTL]; if ((RaModelerQueue = RaNewQueue()) == NULL) exit(0); if ((RaHashTable.array = (struct RaHashTableHeader **) ArgusCalloc (RA_HASHTABLESIZE, sizeof (struct RaHashTableHeader *))) != NULL) { RaHashTable.size = RA_HASHTABLESIZE; } if (Hflag) { if (!(RaHistoTimeParse (Hstr))) usage(); } if (nflag) { hfield = 15; pfield = 5; } RaInitialized++; } } void ArgusClientTimeout () { RaProcessQueue (RaModelerQueue, ARGUS_STATUS); #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusClientTimeout: current time %s.\n", print_time(&ArgusGlobalTime)); if (ArgusMinuteUpdate++ == 60) { ArgusDebug (2, "ArgusClientTimeout: current time %s HashHdrs %d Hash %d Queue %d\n", print_time(&ArgusGlobalTime), RaAllocHashTableHeaders, RaHashTable.count, RaModelerQueue->count); ArgusMinuteUpdate = 1; } if (ArgusHourlyUpdate++ == 3600) { ArgusDebug (2, "ArgusClientTimeout: current time %s.\n", print_time(&ArgusGlobalTime)); ArgusHourlyUpdate = 1; } #endif } int RaParseCompleting = 0; void RaParseComplete (int sig) { if ((sig >= 0) && (!RaParseCompleting)) { RaParseCompleting++; RaProcessQueue (RaModelerQueue, ARGUS_STOP); fflush(stdout); } #ifdef ARGUSDEBUG ArgusDebug (1, "RaParseComplete: returning\n"); #endif } void parse_arg (int argc, char**argv) { } void usage () { extern char version[]; fprintf (stderr, "Rapath Version %s\n", version); fprintf (stderr, "usage: %s \n", ArgusProgramName); fprintf (stderr, "usage: %s [options]\n", ArgusProgramName); fprintf (stderr, "options: -D specify debug level\n"); fprintf (stderr, " -n don't convert numbers to names.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [mm/dd[/yy].]hh[:mm[:ss]]\n"); fprintf (stderr, " mm/dd[/yy]\n"); fprintf (stderr, " -%%d{yMhdms}\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif exit(1); } void RaPrintArgusPath (struct ArgusRecordStore *); struct ArgusServiceRecord ArgusThisSrv; void RaProcessRecord (struct ArgusRecord *argus) { if (argus->ahdr.type & ARGUS_MAR) return; else { switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_UDP: if (argus->argus_far.flow.ip_flow.tp_p == ARGUS_RTP_FLOWTAG) if (!((argus->argus_far.src.count > 3) || (argus->argus_far.dst.count > 3))) argus->argus_far.flow.ip_flow.tp_p = 0; break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: default: return; } } if (((argus->argus_far.status & ARGUS_ICMPUNREACH_MAPPED) || (argus->argus_far.status & ARGUS_ICMPTIMXCED_MAPPED)) && (ArgusThisFarStatus & ARGUS_ICMP_DSR_STATUS)) { argus->argus_far.flow.ip_flow.ip_id = 0; switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_UDP: case IPPROTO_TCP: argus->argus_far.flow.ip_flow.sport = 0xFFFF; argus->argus_far.flow.ip_flow.dport = 0xFFFF; break; case IPPROTO_ICMP: break; default: break; } ArgusThisSrv.argus = argus; RaProcessSrvRecord (&ArgusThisSrv); } } void RaUpdateArgusStorePath(struct ArgusRecord *, struct ArgusRecordStore *); void RaProcessSrvRecord (struct ArgusServiceRecord *srv) { struct ArgusRecord *argus = srv->argus; struct ArgusRecordStore *store, *qstr; int RaTimeout = -1, i = RaHistoTimeSeries; RaThisActiveDuration = RaGetActiveDuration(argus); if (Hflag) { if (RaThisActiveDuration < RaHistoStart) return; for (i = 0; i < RaHistoTimeSeries; i++) { if (RaThisActiveDuration <= RaHistoTimeValues[i]) { RaThisActiveIndex = i; break; } } if (i == RaHistoTimeSeries) return; else i++; } RaThisActiveIndex = i; if ((store = RaFindArgusRecord(&RaHashTable, argus)) != NULL) { RaThisArgusStore = store; if (RaCheckTimeout (store, argus)) RaSendArgusRecord (store); if (!(store->data[0])) { struct ArgusRecordData *data = NULL; if ((data = RaNewArgusData(argus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; data->status |= srv->status & RA_SVCTEST; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *)&data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } store->data[0] = data; } else ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); } else RaMergeArgusRecord (argus, store, RaThisActiveIndex); RaUpdateArgusStorePath(argus, store); } else { if ((argus->argus_far.status & ARGUS_ICMPTIMXCED_MAPPED)) { if ((store = RaNewArgusStore(argus)) != NULL) { if ((store->queue = RaNewQueue()) != NULL) { RaAddToQueue(RaModelerQueue, &store->qhdr); if ((qstr = RaNewArgusStore(argus)) != NULL) { RaAddToQueue(store->queue, &qstr->qhdr); if ((qstr->data[0] = RaNewArgusData(argus)) != NULL) { qstr->data[0]->farhdrstatus = ArgusIndexRecord (qstr->data[0]->argus, qstr->data[0]->farhdrs); qstr->status |= RA_MODIFIED; } } RaThisArgusStore = store; if ((store->data[0] = RaNewArgusData(argus)) != NULL) { int tmp = RaThisActiveIndex; store->data[0]->farhdrstatus = ArgusIndexRecord (store->data[0]->argus, store->data[0]->farhdrs); store->status |= RA_MODIFIED; RaThisActiveIndex = 0; if ((store->rahtblhdr = RaAddHashEntry (&RaHashTable, store)) == NULL) ArgusLog (LOG_ERR, "RaProcessSrvRecord RaAddHashEntry %s\n", strerror(errno)); RaThisActiveIndex = tmp; } store->ArgusTimeout = RaTimeout; store->status |= RA_MODIFIED; store->status |= srv->status & RA_SVCTEST; } else ArgusLog (LOG_ERR, "RaProcessSrvRecord RaNewQueue %s\n", strerror(errno)); } else ArgusLog (LOG_ERR, "RaProcessSrvRecord RaNewArgusStore %s\n", strerror(errno)); } } #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessSrvRecord: done\n"); #endif } char *RaPrintTimeStats (struct ArgusRecord *, char *); char * RaPrintTimeStats (struct ArgusRecord *argus, char *str) { char *retn = NULL; struct ArgusAGRStruct *agr; ArgusThisFarStatus = ArgusIndexRecord (argus, ArgusThisFarHdrs); if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) != NULL) { retn = str; sprintf (retn, "%7d +/- %-6d max %7d min %7d n = %d", agr->act.meanval, agr->act.stdev, agr->act.maxval, agr->act.minval, agr->count); } return (retn); } int RaCompareArgusStore (const void *, const void *); void RaPackQueue (struct RaQueueStruct *); void RaSortQueue (struct RaQueueStruct *); void RaPrintArgusPath (struct ArgusRecordStore *store) { char buf[MAXSTRLEN], *ptr = buf, *str = NULL; struct ArgusRecordStore *obj = NULL; struct ArgusRecordData *data = NULL; struct ArgusRecord *argus = store->data[0]->argus; unsigned int srchost, dsthost, intnode, ttl; char srcAddrString[64], dstAddrString[64], intAddrString[64]; char statsbuf[256], *stats = statsbuf; char date[128]; int i, len, pad, margin; str = get_ip_string (store->data[0]->argus); printf ("%s\n", str); len = strlen(str); ArgusPrintDate (date, store->data[0]->argus); pad = len - (strlen(date) + (3 * hfield) + (cflag ? ((4 * 10) + 3) : 0) + (Iflag ? 7 : 0) + (gflag ? 9 : 0)); if (pad < hfield) { pad += 2 * hfield; hfield = pad / 3; pad = hfield; } if (store->queue) { RaSortQueue(store->queue); for (i = 0; i < store->queue->count; i++) { struct ArgusICMPObject *icmp = NULL; if ((obj = (struct ArgusRecordStore *) store->queue->array[i]) == NULL) ArgusLog (LOG_ERR, "RaSortQueue array error"); icmp = (struct ArgusICMPObject *) obj->data[0]->farhdrs[ARGUS_ICMP_DSR_INDEX]; data = obj->data[0]; argus = data->argus; if (argus && (obj->status & RA_MODIFIED)) { if (data->act.n > 0) { data->agr.act.meanval = data->act.sumtime/data->act.n; data->agr.act.stdev = sqrt (data->act.sumsqrd/data->act.n - pow (data->act.sumtime/data->act.n, 2.0)); } if (data->idle.n > 0) { data->agr.idle.meanval = data->idle.sumtime/data->idle.n; data->agr.idle.stdev = sqrt (data->idle.sumsqrd/data->idle.n - pow (data->idle.sumtime/data->idle.n, 2.0)); } data->agr.type = ARGUS_AGR_DSR; data->agr.length = sizeof(data->agr); bcopy ((char *) argus, buf, argus->ahdr.length); bcopy ((char *)&data->agr,&buf[argus->ahdr.length], data->agr.length); argus = (struct ArgusRecord *) ptr; argus->ahdr.length += data->agr.length; } srchost = argus->argus_far.flow.ip_flow.ip_src; dsthost = argus->argus_far.flow.ip_flow.ip_dst; intnode = icmp->osrcaddr; ttl = argus->argus_far.attr_ip.sttl; sprintf(srcAddrString, "%s", ipaddr_string(&srchost)); sprintf(dstAddrString, "%s", ipaddr_string(&dsthost)); sprintf(intAddrString, "%s", ipaddr_string(&intnode)); stats = RaPrintTimeStats (argus, statsbuf); if (idflag) printf (" "); margin = pad + ((2 * hfield) - (strlen(srcAddrString) + strlen(dstAddrString))); if (dsthost != intnode) { if (nflag) printf ("Path %15.15s -> %15.15s INode: %15.15s ", srcAddrString, dstAddrString, intAddrString); else printf ("Path %s -> %s INode: %*.*s ", srcAddrString, dstAddrString, margin, margin, intAddrString); } else { if (nflag) printf ("Path %15.15s -> %15.15s TNode: %15.15s ", srcAddrString, dstAddrString, intAddrString); else printf ("Path %s -> %s TNode: %*.*s ", srcAddrString, dstAddrString, margin, margin, intAddrString); } printf (" Dis: %2d %s\n", ttl, stats); } } #ifdef ARGUSDEBUG ArgusDebug (4, "RaPrintArgusPath (0x%x) returning\n", store); #endif } void RaUpdateArgusStorePath(struct ArgusRecord *argus, struct ArgusRecordStore *store) { int found = 0; struct ArgusRecordStore *str; struct ArgusICMPObject *argicmp = (struct ArgusICMPObject *) ArgusThisFarHdrs[ARGUS_ICMP_DSR_INDEX]; store->status |= RA_MODIFIED; store->qhdr.lasttime = ArgusGlobalTime; if (store->queue) { str = (struct ArgusRecordStore *) store->queue->start; do { struct ArgusICMPObject *stricmp = (struct ArgusICMPObject *) str->data[0]->farhdrs[ARGUS_ICMP_DSR_INDEX]; if ((argus->argus_far.attr_ip.sttl == str->data[0]->argus->argus_far.attr_ip.sttl)) { if ((stricmp && argicmp) && (stricmp->osrcaddr == argicmp->osrcaddr)) { RaMergeArgusRecord(argus, str, 0); found++; break; } } str = (struct ArgusRecordStore *) str->qhdr.nxt; } while (str != (struct ArgusRecordStore *) store->queue->start); if (!(found) && ((argus->argus_far.status & ARGUS_ICMPTIMXCED_MAPPED) || ((argus->argus_far.status & ARGUS_ICMPUNREACH_MAPPED) && (store->queue->count > 0)))) { if (store->queue && ((str = RaNewArgusStore(argus)) != NULL)) { if ((str->data[0] = RaNewArgusData(argus)) != NULL) { RaAddToQueue (store->queue, &str->qhdr); str->data[0]->farhdrstatus = ArgusIndexRecord (str->data[0]->argus, str->data[0]->farhdrs); str->status |= RA_MODIFIED; } } } if (str != NULL) { if (!(str->data[RaThisActiveIndex])) { struct ArgusRecordData *data = NULL; if ((data = RaNewArgusData(argus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *)&data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } str->data[RaThisActiveIndex] = data; } else ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); } else RaMergeArgusRecord(argus, str, RaThisActiveIndex); } } #ifdef ARGUSDEBUG ArgusDebug (4, "RaUpdateArgusStore: \n"); #endif } void RaPrintSVGHeader(void); void RaPrintSVGFooter(void); void RaPrintSVGFunctions(struct ArgusRecordStore *); void RaPrintSVGHeader() { extern char version[]; fprintf (stdout, "\n"); fprintf (stdout, "\n"); fprintf (stdout, "\n", ArgusProgramName, version); fprintf (stdout, "\n"); fprintf (stdout, "Current Histogram Demo\n"); fprintf (stdout, "\n"); fprintf (stdout, " \n"); fprintf (stdout, " \n"); fprintf (stdout, "\n"); fprintf (stdout, "\n"); fflush(stdout); } #include #include #define RA_MAXQSCAN 25600 #define RA_MAXQSIZE 250000 void RaProcessQueue(struct RaQueueStruct *queue, unsigned char status) { struct ArgusRecordStore *obj = NULL; int cnt = 0; switch (status) { case ARGUS_STOP: { if (queue->count > 0) { if (RaPrintSVGOutput) { if (queue->count == 1) RaPrintSVGHeader(); else ArgusLog (LOG_ERR, "svg mode and multiple paths: error\n"); } while ((obj = (struct ArgusRecordStore *) RaPopQueue(queue)) != NULL) { if (RaPrintSVGOutput) { RaPrintSVGFunctions(obj); } else RaTimeoutArgusStore(obj); } if (RaPrintSVGOutput) RaPrintSVGFooter(); } break; } default: while (queue->count > RA_MAXQSIZE) { obj = (struct ArgusRecordStore *) RaRemoveFromQueue(RaModelerQueue, RaModelerQueue->start->prv); RaTimeoutArgusStore(obj); } if ((cnt = ((queue->count > RA_MAXQSCAN) ? RA_MAXQSCAN : queue->count)) != 0) { while (cnt--) { if ((obj = (struct ArgusRecordStore *) RaPopQueue(queue)) != NULL) { if (RaCheckTimeout(obj, NULL)) RaTimeoutArgusStore(obj); else RaAddToQueue(queue, &obj->qhdr); } else cnt++; } } break; } #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessQueue (0x%x, %d) returning\n", queue, status); #endif } int ArgusSeriesNumber = 0; int RaSendArgusRecord(struct ArgusRecordStore *store) { int retn = 0; RaPrintArgusPath(store); store->qhdr.logtime = ArgusGlobalTime; #ifdef ARGUSDEBUG ArgusDebug (4, "RaSendArgusRecord(0x%x) done.\n", store); #endif return (retn); } argus-clients-2.0.6.fixes.1/clients/rapath.h0000664000076600007660000000252207640476616014364 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 RaPath_h #define RaPath_h #include #include #include #include #include #include #include #include #define RA_MODIFIED 1 #define RA_CON 1 #define RA_DONE 2 struct ArgusPathRecord { struct ArgusQueueHeader qhdr; struct RaHashTableHeader *rahtblhdr; struct ArgusRecord *argus; }; void RaProcessQueue(struct RaQueueStruct *, unsigned char state); #endif argus-clients-2.0.6.fixes.1/clients/rapolicy.c0000664000076600007660000006611107640617754014726 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * rapolicy - check argus records against cisco access control * configuration. * * written by Carter Bullard, Olaf Gellert * */ #include #include #include #include int RaInitialized = 0; int RaReadPolicy (struct RaPolicyPolicyStruct **, char *); int RaParsePolicy (struct RaPolicyPolicyStruct *, char *); int RaCheckPolicy (struct ArgusRecord *, struct RaPolicyPolicyStruct *); int RaMeetsPolicyCriteria (struct ArgusRecord *, struct RaPolicyPolicyStruct *); int RaDoNotification (struct ArgusRecord *, struct RaPolicyPolicyStruct *); struct RaPolicyPolicyStruct *policy = NULL; void ArgusClientInit () { if (!(RaInitialized)) { RaInitialized++; RaWriteOut = 0; if (ArgusFlowModelFile != NULL) { RaReadPolicy (&policy, ArgusFlowModelFile); } } } int RaParseCompleting = 0; void RaParseComplete (int sig) { if (!RaParseCompleting) { RaParseCompleting++; } } void ArgusClientTimeout () { } void parse_arg (int argc, char**argv) { } void usage () { extern char version[]; fprintf (stderr, "Rapolicy Version %s\n", version); fprintf (stderr, "usage: %s \n", ArgusProgramName); fprintf (stderr, "usage: %s [-f policyfile] [ra-options] [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "options: -f read Cisco access control policy file.\n"); fprintf (stderr, " -a print record summaries on termination.\n"); fprintf (stderr, " -A print application bytes.\n"); fprintf (stderr, " -b dump packet-matching code.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); fprintf (stderr, " -d print number of from user data capture buffer.\n"); fprintf (stderr, " format: num | s | d | s:d\n"); #if defined (ARGUSDEBUG) fprintf (stderr, " -D specify debug level\n"); #endif fprintf (stderr, " -e convert user data using method.\n"); fprintf (stderr, " Supported types are and .\n"); fprintf (stderr, " -E write records that are rejected by the filter into \n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -n don't convert numbers to names.\n"); fprintf (stderr, " -p print fractional time with precision.\n"); fprintf (stderr, " -q quiet mode. don't print record outputs.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -R print out response data when availabile.\n"); fprintf (stderr, " -s [-][+[#]]field specify fields to print.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [[[yyyy/]mm/]dd.]hh[:mm[:ss]]\n"); fprintf (stderr, " [yyyy/]mm/dd\n"); fprintf (stderr, " -%%d{yMdhms}\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); fprintf (stderr, " -u print time in Unix time format.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif fprintf (stderr, " -w write output to . '-' denotes stdout.\n"); fprintf (stderr, " -z print Argus TCP state changes.\n"); fprintf (stderr, " -Z print actual TCP flag values.<'s'rc | 'd'st | 'b'oth>\n"); exit(1); } int RaLabelCounter = 0; void RaProcessThisRecord (struct ArgusRecord *argus); void RaProcessRecord (struct ArgusRecord *argus) { struct ArgusRecordStore *store = NULL; int process = 0; if (argus->ahdr.type & ARGUS_MAR) process++; else { switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: case IPPROTO_UDP: case IPPROTO_ICMP: process++; default: break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: default: break; } } if (process) { if (RaCheckPolicy (argus, policy)) { if ((store = RaNewArgusStore(argus)) != NULL) { if ((store->data[0] = RaNewArgusData(argus)) != NULL) { store->data[0]->status |= RA_MODIFIED; RaSendArgusRecord (store); RaDeleteArgusStore (store); } else ArgusLog (LOG_ERR, "RaProcessThisRecord: RaNewArgusData(0x%x) %s\n", argus, strerror(errno)); } else ArgusLog (LOG_ERR, "RaProcessThisRecord: RaNewArgusStore(0x%x) %s\n", argus, strerror(errno)); } } if (Nflag > 0) { if (--Nflag == 0) { RaParseComplete(SIGINT); } } } int RaSendArgusRecord(struct ArgusRecordStore *store) { struct ArgusRecordData *data; struct ArgusRecord *argus = NULL; int retn = 0, i; for (i = 0; i < RaHistoTimeSeries; i++) { if ((data = store->data[i]) != NULL) { argus = data->argus; if (!aflag) { #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif ArgusGenerateCanonicalRecord (argus, RaThisCanon); #ifdef _LITTLE_ENDIAN ArgusNtoH(argus); #endif if ((retn = argus_filter (ArgusFilterCode.bf_insns, RaThisCanon)) == 0) return (retn); } if ((ArgusWfileList != NULL) && (!(ArgusListEmpty(ArgusWfileList)))) { struct ArgusWfileStruct *wfile = NULL, *start = NULL; if ((wfile = ArgusFrontList(ArgusWfileList)) != NULL) { start = wfile; do { if ((exceptfile == NULL) || strcmp(wfile->filename, exceptfile)) { #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif ArgusWriteNewLogfile (wfile, argus); #ifdef _LITTLE_ENDIAN ArgusNtoH(argus); #endif } ArgusPopFrontList(ArgusWfileList); ArgusPushBackList(ArgusWfileList, wfile); wfile = ArgusFrontList(ArgusWfileList); } while (wfile != start); } } else { if (argus->ahdr.type & ARGUS_MAR) printf ("%s\n", get_man_string (argus)); else { if (Lflag && !(qflag)) { if (RaLabel == NULL) RaLabel = RaGenerateLabel(argus); if (!(RaLabelCounter++ % Lflag)) { printf ("%s\n", RaLabel); fflush (stdout); } if (Lflag < 0) Lflag = 0; } ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: { int srcportind = 0; if (argus->argus_far.flow.ip_flow.sport == 20) { if (RaPrintAlgorithms[3] == ArgusPrintDstPort) { RaPrintAlgorithms[3] = ArgusPrintSrcPort; srcportind++; } } printf ("%s", get_tcp_string (argus)); if (srcportind) RaPrintAlgorithms[3] = ArgusPrintDstPort; break; } case IPPROTO_ICMP: printf ("%s", get_icmp_string (argus)); break; default: printf ("%s", get_ip_string (argus)); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: printf ("%s", get_arp_string (argus)); break; default: printf ("%s", get_nonip_string (argus)); break; } printf ("\n"); } fflush (stdout); } } } store->qhdr.logtime = ArgusGlobalTime; #ifdef ARGUSDEBUG ArgusDebug (4, "RaSendArgusRecord(0x%x) done.\n", store); #endif return (retn); } #include char *RaParseErrorStr [POLICYERRORNUM] = { "access-list identifier not found", "policy id number not found", "permit/deny indication not found", "protocol indentifier not found", "no source address defined", "no source address mask defined", "wrong source port operator", "wrong source port specification" "no destination address defined", "no destination address mask defined", "wrong destination port operator", "wrong destination port specification", "access violation notification not found", }; int RaReadPolicy (struct RaPolicyPolicyStruct **policy, char *file) { int retn = 1, linenum = 0; struct RaPolicyPolicyStruct *pol, *policyLast = NULL; FILE *fd; char buffer [1024], *str; if (file) { if ((fd = fopen (file, "r")) != NULL) { while (fgets (buffer, 1024, fd)) { linenum++; if ((*buffer != '#') && (*buffer != '\n') && (*buffer != '!')) { if ((pol = (struct RaPolicyPolicyStruct *) calloc (1, sizeof (struct RaPolicyPolicyStruct))) != NULL) { pol->str = strdup (buffer); if (!(RaParsePolicy (pol, buffer))) { str = RaParseErrorStr[RaParseError]; ArgusLog (LOG_ERR, "RaReadPolicy %s parse error line %d: %s\n", file, linenum, str); retn = 0; } if (policyLast) { policyLast->nxt = pol; pol->prv = policyLast; policyLast = pol; } else *policy = policyLast = pol; } } } fclose (fd); } else { retn = 0; ArgusLog (LOG_ERR, "RaReadPolicy: fopen %s\n", strerror(errno)); } } #if defined(ARGUSDEBUG) ArgusDebug (2, "RaReadPolicy (0x%x, %s) returning %d\n", policy, file, retn); #endif return (retn); } #include #include #include #include #include int RaParsePolicy (struct RaPolicyPolicyStruct *policy, char *buf) { int retn = 1, error = -1, state = 0; char *act_word, *nxt_word; if (strncmp (buf, "access", 6)) { if (strstr (buf, "ip")) if (strstr (buf, "source-route")) policy->type = RA_SRCROUTED; } else { policy->type = RA_ACCESSLIST; /* set act_word to the word to be processed now, nxt_word to the following word */ act_word=strtok(buf, " "); if (act_word==NULL) { error++; } else { nxt_word=strtok(NULL, " "); if (nxt_word==NULL) { error++; } else { while ((nxt_word != NULL) && (*nxt_word != '\n') && (error==-1)) { switch (state) { case POLICYSTRING: if ((strcmp (act_word, POLICY_STRING))) { error=POLICYERR_NOACL; } break; case POLICYID: if (!(policy->policyID = atoi (act_word))) { error=POLICYERR_NOID; } break; case POLICYACTION: if (!(strcmp (act_word, "permit"))) policy->flags |= RA_PERMIT; else if (!(strcmp (act_word, "deny"))) policy->flags |= RA_DENY; else error=POLICYERR_NOACTION; break; case POLICYPROTO: if (isdigit((int)*act_word)) { policy->proto = atoi(act_word); policy->flags |= RA_PROTO_SET; } else { struct protoent *proto; if ((proto = getprotobyname(act_word)) != NULL) { policy->proto = proto->p_proto; policy->flags |= RA_PROTO_SET; } else { error=POLICYERR_NOPROTO; } } break; case POLICYSRC: if (!(strcmp(act_word, "any"))) { policy->src.addr = ntohl(inet_addr("0.0.0.0")); policy->src.mask = ntohl(inet_addr("255.255.255.255")); } else if (!(strcmp(act_word, "host"))) { policy->src.addr = ntohl(inet_addr(nxt_word)); policy->src.mask = ntohl(inet_addr("0.0.0.0")); act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) break; } else { policy->src.addr = ntohl(inet_addr(act_word)); policy->src.mask = ntohl(inet_addr(nxt_word)); act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) break; } /* now get next words, check for port number */ if (!(strncmp(nxt_word, "eq", 2))) { act_word=nxt_word; nxt_word=strtok(NULL, " "); policy->src_action = RA_EQ; if (!(policy->src_port_low = (arg_uint16) atoi (nxt_word))) error=POLICYERR_SPORT; act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) break; } else if (!(strncmp (nxt_word, "lt", 2))) { act_word=nxt_word; nxt_word=strtok(NULL, " "); policy->src_action = RA_LT; if (!(policy->src_port_low = (arg_uint16) atoi (nxt_word))) error=POLICYERR_SPORT; act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) break; } else if (!(strncmp (nxt_word, "gt", 2))) { act_word=nxt_word; nxt_word=strtok(NULL, " "); policy->src_action = RA_GT; if (!(policy->src_port_low = (arg_uint16) atoi (nxt_word))) error=POLICYERR_SPORT; act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) break; } else if (!(strncmp (nxt_word, "neq", 3))) { act_word=nxt_word; nxt_word=strtok(NULL, " "); policy->src_action = RA_NEQ; if (!(policy->src_port_low = (arg_uint16) atoi (nxt_word))) error=POLICYERR_SPORT; act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) break; } else if (!(strncmp (nxt_word, "established",11))) { act_word=nxt_word; nxt_word=strtok(NULL, " "); policy->src_action = RA_EST; if (!(policy->src_port_low = (arg_uint16) atoi (nxt_word))) error=POLICYERR_SPORT; act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) break; } else if (!(strncmp (nxt_word, "range", 5))) { act_word=nxt_word; nxt_word=strtok(NULL, " "); policy->src_action = RA_RANGE; if (!(policy->src_port_low = (arg_uint16) atoi (nxt_word))) error=POLICYERR_SPORT; act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) { error=POLICYERR_NODSTADR; break; } if (!(policy->src_port_hi = (arg_uint16) atoi (nxt_word))) error=POLICYERR_SPORT; act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) break; } break; case POLICYDST: if (!(strcmp(act_word, "any"))) { policy->dst.addr = ntohl(inet_addr("0.0.0.0")); policy->dst.mask = ntohl(inet_addr("255.255.255.255")); } else if (!(strcmp(act_word, "host"))) { policy->dst.addr = ntohl(inet_addr(nxt_word)); policy->dst.mask = ntohl(inet_addr("0.0.0.0")); act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) { break; } } else { policy->dst.addr = ntohl(inet_addr(act_word)); policy->dst.mask = ntohl(inet_addr(nxt_word)); act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) { break; } } /* now get next words, check for port number */ if (!(strncmp(nxt_word, "eq", 2))) { act_word=nxt_word; nxt_word=strtok(NULL, " "); policy->dst_action = RA_EQ; /* printf("xxx dst policy RA_EQ\n"); */ if (!(policy->dst_port_low = (arg_uint16) atoi (nxt_word))) error=POLICYERR_DPORT; act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) break; } else if (!(strncmp (nxt_word, "lt", 2))) { act_word=nxt_word; nxt_word=strtok(NULL, " "); policy->dst_action = RA_LT; if (!(policy->dst_port_low = (arg_uint16) atoi (nxt_word))) error=POLICYERR_DPORT; act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) break; } else if (!(strncmp (nxt_word, "gt", 2))) { act_word=nxt_word; nxt_word=strtok(NULL, " "); policy->dst_action = RA_GT; if (!(policy->dst_port_low = (arg_uint16) atoi (nxt_word))) error=POLICYERR_DPORT; act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) break; } else if (!(strncmp (nxt_word, "neq", 3))) { act_word=nxt_word; nxt_word=strtok(NULL, " "); policy->dst_action = RA_NEQ; if (!(policy->dst_port_low = (arg_uint16) atoi (nxt_word))) error=POLICYERR_DPORT; act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) break; } else if (!(strncmp (nxt_word, "established",11))) { act_word=nxt_word; nxt_word=strtok(NULL, " "); policy->dst_action = RA_EST; if ((nxt_word != NULL) && !(policy->dst_port_low = (arg_uint16) atoi (nxt_word))) error=POLICYERR_DPORT; act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) break; } else if (!(strncmp (nxt_word, "range", 5))) { act_word=nxt_word; nxt_word=strtok(NULL, " "); policy->dst_action = RA_RANGE; if (!(policy->dst_port_low = (arg_uint16) atoi (nxt_word))) error=POLICYERR_DPORT; act_word=nxt_word; nxt_word=strtok(NULL, " "); if (!(policy->dst_port_hi = (arg_uint16) atoi (nxt_word))) error=POLICYERR_DPORT; act_word=nxt_word; nxt_word=strtok(NULL, " "); if (nxt_word == NULL) break; } break; case POLICYNOTIFICATION: break; } /* end of switch */ buf = NULL; state++; act_word=nxt_word; nxt_word=strtok(NULL, " "); } /* end of while */ } } } if (error != -1) { RaParseError = error; retn = 0; } return (retn); } int RaCheckPolicy (struct ArgusRecord *argus, struct RaPolicyPolicyStruct *policy) { int retn = 0, policymatch = 0; /* xxx weg damit */ /* printf("\nxxx entry: src %u sp %u -> dst %u dp %u\n", flow->ip_flow.ip_src, flow->ip_flow.sport, flow->ip_flow.ip_dst, flow->ip_flow.dport); */ if (!((argus->ahdr.status) & ARGUS_MAR)) { if (policy) { while (policy) { if ((retn = RaMeetsPolicyCriteria (argus, policy))) { retn = RaDoNotification (argus, policy); policymatch = 1; break; } policy = policy->nxt; } } } return (retn); } int RaMeetsPolicyCriteria (struct ArgusRecord *argus, struct RaPolicyPolicyStruct *policy) { int retn = 0, i = 0; struct ArgusFlow *flow = &argus->argus_far.flow; u_char proto = flow->ip_flow.ip_p; arg_uint32 saddr = 0, daddr = 0; arg_uint16 sport = 0, dport = 0; switch (policy->type) { case RA_SRCROUTED: if ((argus->argus_far.attr_ip.soptions & (ARGUS_SSRCROUTE | ARGUS_LSRCROUTE)) || (argus->argus_far.attr_ip.doptions & (ARGUS_SSRCROUTE | ARGUS_LSRCROUTE))) retn++; break; case RA_ACCESSLIST: saddr = flow->ip_flow.ip_src; daddr = flow->ip_flow.ip_dst; sport = flow->ip_flow.sport; dport = flow->ip_flow.dport; for (i = 0, retn = 1; ((i < POLICYTESTCRITERIA) && retn); i++) { retn = 0; switch (i) { case POLICYTESTPROTO: if (policy->flags & (RA_PROTO_SET)) { if (policy->proto) { if (policy->proto == proto) retn++; } else retn++; } break; case POLICYTESTSRC: if ((saddr & ~policy->src.mask) == policy->src.addr) { retn++; } break; case POLICYTESTDST: if ((daddr & ~policy->dst.mask) == policy->dst.addr) { retn++; } break; case POLICYTESTSRCPORT: switch (policy->src_action) { case RA_EQ: if (sport == policy->src_port_low) { retn++; } else { } continue; case RA_LT: if (sport < policy->src_port_low) { retn++; } continue; case RA_GT: if (sport > policy->src_port_low) { retn++; } continue; case RA_NEQ: if (sport != policy->src_port_low) { retn++; } continue; case RA_RANGE: if ((sport < policy->src_port_low) || (sport > policy->src_port_hi)) { retn++; } continue; case RA_EST: { if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) { struct ArgusTCPObject *tcp = NULL; tcp = (struct ArgusTCPObject *)ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]; if (!(tcp->status & ARGUS_SAW_SYN)) { retn++; } } continue; } } case POLICYTESTDSTPORT: switch (policy->dst_action) { case RA_EQ: if (dport == policy->dst_port_low) { retn++; } else { } continue; case RA_LT: if (dport < policy->dst_port_low) { retn++; } continue; case RA_GT: if (dport > policy->dst_port_low) { retn++; } continue; case RA_NEQ: if (dport != policy->dst_port_low) { retn++; } continue; case RA_RANGE: if ((dport >= policy->dst_port_low) || (dport <= policy->dst_port_hi)) { retn++; } continue; case RA_EST: { if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) { struct ArgusTCPObject *tcp = NULL; tcp = (struct ArgusTCPObject *)ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]; if (!(tcp->status & ARGUS_SAW_SYN)) retn++; } continue; } default: retn++; break; } /* end of inner switch */ } /* end of outer switch */ } /* end of for */ } return (retn); } int RaDoNotification (struct ArgusRecord *argus, struct RaPolicyPolicyStruct *policy) { int retn = 1; if (policy) { if (policy->flags & RA_PERMIT) { if (Argusdflag > 1) { printf ("%s %s ", "policy: permitted", policy->str); } else retn = 0; } else { if (Argusdflag) printf ("%s %s ", "policy: denyed", policy->str); } } return (retn); } argus-clients-2.0.6.fixes.1/clients/rapolicy.h0000664000076600007660000000466307640476616014737 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ #define DEFAULT_POLICY "policy.conf" #define POLICY_STRING "access-list" #define POLICYFIELDNUM 7 #define POLICYSTRING 0 #define POLICYID 1 #define POLICYACTION 2 #define POLICYPROTO 3 #define POLICYSRC 4 #define POLICYDST 5 #define POLICYNOTIFICATION 6 #define POLICYERRORNUM 13 #define POLICYERR_NOACL 0 #define POLICYERR_NOID 1 #define POLICYERR_NOACTION 2 #define POLICYERR_NOPROTO 3 #define POLICYERR_NOSRCADR 4 #define POLICYERR_NOSRCMSK 5 #define POLICYERR_SP_ACT 6 #define POLICYERR_SPORT 7 #define POLICYERR_NODSTADR 8 #define POLICYERR_NODSTMSK 9 #define POLICYERR_DP_ACT 10 #define POLICYERR_DPORT 11 #define POLICYERR_NONOTE 12 #define POLICYTESTCRITERIA 5 #define POLICYTESTPROTO 0 #define POLICYTESTSRC 1 #define POLICYTESTSRCPORT 2 #define POLICYTESTDST 3 #define POLICYTESTDSTPORT 4 #define RA_PERMIT 0x10000 #define RA_DENY 0x20000 #define RA_PROTO_SET 1 #define RA_EQ 0x01 #define RA_LT 0x02 #define RA_GT 0x04 #define RA_NEQ 0x08 #define RA_EST 0x10 #define RA_RANGE 0x20 #define RA_SRCROUTED 0x01 #define RA_ACCESSLIST 0x02 struct ArgusNetStruct { arg_int32 operator; arg_uint32 addr; arg_uint32 mask; }; struct RaPolicyPolicyStruct { struct RaPolicyPolicyStruct *prv, *nxt; arg_int32 type, policyID; arg_int32 flags; struct ArgusNetStruct src, dst; arg_uint16 proto, src_port_low, src_port_hi; arg_uint16 dst_port_low, dst_port_hi, src_action, dst_action; arg_int32 notification; char *str; }; argus-clients-2.0.6.fixes.1/clients/rarpwatch.c0000664000076600007660000005371107640610353015065 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * rarpwatch - argus version of arpwatch * * written by Carter Bullard * QoSient, LLC * */ #include #include #include int RaReadArpTable (void); void RaProcessSrvRecord (struct ArgusServiceRecord *); int RaInitialized = 0; void ArgusClientInit () { if (!(RaInitialized)) { RaWriteOut = 0; if (ArgusFlowModelFile) if (RaReadArpTable() < 0) ArgusLog (LOG_ERR, "ArgusClientInit RaReadArpTable %s\n", strerror(errno)); if ((RaModelerQueue = RaNewQueue()) == NULL) ArgusLog (LOG_ERR, "ArgusClientInit RaNewQueue %s\n", strerror(errno)); if ((RaHashTable.array = (struct RaHashTableHeader **) ArgusCalloc (RA_HASHTABLESIZE, sizeof (struct RaHashTableHeader *))) != NULL) { RaHashTable.size = RA_HASHTABLESIZE; } if (Bflag) { if ((RaHoldingBuffer = (struct ArgusHoldingBuffer *) ArgusCalloc (1, sizeof(*RaHoldingBuffer))) != NULL) { if ((RaHoldingBuffer->array = (struct ArgusListStruct **) ArgusCalloc (Bflag, sizeof(void *))) != NULL) { RaHoldingBuffer->size = Bflag; } else { ArgusLog (LOG_ERR, "ArgusClientInit ArgusCalloc %s\n", strerror(errno)); } } else ArgusLog (LOG_ERR, "ArgusClientInit ArgusCalloc %s\n", strerror(errno)); } if (nflag) { hfield = 15; pfield = 5; } RaInitialized++; } } int RaParseCompleting = 0; void RaParseComplete (int sig) { if ((sig >= 0) && (!RaParseCompleting)) { RaParseCompleting++; if (RaModelerQueue) RaProcessQueue (RaModelerQueue, ARGUS_STOP); } #ifdef ARGUSDEBUG ArgusDebug (1, "RaParseComplete: returning\n"); #endif } void ArgusClientTimeout () { RaProcessQueue (RaModelerQueue, ARGUS_STATUS); #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusClientTimeout: current time %s.\n", print_time(&ArgusGlobalTime)); if (ArgusMinuteUpdate++ == 60) { ArgusDebug (2, "ArgusClientTimeout: current time %s HashHdrs %d Hash %d Queue %d\n", print_time(&ArgusGlobalTime), RaAllocHashTableHeaders, RaHashTable.count, RaModelerQueue->count); ArgusMinuteUpdate = 1; } if (ArgusHourlyUpdate++ == 3600) { ArgusDebug (2, "ArgusClientTimeout: current time %s.\n", print_time(&ArgusGlobalTime)); ArgusHourlyUpdate = 1; } #endif } void parse_arg (int argc, char**argv) { } void usage () { extern char version[]; fprintf (stderr, "Rarpwatch Version %s\n", version); fprintf (stderr, "usage: %s [-f arpconffile]\n", ArgusProgramName); fprintf (stderr, "usage: %s [-f arpconffile] [ra-options]\n", ArgusProgramName); fprintf (stderr, "options: -f read flow model from .\n"); fprintf (stderr, "ra-options: -b dump packet-matching code.\n"); fprintf (stderr, " -D specify debug level\n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -p print fractional time with precision.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [mm/dd[/yy].]hh[:mm[:ss]]\n"); fprintf (stderr, " mm/dd[/yy]\n"); fprintf (stderr, " -%%d{yMhdms}\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); fprintf (stderr, " -u print time in Unix time format.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif exit(1); } void RaProcessRecord (struct ArgusRecord *argus) { switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_ARP: case ETHERTYPE_REVARP: RaProcessARPRecord (argus); break; default: break; } } void RaProcessSrvRecord (struct ArgusServiceRecord *srv) { struct ArgusRecord *argus = srv->argus; struct ArgusArpFlow *arpFlow; struct ArgusRecordStore *store; int RaTimeout = -1; RaThisActiveDuration = RaGetActiveDuration(argus); if (Hflag) { RaThisActiveIndex = (RaThisActiveDuration < 100) ? 0 : (RaThisActiveDuration < 500) ? 1 : (RaThisActiveDuration < 1000) ? 2 : (RaThisActiveDuration < 5000) ? 3 : (RaThisActiveDuration < 10000) ? 4 : (RaThisActiveDuration < 50000) ? 4 : (RaThisActiveDuration < 100000) ? 5 : (RaThisActiveDuration < 500000) ? 6 : (RaThisActiveDuration < 100000) ? 7 : (RaThisActiveDuration < 250000) ? 8 : (RaThisActiveDuration < 500000) ? 9 : (RaThisActiveDuration < 750000) ? 10: (RaThisActiveDuration < 1000000) ? 11: (RaThisActiveDuration < 5000000) ? 12: (RaThisActiveDuration < 10000000) ? 13: (RaThisActiveDuration < 50000000) ? 14: 15; } else RaThisActiveIndex = 0; RaTimeout = 0x1FFFFFF; arpFlow = &argus->argus_far.flow.arp_flow; arpFlow->arp_spa = 0; bcopy ((char *) argus->argus_far.attr_arp.response, arpFlow->etheraddr, sizeof(arpFlow->etheraddr)); if ((store = RaFindArgusRecord(&RaHashTable, argus)) == NULL) if ((store = RaFindRevArgusRecord(&RaHashTable, argus)) != NULL) { } if (store) { RaThisArgusStore = store; if (RaCheckTimeout (store, argus)) RaSendArgusRecord(store); if ((srv->status & RA_SVCTEST) != (store->status & RA_SVCTEST)) { RaSendArgusRecord(store); store->status &= ~RA_SVCTEST; store->status |= (srv->status & RA_SVCTEST); } if (!(store->data[RaThisActiveIndex])) { struct ArgusRecordData *data = NULL; if ((data = RaNewArgusData(argus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; data->status |= srv->status & RA_SVCTEST; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *) &data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } store->data[RaThisActiveIndex] = data; } else ArgusLog (LOG_ERR, "RaProcessSrvRecord RanewArgusData %s\n", strerror(errno)); } else RaMergeArgusRecord(argus, store, RaThisActiveIndex); RaUpdateArgusStore(argus, store); } else { if ((store = RaNewArgusStore(argus)) != NULL) { struct ArgusRecordData *data = NULL; store->ArgusTimeout = RaTimeout; RaThisArgusStore = store; store->status |= RA_MODIFIED; store->status |= srv->status & RA_SVCTEST; if ((data = RaNewArgusData(argus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *) &data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } store->data[RaThisActiveIndex] = data; if ((store->rahtblhdr = RaAddHashEntry (&RaHashTable, store)) != NULL) RaAddToQueue(RaModelerQueue, &store->qhdr); } else ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); } else ArgusLog (LOG_ERR, "RaNewArgusStore failed %s\n", strerror(errno)); } #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessRecord: done\n"); #endif } struct ArgusServiceRecord ArgusThisSrv; char *get_rarpwatch_string (struct ArgusRecord *); extern char argus_strbuf[]; char * get_rarpwatch_string (struct ArgusRecord *argus) { struct ArgusFlow *flow; char srcString[256], dstString[256]; char date[128], fmtstr[256]; int src_count, dst_count, src_bytes, dst_bytes; bzero (argus_strbuf, MAXSTRLEN); bzero (date, 128); flow = &argus->argus_far.flow; src_count = argus->argus_far.src.count; dst_count = argus->argus_far.dst.count; if (Aflag) { src_bytes = argus->argus_far.src.appbytes; dst_bytes = argus->argus_far.dst.appbytes; } else { src_bytes = argus->argus_far.src.bytes; dst_bytes = argus->argus_far.dst.bytes; } ArgusPrintDate (date, argus); if ((argus->ahdr.status & 0xFFFF) == ETHERTYPE_ARP) { strcpy (srcString, ipaddr_string (&flow->arp_flow.arp_tpa)); strcpy (dstString, etheraddr_string (argus->argus_far.attr_arp.response)); strcpy (fmtstr, "%-17.17s %-15.15s %s"); sprintf (&argus_strbuf[strlen(argus_strbuf)], fmtstr, dstString, srcString, date); } return (argus_strbuf); } void RaProcessARPRecord (struct ArgusRecord *argus) { ArgusThisSrv.argus = argus; if (argus->argus_far.src.count && argus->argus_far.dst.count) { ArgusThisSrv.status = RA_SVCPASSED; RaProcessSrvRecord (&ArgusThisSrv); } } int RaSendArgusRecord(struct ArgusRecordStore *store) { char buf[MAXSTRLEN]; struct ArgusRecordData *data; struct ArgusRecord *argus = NULL; struct ArgusFarHeaderStruct *farhdr; struct ArgusAGRStruct *agr = NULL; int retn = 0, i; for (i = 0; i < RaHistoTimeSeries; i++) { if ((data = store->data[i]) != NULL) { argus = data->argus; if (argus && (data->status & RA_MODIFIED)) { if (data->act.n > 0) { data->agr.act.n = data->act.n; data->agr.act.meanval = data->act.sumtime/data->act.n; data->agr.act.stdev = sqrt (data->act.sumsqrd/data->act.n - pow (data->act.sumtime/data->act.n, 2.0)); } if (data->idle.n > 0) { data->agr.idle.n = data->idle.n; data->agr.idle.meanval = data->idle.sumtime/data->idle.n; data->agr.idle.stdev = sqrt (data->idle.sumsqrd/data->idle.n - pow (data->idle.sumtime/data->idle.n, 2.0)); } ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) != NULL) bcopy ((char *)&data->agr, (char *) agr, data->agr.length); bcopy ((char *) argus, buf, argus->ahdr.length); argus = (struct ArgusRecord *) buf; ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); agr = NULL; if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) == NULL) { if (ArgusFlowModelFile && (data->agr.count > 1)) { bcopy ((char *)&data->agr, &buf[argus->ahdr.length], data->agr.length); argus->ahdr.length += data->agr.length; argus->ahdr.status |= ARGUS_MERGED; ArgusFree (data->argus); data->argus = RaCopyArgusRecord(argus); } else argus->ahdr.status &= ~(ARGUS_MERGED); } if ((ArgusWfileList != NULL) && (!(ArgusListEmpty(ArgusWfileList)))) { struct ArgusWfileStruct *wfile = NULL, *start = NULL; if ((wfile = ArgusFrontList(ArgusWfileList)) != NULL) { start = wfile; do { if ((exceptfile == NULL) || strcmp(wfile->filename, exceptfile)) { #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif ArgusWriteNewLogfile (wfile, argus); #ifdef _LITTLE_ENDIAN ArgusNtoH(argus); #endif } ArgusPopFrontList(ArgusWfileList); ArgusPushBackList(ArgusWfileList, wfile); wfile = ArgusFrontList(ArgusWfileList); } while (wfile != start); } } else { if (argus->ahdr.type & ARGUS_MAR) printf ("%s\n", get_man_string (argus)); else { ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: printf ("%s\n", get_tcp_string (argus)); break; case IPPROTO_ICMP: printf ("%s\n", get_icmp_string (argus)); break; default: printf ("%s\n", get_ip_string (argus)); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: fprintf (stdout, "%s\n", get_rarpwatch_string (argus)); break; default: printf ("%s\n", get_nonip_string (argus)); break; } } fflush (stdout); } argus = data->argus; if (argus->ahdr.type & ARGUS_FAR) { int farlen, length = argus->ahdr.length - sizeof(argus->ahdr); farhdr = (struct ArgusFarHeaderStruct *)((char *)argus + sizeof(argus->ahdr)); while (length > 0) { switch (farhdr->type) { case ARGUS_FAR: { struct ArgusFarStruct *far = (struct ArgusFarStruct *) farhdr; far->time.start.tv_sec = 0x7FFFFFFF; far->time.start.tv_usec = 0; far->time.last.tv_sec = 0; far->time.last.tv_usec = 0; far->src.count = 0; far->src.bytes = 0; far->dst.count = 0; far->dst.bytes = 0; break; } case ARGUS_TCP_DSR: { struct ArgusTCPObject *tcp = (struct ArgusTCPObject *) farhdr; tcp->state = 0; tcp->src.seqbase = 0; tcp->src.ackbytes = 0; tcp->src.rpkts = 0; tcp->src.win = 0; tcp->src.flags = 0; tcp->dst.seqbase = 0; tcp->dst.ackbytes = 0; tcp->dst.rpkts = 0; tcp->dst.win = 0; tcp->dst.flags = 0; break; } case ARGUS_TIME_DSR: { struct ArgusTimeStruct *time = (struct ArgusTimeStruct *) farhdr; time->src.act.n = 0; time->src.act.meanval = 0; time->src.act.stdev = 0; time->src.act.maxval = 0; time->src.act.minval = 0x7FFFFFFF; time->src.idle.n = 0; time->src.idle.meanval = 0; time->src.idle.stdev = 0; time->src.idle.maxval = 0; time->src.idle.minval = 0x7FFFFFFF; time->dst.act.n = 0; time->dst.act.meanval = 0; time->dst.act.stdev = 0; time->dst.act.maxval = 0; time->dst.act.minval = 0x7FFFFFFF; time->dst.idle.n = 0; time->dst.idle.meanval = 0; time->dst.idle.stdev = 0; time->dst.idle.maxval = 0; time->dst.idle.minval = 0x7FFFFFFF; break; } case ARGUS_VLAN_DSR: { struct ArgusVlanStruct *vlan = (struct ArgusVlanStruct *) farhdr; vlan->status &= ~(ARGUS_SRC_CHANGED | ARGUS_DST_CHANGED); break; } case ARGUS_MPLS_DSR: { struct ArgusMplsStruct *mpls = (struct ArgusMplsStruct *) farhdr; mpls->status &= ~(ARGUS_SRC_CHANGED | ARGUS_DST_CHANGED); break; } case ARGUS_AGR_DSR: { struct ArgusAGRStruct *agr = (struct ArgusAGRStruct *) farhdr; agr->count = 0; agr->act.n = 0; agr->act.minval = 0x7FFFFFFF; agr->act.meanval = 0; agr->act.stdev = 0; agr->act.maxval = 0; agr->idle.n = 0; agr->idle.minval = 0x7FFFFFFF; agr->idle.meanval = 0; agr->idle.stdev = 0; agr->idle.maxval = 0; break; } } if ((farlen = farhdr->length) == 0) break; if ((farhdr->type == ARGUS_SRCUSRDATA_DSR) || (farhdr->type == ARGUS_DSTUSRDATA_DSR)) farlen = farlen * 4; length -= farlen; farhdr = (struct ArgusFarHeaderStruct *)((char *)farhdr + farlen); } } data->agr.count = 0; data->agr.act.n = 0; data->agr.act.meanval = 0; data->agr.act.stdev = 0; data->agr.act.maxval = 0; data->agr.act.minval = 0x7FFFFFFF; data->agr.idle.n = 0; data->agr.idle.meanval = 0; data->agr.idle.stdev = 0; data->agr.idle.maxval = 0; data->agr.idle.minval = 0x7FFFFFFF; data->act.n = 0; data->act.sumtime = 0; data->act.sumsqrd = 0; data->idle.n = 0; data->idle.sumtime = 0; data->idle.sumtime = 0; data->argus->ahdr.status &= ~ARGUS_MERGED; data->status &= ~RA_MODIFIED; } } } store->qhdr.logtime = ArgusGlobalTime; #ifdef ARGUSDEBUG ArgusDebug (4, "RaSendArgusRecord(0x%x) done.\n", store); #endif return (retn); } int RaReadArpTable () { return (0); } #include #include #define RA_MAXQSCAN 25600 void RaProcessQueue(struct RaQueueStruct *queue, unsigned char status) { struct ArgusRecordStore *obj = NULL; int cnt = 0; switch (status) { case ARGUS_STOP: while ((obj = (struct ArgusRecordStore *) RaPopQueue(queue)) != NULL) RaTimeoutArgusStore(obj); break; default: if ((cnt = ((queue->count > RA_MAXQSCAN) ? RA_MAXQSCAN : queue->count)) != 0) { while (cnt--) { if ((obj = (struct ArgusRecordStore *) RaPopQueue(queue)) != NULL) { if (RaCheckTimeout(obj, NULL)) RaTimeoutArgusStore(obj); else RaAddToQueue(queue, &obj->qhdr); } else cnt++; } } break; } #ifdef ARGUSDEBUG ArgusDebug (4, "RaProcessQueue (0x%x, %d) returning\n", queue, status); #endif } argus-clients-2.0.6.fixes.1/clients/rarpwatch.h0000664000076600007660000000222207640610353015061 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 RarpWatch_h #define RarpWatch_h #include #include #include #include #include #include #include #include void RaProcessQueue(struct RaQueueStruct *, unsigned char state); #endif argus-clients-2.0.6.fixes.1/clients/raseq.c0000664000076600007660000001550107640610353014200 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * raseq - count missing sequence numbers * * written by Carter Bullard * QoSient, LLC * */ #include #include #include int RaInitialized = 0; void ArgusClientInit () { if (!(RaInitialized)) { RaInitialized++; if (!(RaSeqQueue = RaNewQueue())) ArgusLog (LOG_ERR, "ArgusClientInit %s\n", strerror(errno)); } } int RaParseCompleting = 0; unsigned int ArgusSequenceNumber = 0; unsigned int ArgusMissingSeqNum = 0; int ArgusSeqError = 0; int RaTotalOutofOrder = 0; int RaTotalRecords = 0; int RaSendArgusRecord(struct ArgusRecordStore *argus) {return 0;} void RaParseComplete (int sig) { struct RaQueueHeader *obj = NULL, *last = NULL; if ((sig >= 0) && (!RaParseCompleting)) { RaParseCompleting++; if ((RaGetQueueCount(RaSeqQueue)) > 1) { while ((obj = (struct RaQueueHeader *) RaPopQueue(RaSeqQueue))) { if (last != NULL) { ArgusMissingSeqNum += obj->start - last->end; ArgusFree(last); last = NULL; } last = obj; } if (obj != NULL) ArgusFree(obj); } if (ArgusMissingSeqNum > 0) printf ("%d missing sequence numbers\n", ArgusMissingSeqNum); if (aflag) { printf ("RaTotalRecords %d\n", RaTotalRecords); printf ("RaTotalOutofOrder %d\n", RaTotalOutofOrder); } fflush (stdout); } exit (ArgusMissingSeqNum); } void ArgusClientTimeout () { } void parse_arg (int argc, char**argv) { } void usage () { extern char version[]; fprintf (stderr, "Ratemplate Version %s\n", version); fprintf (stderr, "usage: %s \n", ArgusProgramName); fprintf (stderr, "usage: %s [options] -S remoteServer [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "usage: %s [options] -r argusDataFile [- filter-expression]\n\n", ArgusProgramName); fprintf (stderr, "options: -b dump packet-matching code.\n"); fprintf (stderr, " -D specify debug level\n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [mm/dd[/yy].]hh[:mm[:ss]]\n"); fprintf (stderr, " mm/dd[/yy]\n"); fprintf (stderr, " -%%d{yMhdms}\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif exit(1); } struct RaQueueHeader *RaLastObj = NULL; struct RaQueueHeader *RaFindQueueEntry (int); void RaProcessRecord (struct ArgusRecord *argus) { struct RaQueueHeader *obj = NULL; struct ArgusRecordHeader *ahdr = &argus->ahdr; unsigned int thisSeq = ahdr->seqNumber; int thisSeqOutofOrder = 0; if (!(argus->ahdr.type & ARGUS_MAR)) { if ((ArgusSequenceNumber + 1) != thisSeq) { if (ArgusSequenceNumber != 0) thisSeqOutofOrder++; if ((RaLastObj = RaFindQueueEntry(thisSeq)) != NULL) { RaLastObj->end = thisSeq; if (RaLastObj->nxt && (RaLastObj->nxt->start == (thisSeq + 1))) { RaLastObj->end = RaLastObj->nxt->end; RaRemoveFromQueue (RaSeqQueue, (struct ArgusQueueHeader *) RaLastObj->nxt); } } else { if ((obj = (struct RaQueueHeader *) ArgusCalloc (1, sizeof(*obj))) != NULL) { obj->start = thisSeq; obj->end = thisSeq; RaAddToQueue(RaSeqQueue, (struct ArgusQueueHeader *) obj); if ((obj->end + 1) == (obj->nxt->start)) { obj->end = obj->nxt->end; RaRemoveFromQueue (RaSeqQueue, (struct ArgusQueueHeader *) obj->nxt); } RaLastObj = obj; } } } else { if (RaLastObj != NULL) { RaLastObj->end = thisSeq; if (RaLastObj->nxt->start == (thisSeq + 1)) { RaLastObj->end = RaLastObj->nxt->end; RaRemoveFromQueue(RaSeqQueue, (struct ArgusQueueHeader *) RaLastObj->nxt); } } else { struct RaQueueHeader *obj = NULL; if ((obj = (struct RaQueueHeader *) ArgusCalloc (1, sizeof(*obj))) != NULL) { obj->start = thisSeq; obj->end = thisSeq; RaAddToQueue(RaSeqQueue, (struct ArgusQueueHeader *) obj); if ((obj->end + 1) == (obj->nxt->start)) { obj->end = obj->nxt->end; RaRemoveFromQueue (RaSeqQueue, (struct ArgusQueueHeader *) obj->nxt); } RaLastObj = obj; } } } ArgusSequenceNumber = ahdr->seqNumber; if (aflag) { RaTotalRecords++; if (thisSeqOutofOrder) RaTotalOutofOrder++; } } } struct RaQueueHeader * RaFindQueueEntry (int seq) { struct RaQueueHeader *retn = NULL; int found = 0; if (RaSeqQueue && RaSeqQueue->count) { if ((retn = (struct RaQueueHeader *) RaSeqQueue->start) != NULL) { do { if ((retn->end + 1) == seq) { found++; break; } retn = retn->nxt; } while (!found && (retn != (struct RaQueueHeader *) RaSeqQueue->start)); if (!found) retn = NULL; } } return (retn); } argus-clients-2.0.6.fixes.1/clients/raseq.h0000664000076600007660000000232207640476616014216 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 RaSeq_h #define RaSeq_h #include #include struct RaQueueHeader { struct RaQueueHeader *prv, *nxt; struct RaQueueStruct *queue; int status; struct timeval lasttime, logtime; int start, end; }; struct RaQueueStruct *RaSeqQueue = NULL; void RaProcessQueue(struct RaQueueStruct *, unsigned char state); #endif argus-clients-2.0.6.fixes.1/clients/rasort.c0000664000076600007660000001761507640610353014407 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * rasort - sort argus records. * * written by Carter Bullard * QoSient, LLC * */ #include #include int RaSortRoutine (const void *, const void *); void ArgusClientInit () { struct ArgusModeStruct *mode; int i = 0, x = 0; if (!(RaInitialized)) { RaWriteOut = 0; if ((RaArgusRecordQueue = RaNewQueue()) == NULL) ArgusLog (LOG_ERR, "ArgusClientInit: RaNewQueue error %s\n", strerror(errno)); bzero ((char *) RaSortAlgorithms, sizeof(RaSortAlgorithms)); RaSortAlgorithms[0] = RaSortAlgorithmTable[0]; if ((mode = ArgusModeList) != NULL) { while (mode) { for (x = 0; x < MAX_SORT_ALG_TYPES; x++) { if (!strncmp (RaSortKeyWords[x], mode->mode, strlen(RaSortKeyWords[x]))) { RaSortAlgorithms[i++] = RaSortAlgorithmTable[x]; break; } } if (x == MAX_SORT_ALG_TYPES) ArgusLog (LOG_ERR, "sort syntax error. \'%s\' not supported", mode->mode); mode = mode->nxt; } } RaInitialized++; } #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusClientInit () returning\n"); #endif } int RaParseCompleting = 0; void RaParseComplete (int sig) { int i = 0; if ((sig >= 0) && (!RaParseCompleting)) { RaParseCompleting++; if (Nflag == 0) Nflag = RaArgusRecordQueue->count; if (Nflag > 0) { RaSortQueue (RaArgusRecordQueue); for (i = 0; i < Nflag; i++) RaSendArgusRecord ((struct ArgusRecordStore *) RaArgusRecordQueue->array[i]); } } } void ArgusClientTimeout () { } void parse_arg (int argc, char**argv) { } void usage () { extern char version[]; fprintf (stderr, "Rasort Version %s\n", version); fprintf (stderr, "usage: %s [[-M sortfield] [-M sortfield] ...] [ra-options] [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "options: -M specify the (s) in order.\n"); fprintf (stderr, " valid sorfields are:\n"); fprintf (stderr, " startime, lasttime, duration,\n"); fprintf (stderr, " srcaddr, dstaddr, proto, sport, dport,\n"); fprintf (stderr, " stos, dtos, sttl, dttl,\n"); fprintf (stderr, " bytes, srcbytes, dstbytes,\n"); fprintf (stderr, " packets, srcpackets, dstpackets.\n"); fprintf (stderr, "\n"); fprintf (stderr, "ra-options: -b dump packet-matching code.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); fprintf (stderr, " -D specify debug level\n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -s [-][+[#]]field specify fields to print.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [mm/dd[/yy].]hh[:mm[:ss]]\n"); fprintf (stderr, " mm/dd[/yy]\n"); fprintf (stderr, " -%%d{yMhdms}\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif fprintf (stderr, " -w write output to . '-' denotes stdout.\n"); exit(1); } void RaProcessRecord (struct ArgusRecord *argus) { struct ArgusRecordStore *obj = NULL; if (argus->ahdr.type & ARGUS_MAR) RaProcessManRecord (argus); else { if (argus != NULL) { if ((obj = RaNewArgusStore(argus)) != NULL) { if ((obj->data[0] = RaNewArgusData(argus)) != NULL) RaAddToQueue(RaArgusRecordQueue, &obj->qhdr); else ArgusLog (LOG_ERR, "RaProcessRecord: RaNewArgusData(0x%x) %s\n", argus, strerror(errno)); } else ArgusLog (LOG_ERR, "RaProcessRecord: RaNewArgusStore(0x%x) %s\n", argus, strerror(errno)); } } #ifdef ARGUSDEBUG ArgusDebug (4, "RaProcessRecord(0x%x) done.\n", argus); #endif } u_char ArgusRecordBuffer[1024]; int ArgusLastRecord = 0; void RaProcessManRecord (struct ArgusRecord *argus) { if ((argus->ahdr.cause & ARGUS_STOP)) { bcopy ((char *) ArgusOriginal, ArgusRecordBuffer, argus->ahdr.length); ArgusLastRecord++; } } int RaSendArgusRecord(struct ArgusRecordStore *store) { struct ArgusRecord *argus = store->data[0]->argus; int retn = 0; if ((ArgusWfileList != NULL) && (!(ArgusListEmpty(ArgusWfileList)))) { struct ArgusWfileStruct *wfile = NULL, *start = NULL; if ((wfile = ArgusFrontList(ArgusWfileList)) != NULL) { start = wfile; do { if ((exceptfile == NULL) || strcmp(wfile->filename, exceptfile)) { #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif ArgusWriteNewLogfile (wfile, argus); #ifdef _LITTLE_ENDIAN ArgusNtoH(argus); #endif } ArgusPopFrontList(ArgusWfileList); ArgusPushBackList(ArgusWfileList, wfile); wfile = ArgusFrontList(ArgusWfileList); } while (wfile != start); } } else { if (argus->ahdr.type & ARGUS_MAR) printf ("%s\n", get_man_string (argus)); else { ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: printf ("%s\n", get_tcp_string (argus)); break; case IPPROTO_ICMP: printf ("%s\n", get_icmp_string (argus)); break; default: printf ("%s\n", get_ip_string (argus)); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: printf ("%s\n", get_arp_string (argus)); break; default: printf ("%s\n", get_nonip_string (argus)); break; } } fflush (stdout); } #ifdef ARGUSDEBUG ArgusDebug (4, "RaSendArgusRecord(0x%x) done.\n", store); #endif return (retn); } argus-clients-2.0.6.fixes.1/clients/rasort.h0000664000076600007660000000244707640610353014411 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 RaSort_h #define RaSort_h #include #include #include #include #include #include #include #include int RaInitialized = 0; struct ArgusRecord *RaCopyArgusRecord (struct ArgusRecord *); void RaPackQueue (struct RaQueueStruct *); void RaSortQueue (struct RaQueueStruct *); struct RaQueueStruct *RaArgusRecordQueue = NULL; #endif argus-clients-2.0.6.fixes.1/clients/rasrvstats.c0000664000076600007660000012076207640610353015307 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * rasrvstats - argus server statistics. * * written by Carter Bullard * QoSient, LLC * */ #include #include #include int RaReadServicesFile(char *); void RaProcessThisSrvRecord (struct ArgusServiceRecord *); void RaProcessSrvRecord (struct ArgusServiceRecord *); void RaProcessSrvDiscovery (struct ArgusServiceRecord *); char *RaSrvStatsFlowModelFile [] = { "Flow 100 ip * * * * * 200 31536000 31536000", "Flow 101 ip * * * * * 201 31536000 31536000", "Flow 103 ip * * * * * 203 31536000 31536000", "Flow 104 ip * * * * * 204 31536000 31536000", "Flow 105 ip * * * * * 205 31536000 31536000", "Model 200 ip 0.0.0.0 0.0.0.0 yes no yes", "Model 201 ip 0.0.0.0 255.255.255.0 yes no yes", "Model 203 ip 0.0.0.0 255.255.255.255 yes no yes", "Model 204 ip 255.255.255.0 255.255.255.255 yes no yes", "Model 205 ip 255.255.255.255 255.255.255.255 yes no yes", NULL, }; int RaInitialized = 0; struct ArgusRecordStore RaGlobalStoreBuf, *RaGlobalStore = &RaGlobalStoreBuf; struct RaFlowModelStruct *RaFlowModel = NULL; void ArgusClientInit () { struct ArgusModeStruct *mode; int i, x; if (!(RaInitialized)) { RaWriteOut = 0; bzero ((char *) RaGlobalStore, sizeof(RaGlobalStoreBuf)); RaFlowModel = RaReadFlowModelFile (RaSrvStatsFlowModelFile); if (!(RaFlowModel)) usage(); if ((RaModelerQueue = RaNewQueue()) == NULL) exit(0); if ((RaSrvHashTable.array = (struct RaSrvHashTableHeader **) ArgusCalloc (RA_HASHTABLESIZE, sizeof (struct RaSrvHashTableHeader *))) != NULL) { RaSrvHashTable.size = RA_HASHTABLESIZE; } if ((RaHashTable.array = (struct RaHashTableHeader **) ArgusCalloc (RA_HASHTABLESIZE, sizeof (struct RaHashTableHeader *))) != NULL) { RaHashTable.size = RA_HASHTABLESIZE; } RaGlobalStore->queue = RaModelerQueue; RaGlobalStore->htable = &RaHashTable; RaModelerQueue->htable = &RaHashTable; if (ArgusFlowModelFile) if ((RaReadServicesFile(ArgusFlowModelFile)) < 0) exit(0); ArgusFlowModelFile = *RaSrvStatsFlowModelFile; if (Hflag) if (!(RaHistoTimeParse (Hstr))) usage(); bzero ((char *) RaSortAlgorithms, sizeof(RaSortAlgorithms)); RaSortAlgorithms[0] = RaSortAlgorithmTable[0]; if ((mode = ArgusModeList) != NULL) { while (mode) { for (i = 0, x = 0; x < MAX_SORT_ALG_TYPES; x++) { if (!strncmp (RaSortKeyWords[x], mode->mode, strlen(RaSortKeyWords[x]))) { RaSortAlgorithms[i++] = RaSortAlgorithmTable[x]; break; } } if (x == MAX_SORT_ALG_TYPES) ArgusLog (LOG_ERR, "sort syntax error. \'%s\' not supported", mode->mode); mode = mode->nxt; } } else RaSortAlgorithms[0] = RaSortAlgorithmTable[RASORTPKTSCOUNT]; RaInitialized++; } } void RaSortQueue (struct RaQueueStruct *); void RaPrintOutQueue (struct RaQueueStruct *, int); int RaParseCompleting = 0; #define ARGUS_MAXFLOWDEFS 5 #define ARGUS_SERVICE 0 #define ARGUS_SERVICE_SUBNET 1 #define ARGUS_SERVER 2 #define ARGUS_CLIENT_SUBNET 3 #define ARGUS_CLIENT 4 int RaTotals[ARGUS_MAXFLOWDEFS] = {0, 0, 0, 0, 0,}; void RaParseComplete (int sig) { if ((sig >= 0) && (!RaParseCompleting)) { RaParseCompleting++; if (RaTotals[ARGUS_SERVICE] > 0) { printf ("%s Total Services %d Total Servers %d Total Clients %d\n", ArgusProgramName, RaTotals[ARGUS_SERVICE], RaTotals[ARGUS_SERVER], RaTotals[ARGUS_CLIENT]); RaPrintOutQueue (RaModelerQueue, 0); } } #ifdef ARGUSDEBUG ArgusDebug (1, "RaParseComplete: returning\n"); #endif } void ArgusClientTimeout () { RaProcessQueue (RaModelerQueue, ARGUS_STATUS); #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusClientTimeout: current time %s.\n", print_time(&ArgusGlobalTime)); if (ArgusMinuteUpdate++ == 60) { ArgusDebug (2, "ArgusClientTimeout: current time %s HashHdrs %d Hash %d Queue %d\n", print_time(&ArgusGlobalTime), RaAllocHashTableHeaders, RaHashTable.count, RaModelerQueue->count); ArgusMinuteUpdate = 1; } if (ArgusHourlyUpdate++ == 3600) { ArgusDebug (2, "ArgusClientTimeout: current time %s.\n", print_time(&ArgusGlobalTime)); ArgusHourlyUpdate = 1; } #endif } void parse_arg (int argc, char**argv) { } void usage () { fprintf (stderr, "Rasrvstats Version %d.%d\n", major_version, minor_version); fprintf (stderr, "usage: %s \n", ArgusProgramName); fprintf (stderr, "usage: %s [ra-options] [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "options: -b dump packet-matching code.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); fprintf (stderr, " -d specify debug level\n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -n don't convert numbers to names.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [mm/dd[/yy].]hh[:mm[:ss]]\n"); fprintf (stderr, " mm/dd[/yy]\n"); fprintf (stderr, " -%%d{yMhdms}\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); fprintf (stderr, " -u print time in Unix time format.\n"); fprintf (stderr, " -U print fractional time with this precision.\n"); fprintf (stderr, " -w write output to . '-' denotes stdout.\n"); exit(1); } void RaProcessRecord (struct ArgusRecord *argus) { if (argus->ahdr.type & ARGUS_MAR) RaProcessManRecord (argus); else { switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: RaProcessTCPRecord (argus); break; case IPPROTO_UDP: RaProcessUDPRecord (argus); break; case IPPROTO_ICMP: RaProcessICMPRecord (argus); break; case IPPROTO_IGMP: break; default: RaProcessIPRecord (argus); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: RaProcessARPRecord (argus); break; default: RaProcessNonIPRecord (argus); break; } } } void RaProcessThisSrvRecord (struct ArgusServiceRecord *srv) { if (srv->status & RA_SVCPASSED) RaProcessSrvRecord(srv); if (srv->status & RA_SVCDISCOVERY) RaProcessSrvDiscovery(srv); } extern int RaFlowMajorModified; extern int RaHistoStart; extern int RaHistoEnd; extern int RaHistoBins; void RaProcessSrvDiscovery (struct ArgusServiceRecord *srv) { } void RaProcessSrvRecord (struct ArgusServiceRecord *srv) { struct ArgusRecord *argus = srv->argus; struct ArgusRecord *targus = NULL; struct ArgusRecordStore *RaThisPrvStore = RaGlobalStore; struct ArgusRecordStore *store; struct RaPolicyStruct *rap; int RaTimeout = -1, i, index = 0; RaThisActiveDuration = RaGetActiveDuration(argus); RaFlowMajorModified = 1; RaThisActiveIndex = RaHistoTimeSeries; if (Hflag) { if ((RaThisActiveDuration >= RaHistoStart) && (RaThisActiveDuration <= RaHistoEnd)) { for (i = 0; i < RaHistoTimeSeries; i++) { if (RaThisActiveDuration < RaHistoTimeValues[i]) { RaThisActiveIndex = i; break; } } } else return; } else RaThisActiveIndex = 0; for (i = 0; i < ARGUS_MAXFLOWDEFS; i++) { if (i == ARGUS_CLIENT) index = RaThisActiveIndex; if (((rap = RaFlowModel->policy[i]) != NULL) && (RaPolicyMatch (argus, rap))) { targus = RaCopyArgusRecord(argus); RaModifyFlow(rap, targus, RaFlowModel); RaTimeout = rap->ArgusTimeout; if ((store = RaFindArgusRecord(RaThisPrvStore->htable, targus)) != NULL) { RaThisArgusStore = store; if ((srv->status & RA_SVCTEST) != (store->status & RA_SVCTEST)) { RaSendArgusRecord(store); store->status &= ~RA_SVCTEST; store->status |= (srv->status & RA_SVCTEST); } if (!(store->data[index])) { struct ArgusRecordData *data = NULL; if ((data = RaNewArgusData(targus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; data->status |= srv->status & RA_SVCTEST; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *) &data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } store->data[index] = data; } else ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); } else RaMergeArgusRecord(targus, store, RaThisActiveIndex); RaUpdateArgusStore(targus, store); } else { if ((store = RaNewArgusStore(targus)) != NULL) { struct ArgusRecordData *data = NULL; RaTotals[i]++; if ((store->htable = (struct RaHashTableStruct *) ArgusCalloc (1, sizeof (*store->htable))) != NULL) { if ((store->htable->array = (struct RaHashTableHeader **) ArgusCalloc (RA_HASHTABLESIZE, sizeof (struct RaHashTableHeader *))) != NULL) { store->htable->size = RA_HASHTABLESIZE; } else ArgusLog (LOG_ERR, "RaSrvProcessRecord ArgusCalloc %s\n", strerror(errno)); } else ArgusLog (LOG_ERR, "RaSrvProcessRecord ArgusCalloc %s\n", strerror(errno)); store->ArgusTimeout = RaTimeout; RaThisArgusStore = store; store->status |= RA_MODIFIED; store->status |= srv->status & RA_SVCTEST; if ((data = RaNewArgusData(targus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *)&data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } store->data[index] = data; if ((store->rahtblhdr = RaAddHashEntry (RaThisPrvStore->htable, store)) != NULL) { if (RaThisPrvStore != NULL) RaAddToQueue(RaThisPrvStore->queue, &store->qhdr); else RaAddToQueue(RaModelerQueue, &store->qhdr); } } else ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); } else ArgusLog (LOG_ERR, "RaNewArgusStore failed %s\n", strerror(errno)); } RaThisPrvStore = store; if (i != ARGUS_CLIENT) if (store->queue == NULL) store->queue = RaNewQueue(); ArgusFree(targus); } } #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessRecord: done\n"); #endif } void RaProcessManRecord (struct ArgusRecord *argus) { } struct ArgusServiceRecord ArgusThisSrv; void RaProcessTCPRecord (struct ArgusRecord *argus) { struct ArgusTCPObject *tcp = NULL; unsigned int mask; ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Vflag) { if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) { if ((tcp = (struct ArgusTCPObject *) ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]) != NULL) { if (tcp->state & (ARGUS_SAW_SYN || ARGUS_SAW_SYN_SENT)) { if (tcp->state & ARGUS_RESET) { if (!(tcp->src.ackbytes || tcp->dst.ackbytes)) ArgusThisSrv.status = RA_SVCFAILED; } else if (!(tcp->state & (ARGUS_FIN | ARGUS_FIN_ACK | ARGUS_NORMAL_CLOSE))) ArgusThisSrv.status = RA_SVCINCOMPLETE; } else ArgusThisSrv.status = RA_SVCINCOMPLETE; } } } if ((mask = ipaddrtonetmask(argus->argus_far.flow.ip_flow.ip_dst)) != 0) if ((argus->argus_far.flow.ip_flow.ip_dst & mask) == mask) ArgusThisSrv.status |= RA_SVCDISCOVERY; if (((unsigned char *)&argus->argus_far.flow.ip_flow.ip_dst)[0] == 224) ArgusThisSrv.status |= RA_SVCMULTICAST; RaProcessThisSrvRecord (&ArgusThisSrv); } void RaProcessICMPRecord (struct ArgusRecord *argus) { /* ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Vflag) { if ((argus->argus_far.src.count > 0) && (argus->argus_far.dst.count == 0)) { ArgusThisSrv.status = RA_SVCFAILED; } else { ArgusThisSrv.status = RA_SVCPASSED; } } RaProcessThisSrvRecord (&ArgusThisSrv); */ } void RaProcessUDPRecord (struct ArgusRecord *argus) { int srccount, dstcount; unsigned int mask; ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; srccount = argus->argus_far.src.count; dstcount = argus->argus_far.dst.count; if (Vflag) if ((srccount == 0) || (dstcount == 0)) ArgusThisSrv.status = RA_SVCFAILED; if (argus->argus_far.flow.ip_flow.tp_p == ARGUS_RTP_FLOWTAG) if (!((argus->argus_far.src.count > 3) || (argus->argus_far.dst.count > 3))) argus->argus_far.flow.ip_flow.tp_p = 0; if (Rflag) { struct ArgusAGRStruct *agr; if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) != NULL) { if (!((srccount == dstcount) && (srccount == agr->count))) ArgusThisSrv.status = RA_SVCFAILED; } else { if (!((srccount == 1) && (dstcount == 1))) ArgusThisSrv.status = RA_SVCFAILED; } } if ((mask = ipaddrtonetmask(argus->argus_far.flow.ip_flow.ip_dst)) != 0) if ((argus->argus_far.flow.ip_flow.ip_dst & mask) == mask) ArgusThisSrv.status |= RA_SVCDISCOVERY; if (((unsigned char *)&argus->argus_far.flow.ip_flow.ip_dst)[0] == 224) ArgusThisSrv.status |= RA_SVCMULTICAST; RaProcessThisSrvRecord (&ArgusThisSrv); } void RaProcessIPRecord (struct ArgusRecord *argus) { unsigned int mask; ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Vflag) { if ((argus->argus_far.src.count > 0) && (argus->argus_far.dst.count == 0)) { ArgusThisSrv.status = RA_SVCFAILED; } else { ArgusThisSrv.status = RA_SVCPASSED; } } if (Rflag) if (!((argus->argus_far.src.count == 1) && (argus->argus_far.dst.count == 1))) ArgusThisSrv.status = RA_SVCFAILED; if ((mask = ipaddrtonetmask(argus->argus_far.flow.ip_flow.ip_dst)) != 0) if ((argus->argus_far.flow.ip_flow.ip_dst & mask) == mask) ArgusThisSrv.status |= RA_SVCDISCOVERY; if (((unsigned char *)&argus->argus_far.flow.ip_flow.ip_dst)[0] == 224) ArgusThisSrv.status |= RA_SVCMULTICAST; RaProcessThisSrvRecord (&ArgusThisSrv); } void RaProcessARPRecord (struct ArgusRecord *argus) { } void RaProcessNonIPRecord (struct ArgusRecord *argus) { } int RaSendArgusRecord(struct ArgusRecordStore *store) { int retn = 0; /* char buf[MAXSTRLEN], *ptr = buf; struct ArgusRecordData *data; struct ArgusRecord *argus = NULL; struct ArgusFarHeaderStruct *farhdr; int i; for (i = 0; i < RaHistoTimeSeries; i++) { if ((data = store->data[i]) != NULL) { argus = data->argus; if (argus && (data->status & RA_MODIFIED)) { if (data->act.n > 0) { data->agr.act.n = data->act.n; data->agr.act.meanval = data->act.sumtime/data->act.n; data->agr.act.stdev = sqrt (data->act.sumsqrd/data->act.n - pow (data->act.sumtime/data->act.n, 2.0)); } if (data->idle.n > 0) { data->agr.idle.n = data->idle.n; data->agr.idle.meanval = data->idle.sumtime/data->idle.n; data->agr.idle.stdev = sqrt (data->idle.sumsqrd/data->idle.n - pow (data->idle.sumtime/data->idle.n, 2.0)); } bcopy ((char *) argus, buf, argus->ahdr.length); argus = (struct ArgusRecord *) ptr; if (data->agr.count > 0) { bcopy ((char *)&data->agr,&buf[argus->ahdr.length], data->agr.length); argus->ahdr.length += data->agr.length; argus->ahdr.status |= ARGUS_MERGED; } else argus->ahdr.status &= ~(ARGUS_MERGED); argus->argus_far.time.last = data->agr.lasttime; if ((ArgusWfileList != NULL) && (!(ArgusListEmpty(ArgusWfileList)))) { struct ArgusWfileStruct *wfile = NULL, *start = NULL; if ((wfile = ArgusFrontList(ArgusWfileList)) != NULL) { start = wfile; do { if ((exceptfile == NULL) || strcmp(wfile->filename, exceptfile)) { #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif ArgusWriteNewLogfile (wfile, argus); #ifdef _LITTLE_ENDIAN ArgusNtoH(argus); #endif } ArgusPopFrontList(ArgusWfileList); ArgusPushBackList(ArgusWfileList, wfile); wfile = ArgusFrontList(ArgusWfileList); } while (wfile != start); } } else { if (argus->ahdr.type & ARGUS_MAR) printf ("%s\n", get_man_string (argus)); else { ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: printf ("%s\n", get_tcp_string (argus)); break; case IPPROTO_ICMP: printf ("%s\n", get_icmp_string (argus)); break; default: printf ("%s\n", get_ip_string (argus)); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: printf ("%s\n", get_arp_string (argus)); break; default: printf ("%s\n", get_nonip_string (argus)); break; } } fflush (stdout); } argus = data->argus; if (argus->ahdr.type & ARGUS_FAR) { int farlen, length = argus->ahdr.length - sizeof(argus->ahdr);; farhdr = (struct ArgusFarHeaderStruct *)((char *)argus + sizeof(argus->ahdr)); while (length > 0) { switch (farhdr->type) { case ARGUS_FAR: { struct ArgusFarStruct *far = (struct ArgusFarStruct *) farhdr; far->time.start.tv_sec = 0x7FFFFFFF; far->time.start.tv_usec = 0; far->time.last.tv_sec = 0x7FFFFFFF; far->time.last.tv_usec = 0; far->src.count = 0; far->src.bytes = 0; far->dst.count = 0; far->dst.bytes = 0; break; } case ARGUS_TCP_DSR: { struct ArgusTCPObject *tcp = (struct ArgusTCPObject *) farhdr; tcp->state = 0; tcp->src.seqbase = 0; tcp->src.ackbytes = 0; tcp->src.rpkts = 0; tcp->src.win = 0; tcp->src.flags = 0; tcp->dst.seqbase = 0; tcp->dst.ackbytes = 0; tcp->dst.rpkts = 0; tcp->dst.win = 0; tcp->dst.flags = 0; break; } case ARGUS_AGR_DSR: { struct ArgusAGRStruct *agr = (struct ArgusAGRStruct *) farhdr; agr->count = 0; agr->act.n = 0; agr->act.minval = 0x7FFFFFFF; agr->act.meanval = 0; agr->act.stdev = 0; agr->act.maxval = 0; agr->idle.n = 0; agr->idle.minval = 0x7FFFFFFF; agr->idle.meanval = 0; agr->idle.stdev = 0; agr->idle.maxval = 0; break; } } farlen = farhdr->length; if ((farhdr->type == ARGUS_SRCUSRDATA_DSR) || (farhdr->type == ARGUS_DSTUSRDATA_DSR)) farlen = farlen * 4; length -= farlen; farhdr = (struct ArgusFarHeaderStruct *)((char *)farhdr + farlen); } } data->agr.count = 0; data->agr.act.minval = 0x7FFFFFFF; data->agr.act.meanval = 0; data->agr.act.stdev = 0; data->agr.act.maxval = 0; data->agr.idle.minval = 0x7FFFFFFF; data->agr.idle.meanval = 0; data->agr.idle.stdev = 0; data->agr.idle.maxval = 0; data->act.sumtime = 0; data->act.n = 0; data->idle.sumtime = 0; data->idle.n = 0; data->argus->ahdr.status &= ~ARGUS_MERGED; data->status &= ~RA_MODIFIED; } } } */ store->qhdr.logtime = ArgusGlobalTime; #ifdef ARGUSDEBUG ArgusDebug (4, "RaSendArgusRecord(0x%x) done.\n", store); #endif return (retn); } #include #include #define RA_MAXQSCAN 25600 int RaSortCountsArgusStore (const void *, const void *); int RaSortAddrsArgusStore (const void *, const void *); int RaSortCountsArgusStore (const void *void1, const void *void2) { int retn = 0, i; struct ArgusRecord *argus; struct ArgusRecordStore *store1 = *(struct ArgusRecordStore **)void1; struct ArgusRecordStore *store2 = *(struct ArgusRecordStore **)void2; if (store1->sortag == 0) { for (i = 0; i < RaHistoTimeSeries; i++) { if ((store1->data[i]) && ((argus = store1->data[i]->argus) != NULL)) { store1->sortag += argus->argus_far.src.count; store1->sortag += argus->argus_far.dst.count; } } } if (store2->sortag == 0) { for (i = 0; i < RaHistoTimeSeries; i++) { if ((store2->data[i]) && ((argus = store2->data[i]->argus) != NULL)) { store2->sortag += argus->argus_far.src.count; store2->sortag += argus->argus_far.dst.count; } } } retn = (store2->sortag - store1->sortag); return (retn); } int RaSortAddrsArgusStore (const void *void1, const void *void2) { int retn = 0, i; struct ArgusRecordStore *store1 = *(struct ArgusRecordStore **)void1; struct ArgusRecordStore *store2 = *(struct ArgusRecordStore **)void2; struct ArgusRecord *argus1 = NULL, *argus2 = NULL; for (i = 0; i < RaHistoTimeSeries; i++) { if (store1->data[i]) { argus1 = store1->data[i]->argus; break; } } for (i = 0; i < RaHistoTimeSeries; i++) { if (store2->data[i]) { argus2 = store2->data[i]->argus; break; } } if (argus1 && argus2) if (!(retn = (argus2->argus_far.flow.ip_flow.ip_dst - argus1->argus_far.flow.ip_flow.ip_dst))) retn = (argus2->argus_far.flow.ip_flow.ip_src - argus1->argus_far.flow.ip_flow.ip_src); return (retn); } #include struct RaSrvDescTableEntry { int srvDport, srvDaddr, proto, port; char *name, *desc; }; struct RaSrvDescTableEntry *RaFindSrvHashObject (int, int); void RaPrintOutQueue (struct RaQueueStruct *queue, int level) { struct ArgusIPFlow *ipFlow = NULL; struct ArgusRecordStore *obj = NULL; struct ArgusRecordData *data = NULL; struct RaSrvDescTableEntry *dtblent = NULL; double value; int i = 0, n, num = Nflag; struct ArgusAGRStruct *ArgusThisAgr = NULL; struct timeval buf, *time = &buf; if (queue != NULL) { RaSortQueue (queue); if (Nflag == 0) num = queue->count; for (n = 0; n < num; n++) { if ((obj = (struct ArgusRecordStore *) queue->array[n]) != NULL) { for (i = 0; i < RaHistoTimeSeries; i++) { if ((data = obj->data[i]) != NULL) { ipFlow = &data->argus->argus_far.flow.ip_flow; switch (level) { case ARGUS_SERVICE: printf("\n"); switch (ipFlow->ip_p) { case IPPROTO_TCP: { if ((ipFlow->dport == 0xFFFF) && (ipFlow->sport == 20)) { unsigned short port = ipFlow->sport; if ((dtblent = RaFindSrvHashObject(ipFlow->ip_p, port)) != NULL) printf("Service: %-8s src tcp port %-5d \"%s\"\n", dtblent->name, dtblent->port, dtblent->desc); else printf("Service: %-8s src tcp port %-5d\n", tcpport_string(port), port); } else { unsigned short port = ipFlow->dport; if ((dtblent = RaFindSrvHashObject(ipFlow->ip_p, port)) != NULL) printf("Service: %-12s tcp port %-5d \"%s\"\n", dtblent->name, dtblent->port, dtblent->desc); else printf("Service: %-12s tcp port %-5d\n", tcpport_string(port), port); } fflush(stdout); break; } case IPPROTO_UDP: if ((dtblent = RaFindSrvHashObject(ipFlow->ip_p, ipFlow->dport)) != NULL) printf("Service: %-12s udp port %-5d \"%s\"\n", dtblent->name, dtblent->port, dtblent->desc); else printf("Service: %-12s udp port %-5d\n", udpport_string(ipFlow->dport), ipFlow->dport); fflush(stdout); break; case IPPROTO_IGMP: printf("Service: igmp:\n"); fflush(stdout); break; default: printf("Service: %s\n", get_ip_string(data->argus)); fflush(stdout); break; } break; case ARGUS_SERVICE_SUBNET: break; case ARGUS_SERVER: printf(" Server: %-20.20s Trans Mean (sec)\n", ipaddr_string(&ipFlow->ip_dst)); fflush(stdout); break; case ARGUS_CLIENT_SUBNET: break; case ARGUS_CLIENT: if (data->act.n > 0) { data->agr.act.meanval = data->act.sumtime/data->act.n; value = (data->act.sumsqrd/data->act.n - pow (data->act.sumtime/data->act.n, 2.0)); data->agr.act.stdev = sqrt (value); data->agr.act.n = data->act.n; } if (data->idle.n > 0) { data->agr.idle.meanval = data->idle.sumtime/data->idle.n; value = (data->idle.sumsqrd/data->idle.n - pow (data->idle.sumtime/data->idle.n, 2.0)); data->agr.idle.stdev = sqrt (value); data->agr.idle.n = data->idle.n; } if ((ArgusThisAgr = (struct ArgusAGRStruct *) &data->agr)) { int ArgusThisMultiplier = 1000; if (ArgusThisAgr->status & ARGUS_AGR_USECACTTIME) ArgusThisMultiplier = 1000000; time->tv_sec = ArgusThisAgr->act.meanval / ArgusThisMultiplier; time->tv_usec = ArgusThisAgr->act.meanval % ArgusThisMultiplier; } printf(" %15.15s: %5d %4d.%06d ", ipaddr_string(&ipFlow->ip_src), data->agr.count, (int) time->tv_sec, (int) time->tv_usec); if ((ArgusThisAgr = (struct ArgusAGRStruct *) &data->agr)) { int ArgusThisMultiplier = 1000; if (ArgusThisAgr->status & ARGUS_AGR_USECACTTIME) ArgusThisMultiplier = 1000000; time->tv_sec = ArgusThisAgr->act.stdev / ArgusThisMultiplier; time->tv_usec = ArgusThisAgr->act.stdev % ArgusThisMultiplier; } /* printf(" %4d.%06d - ", (int) time->tv_sec, (int) time->tv_usec); if ((ArgusThisAgr = (struct ArgusAGRStruct *) &data->agr)) { int ArgusThisMultiplier = 1000; if (ArgusThisAgr->status & ARGUS_AGR_USECACTTIME) ArgusThisMultiplier = 1000000; time->tv_sec = ArgusThisAgr->act.minval / ArgusThisMultiplier; time->tv_usec = ArgusThisAgr->act.minval % ArgusThisMultiplier; } */ printf(" +/- %d.%06d\n", (int) time->tv_sec, (int) time->tv_usec); break; } } } if (Hflag && (level == ARGUS_CLIENT)) printf("\n"); fflush(stdout); RaPrintOutQueue (obj->queue, level + 1); } else break; } } } void RaProcessQueue(struct RaQueueStruct *queue, unsigned char status) { struct ArgusRecordStore *obj = NULL; struct ArgusRecord *argus = NULL; int cnt = 0; switch (status) { case ARGUS_STOP: while (queue->count) { if ((obj = (struct ArgusRecordStore *) RaPopQueue(queue)) != NULL) { if (obj->htable) { if (obj->htable->array) { ArgusFree(obj->htable->array); obj->htable->array = NULL; } ArgusFree(obj->htable); obj->htable = NULL; } RaTimeoutArgusStore(obj); } } break; default: if ((cnt = ((queue->count > RA_MAXQSCAN) ? RA_MAXQSCAN : queue->count)) != 0) { while (cnt--) { if ((obj = (struct ArgusRecordStore *) RaPopQueue(queue)) != NULL) { argus = obj->data[0]->argus; if (RaCheckTimeout(obj, argus)) { if (obj->htable) { if (obj->htable->array) { ArgusFree(obj->htable->array); obj->htable->array = NULL; } ArgusFree(obj->htable); obj->htable = NULL; } RaTimeoutArgusStore(obj); } else RaAddToQueue(queue, &obj->qhdr); } else cnt++; } } break; } #ifdef ARGUSDEBUG ArgusDebug (4, "RaProcessQueue (0x%x, %d) returning\n", queue, status); #endif } struct RaSrvDescTableEntry * RaFindSrvHashObject (int proto, int port) { struct RaSrvDescTableEntry *retn = NULL; struct RaSrvHashTableHeader *head = NULL, *target = NULL; struct RaSrvHash RaThisSrvHash; unsigned short hash = 0; hash += ((unsigned short *)&proto)[0]; hash += ((unsigned short *)&proto)[1]; hash += ((unsigned short *)&port)[0]; hash += ((unsigned short *)&port)[1]; RaThisSrvHash.srvProto = proto; RaThisSrvHash.srvPort = port; if ((target = RaSrvHashTable.array[hash % RaSrvHashTable.size]) != NULL) { head = target; do { if (!(bcmp ((char *)&RaThisSrvHash, (char *) &target->srvhash, sizeof(RaThisSrvHash)))) { retn = target->storeobj; break; } else target = target->nxt; } while (target != head); } #ifdef ARGUSDEBUG ArgusDebug (5, "RaFindSrvHashObject: returning 0x%x\n", retn); #endif return (retn); } struct RaSrvHashTableHeader * RaAddSrvHashEntry (struct RaSrvDescTableEntry *store) { struct RaSrvHashTableHeader *retn = NULL; struct RaSrvHashTableHeader *start = NULL; struct RaSrvHash RaThisSrvHash; unsigned short hash = 0; if ((retn = (struct RaSrvHashTableHeader *) ArgusCalloc (1, sizeof (struct RaSrvHashTableHeader))) != NULL) { retn->storeobj = store; bzero ((char *) &RaThisSrvHash, sizeof(RaThisSrvHash)); RaThisSrvHash.srvProto = store->proto; RaThisSrvHash.srvPort = store->port; hash += ((unsigned short *)&store->proto)[0]; hash += ((unsigned short *)&store->proto)[1]; hash += ((unsigned short *)&store->port)[0]; hash += ((unsigned short *)&store->port)[1]; retn->srvhash = RaThisSrvHash; retn->hash = hash; if ((start = RaSrvHashTable.array[hash % RaSrvHashTable.size]) != NULL) { retn->nxt = start; retn->prv = start->prv; retn->prv->nxt = retn; retn->nxt->prv = retn; } else retn->prv = retn->nxt = retn; RaSrvHashTable.array[hash % RaSrvHashTable.size] = retn; RaSrvHashTable.count++; } #ifdef ARGUSDEBUG ArgusDebug (6, "RaAddSrvHashEntry (0x%x) returning 0x%x\n", store, retn); #endif return (retn); } void RaRemoveSrvHashEntry (struct RaSrvHashTableHeader *rahtblhdr) { unsigned short hash = rahtblhdr->hash; rahtblhdr->prv->nxt = rahtblhdr->nxt; rahtblhdr->nxt->prv = rahtblhdr->prv; if (rahtblhdr == RaSrvHashTable.array[hash % RaSrvHashTable.size]) { if (rahtblhdr == rahtblhdr->nxt) RaSrvHashTable.array[hash % RaSrvHashTable.size] = NULL; else RaSrvHashTable.array[hash % RaSrvHashTable.size] = rahtblhdr->nxt; RaSrvHashTable.count--; } ArgusFree (rahtblhdr); RaAllocHashTableHeaders--; #ifdef ARGUSDEBUG ArgusDebug (4, "RaRemoveSrvHashObject (0x%x) returning\n", rahtblhdr); #endif } int RaCreateSrvTableEntry(int, char *); int RaCreateSrvTableEntry(int linenum, char *str) { struct RaSrvDescTableEntry *dtblent; char namebuf[1024], descbuf[1024], *ptr, *tmp; int retn = 0; bzero (namebuf, 1024); bzero (descbuf, 1024); if ((dtblent = (struct RaSrvDescTableEntry *) ArgusCalloc (1, sizeof(*dtblent))) != NULL) { if (sscanf (str, "%d %d %d %d", &dtblent->srvDport, &dtblent->srvDaddr, &dtblent->proto, &dtblent->port)) { if ((ptr = strchr (str, (int) '"')) != NULL) if ((tmp = strchr ((++ptr), (int) '"')) != NULL) { *tmp++ = '\0'; dtblent->name = strdup(ptr); str = tmp; } if ((ptr = strchr (str, (int) '"')) != NULL) if ((tmp = strchr (++ptr, (int) '"')) != NULL) { *tmp++ = '\0'; dtblent->desc = strdup(ptr); } } if (dtblent != NULL) RaAddSrvHashEntry(dtblent); } return (retn); } int RaReadServicesFile(char *srvfile) { int retn = 0, RaSrvFileLineNumber = 0; char buf[MAXSTRLEN], *str; FILE *fd = NULL; if (srvfile != NULL) { if ((fd = fopen (srvfile, "r")) != NULL) { while ((str = fgets (buf, MAXSTRLEN, fd)) != NULL) { RaSrvFileLineNumber++; while (isspace((int)*str)) str++; if (strlen(str)) { switch (buf[0]) { case '#': case '\n': case '!': break; default: if ((str = strdup(str)) != NULL) { if (RaCreateSrvTableEntry(RaSrvFileLineNumber, str) < 0) { fprintf (stderr, "%s: RaReadServicesFile: parse error line %d\n", ArgusProgramName, RaSrvFileLineNumber); exit (-1); } } else ArgusLog (LOG_ERR, "RaReadServiceFile: error %s\n", strerror(errno)); } } } fclose(fd); } } else ArgusLog (LOG_ERR, "RaReadServicesFile: %s %s\n", srvfile, strerror(errno)); return (retn); } argus-clients-2.0.6.fixes.1/clients/rasrvstats.h0000664000076600007660000000332107640610353015303 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 RaSrvStats_h #define RaSrvStats_h #include #include #include #include #include #include #include #include struct RaSrvHash { int srvProto, srvPort; }; struct RaSrvHashTableHeader { struct RaSrvHashTableHeader *nxt, *prv; struct RaSrvHashTableStruct *htable; unsigned short hash; struct RaSrvHash srvhash; void *storeobj; }; struct RaSrvHashTableStruct { int size, count; struct RaSrvHashTableHeader **array; }; struct RaSrvHashTableStruct RaSrvHashTable; struct RaSrvDescTableEntry *RaFindSrvHashObject (int, int); struct RaSrvHashTableHeader *RaAddSrvHashEntry (struct RaSrvDescTableEntry *); void RaRemoveSrvHashEntry (struct RaSrvHashTableHeader *); void RaProcessQueue(struct RaQueueStruct *, unsigned char state); #endif argus-clients-2.0.6.fixes.1/clients/rastrip.c0000664000076600007660000003621507640610353014556 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * rastrip - argus data client that strips unwanted DSR's from argus * records. By default it strips them all. * * written by Carter Bullard * QoSient, LLC * */ #include #include int ArgusStripDown = 0; int RaFirstMOptionField = 1; #define RASTRIP_DSR_TYPES 19 #define RASTRIP_DSR_FAR 0 #define RASTRIP_DSR_MAC 1 #define RASTRIP_DSR_TCP 2 #define RASTRIP_DSR_ICMP 3 #define RASTRIP_DSR_RTP 4 #define RASTRIP_DSR_ARP 6 #define RASTRIP_DSR_FRG 7 #define RASTRIP_DSR_ESP 8 #define RASTRIP_DSR_MPLS 9 #define RASTRIP_DSR_VLAN 10 #define RASTRIP_DSR_PPPOE 11 #define RASTRIP_DSR_AGR 12 #define RASTRIP_DSR_TIME 13 #define RASTRIP_DSR_SRCTIME 14 #define RASTRIP_DSR_DSTTIME 15 #define RASTRIP_DSR_USRDATA 16 #define RASTRIP_DSR_SRCUSRDATA 17 #define RASTRIP_DSR_DSTUSRDATA 18 int RaDSRFields[RASTRIP_DSR_TYPES]; char *RaDSRKeyWords[RASTRIP_DSR_TYPES] = { "far", "mac", "tcp", "icmp", "rtp", "igmp", "arp", "frag", "esp", "mpls", "vlan", "pppoe", "agr", "jitter", "stime", "dtime", "user", "srcuser", "dstuser", }; void RaProcessMOptions(struct ArgusModeStruct *); #define RA_ADD_OPTION 1 #define RA_SUB_OPTION 2 void RaProcessMOptions(struct ArgusModeStruct *mode) { int x, RaOptionOperation, setValue = 0; char *ptr = NULL; char *endptr; if (mode != NULL) { while (mode) { if (isdigit(*mode->mode)) { ArgusStripDown = strtol(mode->mode, &endptr, 10); if (mode->mode == endptr) usage(); } else { if (*mode->mode == '-') { if (RaFirstMOptionField) { for (x = 0; x < RASTRIP_DSR_TYPES; x++) RaDSRFields[x] = 1; RaFirstMOptionField = 0; } ptr = mode->mode + 1; RaOptionOperation = RA_SUB_OPTION; } else if (*mode->mode == '+') { ptr = mode->mode + 1; RaOptionOperation = RA_ADD_OPTION; } else { if (RaFirstMOptionField) { bzero ((char *) RaDSRFields, sizeof(RaDSRFields)); RaFirstMOptionField = 0; } ptr = mode->mode; RaOptionOperation = RA_ADD_OPTION; } setValue = (RaOptionOperation == RA_ADD_OPTION) ? 1 : 0; for (x = 0; x < RASTRIP_DSR_TYPES; x++) { if (!strncmp (RaDSRKeyWords[x], ptr, strlen(RaPrintKeyWords[x]))) { switch (x) { case RASTRIP_DSR_USRDATA: { RaDSRFields[RASTRIP_DSR_SRCUSRDATA] = setValue; RaDSRFields[RASTRIP_DSR_DSTUSRDATA] = setValue; break; } default: RaDSRFields[x] = setValue; break; } } } mode = mode->nxt; } } } } void ArgusClientInit () { struct ArgusModeStruct *mode; if (!(RaInitialized)) { RaWriteOut = 0; RaCumulativeMerge = 1; if (ArgusInputFileList == NULL) usage(); bzero ((char *)RaDSRFields, sizeof(RaDSRFields)); RaDSRFields[RASTRIP_DSR_FAR] = 1; RaDSRFields[RASTRIP_DSR_TCP] = 1; if ((mode = ArgusModeList) != NULL) RaProcessMOptions(mode); if (!(ArgusStripDown)) ArgusStripDown++; } } int RaParseCompleting = 0; void RaParseComplete (int sig) { if ((sig >= 0) && (!RaParseCompleting)) RaParseCompleting++; } void ArgusClientTimeout () { } void parse_arg (int argc, char**argv) { } void usage () { extern char version[]; fprintf (stderr, "Rastrip Version %s\n", version); fprintf (stderr, "usage: %s \n", ArgusProgramName); fprintf (stderr, "usage: %s [options] -r argusDataFile [- filter-expression]\n\n", ArgusProgramName); fprintf (stderr, "options: -b dump packet-matching code.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); fprintf (stderr, " -D specify debug level\n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [mm/dd[/yy].]hh[:mm[:ss]]\n"); fprintf (stderr, " mm/dd[/yy]\n"); fprintf (stderr, " -%%d{yMhdms}\n"); fprintf (stderr, " -w write output to . '-' denotes stdout.\n"); exit(1); } int RaSendArgusRecord(struct ArgusRecordStore *argus) {return 0;} #include unsigned char argusBuf[2048]; extern struct ArgusCanonicalRecord *RaThisCanon; struct ArgusRecord * RaConstructArgusRecord (struct ArgusRecord *); struct ArgusRecord * RaConstructArgusRecord (struct ArgusRecord *argus) { struct ArgusRecord *newarg = NULL; struct ArgusFarHeaderStruct **hdrs = NULL, *hdr; if (argus != NULL) { ArgusThisFarStatus = ArgusIndexRecord (argus, ArgusThisFarHdrs); hdrs = ArgusThisFarHdrs; bzero (argusBuf, sizeof(argusBuf)); newarg = (struct ArgusRecord *) argusBuf; bcopy ((char *)&argus->ahdr, (char *)&newarg->ahdr, sizeof (struct ArgusRecordHeader)); newarg->ahdr.length = sizeof (struct ArgusRecordHeader); if (argus->ahdr.type & ARGUS_MAR) { bcopy ((char *)&argus->argus_mar, (char *)&newarg->argus_mar, sizeof(struct ArgusMarStruct)); newarg->ahdr.length += sizeof(struct ArgusMarStruct); } else { if (((hdr = hdrs[ARGUS_FAR_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_FAR])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_MAC_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_MAC])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_TCP_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_TCP])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_VLAN_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_VLAN])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_MPLS_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_MPLS])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_AGR_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_AGR])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_TIME_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_TIME])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_ICMP_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_ICMP])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_RTP_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_RTP])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_ARP_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_ARP])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_FRG_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_FRG])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_ESP_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_ESP])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_SRCUSRDATA_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_SRCUSRDATA])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } if (((hdr = hdrs[ARGUS_DSTUSRDATA_DSR_INDEX]) != NULL) && (RaDSRFields[RASTRIP_DSR_DSTUSRDATA])) { bcopy((char *) hdr, (char *)&((char *)newarg)[newarg->ahdr.length], hdr->length); newarg->ahdr.length += hdr->length; } } } return (newarg); } void RaGenerateCanonicalRecord (struct ArgusRecord *ptr, struct ArgusCanonicalRecord *); int RaInitialRecord = 0; void RaProcessRecord (struct ArgusRecord *argus) { struct ArgusRecord *retn = NULL; if (!(RaInitialRecord)) { RaInitialRecord++; } else { if ((retn = RaConstructArgusRecord (argus)) != NULL) { if ((ArgusWfileList != NULL) && (!(ArgusListEmpty(ArgusWfileList)))) { struct ArgusWfileStruct *wfile = NULL, *start = NULL; if ((wfile = ArgusFrontList(ArgusWfileList)) != NULL) { start = wfile; do { if ((exceptfile == NULL) || strcmp(wfile->filename, exceptfile)) { #ifdef _LITTLE_ENDIAN ArgusHtoN(retn); #endif ArgusWriteNewLogfile (wfile, retn); #ifdef _LITTLE_ENDIAN ArgusNtoH(retn); #endif } ArgusPopFrontList(ArgusWfileList); ArgusPushBackList(ArgusWfileList, wfile); wfile = ArgusFrontList(ArgusWfileList); } while (wfile != start); } } } } } void RaGenerateCanonicalRecord (struct ArgusRecord *ptr, struct ArgusCanonicalRecord *canon) { int i, index = 0; struct ArgusFarHeaderStruct **hdrs = NULL; struct ArgusRecord *ar = (struct ArgusRecord *) canon; ArgusThisFarStatus = ArgusIndexRecord (ptr, ArgusThisFarHdrs); hdrs = ArgusThisFarHdrs; bzero ((char *)canon, sizeof(*canon)); if (ptr->ahdr.type & ARGUS_MAR) { bcopy ((char *)ptr, (char *)canon, sizeof(*ptr)); } else { bcopy ((char *)&ptr->ahdr, (char *)&canon->ahdr, sizeof(canon->ahdr)); for (i = 1; i < 33; i++) { index = 1 << (i - 1); switch (index) { case ARGUS_FAR_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_FAR_DSR_STATUS) bcopy((char *) hdrs[ARGUS_FAR_DSR_INDEX], (char *)&ar->argus_far, sizeof (ar->argus_far)); break; case ARGUS_MAC_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_MAC_DSR_STATUS) bcopy((char *) hdrs[ARGUS_MAC_DSR_INDEX], (char *)&canon->mac, sizeof(canon->mac)); break; case ARGUS_VLAN_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_VLAN_DSR_STATUS) bcopy((char *) hdrs[ARGUS_VLAN_DSR_INDEX], (char *)&canon->vlan, sizeof(canon->vlan)); break; case ARGUS_MPLS_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_MPLS_DSR_STATUS) bcopy((char *) hdrs[ARGUS_MPLS_DSR_INDEX], (char *)&canon->mpls, sizeof(canon->mpls)); break; case ARGUS_AGR_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_AGR_DSR_STATUS) bcopy((char *) hdrs[ARGUS_AGR_DSR_INDEX], (char *)&canon->agr, sizeof(canon->agr)); break; case ARGUS_TIME_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_TIME_DSR_STATUS) bcopy((char *) hdrs[ARGUS_TIME_DSR_INDEX], (char *)&canon->time, sizeof(canon->time)); break; case ARGUS_TCP_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) bcopy((char *) hdrs[ARGUS_TCP_DSR_INDEX], (char *)&canon->acr_tcp, sizeof(canon->acr_tcp)); break; case ARGUS_ICMP_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_ICMP_DSR_STATUS) bcopy((char *) hdrs[ARGUS_ICMP_DSR_INDEX], (char *)&canon->acr_icmp, sizeof(canon->acr_icmp)); break; case ARGUS_RTP_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_RTP_DSR_STATUS) bcopy((char *) hdrs[ARGUS_RTP_DSR_INDEX], (char *)&canon->acr_rtp, sizeof(canon->acr_rtp)); break; case ARGUS_ARP_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_ARP_DSR_STATUS) bcopy((char *) hdrs[ARGUS_ARP_DSR_INDEX], (char *)&canon->acr_arp, sizeof(canon->acr_arp)); break; case ARGUS_FRG_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_FRG_DSR_STATUS) bcopy((char *) hdrs[ARGUS_FRG_DSR_INDEX], (char *)&canon->acr_frag, sizeof(canon->acr_frag)); break; case ARGUS_ESP_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_ESP_DSR_STATUS) bcopy((char *) hdrs[ARGUS_ESP_DSR_INDEX], (char *)&canon->acr_esp, sizeof(canon->acr_esp)); break; } } } #ifdef ARGUSDEBUG ArgusDebug (7, "RaGenerateCanonicalRecord (0x%x, 0x%x) returning\n", ptr, canon); #endif } argus-clients-2.0.6.fixes.1/clients/rastrip.h0000664000076600007660000000253707640476616014577 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* rastrip.h */ #ifndef RaStrip_h #define RaStrip_h #include #include #include #include #include #include #include #include #include #include #include #ifndef MAXSTRLEN #define MAXSTRLEN 1024 #endif #ifndef MAXPATHNAMELEN #define MAXPATHNAMELEN BUFSIZ #endif #define MAX_OBJ_SIZE 1024 int RaInitialized = 0; #endif /* RaStrip_h */ argus-clients-2.0.6.fixes.1/clients/ratemplate.c0000664000076600007660000001763207640610353015232 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * template - argus client template. * * This module must define these routines: * * (void) usage (void); * this routine should print the standard usage message * for the specific application. * * ArgusClientInit (); * this is the application specific init * routine, which is called after all parsing * initialization is done, prior to reading the * first argus(1) datum. * * (void) ArgusClientTimeout (); * this routine is called every second, when * the argus client is connected to a remote * data source using the -S flag. * * RaProcessRecord ((struct ArgusRecord *) argus); * this routine is called from the main library * for all Argus Records read from the stream. * The template suggests calling protocol specific * subroutines, but this is just a suggestion. * * (void) RaParseComplete (int); * this routine will be called after all the * monitor data has been read. * * * These modules can optionally extend the common routines functions: * * parse_arg (argc, argv) * this routine can process client specific command * line options, specified with appOptstring. * * * * * written by Carter Bullard * QoSient, LLC * */ #include int RaInitialized = 0; void ArgusClientInit () { if (!(RaInitialized)) RaInitialized++; #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusClientInit: returning\n"); #endif } int RaParseCompleting = 0; void RaParseComplete (int sig) { if ((sig >= 0) && (!RaParseCompleting)) { RaParseCompleting++; } #ifdef ARGUSDEBUG ArgusDebug (2, "RaParseComplete: returning\n"); #endif } void ArgusClientTimeout () { #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusClientTimeout: returning\n"); #endif } void parse_arg (int argc, char**argv) { #ifdef ARGUSDEBUG ArgusDebug (6, "parse_arg: returning\n"); #endif } void usage () { extern char version[]; fprintf (stderr, "Ratemplate Version %s\n", version); fprintf (stderr, "usage: %s \n", ArgusProgramName); fprintf (stderr, "usage: %s [options] -S remoteServer [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "usage: %s [options] -r argusDataFile [- filter-expression]\n\n", ArgusProgramName); fprintf (stderr, "options: -a print record summaries on termination.\n"); fprintf (stderr, " -A print application bytes.\n"); fprintf (stderr, " -b dump packet-matching code.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); fprintf (stderr, " -D specify debug level\n"); fprintf (stderr, " -E write records that are rejected by the filter into \n"); fprintf (stderr, " -f read flow model from .\n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -n don't convert numbers to names.\n"); fprintf (stderr, " -p print fractional time with precision.\n"); fprintf (stderr, " -q quiet mode. don't print record outputs.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -R print out response data when availabile.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [mm/dd[/yy].]hh[:mm[:ss]]\n"); fprintf (stderr, " mm/dd[/yy]\n"); fprintf (stderr, " -%%d{yMhdms}\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); fprintf (stderr, " -u print time in Unix time format.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif fprintf (stderr, " -w write output to . '-' denotes stdout.\n"); fprintf (stderr, " -z print Argus TCP state changes.\n"); fprintf (stderr, " -Z print actual TCP flag values.<'s'rc | 'd'st | 'b'oth>\n"); exit(1); } void RaProcessRecord (struct ArgusRecord *argus) { if (argus->ahdr.type & ARGUS_MAR) RaProcessManRecord (argus); else { switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: RaProcessTCPRecord (argus); break; case IPPROTO_UDP: RaProcessUDPRecord (argus); break; case IPPROTO_ICMP: RaProcessICMPRecord (argus); break; default: RaProcessIPRecord (argus); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: RaProcessARPRecord (argus); break; default: RaProcessNonIPRecord (argus); break; } } #ifdef ARGUSDEBUG ArgusDebug (5, "RaProcessRecord (0x%x) returning\n", argus); #endif } void RaProcessManRecord (struct ArgusRecord *argus) { #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessManRecord (0x%x) returning\n", argus); #endif } void RaProcessTCPRecord (struct ArgusRecord *argus) { #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessTCPRecord (0x%x) returning\n", argus); #endif } void RaProcessICMPRecord (struct ArgusRecord *argus) { #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessICMPRecord (0x%x) returning\n", argus); #endif } void RaProcessUDPRecord (struct ArgusRecord *argus) { #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessUDPRecord (0x%x) returning\n", argus); #endif } void RaProcessIPRecord (struct ArgusRecord *argus) { #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessIPRecord (0x%x) returning\n", argus); #endif } void RaProcessARPRecord (struct ArgusRecord *argus) { #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessARPRecord (0x%x) returning\n", argus); #endif } void RaProcessNonIPRecord (struct ArgusRecord *argus) { #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessNonIPRecord (0x%x) returning\n", argus); #endif } int RaSendArgusRecord(struct ArgusRecordStore *argus) { int retn = 0; #ifdef ARGUSDEBUG ArgusDebug (6, "RaSendArgusRecord (0x%x) returning\n", argus); #endif return (retn); } argus-clients-2.0.6.fixes.1/clients/raxml.c0000664000076600007660000010436210047721710014207 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * raxml - writeout XML data format for argus data. * * written by Carter Bullard * QoSient, LLC * */ #include #include void RaXMLPrintFlowEncapsData(struct ArgusRecord *argus); void RaXMLPrintMacData(struct ArgusRecord *argus); void RaXMLPrintAddrNames(struct ArgusRecord *argus); void RaXMLPrintFlowAttrsData(struct ArgusRecord *argus); void RaXMLPrintMACAttrsData(struct ArgusRecord *argus); void RaXMLPrintMetricsData (struct ArgusRecord *argus); void RaXMLPrintTimeData (struct ArgusRecord *argus); void RaXMLPrintUsrData (struct ArgusRecord *argus); void RaXMLPrintAgrData (struct ArgusRecord *argus); int RaInitialized = 0; int RaStartedXML = 0; int RaXMLRecords = 0; void ArgusClientInit () { if (!(RaInitialized)) { RaInitialized++; pflag = 0; ArgusPrintGMT = 0; if (ArgusPrintGMT) RaTimeFormat="%Y-%m-%dT%TZ"; else RaTimeFormat="%Y-%m-%dT%T"; (void) signal (SIGHUP, (void (*)(int)) RaParseComplete); (void) signal (SIGTERM, (void (*)(int)) RaParseComplete); (void) signal (SIGQUIT, (void (*)(int)) RaParseComplete); (void) signal (SIGINT, (void (*)(int)) RaParseComplete); } } void RaParseComplete (int sig) { if ((sig >= 0) && RaStartedXML) { printf(" \n", RaXMLRecords); printf("\n"); fflush(stdout); } _exit(0); } void ArgusClientTimeout () { } void parse_arg (int argc, char**argv) { } void usage () { extern char version[]; fprintf (stderr, "Raxml Version %s\n", version); fprintf (stderr, "usage: %s \n", ArgusProgramName); fprintf (stderr, "usage: %s [ra-options] [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "ra-options: -b dump packet-matching code.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); fprintf (stderr, " -D specify debug level\n"); fprintf (stderr, " -e convert user data using method.\n"); fprintf (stderr, " Supported types are and .\n"); fprintf (stderr, " -E write records that are rejected by the filter into \n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -n don't convert numbers to names.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [mm/dd[/yy].]hh[:mm[:ss]]\n"); fprintf (stderr, " mm/dd[/yy]\n"); fprintf (stderr, " -%%d{yMhdms}\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif exit(1); } #include void RaProcessRecord (struct ArgusRecord *argus) { struct timeval diffbuf, *diff = &diffbuf; char *StartDateBuf, *LastDateBuf; char *StartTimeBuf, *LastTimeBuf, *CauseStr; char IDStrBuf[32], *IDStr = IDStrBuf; if (!(RaStartedXML)) RaProcessManRecord(&ArgusInput->ArgusManStart); if (argus->ahdr.type & ARGUS_MAR) RaProcessManRecord (argus); else { RaXMLRecords++; diff->tv_sec = argus->argus_far.time.last.tv_sec - argus->argus_far.time.start.tv_sec; diff->tv_usec = argus->argus_far.time.last.tv_usec - argus->argus_far.time.start.tv_usec; if (diff->tv_usec < 0) { diff->tv_sec--; diff->tv_usec += 1000000; } RaTimeFormat="%Y-%m-%d"; StartDateBuf = strdup(print_time(&argus->argus_far.time.start)); RaTimeFormat="%T"; StartTimeBuf = strdup(print_time(&argus->argus_far.time.start)); RaTimeFormat="%Y-%m-%d"; LastDateBuf = strdup(print_time(&argus->argus_far.time.last)); RaTimeFormat="%T"; LastTimeBuf = strdup(print_time(&argus->argus_far.time.last)); switch (argus->ahdr.cause) { case ARGUS_START: CauseStr = "Start"; break; case ARGUS_STATUS: CauseStr = "Status"; break; case ARGUS_STOP: CauseStr = "Stop"; break; case ARGUS_SHUTDOWN: CauseStr = "Shutdown"; break; case ARGUS_TIMEOUT: CauseStr = "Timeout"; break; case ARGUS_ERROR: CauseStr = "Error"; break; default: CauseStr = "Unknown"; break; } if (argus->ahdr.status & ARGUS_ID_IS_IPADDR) { nflag++; IDStr = ipaddr_string(&argus->ahdr.argusid); nflag--; } else sprintf (IDStrBuf, "%u", argus->ahdr.argusid); printf(" ahdr.seqNumber, CauseStr); printf(" StartDate = \"%s\" StartTime = \"%s\" StartTimeusecs = \"%d\"\n", StartDateBuf, StartTimeBuf, (int)argus->argus_far.time.start.tv_usec); printf(" LastDate = \"%s\" LastTime = \"%s\" LastTimeusecs = \"%d\"\n", LastDateBuf, LastTimeBuf, (int)argus->argus_far.time.last.tv_usec); printf(" Duration = \"%d.%06d\" TransRefNum = \"%u\">\n", (int) diff->tv_sec, (int) diff->tv_usec, argus->argus_far.ArgusTransRefNum); free(StartDateBuf); free(StartTimeBuf); free(LastDateBuf); free(LastTimeBuf); switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: RaProcessTCPRecord (argus); break; case IPPROTO_ICMP: RaProcessICMPRecord (argus); break; default: case IPPROTO_UDP: RaProcessIPRecord (argus); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: RaProcessARPRecord (argus); break; default: RaProcessNonIPRecord (argus); break; } printf(" \n"); fflush(stdout); } } void RaProcessManRecord (struct ArgusRecord *argus) { extern struct ArgusInterfaceStruct interfacetypes []; extern char version[]; struct ArgusInterfaceStruct *interface = &interfacetypes[0]; char *StartDateBuf, *CurrentDateBuf, *StartTimeBuf, *CurrentTimeBuf; char IDStrBuf[32], *IDStr = IDStrBuf; if (argus->ahdr.cause == ARGUS_START) { if (RaStartedXML++ == 0) { Uflag = 0; XMLflag = 2; printf("\n"); printf("\n", version); RaTimeFormat="%Y-%m-%d"; StartDateBuf = strdup(print_time(&argus->argus_far.time.start)); RaTimeFormat="%T"; StartTimeBuf = strdup(print_time(&argus->argus_far.time.start)); RaTimeFormat="%Y-%m-%d"; CurrentDateBuf = strdup(print_time(&argus->argus_far.time.start)); RaTimeFormat="%T"; CurrentTimeBuf = strdup(print_time(&argus->argus_far.time.start)); printf("argus_mar.startime.tv_usec); printf(" CurrentDate = \"%s\" CurrentTime = \"%s\" CurrentTimeusec = \"%d\"\n", CurrentDateBuf, CurrentTimeBuf, (int)argus->argus_mar.now.tv_usec); printf(" MajorVersion = \"%d\" MinorVersion = \"%d\" ", major_version, minor_version); while (interface->value >= 0) { if (argus->argus_mar.interfaceType == interface->value) break; interface++; } nflag++; if (argus->ahdr.status & ARGUS_ID_IS_IPADDR) { IDStr = ipaddr_string(&argus->argus_mar.argusid); } else sprintf (IDStrBuf, "%u", argus->argus_mar.argusid); printf("InterfaceType = \"%s\" InterfaceStatus = \"%s\"\n", interface->label, "Up"); printf(" SourceId = \"%s\" ", IDStr); printf(" NetAddr = \"%s\" ", ipaddr_string(&argus->argus_mar.localnet)); printf(" NetMask = \"%s\">\n\n", ipaddr_string(&argus->argus_mar.netmask)); nflag--; XMLflag = 1; } } fflush(stdout); } #define IPPROTOSTR 134 extern char *ip_proto_string []; extern char *ArgusTCPFlags []; #define ARGUSPROTOLEN 16 char ArgusProtoStrBuf[ARGUSPROTOLEN]; char *ArgusGetProtoString(unsigned short); char * ArgusGetProtoString(unsigned short proto) { char *retn = NULL; bzero (ArgusProtoStrBuf, ARGUSPROTOLEN); if ((nflag > 1) || ((proto >= IPPROTOSTR) || !(strncmp("unas", ip_proto_string[proto], 4)))) { snprintf(ArgusProtoStrBuf, ARGUSPROTOLEN - 1, "%u", proto); retn = ArgusProtoStrBuf; } else retn = ip_proto_string[proto]; return (retn); } void RaProcessTCPRecord (struct ArgusRecord *argus) { struct ArgusTCPObject *tcp = NULL; char SrcAddr[128], DstAddr[128], *protoStr = NULL; char TCPStatusStr[128], TCPOptionsStr[128], SrcTCPFlagsStr[16], DstTCPFlagsStr[16]; struct ArgusFlow *flow = &argus->argus_far.flow; unsigned int status, options, i, index; nflag++; sprintf(SrcAddr, "%s", ipaddr_string(&flow->ip_flow.ip_src)); sprintf(DstAddr, "%s", ipaddr_string(&flow->ip_flow.ip_dst)); nflag--; protoStr = ArgusGetProtoString(flow->ip_flow.ip_p); if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) tcp = (struct ArgusTCPObject *)ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]; bzero ((char *)TCPStatusStr, sizeof(TCPStatusStr)); if ((tcp != NULL) && ((status = tcp->state) != 0)) { if (status) { if (status & ARGUS_SAW_SYN) strcat (TCPStatusStr, "SYN|"); if (status & ARGUS_SAW_SYN_SENT) strcat (TCPStatusStr, "SYNACK|"); if (status & ARGUS_CON_ESTABLISHED) strcat (TCPStatusStr, "EST|"); if (status & ARGUS_FIN) strcat (TCPStatusStr, "FIN|"); if (status & ARGUS_FIN_ACK) strcat (TCPStatusStr, "FINACK|"); if (status & ARGUS_NORMAL_CLOSE) strcat (TCPStatusStr, "CLO|"); if (status & ARGUS_RESET) strcat (TCPStatusStr, "RST|"); if (status & ARGUS_SRC_WINDOW_SHUT) strcat (TCPStatusStr, "SWIN|"); if (status & ARGUS_DST_WINDOW_SHUT) strcat (TCPStatusStr, "DWIN|"); if (status & ARGUS_SRC_CONGESTED) strcat (TCPStatusStr, "SECN|"); if (status & ARGUS_DST_CONGESTED) strcat (TCPStatusStr, "DECN|"); if (status & ARGUS_SRC_PKTS_RETRANS)strcat (TCPStatusStr, "SRTN|"); if (status & ARGUS_DST_PKTS_RETRANS)strcat (TCPStatusStr, "DRTN|"); TCPStatusStr[strlen(TCPStatusStr) - 1] = '\0'; } else strcat(TCPStatusStr, "None"); } else strcat(TCPStatusStr, "None"); bzero ((char *)TCPOptionsStr, sizeof(TCPOptionsStr)); if ((tcp != NULL) && ((options = tcp->options) != 0)) { if (options) { if (options & ARGUS_TCP_MAXSEG) strcat (TCPOptionsStr, "MAX|"); if (options & ARGUS_TCP_WSCALE) strcat (TCPOptionsStr, "WSC|"); if (options & ARGUS_TCP_SACKOK) strcat (TCPOptionsStr, "SACKOK|"); if (options & ARGUS_TCP_SACK) strcat (TCPOptionsStr, "SACK|"); if (options & ARGUS_TCP_ECHO) strcat (TCPOptionsStr, "ECHO|"); if (options & ARGUS_TCP_ECHOREPLY) strcat (TCPOptionsStr, "ECHOR|"); if (options & ARGUS_TCP_TIMESTAMP) strcat (TCPOptionsStr, "TIME|"); if (options & ARGUS_TCP_CC) strcat (TCPOptionsStr, "CC|"); if (options & ARGUS_TCP_CCNEW) strcat (TCPOptionsStr, "CCNEW|"); if (options & ARGUS_TCP_CCECHO) strcat (TCPOptionsStr, "CCECHO|"); if (options & ARGUS_TCP_SRC_ECN) strcat (TCPOptionsStr, "SECN|"); if (options & ARGUS_TCP_DST_ECN) strcat (TCPOptionsStr, "DECN|"); TCPOptionsStr[strlen(TCPOptionsStr) - 1] = '\0'; } else strcat(TCPOptionsStr, "None"); } else strcat(TCPOptionsStr, "None"); bzero(SrcTCPFlagsStr, sizeof(SrcTCPFlagsStr)); bzero(DstTCPFlagsStr, sizeof(DstTCPFlagsStr)); if (tcp != NULL) { for (i = 0, index = 1; i < 8; i++) { if (tcp->src.flags & index) { strcat (SrcTCPFlagsStr, ArgusTCPFlags[i]); } if (tcp->dst.flags & index) { strcat (DstTCPFlagsStr, ArgusTCPFlags[i]); } index <<= 1; } } RaXMLPrintFlowEncapsData(argus); RaXMLPrintMACAttrsData(argus); printf(" argus_far.flow.ip_flow.sport != 0xFFFF) printf("Sport = \"%d\" ", argus->argus_far.flow.ip_flow.sport); if (argus->argus_far.flow.ip_flow.dport != 0xFFFF) printf("Dport = \"%d\" ", argus->argus_far.flow.ip_flow.dport); if ((argus->argus_far.flow.ip_flow.ip_id != 0xFFFF) || (argus->argus_far.flow.ip_flow.ip_id != 0)) printf("IpId = \"%x\" ", argus->argus_far.flow.ip_flow.ip_id); printf ("/> \n"); RaXMLPrintAddrNames(argus); RaXMLPrintFlowAttrsData(argus); if (tcp != NULL) { printf(" \n", TCPStatusStr, TCPOptionsStr, tcp->synAckuSecs, tcp->ackDatauSecs); printf(" src.seqbase, tcp->src.ackbytes); printf ("SrcTCPBytes = \"%u\" SrcTCPRetrans = \"%d\" SrcTCPWin = \"%d\" SrcTCPFlags = \"%s\"\n", tcp->src.bytes, tcp->src.rpkts, tcp->src.win, SrcTCPFlagsStr); printf(" DstTCPSeqBase = \"%u\" DstTCPAckBytes = \"%u\" ", tcp->dst.seqbase, tcp->dst.ackbytes); printf ("DstTCPBytes = \"%u\" DstTCPRetrans = \"%d\" DstTCPWin = \"%d\" DstTCPFlags = \"%s\" />\n", tcp->dst.bytes, tcp->dst.rpkts, tcp->dst.win, DstTCPFlagsStr); printf(" \n"); printf(" \n"); } RaXMLPrintMetricsData(argus); RaXMLPrintTimeData(argus); RaXMLPrintUsrData(argus); /* RaXMLPrintAgrData (argus); */ } #if defined(__OpenBSD__) #include #include #endif #include extern char *icmptypestr[]; void RaProcessICMPRecord (struct ArgusRecord *argus) { char SrcAddr[128], DstAddr[128]; char *protoStr, *typeStr = NULL, *codeStr = NULL; struct ArgusFlow *flow = &argus->argus_far.flow; struct ArgusICMPFlow *icmpFlow = &argus->argus_far.flow.icmp_flow; struct ArgusICMPObject *icmp = NULL; unsigned char ra_icmp_type = 0, ra_icmp_code = 0; unsigned short ra_icmp_data = 0; unsigned int ra_src_addr = 0, ra_dst_addr = 0, ra_gw_addr = 0; nflag++; sprintf(SrcAddr, "%s", ipaddr_string(&flow->ip_flow.ip_src)); sprintf(DstAddr, "%s", ipaddr_string(&flow->ip_flow.ip_dst)); nflag--; protoStr = ArgusGetProtoString(flow->ip_flow.ip_p); if (ArgusThisFarStatus & ARGUS_ICMP_DSR_STATUS) { icmp = (struct ArgusICMPObject *)ArgusThisFarHdrs[ARGUS_ICMP_DSR_INDEX]; ra_src_addr = icmp->isrcaddr; ra_dst_addr = icmp->idstaddr; ra_gw_addr = icmp->igwaddr; ra_icmp_type = icmp->icmp_type; ra_icmp_code = icmpFlow->code; } else { ra_icmp_type = icmpFlow->type; ra_icmp_code = icmpFlow->code; } ra_icmp_data = icmpFlow->id; if (ra_icmp_type < (unsigned char) (ICMP_MAXTYPE + 1)) typeStr = icmptypestr[ra_icmp_type]; else typeStr = "UNK"; #ifndef ICMP_UNREACH_NET_UNKNOWN #define ICMP_UNREACH_NET_UNKNOWN 6 #endif #ifndef ICMP_UNREACH_HOST_UNKNOWN #define ICMP_UNREACH_HOST_UNKNOWN 7 #endif #ifndef ICMP_UNREACH_ISOLATED #define ICMP_UNREACH_ISOLATED 8 #endif #ifndef ICMP_UNREACH_NET_PROHIB #define ICMP_UNREACH_NET_PROHIB 9 #endif #ifndef ICMP_UNREACH_HOST_PROHIB #define ICMP_UNREACH_HOST_PROHIB 10 #endif #ifndef ICMP_UNREACH_TOSNET #define ICMP_UNREACH_TOSNET 11 #endif #ifndef ICMP_UNREACH_TOSHOST #define ICMP_UNREACH_TOSHOST 12 #endif #ifndef ICMP_UNREACH_FILTER_PROHIB #define ICMP_UNREACH_FILTER_PROHIB 13 #endif #ifndef ICMP_UNREACH_HOST_PRECEDENCE #define ICMP_UNREACH_HOST_PRECEDENCE 14 #endif #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 #endif switch (ra_icmp_type) { case ICMP_UNREACH: switch (ra_icmp_code) { case ICMP_UNREACH_NET: codeStr = "Net"; break; case ICMP_UNREACH_HOST: codeStr = "Host"; break; case ICMP_UNREACH_PROTOCOL: codeStr = "Proto"; break; case ICMP_UNREACH_PORT: codeStr = "Port"; break; case ICMP_UNREACH_NEEDFRAG: codeStr = "NeedFrag"; break; case ICMP_SR_FAILED: codeStr = "SrcRoute"; break; case ICMP_UNREACH_NET_UNKNOWN: codeStr = "Net Unkn"; break; case ICMP_UNREACH_HOST_UNKNOWN: codeStr = "Host Unkn"; break; case ICMP_UNREACH_ISOLATED: codeStr = "Isolated"; break; case ICMP_UNREACH_NET_PROHIB: codeStr = "Net Prohib"; break; case ICMP_UNREACH_HOST_PROHIB: codeStr = "Host Prohib"; break; case ICMP_UNREACH_TOSNET: codeStr = "Tos Net"; break; case ICMP_UNREACH_TOSHOST: codeStr = "Tos Host"; break; case ICMP_UNREACH_FILTER_PROHIB: codeStr = "Filter"; break; case ICMP_UNREACH_HOST_PRECEDENCE: codeStr = "Host Prec"; break; case ICMP_UNREACH_PRECEDENCE_CUTOFF: codeStr = "Prec Xoff"; break; } break; case ICMP_REDIRECT: switch (ra_icmp_code) { case ICMP_REDIRECT_NET: codeStr = "Net"; break; case ICMP_REDIRECT_HOST: codeStr = "Host"; break; case ICMP_REDIRECT_TOSNET: codeStr = "Tos Net"; break; case ICMP_REDIRECT_TOSHOST: codeStr = "Tos Host"; break; } break; case ICMP_ROUTERADVERT: codeStr = ra_icmp_code ? "not_common" : "normal"; break; case ICMP_TIMXCEED: codeStr = ra_icmp_code ? "reassembly" : "in_transit"; break; case ICMP_PARAMETERPROB: codeStr = ra_icmp_code ? ((ra_icmp_code == 1) ? "option" : "length") : "pointer"; break; } RaXMLPrintFlowEncapsData(argus); RaXMLPrintMACAttrsData(argus); printf(" ", ra_icmp_data); if ((argus->argus_far.flow.icmp_flow.ip_id != 0xFFFF) || (argus->argus_far.flow.icmp_flow.ip_id != 0)) printf("IpId = \"%x\" ", argus->argus_far.flow.icmp_flow.ip_id); printf("\n"); RaXMLPrintAddrNames(argus); RaXMLPrintFlowAttrsData(argus); RaXMLPrintMetricsData(argus); RaXMLPrintTimeData(argus); RaXMLPrintUsrData(argus); RaXMLPrintAgrData (argus); } void RaProcessIPRecord (struct ArgusRecord *argus) { char SrcAddr[128], DstAddr[128], *protoStr = NULL; struct ArgusFlow *flow = &argus->argus_far.flow; nflag++; sprintf(SrcAddr, "%s", ipaddr_string(&flow->ip_flow.ip_src)); sprintf(DstAddr, "%s", ipaddr_string(&flow->ip_flow.ip_dst)); nflag--; protoStr = ArgusGetProtoString(flow->ip_flow.ip_p); RaXMLPrintFlowEncapsData(argus); RaXMLPrintMACAttrsData(argus); if (ArgusThisFarStatus & ARGUS_ESP_DSR_STATUS) { printf(" argus_far.flow.esp_flow.spi) printf("Spi = \"%d\" ", argus->argus_far.flow.esp_flow.spi); } else printf(" ip_flow.ip_p == IPPROTO_UDP) { if (argus->argus_far.flow.ip_flow.sport != 0xFFFF) printf("Sport = \"%d\" ", argus->argus_far.flow.ip_flow.sport); if (argus->argus_far.flow.ip_flow.dport != 0xFFFF) printf("Dport = \"%d\" ", argus->argus_far.flow.ip_flow.dport); } if ((argus->argus_far.flow.ip_flow.ip_id != 0xFFFF) || (argus->argus_far.flow.ip_flow.ip_id != 0)) printf("IpId = \"%x\" ", argus->argus_far.flow.ip_flow.ip_id); printf ("/> \n"); RaXMLPrintAddrNames(argus); RaXMLPrintFlowAttrsData(argus); if (ArgusThisFarStatus & ARGUS_ESP_DSR_STATUS) { struct ArgusESPStruct *esp = (struct ArgusESPStruct *) ArgusThisFarHdrs[ARGUS_ESP_DSR_INDEX]; char ArgusLastSeqBuf[32], ArgusLostSeqBuf[32]; bzero(ArgusLastSeqBuf, 32); bzero(ArgusLostSeqBuf, 32); sprintf (ArgusLastSeqBuf, "\"%u\"", esp->src.lastseq); sprintf (ArgusLostSeqBuf, "\"%u\"", esp->src.lostseq); printf(" dst.lastseq); sprintf (ArgusLostSeqBuf, "\"%u\"", esp->dst.lostseq); printf(" DstEspLastSeq = %-9s DstEspDroppedPkts = %s />\n", ArgusLastSeqBuf, ArgusLostSeqBuf); printf(" \n"); } if (ArgusThisFarStatus & ARGUS_FRG_DSR_STATUS) { struct ArgusFragObject *frag = (struct ArgusFragObject *) ArgusThisFarHdrs[ARGUS_FRG_DSR_INDEX]; printf(" ", frag->frag_id, frag->totlen, frag->maxfraglen); printf("\n"); } RaXMLPrintMetricsData(argus); RaXMLPrintTimeData(argus); RaXMLPrintUsrData(argus); RaXMLPrintAgrData (argus); } #include void RaProcessARPRecord (struct ArgusRecord *argus) { char SrcAddr[128], TarAddr[128], MacAddr[128]; struct ArgusArpFlow *arpFlow = &argus->argus_far.flow.arp_flow; nflag++; sprintf(SrcAddr, "%s", ipaddr_string(&arpFlow->arp_spa)); sprintf(TarAddr, "%s", ipaddr_string(&arpFlow->arp_tpa)); sprintf(MacAddr, "%s", etheraddr_string(arpFlow->etheraddr)); nflag--; RaXMLPrintFlowEncapsData(argus); printf(" \n", SrcAddr, TarAddr, MacAddr); RaXMLPrintAddrNames(argus); RaXMLPrintMetricsData(argus); RaXMLPrintTimeData(argus); RaXMLPrintUsrData(argus); RaXMLPrintAgrData (argus); } void RaProcessNonIPRecord (struct ArgusRecord *argus) { char SrcAddr[128], DstAddr[128], *protoStr; struct ArgusMACFlow *macFlow = &argus->argus_far.flow.mac_flow; unsigned short proto; sprintf(SrcAddr, "%s", etheraddr_string((unsigned char *)&macFlow->ehdr.ether_shost)); sprintf(DstAddr, "%s", etheraddr_string((unsigned char *)&macFlow->ehdr.ether_dhost)); proto = argus->ahdr.status & 0xFFFF; protoStr = etherproto_string(proto); RaXMLPrintFlowEncapsData(argus); printf(" \n", SrcAddr, DstAddr, protoStr); RaXMLPrintMetricsData (argus); RaXMLPrintTimeData (argus); RaXMLPrintUsrData (argus); RaXMLPrintAgrData (argus); } int RaSendArgusRecord(struct ArgusRecordStore *argus) {return 0;} void RaXMLPrintFlowEncapsData(struct ArgusRecord *argus) { if (ArgusThisFarStatus & ARGUS_VLAN_DSR_STATUS) { struct ArgusVlanStruct *vlan = (struct ArgusVlanStruct *) ArgusThisFarHdrs[ARGUS_VLAN_DSR_INDEX]; printf(" status & ARGUS_SRC_VLAN) printf("SrcVid = \"%x\" ", vlan->sid); if (vlan->status & ARGUS_DST_VLAN) printf("DstVid = \"%x\" ", vlan->did); printf("/> \n"); } if (ArgusThisFarStatus & ARGUS_MPLS_DSR_STATUS) { struct ArgusMplsStruct *mpls = (struct ArgusMplsStruct *) ArgusThisFarHdrs[ARGUS_MPLS_DSR_INDEX]; printf(" status & ARGUS_SRC_MPLS) printf("SrcLabel = \"%x\" ", mpls->slabel); if (mpls->status & ARGUS_DST_MPLS) printf("DstLabel = \"%x\" ", mpls->dlabel); printf("/> \n"); } } void RaXMLPrintAddrNames(struct ArgusRecord *argus) { if (!nflag) { char SrcAddr[128], DstAddr[128]; switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: { struct ArgusFlow *flow = &argus->argus_far.flow; sprintf(SrcAddr, "%s", ipaddr_string(&flow->ip_flow.ip_src)); sprintf(DstAddr, "%s", ipaddr_string(&flow->ip_flow.ip_dst)); printf(" \n", SrcAddr, DstAddr); break; } case ETHERTYPE_ARP: case ETHERTYPE_REVARP: { struct ArgusArpFlow *arpFlow = &argus->argus_far.flow.arp_flow; sprintf(SrcAddr, "%s", ipaddr_string(&arpFlow->arp_spa)); sprintf(DstAddr, "%s", ipaddr_string(&arpFlow->arp_tpa)); printf(" \n", SrcAddr, DstAddr); break; } default: return; } } } void RaXMLPrintFlowAttrsData(struct ArgusRecord *argus) { char *StatusStr = NULL, statusStrBuf[256]; struct ArgusFlow *flow = &argus->argus_far.flow; int len; bzero (statusStrBuf, 256); StatusStr = statusStrBuf; if (argus->argus_far.status & ARGUS_FRAGMENTS) strcat(statusStrBuf, "Frag|"); if (flow->ip_flow.tp_p == ARGUS_RTP_FLOWTAG) strcat(statusStrBuf, "RTP|"); if (argus->ahdr.status & ARGUS_PPPoE) strcat(statusStrBuf, "PPPoE|"); if (argus->argus_far.status & ARGUS_ICMP_MAPPED) strcat(statusStrBuf, "ICMP_MAPPED|"); if (argus->ahdr.status & ARGUS_MULTIADDR) strcat(statusStrBuf, "MULTIADDR|"); if ((len = strlen(StatusStr)) > 0) statusStrBuf[strlen(StatusStr) - 1] = '\0'; else StatusStr = NULL; if (StatusStr) printf(" \n", StatusStr, argus->argus_far.attr_ip.sttl, argus->argus_far.attr_ip.dttl, argus->argus_far.attr_ip.stos, argus->argus_far.attr_ip.dtos); else printf(" \n", argus->argus_far.attr_ip.sttl, argus->argus_far.attr_ip.dttl, argus->argus_far.attr_ip.stos, argus->argus_far.attr_ip.dtos); } void RaXMLPrintMACAttrsData(struct ArgusRecord *argus) { char *esrcString = NULL, *edstString = NULL; if (ArgusThisFarStatus & ARGUS_MAC_DSR_STATUS) { struct ArgusMacStruct *mac = (struct ArgusMacStruct *) ArgusThisFarHdrs[ARGUS_MAC_DSR_INDEX]; esrcString = etheraddr_string ((u_char *)&mac->phys_union.ether.ethersrc); edstString = etheraddr_string ((u_char *)&mac->phys_union.ether.etherdst); printf(" \n", esrcString, edstString); } } void RaXMLPrintMetricsData (struct ArgusRecord *argus) { printf(" argus_far.src.count, argus->argus_far.dst.count, argus->argus_far.src.bytes, argus->argus_far.dst.bytes); printf(" SrcAppBytes = \"%d\" DstAppBytes = \"%d\" />\n", argus->argus_far.src.appbytes, argus->argus_far.dst.appbytes); } void RaXMLPrintTimeData (struct ArgusRecord *argus) { if (ArgusThisFarStatus & ARGUS_TIME_DSR_STATUS) { struct ArgusTimeStruct *time = (struct ArgusTimeStruct *) ArgusThisFarHdrs[ARGUS_TIME_DSR_INDEX]; if ((time->src.act.n > 1) || (time->dst.act.n > 1) || (time->src.idle.n > 1) || (time->dst.idle.n > 1)) { printf (" \n"); if (time->src.act.n) { printf (" \n", time->src.act.n, time->src.act.meanval, time->src.act.stdev, time->src.act.maxval, time->src.act.minval); } if (time->src.idle.n) { printf (" \n", time->src.idle.n, time->src.idle.meanval, time->src.idle.stdev, time->src.idle.maxval, time->src.idle.minval); } if (time->dst.act.n) { printf (" \n", time->dst.act.n, time->dst.act.meanval, time->dst.act.stdev, time->dst.act.maxval, time->dst.act.minval); } if (time->dst.idle.n) { printf (" \n", time->dst.idle.n, time->dst.idle.meanval, time->dst.idle.stdev, time->dst.idle.maxval, time->dst.idle.minval); } printf (" \n"); } } } void RaXMLPrintUsrData (struct ArgusRecord *argus) { int len = 0; struct ArgusUserStruct *user = NULL; char strbuf[MAXSTRLEN], *str = strbuf; if (dflag && (ArgusThisFarStatus & (ARGUS_SRCUSRDATA_DSR_STATUS | ARGUS_DSTUSRDATA_DSR_STATUS))) { printf (" \n"); if (ArgusThisFarStatus & ARGUS_SRCUSRDATA_DSR_STATUS) { user = (struct ArgusUserStruct *) ArgusThisFarHdrs[ARGUS_SRCUSRDATA_DSR_INDEX]; len = (user->length - 1) * 4; len = (len < argus->argus_far.src.appbytes) ? len : argus->argus_far.src.appbytes; len = len > ArgusSrcUserDataLen ? ArgusSrcUserDataLen : len; if (ArgusSrcUserDataLen > 0) { printf (" data, NULL, len, str, sizeof(strbuf))) != 0) printf ("%s />\n", str); } } if (ArgusThisFarStatus & ARGUS_DSTUSRDATA_DSR_STATUS) { struct ArgusUserStruct *user = (struct ArgusUserStruct *) ArgusThisFarHdrs[ARGUS_DSTUSRDATA_DSR_INDEX]; char strbuf[MAXSTRLEN], *str = strbuf; len = (user->length - 1) * 4; len = (len < argus->argus_far.dst.appbytes) ? len : argus->argus_far.dst.appbytes; len = len > ArgusDstUserDataLen ? ArgusDstUserDataLen : len; printf (" data, NULL, len, str, sizeof(strbuf))) printf ("%s />\n", str); } printf (" \n"); } } void RaXMLPrintAgrData (struct ArgusRecord *argus) { struct ArgusAGRStruct *agr; if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) != NULL) { printf (" \n"); printf (" count); if ((agr->act.n > 1) || (agr->idle.n > 1)) { if (agr->act.n) { if (agr->status & ARGUS_AGR_USECACTTIME) { printf (" \n", agr->act.n, agr->act.meanval, agr->act.stdev, agr->act.maxval, agr->act.minval); } else { printf (" \n", agr->act.n, agr->act.meanval, agr->act.stdev, agr->act.maxval, agr->act.minval); } } if (agr->idle.n) { if (agr->status & ARGUS_AGR_USECACTTIME) { printf (" \n", agr->idle.n, agr->idle.meanval, agr->idle.stdev, agr->idle.maxval, agr->idle.minval); } else { printf (" \n", agr->idle.n, agr->idle.meanval, agr->idle.stdev, agr->idle.maxval, agr->idle.minval); } } } printf (" \n"); } } argus-clients-2.0.6.fixes.1/common/0000775000076600007660000000000010047734056012630 5argus-clients-2.0.6.fixes.1/common/Makefile.in0000775000076600007660000001064507703321100014611 # # Copyright (c) 2000-2003 QoSient, LLC # All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # # Various configurable paths (remember to edit Makefile.in, not Makefile) # # Top level hierarchy prefix = $(DESTDIR)@prefix@ exec_prefix = @exec_prefix@ # Pathname of directory to install the include files INCLDEST = @includedir@ # Pathname of directory to install the library LIBDEST = @libdir@ # Pathname of directory to install the man page MANDEST = @mandir@ # VPATH srcdir = @srcdir@ VPATH = @srcdir@ # # You shouldn't need to edit anything below. # CC = @CC@ CCOPT = @V_CCOPT@ INCLS = -I. -I../include @V_INCLS@ DEFS = @DEFS@ # Standard CFLAGS CFLAGS = $(CCOPT) $(INCLS) $(DEFS) INSTALL = @INSTALL@ RANLIB = @V_RANLIB@ # # Flex and bison allow you to specify the prefixes of the global symbols # used by the generated parser. This allows programs to use lex/yacc # and link against libpcap. If you don't have flex or bison, get them. # LEX = @V_LEX@ YACC = @V_YACC@ # Explicitly define compilation rule since SunOS 4's make doesn't like gcc. # Also, gcc does not remove the .o before forking 'as', which can be a # problem if you don't own the file but can write to the directory. .c.o: @rm -f $@ $(CC) $(CFLAGS) -c $(srcdir)/$*.c # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot # hack the extra indirection VSRC = version.c LSRC = scanner.l YSRC = grammar.y GENSRC = $(LSRC:.l=.c) $(YSRC:.y=.c) GENHDR = tokdefs.h TAGHDR = bpf/net/bpf.h TAGFILES = $(SRC) $(HDR) $(TAGHDR) LIBS = @INSTALL_LIB@/argus_parse.a @INSTALL_LIB@/argus_common.a @INSTALL_LIB@/argus_client.a OBJ = $(COMMONOBJ) $(PARSEOBJ) $(CLIENTOBJ) CLEANFILES = $(LIBS) $(OBJ) $(GENSRC) $(GENHDR) $(VSRC) lex.yy.c COMMONSRC = gencode.c argus_filter.c $(GENSRC) $(VSRC) COMMONOBJ = gencode.o argus_filter.o scanner.o grammar.o version.o PARSESRC = argus_parse.c argus_util.c argus_auth.c PARSEOBJ = argus_parse.o argus_util.o argus_auth.o CLIENTSRC = argus_client.c CLIENTOBJ = argus_client.o SRC = $(COMMONSRC) $(PARSESRC) $(CLIENTSRC) all: $(LIBS) @INSTALL_LIB@/argus_common.a: $(COMMONOBJ) rm -f $@; ar qc $@ $(COMMONOBJ) -$(RANLIB) $@ @INSTALL_LIB@/argus_parse.a: $(PARSEOBJ) rm -f $@; ar qc $@ $(PARSEOBJ) -$(RANLIB) $@ @INSTALL_LIB@/argus_client.a: $(CLIENTOBJ) rm -f $@; ar qc $@ $(CLIENTOBJ) -$(RANLIB) $@ scanner.c: scanner.l @rm -f $@ $(LEX) -t $< > $$$$.$@; mv $$$$.$@ $@ scanner.o: scanner.c tokdefs.h tokdefs.h: grammar.c grammar.c: grammar.y @rm -f grammar.c tokdefs.h $(YACC) -d $< mv y.tab.c grammar.c mv y.tab.h tokdefs.h grammar.o: grammar.c $(CC) $(CFLAGS) -Dyylval=argus_lval -c grammar.c version.o: version.c version.c: $(srcdir)/../VERSION @rm -f $@ sed -e 's/.*/char version[] = "&";/' $(srcdir)/../VERSION > $@ install: force all [ -d $(LIBDEST) ] || \ (mkdir -p $(LIBDEST); chmod 755 $(LIBDEST)) $(INSTALL) $(srcdir)/../lib/argus_common.a $(LIBDEST)/argus_common.a $(INSTALL) $(srcdir)/../lib/argus_parse.a $(LIBDEST)/argus_parse.a $(RANLIB) $(LIBDEST)/argus_common.a $(RANLIB) $(LIBDEST)/argus_parse.a clean: rm -f $(CLEANFILES) distclean: rm -f $(CLEANFILES) Makefile config.cache config.log config.status \ gnuc.h os-proto.h bpf_filter.c net tags: $(TAGFILES) ctags -wtd $(TAGFILES) tar: force @cwd=`pwd` ; dir=`basename $$cwd` ; name=libpcap-`cat VERSION` ; \ list="" ; tar="tar chFFf" ; \ for i in `cat FILES` ; do list="$$list $$name/$$i" ; done; \ echo \ "rm -f ../$$name; ln -s $$dir ../$$name" ; \ rm -f ../$$name; ln -s $$dir ../$$name ; \ echo \ "(cd .. ; $$tar - [lots of files]) | compress > /tmp/$$name.tar.Z" ; \ (cd .. ; $$tar - $$list) | compress > /tmp/$$name.tar.Z ; \ echo \ "rm -f ../$$name" ; \ rm -f ../$$name force: /tmp depend: $(SRC) force ../bin/mkdep -c $(CC) $(DEFS) $(INCLS) $(SRC) argus-clients-2.0.6.fixes.1/common/argus_auth.c0000664000076600007660000003737207764413060015073 /* * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * Copyright (c) 2000 Carnegie Mellon University. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "Carnegie Mellon University" must not be used to * endorse or promote products derived from this software without * prior written permission. For permission or any other legal * details, please contact * Office of Technology Transfer * Carnegie Mellon University * 5000 Forbes Avenue * Pittsburgh, PA 15213-3890 * (412) 268-4387, fax: (412) 268-7395 * tech-transfer@andrew.cmu.edu * * 4. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by Computing Services * at Carnegie Mellon University (http://www.cmu.edu/computing/)." * * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Modified by Carter Bullard * QoSient, LLC * */ #ifndef ArgusAuth #define ArgusAuth #endif #include #include #include #include #include #ifdef ARGUS_SASL #include #include #include #endif /* ARGUS_SASL */ #include #include #include #include #include #include #include extern void ArgusLog (int, char *, ...); int ArgusInitializeAuthentication (struct ARGUS_INPUT *); int ArgusAuthenticate (struct ARGUS_INPUT *); #ifdef ARGUS_SASL extern int ArgusMaxSsf; extern int ArgusMinSsf; static int RaGetRealm(void *context, int, const char **, const char **); static int RaSimple(void *context, int, const char **, unsigned *); static int RaGetSecret(sasl_conn_t *, void *context, int, sasl_secret_t **); int RaSaslNegotiate(int, int, sasl_conn_t *); int RaGetSaslString (int, char *, int); int RaSendSaslString (int, const char *, int); /* RaCallBacks we support */ static sasl_callback_t RaCallBacks[] = { { SASL_CB_GETREALM, &RaGetRealm, NULL }, { SASL_CB_USER, &RaSimple, NULL }, { SASL_CB_AUTHNAME, &RaSimple, NULL }, { SASL_CB_PASS, &RaGetSecret, NULL }, { SASL_CB_LIST_END, NULL, NULL } }; char *RaSaslMech = NULL; #endif /* ARGUS_SASL */ int ArgusInitializeAuthentication (struct ARGUS_INPUT *input) { int retn = 1; #ifdef ARGUS_SASL #define SASL_SEC_MASK 0x0fff struct sockaddr_in localaddr, remoteaddr; int salen, fd = input->fd; char *remotehostname = NULL; int SASLOpts = 0; sasl_security_properties_t secprops; if ((retn = sasl_client_init(RaCallBacks)) != SASL_OK) ArgusLog (LOG_ERR, "ArgusInitializeAuthentication() sasl_client_init %d", retn); if ((remotehostname = input->hostname) != NULL) { if (!strchr (remotehostname, '.')) { if ((remotehostname = ArgusCalloc(1, 1024)) == NULL) ArgusLog (LOG_ERR, "ArgusInitializeAuthentication() ArgusCalloc %s", strerror(errno)); if (!(strcasecmp(input->hostname, "localhost"))) gethostname (remotehostname, 1024); else strcpy (remotehostname, input->hostname); if (!strchr (remotehostname, '.')) { strcat (remotehostname, "."); getdomainname (&remotehostname[strlen(remotehostname)], 1024 - strlen(remotehostname)); } } #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusInitializeAuthentication () auth argus.%s\n", remotehostname); #endif if ((retn = sasl_client_new("argus", remotehostname, NULL, SASL_SECURITY_LAYER, &input->sasl_conn)) != SASL_OK) ArgusLog (LOG_ERR, "ArgusInitializeAuthentication() sasl_client_new %s %d", remotehostname, retn); /* set external properties here sasl_setprop(input->sasl_conn, SASL_SSF_EXTERNAL, &extprops); */ /* set required security properties here */ secprops.min_ssf = ArgusMinSsf; secprops.max_ssf = ArgusMaxSsf; secprops.security_flags = SASLOpts & SASL_SEC_MASK; sasl_setprop(input->sasl_conn, SASL_SEC_PROPS, &secprops); /* set ip addresses */ salen = sizeof(localaddr); if (getsockname(fd, (struct sockaddr *)&localaddr, &salen) < 0) perror("getsockname"); salen = sizeof(remoteaddr); if (getpeername(fd, (struct sockaddr *)&remoteaddr, &salen) < 0) perror("getpeername"); if ((retn = sasl_setprop(input->sasl_conn, SASL_IP_LOCAL, &localaddr)) != SASL_OK) ArgusLog (LOG_ERR, "ArgusInitializeAuthentication() error setting localaddr %d", retn); if ((retn = sasl_setprop(input->sasl_conn, SASL_IP_REMOTE, &remoteaddr)) != SASL_OK) ArgusLog (LOG_ERR, "ArgusInitializeAuthentication() error setting remoteaddr %d", retn); retn = 1; } else retn = 0; #endif /* ARGUS_SASL */ #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusInitializeAuthentication () returning %d\n", retn); #endif return (retn); } int ArgusAuthenticate (struct ARGUS_INPUT *input) { int retn = 0; if (ArgusInitializeAuthentication(input)) { #ifdef ARGUS_SASL int fd = input->fd; if ((input->in = fd) < 0) ArgusLog (LOG_ERR, "ArgusAuthenticate(0x%x) in fd not set"); if ((input->out = fd) < 0) ArgusLog (LOG_ERR, "ArgusAuthenticate(0x%x) out fd not set"); if ((retn = RaSaslNegotiate(input->in, input->out, input->sasl_conn)) == SASL_OK) retn = 1; else retn = 0; #endif /* ARGUS_SASL */ } #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusAuthenticate (0x%x) returning %d\n", input, retn); #endif return (retn); } #ifdef ARGUS_SASL static void RaChop (char *s) /* remove \r\n at end of the line */ { char *p; assert(s); p = s + strlen(s) - 1; if (p[0] == '\n') *p-- = '\0'; if (p >= s && p[0] == '\r') *p-- = '\0'; } static int RaGetRealm(void *context __attribute__((unused)), int id, const char **availrealms, const char **result) { static char buf[1024]; if (id != SASL_CB_GETREALM) return SASL_BADPARAM; if (!result) return SASL_BADPARAM; printf("please choose a realm (available:"); while (*availrealms) { printf(" %s", *availrealms); availrealms++; } printf("): "); fgets(buf, sizeof buf, stdin); RaChop(buf); *result = buf; return SASL_OK; } static char RaSimpleBuf[1024]; static int RaSimple(void *context __attribute__((unused)), int id, const char **result, unsigned *len) { char *ptr = NULL; if (! result) return SASL_BADPARAM; switch (id) { case SASL_CB_USER: if (ustr == NULL) { printf("please enter an authorization id: "); fgets(RaSimpleBuf, sizeof RaSimpleBuf, stdin); } else { if ((ptr = strchr(ustr, '/')) != NULL) *ptr = '\0'; sprintf (RaSimpleBuf, "%s", ustr); if (ptr) *ptr = '/'; #ifdef ARGUSDEBUG ArgusDebug (4, "RaSimple SASL_CB_USER is %s", RaSimpleBuf); #endif } break; case SASL_CB_AUTHNAME: if (ustr != NULL) if ((ptr = strchr(ustr, '/')) != NULL) ptr++; if (ptr == NULL) { printf("please enter an authentication id: "); fgets(RaSimpleBuf, sizeof RaSimpleBuf, stdin); } else sprintf (RaSimpleBuf, "%s", ptr); #ifdef ARGUSDEBUG ArgusDebug (4, "RaSimple SASL_CB_AUTHNAME is %s", RaSimpleBuf); #endif break; default: return SASL_BADPARAM; } RaChop(RaSimpleBuf); *result = RaSimpleBuf; if (len) *len = strlen(RaSimpleBuf); return SASL_OK; } #ifndef HAVE_GETPASSPHRASE char * getpassphrase(const char *); char * getpassphrase(const char *prompt) { return getpass(prompt); } #endif /* ! HAVE_GETPASSPHRASE */ static int RaGetSecret(sasl_conn_t *conn, void *context __attribute__((unused)), int id, sasl_secret_t **psecret) { char *password; size_t len; static sasl_secret_t *x; if (! conn || ! psecret || id != SASL_CB_PASS) return SASL_BADPARAM; if (pstr != NULL) password = pstr; else password = getpassphrase("Password: "); if (! password) return SASL_FAIL; len = strlen(password); x = (sasl_secret_t *) realloc(x, sizeof(sasl_secret_t) + len); if (!x) { memset(password, 0, len); return SASL_NOMEM; } x->len = len; strcpy(x->data, password); *psecret = x; return SASL_OK; } int RaSaslNegotiate(int in, int out, sasl_conn_t *conn) { int retn = 0; char buf[8192]; char *data, c; const char *chosenmech; int len, cnt; #ifdef ARGUSDEBUG ArgusDebug (1, "RaSaslNegotiate(0x%x, 0x%x, 0x%x) receiving capability list... ", in, out, conn); #endif if ((len = RaGetSaslString(in, buf, sizeof(buf))) <= 0) ArgusLog (LOG_ERR, "RaSaslNegotiate: RaGetSaslString(0x%x, 0x%x, %d) error %s\n", in, buf, sizeof(buf), strerror(errno)); if (RaSaslMech) { /* make sure that 'RaSaslMech' appears in 'buf' */ if (!strstr(buf, RaSaslMech)) { printf("server doesn't offer mandatory mech '%s'\n", RaSaslMech); return 0; } } else RaSaslMech = buf; #ifdef ARGUSDEBUG ArgusDebug (1, "RaSaslNegotiate(0x%x, 0x%x, 0x%x) calling sasl_client_start()", in, out, conn); #endif retn = sasl_client_start(conn, RaSaslMech, NULL, NULL, &data, &len, &chosenmech); if ((retn != SASL_OK) && (retn != SASL_CONTINUE)) { if ((cnt = write(out, "N", 1)) != 1) ArgusLog (LOG_ERR, "RaSendSaslString: write error %s", strerror(errno)); ArgusLog (LOG_ERR, "RaSaslNegotiate: error starting SASL negotiation"); } if (retn == SASL_INTERACT) ArgusLog (LOG_ERR, "RaSaslNegotiate: returned SASL_INTERACT\n"); #ifdef ARGUSDEBUG ArgusDebug (1, "RaSaslNegotiate: using mechanism %s\n", chosenmech); #endif /* we send two strings; the mechanism chosen and the initial response */ RaSendSaslString(out, chosenmech, strlen(chosenmech)); RaSendSaslString(out, data, len); for (;;) { #ifdef ARGUSDEBUG ArgusDebug (2, "waiting for server reply...\n"); #endif if ((cnt = read(in, &c, 1)) != 1) ArgusLog (LOG_ERR, "RaGetSaslString: read error %s", strerror(errno)); switch (c) { case 'O': goto done_ok; case 'N': goto done_no; case 'C': /* continue authentication */ break; default: printf("bad protocol from server (%c %x)\n", c, c); return 0; } if ((len = RaGetSaslString(in, buf, sizeof(buf))) <= 0) ArgusLog (LOG_ERR, "RaSaslNegotiate: RaGetSaslString(%d, 0x%x, %d) returned %d\n", in, buf, sizeof(buf), len); retn = sasl_client_step(conn, buf, len, NULL, &data, &len); if ((retn != SASL_OK) && (retn != SASL_CONTINUE)) { if ((cnt = write(out, "N", 1)) != 1) ArgusLog (LOG_ERR, "RaSendSaslString: write error %s", strerror(errno)); ArgusLog (LOG_ERR, "RaSaslNegotiate: error performing SASL negotiation"); } if (data) { #ifdef ARGUSDEBUG ArgusDebug (2, "sending response length %d...\n", len); #endif RaSendSaslString(out, data, len); free(data); } else { #ifdef ARGUSDEBUG ArgusDebug (2, "sending null response...\n"); #endif RaSendSaslString(out, "", 0); } } done_ok: #ifdef ARGUSDEBUG ArgusDebug (1, "successful authentication"); #endif return SASL_OK; done_no: #ifdef ARGUSDEBUG ArgusDebug (1, "authentication failed"); #endif return -1; } /* send/recv library for IMAP4 style literals. */ int RaSendSaslString (int fd, const char *s, int l) { char saslbuf[MAXSTRLEN]; int len, cnt = 0; bzero (saslbuf, MAXSTRLEN); sprintf(saslbuf, "{%d}\r\n", l); len = strlen(saslbuf); bcopy (s, &saslbuf[len], l); len += l; if ((cnt = write(fd, saslbuf, len)) != len) ArgusLog (LOG_ERR, "RaSendSaslString: write error %s", strerror(errno)); #ifdef ARGUSDEBUG ArgusDebug (3, "RaSendSaslString(%d, 0x%x, %d)\n", fd, s, l); s = saslbuf; if (3 <= Argusdflag) { while (len--) { if (isprint((int)((unsigned char) *s))) { printf("%c ", *s); } else { printf("%x ", (unsigned char) *s); } s++; } printf("\n"); } #endif return cnt; } int RaGetSaslString (int fd, char *buf, int buflen) { int c = 0, len = 0, l = 0, cnt = 0; char *s = NULL; if ((cnt = read(fd, &c, 1)) != 1) ArgusLog (LOG_ERR, "RaGetSaslString: read error %s", strerror(errno)); if (c != '{') return -1; /* read length */ len = 0; if ((cnt = read(fd, &c, 1)) != 1) ArgusLog (LOG_ERR, "RaGetSaslString: read error %s", strerror(errno)); while (isdigit(c)) { len = len * 10 + (c - '0'); if ((cnt = read(fd, &c, 1)) != 1) ArgusLog (LOG_ERR, "RaGetSaslString: read error %s", strerror(errno)); } if (c != '}') return -1; if ((cnt = read(fd, &c, 1)) != 1) ArgusLog (LOG_ERR, "RaGetSaslString: read error %s", strerror(errno)); if (c != '\r') return -1; if ((cnt = read(fd, &c, 1)) != 1) ArgusLog (LOG_ERR, "RaGetSaslString: read error %s", strerror(errno)); if (c != '\n') return -1; /* read string */ if (buflen <= len) { if ((cnt = read(fd, buf, buflen - 1)) != (buflen - 1)) ArgusLog (LOG_ERR, "RaGetSaslString: read error %s", strerror(errno)); buf[buflen - 1] = '\0'; /* discard oversized string */ len -= buflen - 1; while (len--) if ((cnt = read(fd, &c, 1)) != 1) ArgusLog (LOG_ERR, "RaGetSaslString: read error %s", strerror(errno)); len = buflen - 1; } else { if ((cnt = read(fd, buf, len)) != len) ArgusLog (LOG_ERR, "RaGetSaslString: read error %s", strerror(errno)); buf[len] = '\0'; } l = len; s = buf; #ifdef ARGUSDEBUG ArgusDebug (3, "RaGetSaslString(%d, 0x%x, %d)\n", fd, s, l); if (3 <= Argusdflag) { while (l--) { if (isprint((int)((unsigned char) *s))) { printf("%c ", *s); } else { printf("%X ", (unsigned char) *s); } s++; } printf("\n"); } #endif return len; } #endif /* ARGUS_SASL */ argus-clients-2.0.6.fixes.1/common/argus_client.c0000664000076600007660000041433710047703216015401 /* * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * argus client library * * written by Carter Bullard * QoSient, LLC * */ #ifndef ArgusClient #define ArgusClient #endif #include #include #define RA_ADD_OPTION 1 #define RA_SUB_OPTION 2 void RaProcessSOptions(void); void RaProcessSOptions() { int i, x, RaOptionOperation, RaOptionRank; char *soption = NULL; if ((soption = RaSOptionStrings[0]) != NULL) { if (!((*soption == '+') || (*soption == '-'))) bzero ((char *) RaPrintAlgorithms, sizeof(RaPrintAlgorithms)); } else ArgusLog (LOG_ERR, "ArgusClientInit Index %d String NULL", RaSOptionIndex); for (i = 0; i < ARGUS_MAX_S_OPTIONS; i++) { if ((soption = RaSOptionStrings[i]) != NULL) { RaOptionOperation = RA_ADD_OPTION; RaOptionRank = -1; if ((*soption == '+') || (*soption == '-')) { if (*soption == '-') RaOptionOperation = RA_SUB_OPTION; soption++; if (isdigit((int)*soption)) { sscanf(soption, "%d", &RaOptionRank); while(isdigit((int)*soption)) soption++; } } RaPrintDate = 0; for (x = 0; x < MAX_PRINT_ALG_TYPES; x++) { if (!strncmp (RaPrintKeyWords[x], soption, strlen(RaPrintKeyWords[x]))) { if (x < 3) RaPrintDate++; switch (RaOptionOperation) { case RA_ADD_OPTION: if (RaOptionRank == -1) { int z = 0; while (RaPrintAlgorithms[z] != NULL) z++; if (z < ARGUS_MAX_PRINT_ALG) RaPrintAlgorithms[z] = RaPrintAlgorithmTable[x]; } else { int z = RaOptionRank; while (RaPrintAlgorithms[z] != NULL) z++; while (z != RaOptionRank) { RaPrintAlgorithms[z] = RaPrintAlgorithms[z - 1]; RaPrintAlgorithms[z - 1] = NULL; z--; } RaPrintAlgorithms[z] = RaPrintAlgorithmTable[x]; } break; case RA_SUB_OPTION: { for (RaOptionRank = 0; RaOptionRank < ARGUS_MAX_PRINT_ALG; RaOptionRank++) if (RaPrintAlgorithms[RaOptionRank] == RaPrintAlgorithmTable[x]) break; if (RaOptionRank < ARGUS_MAX_PRINT_ALG) { RaPrintAlgorithms[RaOptionRank] = NULL; while (RaOptionRank < ARGUS_MAX_PRINT_ALG) { RaPrintAlgorithms[RaOptionRank] = RaPrintAlgorithms[RaOptionRank + 1]; RaOptionRank++; } } break; } } break; } } } else break; } } struct ArgusRecord * RaCopyArgusRecord (struct ArgusRecord *argus) { int length = 0; struct ArgusRecord *retn = NULL; if (argus && ((length = argus->ahdr.length) > 0)) if ((retn = (struct ArgusRecord *) ArgusCalloc(1, length)) != NULL) bcopy ((char *) argus, (char *) retn, length); return (retn); } long long RaGetActiveDuration (struct ArgusRecord *argus) { return (RaGetuSecDuration (argus)); } long long RaGetuSecAvgDuration (struct ArgusRecord *); long long RaGetuSecAvgDuration (struct ArgusRecord *argus) { struct ArgusAGRStruct *agr; struct ArgusFarHeaderStruct *argusthisfarhdrs[32]; long long retn = 0; int sec, usec; ArgusIndexRecord (argus, argusthisfarhdrs); if ((agr = (struct ArgusAGRStruct *) argusthisfarhdrs[ARGUS_AGR_DSR_INDEX]) != NULL) { int ArgusThisMultiplier = 1000; if (agr->status & ARGUS_AGR_USECACTTIME) ArgusThisMultiplier = 1; if (agr->act.n) return (agr->act.meanval * ArgusThisMultiplier); } sec = argus->argus_far.time.last.tv_sec - argus->argus_far.time.start.tv_sec; usec = argus->argus_far.time.last.tv_usec - argus->argus_far.time.start.tv_usec; if (usec < 0) { sec--; usec += 1000000; } retn = ((long long) (sec * 1000000)) + (long long) usec; return (retn); } long long RaGetuSecDuration (struct ArgusRecord *argus) { unsigned int retn = 0; int sec, usec; sec = argus->argus_far.time.last.tv_sec - argus->argus_far.time.start.tv_sec; usec = argus->argus_far.time.last.tv_usec - argus->argus_far.time.start.tv_usec; if (usec < 0) { sec--; usec += 1000000; } retn = ((long long)(sec * 1000000)) + (long long)usec; return (retn); } int RaTypeMatches (u_short policytype, u_short recordtype) { int retn = 1; if (policytype != 0xFFFF) if ((policytype != recordtype) && (recordtype != 65535)) retn = 0; return(retn); } int RaCIDRAddrMatches (u_int addr, struct RaCIDRAddr *cidr) { int retn = 1; switch (cidr->type) { case RA_CIDR_TYPE: if (cidr->addr) { if ((addr & cidr->mask) != cidr->addr) retn = 0; } break; case RA_NETCLASS_TYPE: if (cidr->addr) { if ((addr & ipaddrtonetmask(addr)) != cidr->addr) retn = 0; } break; } #ifdef ARGUSDEBUG ArgusDebug (6, "RaCIDRAddrMatches(0x%x, 0x%x) returned %d\n", addr, cidr, retn); #endif return (retn); } int RaProtoMatches (u_short p, int proto) { int retn = 1; if (proto != 0xFF) retn = (p == proto) ? 1 : 0; #ifdef ARGUSDEBUG ArgusDebug (6, "RaProtoMatches (%d, %d) returned %d\n", p, proto, retn); #endif return (retn); } int RaPortMatches (u_short p1, u_short p2) { int retn = 1; if (p2 != 0xFFFF) retn = (p1 == p2) ? 1 : 0; #ifdef ARGUSDEBUG ArgusDebug (6, "RaPortMatches (%d, %d) returned %d\n", p1, p2, retn); #endif return (retn); } int RaPolicyMatch (struct ArgusRecord *argus, struct RaPolicyStruct *rap) { int retn = 0; struct ArgusFlow *flow = &argus->argus_far.flow; u_char proto = flow->ip_flow.ip_p; if (RaTypeMatches ((argus->ahdr.status & 0xFFFF), rap->type)) if (RaCIDRAddrMatches (flow->ip_flow.ip_src, &rap->src)) if (RaCIDRAddrMatches (flow->ip_flow.ip_dst, &rap->dst)) if (RaProtoMatches (flow->ip_flow.ip_p, rap->proto)) switch (proto) { case IPPROTO_TCP: case IPPROTO_UDP: if (RaPortMatches (flow->ip_flow.sport, rap->sport)) if (RaPortMatches (flow->ip_flow.dport, rap->dport)) retn = 1; break; case IPPROTO_ICMP: if (RaPortMatches (flow->icmp_flow.type, rap->sport)) if (RaPortMatches (flow->icmp_flow.code, rap->dport)) retn = 1; break; default: retn = 1; break; } #ifdef ARGUSDEBUG ArgusDebug (6, "RaPolicyMatch(0x%x, 0x%x) returned %d\n", argus, rap, retn); #endif return (retn); } struct RaPolicyStruct * RaFlowModelOverRides (struct ArgusRecord *argus, struct RaFlowModelStruct *fmodel) { struct RaPolicyStruct *retn = NULL; int i; if (fmodel) { switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_ARP: case ETHERTYPE_IP: for (i = 0; i < fmodel->pindex; i++) { if (RaPolicyMatch (argus, fmodel->policy[i])) { retn = fmodel->policy[i]; break; } } break; case ETHERTYPE_REVARP: break; default: break; } } #ifdef ARGUSDEBUG ArgusDebug (7, "RaFlowModelOverRides(0x%x) returned 0x%x\n", argus, retn); #endif return (retn); } #if defined(__OpenBSD__) #include #include #endif #include #include void RaModifyDefaultFlow (struct ArgusRecord *argus) { struct ArgusFlow *flow = &argus->argus_far.flow; switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: if (argus->argus_far.flow.ip_flow.tp_p == ARGUS_FRAG_FLOWTAG) argus->argus_far.flow.ip_flow.tp_p = 0; switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_UDP: case IPPROTO_TCP: break; case IPPROTO_ICMP: if (flow->icmp_flow.type != ICMP_UNREACH) flow->icmp_flow.id = 0xFFFF; flow->icmp_flow.ip_id = 0xFFFF; break; default: break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: break; default: break; } } int RaFlowMajorModified = 0; void RaModifyFlow (struct RaPolicyStruct *rap, struct ArgusRecord *argus, struct RaFlowModelStruct *fmodel) { struct RaPolicyStruct *model = NULL; struct ArgusFlow *flow = &argus->argus_far.flow; u_short proto; RaFlowMajorModified = 0; if (fmodel->model) { int i; for (i = 0; i < fmodel->mindex; i++) { if (fmodel->model[i]->RaPolicyId == rap->RaModelId) { model = fmodel->model[i]; break; } } } else ArgusLog (LOG_ERR, "RaModifyFlow () model is NULL"); switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: if (flow->ip_flow.tp_p == ARGUS_FRAG_FLOWTAG) { flow->ip_flow.tp_p = 0; } if (model) { switch (model->src.type) { case RA_CIDR_TYPE: flow->ip_flow.ip_src = flow->ip_flow.ip_src & model->src.addr; break; case RA_NETCLASS_TYPE: flow->ip_flow.ip_src = flow->ip_flow.ip_src & ipaddrtonetmask(flow->ip_flow.ip_src); break; } switch (model->dst.type) { case RA_CIDR_TYPE: flow->ip_flow.ip_dst = flow->ip_flow.ip_dst & model->dst.addr; break; case RA_NETCLASS_TYPE: flow->ip_flow.ip_dst = flow->ip_flow.ip_dst & ipaddrtonetmask(flow->ip_flow.ip_dst); break; } proto = flow->ip_flow.ip_p; flow->ip_flow.ip_p &= model->proto; switch (proto) { case IPPROTO_TCP: flow->ip_flow.tp_p = 0; case IPPROTO_UDP: switch (proto) { case IPPROTO_TCP: if (flow->ip_flow.sport == 20) { if (!(model->sport)) flow->ip_flow.dport = 0xFFFF; if (!(model->dport)) { flow->ip_flow.sport = 0xFFFF; RaFlowMajorModified = 1; } } else case IPPROTO_UDP: if (!(model->sport)) flow->ip_flow.sport = 0xFFFF; if (!(model->dport)) { flow->ip_flow.dport = 0xFFFF; RaFlowMajorModified = 1; } break; default: flow->ip_flow.sport = 0xFFFF; flow->ip_flow.dport = 0xFFFF; break; } break; case IPPROTO_ICMP: if (!(model->sport)) { flow->icmp_flow.type = 0xFF; RaFlowMajorModified = 1; } if (!(model->dport)) { flow->icmp_flow.code = 0xFF; RaFlowMajorModified = 1; } flow->icmp_flow.id = 0xFFFF; flow->icmp_flow.ip_id = 0xFFFF; flow->icmp_flow.tp_p = 0; break; default: flow->ip_flow.tp_p = 0; if (!(model->sport)) flow->ip_flow.sport = 0xFFFF; else flow->ip_flow.sport = 0; if (!(model->dport)) flow->ip_flow.dport = 0xFFFF; else flow->ip_flow.dport = 0; RaFlowMajorModified = 1; break; } if (flow->ip_flow.ip_p == 0) flow->ip_flow.tp_p = 0; } break; case ETHERTYPE_ARP: if (model) { switch (model->src.type) { case RA_CIDR_TYPE: flow->arp_flow.arp_spa = flow->arp_flow.arp_spa & model->src.addr; break; case RA_NETCLASS_TYPE: flow->arp_flow.arp_spa = flow->arp_flow.arp_spa & ipaddrtonetmask(flow->ip_flow.ip_src); break; } switch (model->dst.type) { case RA_CIDR_TYPE: flow->arp_flow.arp_tpa = flow->arp_flow.arp_tpa & model->dst.addr; break; case RA_NETCLASS_TYPE: flow->arp_flow.arp_tpa = flow->arp_flow.arp_tpa & ipaddrtonetmask(flow->ip_flow.ip_dst); break; } bzero (flow->arp_flow.etheraddr, 6); flow->arp_flow.pad = 0; } break; case ETHERTYPE_REVARP: default: break; } #ifdef ARGUSDEBUG ArgusDebug (7, "RaModifyFlow(0x%x, 0x%x) done.\n", rap, argus); #endif } int RaThisFlowRev = 0; struct ArgusRecordStore * RaFindRevArgusRecord(struct RaHashTableStruct *htable, struct ArgusRecord *argus) { struct ArgusRecordStore *retn = NULL; struct RaHashTableHeader *hashEntry; struct ArgusFlow flowbuf, *RaThisFlow = &flowbuf; struct RaHashStruct ArgusHash; struct ArgusFlow flow; unsigned short *ptr = NULL; unsigned short ip_id = 0; int i, len; bzero ((char *)&ArgusHash, sizeof(ArgusHash)); ArgusHash.len = sizeof(ArgusHash.buf); *RaThisFlow = argus->argus_far.flow; flow = *RaThisFlow; RaThisFlowRev = 0; if (!(RaAutoCorrection)) return (retn); if ((argus->ahdr.status & 0xFFFF) == ETHERTYPE_IP) { switch (flow.ip_flow.ip_p) { case IPPROTO_UDP: case IPPROTO_TCP: RaThisFlow->ip_flow.ip_src = flow.ip_flow.ip_dst; RaThisFlow->ip_flow.ip_dst = flow.ip_flow.ip_src; RaThisFlow->ip_flow.sport = flow.ip_flow.dport; RaThisFlow->ip_flow.dport = flow.ip_flow.sport; ip_id = RaThisFlow->ip_flow.ip_id; RaThisFlow->ip_flow.ip_id = 0; break; case IPPROTO_ICMP: { RaThisFlow->icmp_flow.ip_src = flow.icmp_flow.ip_dst; RaThisFlow->icmp_flow.ip_dst = flow.icmp_flow.ip_src; ip_id = RaThisFlow->icmp_flow.ip_id; RaThisFlow->icmp_flow.ip_id = 0; switch (RaThisFlow->icmp_flow.type) { case ICMP_MASKREQ: RaThisFlow->icmp_flow.type = ICMP_MASKREPLY; break; case ICMP_MASKREPLY: RaThisFlow->icmp_flow.type = ICMP_MASKREQ; break; case ICMP_ECHO: RaThisFlow->icmp_flow.type = ICMP_ECHOREPLY; break; case ICMP_ECHOREPLY: RaThisFlow->icmp_flow.type = ICMP_ECHO; break; case ICMP_TSTAMP: RaThisFlow->icmp_flow.type = ICMP_TSTAMPREPLY; break; case ICMP_TSTAMPREPLY: RaThisFlow->icmp_flow.type = ICMP_TSTAMP; break; case ICMP_IREQ: RaThisFlow->icmp_flow.type = ICMP_IREQREPLY; break; case ICMP_IREQREPLY: RaThisFlow->icmp_flow.type = ICMP_IREQ; break; } break; } case IPPROTO_ESP: default: RaThisFlow->ip_flow.ip_src = flow.ip_flow.ip_dst; RaThisFlow->ip_flow.ip_dst = flow.ip_flow.ip_src; ip_id = RaThisFlow->ip_flow.ip_id; RaThisFlow->ip_flow.ip_id = 0; break; } } ArgusHash.buf[0] = argus->ahdr.argusid; bcopy (RaThisFlow, (char *)&ArgusHash.buf[1], sizeof(*RaThisFlow)); ptr = (unsigned short *)&ArgusHash.buf[0]; for (i = 0, len = ArgusHash.len / sizeof(unsigned short); i < len; i++) ArgusHash.hash += *ptr++; if ((hashEntry = RaFindHashEntry (htable, &ArgusHash)) != NULL) { RaThisFlowRev++; retn = hashEntry->storeobj; } switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: { switch (flow.ip_flow.ip_p) { default: case IPPROTO_TCP: case IPPROTO_UDP: RaThisFlow->ip_flow.ip_id = ip_id; break; case IPPROTO_ICMP: RaThisFlow->icmp_flow.ip_id = ip_id; break; } } } return (retn); } struct ArgusRecordStore * RaFindArgusRecord(struct RaHashTableStruct *htable, struct ArgusRecord *argus) { struct ArgusRecordStore *retn = NULL; struct RaHashTableHeader *hashEntry; struct ArgusFlow *RaThisFlow = NULL; unsigned short *ptr, ip_id = 0; struct RaHashStruct ArgusHash; int i, len; bzero ((char *)&ArgusHash, sizeof(ArgusHash)); ArgusHash.len = sizeof(ArgusHash.buf); RaThisFlowRev = 0; RaThisFlow = &argus->argus_far.flow; switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: { switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_ICMP: ip_id = RaThisFlow->icmp_flow.ip_id; RaThisFlow->icmp_flow.ip_id = 0; break; default: ip_id = RaThisFlow->ip_flow.ip_id; RaThisFlow->ip_flow.ip_id = 0; break; } } } ArgusHash.buf[0] = argus->ahdr.argusid; bcopy (RaThisFlow, (char *)&ArgusHash.buf[1], sizeof(*RaThisFlow)); ptr = (unsigned short *)&ArgusHash.buf[0]; for (i = 0, len = ArgusHash.len / sizeof(unsigned short); i < len; i++) ArgusHash.hash += *ptr++; if ((hashEntry = RaFindHashEntry (htable, &ArgusHash)) != NULL) retn = hashEntry->storeobj; switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: { switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_ICMP: RaThisFlow->icmp_flow.ip_id = ip_id; break; default: RaThisFlow->ip_flow.ip_id = ip_id; break; } } } #ifdef ARGUSDEBUG ArgusDebug (4, "RaFindArgusRecord: returning 0x%x\n", retn); #endif return (retn); } struct ArgusRecordStore * RaNewArgusStore(struct ArgusRecord *argus) { struct ArgusRecordStore *retn = NULL; struct timeval lasttime; if ((retn = (struct ArgusRecordStore *) ArgusCalloc (1, sizeof(struct ArgusRecordStore))) != NULL) { RaAllocArgusRecordStore++; if (argus != NULL) { lasttime = argus->argus_far.time.last; retn->qhdr.lasttime = lasttime; retn->qhdr.logtime = lasttime; } if ((retn->data = (struct ArgusRecordData **) ArgusCalloc (RaHistoTimeSeries + 1, sizeof(void *))) == NULL) ArgusLog (LOG_ERR, "RaNewArgusStore () ArgusCalloc %s\n", strerror(errno)); } else ArgusLog (LOG_ERR, "RaNewArgusStore () ArgusCalloc %s\n", strerror(errno)); #ifdef ARGUSDEBUG ArgusDebug (6, "RaNewArgusStore: added 0x%x\n", retn); #endif return (retn); } void RaDeleteArgusStore(struct ArgusRecordStore *); void RaDeleteArgusData(struct ArgusRecordData *); /* struct ArgusRecordStore { struct ArgusQueueHeader qhdr; struct RaHashTableStruct *htable; struct RaHashTableHeader *rahtblhdr; struct RaQueueStruct *queue; struct timeval startime, lasttime; int ArgusTimeout, ArgusIdleTimeout; int status, sortag; char *displaystr; struct ArgusRecordData **data; struct ArgusRecord *cor[8]; struct RaSrvSignature *sig; struct ArgusStoreObjectStruct *object; }; */ void RaDeleteArgusStore(struct ArgusRecordStore *store) { int i = 0; if (store->qhdr.queue != NULL) RaRemoveFromQueue(store->qhdr.queue, &store->qhdr); if (store->rahtblhdr != NULL) { if (store->rahtblhdr->htable != NULL) RaRemoveHashEntry (store->rahtblhdr->htable, store->rahtblhdr); store->rahtblhdr = NULL; } if (store->data != NULL) { for (i = 0; i < RaHistoTimeSeries + 1; i++) if (store->data[i] != NULL) RaDeleteArgusData(store->data[i]); ArgusFree(store->data); store->data = NULL; } if (store->queue != NULL) { RaDeleteQueue(store->queue); store->queue = NULL; } if (store->displaystr != NULL) { free(store->displaystr); store->displaystr = NULL; } if (store->object != NULL) { ArgusFree(store->object); store->object = NULL; } ArgusFree(store); #ifdef ARGUSDEBUG ArgusDebug (6, "RaDeleteArgusStore(0x%x): Done\n", store); #endif } int RaAllocArgusRecordData = 0; int RaTotalDataRecords = 0; struct ArgusRecordData * RaNewArgusData(struct ArgusRecord *argus) { struct ArgusRecordData *retn = NULL; struct timeval lasttime; if ((retn = (struct ArgusRecordData *) ArgusCalloc (1, sizeof (*retn))) != NULL) { RaAllocArgusRecordData++; if ((retn->argus = RaCopyArgusRecord(argus)) != NULL) { RaTotalDataRecords++; retn->agr.laststartime = argus->argus_far.time.start; lasttime = argus->argus_far.time.last; retn->agr.type = ARGUS_AGR_DSR; retn->agr.length = sizeof(retn->agr); retn->agr.lasttime = lasttime; retn->agr.act.maxval = RaThisActiveDuration; retn->agr.act.minval = RaThisActiveDuration; retn->act.sumtime = RaThisActiveDuration; if (RaThisActiveDuration != 0) retn->act.sumsqrd = pow (RaThisActiveDuration, 2.0); retn->act.n = 1; retn->agr.count = 1; retn->agr.idle.minval = 0x7FFFFFFF; retn->agr.status |= ARGUS_AGR_USECACTTIME; retn->agr.status |= ARGUS_AGR_USECIDLETIME; bcopy ((char *) RaArgusFlow, (char *)&retn->flow, sizeof(retn->flow)); } else { ArgusFree (retn); RaAllocArgusRecordData--; retn = NULL; } } #ifdef ARGUSDEBUG ArgusDebug (6, "RaNewArgusData: added 0x%x\n", retn); #endif return (retn); } void RaDeleteArgusData(struct ArgusRecordData *data) { if (data->argus != NULL) ArgusFree(data->argus); ArgusFree(data); #ifdef ARGUSDEBUG ArgusDebug (6, "RaRemoveArgusRecord: done\n"); #endif } void RaRemoveArgusRecord(struct ArgusRecord *argus) { #ifdef ARGUSDEBUG ArgusDebug (6, "RaRemoveArgusRecord: done\n"); #endif } void RaMergeArgusRecord(struct ArgusRecord *a1, struct ArgusRecordStore *store, int index) { u_char buf[MAXSTRLEN]; struct ArgusRecordData *data = store->data[index]; struct ArgusRecord *a2 = NULL, *tmp = (struct ArgusRecord *)buf; struct ArgusFarHeaderStruct *a1farhdr[32], *a2farhdr[32]; struct ArgusFarStruct *far1 = NULL; struct ArgusFarStruct *far2 = NULL; struct ArgusFarStruct *ArgusThisDataFar; unsigned int a1DSRStatus = 0, a2DSRStatus = 0; unsigned int i, status = 0, TimeMultiplier; struct ArgusAGRStruct *agr; unsigned int duration, rev = 0; if (!(a1 && data)) return; if ((a2 = data->argus) != NULL) { bzero (buf, sizeof(buf)); bcopy ((char *) a2, buf, a2->ahdr.length); ArgusThisDataFar = (struct ArgusFarStruct *) data->farhdrs[ARGUS_FAR_DSR_INDEX]; a1DSRStatus = ArgusIndexRecord (a1, a1farhdr); a2DSRStatus = ArgusIndexRecord (tmp, a2farhdr); status = a1DSRStatus & a2DSRStatus; far1 = (struct ArgusFarStruct *) a1farhdr[ARGUS_FAR_DSR_INDEX]; far2 = (struct ArgusFarStruct *) a2farhdr[ARGUS_FAR_DSR_INDEX]; if (!(RaThisFlowRev)) { if (((far2->src.count + far1->src.count) < far2->src.count) || ((far2->dst.count + far1->dst.count) < far2->dst.count) || ((far2->src.bytes + far1->src.bytes) < far2->src.bytes) || ((far2->dst.bytes + far1->dst.bytes) < far2->dst.bytes)) { goto doneRaMergeArgus; } } else { if (((far2->src.count + far1->dst.count) < far2->src.count) || ((far2->dst.count + far1->src.count) < far2->dst.count) || ((far2->src.bytes + far1->dst.bytes) < far2->src.bytes) || ((far2->dst.bytes + far1->src.bytes) < far2->dst.bytes)) { goto doneRaMergeArgus; } if ((far1->time.start.tv_sec < far2->time.start.tv_sec) || ((far1->time.start.tv_sec == far2->time.start.tv_sec) && (far1->time.start.tv_usec < far2->time.start.tv_usec))) { rev++; } } for (i = 0; i < 32; i++) { if (status & 0x01) { switch (i) { case ARGUS_FAR_DSR_INDEX: { u_int diffstartime = 0; int diffusec = 0; far1 = (struct ArgusFarStruct *) a1farhdr[i]; far2 = (struct ArgusFarStruct *) a2farhdr[i]; switch (a2->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: { if (!(RaThisFlowRev)) { if (!(data->status & ARGUS_FAR_SRCADDR_MODIFIED)) if (RaArgusFlow->ip_flow.ip_src != data->flow.ip_flow.ip_src) { data->status |= ARGUS_FAR_SRCADDR_MODIFIED; if (far2->flow.ip_flow.ip_src != far1->flow.ip_flow.ip_src) far2->flow.ip_flow.ip_src = far1->flow.ip_flow.ip_src; } if (!(data->status & ARGUS_FAR_DSTADDR_MODIFIED)) if (RaArgusFlow->ip_flow.ip_dst != data->flow.ip_flow.ip_dst) { data->status |= ARGUS_FAR_DSTADDR_MODIFIED; if (far2->flow.ip_flow.ip_dst != far1->flow.ip_flow.ip_dst) far2->flow.ip_flow.ip_dst = far1->flow.ip_flow.ip_dst; } if (!(data->status & ARGUS_FAR_PROTO_MODIFIED)) if (RaArgusFlow->ip_flow.ip_p != data->flow.ip_flow.ip_p) { data->status |= ARGUS_FAR_PROTO_MODIFIED; if (far2->flow.ip_flow.ip_p != far1->flow.ip_flow.ip_p) far2->flow.ip_flow.ip_p = far1->flow.ip_flow.ip_p; } switch (data->flow.ip_flow.ip_p) { case IPPROTO_UDP: case IPPROTO_TCP: far2->flow.ip_flow.ip_id = far1->flow.ip_flow.ip_id; if (!(data->status & ARGUS_FAR_SRCPORT_MODIFIED)) if (RaArgusFlow->ip_flow.sport != data->flow.ip_flow.sport) { data->status |= ARGUS_FAR_SRCPORT_MODIFIED; if (far2->flow.ip_flow.sport != far1->flow.ip_flow.sport) far2->flow.ip_flow.sport = 0xFFFF; } if (!(data->status & ARGUS_FAR_DSTPORT_MODIFIED)) if (RaArgusFlow->ip_flow.dport != data->flow.ip_flow.dport) { data->status |= ARGUS_FAR_DSTPORT_MODIFIED; if (far2->flow.ip_flow.dport != far1->flow.ip_flow.dport) far2->flow.ip_flow.dport = 0xFFFF; } break; case IPPROTO_IGMP: break; case IPPROTO_ICMP: if (far2->flow.icmp_flow.type != far1->flow.icmp_flow.type) far2->flow.icmp_flow.type = 0xFF; if (far2->flow.icmp_flow.code != far1->flow.icmp_flow.code) far2->flow.icmp_flow.code = 0xFF; far2->flow.icmp_flow.ip_id = far1->flow.icmp_flow.ip_id; break; } if (!(data->status & ARGUS_FAR_TPVAL_MODIFIED)) if (RaArgusFlow->ip_flow.tp_p != data->flow.ip_flow.tp_p) { data->status |= ARGUS_FAR_TPVAL_MODIFIED; if (far2->flow.ip_flow.tp_p != far1->flow.ip_flow.tp_p) far2->flow.ip_flow.tp_p = 0; } } else { if (!(data->status & ARGUS_FAR_SRCADDR_MODIFIED)) if (RaArgusFlow->ip_flow.ip_src != data->flow.ip_flow.ip_src) { data->status |= ARGUS_FAR_SRCADDR_MODIFIED; if (far2->flow.ip_flow.ip_src != far1->flow.ip_flow.ip_dst) far2->flow.ip_flow.ip_src = far1->flow.ip_flow.ip_src; } if (!(data->status & ARGUS_FAR_DSTADDR_MODIFIED)) if (RaArgusFlow->ip_flow.ip_dst != data->flow.ip_flow.ip_dst) { data->status |= ARGUS_FAR_DSTADDR_MODIFIED; if (far2->flow.ip_flow.ip_dst != far1->flow.ip_flow.ip_src) far2->flow.ip_flow.ip_dst = far1->flow.ip_flow.ip_dst; } if (!(data->status & ARGUS_FAR_PROTO_MODIFIED)) if (RaArgusFlow->ip_flow.ip_p != data->flow.ip_flow.ip_p) { data->status |= ARGUS_FAR_PROTO_MODIFIED; if (far2->flow.ip_flow.ip_p != far1->flow.ip_flow.ip_p) far2->flow.ip_flow.ip_p = far1->flow.ip_flow.ip_p; } switch (far2->flow.ip_flow.ip_p) { case IPPROTO_UDP: case IPPROTO_TCP: if (!(data->status & ARGUS_FAR_SRCPORT_MODIFIED)) if (RaArgusFlow->ip_flow.sport != data->flow.ip_flow.sport) { data->status |= ARGUS_FAR_SRCPORT_MODIFIED; if (far2->flow.ip_flow.sport != far1->flow.ip_flow.dport) far2->flow.ip_flow.sport = 0xFFFF; } if (!(data->status & ARGUS_FAR_DSTPORT_MODIFIED)) if (RaArgusFlow->ip_flow.dport != data->flow.ip_flow.dport) { data->status |= ARGUS_FAR_DSTPORT_MODIFIED; if (far2->flow.ip_flow.dport != far1->flow.ip_flow.sport) far2->flow.ip_flow.dport = 0xFFFF; } break; case IPPROTO_IGMP: break; case IPPROTO_ICMP: break; } if (!(data->status & ARGUS_FAR_TPVAL_MODIFIED)) if (RaArgusFlow->ip_flow.tp_p != data->flow.ip_flow.tp_p) { data->status |= ARGUS_FAR_TPVAL_MODIFIED; if (far2->flow.ip_flow.tp_p != far1->flow.ip_flow.tp_p) far2->flow.ip_flow.tp_p = 0; } } } } if (!(RaThisFlowRev)) { if (((far2->src.count + far1->src.count) < far2->src.count) || ((far2->src.bytes + far1->src.bytes) < far2->src.bytes) || ((far2->dst.count + far1->dst.count) < far2->dst.count) || ((far2->dst.bytes + far1->dst.bytes) < far2->dst.bytes)) RaSendArgusRecord(store); far2->src.count += far1->src.count; far2->src.bytes += far1->src.bytes; far2->dst.count += far1->dst.count; far2->dst.bytes += far1->dst.bytes; far2->src.appbytes += far1->src.appbytes; far2->dst.appbytes += far1->dst.appbytes; if ((a1->ahdr.status & 0xFFFF) == ETHERTYPE_IP) { if (far1->attr_ip.sttl != far2->attr_ip.sttl) far2->attr_ip.sttl = 0xFF; if (far1->attr_ip.dttl != far2->attr_ip.dttl) far2->attr_ip.dttl = 0xFF; if (far1->attr_ip.stos != far2->attr_ip.stos) far2->attr_ip.stos = 0xFF; if (far1->attr_ip.dtos != far2->attr_ip.dtos) far2->attr_ip.dtos = 0xFF; } } else { if (((far2->src.count + far1->dst.count) < far2->src.count) || ((far2->src.bytes + far1->dst.bytes) < far2->src.bytes) || ((far2->dst.count + far1->src.count) < far2->dst.count) || ((far2->dst.bytes + far1->src.bytes) < far2->dst.bytes)) RaSendArgusRecord(store); if ((a1->ahdr.status & 0xFFFF) == ETHERTYPE_IP) { if (far1->attr_ip.sttl != far2->attr_ip.dttl) far2->attr_ip.dttl = 0xFF; if (far1->attr_ip.dttl != far2->attr_ip.sttl) far2->attr_ip.sttl = 0xFF; if (far1->attr_ip.stos != far2->attr_ip.dtos) far2->attr_ip.dtos = 0xFF; if (far1->attr_ip.dtos != far2->attr_ip.stos) far2->attr_ip.stos = 0xFF; } far2->src.count += far1->dst.count; far2->src.bytes += far1->dst.bytes; far2->dst.count += far1->src.count; far2->dst.bytes += far1->src.bytes; far2->src.appbytes += far1->dst.appbytes; far2->dst.appbytes += far1->src.appbytes; } diffstartime = (far1->time.start.tv_sec - data->agr.laststartime.tv_sec); if ((diffusec = (far1->time.start.tv_usec - data->agr.laststartime.tv_usec)) < 0) { diffstartime--; diffusec += 1000000; } data->agr.laststartime = far1->time.start; if (diffstartime > 0) { if (diffstartime > 2147) { if (data->agr.status & ARGUS_AGR_USECIDLETIME) { if (data->agr.idle.minval != 0x7FFFFFFF) data->agr.idle.minval /= 1000; data->agr.idle.maxval /= 1000; data->idle.sumtime /= 1000; data->idle.sumsqrd /= 1000000.0; data->agr.status &= ~ARGUS_AGR_USECIDLETIME; data->agr.status |= ARGUS_AGR_MSECIDLETIME; } } if (data->agr.status & ARGUS_AGR_USECIDLETIME) TimeMultiplier = 1000000; else TimeMultiplier = 1000; diffstartime *= TimeMultiplier; diffstartime += (diffusec * 1000) / (TimeMultiplier / 1000); if ((data->agr.idle.minval > diffstartime) && (diffstartime > 0)) data->agr.idle.minval = diffstartime; if ((data->agr.idle.maxval < diffstartime) && (diffstartime > 0)) data->agr.idle.maxval = diffstartime; data->idle.sumtime += diffstartime; data->idle.sumsqrd += pow(diffstartime, 2.0); data->idle.n++; } duration = RaGetuSecDuration(a1); if (duration > 0x6FFFFFFF) { if (data->agr.status & ARGUS_AGR_USECIDLETIME) { if (data->agr.idle.minval != 0x7FFFFFFF) data->agr.act.minval /= 1000; data->agr.act.maxval /= 1000; data->act.sumtime /= 1000; data->act.sumsqrd /= 1000000.0; data->agr.status &= ~ARGUS_AGR_USECACTTIME; data->agr.status |= ARGUS_AGR_MSECACTTIME; } } if (data->agr.status & ARGUS_AGR_USECACTTIME) TimeMultiplier = 1; else TimeMultiplier = 1000; duration /= TimeMultiplier; if ((data->agr.act.minval > duration) && (duration > 0)) data->agr.act.minval = duration; if ((data->agr.act.maxval < duration) && (duration > 0)) data->agr.act.maxval = duration; data->act.sumtime += duration; data->act.sumsqrd += pow(duration, 2.0); data->act.n++; if (((a1->ahdr.status & 0xFFFF) == ETHERTYPE_IP) && (far2->flow.ip_flow.ip_p == IPPROTO_TCP)) { struct ArgusTCPObject *tcp1 = (struct ArgusTCPObject *) a1farhdr[ARGUS_TCP_DSR_INDEX]; if (tcp1 && ((tcp1->state & (ARGUS_FIN | ARGUS_FIN_ACK | ARGUS_NORMAL_CLOSE | ARGUS_RESET)) > 0)) { if (!((tcp1->state & ARGUS_RESET) && (!(far1->dst.count && far1->src.count)))) data->agr.count++; } } else data->agr.count++; if ((agr = (struct ArgusAGRStruct *) a2farhdr[ARGUS_AGR_DSR_INDEX]) == NULL) { } if (far1->ArgusTransRefNum != far2->ArgusTransRefNum) far2->ArgusTransRefNum = 0; if ((far2->time.start.tv_sec > far1->time.start.tv_sec) || ((far2->time.start.tv_sec == far1->time.start.tv_sec) && (far2->time.start.tv_usec > far1->time.start.tv_usec))) { far2->time.start = far1->time.start; if (RaThisFlowRev) rev++; } if ((far2->time.last.tv_sec < far1->time.last.tv_sec) || ((far2->time.last.tv_sec == far1->time.last.tv_sec) && (far2->time.last.tv_usec < far1->time.last.tv_usec))) far2->time.last = far1->time.last; if (store->qhdr.lasttime.tv_sec != far2->time.last.tv_sec) { store->qhdr.lasttime = far2->time.last; data->agr.lasttime = far2->time.last; } else if (store->qhdr.lasttime.tv_usec < far2->time.last.tv_usec) { store->qhdr.lasttime = far2->time.last; } } break; #define TCP_FIN_STATE_TIME 360 case ARGUS_TCP_DSR_INDEX: { struct ArgusTCPObject *tcp1 = (struct ArgusTCPObject *) a1farhdr[i]; struct ArgusTCPObject *tcp2 = (struct ArgusTCPObject *) a2farhdr[i]; if ((tcp1->state & ARGUS_SAW_SYN) && (!(tcp2->state & ARGUS_SAW_SYN))) if (RaThisFlowRev) rev++; if (RaCumulativeMerge) tcp2->state |= tcp1->state; else tcp2->state = tcp1->state; if (!(tcp2->synAckuSecs)) tcp2->synAckuSecs = tcp1->synAckuSecs; else if (tcp2->synAckuSecs > tcp1->synAckuSecs) if (tcp1->synAckuSecs) tcp2->synAckuSecs = tcp1->synAckuSecs; if (!(tcp2->ackDatauSecs)) tcp2->ackDatauSecs = tcp1->ackDatauSecs; else if (tcp2->ackDatauSecs > tcp1->ackDatauSecs) if (tcp1->ackDatauSecs) tcp2->ackDatauSecs = tcp1->ackDatauSecs; tcp2->src.seqbase = 0; tcp2->dst.seqbase = 0; if (!(RaThisFlowRev)) { tcp2->src.ackbytes += tcp1->src.ackbytes; tcp2->dst.ackbytes += tcp1->dst.ackbytes; tcp2->src.bytes += tcp1->src.bytes; tcp2->dst.bytes += tcp1->dst.bytes; tcp2->src.rpkts += tcp1->src.rpkts; tcp2->dst.rpkts += tcp1->dst.rpkts; if (tcp2->src.win > tcp1->src.win); tcp2->src.win = tcp1->src.win; if (tcp2->dst.win > tcp1->dst.win); tcp2->dst.win = tcp1->dst.win; tcp2->src.flags |= tcp1->src.flags; tcp2->dst.flags |= tcp1->dst.flags; } else { tcp2->src.ackbytes += tcp1->dst.ackbytes; tcp2->dst.ackbytes += tcp1->src.ackbytes; tcp2->src.bytes += tcp1->dst.bytes; tcp2->dst.bytes += tcp1->src.bytes; tcp2->src.rpkts += tcp1->dst.rpkts; tcp2->dst.rpkts += tcp1->src.rpkts; if (tcp2->src.win > tcp1->dst.win); tcp2->src.win = tcp1->dst.win; if (tcp2->dst.win > tcp1->src.win); tcp2->dst.win = tcp1->src.win; tcp2->src.flags |= tcp1->dst.flags; tcp2->dst.flags |= tcp1->src.flags; } } break; case ARGUS_RTP_DSR_INDEX: { struct ArgusRTPObject *rtp1 = (struct ArgusRTPObject *) a1farhdr[i]; struct ArgusRTPObject *rtp2 = (struct ArgusRTPObject *) a2farhdr[i]; if (rtp1 && rtp2) { if (!(RaThisFlowRev)) { if ((((rtp2->sdrop + rtp1->sdrop) < rtp2->sdrop) || ((rtp2->ddrop + rtp1->ddrop) < rtp2->ddrop)) || (((rtp2->ssdev + rtp1->ssdev) < rtp2->ssdev) || ((rtp2->dsdev + rtp1->dsdev) < rtp2->dsdev))) { RaSendArgusRecord(store); rtp2->sdrop = rtp1->sdrop; rtp2->ddrop = rtp1->ddrop; rtp2->ssdev = rtp1->ssdev; rtp2->dsdev = rtp1->dsdev; } else { rtp2->sdrop += rtp1->sdrop; rtp2->ddrop += rtp1->ddrop; rtp2->ssdev += rtp1->ssdev; rtp2->dsdev += rtp1->dsdev; } } else { if ((((rtp2->ddrop + rtp1->sdrop) < rtp2->ddrop) || ((rtp2->sdrop + rtp1->ddrop) < rtp2->sdrop)) || (((rtp2->dsdev + rtp1->ssdev) < rtp2->dsdev) || ((rtp2->ssdev + rtp1->dsdev) < rtp2->ssdev))) { RaSendArgusRecord(store); rtp2->sdrop = rtp1->ddrop; rtp2->ddrop = rtp1->sdrop; rtp2->ssdev = rtp1->dsdev; rtp2->dsdev = rtp1->ssdev; } else { rtp2->sdrop += rtp1->ddrop; rtp2->ddrop += rtp1->sdrop; rtp2->ssdev += rtp1->dsdev; rtp2->dsdev += rtp1->ssdev; } } } } break; case ARGUS_ICMP_DSR_INDEX: { struct ArgusICMPObject *icmp1 = (struct ArgusICMPObject *) a1farhdr[i]; struct ArgusICMPObject *icmp2 = (struct ArgusICMPObject *) a2farhdr[i]; if (icmp1->icmp_type != icmp2->icmp_type) { switch (icmp2->icmp_type) { case ICMP_MASKREQ: case ICMP_ECHO: case ICMP_TSTAMP: case ICMP_IREQ: break; case ICMP_MASKREPLY: if (icmp1->icmp_type == ICMP_MASKREQ) { icmp2->icmp_type = ICMP_MASKREQ; rev++; } break; case ICMP_ECHOREPLY: if (icmp1->icmp_type == ICMP_ECHO) { icmp2->icmp_type = ICMP_ECHO; rev++; } break; case ICMP_TSTAMPREPLY: if (icmp1->icmp_type == ICMP_TSTAMP) { icmp2->icmp_type = ICMP_TSTAMP; rev++; } break; case ICMP_IREQREPLY: if (icmp1->icmp_type == ICMP_IREQ) { icmp2->icmp_type = ICMP_IREQ; rev++; } break; } } } case ARGUS_ARP_DSR_INDEX: case ARGUS_FRG_DSR_INDEX: break; case ARGUS_VLAN_DSR_INDEX: { struct ArgusVlanStruct *vlan1 = (struct ArgusVlanStruct *) a1farhdr[i]; struct ArgusVlanStruct *vlan2 = (struct ArgusVlanStruct *) a2farhdr[i]; if (vlan1 && vlan2) { if ((vlan2->status & ARGUS_SRC_VLAN) && (vlan1->status & ARGUS_SRC_VLAN)) if (vlan2->sid != vlan1->sid) vlan2->status |= ARGUS_SRC_CHANGED; if ((vlan2->status & ARGUS_DST_VLAN) && (vlan1->status & ARGUS_DST_VLAN)) if (vlan2->did != vlan1->did) vlan2->status |= ARGUS_DST_CHANGED; vlan2->status |= vlan1->status; vlan2->sid = vlan1->sid; vlan2->did = vlan1->did; } } break; case ARGUS_MPLS_DSR_INDEX: { struct ArgusMplsStruct *mpls1 = (struct ArgusMplsStruct *) a1farhdr[i]; struct ArgusMplsStruct *mpls2 = (struct ArgusMplsStruct *) a2farhdr[i]; if (mpls1 && mpls2) { if (!(RaThisFlowRev)) { if ((mpls2->status & ARGUS_SRC_MPLS) && (mpls1->status & ARGUS_SRC_MPLS)) if (mpls2->slabel != mpls1->slabel) mpls2->status |= ARGUS_SRC_CHANGED; if ((mpls2->status & ARGUS_DST_MPLS) && (mpls1->status & ARGUS_DST_MPLS)) if (mpls2->dlabel != mpls1->dlabel) mpls2->status |= ARGUS_DST_CHANGED; mpls2->status |= mpls1->status; mpls2->slabel = mpls1->slabel; mpls2->dlabel = mpls1->dlabel; } else { if ((mpls2->status & ARGUS_SRC_MPLS) && (mpls1->status & ARGUS_SRC_MPLS)) if (mpls2->slabel != mpls1->dlabel) mpls2->status |= ARGUS_SRC_CHANGED; if ((mpls2->status & ARGUS_DST_MPLS) && (mpls1->status & ARGUS_DST_MPLS)) if (mpls2->dlabel != mpls1->slabel) mpls2->status |= ARGUS_DST_CHANGED; mpls2->status |= mpls1->status; mpls2->slabel = mpls1->dlabel; mpls2->dlabel = mpls1->slabel; } } } break; case ARGUS_ESP_DSR_INDEX: { struct ArgusESPStruct *esp1 = (struct ArgusESPStruct *) a1farhdr[i]; struct ArgusESPStruct *esp2 = (struct ArgusESPStruct *) a2farhdr[i]; if (esp1 && esp2) { if (!(RaThisFlowRev)) { if (esp1->src.spi != esp2->src.spi) esp2->src.spi = 0; if (esp1->dst.spi != esp2->dst.spi) esp2->dst.spi = 0; esp2->src.lastseq = esp1->src.lastseq; esp2->dst.lastseq = esp1->dst.lastseq; esp2->src.lostseq = esp1->src.lostseq; esp2->dst.lostseq = esp1->dst.lostseq; } else { if (esp1->src.spi != esp2->dst.spi) esp2->dst.spi = 0; if (esp1->dst.spi != esp2->src.spi) esp2->src.spi = 0; esp2->src.lastseq = esp1->dst.lastseq; esp2->dst.lastseq = esp1->src.lastseq; esp2->src.lostseq = esp1->dst.lostseq; esp2->dst.lostseq = esp1->src.lostseq; } } } break; case ARGUS_TIME_DSR_INDEX: { struct ArgusTimeStruct *time1 = (struct ArgusTimeStruct *) a1farhdr[i]; struct ArgusTimeStruct *time2 = (struct ArgusTimeStruct *) a2farhdr[i]; long long sumtime, sumtime1, sumtime2; double sumsqrd, sumsqrd1, sumsqrd2; if (time1 && time2) { if (!(RaThisFlowRev)) { if (time1->src.act.n > 0) { sumtime1 = (time1->src.act.meanval * time1->src.act.n); sumtime2 = (time2->src.act.meanval * time2->src.act.n); if ((sumtime = (sumtime1 + sumtime2)) < sumtime1) goto doneRaMergeArgus; if (time1->src.act.n) sumsqrd1 = (time1->src.act.n * pow(time1->src.act.stdev, 2.0)) + pow(sumtime1, 2.0)/time1->src.act.n; else sumsqrd1 = 0; if (time2->src.act.n) sumsqrd2 = (time2->src.act.n * pow(time2->src.act.stdev, 2.0)) + pow(sumtime2, 2.0)/time2->src.act.n; else sumsqrd2 = 0; time2->src.act.n += time1->src.act.n; time2->src.act.meanval = sumtime/time2->src.act.n; if ((sumsqrd = sumsqrd1 + sumsqrd2) < sumsqrd1) goto doneRaMergeArgus; time2->src.act.stdev = sqrt (sumsqrd/time2->src.act.n - pow (sumtime/time2->src.act.n, 2.0)); if (time2->src.act.maxval < time1->src.act.maxval) time2->src.act.maxval = time1->src.act.maxval; if (time2->src.act.minval > time1->src.act.minval) time2->src.act.minval = time1->src.act.minval; } if (time1->dst.act.n > 0) { sumtime1 = (time1->dst.act.meanval * time1->dst.act.n); sumtime2 = (time2->dst.act.meanval * time2->dst.act.n); if ((sumtime = sumtime1 + sumtime2) < sumtime1) goto doneRaMergeArgus; if (time1->dst.act.n) sumsqrd1 = (time1->dst.act.n * pow(time1->dst.act.stdev, 2.0)) + pow(sumtime1, 2.0)/time1->dst.act.n; else sumsqrd1 = 0; sumsqrd2 = (time2->dst.act.n * pow(time2->dst.act.stdev, 2.0)) + pow(sumtime2, 2.0)/time2->dst.act.n; if ((sumsqrd = sumsqrd1 + sumsqrd2) < sumsqrd1) goto doneRaMergeArgus; time2->dst.act.n += time1->dst.act.n; time2->dst.act.meanval = sumtime/time2->dst.act.n; time2->dst.act.stdev = sqrt (sumsqrd/time2->dst.act.n - pow (sumtime/time2->dst.act.n, 2.0)); if (time2->dst.act.maxval < time1->dst.act.maxval) time2->dst.act.maxval = time1->dst.act.maxval; if (time2->dst.act.minval > time1->dst.act.minval) time2->dst.act.minval = time1->dst.act.minval; } if (time1->src.idle.n > 0) { sumtime1 = (time1->src.idle.meanval * time1->src.idle.n); sumtime2 = (time2->src.idle.meanval * time2->src.idle.n); if ((sumtime = sumtime1 + sumtime2) < sumtime1) goto doneRaMergeArgus; time2->src.idle.n += time1->src.idle.n; time2->src.idle.meanval = sumtime/time2->src.idle.n; if (time1->src.idle.n) sumsqrd1 = (time1->src.idle.n * pow(time1->src.idle.stdev, 2.0)) + pow(sumtime1, 2.0)/time1->src.idle.n; else sumsqrd1 = 0; sumsqrd2 = (time2->src.idle.n * pow(time2->src.idle.stdev, 2.0)) + pow(sumtime2, 2.0)/time2->src.idle.n; if ((sumsqrd = sumsqrd1 + sumsqrd2) < sumsqrd1) goto doneRaMergeArgus; time2->src.idle.stdev = sqrt (sumsqrd/time2->src.idle.n - pow (sumtime/time2->src.idle.n, 2.0)); if (time2->src.idle.maxval < time1->src.idle.maxval) time2->src.idle.maxval = time1->src.idle.maxval; if (time2->src.idle.minval > time1->src.idle.minval) time2->src.idle.minval = time1->src.idle.minval; } if (time1->dst.idle.n > 0) { sumtime1 = (time1->dst.idle.meanval * time1->dst.idle.n); sumtime2 = (time2->dst.idle.meanval * time2->dst.idle.n); if ((sumtime = sumtime1 + sumtime2) < sumtime1) goto doneRaMergeArgus; time2->dst.idle.n += time1->dst.idle.n; time2->dst.idle.meanval = sumtime/time2->dst.idle.n; if (time1->dst.idle.n) sumsqrd1 = (time1->dst.idle.n * pow(time1->dst.idle.stdev, 2.0)) + pow(sumtime1, 2.0)/time1->dst.idle.n; else sumsqrd1 = 0; sumsqrd2 = (time2->dst.idle.n * pow(time2->dst.idle.stdev, 2.0)) + pow(sumtime2, 2.0)/time2->dst.idle.n; if ((sumsqrd = sumsqrd1 + sumsqrd2) < sumsqrd1) goto doneRaMergeArgus; time2->dst.idle.stdev = sqrt (sumsqrd/time2->dst.idle.n - pow (sumtime/time2->dst.idle.n, 2.0)); if (time2->dst.idle.maxval < time1->dst.idle.maxval) time2->dst.idle.maxval = time1->dst.idle.maxval; if (time2->dst.idle.minval > time1->dst.idle.minval) time2->dst.idle.minval = time1->dst.idle.minval; } } else { if (time1->src.act.n > 0) { sumtime1 = (time1->src.act.meanval * time1->src.act.n); sumtime2 = (time2->dst.act.meanval * time2->dst.act.n); if ((sumtime = (sumtime1 + sumtime2)) < sumtime1) goto doneRaMergeArgus; if (time1->src.act.n) sumsqrd1 = (time1->src.act.n * pow(time1->src.act.stdev, 2.0)) + pow(sumtime1, 2.0)/time1->src.act.n; else sumsqrd1 = 0; if (time2->dst.act.n) sumsqrd2 = (time2->dst.act.n * pow(time2->dst.act.stdev, 2.0)) + pow(sumtime2, 2.0)/time2->dst.act.n; else sumsqrd2 = 0; time2->dst.act.n += time1->src.act.n; time2->dst.act.meanval = sumtime/time2->dst.act.n; if ((sumsqrd = sumsqrd1 + sumsqrd2) < sumsqrd1) goto doneRaMergeArgus; time2->dst.act.stdev = sqrt (sumsqrd/time2->dst.act.n - pow (sumtime/time2->dst.act.n, 2.0)); if (time2->dst.act.maxval < time1->src.act.maxval) time2->dst.act.maxval = time1->src.act.maxval; if (time2->dst.act.minval > time1->src.act.minval) time2->dst.act.minval = time1->src.act.minval; } if (time1->dst.act.n > 0) { sumtime1 = (time1->dst.act.meanval * time1->dst.act.n); sumtime2 = (time2->src.act.meanval * time2->src.act.n); if ((sumtime = sumtime1 + sumtime2) < sumtime1) goto doneRaMergeArgus; if (time1->dst.act.n) sumsqrd1 = (time1->dst.act.n * pow(time1->dst.act.stdev, 2.0)) + pow(sumtime1, 2.0)/time1->dst.act.n; else sumsqrd1 = 0; sumsqrd2 = (time2->src.act.n * pow(time2->src.act.stdev, 2.0)) + pow(sumtime2, 2.0)/time2->src.act.n; if ((sumsqrd = sumsqrd1 + sumsqrd2) < sumsqrd1) goto doneRaMergeArgus; time2->src.act.n += time1->dst.act.n; time2->src.act.meanval = sumtime/time2->src.act.n; time2->src.act.stdev = sqrt (sumsqrd/time2->src.act.n - pow (sumtime/time2->src.act.n, 2.0)); if (time2->src.act.maxval < time1->dst.act.maxval) time2->src.act.maxval = time1->dst.act.maxval; if (time2->src.act.minval > time1->dst.act.minval) time2->src.act.minval = time1->dst.act.minval; } if (time1->src.idle.n > 0) { sumtime1 = (time1->src.idle.meanval * time1->src.idle.n); sumtime2 = (time2->dst.idle.meanval * time2->dst.idle.n); if ((sumtime = sumtime1 + sumtime2) < sumtime1) goto doneRaMergeArgus; time2->dst.idle.n += time1->src.idle.n; time2->dst.idle.meanval = sumtime/time2->dst.idle.n; if (time1->src.idle.n) sumsqrd1 = (time1->src.idle.n * pow(time1->src.idle.stdev, 2.0)) + pow(sumtime1, 2.0)/time1->src.idle.n; else sumsqrd1 = 0; sumsqrd2 = (time2->dst.idle.n * pow(time2->dst.idle.stdev, 2.0)) + pow(sumtime2, 2.0)/time2->dst.idle.n; if ((sumsqrd = sumsqrd1 + sumsqrd2) < sumsqrd1) goto doneRaMergeArgus; time2->dst.idle.stdev = sqrt (sumsqrd/time2->dst.idle.n - pow (sumtime/time2->dst.idle.n, 2.0)); if (time2->dst.idle.maxval < time1->src.idle.maxval) time2->dst.idle.maxval = time1->src.idle.maxval; if (time2->dst.idle.minval > time1->src.idle.minval) time2->dst.idle.minval = time1->src.idle.minval; } if (time1->dst.idle.n > 0) { sumtime1 = (time1->dst.idle.meanval * time1->dst.idle.n); sumtime2 = (time2->src.idle.meanval * time2->src.idle.n); if ((sumtime = sumtime1 + sumtime2) < sumtime1) goto doneRaMergeArgus; time2->src.idle.n += time1->dst.idle.n; time2->src.idle.meanval = sumtime/time2->src.idle.n; if (time1->dst.idle.n) sumsqrd1 = (time1->dst.idle.n * pow(time1->dst.idle.stdev, 2.0)) + pow(sumtime1, 2.0)/time1->dst.idle.n; else sumsqrd1 = 0; sumsqrd2 = (time2->src.idle.n * pow(time2->src.idle.stdev, 2.0)) + pow(sumtime2, 2.0)/time2->src.idle.n; if ((sumsqrd = sumsqrd1 + sumsqrd2) < sumsqrd1) goto doneRaMergeArgus; time2->src.idle.stdev = sqrt (sumsqrd/time2->src.idle.n - pow (sumtime/time2->src.idle.n, 2.0)); if (time2->src.idle.maxval < time1->dst.idle.maxval) time2->src.idle.maxval = time1->dst.idle.maxval; if (time2->src.idle.minval > time1->dst.idle.minval) time2->src.idle.minval = time1->dst.idle.minval; } } } } break; case ARGUS_SRCUSRDATA_DSR_INDEX: case ARGUS_DSTUSRDATA_DSR_INDEX: { struct ArgusUserStruct *user1 = (struct ArgusUserStruct *) a1farhdr[i]; struct ArgusUserStruct *user2 = (struct ArgusUserStruct *) a2farhdr[i]; int len, len1 = 0, len2 = 0, x; unsigned short newstatus = 0; if (user1 && user2) { len1 = (user1->length - 1) * 4; len2 = (user2->length - 1) * 4; len = (len1 > len2) ? len2 : len1; len = (len > 16) ? 16 : len; for (x = 0; x < len; x++) if ((&user2->data)[x] != (&user1->data)[x]) ((char *)&newstatus)[x/8] |= (0x80 >> (x % 8)); user2->status = newstatus; } } break; case ARGUS_AGR_DSR_INDEX: { struct ArgusAGRStruct *agr1 = (struct ArgusAGRStruct *) a1farhdr[i]; unsigned int agr1sumtime, sumtime; double agr1sumsqrd, sumsqrd; int overlapping = 1; long long newvalue = 0; if (!((data->agr.status & ARGUS_AGR_USECACTTIME) && (agr1->status & ARGUS_AGR_USECACTTIME))) { if (data->agr.status & ARGUS_AGR_USECACTTIME) { data->agr.act.maxval /= 1000; data->agr.act.minval /= 1000; data->agr.act.meanval /= 1000; data->agr.act.stdev /= 1000; data->act.sumtime /= 1000; data->act.sumsqrd /= 1000000.0; data->agr.status &= ~ARGUS_AGR_USECACTTIME; data->agr.status |= ARGUS_AGR_MSECACTTIME; } if (agr1->status & ARGUS_AGR_USECACTTIME) { agr1->act.maxval /= 1000; agr1->act.minval /= 1000; agr1->act.meanval /= 1000; agr1->act.stdev /= 1000; agr1->status &= ~ARGUS_AGR_USECACTTIME; agr1->status |= ARGUS_AGR_MSECACTTIME; } } if (data->agr.act.minval > agr1->act.minval) data->agr.act.minval = agr1->act.minval; if (data->agr.act.maxval < agr1->act.maxval) data->agr.act.maxval = agr1->act.maxval; if (agr1->act.n) { agr1sumtime = agr1->act.meanval * agr1->act.n; agr1sumsqrd = (agr1->act.n * pow(agr1->act.stdev, 2.0)) + pow(agr1sumtime, 2.0)/agr1->act.n; data->act.sumtime += agr1sumtime; data->act.sumsqrd += agr1sumsqrd; sumtime = data->act.sumtime; sumsqrd = data->act.sumsqrd; data->agr.act.n += agr1->act.n; data->act.n += agr1->act.n; data->agr.act.meanval = sumtime/data->act.n; data->agr.act.stdev = sqrt (sumsqrd/data->act.n - pow (sumtime/data->act.n, 2.0)); } if (!((data->agr.status & ARGUS_AGR_USECIDLETIME) && (agr1->status & ARGUS_AGR_USECIDLETIME))) { if (data->agr.status & ARGUS_AGR_USECIDLETIME) { data->agr.idle.maxval /= 1000; data->agr.idle.minval /= 1000; data->agr.idle.meanval /= 1000; data->agr.idle.stdev /= 1000; data->idle.sumtime /= 1000; data->idle.sumsqrd /= 1000000.0; data->agr.status &= ~ARGUS_AGR_USECIDLETIME; data->agr.status |= ARGUS_AGR_MSECIDLETIME; } if (agr1->status & ARGUS_AGR_USECIDLETIME) { agr1->idle.maxval /= 1000; agr1->idle.minval /= 1000; agr1->idle.meanval /= 1000; agr1->idle.stdev /= 1000; agr1->status &= ~ARGUS_AGR_USECIDLETIME; agr1->status |= ARGUS_AGR_MSECIDLETIME; } } if (data->agr.status & ARGUS_AGR_USECIDLETIME) TimeMultiplier = 1; else TimeMultiplier = 1000; overlapping = 1; if ((a2->argus_far.time.start.tv_sec < a1->argus_far.time.start.tv_sec) || ((a2->argus_far.time.start.tv_sec == a1->argus_far.time.start.tv_sec) && (a2->argus_far.time.start.tv_usec < a1->argus_far.time.start.tv_usec))) { if ((a2->argus_far.time.last.tv_sec < a1->argus_far.time.start.tv_sec) || ((a2->argus_far.time.last.tv_sec == a1->argus_far.time.start.tv_sec) && (a2->argus_far.time.last.tv_usec < a1->argus_far.time.start.tv_usec))) { newvalue = (((agr1->laststartime.tv_sec - data->agr.laststartime.tv_sec) * 1000000) + (agr1->laststartime.tv_usec - data->agr.laststartime.tv_usec))/TimeMultiplier; overlapping = 0; } } else { if ((a1->argus_far.time.last.tv_sec < a2->argus_far.time.start.tv_sec) || ((a1->argus_far.time.last.tv_sec == a2->argus_far.time.start.tv_sec) && (a1->argus_far.time.last.tv_usec < a2->argus_far.time.start.tv_usec))) { newvalue = (((data->agr.laststartime.tv_sec - agr1->laststartime.tv_sec) * 1000000) + (data->agr.laststartime.tv_usec - agr1->laststartime.tv_usec))/TimeMultiplier; overlapping = 0; } } if (!(overlapping)) { sumtime = (agr1->idle.meanval * agr1->idle.n) + newvalue; sumsqrd = ((agr1->idle.n * pow(agr1->idle.stdev, 2.0)) + pow(sumtime, 2.0)/agr1->idle.n) + pow(newvalue, 2.0); data->idle.sumtime += sumtime; data->idle.sumsqrd += sumsqrd; data->idle.n += agr1->idle.n + 1; if (newvalue) { if (newvalue > data->agr.idle.maxval) data->agr.idle.maxval = newvalue; else if (newvalue < data->agr.idle.minval) data->agr.idle.minval = newvalue; } data->agr.count += agr1->count; } else { if (data->agr.idle.minval >= agr1->idle.minval) { data->idle.sumtime += agr1->idle.minval; data->idle.sumsqrd += pow(agr1->idle.minval, 2.0); data->idle.n++; data->agr.idle.minval = agr1->idle.minval; } } if ((data->agr.laststartime.tv_sec > agr1->laststartime.tv_sec) || ((data->agr.laststartime.tv_sec == agr1->laststartime.tv_sec) && (data->agr.laststartime.tv_usec > agr1->laststartime.tv_usec))) { data->agr.laststartime = agr1->laststartime; } if ((data->agr.lasttime.tv_sec < agr1->lasttime.tv_sec) || ((data->agr.lasttime.tv_sec == agr1->lasttime.tv_sec) && (data->agr.lasttime.tv_usec < agr1->lasttime.tv_usec))) { store->qhdr.lasttime = agr1->lasttime; data->agr.lasttime = agr1->lasttime; } } break; } } else { /* int datalen = 0; switch (i) { case ARGUS_SRCUSRDATA_DSR_INDEX: datalen = (ArgusSrcUserDataLen + 3)/ 4; case ARGUS_DSTUSRDATA_DSR_INDEX: { struct ArgusUserStruct *user1 = (struct ArgusUserStruct *) a1farhdr[i]; struct ArgusUserStruct *user2 = (struct ArgusUserStruct *) a2farhdr[i]; datalen = (ArgusDstUserDataLen + 3)/ 4; if (user1 && (user2 == NULL)) { datalen = (datalen > (user1->length)) ? datalen : (user1->length); user1->length = datalen + 1; bcopy ((char *) user1, &buf[tmp->ahdr.length], user1->length*4); tmp->ahdr.length += (user1->length * 4); } break; } } */ } status >>= 1; } if (rev) { ArgusReverseRecord (tmp); if (store->rahtblhdr != NULL) { struct RaHashTableStruct *htable; if ((htable = store->rahtblhdr->htable) != NULL) { RaRemoveHashEntry (htable, store->rahtblhdr); RaFindArgusRecord(htable, tmp); if ((store->rahtblhdr = RaAddHashEntry (&RaHashTable, store)) == NULL) ArgusLog (LOG_ERR, "RaMergeArgusRecord: RaAddHashEntry: %s", strerror(errno)); } } } ArgusFree(data->argus); data->argus = RaCopyArgusRecord(tmp); data->status |= RA_MODIFIED; data->argus->ahdr.status |= ARGUS_MERGED; data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); if (Rflag) { switch (far2->flow.ip_flow.ip_p) { case IPPROTO_UDP: case IPPROTO_ICMP: break; } } #ifdef ARGUSDEBUG ArgusDebug (5, "RaMergeArgusRecord: merged\n"); #endif return; } else { if (RaThisFlowRev) ArgusReverseRecord(a1); data->argus = RaCopyArgusRecord(a1); data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); #ifdef ARGUSDEBUG ArgusDebug (5, "RaMergeArgusRecord: swapped"); #endif return; } doneRaMergeArgus: RaSendArgusRecord(store); ArgusFree(data->argus); if (RaThisFlowRev) ArgusReverseRecord(a1); data->argus = RaCopyArgusRecord(a1); bcopy ((char *)&RaArgusFlow->ip_flow, (char *)&data->flow.ip_flow, sizeof(RaArgusFlow->ip_flow)); data->status &= ~((ARGUS_FAR_SRCADDR_MODIFIED | ARGUS_FAR_DSTADDR_MODIFIED) | (ARGUS_FAR_DSTPORT_MODIFIED | ARGUS_FAR_DSTPORT_MODIFIED) | (ARGUS_FAR_PROTO_MODIFIED | ARGUS_FAR_TPVAL_MODIFIED)); data->status |= RA_MODIFIED; data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); #ifdef ARGUSDEBUG ArgusDebug (5, "RaMergeArgusRecord: dumped and swapped"); #endif } void RaUpdateArgusStore(struct ArgusRecord *argus, struct ArgusRecordStore *store) { store->status |= RA_MODIFIED; store->qhdr.lasttime = ArgusGlobalTime; #ifdef ARGUSDEBUG ArgusDebug (6, "RaUpdateArgusStore: \n"); #endif } int RaTimeoutArgusStore (struct ArgusRecordStore *store) { struct ArgusRecord *argus; int i, retn = 0; if (store != NULL) { if (store->status & RA_MODIFIED) retn = RaSendArgusRecord(store); if (store->rahtblhdr) RaRemoveHashEntry (store->rahtblhdr->htable, store->rahtblhdr); for (i = 0; i < RaHistoTimeSeries + 1; i++) { struct ArgusRecordData *data = NULL; if ((data = store->data[i]) != NULL) { if ((argus = data->argus) != NULL) { RaRemoveArgusRecord(argus); ArgusFree (argus); data->argus = NULL; } ArgusFree(data); store->data[i] = NULL; } } if (store->queue != NULL) RaDeleteQueue(store->queue); ArgusFree (store->data); ArgusFree (store); RaAllocArgusRecordStore--; } #ifdef ARGUSDEBUG ArgusDebug (6, "RaTimeoutArgusStore: 0x%x returning %d\n", store, retn); #endif return (retn); } int RaCheckTimeout (struct ArgusRecordStore *store, struct ArgusRecord *argus) { int retn = 0, lapseTime; struct ArgusRecordData *data = NULL; struct ArgusRecord *sargus = NULL; struct timeval *tvp = &ArgusGlobalTime; int lapseTimeSecs, lapseTimeuSecs; int starTimeSecs, starTimeuSecs; int lastTimeSecs, lastTimeuSecs; if (store->ArgusTimeout > 0) { lapseTime = store->qhdr.logtime.tv_sec + store->ArgusTimeout; if ((tvp->tv_sec > lapseTime) || ((tvp->tv_sec == lapseTime) && (tvp->tv_usec > store->qhdr.logtime.tv_usec))) { RaSendArgusRecord(store); } else { if (argus != NULL) { if ((data = store->data[0]) != NULL) { sargus = data->argus; starTimeSecs = sargus->argus_far.time.start.tv_sec; starTimeuSecs = sargus->argus_far.time.start.tv_usec; if (argus->argus_far.time.last.tv_sec > sargus->argus_far.time.last.tv_sec) { lastTimeSecs = argus->argus_far.time.last.tv_sec; lastTimeuSecs = argus->argus_far.time.last.tv_usec; } else { lastTimeSecs = sargus->argus_far.time.last.tv_sec; if (argus->argus_far.time.last.tv_sec == sargus->argus_far.time.last.tv_sec) { if (argus->argus_far.time.last.tv_usec > sargus->argus_far.time.last.tv_usec) { lastTimeuSecs = argus->argus_far.time.last.tv_usec; } else lastTimeuSecs = sargus->argus_far.time.last.tv_usec; } else lastTimeuSecs = sargus->argus_far.time.last.tv_usec; } lapseTimeSecs = (lastTimeSecs - starTimeSecs); lapseTimeuSecs = (lastTimeuSecs - starTimeuSecs); if (lapseTimeuSecs < 0) { lapseTimeSecs--; lapseTimeuSecs += 1000000; } if (lapseTimeSecs >= store->ArgusTimeout) RaSendArgusRecord(store); } } } } if (store->ArgusIdleTimeout > 0) { if ((data = store->data[0]) != NULL) { sargus = data->argus; lastTimeSecs = sargus->argus_far.time.last.tv_sec; lastTimeuSecs = sargus->argus_far.time.last.tv_usec; lapseTimeSecs = (tvp->tv_sec - lastTimeSecs); lapseTimeuSecs = (tvp->tv_usec - lastTimeuSecs); if (lapseTimeSecs >= store->ArgusIdleTimeout) retn++; } } #ifdef ARGUSDEBUG ArgusDebug (6, "RaCheckTimeout: returning %d \n", retn); #endif return (retn); } #include #include #include int RaParseType (char *str) { return(argus_nametoeproto(str)); } struct RaCIDRAddr * RaParseCIDRAddr (char *str) { int error = 0, vlen, notIPAddr = 0, i; struct RaCIDRAddr *retn = NULL; char *ptr = NULL, chr = '\0'; unsigned int **alist; int maskIndex; RaCIDRPtr->type = RA_CIDR_TYPE; RaCIDRPtr->addr = 0; RaCIDRPtr->mask = 0xFFFFFFFF; if ((ptr = strchr(str, '*')) == NULL) { if ((strncasecmp (str, "class", 5)) != 0) { if ((ptr = strchr (str, ':')) != NULL) { chr = *ptr; *ptr++ = 0; } else { if ((ptr = strchr (str, '/')) != NULL) { chr = *ptr; *ptr++ = 0; } } for (i = 0; i < strlen(str); i++) if (!(isdigit((int)str[i]) || (str[i] == '.'))) notIPAddr++; if (!(notIPAddr)) { vlen = __argus_atoin(str, &RaCIDRPtr->addr); /* Promote short net number */ while (RaCIDRPtr->addr && (RaCIDRPtr->addr & 0xff000000) == 0) { RaCIDRPtr->addr <<= 8; RaCIDRPtr->mask <<= 8; } } else { if ((alist = argus_nametoaddr(str)) != NULL) { RaCIDRPtr->addr = **alist; } else error++; } if (ptr && (((chr == ':') || (chr == '/')) && isdigit((int) *ptr))) { maskIndex = atoi(ptr); if ((maskIndex) > 0) { RaCIDRPtr->mask = 0xFFFFFFFF; RaCIDRPtr->mask <<= (32 - maskIndex); } if (RaCIDRPtr->mask) RaCIDRPtr->addr &= RaCIDRPtr->mask; } } else { RaCIDRPtr->type = RA_NETCLASS_TYPE; } } if (!error) retn = RaCIDRPtr; #ifdef ARGUSDEBUG ArgusDebug (6, "RaParseCIDRAddr: returning 0x%x \n", retn); #endif return (retn); } int RaParseProtoField = 1; struct RaPolicyStruct * RaParsePolicyEntry (char *str) { struct RaPolicyStruct *retn = NULL; struct RaCIDRAddr *addr = NULL; int i, type, policyelements, error = 0; unsigned short prototype; char buf[MAXSTRLEN], *ptr = NULL, *tmp = buf; if (strncmp (str, RA_FLOWTAGSTR, strlen(RA_FLOWTAGSTR)) == 0) { type = RA_FLOWLIST; policyelements = RA_FLOWPOLICYFIELDNUM; } else { if ((strncmp (str, RA_MODELTAGSTR, strlen(RA_MODELTAGSTR))) == 0) { type = RA_MODELIST; policyelements = RA_MODELPOLICYFIELDNUM; } else return (NULL); } if ((retn = (struct RaPolicyStruct *) ArgusCalloc (1, sizeof (*retn))) == NULL) return retn; bzero (buf, MAXSTRLEN); bcopy ((char *) str, buf, strlen(str)); for (i = 0; ((i < policyelements) && !(error)); i++) { if ((ptr = strtok (tmp, " \t")) && (*ptr != '\n')) { switch (i) { case RA_LABELSTRING: switch (type) { case RA_FLOWLIST: if (strcmp (ptr, RA_FLOWTAGSTR)) error++; else retn->RaEntryType = RA_FLOWLIST; break; case RA_MODELIST: if (strcmp (ptr, RA_MODELTAGSTR)) error++; else retn->RaEntryType = RA_MODELIST; break; } break; case RA_POLICYID: if (!(retn->RaPolicyId = atoi (ptr))) error++; break; case RA_POLICYTYPE: if ((prototype = RaParseType (ptr)) != 0) retn->type = prototype & 0xFFFF; else error++; break; case RA_POLICYSRCADDR: if ((addr = RaParseCIDRAddr (ptr)) != NULL) retn->src = *addr; else error++; break; case RA_POLICYDSTADDR: if ((addr = RaParseCIDRAddr (ptr)) != NULL) retn->dst = *addr; else error++; break; case RA_POLICYPROTO: if (RaParseProtoField) { switch (type) { case RA_FLOWLIST: if (isdigit((int)*ptr)) { retn->proto = atoi(ptr); } else { if (*ptr == '*') { retn->proto = 0xFF; } else { struct protoent *proto; if ((proto = getprotobyname(ptr)) != NULL) retn->proto = proto->p_proto; else { error++; } } } break; case RA_MODELIST: if ((strstr(ptr, "yes")) != NULL) retn->proto = 0xFF; else if ((strstr(ptr, "no")) != NULL) retn->proto = 0x00; else error++; break; } } break; case RA_POLICYSRCPORT: switch (type) { case RA_FLOWLIST: if (isdigit((int)*ptr)) { retn->sport = (arg_uint16) atoi (ptr); } else { if (*ptr == '*') retn->sport = 0xFFFF; else { int proto = retn->proto, port = 0; if (retn->proto == IPPROTO_ICMP) { if (!(strcmp (ptr, "echo"))) retn->sport = ICMP_ECHO; else if (!(strcmp (ptr, "unreach"))) retn->sport = ICMP_UNREACH; else if (!(strcmp (ptr, "squench"))) retn->sport = ICMP_SOURCEQUENCH; else if (!(strcmp (ptr, "redirect"))) retn->sport = ICMP_REDIRECT; else if (!(strcmp (ptr, "timexed"))) retn->sport = ICMP_TIMXCEED; else if (!(strcmp (ptr, "param"))) retn->sport = ICMP_PARAMPROB; else if (!(strcmp (ptr, "timestmp"))) retn->sport = ICMP_TSTAMP; else if (!(strcmp (ptr, "info"))) retn->sport = ICMP_IREQ; else if (!(strcmp (ptr, "advert"))) retn->sport = ICMP_ROUTERADVERT; else if (!(strcmp (ptr, "solicit"))) retn->sport = ICMP_ROUTERSOLICIT; else error++; } else { if (argus_nametoport(ptr, &port, &proto)) { retn->sport = port; } else error++; } } } break; case RA_MODELIST: if ((strstr(ptr, "yes")) != NULL) retn->sport = 0xFFFF; else if ((strstr(ptr, "no")) != NULL) retn->sport = 0x0000; else error++; break; } break; case RA_POLICYDSTPORT: switch (type) { case RA_FLOWLIST: if (isdigit((int)*ptr)) { retn->dport = (arg_uint16) atoi (ptr); } else { if (*ptr == '*') retn->dport = 0xFFFF; else { if (retn->proto == IPPROTO_ICMP) { } else { int proto = retn->proto, port; if (argus_nametoport(ptr, &port, &proto)) { retn->dport = port; } else error++; } } } break; case RA_MODELIST: if ((strstr(ptr, "yes")) != NULL) retn->dport = 0xFFFF; else if ((strstr(ptr, "no")) != NULL) retn->dport = 0x0000; else error++; break; } break; case RA_POLICYMODELST: if (type == RA_FLOWLIST) { if (isdigit((int)*ptr)) retn->RaModelId = (arg_uint32) atoi (ptr); else error++; } break; case RA_POLICYTIMEOUT: if (type == RA_FLOWLIST) { if (isdigit((int)*ptr)) retn->ArgusTimeout = (arg_uint32) atoi (ptr); else error++; } case RA_POLICYIDLETIMEOUT: if (type == RA_FLOWLIST) { if (isdigit((int)*ptr)) retn->ArgusIdleTimeout = (arg_uint32) atoi (ptr); } break; } tmp = NULL; } else break; } if (error) { ArgusFree(retn); retn = NULL; } #ifdef ARGUSDEBUG ArgusDebug (6, "RaParsePolicyEntry: returning 0x%x \n", retn); #endif return (retn); } int RaCreatePolicyEntry (struct RaFlowModelStruct *fmodel, int index, char *str) { int retn = 0; struct RaPolicyStruct *rap; if (strncmp (str, RA_MODELNAMETAGSTR, strlen(RA_MODELNAMETAGSTR)) == 0) { fmodel->desc = strdup(&str[strlen(RA_MODELNAMETAGSTR)]); return retn; } if (strncmp (str, RA_PRESERVETAGSTR, strlen(RA_PRESERVETAGSTR)) == 0) { if (!(strncmp (&str[strlen(RA_PRESERVETAGSTR)], "yes", 3))) { fmodel->preserve = 1; } else RaPrintActualValues = 0; return retn; } if (strncmp (str, RA_REPORTTAGSTR, strlen(RA_REPORTTAGSTR)) == 0) { if (!(strncmp (&str[strlen(RA_REPORTTAGSTR)], "yes", 3))) fmodel->report = 1; return retn; } if (strncmp (str, RA_AUTOCORRECTSTR, strlen(RA_AUTOCORRECTSTR)) == 0) { if (!(strncmp (&str[strlen(RA_AUTOCORRECTSTR)], "yes", 3))) { fmodel->autocorrect = 1; } else { fmodel->autocorrect = 0; RaAutoCorrection = 0; } return retn; } if ((rap = RaParsePolicyEntry (str)) != NULL) { rap->str = str; switch (rap->RaEntryType) { case RA_FLOWLIST: fmodel->policy[fmodel->pindex++] = rap; break; case RA_MODELIST: fmodel->model[fmodel->mindex++] = rap; break; } } else ArgusLog (LOG_ERR, "RaCreatePolicyEntry: format error line %d %s", index, str); #ifdef ARGUSDEBUG ArgusDebug (6, "RaCreatePolicyEntry: returning %d\n", retn); #endif return (retn); } #include #include #include #define ARGUSMAXMODELFILE 2048 #define RAMAXPOLICYSIZE 2048 char *modelbuf[ARGUSMAXMODELFILE]; struct RaFlowModelStruct * RaReadFlowModelFile (char **model) { struct RaFlowModelStruct *retn = NULL; int RaPolicyLines = 0, RaPolicyLineNumber = 0; char strbuf[MAXSTRLEN], *str = strbuf; int i = 0, x = 0; FILE *fd; if (model == NULL) { bzero ((char *) modelbuf, sizeof(modelbuf)); if ((fd = fopen (ArgusFlowModelFile, "r")) != NULL) { while ((str = fgets (str, MAXSTRLEN, fd)) != NULL) modelbuf[i++] = strdup(str); model = modelbuf; } else ArgusLog (LOG_ERR, "%s: %s", ArgusFlowModelFile, strerror(errno)); } if ((retn = (struct RaFlowModelStruct *) ArgusCalloc (1, sizeof (*retn))) == NULL) ArgusLog (LOG_ERR, "RaReadFlowModelFile: ArgusCalloc %s", strerror(errno)); if ((retn->policy = (struct RaPolicyStruct **) ArgusCalloc (RAMAXPOLICYSIZE, sizeof (void *))) == NULL) ArgusLog (LOG_ERR, "RaReadFlowModelFile: ArgusCalloc %s", strerror(errno)); if ((retn->model = (struct RaPolicyStruct **) ArgusCalloc (RAMAXPOLICYSIZE, sizeof (void *))) == NULL) ArgusLog (LOG_ERR, "RaReadFlowModelFile: ArgusCalloc %s", strerror(errno)); while ((str = *model++) != NULL) { RaPolicyLineNumber++; while (isspace((int)*str)) str++; if (strlen(str)) { switch (*str) { case '#': case '\n': case '!': break; default: if ((str = strdup(str)) != NULL) { if (RaCreatePolicyEntry(retn, RaPolicyLines, str) < 0) { ArgusLog (LOG_ERR, "RaReadFlowModelFile: parse error line %d %s\n", RaPolicyLineNumber, RaPolicyError[RaParseError]); } else RaPolicyLines++; } else ArgusLog (LOG_ERR, "RaReadFlowModelFile: error %s\n", strerror(errno)); } } } for (i = 0; i < RaThisFlowNum; i++) { if (retn->policy[i]) { int found = 0; for (x = 0; x < RaThisModelNum; x++) { if (retn->model[x]) if (retn->policy[i]->RaModelId == retn->model[x]->RaPolicyId) { retn->policy[i]->RaModelId = x; found++; break; } } if (!found) ArgusLog (LOG_ERR, "%s: RaReadFlowModelFile: Model Index %d not found\n", ArgusProgramName, retn->policy[i]->RaModelId); } } if (modelbuf[0] != NULL) { do { free(modelbuf[i]); modelbuf[i++] = NULL; } while (modelbuf[i] != NULL); } #ifdef ARGUSDEBUG ArgusDebug (3, "RaReadFlowModelFile: returning 0x%x\n", retn); #endif return (retn); } struct RaHashTableHeader * RaFindHashEntry (struct RaHashTableStruct *thisHashTable, struct RaHashStruct *hstruct) { struct RaHashTableHeader *retn = NULL; struct RaHashTableHeader *head = NULL, *target; if (thisHashTable->size > 0) { if ((target = thisHashTable->array[hstruct->hash % thisHashTable->size]) != NULL) { head = target; do { if (!(bcmp ((char *) hstruct->buf, (char *) &target->hstruct.buf, sizeof(hstruct->buf)))) { retn = target; break; } else target = target->nxt; } while (target != head); } } #ifdef ARGUSDEBUG ArgusDebug (7, "RaFindHashEntry: returning 0x%x\n", retn); #endif return (retn); } struct RaHashTableHeader * RaAddHashEntry (struct RaHashTableStruct *thisHashTable, struct ArgusRecordStore *store) { struct RaHashTableHeader *retn = NULL; struct RaHashTableHeader *start = NULL; struct ArgusFlow *RaThisFlow = NULL; struct ArgusRecord *argus = NULL; struct RaHashStruct ArgusHash; unsigned short ip_id = 0, *ptr = NULL; int i, len; if (store && store->data && store->data[RaThisActiveIndex] && (argus = store->data[RaThisActiveIndex]->argus)) { if ((retn = (struct RaHashTableHeader *) ArgusCalloc (1, sizeof (struct RaHashTableHeader))) != NULL) { RaAllocHashTableHeaders++; RaThisFlow = &argus->argus_far.flow; bzero ((char *)&ArgusHash, sizeof(ArgusHash)); ArgusHash.len = sizeof(ArgusHash.buf); if ((argus->ahdr.status & 0xFFFF) == ETHERTYPE_IP) { switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_ICMP: ip_id = RaThisFlow->icmp_flow.ip_id; RaThisFlow->icmp_flow.ip_id = 0; break; default: ip_id = RaThisFlow->ip_flow.ip_id; RaThisFlow->ip_flow.ip_id = 0; break; } } ArgusHash.buf[0] = argus->ahdr.argusid; bcopy (RaThisFlow, (char *)&ArgusHash.buf[1], sizeof(*RaThisFlow)); ptr = (unsigned short *)&ArgusHash.buf[0]; for (i = 0, len = ArgusHash.len / sizeof(unsigned short); i < len; i++) ArgusHash.hash += *ptr++; bcopy((char *)&ArgusHash, (char *)&retn->hstruct, sizeof (ArgusHash)); retn->storeobj = store; if ((start = thisHashTable->array[ArgusHash.hash % thisHashTable->size]) != NULL) { retn->nxt = start; retn->prv = start->prv; retn->prv->nxt = retn; retn->nxt->prv = retn; } else retn->prv = retn->nxt = retn; thisHashTable->array[ArgusHash.hash % thisHashTable->size] = retn; thisHashTable->count++; retn->htable = thisHashTable; if ((argus->ahdr.status & 0xFFFF) == ETHERTYPE_IP) { switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_ICMP: RaThisFlow->icmp_flow.ip_id = ip_id; break; default: RaThisFlow->ip_flow.ip_id = ip_id; break; } } } } #ifdef ARGUSDEBUG ArgusDebug (7, "RaAddHashEntry (0x%x) returning 0x%x\n", store, retn); #endif return (retn); } void RaRemoveHashEntry (struct RaHashTableStruct *thisHashTable, struct RaHashTableHeader *rahtblhdr) { unsigned short hash = rahtblhdr->hstruct.hash; if (rahtblhdr->htable == thisHashTable) { if ((rahtblhdr->prv) && (rahtblhdr->nxt)) { rahtblhdr->prv->nxt = rahtblhdr->nxt; rahtblhdr->nxt->prv = rahtblhdr->prv; if ((rahtblhdr->nxt == rahtblhdr) || (rahtblhdr->prv == rahtblhdr)) { rahtblhdr->nxt = NULL; rahtblhdr->prv = NULL; } } rahtblhdr->htable = NULL; if (thisHashTable) { if (rahtblhdr == thisHashTable->array[hash % thisHashTable->size]) { if (rahtblhdr == rahtblhdr->nxt) thisHashTable->array[hash % thisHashTable->size] = NULL; else thisHashTable->array[hash % thisHashTable->size] = rahtblhdr->nxt; } thisHashTable->count--; } } else ArgusLog (LOG_ERR, "RaRemoveHashEntry (0x%x, 0x%x) obj not in table\n", thisHashTable, rahtblhdr); ArgusFree (rahtblhdr); RaAllocHashTableHeaders--; #ifdef ARGUSDEBUG ArgusDebug (7, "RaRemoveHashObject (0x%x) returning\n", rahtblhdr); #endif } void RaCleanHashTable (struct RaHashTableStruct *thisHashTable) { struct RaHashTableHeader *rahtblhdr = NULL; int i; for (i = 0; i < thisHashTable->size; i++) while ((rahtblhdr = thisHashTable->array[i]) != NULL) RaRemoveHashEntry(rahtblhdr->htable, rahtblhdr); ArgusFree (thisHashTable->array); thisHashTable->array = NULL; #ifdef ARGUSDEBUG ArgusDebug (7, "RaCleanHashTable (0x%x) returning\n", thisHashTable); #endif } void RaDeleteHashTable (struct RaHashTableStruct *thisHashTable) { struct RaHashTableHeader *rahtblhdr = NULL; int i; for (i = 0; i < thisHashTable->size; i++) while ((rahtblhdr = thisHashTable->array[i]) != NULL) RaRemoveHashEntry(rahtblhdr->htable, rahtblhdr); if (thisHashTable->array != NULL) ArgusFree (thisHashTable->array); ArgusFree (thisHashTable); #ifdef ARGUSDEBUG ArgusDebug (7, "RaDeleteHashTable (0x%x) returning\n", thisHashTable); #endif } struct RaQueueStruct * RaNewQueue () { struct RaQueueStruct *retn = NULL; if ((retn = (struct RaQueueStruct *) ArgusCalloc (1, sizeof (struct RaQueueStruct))) != NULL) { retn->count = 0; retn->start = NULL; } #ifdef ARGUSDEBUG ArgusDebug (4, "RaNewQueue () returning 0x%x\n", retn); #endif return (retn); } void RaDeleteQueue (struct RaQueueStruct *queue) { struct ArgusQueueHeader *obj = NULL; if (queue != NULL) { while ((obj = RaPopQueue(queue))) ArgusFree(obj); ArgusFree(queue); } #ifdef ARGUSDEBUG ArgusDebug (4, "RaDeleteQueue (0x%x) returning\n", queue); #endif } int RaGetQueueCount(struct RaQueueStruct *queue) { #ifdef ARGUSDEBUG ArgusDebug (7, "RaGetQueueCount (0x%x) returning %d\n", queue, queue->count); #endif return (queue->count); } void RaPushQueue(struct RaQueueStruct *queue, struct ArgusQueueHeader *obj) { int retn = 0; if ((retn = RaAddToQueue (queue, obj)) > 0) queue->start = queue->start->prv; #ifdef ARGUSDEBUG ArgusDebug (7, "RaPushQueue (0x%x, 0x%x) returning\n", queue, obj); #endif } int RaAddToQueue(struct RaQueueStruct *queue, struct ArgusQueueHeader *obj) { int retn = 0; if (queue && obj) { if (obj->queue == NULL) { if (queue->start != NULL) { obj->prv = queue->start->prv; queue->start->prv = obj; obj->nxt = queue->start; obj->prv->nxt = obj; } else { queue->start = obj; obj->nxt = obj; obj->prv = obj; } queue->count++; obj->queue = queue; retn = 1; } else ArgusLog (LOG_ERR, "RaAddToQueue (0x%x, 0x%x) obj in queue 0x%x\n", queue, obj, obj->queue); } else ArgusLog (LOG_ERR, "RaAddToQueue (0x%x, 0x%x) parameter error\n", queue, obj); #ifdef ARGUSDEBUG ArgusDebug (7, "RaAddToQueue (0x%x, 0x%x) returning %d\n", queue, obj, retn); #endif return (retn); } struct ArgusQueueHeader * RaPopQueue (struct RaQueueStruct *queue) { struct ArgusQueueHeader *retn = NULL; struct ArgusQueueHeader *obj = NULL; if (queue && queue->count) { if ((obj = (struct ArgusQueueHeader *) queue->start) != NULL) retn = RaRemoveFromQueue(queue, obj); else ArgusLog (LOG_ERR, "RaPopQueue(0x%x) internal queue error count %d start NULL\n", queue, queue->count); } #ifdef ARGUSDEBUG ArgusDebug (8, "RaPopQueue (0x%x) returning 0x%x\n", queue, retn); #endif return(retn); } struct ArgusQueueHeader * RaRemoveFromQueue(struct RaQueueStruct *queue, struct ArgusQueueHeader *obj) { struct ArgusQueueHeader *retn = NULL; if ((queue != NULL) && (obj != NULL)) { if (queue->count && (obj->queue == queue)) { queue->count--; if (queue->count) { if (queue->start == obj) queue->start = obj->nxt; obj->prv->nxt = obj->nxt; obj->nxt->prv = obj->prv; } else queue->start = NULL; obj->prv = NULL; obj->nxt = NULL; obj->queue = NULL; retn = obj; } else ArgusLog (LOG_ERR, "RaRemoveFromQueue(0x%x, 0x%x) obj not in queue\n", queue, obj); } else ArgusLog (LOG_ERR, "RaRemoveFromQueue(0x%x, 0x%x) parameter error\n", queue, obj); #ifdef ARGUSDEBUG ArgusDebug (9, "RaRemoveFromQueue (0x%x, 0x%x) returning 0x%x\n", queue, obj, obj); #endif return (retn); } struct ArgusListStruct * ArgusNewList () { struct ArgusListStruct *retn = NULL; if ((retn = (struct ArgusListStruct *) ArgusCalloc (1, sizeof (struct ArgusListStruct))) != NULL) { retn->start = NULL; retn->count = 0; } #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusNewList () returning 0x%x\n", retn); #endif return (retn); } void ArgusDeleteList (struct ArgusListStruct *list) { if (list) { while (list->start) ArgusPopFrontList(list); ArgusFree (list); } #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusDeleteList (0x%x) returning\n", list); #endif } int ArgusListEmpty (struct ArgusListStruct *list) { return (list->start == NULL); } int ArgusGetListCount(struct ArgusListStruct *list) { return (list->count); } void ArgusPushFrontList(struct ArgusListStruct *list, void *obj) { struct ArgusListObjectStruct *lobj = NULL; if (list && obj) { if ((lobj = (struct ArgusListObjectStruct *) ArgusCalloc (1, sizeof(*lobj))) != NULL) { lobj->obj = obj; if (list->start) { lobj->nxt = list->start; lobj->prv = list->start->prv; lobj->nxt->prv = lobj; lobj->prv->nxt = lobj; } else { lobj->prv = lobj; lobj->nxt = lobj; } list->start = lobj; list->count++; } } #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusPushFrontList (0x%x, 0x%x) returning 0x%x\n", list, obj); #endif } void ArgusPushBackList(struct ArgusListStruct *list, void *obj) { ArgusPushFrontList(list, obj); list->start = list->start->nxt; #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusPushBackList (0x%x, 0x%x) returning 0x%x\n", list, obj); #endif } void * ArgusFrontList(struct ArgusListStruct *list) { void *retn = NULL; if (list->start) retn = list->start->obj; #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusFrontList (0x%x) returning 0x%x\n", list, retn); #endif return (retn); } void * ArgusBackList(struct ArgusListStruct *list) { void *retn = NULL; if (list->start) retn = list->start->prv->obj; #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusBackList (0x%x) returning 0x%x\n", list, retn); #endif return (retn); } void ArgusPopBackList(struct ArgusListStruct *list) { struct ArgusListObjectStruct *lobj = NULL; if ((lobj = list->start)) { list->start = list->start->prv; ArgusPopFrontList(list); } #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusPopBackList (0x%x) returning\n", list); #endif } void ArgusPopFrontList(struct ArgusListStruct *list) { struct ArgusListObjectStruct *lobj = NULL; if ((lobj = list->start)) { if (--list->count > 0) { if (lobj->prv) lobj->prv->nxt = lobj->nxt; if (lobj->nxt) lobj->nxt->prv = lobj->prv; list->start = lobj->nxt; } else list->start = NULL; ArgusFree(lobj); } #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusPopFrontList (0x%x) returning\n", list); #endif } char RaPrecisionPad[32], RaTimePad[32], RaDateBuf[128]; char * RaGenerateLabel(struct ArgusRecord *argus) { int i, x; bzero (RaDateBuf, sizeof (RaDateBuf)); bzero (RaTimePad, sizeof (RaTimePad)); bzero (RaPrecisionPad, sizeof (RaPrecisionPad)); bzero (RaLabelStr, sizeof(RaLabelStr)); ArgusPrintStartDate (RaDateBuf, argus); if (strlen(RaDateBuf) > 10) { for (x = 0; x < (strlen(RaDateBuf) - 10)/2; x++) strcat (RaTimePad, " "); } if (pflag) for (x = 0; x < pflag/2; x++) strcat (RaPrecisionPad, " "); RaLabel = RaLabelStr; for (i = 0; i < MAX_PRINT_ALG_TYPES; i++) { if (RaPrintAlgorithms[i] != NULL) { for (x = 0; x < MAX_PRINT_ALG_TYPES; x++) { if ((void *) RaPrintAlgorithms[i] == (void *) RaPrintAlgorithmTable[x]) { RaPrintLabelAlgorithmTable[x](&RaLabel[strlen(RaLabel)]); break; } } } else break; } if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) { char tmpbuf[128], *ptr = tmpbuf, *str = RaLabel, lastchr = ' '; bzero (tmpbuf, sizeof(tmpbuf)); lastchr = RaFieldDelimiter; while (*str) { if (*str == ' ') { if (lastchr != RaFieldDelimiter) *ptr++ = RaFieldDelimiter; while (isspace((int)*str)) str++; } lastchr = *str; *ptr++ = *str++; } bzero (RaLabel, MAXSTRLEN); if (tmpbuf[strlen(tmpbuf) - 1] == RaFieldDelimiter) tmpbuf[strlen(tmpbuf) - 1] = '\0'; bcopy (tmpbuf, RaLabel, strlen(tmpbuf)); } return (RaLabel); } void ArgusPrintDateLabel (char *buf) { if (lflag) ArgusPrintLastDateLabel (buf); else ArgusPrintStartDateLabel (buf); } void ArgusPrintStartDateLabel (char *buf) { sprintf (&buf[strlen(buf)], RaTimePad); sprintf (&buf[strlen(buf)], "StartTime "); if (pflag) { if (!uflag) if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) sprintf (&buf[strlen(buf)], "Fraction "); } sprintf (&buf[strlen(buf)], RaTimePad); if (strlen(RaDateBuf) & 0x01) sprintf (&buf[strlen(buf)], " "); } void ArgusPrintLastDateLabel (char *buf) { sprintf (&buf[strlen(buf)], RaTimePad); sprintf (&buf[strlen(buf)], " LastTime "); if (pflag) { if (!uflag) if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) sprintf (&buf[strlen(buf)], "Fraction "); } sprintf (&buf[strlen(buf)], RaTimePad); if (strlen(RaDateBuf) & 0x01) sprintf (&buf[strlen(buf)], " "); } void ArgusPrintSourceIDLabel (char *buf) { sprintf (&buf[strlen(buf)], " ProbeId "); } void ArgusPrintIndicatorLabel (char *buf) { sprintf (&buf[strlen(buf)], " Flgs "); } void ArgusPrintMACAddressLabel (char *buf) { sprintf (&buf[strlen(buf)], RamOptionLabel); } void ArgusPrintProtoLabel (char *buf) { sprintf (&buf[strlen(buf)], "Type "); } void ArgusPrintSrcNetLabel (char *buf) { sprintf (&buf[strlen(buf)], "%*sSrcNet%*s ", (hfield - 6)/2, " ", (hfield - 6)/2, " "); if ((hfield & 0x01)) sprintf (&buf[strlen(buf)], " "); } void ArgusPrintSrcAddrLabel (char *buf) { if (ArgusInput->ArgusManStart.ahdr.type & ARGUS_RMON) sprintf (&buf[strlen(buf)], "%*s Addr%*s ", (hfield - 5)/2, " ", (hfield - 5)/2, " "); else sprintf (&buf[strlen(buf)], "%*sSrcAddr%*s ", (hfield - 7)/2, " ", (hfield - 7)/2, " "); if (!(hfield & 0x01)) sprintf (&buf[strlen(buf)], " "); } void ArgusPrintDstNetLabel (char *buf) { sprintf (&buf[strlen(buf)], " %*sDstNet%*s ", (hfield - 6)/2, " ", (hfield - 6)/2, " "); if ((hfield & 0x01)) sprintf (&buf[strlen(buf)], " "); } void ArgusPrintDstAddrLabel (char *buf) { sprintf (&buf[strlen(buf)], "%*sDstAddr%*s ", (hfield - 7)/2, " ", (hfield - 7)/2, " "); if (!(hfield & 0x01)) sprintf (&buf[strlen(buf)], " "); } void ArgusPrintSrcPortLabel (char *buf) { if (!(pfield & 0x01)) sprintf (&buf[strlen(buf)], " "); if (pfield > 6) { sprintf (&buf[strlen(buf)], "%*sSport%*s ", (pfield - 5)/2, " ", (pfield - 5)/2, " "); } else { sprintf (&buf[strlen(buf)], "Sport "); } } void ArgusPrintDstPortLabel (char *buf) { if (!(pfield & 0x01)) sprintf (&buf[strlen(buf)], " "); if (pfield > 6) { sprintf (&buf[strlen(buf)], "%*sDport%*s ", (pfield - 5)/2, " ", (pfield - 5)/2, " "); } else { sprintf (&buf[strlen(buf)], "Dport "); } } void ArgusPrintIpIdLabel (char *buf) { sprintf (&buf[strlen(buf)], " IpId "); } void ArgusPrintDirLabel (char *buf) { sprintf (&buf[strlen(buf)], "Dir "); } void ArgusPrintCountsLabel (char *buf) { if (ArgusInput->ArgusManStart.ahdr.type & ARGUS_RMON) sprintf (&buf[strlen(buf)], "InPkt OutPkt "); else sprintf (&buf[strlen(buf)], "SrcPkt DstPkt "); } void ArgusPrintSrcPacketsLabel (char *buf) { if (ArgusInput->ArgusManStart.ahdr.type & ARGUS_RMON) sprintf (&buf[strlen(buf)], "InPkt "); else sprintf (&buf[strlen(buf)], "SrcPkt "); } void ArgusPrintDstPacketsLabel (char *buf) { if (ArgusInput->ArgusManStart.ahdr.type & ARGUS_RMON) sprintf (&buf[strlen(buf)], "OutPkt "); else sprintf (&buf[strlen(buf)], "DstPkt "); } void ArgusPrintBytesLabel (char *buf) { if (ArgusInput->ArgusManStart.ahdr.type & ARGUS_RMON) { if (Aflag) sprintf (&buf[strlen(buf)], "InAppBytes OutAppBytes "); else if (Rflag) sprintf (&buf[strlen(buf)], "Response Information "); else sprintf (&buf[strlen(buf)], "InBytes OutBytes "); } else { if (Aflag) sprintf (&buf[strlen(buf)], "SAppBytes DAppBytes "); else if (Rflag) sprintf (&buf[strlen(buf)], "Response Information "); else sprintf (&buf[strlen(buf)], "SrcBytes DstBytes "); } } void ArgusPrintSrcBytesLabel (char *buf) { if (ArgusInput->ArgusManStart.ahdr.type & ARGUS_RMON) { if (Aflag) sprintf (&buf[strlen(buf)], "InAppBytes "); else if (Rflag) sprintf (&buf[strlen(buf)], "InBytes "); else sprintf (&buf[strlen(buf)], "InBytes "); } else { if (Aflag) sprintf (&buf[strlen(buf)], "SAppBytes "); else if (Rflag) sprintf (&buf[strlen(buf)], "SrcBytes "); else sprintf (&buf[strlen(buf)], "SrcBytes "); } } void ArgusPrintDstBytesLabel (char *buf) { if (ArgusInput->ArgusManStart.ahdr.type & ARGUS_RMON) { if (Aflag) sprintf (&buf[strlen(buf)], "OutAppBytes "); else if (Rflag) sprintf (&buf[strlen(buf)], "OutBytes "); else sprintf (&buf[strlen(buf)], "OutBytes "); } else { if (Aflag) sprintf (&buf[strlen(buf)], "DAppBytes "); else if (Rflag) sprintf (&buf[strlen(buf)], "SrcBytes "); else sprintf (&buf[strlen(buf)], "DstBytes "); } } void ArgusPrintSrcJitterLabel (char *buf) { RaPrintSrcTime = 1; RaPrintDstTime = 0; ArgusPrintJitterLabel (buf); } void ArgusPrintDstJitterLabel (char *buf) { RaPrintSrcTime = 0; RaPrintDstTime = 1; ArgusPrintJitterLabel (buf); } void ArgusPrintJitterLabel (char *buf) { if (RaPrintSrcTime) { if ((RaPrintActTime) && (RaPrintIdleTime)) { sprintf (&buf[strlen(buf)], " SrcJitter "); } else { if (RaPrintActTime) sprintf (&buf[strlen(buf)], " SrcAJitter "); else if (RaPrintIdleTime) sprintf (&buf[strlen(buf)], " SrcIJitter "); else sprintf (&buf[strlen(buf)], " "); } } if (RaPrintDstTime) { if ((RaPrintActTime) && (RaPrintIdleTime)) sprintf (&buf[strlen(buf)], " DstJitter "); else { if (RaPrintActTime) sprintf (&buf[strlen(buf)], " DstAJitter "); else if (RaPrintIdleTime) sprintf (&buf[strlen(buf)], " DstIJitter "); else sprintf (&buf[strlen(buf)], " "); } } } void ArgusPrintStatusLabel (char *buf) { if (zflag || Zflag) { sprintf (&buf[strlen(buf)], " Status"); } else { sprintf (&buf[strlen(buf)], "State"); } } void ArgusPrintUserDataLabel (char *buf) { int len = 0; if ((ArgusSrcUserDataLen) || (ArgusDstUserDataLen)) { if (ArgusSrcUserDataLen > 0) { switch (eflag) { case ARGUS_ENCODE_ASCII: len = ArgusSrcUserDataLen; break; case ARGUS_ENCODE_32: case ARGUS_ENCODE_64: len = ArgusSrcUserDataLen; len *= 2; break; } if (ArgusSrcUserDataLen > 10) len++; sprintf (&buf[strlen(buf)], " %*ssrcUdata%*s ", (len)/2, " ", (len)/2, " "); if (len & 0x01) sprintf(&buf[strlen(buf)], " "); } else sprintf(&buf[strlen(buf)], " "); if (ArgusDstUserDataLen > 0) { switch (eflag) { case ARGUS_ENCODE_ASCII: len = ArgusDstUserDataLen; break; case ARGUS_ENCODE_32: case ARGUS_ENCODE_64: len = ArgusDstUserDataLen; len *= 2; break; } if (ArgusDstUserDataLen > 10) len++; sprintf (&buf[strlen(buf)], "%*sdstUdata%*s ", (len)/2, " ", (len)/2, " "); if (len & 0x01) sprintf(&buf[strlen(buf)], " "); } } } void ArgusPrintTCPExtensionsLabel (char *buf) { } void ArgusPrintSrcRateLabel (char *buf) { sprintf (&buf[strlen(buf)], RaSrcRateOptionLabel); } void ArgusPrintDstRateLabel (char *buf) { sprintf (&buf[strlen(buf)], RaDstRateOptionLabel); } void ArgusPrintRateLabel (char *buf) { sprintf (&buf[strlen(buf)], RaRateOptionLabel); } void ArgusPrintLossLabel (char *buf) { sprintf (&buf[strlen(buf)], RaLossOptionLabel); } void ArgusPrintSrcLoadLabel (char *buf) { if (Aflag) sprintf (&buf[strlen(buf)], RaSrcAppLoadOptionLabel); else sprintf (&buf[strlen(buf)], RaSrcLoadOptionLabel); } void ArgusPrintDstLoadLabel (char *buf) { if (Aflag) sprintf (&buf[strlen(buf)], RaDstAppLoadOptionLabel); else sprintf (&buf[strlen(buf)], RaDstLoadOptionLabel); } void ArgusPrintLoadLabel (char *buf) { if (Aflag) sprintf (&buf[strlen(buf)], RaAppLoadOptionLabel); else sprintf (&buf[strlen(buf)], RaLoadOptionLabel); } void ArgusPrintSrcTTLLabel (char *buf) { if (RaPrintDistance) sprintf (&buf[strlen(buf)], "SrcDis "); else sprintf (&buf[strlen(buf)], "SrcTTL "); } void ArgusPrintDstTTLLabel (char *buf) { if (RaPrintDistance) sprintf (&buf[strlen(buf)], "DstDis "); else sprintf (&buf[strlen(buf)], "DstTTL "); } void ArgusPrintMPLSLabel (char *buf) { sprintf (&buf[strlen(buf)], " sMPLS dMPLS "); } void ArgusPrintVLANLabel (char *buf) { sprintf (&buf[strlen(buf)], " sVLAN dVLAN "); } void ArgusPrintSrcTOSLabel (char *buf) { sprintf (&buf[strlen(buf)], "SrcTOS "); } void ArgusPrintDstTOSLabel (char *buf) { sprintf (&buf[strlen(buf)], "DstTOS "); } void ArgusPrintWindowLabel (char *buf) { sprintf (&buf[strlen(buf)], "SrcWin DstWin "); } void ArgusPrintDurationLabel (char *buf) { sprintf (&buf[strlen(buf)], RaPrecisionPad); sprintf (&buf[strlen(buf)], " Dur "); sprintf (&buf[strlen(buf)], RaPrecisionPad); if (pflag) { sprintf (&buf[strlen(buf)], " "); if (pflag & 0x01) sprintf (&buf[strlen(buf)], " "); } } void ArgusPrintAvgDurationLabel (char *buf) { sprintf (&buf[strlen(buf)], RaPrecisionPad); sprintf (&buf[strlen(buf)], " AvgDur "); sprintf (&buf[strlen(buf)], RaPrecisionPad); if (pflag) { sprintf (&buf[strlen(buf)], " "); if (pflag & 0x01) sprintf (&buf[strlen(buf)], " "); } } void ArgusPrintTransactionsLabel (char *buf) { sprintf (&buf[strlen(buf)], "Trans "); } void ArgusPrintSequenceNumberLabel (char *buf) { sprintf (&buf[strlen(buf)], " Seq "); } void ArgusPrintBinNumberLabel (char *buf) { sprintf (&buf[strlen(buf)], " Bin "); } void ArgusPrintBinsLabel (char *buf) { sprintf (&buf[strlen(buf)], " Bins "); } void RaSortQueue (struct RaQueueStruct *queue) { int i = 0, cnt = queue->count; struct ArgusQueueHeader *qhdr; if (queue->array != NULL) { ArgusFree(queue->array); queue->array = NULL; } if (cnt > 0) { if ((queue->array = (struct ArgusQueueHeader **) ArgusCalloc(sizeof(struct ArgusQueueHeader *), cnt + 1)) != NULL) { qhdr = queue->start; for (i = 0; i < cnt; i++) { queue->array[i] = qhdr; qhdr = qhdr->nxt; if (qhdr == queue->start) break; } qsort ((char *) queue->array, i + 1, sizeof (struct ArgusQueueHeader *), RaSortRoutine); } else ArgusLog (LOG_ERR, "RaSortQueue: ArgusCalloc(%d, %d) %s\n", sizeof(struct ArgusRecord *), cnt, strerror(errno)); } #ifdef ARGUSDEBUG ArgusDebug (3, "RaSortQueue(0x%x) returned\n", queue); #endif } int RaSortRoutine (const void *void1, const void *void2) { int retn = 0, i = 0; struct ArgusRecordStore *store1 = *(struct ArgusRecordStore **)void1; struct ArgusRecordStore *store2 = *(struct ArgusRecordStore **)void2; struct ArgusRecord *argus1 = NULL; struct ArgusRecord *argus2 = NULL; if ((store1 && store1->data[0] && store1->data[0]->argus) && ((store2 && store2->data[0] && store2->data[0]->argus))) { argus1 = store1->data[0]->argus; argus2 = store2->data[0]->argus; for (i = 0; i < ARGUS_MAX_SORT_ALG; i++) if (RaSortAlgorithms[i] != NULL) if ((retn = RaSortAlgorithms[i](argus2, argus1)) != 0) break; } return (retn); } int RaSortSrcId (struct ArgusRecord *a2, struct ArgusRecord *a1) { unsigned int sid1 = a1->ahdr.argusid; unsigned int sid2 = a2->ahdr.argusid; return ((sid1 > sid2) ? 1 : ((sid1 == sid2) ? 0 : -1)); } int RaSortStartTime (struct ArgusRecord *a1, struct ArgusRecord *a2) { unsigned int retn; if ((retn = a2->argus_far.time.start.tv_sec - a1->argus_far.time.start.tv_sec) == 0) retn = a2->argus_far.time.start.tv_usec - a1->argus_far.time.start.tv_usec; return (retn); } int RaSortLastTime (struct ArgusRecord *a1, struct ArgusRecord *a2) { unsigned int retn; if ((retn = a2->argus_far.time.last.tv_sec - a1->argus_far.time.last.tv_sec) == 0) retn = a2->argus_far.time.last.tv_usec - a1->argus_far.time.last.tv_usec; return (retn); } int RaSortCount (struct ArgusRecord *a2, struct ArgusRecord *a1) { int cnt1 = 1, cnt2 = 1; struct ArgusAGRStruct *agr1, *agr2; struct ArgusFarHeaderStruct *a1farhdrs[32]; struct ArgusFarHeaderStruct *a2farhdrs[32]; ArgusIndexRecord (a1, a1farhdrs); ArgusIndexRecord (a2, a2farhdrs); agr1 = (struct ArgusAGRStruct *) a1farhdrs[ARGUS_AGR_DSR_INDEX]; agr2 = (struct ArgusAGRStruct *) a2farhdrs[ARGUS_AGR_DSR_INDEX]; if (agr1 != NULL) cnt1 = agr1->count; if (agr2 != NULL) cnt2 = agr2->count; return (cnt2 - cnt1); } int RaSortAvgDuration (struct ArgusRecord *a2, struct ArgusRecord *a1) { return ((int)(RaGetuSecAvgDuration(a1) - RaGetuSecAvgDuration(a2))); } int RaSortDuration (struct ArgusRecord *a2, struct ArgusRecord *a1) { return ((int)(RaGetuSecDuration(a1) - RaGetuSecDuration(a2))); } int RaSortSrcAddr (struct ArgusRecord *a2, struct ArgusRecord *a1) { int retn = 0; if ((retn = (a1->ahdr.status & 0xFFFF) - (a2->ahdr.status & 0xFFFF)) == 0) { switch (a1->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: { unsigned int addr1 = a1->argus_far.flow.ip_flow.ip_src; unsigned int addr2 = a2->argus_far.flow.ip_flow.ip_src; retn = (addr1 > addr2) ? 1 : ((addr1 == addr2) ? 0 : -1); break; } case ETHERTYPE_ARP: { unsigned int addr1 = a1->argus_far.flow.arp_flow.arp_spa; unsigned int addr2 = a2->argus_far.flow.arp_flow.arp_spa; retn = (addr1 > addr2) ? 1 : ((addr1 == addr2) ? 0 : -1); break; } default: retn = bcmp ((char *)&a2->argus_far.flow.mac_flow.ehdr.ether_shost, (char *)&a1->argus_far.flow.mac_flow.ehdr.ether_shost, 6); break; } } return (retn); } int RaSortDstAddr (struct ArgusRecord *a2, struct ArgusRecord *a1) { int retn = 0; if ((retn = (a1->ahdr.status & 0xFFFF) - (a2->ahdr.status & 0xFFFF)) == 0) { switch (a1->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: { unsigned int addr1 = a1->argus_far.flow.ip_flow.ip_dst; unsigned int addr2 = a2->argus_far.flow.ip_flow.ip_dst; retn = (addr1 > addr2) ? 1 : ((addr1 == addr2) ? 0 : -1); break; } case ETHERTYPE_ARP: { unsigned int addr1 = a1->argus_far.flow.arp_flow.arp_tpa; unsigned int addr2 = a2->argus_far.flow.arp_flow.arp_tpa; retn = (addr1 > addr2) ? 1 : ((addr1 == addr2) ? 0 : -1); break; } default: retn = bcmp ((char *)&a2->argus_far.flow.mac_flow.ehdr.ether_dhost, (char *)&a1->argus_far.flow.mac_flow.ehdr.ether_dhost, 6); break; } } return (retn); } int RaSortProtocol (struct ArgusRecord *a1, struct ArgusRecord *a2) { int retn; if ((retn = (a1->ahdr.status & 0xFFFF) - (a2->ahdr.status & 0xFFFF)) == 0) if (((a1->ahdr.status & 0xFFFF) == ETHERTYPE_IP) && ((a2->ahdr.status & 0xFFFF) == ETHERTYPE_IP)) if ((retn = a1->argus_far.flow.ip_flow.ip_p - a2->argus_far.flow.ip_flow.ip_p) == 0) retn = a1->argus_far.flow.ip_flow.tp_p - a2->argus_far.flow.ip_flow.tp_p; return (retn); } int RaSortSrcPort (struct ArgusRecord *a1, struct ArgusRecord *a2) { return (a2->argus_far.flow.ip_flow.sport - a1->argus_far.flow.ip_flow.sport); } int RaSortDstPort (struct ArgusRecord *a1, struct ArgusRecord *a2) { return (a2->argus_far.flow.ip_flow.dport - a1->argus_far.flow.ip_flow.dport); } int RaSortSrcTos (struct ArgusRecord *a1, struct ArgusRecord *a2) { int retn = 0; if ((a1->ahdr.status & 0xFFFF) == ETHERTYPE_IP) retn = (a2->argus_far.attr_ip.stos - a1->argus_far.attr_ip.stos); return (retn); } int RaSortDstTos (struct ArgusRecord *a1, struct ArgusRecord *a2) { int retn = 0; if ((a1->ahdr.status & 0xFFFF) == ETHERTYPE_IP) retn = (a2->argus_far.attr_ip.dtos - a1->argus_far.attr_ip.dtos); return (retn); } int RaSortSrcTtl (struct ArgusRecord *a1, struct ArgusRecord *a2) { int retn = 0; if ((a1->ahdr.status & 0xFFFF) == ETHERTYPE_IP) retn = (a2->argus_far.attr_ip.sttl - a1->argus_far.attr_ip.sttl); return (retn); } int RaSortDstTtl (struct ArgusRecord *a1, struct ArgusRecord *a2) { int retn = 0; if ((a1->ahdr.status & 0xFFFF) == ETHERTYPE_IP) retn = (a2->argus_far.attr_ip.dttl - a1->argus_far.attr_ip.dttl); return (retn); } int RaSortByteCount (struct ArgusRecord *a1, struct ArgusRecord *a2) { long long cnt1, cnt2; int retn; if (Aflag) { cnt1 = a1->argus_far.src.appbytes + a1->argus_far.dst.appbytes; cnt2 = a2->argus_far.src.appbytes + a2->argus_far.dst.appbytes; retn = (int) (cnt1 - cnt2); } else { cnt1 = a1->argus_far.src.bytes + a1->argus_far.dst.bytes; cnt2 = a2->argus_far.src.bytes + a2->argus_far.dst.bytes; retn = (int) (cnt1 - cnt2); } return (retn); } int RaSortLoad (struct ArgusRecord *a1, struct ArgusRecord *a2) { int src1, src2, dst1, dst2, retn = 0; struct timeval *start = NULL, *last = NULL; struct timeval timebuf, *time = &timebuf; double sec1, sec2; start = &a1->argus_far.time.start; last = &a1->argus_far.time.last; *time = *last; time->tv_sec -= start->tv_sec; time->tv_usec -= start->tv_usec; if (time->tv_usec < 0) { time->tv_sec--; time->tv_usec += 1000000; } if (time->tv_usec >= 1000000) { time->tv_sec++; time->tv_usec -= 1000000; } sec1 = (double)(time->tv_sec * 1.0) + (double)(time->tv_usec/1000000.0); start = &a2->argus_far.time.start; last = &a2->argus_far.time.last; *time = *last; time->tv_sec -= start->tv_sec; time->tv_usec -= start->tv_usec; if (time->tv_usec < 0) { time->tv_sec--; time->tv_usec += 1000000; } if (time->tv_usec >= 1000000) { time->tv_sec++; time->tv_usec -= 1000000; } sec2 = (double)(time->tv_sec * 1.0) + (double)(time->tv_usec/1000000.0); if (Aflag) { src1 = a1->argus_far.src.appbytes; dst1 = a1->argus_far.dst.appbytes; src2 = a2->argus_far.src.appbytes; dst2 = a2->argus_far.dst.appbytes; } else { src1 = a1->argus_far.src.bytes; dst1 = a1->argus_far.dst.bytes; src2 = a2->argus_far.src.bytes; dst2 = a2->argus_far.dst.bytes; } if (sec1 && sec2) { retn = (((double)(((src1 + dst1) * 1.0)/(double)(sec1 * 1.0)) > (double)(((src2 + dst2) * 1.0)/(double)(sec2 * 1.0))) ? 1 : ((double)(((src1 + dst1) * 1.0)/(double)(sec1 * 1.0)) == (double)(((src2 + dst2) * 1.0)/(double)(sec2 * 1.0))) ? 0 : -1); } else { if (sec1) retn = 1; if (sec2) retn = -1; } return (retn); } int RaSortLoss (struct ArgusRecord *a1, struct ArgusRecord *a2) { /* struct ArgusTCPObjectMetrics { unsigned int seqbase, ackbytes; unsigned int bytes, rpkts; unsigned short win; unsigned char flags, pad; }; struct ArgusTCPObject { unsigned char type, length; unsigned short status; unsigned int state; unsigned int options; unsigned int synAckuSecs, ackDatauSecs; struct ArgusTCPObjectMetrics src, dst; }; */ int retn = 0; double a1pkts, a1rpkts, a1loss; double a2pkts, a2rpkts, a2loss; if ((a1->argus_far.flow.ip_flow.ip_p == IPPROTO_TCP) && (a2->argus_far.flow.ip_flow.ip_p == IPPROTO_TCP)) { unsigned int a1DSRStatus = 0, a2DSRStatus = 0; struct ArgusFarHeaderStruct *a1farhdr[32], *a2farhdr[32]; struct ArgusTCPObject *tcp1 = NULL; struct ArgusTCPObject *tcp2 = NULL; a1DSRStatus = ArgusIndexRecord (a1, a1farhdr); a2DSRStatus = ArgusIndexRecord (a2, a2farhdr); if ((a1DSRStatus & ARGUS_TCP_DSR_STATUS) && (a2DSRStatus & ARGUS_TCP_DSR_STATUS)) { tcp1 = (struct ArgusTCPObject *) a1farhdr[ARGUS_TCP_DSR_INDEX]; tcp2 = (struct ArgusTCPObject *) a2farhdr[ARGUS_TCP_DSR_INDEX]; a1pkts = (a1->argus_far.src.count + a1->argus_far.dst.count) * 1.0; a2pkts = (a2->argus_far.src.count + a2->argus_far.dst.count) * 1.0; a1rpkts = (tcp1->src.rpkts + tcp1->dst.rpkts) * 1.0; a2rpkts = (tcp2->src.rpkts + tcp2->dst.rpkts) * 1.0; a1loss = a1rpkts/a1pkts; a2loss = a2rpkts/a2pkts; retn = (a1loss > a2loss) ? 1 : ((a1loss == a2loss) ? 0 : -1); } } return (retn); } int RaSortRate (struct ArgusRecord *a1, struct ArgusRecord *a2) { int src1 = 0, src2 = 0, dst1 = 0, dst2 = 0, retn = 0; struct timeval *start = NULL, *last = NULL; struct timeval timebuf, *time = &timebuf; double sec1, sec2; start = &a1->argus_far.time.start; last = &a1->argus_far.time.last; *time = *last; time->tv_sec -= start->tv_sec; time->tv_usec -= start->tv_usec; if (time->tv_usec < 0) { time->tv_sec--; time->tv_usec += 1000000; } if (time->tv_usec >= 1000000) { time->tv_sec++; time->tv_usec -= 1000000; } sec1 = (double)(time->tv_sec * 1.0) + (double)(time->tv_usec/1000000.0); start = &a2->argus_far.time.start; last = &a2->argus_far.time.last; *time = *last; time->tv_sec -= start->tv_sec; time->tv_usec -= start->tv_usec; if (time->tv_usec < 0) { time->tv_sec--; time->tv_usec += 1000000; } if (time->tv_usec >= 1000000) { time->tv_sec++; time->tv_usec -= 1000000; } sec2 = (double)(time->tv_sec * 1.0) + (double)(time->tv_usec/1000000.0); if (a1->argus_far.src.count > 1) src1 = a1->argus_far.src.count; if (a1->argus_far.dst.count > 1) dst1 = a1->argus_far.dst.count; if (a2->argus_far.src.count > 1) src2 = a2->argus_far.src.count; if (a2->argus_far.dst.count > 1) dst2 = a2->argus_far.dst.count; if (sec1 && sec2) { retn = (((double)(((src1 + dst1) * 1.0)/(double)(sec1 * 1.0)) > (double)(((src2 + dst2) * 1.0)/(double)(sec2 * 1.0))) ? 1 : ((double)(((src1 + dst1) * 1.0)/(double)(sec1 * 1.0)) == (double)(((src2 + dst2) * 1.0)/(double)(sec2 * 1.0))) ? 0 : -1); } else { if (sec1) retn = 1; if (sec2) retn = -1; } return (retn); } int RaSortTranRef (struct ArgusRecord *a1, struct ArgusRecord *a2) { return (a1->argus_far.ArgusTransRefNum - a2->argus_far.ArgusTransRefNum); } int RaSortSeq (struct ArgusRecord *a1, struct ArgusRecord *a2) { return (a1->ahdr.seqNumber - a2->ahdr.seqNumber); } int RaSortSrcByteCount (struct ArgusRecord *a1, struct ArgusRecord *a2) { if (Aflag) return (a1->argus_far.src.appbytes - a2->argus_far.src.appbytes); else return (a1->argus_far.src.bytes - a2->argus_far.src.bytes); } int RaSortDstByteCount (struct ArgusRecord *a1, struct ArgusRecord *a2) { if (Aflag) return (a1->argus_far.dst.appbytes - a2->argus_far.dst.appbytes); else return (a1->argus_far.dst.bytes - a2->argus_far.dst.bytes); } int RaSortPktsCount (struct ArgusRecord *a1, struct ArgusRecord *a2) { return ((a1->argus_far.src.count + a1->argus_far.dst.count) - (a2->argus_far.src.count + a2->argus_far.dst.count)); } int RaSortSrcPktsCount (struct ArgusRecord *a1, struct ArgusRecord *a2) { return (a1->argus_far.src.count - a2->argus_far.src.count); } int RaSortDstPktsCount (struct ArgusRecord *a1, struct ArgusRecord *a2) { return (a1->argus_far.dst.count - a2->argus_far.dst.count); } char RaUserDataStr[MAXSTRLEN]; char * RaGetUserDataString (struct ArgusRecord *argus) { char *retn = RaUserDataStr; char strbuf[MAXSTRLEN], *str = strbuf; char delim = ' '; int len = 0; bzero (RaUserDataStr, MAXSTRLEN); if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) delim = RaFieldDelimiter; if (ArgusSrcUserDataLen > 0) { len = 0; if (ArgusThisFarStatus & ARGUS_SRCUSRDATA_DSR_STATUS) { struct ArgusUserStruct *user = (struct ArgusUserStruct *) ArgusThisFarHdrs[ARGUS_SRCUSRDATA_DSR_INDEX]; len = (user->length - 1) * 4; len = (len < argus->argus_far.src.appbytes) ? len : argus->argus_far.src.appbytes; len = len > ArgusSrcUserDataLen ? ArgusSrcUserDataLen : len; bzero(strbuf, sizeof(strbuf)); if ((len = ArgusEncode (&user->data, NULL, len, str, sizeof(strbuf))) != 0) sprintf (RaUserDataStr, "%cs[%d]=%s", delim, len, str); } else if (delim != ' ') sprintf (&RaUserDataStr[strlen(RaUserDataStr)], "%c", delim); if (delim == ' ') sprintf (&RaUserDataStr[strlen(RaUserDataStr)], "%*s", (ArgusSrcUserDataLen - len) + 1, " "); } if (ArgusDstUserDataLen > 0) { len = 0; if (ArgusThisFarStatus & ARGUS_DSTUSRDATA_DSR_STATUS) { struct ArgusUserStruct *user = (struct ArgusUserStruct *) ArgusThisFarHdrs[ARGUS_DSTUSRDATA_DSR_INDEX]; len = (user->length - 1) * 4; len = (len < argus->argus_far.dst.appbytes) ? len : argus->argus_far.dst.appbytes; len = len > ArgusDstUserDataLen ? ArgusDstUserDataLen : len; bzero(strbuf, sizeof(strbuf)); if ((len = ArgusEncode (&user->data, NULL, len, str, sizeof(strbuf))) != 0) sprintf (&RaUserDataStr[strlen(RaUserDataStr)], "%cd[%d]=%s", delim, len, str); } else if (delim != ' ') sprintf (&RaUserDataStr[strlen(RaUserDataStr)], "%c", delim); } return (retn); } /* Format is "bins[L]:range" where range is value-value value is %d[ums] */ int RaHistoTimeParse (char *); int *RaHistoTimeValues = NULL; int RaHistoStart = 0; int RaHistoEnd = 0; int RaHistoBins = 0; int RaHistoTimeParse (char *str) { int RaHistoTimeLog = 0; double RaHistoBinSize = 0.0, RaHistoLogInterval = 0.0; double RaHistoStartLog = 0.0, RaHistoEndLog = 0.0; int retn = 0, i; char *ptr, *vptr, tmpbuf[64], *tmp = tmpbuf; bzero (tmpbuf, 64); strcpy (tmpbuf, str); if ((ptr = strchr (tmp, ':')) != NULL) { *ptr++ = '\0'; vptr = ptr; if (strchr (tmp, 'L')) RaHistoTimeLog++; if (isdigit((int)*tmp)) if ((RaHistoBins = atoi(tmp)) < 0) return (retn); if ((ptr = strchr (vptr, '-')) != NULL) { *ptr++ = '\0'; if ((RaHistoStart = atoi(vptr)) < 0) return (retn); if ((RaHistoEnd = atoi(ptr)) < 0) return (retn); while (isdigit((int)*ptr)) ptr++; switch (*ptr) { case 'u': RaHistoStart *= 1; RaHistoEnd *= 1; break; case 'm': RaHistoStart *= 1000; RaHistoEnd *= 1000; break; case 's': RaHistoStart *= 1000000; RaHistoEnd *= 1000000; break; case 'M': RaHistoStart *= 60000000; RaHistoEnd *= 60000000; break; case '\0': break; default: return (retn); } retn++; RaHistoTimeSeries = RaHistoBins; if ((RaHistoTimeValues = (int *) ArgusCalloc (RaHistoBins + 1, sizeof(int))) != NULL) { for (i = 0; i < RaHistoBins; i++) { if (RaHistoTimeLog) { if (i == 0) { if (RaHistoStart > 0) RaHistoStartLog = log10(RaHistoStart); RaHistoEndLog = log10(RaHistoEnd); RaHistoLogInterval = ((RaHistoEndLog - RaHistoStartLog)/(RaHistoBins * 1.0)); } RaHistoTimeValues[i] = RaHistoStart + pow(10.0, RaHistoLogInterval * i); } else { if (i == 0) RaHistoBinSize = ((RaHistoEnd - RaHistoStart) * 1.0) / RaHistoBins * 1.0; RaHistoTimeValues[i] = RaHistoStart + RaHistoBinSize * (i + 1); } } RaHistoTimeValues[RaHistoBins] = RaHistoEnd; } else ArgusLog (LOG_ERR, "RaHistoTimeParse: ArgusCalloc %s\n", strerror(errno)); } } return (retn); } argus-clients-2.0.6.fixes.1/common/argus_filter.c0000664000076600007660000040626507640476616015431 /* * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * Copyright (c) 1990, 1991, 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)bpf.c 7.5 (Berkeley) 7/15/91 * */ #ifndef ArgusFilter #define ArgusFilter #endif #include #include #include #include #include #include #include #if defined(HAVE_SOLARIS) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef sun #include #endif #include extern void ArgusLog (int, char *, ...); #if defined(sparc) || defined(mips) || defined(ibm032) || defined(__alpha)\ || defined(AIX) #define BPF_ALIGN #endif #ifndef BPF_ALIGN #define EXTRACT_SHORT(p) ((arg_uint16)ntohs(*(arg_uint16 *)p)) #define EXTRACT_LONG(p) (ntohl(*(unsigned int *)p)) #else #define EXTRACT_SHORT(p)\ ((arg_uint16)\ ((arg_uint16)*((u_char *)p+0)<<8|\ (arg_uint16)*((u_char *)p+1)<<0)) #define EXTRACT_LONG(p)\ ((unsigned int)*((u_char *)p+0)<<24|\ (unsigned int)*((u_char *)p+1)<<16|\ (unsigned int)*((u_char *)p+2)<<8|\ (unsigned int)*((u_char *)p+3)<<0) #endif #include /* Hex digit to integer. */ static inline int xdtoi(int c) { if (isdigit(c)) return c - '0'; else if (islower(c)) return c - 'a' + 10; else return c - 'A' + 10; } /* * Execute the filter program starting at pc on the packet p * wirelen is the length of the original packet * buflen is the amount of data present */ unsigned int argus_filter (struct bpf_insn *pc, struct ArgusCanonicalRecord *canon) { return argus_filter_orig (pc, (u_char *)canon, sizeof(*canon), sizeof(*canon)); } unsigned int argus_filter_orig (pc, p, wirelen, buflen) struct bpf_insn *pc; u_char *p; int wirelen, buflen; { unsigned int A = 0, X = 0; int k; int mem [BPF_MEMWORDS]; if (pc == 0) /* * No filter means accept all. */ return (unsigned int) -1; --pc; while (1) { ++pc; switch (pc->code) { default: #ifdef KERNEL return 0; #else abort(); #endif case BPF_RET|BPF_K: return (unsigned int)pc->k; case BPF_RET|BPF_A: return (unsigned int)A; case BPF_LD|BPF_W|BPF_ABS: k = pc->k; if (k + sizeof(int) > buflen) { #ifdef KERNEL int merr; if (buflen != 0) return 0; A = m_xword((struct mbuf *)p, k, &merr); if (merr != 0) return 0; continue; #else return 0; #endif } A = EXTRACT_LONG(&p[k]); continue; case BPF_LD|BPF_H|BPF_ABS: k = pc->k; if (k + sizeof(short) > buflen) { #ifdef KERNEL int merr; if (buflen != 0) return 0; A = m_xhalf((struct mbuf *)p, k, &merr); continue; #else return 0; #endif } A = EXTRACT_SHORT(&p[k]); continue; case BPF_LD|BPF_B|BPF_ABS: k = pc->k; if (k >= buflen) { #ifdef KERNEL struct mbuf *m; if (buflen != 0) return 0; m = (struct mbuf *)p; MINDEX(m, k); A = mtod(m, u_char *)[k]; continue; #else return 0; #endif } A = p[k]; continue; case BPF_LD|BPF_W|BPF_LEN: A = wirelen; continue; case BPF_LDX|BPF_W|BPF_LEN: X = wirelen; continue; case BPF_LD|BPF_W|BPF_IND: k = X + pc->k; if (k + sizeof(int) > buflen) { #ifdef KERNEL int merr; if (buflen != 0) return 0; A = m_xword((struct mbuf *)p, k, &merr); if (merr != 0) return 0; continue; #else return 0; #endif } A = EXTRACT_LONG(&p[k]); continue; case BPF_LD|BPF_H|BPF_IND: k = X + pc->k; if (k + sizeof(short) > buflen) { #ifdef KERNEL int merr; if (buflen != 0) return 0; A = m_xhalf((struct mbuf *)p, k, &merr); if (merr != 0) return 0; continue; #else return 0; #endif } A = EXTRACT_SHORT(&p[k]); continue; case BPF_LD|BPF_B|BPF_IND: k = X + pc->k; if (k >= buflen) { #ifdef KERNEL struct mbuf *m; if (buflen != 0) return 0; m = (struct mbuf *)p; MINDEX(m, k); A = mtod(m, char *)[k]; continue; #else return 0; #endif } A = p[k]; continue; case BPF_LDX|BPF_MSH|BPF_B: k = pc->k; if (k >= buflen) { #ifdef KERNEL struct mbuf *m; if (buflen != 0) return 0; m = (struct mbuf *)p; MINDEX(m, k); X = (mtod(m, char *)[k] & 0xf) << 2; continue; #else return 0; #endif } X = (p[pc->k] & 0xf) << 2; continue; case BPF_LD|BPF_IMM: A = pc->k; continue; case BPF_LDX|BPF_IMM: X = pc->k; continue; case BPF_LD|BPF_MEM: A = mem[pc->k]; continue; case BPF_LDX|BPF_MEM: X = mem[pc->k]; continue; case BPF_ST: mem[pc->k] = A; continue; case BPF_STX: mem[pc->k] = X; continue; case BPF_JMP|BPF_JA: pc += pc->k; continue; case BPF_JMP|BPF_JGT|BPF_K: pc += (A > pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JGE|BPF_K: pc += (A >= pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JEQ|BPF_K: pc += (A == pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JSET|BPF_K: pc += (A & pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JGT|BPF_X: pc += (A > X) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JGE|BPF_X: pc += (A >= X) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JEQ|BPF_X: pc += (A == X) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JSET|BPF_X: pc += (A & X) ? pc->jt : pc->jf; continue; case BPF_ALU|BPF_ADD|BPF_X: A += X; continue; case BPF_ALU|BPF_SUB|BPF_X: A -= X; continue; case BPF_ALU|BPF_MUL|BPF_X: A *= X; continue; case BPF_ALU|BPF_DIV|BPF_X: if (X == 0) return 0; A /= X; continue; case BPF_ALU|BPF_AND|BPF_X: A &= X; continue; case BPF_ALU|BPF_OR|BPF_X: A |= X; continue; case BPF_ALU|BPF_LSH|BPF_X: A <<= X; continue; case BPF_ALU|BPF_RSH|BPF_X: A >>= X; continue; case BPF_ALU|BPF_ADD|BPF_K: A += pc->k; continue; case BPF_ALU|BPF_SUB|BPF_K: A -= pc->k; continue; case BPF_ALU|BPF_MUL|BPF_K: A *= pc->k; continue; case BPF_ALU|BPF_DIV|BPF_K: A /= pc->k; continue; case BPF_ALU|BPF_AND|BPF_K: A &= pc->k; continue; case BPF_ALU|BPF_OR|BPF_K: A |= pc->k; continue; case BPF_ALU|BPF_LSH|BPF_K: A <<= pc->k; continue; case BPF_ALU|BPF_RSH|BPF_K: A >>= pc->k; continue; case BPF_ALU|BPF_NEG: A = -A; continue; case BPF_MISC|BPF_TAX: X = A; continue; case BPF_MISC|BPF_TXA: A = X; continue; } } } #ifdef KERNEL /* * Return true if the 'fcode' is a valid filter program. * The constraints are that each jump be forward and to a valid * code. The code must terminate with either an accept or reject. * 'valid' is an array for use by the routine (it must be at least * 'len' bytes long). * * The kernel needs to be able to verify an application's filter code. * Otherwise, a bogus program could easily crash the system. */ int bpf_validate(f, len) struct bpf_insn *f; int len; { int i; struct bpf_insn *p; for (i = 0; i < len; ++i) { /* * Check that that jumps are forward, and within * the code block. */ p = &f[i]; if (BPF_CLASS(p->code) == BPF_JMP) { int from = i + 1; if (BPF_OP(p->code) == BPF_JA) { if (from + p->k >= len) return 0; } else if (from + p->jt >= len || from + p->jf >= len) return 0; } /* * Check that memory operations use valid addresses. */ if ((BPF_CLASS(p->code) == BPF_ST || (BPF_CLASS(p->code) == BPF_LD && (p->code & 0xe0) == BPF_MEM)) && (p->k >= BPF_MEMWORDS || p->k < 0)) return 0; /* * Check for constant division by 0. */ if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) return 0; } return BPF_CLASS(f[len - 1].code) == BPF_RET; } #endif /* * Copyright (c) 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* #include */ #ifndef __GNUC__ #define inline #endif static inline int skip_space(FILE *); static inline int skip_line(FILE *); static inline int skip_space(f) FILE *f; { int c; do { c = getc(f); } while (isspace(c) && c != '\n'); return c; } static inline int skip_line(f) FILE *f; { int c; do c = getc(f); while (c != '\n' && c != EOF); return c; } #include struct argus_etherent * argus_next_etherent(FILE *fp) { int c, d, i; char *bp; static struct argus_etherent e; static int nline = 1; top: while (nline) { /* Find addr */ c = skip_space(fp); if (c == '\n') continue; /* If this is a comment, or first thing on line cannot be ethernet address, skip the line. */ else if (!isxdigit(c)) c = skip_line(fp); else { /* must be the start of an address */ for (i = 0; i < 6; i += 1) { d = xdtoi(c); c = getc(fp); if (c != ':') { d <<= 4; d |= xdtoi(c); c = getc(fp); } e.addr[i] = d; if (c != ':') break; c = getc(fp); } nline = 0; } if (c == EOF) return 0; } /* If we started a new line, 'c' holds the char past the ether addr, which we assume is white space. If we are continuing a line, 'c' is garbage. In either case, we can throw it away. */ c = skip_space(fp); if (c == '\n') { nline = 1; goto top; } else if (c == '#') { (void)skip_line(fp); nline = 1; goto top; } else if (c == EOF) return 0; /* Must be a name. */ bp = e.name; /* Use 'd' to prevent argus_strbuffer overflow. */ d = sizeof(e.name) - 1; do { *bp++ = c; c = getc(fp); } while (!isspace(c) && c != EOF && --d > 0); *bp = '\0'; if (c == '\n') nline = 1; return &e; } /* * Copyright (c) 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef HAVE_SOLARIS #include #endif /* Not all systems have IFF_LOOPBACK */ #ifdef IFF_LOOPBACK #define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK) #else #define ISLOOPBACK(p) (strcmp((p)->ifr_name, "lo0") == 0) #endif #if !defined(__OpenBSD__) #include #endif /* * Return the name of a network interface attached to the system, or NULL * if none can be found. The interface must be configured up; the * lowest unit number is preferred; loopback is ignored. */ char * argus_lookupdev(ebuf) char *ebuf; { int fd, minunit, n; char *cp; struct ifreq *ifrp, *ifend, *ifnext, *mp; struct ifconf ifc; struct ifreq ibuf[16], ifr; static char device[sizeof(ifrp->ifr_name) + 1]; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { (void)sprintf(ebuf, "socket: %s", argus_strerror(errno)); return (NULL); } ifc.ifc_len = sizeof ibuf; ifc.ifc_buf = (caddr_t)ibuf; if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || ifc.ifc_len < sizeof(struct ifreq)) { (void)sprintf(ebuf, "SIOCGIFCONF: %s", argus_strerror(errno)); (void)close(fd); return (NULL); } ifrp = ibuf; ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); mp = NULL; minunit = 666; for (; ifrp < ifend; ifrp = ifnext) { #if BSD - 0 >= 199006 n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); if (n < sizeof(*ifrp)) ifnext = ifrp + 1; else ifnext = (struct ifreq *)((char *)ifrp + n); if (ifrp->ifr_addr.sa_family != AF_INET) continue; #else ifnext = ifrp + 1; #endif /* * Need a template to preserve address info that is * used below to locate the next entry. (Otherwise, * SIOCGIFFLAGS stomps over it because the requests * are returned in a union.) */ strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) { (void)sprintf(ebuf, "SIOCGIFFLAGS: %s", argus_strerror(errno)); (void)close(fd); return (NULL); } /* Must be up and not the loopback */ if ((ifr.ifr_flags & IFF_UP) == 0 || ISLOOPBACK(&ifr)) continue; for (cp = ifrp->ifr_name; !isdigit((int)*cp); ++cp) continue; n = atoi(cp); if (n < minunit) { minunit = n; mp = ifrp; } } (void)close(fd); if (mp == NULL) { (void)strcpy(ebuf, "no suitable device found"); return (NULL); } (void)strncpy(device, mp->ifr_name, sizeof(device) - 1); device[sizeof(device) - 1] = '\0'; return (device); } int argus_lookupnet(char *device, unsigned int *netp, unsigned int *maskp, char *ebuf) { int fd; struct sockaddr_in *sin; struct ifreq ifr; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { (void)sprintf(ebuf, "socket: %s", argus_strerror(errno)); return (-1); } (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { (void)sprintf(ebuf, "SIOCGIFADDR: %s: %s", device, argus_strerror(errno)); (void)close(fd); return (-1); } sin = (struct sockaddr_in *)&ifr.ifr_addr; *netp = sin->sin_addr.s_addr; if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { (void)sprintf(ebuf, "SIOCGIFNETMASK: %s: %s", device, argus_strerror(errno)); (void)close(fd); return (-1); } (void)close(fd); *maskp = sin->sin_addr.s_addr; if (*maskp == 0) { if (IN_CLASSA(*netp)) *maskp = IN_CLASSA_NET; else if (IN_CLASSB(*netp)) *maskp = IN_CLASSB_NET; else if (IN_CLASSC(*netp)) *maskp = IN_CLASSC_NET; else { (void)sprintf(ebuf, "inet class for 0x%x unknown", *netp); return (-1); } } *netp &= *maskp; return (0); } #ifndef HAVE_SYS_ERRLIST static char argus_error[20]; #endif char * argus_strerror(int errnum) { #ifndef HAVE_SYS_ERRLIST extern int sys_nerr; extern char *sys_errlist[]; if ((unsigned int)errnum < sys_nerr) return ((char *) sys_errlist[errnum]); (void)sprintf(argus_error, "Unknown error: %d", errnum); return (argus_error); #else return (strerror(errnum)); #endif } /* * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Optimization module for tcpdump intermediate representation. */ #ifdef __osf__ #include #endif #include #ifdef linux #include #endif #define BITS_PER_WORD (8*sizeof(unsigned int)) #define A_ATOM BPF_MEMWORDS #define X_ATOM (BPF_MEMWORDS+1) #define NOP -1 /* * This define is used to represent *both* the accumulator and * x register in use-def computations. * Currently, the use-def code assumes only one definition per instruction. */ #define AX_ATOM N_ATOMS /* * A flag to indicate that further optimization is needed. * Iterative passes are continued until a given pass yields no * branch movement. */ static int done; /* * A block is marked if only if its mark equals the current mark. * Rather than traverse the code array, marking each item, 'cur_mark' is * incremented. This automatically makes each element unmarked. */ static int cur_mark; #define isMarked(p) ((p)->mark == cur_mark) #define unMarkAll() cur_mark += 1 #define Mark(p) ((p)->mark = cur_mark) static void opt_init(struct ablock *); static void opt_cleanup(void); static void make_marks(struct ablock *); static void mark_code(struct ablock *); static void intern_blocks(struct ablock *); static int eq_slist(struct slist *, struct slist *); static void find_levels_r(struct ablock *); static void find_levels(struct ablock *); static void find_dom(struct ablock *); static void propedom(struct edge *); static void find_edom(struct ablock *); static void find_closure(struct ablock *); static int atomuse(struct stmt *); static int atomdef(struct stmt *); static void compute_local_ud(struct ablock *); static void find_ud(struct ablock *); static void init_val(void); static int F(int, int, int); static inline void vstore(struct stmt *, int *, int, int); static void opt_blk(struct ablock *, int); static int use_conflict(struct ablock *, struct ablock *); static void opt_j(struct edge *); static void or_pullup(struct ablock *); static void and_pullup(struct ablock *); static void opt_blks(struct ablock *, int); static inline void link_inedge(struct edge *, struct ablock *); static void find_inedges(struct ablock *); static void opt_root(struct ablock **); static void opt_loop(struct ablock *, int); static void fold_op(struct stmt *, int, int); static inline struct slist *this_op(struct slist *); static void opt_not(struct ablock *); static void opt_peep(struct ablock *); static void opt_stmt(struct stmt *, int[], int); static void deadstmt(struct stmt *, struct stmt *[]); static void opt_deadstores(struct ablock *); static void opt_blk(struct ablock *, int); static int use_conflict(struct ablock *, struct ablock *); static void opt_j(struct edge *); static struct ablock *fold_edge(struct ablock *, struct edge *); static inline int eq_blk(struct ablock *, struct ablock *); static int slength(struct slist *); static int count_blocks(struct ablock *); static void number_blks_r(struct ablock *); static int count_stmts(struct ablock *); static int convert_code_r(struct ablock *); static int n_blocks; struct ablock **blocks; static int n_edges; struct edge **edges; /* * A bit vector set representation of the dominators. * We round up the set size to the next power of two. */ static int nodewords; static int edgewords; struct ablock **levels; unsigned int *space; /* * True if a is in uset {p} */ #define SET_MEMBER(p, a) \ ((p)[(a) / BITS_PER_WORD] & (1 << ((a) % BITS_PER_WORD))) /* * Add 'a' to uset p. */ #define SET_INSERT(p, a) \ (p)[(a) / BITS_PER_WORD] |= (1 << ((a) % BITS_PER_WORD)) /* * Delete 'a' from uset p. */ #define SET_DELETE(p, a) \ (p)[(a) / BITS_PER_WORD] &= ~(1 << ((a) % BITS_PER_WORD)) /* * a := a intersect b */ #define SET_INTERSECT(a, b, n)\ {\ register unsigned int *_x = a, *_y = b;\ register int _n = n;\ while (--_n >= 0) *_x++ &= *_y++;\ } /* * a := a - b */ #define SET_SUBTRACT(a, b, n)\ {\ register unsigned int *_x = a, *_y = b;\ register int _n = n;\ while (--_n >= 0) *_x++ &=~ *_y++;\ } /* * a := a union b */ #define SET_UNION(a, b, n)\ {\ register unsigned int *_x = a, *_y = b;\ register int _n = n;\ while (--_n >= 0) *_x++ |= *_y++;\ } static uset all_dom_sets; static uset all_closure_sets; static uset all_edge_sets; #ifndef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) #endif static void find_levels_r(b) struct ablock *b; { int level; if (isMarked(b)) return; Mark(b); b->link = 0; if (JT(b)) { find_levels_r(JT(b)); find_levels_r(JF(b)); level = MAX(JT(b)->level, JF(b)->level) + 1; } else level = 0; b->level = level; b->link = levels[level]; levels[level] = b; } /* * Level graph. The levels go from 0 at the leaves to * N_LEVELS at the root. The levels[] array points to the * first node of the level list, whose elements are linked * with the 'link' field of the struct ablock. */ static void find_levels(root) struct ablock *root; { memset((char *)levels, 0, n_blocks * sizeof(*levels)); unMarkAll(); find_levels_r(root); } /* * Find dominator relationships. * Assumes graph has been leveled. */ static void find_dom(root) struct ablock *root; { int i; struct ablock *b; unsigned int *x; /* * Initialize sets to contain all nodes. */ x = all_dom_sets; i = n_blocks * nodewords; while (--i >= 0) *x++ = ~0; /* Root starts off empty. */ for (i = nodewords; --i >= 0;) root->dom[i] = 0; /* root->level is the highest level no found. */ for (i = root->level; i >= 0; --i) { for (b = levels[i]; b; b = b->link) { SET_INSERT(b->dom, b->id); if (JT(b) == 0) continue; SET_INTERSECT(JT(b)->dom, b->dom, nodewords); SET_INTERSECT(JF(b)->dom, b->dom, nodewords); } } } static void propedom(ep) struct edge *ep; { SET_INSERT(ep->edom, ep->id); if (ep->succ) { SET_INTERSECT(ep->succ->et.edom, ep->edom, edgewords); SET_INTERSECT(ep->succ->ef.edom, ep->edom, edgewords); } } /* * Compute edge dominators. * Assumes graph has been leveled and predecessors established. */ static void find_edom(root) struct ablock *root; { int i; uset x; struct ablock *b; x = all_edge_sets; for (i = n_edges * edgewords; --i >= 0; ) x[i] = ~0; /* root->level is the highest level no found. */ memset(root->et.edom, 0, edgewords * sizeof(*(uset)0)); memset(root->ef.edom, 0, edgewords * sizeof(*(uset)0)); for (i = root->level; i >= 0; --i) { for (b = levels[i]; b != 0; b = b->link) { propedom(&b->et); propedom(&b->ef); } } } /* * Find the backwards transitive closure of the flow graph. These sets * are backwards in the sense that we find the set of nodes that reach * a given node, not the set of nodes that can be reached by a node. * * Assumes graph has been leveled. */ static void find_closure(root) struct ablock *root; { int i; struct ablock *b; /* * Initialize sets to contain no nodes. */ memset((char *)all_closure_sets, 0, n_blocks * nodewords * sizeof(*all_closure_sets)); /* root->level is the highest level no found. */ for (i = root->level; i >= 0; --i) { for (b = levels[i]; b; b = b->link) { SET_INSERT(b->closure, b->id); if (JT(b) == 0) continue; SET_UNION(JT(b)->closure, b->closure, nodewords); SET_UNION(JF(b)->closure, b->closure, nodewords); } } } /* * Return the register number that is used by s. If A and X are both * used, return AX_ATOM. If no register is used, return -1. * * The implementation should probably change to an array access. */ static int atomuse(s) struct stmt *s; { register int c = s->code; if (c == NOP) return -1; switch (BPF_CLASS(c)) { case BPF_RET: return (BPF_RVAL(c) == BPF_A) ? A_ATOM : (BPF_RVAL(c) == BPF_X) ? X_ATOM : -1; case BPF_LD: case BPF_LDX: return (BPF_MODE(c) == BPF_IND) ? X_ATOM : (BPF_MODE(c) == BPF_MEM) ? s->k : -1; case BPF_ST: return A_ATOM; case BPF_STX: return X_ATOM; case BPF_JMP: case BPF_ALU: if (BPF_SRC(c) == BPF_X) return AX_ATOM; return A_ATOM; case BPF_MISC: return BPF_MISCOP(c) == BPF_TXA ? X_ATOM : A_ATOM; } abort(); /* NOTREACHED */ } /* * Return the register number that is defined by 's'. We assume that * a single stmt cannot define more than one register. If no register * is defined, return -1. * * The implementation should probably change to an array access. */ static int atomdef(s) struct stmt *s; { if (s->code == NOP) return -1; switch (BPF_CLASS(s->code)) { case BPF_LD: case BPF_ALU: return A_ATOM; case BPF_LDX: return X_ATOM; case BPF_ST: case BPF_STX: return s->k; case BPF_MISC: return BPF_MISCOP(s->code) == BPF_TAX ? X_ATOM : A_ATOM; } return -1; } static void compute_local_ud(b) struct ablock *b; { struct slist *s; atomset def = 0, use = 0, kill = 0; int atom; for (s = b->stmts; s; s = s->next) { if (s->s.code == NOP) continue; atom = atomuse(&s->s); if (atom >= 0) { if (atom == AX_ATOM) { if (!ATOMELEM(def, X_ATOM)) use |= ATOMMASK(X_ATOM); if (!ATOMELEM(def, A_ATOM)) use |= ATOMMASK(A_ATOM); } else if (atom < N_ATOMS) { if (!ATOMELEM(def, atom)) use |= ATOMMASK(atom); } else abort(); } atom = atomdef(&s->s); if (atom >= 0) { if (!ATOMELEM(use, atom)) kill |= ATOMMASK(atom); def |= ATOMMASK(atom); } } if (!ATOMELEM(def, A_ATOM) && BPF_CLASS(b->s.code) == BPF_JMP) use |= ATOMMASK(A_ATOM); b->def = def; b->kill = kill; b->in_use = use; } /* * Assume graph is already leveled. */ static void find_ud(root) struct ablock *root; { int i, maxlevel; struct ablock *p; /* * root->level is the highest level no found; * count down from there. */ maxlevel = root->level; for (i = maxlevel; i >= 0; --i) for (p = levels[i]; p; p = p->link) { compute_local_ud(p); p->out_use = 0; } for (i = 1; i <= maxlevel; ++i) { for (p = levels[i]; p; p = p->link) { p->out_use |= JT(p)->in_use | JF(p)->in_use; p->in_use |= p->out_use &~ p->kill; } } } /* * These data structures are used in a Cocke and Shwarz style * value numbering scheme. Since the flowgraph is acyclic, * exit values can be propagated from a node's predecessors * provided it is uniquely defined. */ struct valnode { int code; int v0, v1; int val; struct valnode *next; }; #define MODULUS 213 static struct valnode *hashtbl[MODULUS]; static int curval; static int maxval; /* Integer constants mapped with the load immediate opcode. */ #define K(i) F(BPF_LD|BPF_IMM|BPF_W, i, 0L) struct vmapinfo { int is_const; int const_val; }; struct vmapinfo *vmap; struct valnode *vnode_base; struct valnode *next_vnode; static void init_val() { curval = 0; next_vnode = vnode_base; memset((char *)vmap, 0, maxval * sizeof(*vmap)); memset((char *)hashtbl, 0, sizeof hashtbl); } /* Because we really don't have an IR, this stuff is a little messy. */ static int F(code, v0, v1) int code; int v0, v1; { u_int hash; int val; struct valnode *p; hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8); hash %= MODULUS; for (p = hashtbl[hash]; p; p = p->next) if (p->code == code && p->v0 == v0 && p->v1 == v1) return p->val; val = ++curval; if (BPF_MODE(code) == BPF_IMM && (BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) { vmap[val].const_val = v0; vmap[val].is_const = 1; } p = next_vnode++; p->val = val; p->code = code; p->v0 = v0; p->v1 = v1; p->next = hashtbl[hash]; hashtbl[hash] = p; return val; } static inline void vstore(s, valp, newval, alter) struct stmt *s; int *valp; int newval; int alter; { if (alter && *valp == newval) s->code = NOP; else *valp = newval; } static void fold_op(s, v0, v1) struct stmt *s; int v0, v1; { int a, b; a = vmap[v0].const_val; b = vmap[v1].const_val; switch (BPF_OP(s->code)) { case BPF_ADD: a += b; break; case BPF_SUB: a -= b; break; case BPF_MUL: a *= b; break; case BPF_DIV: if (b == 0) ArgusLog(LOG_ERR, "division by zero"); a /= b; break; case BPF_AND: a &= b; break; case BPF_OR: a |= b; break; case BPF_LSH: a <<= b; break; case BPF_RSH: a >>= b; break; case BPF_NEG: a = -a; break; default: abort(); } s->k = a; s->code = BPF_LD|BPF_IMM; done = 0; } static inline struct slist * this_op(s) struct slist *s; { while (s != 0 && s->s.code == NOP) s = s->next; return s; } static void opt_not(b) struct ablock *b; { struct ablock *tmp = JT(b); JT(b) = JF(b); JF(b) = tmp; } static void opt_peep(b) struct ablock *b; { struct slist *s; struct slist *next, *last; int val; int v; s = b->stmts; if (s == 0) return; last = s; while (1) { s = this_op(s); if (s == 0) break; next = this_op(s->next); if (next == 0) break; last = next; /* * st M[k] --> st M[k] * ldx M[k] tax */ if (s->s.code == BPF_ST && next->s.code == (BPF_LDX|BPF_MEM) && s->s.k == next->s.k) { done = 0; next->s.code = BPF_MISC|BPF_TAX; } /* * ld #k --> ldx #k * tax txa */ if (s->s.code == (BPF_LD|BPF_IMM) && next->s.code == (BPF_MISC|BPF_TAX)) { s->s.code = BPF_LDX|BPF_IMM; next->s.code = BPF_MISC|BPF_TXA; done = 0; } /* * This is an ugly special case, but it happens * when you say tcp[k] or udp[k] where k is a constant. */ if (s->s.code == (BPF_LD|BPF_IMM)) { struct slist *add, *tax, *ild; /* * Check that X isn't used on exit from this * block (which the optimizer might cause). * We know the code generator won't generate * any local dependencies. */ if (ATOMELEM(b->out_use, X_ATOM)) break; if (next->s.code != (BPF_LDX|BPF_MSH|BPF_B)) add = next; else add = this_op(next->next); if (add == 0 || add->s.code != (BPF_ALU|BPF_ADD|BPF_X)) break; tax = this_op(add->next); if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX)) break; ild = this_op(tax->next); if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD || BPF_MODE(ild->s.code) != BPF_IND) break; /* * XXX We need to check that X is not * subsequently used. We know we can eliminate the * accumulator modifications since it is defined * by the last stmt of this sequence. * * We want to turn this sequence: * * (004) ldi #0x2 {s} * (005) ldxms [14] {next} -- optional * (006) addx {add} * (007) tax {tax} * (008) ild [x+0] {ild} * * into this sequence: * * (004) nop * (005) ldxms [14] * (006) nop * (007) nop * (008) ild [x+2] * */ ild->s.k += s->s.k; s->s.code = NOP; add->s.code = NOP; tax->s.code = NOP; done = 0; } s = next; } /* * If we have a subtract to do a comparison, and the X register * is a known constant, we can merge this value into the * comparison. */ if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X) && !ATOMELEM(b->out_use, A_ATOM)) { val = b->val[X_ATOM]; if (vmap[val].is_const) { b->s.k += vmap[val].const_val; last->s.code = NOP; done = 0; } else if (b->s.k == 0) { /* * sub x -> nop * j #0 j x */ last->s.code = NOP; b->s.code = BPF_CLASS(b->s.code) | BPF_OP(b->s.code) | BPF_X; done = 0; } } /* * Likewise, a constant subtract can be simplified. */ else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K) && !ATOMELEM(b->out_use, A_ATOM)) { b->s.k += last->s.k; last->s.code = NOP; done = 0; } /* * and #k nop * jeq #0 -> jset #k */ if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) && !ATOMELEM(b->out_use, A_ATOM) && b->s.k == 0) { b->s.k = last->s.k; b->s.code = BPF_JMP|BPF_K|BPF_JSET; last->s.code = NOP; done = 0; opt_not(b); } /* * If the accumulator is a known constant, we can compute the * comparison result. */ val = b->val[A_ATOM]; if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) { v = vmap[val].const_val; switch (BPF_OP(b->s.code)) { case BPF_JEQ: v = v == b->s.k; break; case BPF_JGT: v = v > b->s.k; break; case BPF_JGE: v = v >= b->s.k; break; case BPF_JSET: v &= b->s.k; break; default: abort(); } if (JF(b) != JT(b)) done = 0; if (v) JF(b) = JT(b); else JT(b) = JF(b); } } /* * Compute the symbolic value of expression of 's', and update * anything it defines in the value table 'val'. If 'alter' is true, * do various optimizations. This code would be cleaner if symbolic * evaluation and code transformations weren't folded together. */ static void opt_stmt(s, val, alter) struct stmt *s; int val[]; int alter; { int op; int v; switch (s->code) { case BPF_LD|BPF_ABS|BPF_W: case BPF_LD|BPF_ABS|BPF_H: case BPF_LD|BPF_ABS|BPF_B: v = F(s->code, s->k, 0L); vstore(s, &val[A_ATOM], v, alter); break; case BPF_LD|BPF_IND|BPF_W: case BPF_LD|BPF_IND|BPF_H: case BPF_LD|BPF_IND|BPF_B: v = val[X_ATOM]; if (alter && vmap[v].is_const) { s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code); s->k += vmap[v].const_val; v = F(s->code, s->k, 0L); done = 0; } else v = F(s->code, s->k, v); vstore(s, &val[A_ATOM], v, alter); break; case BPF_LD|BPF_LEN: v = F(s->code, 0L, 0L); vstore(s, &val[A_ATOM], v, alter); break; case BPF_LD|BPF_IMM: v = K(s->k); vstore(s, &val[A_ATOM], v, alter); break; case BPF_LDX|BPF_IMM: v = K(s->k); vstore(s, &val[X_ATOM], v, alter); break; case BPF_LDX|BPF_MSH|BPF_B: v = F(s->code, s->k, 0L); vstore(s, &val[X_ATOM], v, alter); break; case BPF_ALU|BPF_NEG: if (alter && vmap[val[A_ATOM]].is_const) { s->code = BPF_LD|BPF_IMM; s->k = -vmap[val[A_ATOM]].const_val; val[A_ATOM] = K(s->k); } else val[A_ATOM] = F(s->code, val[A_ATOM], 0L); break; case BPF_ALU|BPF_ADD|BPF_K: case BPF_ALU|BPF_SUB|BPF_K: case BPF_ALU|BPF_MUL|BPF_K: case BPF_ALU|BPF_DIV|BPF_K: case BPF_ALU|BPF_AND|BPF_K: case BPF_ALU|BPF_OR|BPF_K: case BPF_ALU|BPF_LSH|BPF_K: case BPF_ALU|BPF_RSH|BPF_K: op = BPF_OP(s->code); if (alter) { if (s->k == 0) { if (op == BPF_ADD || op == BPF_SUB || op == BPF_LSH || op == BPF_RSH || op == BPF_OR) { s->code = NOP; break; } if (op == BPF_MUL || op == BPF_AND) { s->code = BPF_LD|BPF_IMM; val[A_ATOM] = K(s->k); break; } } if (vmap[val[A_ATOM]].is_const) { fold_op(s, val[A_ATOM], K(s->k)); val[A_ATOM] = K(s->k); break; } } val[A_ATOM] = F(s->code, val[A_ATOM], K(s->k)); break; case BPF_ALU|BPF_ADD|BPF_X: case BPF_ALU|BPF_SUB|BPF_X: case BPF_ALU|BPF_MUL|BPF_X: case BPF_ALU|BPF_DIV|BPF_X: case BPF_ALU|BPF_AND|BPF_X: case BPF_ALU|BPF_OR|BPF_X: case BPF_ALU|BPF_LSH|BPF_X: case BPF_ALU|BPF_RSH|BPF_X: op = BPF_OP(s->code); if (alter && vmap[val[X_ATOM]].is_const) { if (vmap[val[A_ATOM]].is_const) { fold_op(s, val[A_ATOM], val[X_ATOM]); val[A_ATOM] = K(s->k); } else { s->code = BPF_ALU|BPF_K|op; s->k = vmap[val[X_ATOM]].const_val; done = 0; val[A_ATOM] = F(s->code, val[A_ATOM], K(s->k)); } break; } /* * Check if we're doing something to an accumulator * that is 0, and simplify. This may not seem like * much of a simplification but it could open up further * optimizations. * XXX We could also check for mul by 1, and -1, etc. */ if (alter && vmap[val[A_ATOM]].is_const && vmap[val[A_ATOM]].const_val == 0) { if (op == BPF_ADD || op == BPF_OR || op == BPF_LSH || op == BPF_RSH || op == BPF_SUB) { s->code = BPF_MISC|BPF_TXA; vstore(s, &val[A_ATOM], val[X_ATOM], alter); break; } else if (op == BPF_MUL || op == BPF_DIV || op == BPF_AND) { s->code = BPF_LD|BPF_IMM; s->k = 0; vstore(s, &val[A_ATOM], K(s->k), alter); break; } else if (op == BPF_NEG) { s->code = NOP; break; } } val[A_ATOM] = F(s->code, val[A_ATOM], val[X_ATOM]); break; case BPF_MISC|BPF_TXA: vstore(s, &val[A_ATOM], val[X_ATOM], alter); break; case BPF_LD|BPF_MEM: v = val[s->k]; if (alter && vmap[v].is_const) { s->code = BPF_LD|BPF_IMM; s->k = vmap[v].const_val; done = 0; } vstore(s, &val[A_ATOM], v, alter); break; case BPF_MISC|BPF_TAX: vstore(s, &val[X_ATOM], val[A_ATOM], alter); break; case BPF_LDX|BPF_MEM: v = val[s->k]; if (alter && vmap[v].is_const) { s->code = BPF_LDX|BPF_IMM; s->k = vmap[v].const_val; done = 0; } vstore(s, &val[X_ATOM], v, alter); break; case BPF_ST: vstore(s, &val[s->k], val[A_ATOM], alter); break; case BPF_STX: vstore(s, &val[s->k], val[X_ATOM], alter); break; } } static void deadstmt(s, last) register struct stmt *s; register struct stmt *last[]; { register int atom; atom = atomuse(s); if (atom >= 0) { if (atom == AX_ATOM) { last[X_ATOM] = 0; last[A_ATOM] = 0; } else last[atom] = 0; } atom = atomdef(s); if (atom >= 0) { if (last[atom]) { done = 0; last[atom]->code = NOP; } last[atom] = s; } } static void opt_deadstores(b) register struct ablock *b; { register struct slist *s; register int atom; struct stmt *last[N_ATOMS]; memset((char *)last, 0, sizeof last); for (s = b->stmts; s != 0; s = s->next) deadstmt(&s->s, last); deadstmt(&b->s, last); for (atom = 0; atom < N_ATOMS; ++atom) if (last[atom] && !ATOMELEM(b->out_use, atom)) { last[atom]->code = NOP; done = 0; } } static void opt_blk(b, do_stmts) struct ablock *b; int do_stmts; { struct slist *s; struct edge *p; int i; int aval; /* * Initialize the atom values. * If we have no predecessors, everything is undefined. * Otherwise, we inherent our values from our predecessors. * If any register has an ambiguous value (i.e. control paths are * merging) give it the undefined value of 0. */ p = b->in_edges; if (p == 0) memset((char *)b->val, 0, sizeof(b->val)); else { memcpy((char *)b->val, (char *)p->pred->val, sizeof(b->val)); while ((p = p->next) != NULL) { for (i = 0; i < N_ATOMS; ++i) if (b->val[i] != p->pred->val[i]) b->val[i] = 0; } } aval = b->val[A_ATOM]; for (s = b->stmts; s; s = s->next) opt_stmt(&s->s, b->val, do_stmts); /* * This is a special case: if we don't use anything from this * block, and we load the accumulator with value that is * already there, eliminate all the statements. */ if (do_stmts && b->out_use == 0 && aval != 0 && b->val[A_ATOM] == aval) b->stmts = 0; else { opt_peep(b); opt_deadstores(b); } /* * Set up values for branch optimizer. */ if (BPF_SRC(b->s.code) == BPF_K) b->oval = K(b->s.k); else b->oval = b->val[X_ATOM]; b->et.code = b->s.code; b->ef.code = -b->s.code; } /* * Return true if any register that is used on exit from 'succ', has * an exit value that is different from the corresponding exit value * from 'b'. */ static int use_conflict(b, succ) struct ablock *b, *succ; { int atom; atomset use = succ->out_use; if (use == 0) return 0; for (atom = 0; atom < N_ATOMS; ++atom) if (ATOMELEM(use, atom)) if (b->val[atom] != succ->val[atom]) return 1; return 0; } static struct ablock * fold_edge(child, ep) struct ablock *child; struct edge *ep; { int sense; int aval0, aval1, oval0, oval1; int code = ep->code; if (code < 0) { code = -code; sense = 0; } else sense = 1; if (child->s.code != code) return 0; aval0 = child->val[A_ATOM]; oval0 = child->oval; aval1 = ep->pred->val[A_ATOM]; oval1 = ep->pred->oval; if (aval0 != aval1) return 0; if (oval0 == oval1) /* * The operands are identical, so the * result is true if a true branch was * taken to get here, otherwise false. */ return sense ? JT(child) : JF(child); if (sense && code == (BPF_JMP|BPF_JEQ|BPF_K)) /* * At this point, we only know the comparison if we * came down the true branch, and it was an equality * comparison with a constant. We rely on the fact that * distinct constants have distinct value numbers. */ return JF(child); return 0; } static void opt_j(ep) struct edge *ep; { register int i, k; register struct ablock *target; if (JT(ep->succ) == 0) return; if (JT(ep->succ) == JF(ep->succ)) { /* * Common branch targets can be eliminated, provided * there is no data dependency. */ if (!use_conflict(ep->pred, ep->succ->et.succ)) { done = 0; ep->succ = JT(ep->succ); } } /* * For each edge dominator that matches the successor of this * edge, promote the edge successor to the its grandchild. * * XXX We violate the set abstraction here in favor a reasonably * efficient loop. */ top: for (i = 0; i < edgewords; ++i) { register unsigned int x = ep->edom[i]; while (x != 0) { k = ffs(x) - 1; x &=~ (1 << k); k += i * BITS_PER_WORD; target = fold_edge(ep->succ, edges[k]); /* * Check that there is no data dependency between * nodes that will be violated if we move the edge. */ if (target != 0 && !use_conflict(ep->pred, target)) { done = 0; ep->succ = target; if (JT(target) != 0) /* * Start over unless we hit a leaf. */ goto top; return; } } } } static void or_pullup(b) struct ablock *b; { int val, at_top; struct ablock *pull; struct ablock **diffp, **samep; struct edge *ep; ep = b->in_edges; if (ep == 0) return; /* * Make sure each predecessor loads the same value. * XXX why? */ val = ep->pred->val[A_ATOM]; for (ep = ep->next; ep != 0; ep = ep->next) if (val != ep->pred->val[A_ATOM]) return; if (JT(b->in_edges->pred) == b) diffp = &JT(b->in_edges->pred); else diffp = &JF(b->in_edges->pred); at_top = 1; while (1) { if (*diffp == 0) return; if (JT(*diffp) != JT(b)) return; if (!SET_MEMBER((*diffp)->dom, b->id)) return; if ((*diffp)->val[A_ATOM] != val) break; diffp = &JF(*diffp); at_top = 0; } samep = &JF(*diffp); while (1) { if (*samep == 0) return; if (JT(*samep) != JT(b)) return; if (!SET_MEMBER((*samep)->dom, b->id)) return; if ((*samep)->val[A_ATOM] == val) break; /* XXX Need to check that there are no data dependencies between dp0 and dp1. Currently, the code generator will not produce such dependencies. */ samep = &JF(*samep); } #ifdef notdef /* XXX This doesn't cover everything. */ for (i = 0; i < N_ATOMS; ++i) if ((*samep)->val[i] != pred->val[i]) return; #endif /* Pull up the node. */ pull = *samep; *samep = JF(pull); JF(pull) = *diffp; /* * At the top of the chain, each predecessor needs to point at the * pulled up node. Inside the chain, there is only one predecessor * to worry about. */ if (at_top) { for (ep = b->in_edges; ep != 0; ep = ep->next) { if (JT(ep->pred) == b) JT(ep->pred) = pull; else JF(ep->pred) = pull; } } else *diffp = pull; done = 0; } static void and_pullup(b) struct ablock *b; { int val, at_top; struct ablock *pull; struct ablock **diffp, **samep; struct edge *ep; ep = b->in_edges; if (ep == 0) return; /* * Make sure each predecessor loads the same value. */ val = ep->pred->val[A_ATOM]; for (ep = ep->next; ep != 0; ep = ep->next) if (val != ep->pred->val[A_ATOM]) return; if (JT(b->in_edges->pred) == b) diffp = &JT(b->in_edges->pred); else diffp = &JF(b->in_edges->pred); at_top = 1; while (1) { if (*diffp == 0) return; if (JF(*diffp) != JF(b)) return; if (!SET_MEMBER((*diffp)->dom, b->id)) return; if ((*diffp)->val[A_ATOM] != val) break; diffp = &JT(*diffp); at_top = 0; } samep = &JT(*diffp); while (1) { if (*samep == 0) return; if (JF(*samep) != JF(b)) return; if (!SET_MEMBER((*samep)->dom, b->id)) return; if ((*samep)->val[A_ATOM] == val) break; /* XXX Need to check that there are no data dependencies between diffp and samep. Currently, the code generator will not produce such dependencies. */ samep = &JT(*samep); } #ifdef notdef /* XXX This doesn't cover everything. */ for (i = 0; i < N_ATOMS; ++i) if ((*samep)->val[i] != pred->val[i]) return; #endif /* Pull up the node. */ pull = *samep; *samep = JT(pull); JT(pull) = *diffp; /* * At the top of the chain, each predecessor needs to point at the * pulled up node. Inside the chain, there is only one predecessor * to worry about. */ if (at_top) { for (ep = b->in_edges; ep != 0; ep = ep->next) { if (JT(ep->pred) == b) JT(ep->pred) = pull; else JF(ep->pred) = pull; } } else *diffp = pull; done = 0; } static void opt_blks(root, do_stmts) struct ablock *root; int do_stmts; { int i, maxlevel; struct ablock *p; init_val(); maxlevel = root->level; for (i = maxlevel; i >= 0; --i) for (p = levels[i]; p; p = p->link) opt_blk(p, do_stmts); if (do_stmts) /* * No point trying to move branches; it can't possibly * make a difference at this point. */ return; for (i = 1; i <= maxlevel; ++i) { for (p = levels[i]; p; p = p->link) { opt_j(&p->et); opt_j(&p->ef); } } for (i = 1; i <= maxlevel; ++i) { for (p = levels[i]; p; p = p->link) { or_pullup(p); and_pullup(p); } } } static inline void link_inedge(parent, child) struct edge *parent; struct ablock *child; { parent->next = child->in_edges; child->in_edges = parent; } static void find_inedges(root) struct ablock *root; { int i; struct ablock *b; for (i = 0; i < n_blocks; ++i) blocks[i]->in_edges = 0; /* * Traverse the graph, adding each edge to the predecessor * list of its successors. Skip the leaves (i.e. level 0). */ for (i = root->level; i > 0; --i) { for (b = levels[i]; b != 0; b = b->link) { link_inedge(&b->et, JT(b)); link_inedge(&b->ef, JF(b)); } } } static void opt_root(b) struct ablock **b; { struct slist *tmp, *s; s = (*b)->stmts; (*b)->stmts = 0; while (BPF_CLASS((*b)->s.code) == BPF_JMP && JT(*b) == JF(*b)) *b = JT(*b); tmp = (*b)->stmts; if (tmp != 0) Argussappend(s, tmp); (*b)->stmts = s; } static void opt_loop(root, do_stmts) struct ablock *root; int do_stmts; { #ifdef BDEBUG if (dflag > 1) opt_dump(root); #endif do { done = 1; find_levels(root); find_dom(root); find_closure(root); find_inedges(root); find_ud(root); find_edom(root); opt_blks(root, do_stmts); #ifdef BDEBUG if (dflag > 1) opt_dump(root); #endif } while (!done); } /* * Optimize the filter code in its dag representation. */ void Argusbpf_optimize(rootp) struct ablock **rootp; { struct ablock *root; root = *rootp; opt_init(root); opt_loop(root, 0); opt_loop(root, 1); intern_blocks(root); opt_root(rootp); opt_cleanup(); } static void make_marks(p) struct ablock *p; { if (!isMarked(p)) { Mark(p); if (BPF_CLASS(p->s.code) != BPF_RET) { make_marks(JT(p)); make_marks(JF(p)); } } } /* * Mark code array such that isMarked(i) is true * only for nodes that are alive. */ static void mark_code(p) struct ablock *p; { cur_mark += 1; make_marks(p); } /* * True iff the two stmt lists load the same value from the packet into * the accumulator. */ static int eq_slist(x, y) struct slist *x, *y; { while (1) { while (x && x->s.code == NOP) x = x->next; while (y && y->s.code == NOP) y = y->next; if (x == 0) return y == 0; if (y == 0) return x == 0; if (x->s.code != y->s.code || x->s.k != y->s.k) return 0; x = x->next; y = y->next; } } static inline int eq_blk(b0, b1) struct ablock *b0, *b1; { if (b0->s.code == b1->s.code && b0->s.k == b1->s.k && b0->et.succ == b1->et.succ && b0->ef.succ == b1->ef.succ) return eq_slist(b0->stmts, b1->stmts); return 0; } static void intern_blocks(root) struct ablock *root; { struct ablock *p; int i, j; int done; top: done = 1; for (i = 0; i < n_blocks; ++i) blocks[i]->link = 0; mark_code(root); for (i = n_blocks - 1; --i >= 0; ) { if (!isMarked(blocks[i])) continue; for (j = i + 1; j < n_blocks; ++j) { if (!isMarked(blocks[j])) continue; if (eq_blk(blocks[i], blocks[j])) { blocks[i]->link = blocks[j]->link ? blocks[j]->link : blocks[j]; break; } } } for (i = 0; i < n_blocks; ++i) { p = blocks[i]; if (JT(p) == 0) continue; if (JT(p)->link) { done = 0; JT(p) = JT(p)->link; } if (JF(p)->link) { done = 0; JF(p) = JF(p)->link; } } if (!done) goto top; } static void opt_cleanup() { free((void *)vnode_base); free((void *)vmap); free((void *)edges); free((void *)space); free((void *)levels); free((void *)blocks); } /* * Return the number of stmts in 's'. */ static int slength(s) struct slist *s; { int n = 0; for (; s; s = s->next) if (s->s.code != NOP) ++n; return n; } /* * Return the number of nodes reachable by 'p'. * All nodes should be initially unmarked. */ static int count_blocks(p) struct ablock *p; { if (p == 0 || isMarked(p)) return 0; Mark(p); return count_blocks(JT(p)) + count_blocks(JF(p)) + 1; } /* * Do a depth first search on the flow graph, numbering the * the basic blocks, and entering them into the 'blocks' array.` */ static void number_blks_r(p) struct ablock *p; { int n; if (p == 0 || isMarked(p)) return; Mark(p); n = n_blocks++; p->id = n; blocks[n] = p; number_blks_r(JT(p)); number_blks_r(JF(p)); } /* * Return the number of stmts in the flowgraph reachable by 'p'. * The nodes should be unmarked before calling. */ static int count_stmts(p) struct ablock *p; { int n; if (p == 0 || isMarked(p)) return 0; Mark(p); n = count_stmts(JT(p)) + count_stmts(JF(p)); return slength(p->stmts) + n + 1; } /* * Allocate memory. All allocation is done before optimization * is begun. A linear bound on the size of all data structures is computed * from the total number of blocks and/or statements. */ static void opt_init(root) struct ablock *root; { unsigned int *p; int i, n, max_stmts; /* * First, count the blocks, so we can malloc an array to map * block number to block. Then, put the blocks into the array. */ unMarkAll(); n = count_blocks(root); blocks = (struct ablock **)malloc(n * sizeof(*blocks)); unMarkAll(); n_blocks = 0; number_blks_r(root); n_edges = 2 * n_blocks; edges = (struct edge **)malloc(n_edges * sizeof(*edges)); /* * The number of levels is bounded by the number of nodes. */ levels = (struct ablock **)malloc(n_blocks * sizeof(*levels)); edgewords = n_edges / (8 * sizeof(unsigned int)) + 1; nodewords = n_blocks / (8 * sizeof(unsigned int)) + 1; /* XXX */ space = (unsigned int *)malloc(2 * n_blocks * nodewords * sizeof(*space) + n_edges * edgewords * sizeof(*space)); p = space; all_dom_sets = p; for (i = 0; i < n; ++i) { blocks[i]->dom = p; p += nodewords; } all_closure_sets = p; for (i = 0; i < n; ++i) { blocks[i]->closure = p; p += nodewords; } all_edge_sets = p; for (i = 0; i < n; ++i) { register struct ablock *b = blocks[i]; b->et.edom = p; p += edgewords; b->ef.edom = p; p += edgewords; b->et.id = i; edges[i] = &b->et; b->ef.id = n_blocks + i; edges[n_blocks + i] = &b->ef; b->et.pred = b; b->ef.pred = b; } max_stmts = 0; for (i = 0; i < n; ++i) max_stmts += slength(blocks[i]->stmts) + 1; /* * We allocate at most 3 value numbers per statement, * so this is an upper bound on the number of valnodes * we'll need. */ maxval = 3 * max_stmts; vmap = (struct vmapinfo *)malloc(maxval * sizeof(*vmap)); vnode_base = (struct valnode *)malloc(maxval * sizeof(*vmap)); } /* * Some pointers used to convert the basic block form of the code, * into the array form that BPF requires. 'fstart' will point to * the malloc'd array while 'ftail' is used during the recursive traversal. */ static struct bpf_insn *fstart; static struct bpf_insn *ftail; extern void ArgusLog (int, char *, ...); #ifdef BDEBUG int bids[1000]; #endif static int convert_code_r(p) struct ablock *p; { struct bpf_insn *dst; struct slist *src; int slen; u_int off; int extrajmps; /* number of extra jumps inserted */ struct slist **offset = NULL; if (p == 0 || isMarked(p)) return (1); Mark(p); if (convert_code_r(JF(p)) == 0) return (0); if (convert_code_r(JT(p)) == 0) return (0); slen = slength(p->stmts); dst = ftail -= (slen + 1 + p->longjt + p->longjf); /* inflate length by any extra jumps */ p->offset = dst - fstart; /* generate offset[] for convenience */ if (slen) { offset = (struct slist **)calloc(sizeof(struct slist *), slen); if (!offset) { ArgusLog (LOG_ERR, "not enough core"); /*NOTREACHED*/ } } src = p->stmts; for (off = 0; off < slen && src; off++) { #if 0 printf("off=%d src=%x\n", off, src); #endif offset[off] = src; src = src->next; } off = 0; for (src = p->stmts; src; src = src->next) { if (src->s.code == NOP) continue; dst->code = (u_short)src->s.code; dst->k = src->s.k; /* fill block-local relative jump */ if ((BPF_CLASS(src->s.code) != BPF_JMP) || (src->s.code == (BPF_JMP|BPF_JA))) { #if 0 if (src->s.jt || src->s.jf) { ArgusLog (LOG_ERR, "illegal jmp destination"); /*NOTREACHED*/ } #endif goto filled; } if (off == slen - 2) /*???*/ goto filled; { int i; int jt, jf; char *ljerr = "%s for block-local relative jump: off=%d"; #if 0 printf("code=%x off=%d %x %x\n", src->s.code, off, src->s.jt, src->s.jf); #endif if (!src->s.jt || !src->s.jf) { ArgusLog (LOG_ERR, ljerr, "no jmp destination", off); /*NOTREACHED*/ } jt = jf = 0; for (i = 0; i < slen; i++) { if (offset[i] == src->s.jt) { if (jt) { ArgusLog (LOG_ERR, ljerr, "multiple matches", off); /*NOTREACHED*/ } dst->jt = i - off - 1; jt++; } if (offset[i] == src->s.jf) { if (jf) { ArgusLog (LOG_ERR, ljerr, "multiple matches", off); /*NOTREACHED*/ } dst->jf = i - off - 1; jf++; } } if (!jt || !jf) { ArgusLog (LOG_ERR, ljerr, "no destination found", off); /*NOTREACHED*/ } } filled: ++dst; ++off; } if (offset) free(offset); #ifdef BDEBUG bids[dst - fstart] = p->id + 1; #endif dst->code = (u_short)p->s.code; dst->k = p->s.k; if (JT(p)) { extrajmps = 0; off = JT(p)->offset - (p->offset + slen) - 1; if (off >= 256) { /* offset too large for branch, must add a jump */ if (p->longjt == 0) { /* mark this instruction and retry */ p->longjt++; return(0); } /* branch if T to following jump */ dst->jt = extrajmps; extrajmps++; dst[extrajmps].code = BPF_JMP|BPF_JA; dst[extrajmps].k = off - extrajmps; } else dst->jt = off; off = JF(p)->offset - (p->offset + slen) - 1; if (off >= 256) { /* offset too large for branch, must add a jump */ if (p->longjf == 0) { /* mark this instruction and retry */ p->longjf++; return(0); } /* branch if F to following jump */ /* if two jumps are inserted, F goes to second one */ dst->jf = extrajmps; extrajmps++; dst[extrajmps].code = BPF_JMP|BPF_JA; dst[extrajmps].k = off - extrajmps; } else dst->jf = off; } return (1); } /* * Convert flowgraph intermediate representation to the * BPF array representation. Set *lenp to the number of instructions. */ struct bpf_insn * Argusicode_to_fcode(root, lenp) struct ablock *root; int *lenp; { int n; struct bpf_insn *fp; /* * Loop doing convert_codr_r() until no branches remain * with too-large offsets. */ while (1) { unMarkAll(); n = *lenp = count_stmts(root); fp = (struct bpf_insn *)malloc(sizeof(*fp) * n); memset((char *)fp, 0, sizeof(*fp) * n); fstart = fp; ftail = fp + n; unMarkAll(); if (convert_code_r(root)) break; free(fp); } return fp; } #ifdef BDEBUG opt_dump(root) struct ablock *root; { struct bpf_program f; memset(bids, 0, sizeof bids); f.bf_insns = Argusicode_to_fcode(root, &f.bf_len); bpf_dump(&f, 1); putchar('\n'); free((char *)f.bf_insns); } #endif /* * Copyright (c) 1990, 1991, 1992, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ static char *bpf_image(struct bpf_insn *, int); static char * bpf_image(p, n) struct bpf_insn *p; int n; { int v; char *fmt, *op; static char image[256]; char operand[64]; v = p->k; switch (p->code) { default: op = "unimp"; fmt = "0x%x"; v = p->code; break; case BPF_RET|BPF_K: op = "ret"; fmt = "#%d"; break; case BPF_RET|BPF_A: op = "ret"; fmt = ""; break; case BPF_LD|BPF_W|BPF_ABS: op = "ld"; fmt = "[%d]"; break; case BPF_LD|BPF_H|BPF_ABS: op = "ldh"; fmt = "[%d]"; break; case BPF_LD|BPF_B|BPF_ABS: op = "ldb"; fmt = "[%d]"; break; case BPF_LD|BPF_W|BPF_LEN: op = "ld"; fmt = "#pktlen"; break; case BPF_LD|BPF_W|BPF_IND: op = "ld"; fmt = "[x + %d]"; break; case BPF_LD|BPF_H|BPF_IND: op = "ldh"; fmt = "[x + %d]"; break; case BPF_LD|BPF_B|BPF_IND: op = "ldb"; fmt = "[x + %d]"; break; case BPF_LD|BPF_IMM: op = "ld"; fmt = "#0x%x"; break; case BPF_LDX|BPF_IMM: op = "ldx"; fmt = "#0x%x"; break; case BPF_LDX|BPF_MSH|BPF_B: op = "ldxb"; fmt = "4*([%d]&0xf)"; break; case BPF_LD|BPF_MEM: op = "ld"; fmt = "M[%d]"; break; case BPF_LDX|BPF_MEM: op = "ldx"; fmt = "M[%d]"; break; case BPF_ST: op = "st"; fmt = "M[%d]"; break; case BPF_STX: op = "stx"; fmt = "M[%d]"; break; case BPF_JMP|BPF_JA: op = "ja"; fmt = "%d"; v = n + p->k; break; case BPF_JMP|BPF_JGT|BPF_K: op = "jgt"; fmt = "#0x%x"; break; case BPF_JMP|BPF_JGE|BPF_K: op = "jge"; fmt = "#0x%x"; break; case BPF_JMP|BPF_JEQ|BPF_K: op = "jeq"; fmt = "#0x%x"; break; case BPF_JMP|BPF_JSET|BPF_K: op = "jset"; fmt = "#0x%x"; break; case BPF_JMP|BPF_JGT|BPF_X: op = "jgt"; fmt = "x"; break; case BPF_JMP|BPF_JGE|BPF_X: op = "jge"; fmt = "x"; break; case BPF_JMP|BPF_JEQ|BPF_X: op = "jeq"; fmt = "x"; break; case BPF_JMP|BPF_JSET|BPF_X: op = "jset"; fmt = "x"; break; case BPF_ALU|BPF_ADD|BPF_X: op = "add"; fmt = "x"; break; case BPF_ALU|BPF_SUB|BPF_X: op = "sub"; fmt = "x"; break; case BPF_ALU|BPF_MUL|BPF_X: op = "mul"; fmt = "x"; break; case BPF_ALU|BPF_DIV|BPF_X: op = "div"; fmt = "x"; break; case BPF_ALU|BPF_AND|BPF_X: op = "and"; fmt = "x"; break; case BPF_ALU|BPF_OR|BPF_X: op = "or"; fmt = "x"; break; case BPF_ALU|BPF_LSH|BPF_X: op = "lsh"; fmt = "x"; break; case BPF_ALU|BPF_RSH|BPF_X: op = "rsh"; fmt = "x"; break; case BPF_ALU|BPF_ADD|BPF_K: op = "add"; fmt = "#%d"; break; case BPF_ALU|BPF_SUB|BPF_K: op = "sub"; fmt = "#%d"; break; case BPF_ALU|BPF_MUL|BPF_K: op = "mul"; fmt = "#%d"; break; case BPF_ALU|BPF_DIV|BPF_K: op = "div"; fmt = "#%d"; break; case BPF_ALU|BPF_AND|BPF_K: op = "and"; fmt = "#%d"; break; case BPF_ALU|BPF_OR|BPF_K: op = "or"; fmt = "#%d"; break; case BPF_ALU|BPF_LSH|BPF_K: op = "lsh"; fmt = "#%d"; break; case BPF_ALU|BPF_RSH|BPF_K: op = "rsh"; fmt = "#%d"; break; case BPF_ALU|BPF_NEG: op = "neg"; fmt = ""; break; case BPF_MISC|BPF_TAX: op = "tax"; fmt = ""; break; case BPF_MISC|BPF_TXA: op = "txa"; fmt = ""; break; } (void)sprintf(operand, fmt, v); (void)sprintf(image, (BPF_CLASS(p->code) == BPF_JMP && BPF_OP(p->code) != BPF_JA) ? "(%03d) %-8s %-16s jt %d\tjf %d" : "(%03d) %-8s %s", n, op, operand, n + 1 + p->jt, n + 1 + p->jf); return image; } /* * Convert string to integer. Just like atoi(), but checks for * preceding 0x or 0 and uses hex or octal instead of decimal. */ int stoi(s) char *s; { int base = 10; int n = 0; if (*s == '0') { if (s[1] == 'x' || s[1] == 'X') { s += 2; base = 16; } else { base = 8; s += 1; } } while (*s) n = n * base + xdtoi(*s++); return n; } #ifdef NOVFPRINTF /* * Stock 4.3 doesn't have vfprintf. * This routine is due to Chris Torek. */ vfprintf(f, fmt, args) FILE *f; char *fmt; va_list args; { int ret; if ((f->_flag & _IOWRT) == 0) { if (f->_flag & _IORW) f->_flag |= _IOWRT; else return EOF; } ret = _doprnt(fmt, args, f); return ferror(f) ? EOF : ret; } #endif /* A replacement for strdup() that cuts down on malloc() overhead */ char * savestr(const char *str) { u_int size; char *p; static char *strptr = NULL; static u_int strsize = 0; size = strlen(str) + 1; if (size > strsize) { strsize = 1024; if (strsize < size) strsize = size; strptr = (char *) malloc(strsize); if (strptr == NULL) ArgusLog(LOG_ERR, "savestr: malloc %s", strerror(errno)); } (void)strcpy(strptr, str); p = strptr; strptr += size; strsize -= size; return (p); } /* * Copy arg vector into a new argus_strbuffer, concatenating arguments with spaces. */ char * copy_argv(argv) char **argv; { char **p; int len = 0; char *argus_strbuf; char *src, *dst; p = argv; if (*p == 0) return 0; while (*p) len += strlen(*p++) + 1; argus_strbuf = (char *) malloc (len); p = argv; dst = argus_strbuf; while ((src = *p++) != NULL) { while ((*dst++ = *src++) != '\0') ; dst[-1] = ' '; } dst[-1] = '\0'; return argus_strbuf; } char * read_infile(char *fname) { struct stat argus_strbuf; int fd; char *p; fd = open(fname, O_RDONLY); if (fd < 0) ArgusLog(LOG_ERR, "can't open '%s' %s", fname, strerror(errno)); if (fstat(fd, &argus_strbuf) < 0) ArgusLog(LOG_ERR, "can't state '%s' %s", fname, strerror(errno)); p = (char *) calloc(1, (unsigned)argus_strbuf.st_size + 1); if (read(fd, p, (int)argus_strbuf.st_size) != argus_strbuf.st_size) ArgusLog(LOG_ERR, "problem reading '%s' %s", fname, strerror(errno)); return p; } /* * Left justify 'addr' and return its resulting network mask. unsigned int net_mask(addr) unsigned int *addr; { unsigned int m = 0xffffffff; if (*addr) while ((*addr & 0xff000000) == 0) *addr <<= 8, m <<= 8; return m; } */ unsigned int ipaddrtonetmask(addr) unsigned int addr; { if (IN_CLASSA (addr)) return IN_CLASSA_NET; if (IN_CLASSB (addr)) return IN_CLASSB_NET; if (IN_CLASSC (addr)) return IN_CLASSC_NET; if (IN_CLASSD (addr)) return 0xFFFFFFFF; else return 0; } unsigned int getnetnumber(addr) unsigned int addr; { if (IN_CLASSA (addr)) return (addr >> 24 ); if (IN_CLASSB (addr)) return (addr >> 16 ); if (IN_CLASSC (addr)) return (addr >> 8 ); if (IN_CLASSD (addr)) return (addr >> 0 ); else return 0; } /* * Copyright (c) 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include extern void bpf_dump(struct bpf_program *, int); static char *bpf_image(struct bpf_insn *p, int n); void bpf_dump(struct bpf_program *p, int option) { struct bpf_insn *insn; int i; int n = p->bf_len; insn = p->bf_insns; if (option > 2) { printf("%d\n", n); for (i = 0; i < n; ++insn, ++i) { printf("%lu %lu %lu %lu\n", (long)insn->code, (long)insn->jt, (long)insn->jf, (long)insn->k); } return ; } if (option > 1) { for (i = 0; i < n; ++insn, ++i) printf("{ 0x%x, %d, %d, 0x%08x },\n", insn->code, insn->jt, insn->jf, insn->k); return; } for (i = 0; i < n; ++insn, ++i) { #ifdef BDEBUG extern int bids[]; printf(bids[i] > 0 ? "[%02d]" : " -- ", bids[i] - 1); #endif puts(bpf_image(insn, i)); } } /* * Copyright (c) 2000 QoSient, LLC * All rights reserved. * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation, and that the name of CMU not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * QOSIENT, LLC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS, IN NO EVENT SHALL CARTER BULLARD BE LIABLE FOR ANY * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Internet, ethernet, port, and protocol string to address * and address to string conversion routines */ #ifndef ArgusAddrtoName #define ArgusAddrtoName #endif #include #include #include #include #include #include #include static SIGRET nohostname(int); #ifdef ETHER_SERVICE struct ether_addr; #if !defined(HAVE_ETHER_HOSTTON) && !defined(linux) && !defined(CYGWIN) extern int ether_ntohost(char *, struct ether_addr *); #endif #endif /* * hash tables for whatever-to-name translations */ #define HASHNAMESIZE 4096 struct hnamemem { unsigned int addr; char *name; struct hnamemem *nxt; }; struct hnamemem hnametable[HASHNAMESIZE]; struct hnamemem tporttable[HASHNAMESIZE]; struct hnamemem uporttable[HASHNAMESIZE]; struct hnamemem eprototable[HASHNAMESIZE]; struct hnamemem nnametable[HASHNAMESIZE]; struct hnamemem llcsaptable[HASHNAMESIZE]; struct enamemem { u_short e_addr0; u_short e_addr1; u_short e_addr2; char *e_name; u_char *e_nsap; /* used only for nsaptable[] */ struct enamemem *e_nxt; }; struct enamemem enametable[HASHNAMESIZE]; struct enamemem nsaptable[HASHNAMESIZE]; struct protoidmem { unsigned int p_oui; arg_uint16 p_proto; char *p_name; struct protoidmem *p_nxt; }; struct protoidmem protoidtable[HASHNAMESIZE]; /* * A faster replacement for inet_ntoa(). */ char * intoa(unsigned int addr) { char *cp; u_int byte; int n; static char buf[sizeof(".xxx.xxx.xxx.xxx")]; addr = ntohl(addr); cp = &buf[sizeof buf]; *--cp = '\0'; n = 4; do { byte = addr & 0xff; *--cp = byte % 10 + '0'; byte /= 10; if (byte > 0) { *--cp = byte % 10 + '0'; byte /= 10; if (byte > 0) *--cp = byte + '0'; } *--cp = '.'; addr >>= 8; } while (--n > 0); return cp + 1; } static unsigned int f_netmask; static unsigned int f_localnet; static unsigned int netmask; /* * "getname" is written in this atrocious way to make sure we don't * wait forever while trying to get hostnames from yp. */ #include jmp_buf getname_env; static SIGRET nohostname(int signo) { longjmp(getname_env, 1); } /* * Return a name for the IP address pointed to by ap. This address * is assumed to be in network byte order. */ char * getname(u_char *ap) { struct hostent *hp; unsigned int addr; static struct hnamemem *p; /* static for longjmp() */ #ifndef TCPDUMP_ALIGN addr = *(const unsigned int *)ap; #else /* * Deal with alignment. */ switch ((int)ap & 3) { case 0: addr = *(unsigned int *)ap; break; case 2: #if BYTES_BIG_ENDIAN == FALSE addr = ((unsigned int)*(u_short *)(ap + 2) << 16) | (unsigned int)*(u_short *)ap; #else addr = ((unsigned int)*(u_short *)ap << 16) | (unsigned int)*(u_short *)(ap + 2); #endif break; default: #if BYTES_BIG_ENDIAN == FALSE addr = ((unsigned int)ap[0] << 24) | ((unsigned int)ap[1] << 16) | ((unsigned int)ap[2] << 8) | (unsigned int)ap[3]; #else addr = ((unsigned int)ap[3] << 24) | ((unsigned int)ap[2] << 16) | ((unsigned int)ap[1] << 8) | (unsigned int)ap[0]; #endif break; } #endif if (!(nflag)) { p = &hnametable[addr % (HASHNAMESIZE-1)]; for (; p->nxt; p = p->nxt) { if (p->addr == addr) if (p->name != NULL) return (p->name); } p->addr = addr; p->nxt = (struct hnamemem *)calloc(1, sizeof (*p)); } /* * Only print names when: * (1) -n was not given. * (2) Address is foreign and -f was given. If -f was not * present, f_netmask and f_local are 0 and the second * test will succeed. * (3) The host portion is not 0 (i.e., a network address). * (4) The host portion is not broadcast. */ if (!(nflag)) { if ((addr & f_netmask) == f_localnet) if ((addr &~ netmask) != 0) if ((addr | netmask) != 0xffffffff) if (!setjmp(getname_env)) { (void)signal(SIGALRM, nohostname); (void)alarm(20); addr = ntohl(addr); hp = gethostbyaddr((char *)&addr, 4, AF_INET); addr = htonl(addr); (void)alarm(0); if (hp) { if ((p->name = savestr(hp->h_name)) != NULL) return (p->name); } } } #if BYTES_BIG_ENDIAN == FALSE addr = ((unsigned int)ap[0] << 24) | ((unsigned int)ap[1] << 16) | ((unsigned int)ap[2] << 8) | (unsigned int)ap[3]; #endif return (intoa(addr)); } static char hex[] = "0123456789abcdef"; /* Find the hash node that corresponds the ether address 'ep'. */ static inline struct enamemem * lookup_emem(const u_char *ep) { u_int i, j, k; struct enamemem *tp; k = (ep[0] << 8) | ep[1]; j = (ep[2] << 8) | ep[3]; i = (ep[4] << 8) | ep[5]; tp = &enametable[(i ^ j) % (HASHNAMESIZE-1)]; while (tp->e_nxt) if (tp->e_addr0 == i && tp->e_addr1 == j && tp->e_addr2 == k) return tp; else tp = tp->e_nxt; tp->e_addr0 = i; tp->e_addr1 = j; tp->e_addr2 = k; tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); return tp; } /* Find the hash node that corresponds the NSAP 'nsap'. */ static inline struct enamemem * lookup_nsap(const u_char *nsap) { u_int i, j, k; int nlen = *nsap; struct enamemem *tp; const u_char *ensap = nsap + nlen - 6; if (nlen > 6) { k = (ensap[0] << 8) | ensap[1]; j = (ensap[2] << 8) | ensap[3]; i = (ensap[4] << 8) | ensap[5]; } else i = j = k = 0; tp = &nsaptable[(i ^ j) % (HASHNAMESIZE-1)]; while (tp->e_nxt) if (tp->e_addr0 == i && tp->e_addr1 == j && tp->e_addr2 == k && tp->e_nsap[0] == nlen && bcmp((char *)&(nsap[1]), (char *)&(tp->e_nsap[1]), nlen) == 0) return tp; else tp = tp->e_nxt; tp->e_addr0 = i; tp->e_addr1 = j; tp->e_addr2 = k; tp->e_nsap = (u_char *) calloc(1, nlen + 1); bcopy(nsap, tp->e_nsap, nlen + 1); tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); return tp; } /* Find the hash node that corresponds the protoid 'pi'. */ static inline struct protoidmem * lookup_protoid(const u_char *pi) { u_int i, j; struct protoidmem *tp; /* 5 octets won't be aligned */ i = (((pi[0] << 8) + pi[1]) << 8) + pi[2]; j = (pi[3] << 8) + pi[4]; /* XXX should be endian-insensitive, but do big-endian testing XXX */ tp = &protoidtable[(i ^ j) % (HASHNAMESIZE-1)]; while (tp->p_nxt) if (tp->p_oui == i && tp->p_proto == j) return tp; else tp = tp->p_nxt; tp->p_oui = i; tp->p_proto = j; tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp)); return tp; } char * etheraddr_string(u_char *ep) { u_int i, j; char *cp; struct enamemem *tp; tp = lookup_emem(ep); if (tp->e_name) return (tp->e_name); #if defined(ETHER_SERVICE) && !defined(linux) && !defined(CYGWIN) if (!nflag) { char buf[128]; if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) { tp->e_name = savestr(buf); return (tp->e_name); } } #endif tp->e_name = cp = (char *)malloc(sizeof("00:00:00:00:00:00")); if ((j = *ep >> 4) != 0) *cp++ = hex[j]; *cp++ = hex[*ep++ & 0xf]; for (i = 5; (int)--i >= 0;) { *cp++ = ':'; if ((j = *ep >> 4) != 0) *cp++ = hex[j]; *cp++ = hex[*ep++ & 0xf]; } *cp = '\0'; return (tp->e_name); } #define ARGUS_MAXEPROTODB 0x10000 struct ArgusEtherTypeStruct *argus_eproto_db[ARGUS_MAXEPROTODB]; char * etherproto_string(u_short port) { struct ArgusEtherTypeStruct *p; char *retn = NULL, *cp = NULL; if ((p = argus_eproto_db[port]) != NULL) { retn = p->tag; } else { if ((p = (struct ArgusEtherTypeStruct *) calloc (1, sizeof(*p))) != NULL) { if (nflag < 2) p->tag = "unknown"; else { p->tag = cp = (char *)malloc(sizeof("000000")); sprintf (cp, "%d", port); } p->range = cp; argus_eproto_db[port] = p; retn = p->tag; } } return (retn); } char * protoid_string(const u_char *pi) { u_int i, j; char *cp; struct protoidmem *tp; tp = lookup_protoid(pi); if (tp->p_name) return tp->p_name; tp->p_name = cp = (char *)malloc(sizeof("00:00:00:00:00")); if ((j = *pi >> 4) != 0) *cp++ = hex[j]; *cp++ = hex[*pi++ & 0xf]; for (i = 4; (int)--i >= 0;) { *cp++ = ':'; if ((j = *pi >> 4) != 0) *cp++ = hex[j]; *cp++ = hex[*pi++ & 0xf]; } *cp = '\0'; return (tp->p_name); } char * llcsap_string(u_char sap) { char *cp; struct hnamemem *tp; unsigned int i = sap; for (tp = &llcsaptable[i % (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) if (tp->addr == i) return (tp->name); tp->name = cp = (char *)malloc(sizeof("00000")); tp->addr = i; tp->nxt = (struct hnamemem *)calloc(1, sizeof (*tp)); *cp++ = '0'; *cp++ = 'x'; *cp++ = hex[sap >> 4 & 0xf]; *cp++ = hex[sap & 0xf]; *cp++ = '\0'; return (tp->name); } char * isonsap_string(const u_char *nsap) { u_int i, nlen = nsap[0]; char *cp; struct enamemem *tp; tp = lookup_nsap(nsap); if (tp->e_name) return tp->e_name; tp->e_name = cp = (char *)malloc(nlen * 2 + 2); nsap++; *cp++ = '/'; for (i = nlen; (int)--i >= 0;) { *cp++ = hex[*nsap >> 4]; *cp++ = hex[*nsap++ & 0xf]; } *cp = '\0'; return (tp->e_name); } char * tcpport_string(arg_uint16 port) { struct hnamemem *tp; unsigned int i = port; for (tp = &tporttable[i % (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) if (tp->addr == i) return (tp->name); tp->name = (char *)malloc(sizeof("00000")); tp->addr = i; tp->nxt = (struct hnamemem *)calloc(1, sizeof (*tp)); (void)sprintf(tp->name, "%d", i); return (tp->name); } char * udpport_string(u_short port) { struct hnamemem *tp; unsigned int i = port; if (port) { for (tp = &uporttable[i % (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) if (tp->addr == i) return (tp->name); tp->name = (char *)malloc(sizeof("00000")); tp->addr = i; tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp)); (void)sprintf(tp->name, "%d", i); return (tp->name); } else return ("*"); } static void init_servarray(void) { #if !defined(CYGWIN) struct servent *sv; struct hnamemem *table; int i; while ((sv = getservent()) != NULL) { int port = ntohs(sv->s_port); i = port % (HASHNAMESIZE-1); if (strcmp(sv->s_proto, "tcp") == 0) table = &tporttable[i]; else if (strcmp(sv->s_proto, "udp") == 0) table = &uporttable[i]; else continue; while (table->name) table = table->nxt; if (nflag > 1) { char buf[32]; (void)sprintf(buf, "%d", port); table->name = savestr(buf); } else table->name = savestr(sv->s_name); table->addr = port; table->nxt = (struct hnamemem *)calloc(1, sizeof(*table)); } endservent(); #endif } static void init_eprotoarray(void) { struct ArgusEtherTypeStruct *p = argus_ethertype_names; bzero ((char *)argus_eproto_db, sizeof (argus_eproto_db)); while (p->range != NULL) { int i, start, end; char *ptr; start = atoi(p->range); if ((ptr = strchr(p->range, '-')) != NULL) end = atoi(ptr + 1); else end = start; for (i = start; i < (end + 1); i++) argus_eproto_db[i] = p; p++; } } /* * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet * types. */ static void init_protoidarray(void) { struct ArgusEtherTypeStruct *p; int i; struct protoidmem *tp; u_char protoid[5]; protoid[0] = 0; protoid[1] = 0; protoid[2] = 0; for (i = 0; i < ARGUS_MAXEPROTODB; i++) { if ((p = argus_eproto_db[i]) != NULL) { protoid[3] = i; tp = lookup_protoid(protoid); tp->p_name = p->tag; } } } static struct etherlist { u_char addr[6]; char *name; } etherlist[] = { {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" }, {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL } }; /* * Initialize the ethers hash table. We take two different approaches * depending on whether or not the system provides the ethers name * service. If it does, we just wire in a few names at startup, * and etheraddr_string() fills in the table on demand. If it doesn't, * then we suck in the entire /etc/ethers file at startup. The idea * is that parsing the local file will be fast, but spinning through * all the ethers entries via NIS & next_etherent might be very slow. * * XXX argus_next_etherent doesn't belong in the pcap interface, but * since the pcap module already does name-to-address translation, * it's already does most of the work for the ethernet address-to-name * translation, so we just argus_next_etherent as a convenience. */ static void init_etherarray(void) { struct etherlist *el; struct enamemem *tp; #ifndef ETHER_SERVICE struct argus_etherent *ep; FILE *fp; /* Suck in entire ethers file */ fp = fopen(PCAP_ETHERS_FILE, "r"); if (fp != NULL) { while ((ep = argus_next_etherent(fp)) != NULL) { tp = lookup_emem(ep->addr); tp->e_name = savestr(ep->name); } (void)fclose(fp); } #endif /* Hardwire some ethernet names */ for (el = etherlist; el->name != NULL; ++el) { #if defined(ETHER_SERVICE) && !defined(linux) && !defined(CYGWIN) /* Use yp/nis version of name if available */ char wrk[256]; if (ether_ntohost(wrk, (struct ether_addr *)el->addr) == 0) { tp = lookup_emem(el->addr); tp->e_name = savestr(wrk); } #else /* install if not already present */ tp = lookup_emem(el->addr); if (tp->e_name == NULL) tp->e_name = el->name; #endif } } static struct ArgusTokenStruct llcsap_db[] = { { LLCSAP_NULL, "null" }, { LLCSAP_8021B_I, "gsap" }, { LLCSAP_8021B_G, "isap" }, { LLCSAP_SNAPATH, "snapath" }, { LLCSAP_IP, "ipsap" }, { LLCSAP_SNA1, "sna1" }, { LLCSAP_SNA2, "sna2" }, { LLCSAP_PROWAYNM, "p-nm" }, { LLCSAP_TI, "ti" }, { LLCSAP_BPDU, "stp" }, { LLCSAP_RS511, "eia" }, { LLCSAP_ISO8208, "x25" }, { LLCSAP_XNS, "xns" }, { LLCSAP_NESTAR, "nestar" }, { LLCSAP_PROWAYASLM, "p-aslm" }, { LLCSAP_ARP, "arp" }, { LLCSAP_SNAP, "snap" }, { LLCSAP_VINES1, "vine1" }, { LLCSAP_VINES2, "vine2" }, { LLCSAP_NETWARE, "netware" }, { LLCSAP_NETBIOS, "netbios" }, { LLCSAP_IBMNM, "ibmnm" }, { LLCSAP_RPL1, "rpl1" }, { LLCSAP_UB, "ub" }, { LLCSAP_RPL2, "rpl2" }, { LLCSAP_ISONS, "clns" }, { LLCSAP_GLOBAL, "gbl" }, { 0, NULL } }; static void init_llcsaparray(void) { int i; struct hnamemem *table; for (i = 0; llcsap_db[i].s != NULL; i++) { table = &llcsaptable[llcsap_db[i].v]; while (table->name) table = table->nxt; table->name = llcsap_db[i].s; table->addr = llcsap_db[i].v; table->nxt = (struct hnamemem *)calloc(1, sizeof(*table)); } } /* * Initialize the address to name translation machinery. We map all * non-local IP addresses to numeric addresses if fflag is true (i.e., * to prevent blocking on the nameserver). localnet is the IP address * of the local network. mask is its subnet mask. */ void init_addrtoname(int fflag, unsigned int localnet, unsigned int mask) { netmask = mask; if (fflag) { f_localnet = localnet; f_netmask = mask; } if (nflag > 1) /* * Simplest way to suppress names. */ return; init_etherarray(); init_servarray(); init_eprotoarray(); init_llcsaparray(); init_protoidarray(); } /* * Copyright (c) 2000 QoSient, LLC * All rights reserved. * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation, and that the name of CMU not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * QOSIENT, LLC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS, IN NO EVENT SHALL CARTER BULLARD BE LIABLE FOR ANY * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Name to id translation routines used by the scanner. * These functions are not time critical. */ #include #ifndef __GNUC__ #define inline #endif #ifndef NTOHL #define NTOHL(x) (x) = ntohl(x) #define NTOHS(x) (x) = ntohs(x) #endif /* * Convert host name to internet address. * Return 0 upon failure. */ unsigned int ** argus_nametoaddr(char *name) { #ifndef h_addr static unsigned int *hlist[2]; #endif unsigned int **p; struct hostent *hp; if ((hp = gethostbyname(name)) != NULL) { #ifndef h_addr hlist[0] = (unsigned int *)hp->h_addr; NTOHL(hp->h_addr); return hlist; #else for (p = (unsigned int **)hp->h_addr_list; *p; ++p) NTOHL(**p); return (unsigned int **)hp->h_addr_list; #endif } else return 0; } /* * Convert net name to internet address. * Return 0 upon failure. */ unsigned int argus_nametonetaddr(char *name) { #if !defined(CYGWIN) struct netent *np; if ((np = getnetbyname(name)) != NULL) return np->n_net; else #endif return 0; } /* * Convert a port name to its port and protocol numbers. * We assume only TCP or UDP. * Return 0 upon failure. */ int argus_nametoport(char *name, int *port, int *proto) { struct protoent *pp = NULL; struct servent *sp = NULL; char *pname = NULL, *other; #ifdef ARGUSDEBUG ArgusDebug (2, "argus_nametoport (%s, %d, %d)\n", name, *port, *proto); #endif if ((proto != NULL) && (*proto != -1)) if ((pp = getprotobynumber(*proto)) != NULL) pname = pp->p_name; if (name != NULL) sp = getservbyname(name, pname); if (sp != NULL) { NTOHS(sp->s_port); *port = sp->s_port; *proto = argus_nametoproto(sp->s_proto); /* * We need to check /etc/services for ambiguous entries. * If we find the ambiguous entry, and it has the * same port number, change the proto to PROTO_UNDEF * so both TCP and UDP will be checked. */ if (*proto == IPPROTO_TCP) other = "udp"; else other = "tcp"; sp = getservbyname(name, other); if (sp != 0) { NTOHS(sp->s_port); if (*port != sp->s_port) /* Can't handle ambiguous names that refer to different port numbers. */ ArgusLog(LOG_ERR, "ambiguous port %s in /etc/services values %d and %d", name, *port, sp->s_port); *proto = PROTO_UNDEF; } return 1; } #if defined(ultrix) || defined(__osf__) /* Special hack in case NFS isn't in /etc/services */ if (strcmp(name, "nfs") == 0) { *port = 2049; *proto = PROTO_UNDEF; return 1; } #endif return 0; } int argus_nametoproto(char *str) { struct protoent *p; p = getprotobyname(str); if (p != 0) return p->p_proto; else return PROTO_UNDEF; } int argus_nametoeproto(char *s) { struct ArgusEtherTypeStruct *p = argus_ethertype_names; while (p->tag != 0) { if (strcmp(p->tag, s) == 0) { return atoi(p->range); } p += 1; } return PROTO_UNDEF; } unsigned int __argus_atoin(char *s, unsigned int *addr) { u_int n; int len; *addr = 0; len = 0; while (1) { n = 0; while (*s && *s != '.') n = n * 10 + *s++ - '0'; *addr <<= 8; *addr |= n & 0xff; len += 8; if (*s == '\0') return len; ++s; } /* NOTREACHED */ } unsigned int __argus_atodn(char *s) { #define AREASHIFT 10 #define AREAMASK 0176000 #define NODEMASK 01777 unsigned int addr = 0; u_int node, area; if (sscanf((char *)s, "%d.%d", (int *) &area, (int *) &node) != 2) ArgusLog (LOG_ERR,"malformed decnet address '%s'", s); addr = (area << AREASHIFT) & AREAMASK; addr |= (node & NODEMASK); return(addr); } /* * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new * ethernet address. Assumes 's' is well formed. */ u_char * argus_ether_aton(char *s) { register u_char *ep, *e; register u_int d; e = ep = (u_char *)malloc(6); while (*s) { if (*s == ':') s += 1; d = xdtoi(*s++); if (isxdigit((int)*s)) { d <<= 4; d |= xdtoi(*s++); } *ep++ = d; } return (e); } #if !defined(ETHER_SERVICE) || defined(linux) || defined(CYGWIN) /* Roll our own */ u_char * argus_ether_hostton(char *name) { register struct argus_etherent *ep; register u_char *ap; static FILE *fp = NULL; static int init = 0; if (!init) { fp = fopen(PCAP_ETHERS_FILE, "r"); ++init; if (fp == NULL) return (NULL); } else if (fp == NULL) return (NULL); else rewind(fp); while ((ep = argus_next_etherent(fp)) != NULL) { if (strcmp(ep->name, name) == 0) { ap = (u_char *)malloc(6); if (ap != NULL) { memcpy(ap, ep->addr, 6); return (ap); } break; } } return (NULL); } #else /* Use the os supplied routines */ u_char * argus_ether_hostton(char *name) { register u_char *ap; u_char a[6]; #if !defined(HAVE_ETHER_HOSTTON) extern int ether_hostton(char *, struct ether_addr *); #endif ap = NULL; if (ether_hostton((char*)name, (struct ether_addr *)a) == 0) { ap = (u_char *)malloc(6); if (ap != NULL) memcpy(ap, a, 6); } return (ap); } #endif u_short __argus_nametodnaddr(char *name) { #ifndef DECNETLIB ArgusLog (LOG_ERR,"decnet name support not included, '%s' cannot be translated\n", name); return(0); #else struct nodeent *getnodebyname(); struct nodeent *nep; unsigned short res; nep = getnodebyname(name); if (nep == ((struct nodeent *)0)) ArgusLog (LOG_ERR,"unknown decnet host name '%s'\n", name); memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short)); return(res); #endif } #include extern char *ArgusProgramName; char ArgusPrintTimeBuf[64]; char * print_time(struct timeval *tvp) { char timeZoneBuf[32]; char *retn = ArgusPrintTimeBuf, *ptr; struct tm *tm; bzero (timeZoneBuf, sizeof(timeZoneBuf)); bzero (ArgusPrintTimeBuf, sizeof(ArgusPrintTimeBuf)); if (ArgusPrintGMT) { if ((tm = gmtime ((time_t *)&tvp->tv_sec)) == NULL) return (NULL); } else { if ((tm = localtime ((time_t *)&tvp->tv_sec)) == NULL) return (NULL); } if (uflag) sprintf (retn, "%9d", (int) tvp->tv_sec); else if ((strftime ((char *) retn, 64, RaTimeFormat, tm)) == 0) ArgusLog (LOG_ERR, "print_time: format %s not supported.\n", RaTimeFormat); if (pflag) { ptr = &retn[strlen(retn)]; if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) { if (uflag) { sprintf (ptr, ".%06d", (int) tvp->tv_usec); ptr[pflag + 1] = '\0'; } else { sprintf (ptr, "%c0.%06d", RaFieldDelimiter, (int) tvp->tv_usec); ptr[pflag + 3] = '\0'; } } else { sprintf (ptr, ".%06d", (int) tvp->tv_usec); ptr[pflag + 1] = '\0'; } } return (retn); } #ifdef ARGUSDEBUG void ArgusDebug (int d, char *fmt, ...) { va_list ap; char buf[1024], *ptr; struct timeval tvp; if (d <= Argusdflag) { gettimeofday (&tvp, 0L); (void) sprintf (buf, "%s[%d]: %s ", ArgusProgramName, (int)getpid(), print_time(&tvp)); ptr = &buf[strlen(buf)]; #if defined(__STDC__) va_start(ap, fmt); #else va_start(ap); #endif (void) vsprintf (ptr, fmt, ap); ptr = &buf[strlen(buf)]; va_end (ap); if (*fmt) { fmt += (int) strlen (fmt); if (fmt[-1] != '\n') sprintf (ptr, "\n"); } fprintf (stderr, "%s", buf); } } #endif #if defined(_LITTLE_ENDIAN) #if !defined(ntohll) long long ntohll (long long); long long ntohll (long long data) { long long retn; unsigned char *ptr1, *ptr2; int i, len; ptr1 = (unsigned char *) &data; ptr2 = (unsigned char *) &retn; for (i = 0, len = sizeof(retn); i < len; i++) ptr2[(len - 1) - i] = ptr1[i]; return(retn); } #endif #if !defined(htonll) long long htonll (long long); long long htonll (long long data) { long long retn; unsigned char *ptr1, *ptr2; int i, len; ptr1 = (unsigned char *) &data; ptr2 = (unsigned char *) &retn; for (i = 0, len = sizeof(retn); i < len; i++) ptr2[(len - 1) - i] = ptr1[i]; return(retn); } #endif #endif void ArgusNtoH (struct ArgusRecord *); void ArgusHtoN (struct ArgusRecord *); void ArgusNtoH (struct ArgusRecord *argus) { #if defined(_LITTLE_ENDIAN) int farlen = 0; argus->ahdr.length = ntohs(argus->ahdr.length); argus->ahdr.argusid = ntohl(argus->ahdr.argusid); argus->ahdr.seqNumber = ntohl(argus->ahdr.seqNumber); argus->ahdr.status = ntohl(argus->ahdr.status); if (argus->ahdr.type & ARGUS_MAR) { argus->argus_mar.startime.tv_sec = ntohl(argus->argus_mar.startime.tv_sec); argus->argus_mar.startime.tv_usec = ntohl(argus->argus_mar.startime.tv_usec); argus->argus_mar.now.tv_sec = ntohl(argus->argus_mar.now.tv_sec); argus->argus_mar.now.tv_usec = ntohl(argus->argus_mar.now.tv_usec); argus->argus_mar.reportInterval = ntohs(argus->argus_mar.reportInterval); argus->argus_mar.argusMrInterval = ntohs(argus->argus_mar.argusMrInterval); argus->argus_mar.argusid = ntohl(argus->argus_mar.argusid); argus->argus_mar.localnet = ntohl(argus->argus_mar.localnet); argus->argus_mar.netmask = ntohl(argus->argus_mar.netmask); argus->argus_mar.nextMrSequenceNum = ntohl(argus->argus_mar.nextMrSequenceNum); argus->argus_mar.pktsRcvd = ntohll(argus->argus_mar.pktsRcvd); argus->argus_mar.bytesRcvd = ntohll(argus->argus_mar.bytesRcvd); argus->argus_mar.pktsDrop = ntohl(argus->argus_mar.pktsDrop); argus->argus_mar.flows = ntohl(argus->argus_mar.flows); argus->argus_mar.flowsClosed = ntohl(argus->argus_mar.flowsClosed); argus->argus_mar.actIPcons = ntohl( argus->argus_mar.actIPcons); argus->argus_mar.cloIPcons = ntohl( argus->argus_mar.cloIPcons); argus->argus_mar.actICMPcons = ntohl( argus->argus_mar.actICMPcons); argus->argus_mar.cloICMPcons = ntohl( argus->argus_mar.cloICMPcons); argus->argus_mar.actIGMPcons = ntohl( argus->argus_mar.actIGMPcons); argus->argus_mar.cloIGMPcons = ntohl( argus->argus_mar.cloIGMPcons); argus->argus_mar.record_len = ntohl(argus->argus_mar.record_len); } else { unsigned int status, length = argus->ahdr.length - sizeof(argus->ahdr); struct ArgusFarHeaderStruct *farhdr = (struct ArgusFarHeaderStruct *) &argus->argus_far; farhdr->status = ntohs(farhdr->status); status = argus->ahdr.status; while (length > 0) { switch (farhdr->type) { case ARGUS_FAR: { struct ArgusFarStruct *far = (struct ArgusFarStruct *) farhdr; far->ArgusTransRefNum = ntohl(far->ArgusTransRefNum); switch (status & (ETHERTYPE_IP|ETHERTYPE_IPV6|ETHERTYPE_ARP)) { case ETHERTYPE_IP: { struct ArgusIPFlow *ipflow = &far->flow.ip_flow; far->attr_ip.soptions = ntohs(far->attr_ip.soptions); far->attr_ip.doptions = ntohs(far->attr_ip.doptions); switch (ipflow->ip_p) { case IPPROTO_UDP: case IPPROTO_TCP: ipflow->ip_src = ntohl(ipflow->ip_src); ipflow->ip_dst = ntohl(ipflow->ip_dst); ipflow->sport = ntohs(ipflow->sport); ipflow->dport = ntohs(ipflow->dport); ipflow->ip_id = ntohs(ipflow->ip_id); break; case IPPROTO_ICMP: { struct ArgusICMPFlow *icmpflow = &far->flow.icmp_flow; icmpflow->ip_src = ntohl(icmpflow->ip_src); icmpflow->ip_dst = ntohl(icmpflow->ip_dst); icmpflow->id = ntohs(icmpflow->id); icmpflow->ip_id = ntohs(icmpflow->ip_id); break; } default: { ipflow->ip_src = ntohl(ipflow->ip_src); ipflow->ip_dst = ntohl(ipflow->ip_dst); break; } } break; } case ETHERTYPE_IPV6: break; case ETHERTYPE_ARP: { struct ArgusArpFlow *arpflow = &far->flow.arp_flow; arpflow->arp_tpa = ntohl(arpflow->arp_tpa); arpflow->arp_spa = ntohl(arpflow->arp_spa); break; } default: break; } far->time.start.tv_sec = ntohl(far->time.start.tv_sec); far->time.start.tv_usec = ntohl(far->time.start.tv_usec); far->time.last.tv_sec = ntohl(far->time.last.tv_sec); far->time.last.tv_usec = ntohl(far->time.last.tv_usec); far->src.count = ntohl(far->src.count); far->src.bytes = ntohl(far->src.bytes); far->src.appbytes = ntohl(far->src.appbytes); far->dst.count = ntohl(far->dst.count); far->dst.bytes = ntohl(far->dst.bytes); far->dst.appbytes = ntohl(far->dst.appbytes); break; } case ARGUS_MAC_DSR: { struct ArgusMacStruct *mac = (struct ArgusMacStruct *) farhdr; mac->status = ntohs(mac->status); break; } case ARGUS_VLAN_DSR: { struct ArgusVlanStruct *vlan = (struct ArgusVlanStruct *) farhdr; if (vlan->length != sizeof (struct ArgusVlanStruct)) /* fix for pre 2.0.1 len problem */ vlan->length = sizeof (struct ArgusVlanStruct); vlan->status = ntohs(vlan->status); vlan->sid = ntohs(vlan->sid); vlan->did = ntohs(vlan->did); break; } case ARGUS_MPLS_DSR: { struct ArgusMplsStruct *mpls = (struct ArgusMplsStruct *) farhdr; mpls->status = ntohs(mpls->status); mpls->slabel = ntohl(mpls->slabel); mpls->dlabel = ntohl(mpls->dlabel); break; } case ARGUS_TCP_DSR: { struct ArgusTCPObject *tcp = (struct ArgusTCPObject *) farhdr; tcp->status = ntohs(tcp->status); tcp->state = ntohl(tcp->state); tcp->synAckuSecs = ntohl(tcp->synAckuSecs); tcp->ackDatauSecs = ntohl(tcp->ackDatauSecs); tcp->options = ntohl(tcp->options); tcp->src.seqbase = ntohl(tcp->src.seqbase); tcp->src.ackbytes = ntohl(tcp->src.ackbytes); tcp->src.rpkts = ntohl(tcp->src.rpkts); tcp->src.win = ntohs(tcp->src.win); tcp->dst.seqbase = ntohl(tcp->dst.seqbase); tcp->dst.ackbytes = ntohl(tcp->dst.ackbytes); tcp->dst.rpkts = ntohl(tcp->dst.rpkts); tcp->dst.win = ntohs(tcp->dst.win); break; } case ARGUS_ICMP_DSR: { struct ArgusICMPObject *icmp = (struct ArgusICMPObject *) farhdr; icmp->status = ntohs(icmp->status); icmp->iseq = ntohs(icmp->iseq); icmp->osrcaddr = ntohl(icmp->osrcaddr); icmp->odstaddr = ntohl(icmp->odstaddr); icmp->isrcaddr = ntohl(icmp->isrcaddr); icmp->idstaddr = ntohl(icmp->idstaddr); icmp->igwaddr = ntohl(icmp->igwaddr); break; } case ARGUS_TIME_DSR: { struct ArgusTimeStruct *time = (void *) farhdr; time->status = ntohs(time->status); time->src.act.n = ntohl(time->src.act.n); time->src.act.minval = ntohl(time->src.act.minval); time->src.act.meanval = ntohl(time->src.act.meanval); time->src.act.stdev = ntohl(time->src.act.stdev); time->src.act.maxval = ntohl(time->src.act.maxval); time->src.idle.n = ntohl(time->src.idle.n); time->src.idle.minval = ntohl(time->src.idle.minval); time->src.idle.meanval = ntohl(time->src.idle.meanval); time->src.idle.stdev = ntohl(time->src.idle.stdev); time->src.idle.maxval = ntohl(time->src.idle.maxval); time->dst.act.n = ntohl(time->dst.act.n); time->dst.act.minval = ntohl(time->dst.act.minval); time->dst.act.meanval = ntohl(time->dst.act.meanval); time->dst.act.stdev = ntohl(time->dst.act.stdev); time->dst.act.maxval = ntohl(time->dst.act.maxval); time->dst.idle.n = ntohl(time->dst.idle.n); time->dst.idle.minval = ntohl(time->dst.idle.minval); time->dst.idle.meanval = ntohl(time->dst.idle.meanval); time->dst.idle.stdev = ntohl(time->dst.idle.stdev); time->dst.idle.maxval = ntohl(time->dst.idle.maxval); break; } case ARGUS_SRCUSRDATA_DSR: { struct ArgusUserStruct *user = (struct ArgusUserStruct *) farhdr; user->status = ntohs(user->status); break; } case ARGUS_DSTUSRDATA_DSR: { struct ArgusUserStruct *user = (struct ArgusUserStruct *) farhdr; user->status = ntohs(user->status); break; } case ARGUS_ESP_DSR: { struct ArgusESPStruct *esp = (struct ArgusESPStruct *) farhdr; esp->status = ntohs(esp->status); esp->src.spi = ntohl(esp->src.spi); esp->src.lastseq = ntohl(esp->src.lastseq); esp->src.lostseq = ntohl(esp->src.lostseq); esp->dst.spi = ntohl(esp->dst.spi); esp->dst.lastseq = ntohl(esp->dst.lastseq); esp->dst.lostseq = ntohl(esp->dst.lostseq); break; } case ARGUS_AGR_DSR: { struct ArgusAGRStruct *agr = (struct ArgusAGRStruct *) farhdr; agr->status = ntohs(agr->status); agr->count = ntohl(agr->count); agr->laststartime.tv_sec = ntohl(agr->laststartime.tv_sec); agr->laststartime.tv_usec = ntohl(agr->laststartime.tv_usec); agr->lasttime.tv_sec = ntohl(agr->lasttime.tv_sec); agr->lasttime.tv_usec = ntohl(agr->lasttime.tv_usec); agr->act.minval = ntohl(agr->act.minval); agr->act.meanval = ntohl(agr->act.meanval); agr->act.stdev = ntohl(agr->act.stdev); agr->act.maxval = ntohl(agr->act.maxval); agr->idle.minval = ntohl(agr->idle.minval); agr->idle.meanval = ntohl(agr->idle.meanval); agr->idle.stdev = ntohl(agr->idle.stdev); agr->idle.maxval = ntohl(agr->idle.maxval); break; } } if ((farlen = farhdr->length) == 0) break; if ((farhdr->type == ARGUS_SRCUSRDATA_DSR) || (farhdr->type == ARGUS_DSTUSRDATA_DSR)) farlen = farlen * 4; length -= farlen; farhdr = (struct ArgusFarHeaderStruct *)((char *)farhdr + farlen); } } #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusNtoH (0x%x) returning.\n", argus); #endif #endif } void ArgusHtoN (struct ArgusRecord *argus) { #if defined(_LITTLE_ENDIAN) int farlen = 0; unsigned int length = argus->ahdr.length - sizeof(argus->ahdr); unsigned int status = argus->ahdr.status; argus->ahdr.length = htons(argus->ahdr.length); argus->ahdr.argusid = htonl(argus->ahdr.argusid); argus->ahdr.seqNumber = htonl(argus->ahdr.seqNumber); argus->ahdr.status = htonl(argus->ahdr.status); if (argus->ahdr.type & ARGUS_MAR) { argus->argus_mar.startime.tv_sec = htonl(argus->argus_mar.startime.tv_sec); argus->argus_mar.startime.tv_usec = htonl(argus->argus_mar.startime.tv_usec); argus->argus_mar.now.tv_sec = htonl(argus->argus_mar.now.tv_sec); argus->argus_mar.now.tv_usec = htonl(argus->argus_mar.now.tv_usec); argus->argus_mar.reportInterval = htons(argus->argus_mar.reportInterval); argus->argus_mar.argusMrInterval = htons(argus->argus_mar.argusMrInterval); argus->argus_mar.argusid = htonl(argus->argus_mar.argusid); argus->argus_mar.localnet = htonl(argus->argus_mar.localnet); argus->argus_mar.netmask = htonl(argus->argus_mar.netmask); argus->argus_mar.nextMrSequenceNum = htonl(argus->argus_mar.nextMrSequenceNum); argus->argus_mar.pktsRcvd = htonll(argus->argus_mar.pktsRcvd); argus->argus_mar.bytesRcvd = htonll(argus->argus_mar.bytesRcvd); argus->argus_mar.pktsDrop = htonl(argus->argus_mar.pktsDrop); argus->argus_mar.flows = htonl(argus->argus_mar.flows); argus->argus_mar.flowsClosed = htonl(argus->argus_mar.flowsClosed); argus->argus_mar.actIPcons = htonl( argus->argus_mar.actIPcons); argus->argus_mar.cloIPcons = htonl( argus->argus_mar.cloIPcons); argus->argus_mar.actICMPcons = htonl( argus->argus_mar.actICMPcons); argus->argus_mar.cloICMPcons = htonl( argus->argus_mar.cloICMPcons); argus->argus_mar.actIGMPcons = htonl( argus->argus_mar.actIGMPcons); argus->argus_mar.cloIGMPcons = htonl( argus->argus_mar.cloIGMPcons); argus->argus_mar.record_len = htonl(argus->argus_mar.record_len); } else { struct ArgusFarHeaderStruct *farhdr = (struct ArgusFarHeaderStruct *) &argus->argus_far; farhdr->status = htons(farhdr->status); while (length > 0) { switch (farhdr->type) { case ARGUS_FAR: { struct ArgusFarStruct *far = (struct ArgusFarStruct *) farhdr; far->ArgusTransRefNum = htonl(far->ArgusTransRefNum); switch (status & (ETHERTYPE_IP|ETHERTYPE_IPV6|ETHERTYPE_ARP)) { case ETHERTYPE_IP: { struct ArgusIPFlow *ipflow = &far->flow.ip_flow; far->attr_ip.soptions = htons(far->attr_ip.soptions); far->attr_ip.doptions = htons(far->attr_ip.doptions); switch (ipflow->ip_p) { case IPPROTO_UDP: case IPPROTO_TCP: ipflow->ip_src = htonl(ipflow->ip_src); ipflow->ip_dst = htonl(ipflow->ip_dst); ipflow->sport = htons(ipflow->sport); ipflow->dport = htons(ipflow->dport); ipflow->ip_id = htons(ipflow->ip_id); break; case IPPROTO_ICMP: { struct ArgusICMPFlow *icmpflow = &far->flow.icmp_flow; icmpflow->ip_src = htonl(icmpflow->ip_src); icmpflow->ip_dst = htonl(icmpflow->ip_dst); icmpflow->id = htons(icmpflow->id); icmpflow->ip_id = htons(icmpflow->ip_id); break; } default: { ipflow->ip_src = htonl(ipflow->ip_src); ipflow->ip_dst = htonl(ipflow->ip_dst); break; } } break; } case ETHERTYPE_IPV6: break; case ETHERTYPE_ARP: { struct ArgusArpFlow *arpflow = &far->flow.arp_flow; arpflow->arp_tpa = htonl(arpflow->arp_tpa); arpflow->arp_spa = htonl(arpflow->arp_spa); break; } default: break; } far->time.start.tv_sec = htonl(far->time.start.tv_sec); far->time.start.tv_usec = htonl(far->time.start.tv_usec); far->time.last.tv_sec = htonl(far->time.last.tv_sec); far->time.last.tv_usec = htonl(far->time.last.tv_usec); far->src.count = htonl(far->src.count); far->src.bytes = htonl(far->src.bytes); far->src.appbytes = htonl(far->src.appbytes); far->dst.count = htonl(far->dst.count); far->dst.bytes = htonl(far->dst.bytes); far->dst.appbytes = htonl(far->dst.appbytes); break; } case ARGUS_MAC_DSR: { struct ArgusMacStruct *mac = (struct ArgusMacStruct *) farhdr; mac->status = htons(mac->status); break; } case ARGUS_VLAN_DSR: { struct ArgusVlanStruct *vlan = (struct ArgusVlanStruct *) farhdr; if (vlan->length != sizeof (struct ArgusVlanStruct)) vlan->length = sizeof (struct ArgusVlanStruct); vlan->status = ntohs(vlan->status); vlan->sid = ntohs(vlan->sid); vlan->did = ntohs(vlan->did); break; } case ARGUS_MPLS_DSR: { struct ArgusMplsStruct *mpls = (struct ArgusMplsStruct *) farhdr; mpls->status = ntohs(mpls->status); mpls->slabel = ntohl(mpls->slabel); mpls->dlabel = ntohl(mpls->dlabel); break; } case ARGUS_TCP_DSR: { struct ArgusTCPObject *tcp = (struct ArgusTCPObject *) farhdr; tcp->status = htons(tcp->status); tcp->state = htonl(tcp->state); tcp->synAckuSecs = htonl(tcp->synAckuSecs); tcp->ackDatauSecs = htonl(tcp->ackDatauSecs); tcp->options = htonl(tcp->options); tcp->src.seqbase = htonl(tcp->src.seqbase); tcp->src.ackbytes = htonl(tcp->src.ackbytes); tcp->src.rpkts = htonl(tcp->src.rpkts); tcp->src.win = htons(tcp->src.win); tcp->dst.seqbase = htonl(tcp->dst.seqbase); tcp->dst.ackbytes = htonl(tcp->dst.ackbytes); tcp->dst.rpkts = htonl(tcp->dst.rpkts); tcp->dst.win = htons(tcp->dst.win); break; } case ARGUS_ICMP_DSR: { struct ArgusICMPObject *icmp = (struct ArgusICMPObject *) farhdr; icmp->status = htons(icmp->status); icmp->iseq = htons(icmp->iseq); icmp->osrcaddr = htonl(icmp->osrcaddr); icmp->odstaddr = htonl(icmp->odstaddr); icmp->isrcaddr = htonl(icmp->isrcaddr); icmp->idstaddr = htonl(icmp->idstaddr); icmp->igwaddr = htonl(icmp->igwaddr); break; } case ARGUS_TIME_DSR: { struct ArgusTimeStruct *time = (void *) farhdr; time->status = htons(time->status); time->src.act.n = htonl(time->src.act.n); time->src.act.minval = htonl(time->src.act.minval); time->src.act.meanval = htonl(time->src.act.meanval); time->src.act.stdev = htonl(time->src.act.stdev); time->src.act.maxval = htonl(time->src.act.maxval); time->src.idle.n = htonl(time->src.idle.n); time->src.idle.minval = htonl(time->src.idle.minval); time->src.idle.meanval = htonl(time->src.idle.meanval); time->src.idle.stdev = htonl(time->src.idle.stdev); time->src.idle.maxval = htonl(time->src.idle.maxval); time->dst.act.n = htonl(time->dst.act.n); time->dst.act.minval = htonl(time->dst.act.minval); time->dst.act.meanval = htonl(time->dst.act.meanval); time->dst.act.stdev = htonl(time->dst.act.stdev); time->dst.act.maxval = htonl(time->dst.act.maxval); time->dst.idle.n = htonl(time->dst.idle.n); time->dst.idle.minval = htonl(time->dst.idle.minval); time->dst.idle.meanval = htonl(time->dst.idle.meanval); time->dst.idle.stdev = htonl(time->dst.idle.stdev); time->dst.idle.maxval = htonl(time->dst.idle.maxval); break; } case ARGUS_SRCUSRDATA_DSR: { struct ArgusUserStruct *user = (struct ArgusUserStruct *) farhdr; user->status = htons(user->status); break; } case ARGUS_DSTUSRDATA_DSR: { struct ArgusUserStruct *user = (struct ArgusUserStruct *) farhdr; user->status = htons(user->status); break; } case ARGUS_ESP_DSR: { struct ArgusESPStruct *esp = (struct ArgusESPStruct *) farhdr; esp->status = htons(esp->status); esp->src.spi = htonl(esp->src.spi); esp->src.lastseq = htonl(esp->src.lastseq); esp->src.lostseq = htonl(esp->src.lostseq); esp->dst.spi = htonl(esp->dst.spi); esp->dst.lastseq = htonl(esp->dst.lastseq); esp->dst.lostseq = htonl(esp->dst.lostseq); break; } case ARGUS_AGR_DSR: { struct ArgusAGRStruct *agr = (struct ArgusAGRStruct *) farhdr; agr->status = htons(agr->status); agr->count = htonl(agr->count); agr->laststartime.tv_sec = htonl(agr->laststartime.tv_sec); agr->laststartime.tv_usec = htonl(agr->laststartime.tv_usec); agr->lasttime.tv_sec = htonl(agr->lasttime.tv_sec); agr->lasttime.tv_usec = htonl(agr->lasttime.tv_usec); agr->act.minval = htonl(agr->act.minval); agr->act.meanval = htonl(agr->act.meanval); agr->act.stdev = htonl(agr->act.stdev); agr->act.maxval = htonl(agr->act.maxval); agr->idle.minval = htonl(agr->idle.minval); agr->idle.meanval = htonl(agr->idle.meanval); agr->idle.stdev = htonl(agr->idle.stdev); agr->idle.maxval = htonl(agr->idle.maxval); break; } } if ((farlen = farhdr->length) == 0) break; if ((farhdr->type == ARGUS_SRCUSRDATA_DSR) || (farhdr->type == ARGUS_DSTUSRDATA_DSR)) farlen = farlen * 4; length -= farlen; farhdr = (struct ArgusFarHeaderStruct *)((char *)farhdr + farlen); } } #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusHtoN (0x%x) returning.\n", argus); #endif #endif } void ArgusPrintHex (const u_char *bp, u_int length) { const u_short *sp; u_int i; int nshorts; sp = (u_short *)bp; nshorts = (u_int) length / sizeof(u_short); i = 0; while (--nshorts >= 0) { if ((i++ % 8) == 0) { (void)printf("\n\t"); } (void)printf(" %04x", ntohs(*sp++)); } if (length & 1) { if ((i % 8) == 0) (void)printf("\n\t"); (void)printf(" %02x", *(u_char *)sp); } (void)printf("\n"); fflush(stdout); } int ArgusCallocTotal = 0; int ArgusFreeTotal = 0; #define ARGUS_ALLOC 0x3210123 void * ArgusCalloc (int nitems, int size) { unsigned int *retn = NULL; int bytes = nitems * size; if (size) { ArgusCallocTotal++; retn = (unsigned int *) calloc (1, bytes + 4); *retn = 0x45672381; retn++; } #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusCalloc (%d, %d) returning 0x%x\n", nitems, size, retn); #endif return ((void *) retn); } void ArgusFree (void *buf) { unsigned int *retn = (unsigned int *) buf; if (buf) { ArgusFreeTotal++; retn--; if (*retn != 0x45672381) ArgusLog (LOG_ERR, "ArgusFree: buffer error 0x%x", buf); free (retn); } #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusFree (0x%x) returning\n", buf); #endif } extern char *print_time(struct timeval *); #include struct ArgusLogPriorityStruct { int priority; char *label; }; #define ARGUSPRIORITYSTR 8 struct ArgusLogPriorityStruct ArgusPriorityStr[ARGUSPRIORITYSTR] = { { LOG_EMERG, "ArgusEmergency" }, { LOG_ALERT, "ArgusAlert" }, { LOG_CRIT, "ArgusCritical" }, { LOG_ERR, "ArgusError" }, { LOG_WARNING, "ArgusWarning" }, { LOG_NOTICE, "ArgusNotice" }, { LOG_INFO, "ArgusInfo" }, { LOG_DEBUG, "ArgusDebug" }, }; extern int ArgusCurses; void ArgusLog (int priority, char *fmt, ...) { va_list ap; char buf[1024], *ptr = buf; char *label = NULL; int i; if (priority == LOG_NOTICE) return; sprintf (buf, "%s[%d]: ", ArgusProgramName, (int)getpid()); ptr = &buf[strlen(buf)]; #if defined(__STDC__) va_start(ap, fmt); #else va_start(ap); #endif (void) vsprintf (ptr, fmt, ap); ptr = &buf[strlen(buf)]; va_end (ap); if (*fmt) { fmt += (int) strlen (fmt); if (fmt[-1] != '\n') sprintf (ptr, "\n"); } for (i = 0; i < ARGUSPRIORITYSTR; i++) if (ArgusPriorityStr[i].priority == priority) { label = ArgusPriorityStr[i].label; break; } if (ArgusCurses) { } else fprintf (stderr, "%s: %s\n", label, buf); switch (priority) { case LOG_ERR: ArgusShutDown(-1); break; default: break; } } argus-clients-2.0.6.fixes.1/common/argus_parse.c0000664000076600007660000042753707764412365015261 /* * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * argus_parse - parse argus output. * this module performs all the argus(1) related connection parsing, * selects datum from a set of criteria, and then calls specific * protocol dependant routines, depending on the selected datum. * at the end of processing, argus_parse calls an application * specific finish routine, RaParseComplete(), and when * connected to a remote data source, it supplies a periodic * timeout routine; * * this module defines all things, except: * * (void) usage ((char *) argv[0]); * this routine should print the standard usage message * for the specific application. * * ArgusClientInit (); this is the application specific init * routine, which is called after all parsing * initialization is done, prior to reading the * first monitor(1) datum. * * (void) ArgusClientTimeout (); * this routine is called every second, when * argus_parse is connected to a remote data source. * * process_man ((struct ArgusRecord *) ptr); * this routine should process management control events; * * process_tcp ((struct ArgusRecord *) ptr); * this routine should process tcp events; * * process_udp ((struct ArgusRecord *) ptr); * this routine should process tcp events; * * process_icmp ((struct ArgusRecord *) ptr); * this routine should process tcp events; * * process_ip ((struct ArgusRecord *) ptr); * this routine should process tcp events; * * process_arp ((struct ArgusRecord *) ptr); * this routine should process arp events; * * process_non_ip ((struct ArgusRecord *) ptr); * this routine should process all other events; * * (void) RaParseComplete (0); * this routine will be called after all the * monitor data has been read. * * * written by Carter Bullard * QoSient, LLC * */ #define ArgusParse #include #include #include #include #include #include #include #include #include #include #include int ArgusParseResourceFile (char *); void clearRaConfiguration (void); unsigned char *ArgusRemoteFilter = NULL; extern void ArgusLog (int, char *, ...); int ArgusParseInit = 0; extern void ArgusClientTimeout (void); #define ARGUS_READINGPREHDR 1 #define ARGUS_READINGHDR 2 #define ARGUS_READINGBLOCK 4 #define ARGUS_READINGDATAGRAM 8 struct ArgusOutputStruct { char *filename; struct stat statbuf; FILE *fd; }; void argus_parse_init (struct ARGUS_INPUT *input) { char errbuf[MAXSTRLEN]; char *device = NULL; struct tm *tm; struct argtimeval tvpbuf, *tvp = &tvpbuf; unsigned int net, mask; int i, fd = 0; if (input != NULL) fd = input->fd; if (initCon) { if (initCon->ahdr.status & ARGUS_ANON) anonymized++; input->ArgusLocalNet = htonl(initCon->argus_mar.localnet); input->ArgusNetMask = htonl(initCon->argus_mar.netmask); if (tflag && timearg) { tvp->tv_sec = ntohl(initCon->argus_mar.now.tv_sec); tm = localtime((time_t *) &tvp->tv_sec); if (check_time_format (tm, timearg)) ArgusLog (LOG_ERR, "time syntax error %s", timearg); } } else { if ((device = argus_lookupdev (errbuf)) != NULL) { argus_lookupnet(device, &net, &mask, errbuf); input->ArgusLocalNet = net; input->ArgusNetMask = mask; } } input->ArgusLastTime = ArgusRealTime; input->ArgusMarInterval = ntohs(input->ArgusInitCon.argus_mar.argusMrInterval); if (input->ArgusReadBuffer != NULL) { ArgusFree(input->ArgusReadBuffer); input->ArgusReadBuffer = NULL; } if (input->ArgusConvBuffer != NULL) { ArgusFree(input->ArgusConvBuffer); input->ArgusConvBuffer = NULL; } switch (input->mode) { case ARGUS_CISCO_DATA_SOURCE: { if (ArgusRemoteHostList) { input->ArgusReadSocketState = ARGUS_READINGDATAGRAM; input->ArgusReadSize = k_maxFlowPacketSize; } if (ArgusInputFileList) { input->ArgusReadSocketState = ARGUS_READINGPREHDR; input->ArgusReadSize = 4; } if ((input->ArgusReadBuffer = (unsigned char *)ArgusCalloc (1, k_maxFlowPacketSize)) == NULL) ArgusLog (LOG_ERR, "ArgusCalloc error %s", strerror(errno)); if ((input->ArgusConvBuffer = (u_char *)ArgusCalloc (1, k_maxFlowPacketSize)) == NULL) ArgusLog (LOG_ERR, "ArgusCalloc error %s", strerror(errno)); } break; case ARGUS_DATA_SOURCE: { if ((input->ArgusReadBuffer = (unsigned char *)ArgusCalloc (1, MAXSTRLEN)) == NULL) ArgusLog (LOG_ERR, "ArgusCalloc error %s", strerror(errno)); if ((input->ArgusConvBuffer = (u_char *)ArgusCalloc (1, MAXSTRLEN)) == NULL) ArgusLog (LOG_ERR, "ArgusCalloc error %s", strerror(errno)); #ifdef ARGUS_SASL if (input->ArgusSaslBuffer != NULL) ArgusFree(input->ArgusSaslBuffer); if ((input->ArgusSaslBuffer = (u_char *)ArgusCalloc (1, MAXSTRLEN)) == NULL) ArgusLog (LOG_ERR, "ArgusCalloc error %s", strerror(errno)); #endif /* ARGUS_SASL */ if (major_version > 1) input->ArgusReadSocketState = ARGUS_READINGHDR; else { input->ArgusReadSocketState = ARGUS_READINGBLOCK; input->ArgusReadSize = 60; } } } input->ArgusReadPtr = input->ArgusReadBuffer; input->ArgusConvPtr = input->ArgusConvBuffer; input->ArgusReadSocketSize = (input->ArgusReadSize < 0) ? sizeof(struct ArgusRecordHeader) : input->ArgusReadSize; if (!ArgusParseInit++) { for (i = 0; i < ARGUS_MAX_REMOTE_CONN; i++) ArgusRemoteFDs[i] = NULL; init_addrtoname (fflag, ArgusLocalNet, ArgusNetMask); } #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusParseInit (0x%x) returning\n", input); #endif } int ArgusPassNum = 1; int ArgusPortNum = 0; #if defined(CYGWIN) #include #endif char *getoptStr = "aAbB:cCd:D:E:e:f:F:GhH:L:M:nN:O:p:Pqr:RS:s:t:T:uU:Vvw:xXzZ:"; #define RaEnvItems 2 char *RaResourceEnvStr [] = { "HOME", "ARGUSHOME", }; char *RaOutputFilter = NULL; char *RaHomePath = NULL; void ArgusCloseInput(struct ARGUS_INPUT *); int ArgusReadStreamSocket (struct ARGUS_INPUT *); int ArgusReadCiscoStreamSocket (struct ARGUS_INPUT *); int ArgusReadCiscoDatagramSocket (struct ARGUS_INPUT *); int main (int argc, char **argv) { int i, cc, op, retn = 0, fd = 0, Scmdline = 0, rcmdline = 0; char *cmdbuf = NULL, *infile = NULL; char *envstr = NULL, *filter = NULL; char *tmparg; struct stat statbuf; static char path[MAXPATHNAMELEN]; struct timezone tz; int commandlinew = 0; extern char *optarg; extern int optind, opterr; opterr = 0; for (i = 0, cc = 0; i < argc; i++) cc += strlen(argv[i]); if (cc > 0) { int len = cc + (argc + 1); if ((ArgusProgramArgs = (char *) ArgusCalloc (len, sizeof(char))) != NULL) { for (i = 0, *ArgusProgramArgs = '\0'; i < argc; i++) { strcat (ArgusProgramArgs, argv[i]); strcat (ArgusProgramArgs, " "); } } else ArgusLog (LOG_ERR, "ArgusCalloc(%d, %d) failed %s", len, sizeof(char), strerror(errno)); } if (strchr (argv[0], '/')) argv[0] = strrchr(argv[0], '/') + 1; ArgusProgramName = argv[0]; if (gettimeofday(&ArgusRealTime, &tz) < 0) ArgusLog (LOG_ERR, "gettimeofday failed %s", strerror(errno)); ArgusGlobalTime = ArgusRealTime; thiszone = tz.tz_minuteswest * -60; if ((RaTmStruct = localtime ((time_t *)&ArgusRealTime.tv_sec))) { if (RaTmStruct->tm_isdst) thiszone += 3600; } else { ArgusLog (LOG_ERR, "%s: localtime: error %s", *argv, strerror(errno)); } snprintf (path, MAXPATHNAMELEN - 1, "/etc/ra.conf"); if (stat (path, &statbuf) == 0) ArgusParseResourceFile (path); if ((RaHomePath = getenv("ARGUSHOME")) != NULL) { snprintf (path, MAXPATHNAMELEN - 1, "%s/ra.conf", RaHomePath); if (stat (path, &statbuf) == 0) { ArgusParseResourceFile (path); } } if ((envstr = getenv("ARGUSPATH")) != NULL) { while ((RaHomePath = strtok(envstr, ":")) != NULL) { snprintf (path, MAXPATHNAMELEN - 1, "%s/.rarc", RaHomePath); if (stat (path, &statbuf) == 0) { ArgusParseResourceFile (path); break; } envstr = NULL; } } else { for (i = 0; i < RaEnvItems; i++) { envstr = RaResourceEnvStr[i]; if ((RaHomePath = getenv(envstr)) != NULL) { sprintf (path, "%s/.rarc", RaHomePath); if (stat (path, &statbuf) == 0) { ArgusParseResourceFile (path); break; } } } } if ((argv[optind]) != NULL) ArgusProgramOptions = strdup(copy_argv (&argv[optind])); while ((op = getopt (argc, argv, getoptStr)) != EOF) { switch (op) { case 'a': ++aflag; break; case 'A': ++Aflag; break; case 'b': ++bflag; break; case 'B': Bflag = atoi(optarg); break; case 'c': cflag++; break; case 'C': Cflag++; break; case 'D': Argusdflag = atoi (optarg); break; case 'd': ++dflag; if (strstr(ArgusProgramName, "sql") != NULL) dbstr = strdup (optarg); else if ((strncmp(ArgusProgramName, "rahistogram", 11)) && (strncmp(ArgusProgramName, "racricket", 9)) && (strncmp(ArgusProgramName, "rabins", 6))) { if ((dataarg = optarg) != NULL) { if ((retn = parseUserDataArg (&dataarg, argv, optind)) < 0) { usage (); } else { optind += retn; } } } else dflag = atoi(optarg); break; case 'e': estr = optarg; if (strncmp(ArgusProgramName, "ragrep", 6)) { if (!(strncasecmp(optarg, "ascii", 5))) eflag = ARGUS_ENCODE_ASCII; else if (!(strncasecmp(optarg, "encode64", 8))) eflag = ARGUS_ENCODE_64; else if (!(strncasecmp(optarg, "encode32", 8))) eflag = ARGUS_ENCODE_32; else usage(); } else { ArgusGrepSource++; ArgusGrepDestination++; if ((estr[0] == 's') && (estr[1] == ':')) { ArgusGrepDestination = 0; estr = &estr[2]; } if ((estr[0] == 'd') && (estr[1] == ':')) { ArgusGrepSource = 0; estr = &estr[2]; } } break; case 'E': exceptfile = optarg; setArgusWfile (optarg, NULL); break; case 'f': ArgusFlowModelFile = optarg; break; case 'F': if (!(ArgusParseResourceFile (optarg))) ArgusLog(LOG_ERR, "%s: %s", optarg, strerror(errno)); break; case 'G': Gflag++; break; case 'H': ++Hflag; Hstr = optarg; break; case 'I': ++Iflag; break; case 'L': Lflag = atoi(optarg); if (Lflag == 0) Lflag = -1; break; case 'l': ++lflag; break; case 'M': do { if (!(ArgusAddModeList (optarg))) { ArgusLog(LOG_ERR, "%s: error: file arg %s", *argv, optarg); } if ((optarg = argv[optind]) != NULL) if (*optarg != '-') optind++; } while (optarg && (*optarg != '-')); break; case 'n': ++nflag; break; case 'N': Nflag = atoi (optarg); break; case 'O': Oflag = atoi (optarg); break; case 'p': pflag = atoi (optarg); break; case 'P': Pflag++; break; case 'q': ++qflag; break; case 'r': ++rflag; Sflag = 0; if ((!rcmdline++) && (ArgusInputFileList != NULL)) ArgusDeleteFileList(); if (optarg == NULL) optarg = "-"; do { if (!(ArgusAddFileList (optarg, (Cflag ? ARGUS_CISCO_DATA_SOURCE : ARGUS_DATA_SOURCE), -1, -1))) { ArgusLog(LOG_ERR, "%s: error: file arg %s", *argv, optarg); } if ((optarg = argv[optind]) != NULL) if (*optarg != '-') optind++; } while (optarg && (*optarg != '-')); break; case 'R': ++Rflag; break; case 's': do { if (RaSOptionIndex < ARGUS_MAX_S_OPTIONS) RaSOptionStrings[RaSOptionIndex++] = strdup(optarg); else ArgusLog (LOG_ERR, "usage: number of -s options exceeds %d", ARGUS_MAX_S_OPTIONS); if ((optarg = argv[optind]) != NULL) if (*optarg != '-') optind++; } while (optarg && (*optarg != '-')); break; case 'S': ++Sflag; if ((!Scmdline++) && (ArgusRemoteHostList != NULL)) ArgusDeleteHostList(); if (!(ArgusAddHostList (optarg, (Cflag ? ARGUS_CISCO_DATA_SOURCE : ARGUS_DATA_SOURCE)))) { ArgusLog(LOG_ERR, "%s: host %s unknown", *argv, optarg); } break; case 't': ++tflag; if ((timearg = strdup(optarg)) != NULL) { if ((retn = parseTimeArg (&timearg, argv, optind, RaTmStruct)) < 0) { usage (); } else { optind += retn; } } break; case 'T': Tflag = atoi(optarg); break; case 'u': uflag++; break; case 'U': ustr = strdup(optarg); break; case 'v': vflag++; break; case 'V': Vflag++; break; case 'w': if (!commandlinew++) clearArgusWfile(); if ((tmparg = optarg) != NULL) { if ((*tmparg != '-') || ((*tmparg == '-') && (!(strcmp (tmparg, "-"))))) { if (argc == optind) filter = NULL; else { filter = argv[optind]; if (*filter == '-') { filter = NULL; } else optind++; } setArgusWfile (tmparg, filter); break; } } break; case 'x': ++xflag; break; case 'X': clearRaConfiguration (); break; case 'z': ++zflag; break; case 'Z': Zflag = *optarg; break; case 'h': default: usage (); /* NOTREACHED */ } } if (infile) cmdbuf = read_infile (infile); else { char *str; if ((str = argv[optind]) != NULL) { if (strcmp(str, "-") == 0) optind++; cmdbuf = copy_argv (&argv[optind]); } } if (cmdbuf) { if (*RaInputFilter != NULL) free(*RaInputFilter); *RaInputFilter = cmdbuf; } if (RaSOptionIndex > 0) RaProcessSOptions(); bzero ((char *) &ArgusFilterCode, sizeof (ArgusFilterCode)); if (ArgusFilterCompile (&ArgusFilterCode, *RaInputFilter, 1, ArgusNetMask) < 0) { ArgusLog (LOG_ERR, "%s: %s error\n", ArgusProgramName, *RaInputFilter); } else { if (cmdbuf) ArgusRemoteFilter = (unsigned char *) strdup(cmdbuf); else ArgusRemoteFilter = NULL; } ArgusClientInit (); if (bflag) { bpf_dump(&ArgusFilterCode, bflag); exit (0); } if (Sflag) { struct ARGUS_INPUT *addr; if ((addr = ArgusRemoteHostList) != NULL) { while (addr != NULL) { if ((addr->fd = ArgusGetServerSocket (addr)) >= 0) if ((ArgusReadConnection (addr, NULL)) >= 0) ArgusRemoteFDs[ArgusActiveServers++] = addr; addr = addr->nxt; } } ArgusReadStream(); } else { struct ARGUS_INPUT *addr; if (ArgusInputFileList == NULL) if (!(ArgusAddFileList ("-", (Cflag ? ARGUS_CISCO_DATA_SOURCE : ARGUS_DATA_SOURCE), -1, -1))) ArgusLog(LOG_ERR, "%s: error: file arg %s", *argv, optarg); for (i = 0; i < ArgusPassNum; i++) { addr = ArgusInputFileList; while (addr) { if (strcmp (addr->filename, "-")) { if (addr->fd < 0) { if ((addr->fd = open(addr->filename, O_RDONLY)) < 0) { #ifdef ARGUSDEBUG ArgusDebug (0, "open '%s': %s", addr->filename, strerror(errno)); #endif } } else if (lseek(addr->fd, 0, SEEK_SET) < 0) ArgusLog (LOG_ERR, "lseek '%s': %s", addr->filename, strerror(errno)); if (((ArgusReadConnection (addr, addr->filename)) >= 0)) { ArgusRemoteFDs[0] = addr; if (addr->ostart != -1) { addr->offset = addr->ostart + sizeof(struct ArgusRecord); if (lseek(addr->fd, addr->offset, SEEK_SET) < 0) ArgusLog (LOG_ERR, "lseek '%s': %s", addr->filename, strerror(errno)); } ArgusReadStream(); ArgusCloseInput(addr); } } else { addr->fd = 0; addr->ostart = -1; addr->ostop = -1; if (((ArgusReadConnection (addr, addr->filename)) >= 0)) { ArgusRemoteFDs[0] = addr; ArgusReadStream(); } } addr = addr->nxt; } RaParseComplete(ArgusPassNum - i); } } if (fd >= 0) { ArgusShutDown (0); } else retn = 1; #ifdef ARGUSDEBUG ArgusDebug (1, "main () exiting with %d\n", retn); #endif exit (retn); } void ArgusShutDown (int val) { #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusShutDown (%d)\n", val); #endif RaParseComplete (val); _exit (0); } void ArgusGenerateCanonicalRecord (struct ArgusRecord *, struct ArgusCanonicalRecord *); struct ArgusCanonicalRecord RaThisCanonBuf, *RaThisCanon = &RaThisCanonBuf; unsigned int ArgusTotalCount = 0; unsigned int ArgusTotalBytes = 0; int ArgusHandleDatum (struct ArgusRecord *ptr, struct bpf_program *filter) { int retn = 0; if (ptr != NULL) { int len = ntohs(ptr->ahdr.length); struct bpf_insn *fcode = filter->bf_insns; u_char buf[MAXSTRLEN]; totalrecords++; bcopy ((char *)ptr, (char *)ArgusOriginal, len); bcopy ((char *)ptr, (char *)&buf, len); switch (ptr->ahdr.type) { case ARGUS_MAR: case (ARGUS_MAR | ARGUS_CISCO_NETFLOW): case ARGUS_INDEX: case ARGUS_EVENT: marrecords++; break; case ARGUS_FAR: case ARGUS_DATASUP: farrecords++; break; } ArgusGenerateCanonicalRecord ((struct ArgusRecord *) ptr, RaThisCanon); if ((retn = argus_filter (fcode, RaThisCanon)) != 0) { #ifdef _LITTLE_ENDIAN ArgusNtoH ((struct ArgusRecord *)&buf); #endif ArgusThisFarStatus = ArgusIndexRecord ((struct ArgusRecord *)&buf, ArgusThisFarHdrs); if ((retn = check_time ((struct ArgusRecord *)&buf)) != 0) { struct ArgusRecord *argus = (struct ArgusRecord *)&buf; if (!(ptr->ahdr.type & ARGUS_MAR)) { unsigned int count, bytes; #define ARGUSMAXPACKETSIZE 65536 /* correct for 1.8x byte count bug */ if ((count = argus->argus_far.src.count) > 0) if ((bytes = argus->argus_far.src.bytes) > 0) if ((bytes/count) > ARGUSMAXPACKETSIZE) argus->argus_far.src.bytes = 0; if ((count = argus->argus_far.dst.count) > 0) if ((bytes = argus->argus_far.dst.bytes) > 0) if ((bytes/count) > ARGUSMAXPACKETSIZE) argus->argus_far.dst.bytes = 0; if (argus->argus_far.time.start.tv_usec < 0) { argus->argus_far.time.start.tv_sec--; argus->argus_far.time.start.tv_usec += 1000000; } if (argus->argus_far.time.last.tv_usec < 0) { argus->argus_far.time.last.tv_sec--; argus->argus_far.time.last.tv_usec += 1000000; } ArgusTotalCount += (argus->argus_far.src.count + argus->argus_far.dst.count); if (Aflag) ArgusTotalBytes += (argus->argus_far.src.appbytes + argus->argus_far.dst.appbytes); else ArgusTotalBytes += (argus->argus_far.src.bytes + argus->argus_far.dst.bytes); } if ((ArgusWfileList != NULL) && (!(ArgusListEmpty(ArgusWfileList)))) { struct ArgusWfileStruct *wfile = NULL, *start = NULL; if (RaWriteOut) { if ((wfile = ArgusFrontList(ArgusWfileList)) != NULL) { start = wfile; do { if ((exceptfile == NULL) || strcmp(wfile->filename, exceptfile)) if (!(((argus->ahdr.type & ARGUS_MAR) && (argus->ahdr.cause & ARGUS_START)))) if (ArgusWriteNewLogfile (wfile, ArgusOriginal)) ArgusLog (LOG_ERR, "ArgusWriteNewLogfile failed. %s", strerror(errno)); ArgusPopFrontList(ArgusWfileList); ArgusPushBackList(ArgusWfileList, wfile); wfile = ArgusFrontList(ArgusWfileList); } while (wfile != start); } } else RaProcessRecord ((struct ArgusRecord *)&buf); } else RaProcessRecord ((struct ArgusRecord *)&buf); } } else { if (RaWriteOut && exceptfile) { struct ArgusWfileStruct *wfile = NULL, *start = NULL; if ((wfile = ArgusFrontList(ArgusWfileList)) != NULL) { start = wfile; do { if (!(strcmp(wfile->filename, exceptfile))) { if (!((ptr->ahdr.type & ARGUS_MAR) && (ptr->ahdr.cause & ARGUS_START))) if (ArgusWriteNewLogfile (wfile, ArgusOriginal)) ArgusLog (LOG_ERR, "ArgusWriteNewLogfile failed. %s", strerror(errno)); break; } ArgusPopFrontList(ArgusWfileList); ArgusPushBackList(ArgusWfileList, wfile); wfile = ArgusFrontList(ArgusWfileList); } while (wfile != start); } } } retn = 0; if (ptr->ahdr.type & ARGUS_MAR) { switch (ptr->ahdr.cause) { case ARGUS_STOP: case ARGUS_SHUTDOWN: case ARGUS_ERROR: { #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusHandleDatum (0x%x, 0x%x) received closing Mar\n", ptr, filter); #endif if (Sflag) retn = 1; break; } } } } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusHandleDatum (0x%x, 0x%x) returning %d\n", ptr, filter, retn); #endif return (retn); } void ArgusGenerateCanonicalRecord (struct ArgusRecord *ptr, struct ArgusCanonicalRecord *canon) { int i, index = 0; struct ArgusFarHeaderStruct **hdrs = NULL; struct ArgusRecord *ar = (struct ArgusRecord *) canon; ptr->ahdr.length = ntohs(ptr->ahdr.length); ArgusThisFarStatus = ArgusIndexRecord (ptr, ArgusThisFarHdrs); ptr->ahdr.length = htons(ptr->ahdr.length); hdrs = ArgusThisFarHdrs; bzero ((char *)canon, sizeof(*canon)); if (ptr->ahdr.type & ARGUS_MAR) { bcopy ((char *)ptr, (char *)canon, sizeof(*ptr)); } else { bcopy ((char *)&ptr->ahdr, (char *)&canon->ahdr, sizeof(canon->ahdr)); for (i = 1; i < 33; i++) { index = 1 << (i - 1); switch (index) { case ARGUS_FAR_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_FAR_DSR_STATUS) bcopy((char *) hdrs[ARGUS_FAR_DSR_INDEX], (char *)&ar->argus_far, sizeof (ar->argus_far)); break; case ARGUS_MAC_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_MAC_DSR_STATUS) bcopy((char *) hdrs[ARGUS_MAC_DSR_INDEX], (char *)&canon->mac, sizeof(canon->mac)); break; case ARGUS_VLAN_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_VLAN_DSR_STATUS) bcopy((char *) hdrs[ARGUS_VLAN_DSR_INDEX], (char *)&canon->vlan, sizeof(canon->vlan)); break; case ARGUS_MPLS_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_MPLS_DSR_STATUS) bcopy((char *) hdrs[ARGUS_MPLS_DSR_INDEX], (char *)&canon->mpls, sizeof(canon->mpls)); break; case ARGUS_AGR_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_AGR_DSR_STATUS) bcopy((char *) hdrs[ARGUS_AGR_DSR_INDEX], (char *)&canon->agr, sizeof(canon->agr)); break; case ARGUS_TIME_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_TIME_DSR_STATUS) bcopy((char *) hdrs[ARGUS_TIME_DSR_INDEX], (char *)&canon->time, sizeof(canon->time)); break; case ARGUS_TCP_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) bcopy((char *) hdrs[ARGUS_TCP_DSR_INDEX], (char *)&canon->acr_tcp, sizeof(canon->acr_tcp)); break; case ARGUS_ICMP_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_ICMP_DSR_STATUS) bcopy((char *) hdrs[ARGUS_ICMP_DSR_INDEX], (char *)&canon->acr_icmp, sizeof(canon->acr_icmp)); break; case ARGUS_RTP_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_RTP_DSR_STATUS) bcopy((char *) hdrs[ARGUS_RTP_DSR_INDEX], (char *)&canon->acr_rtp, sizeof(canon->acr_rtp)); break; case ARGUS_ARP_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_ARP_DSR_STATUS) bcopy((char *) hdrs[ARGUS_ARP_DSR_INDEX], (char *)&canon->acr_arp, sizeof(canon->acr_arp)); break; case ARGUS_FRG_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_FRG_DSR_STATUS) bcopy((char *) hdrs[ARGUS_FRG_DSR_INDEX], (char *)&canon->acr_frag, sizeof(canon->acr_frag)); break; case ARGUS_ESP_DSR_STATUS: if (ArgusThisFarStatus & ARGUS_ESP_DSR_STATUS) bcopy((char *) hdrs[ARGUS_ESP_DSR_INDEX], (char *)&canon->acr_esp, sizeof(canon->acr_esp)); break; } } } #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusGenerateCanonicalRecord (0x%x, 0x%x) returning\n", ptr, canon); #endif } #include struct ArgusRecord *ArgusNetFlowCallRecord (u_char **); struct ArgusRecord *ArgusNetFlowDetailInt (u_char **); struct ArgusRecord *ArgusParseCiscoRecord (u_char **); struct ArgusRecord *ArgusParseCiscoRecordV1 (u_char **); struct ArgusRecord *ArgusParseCiscoRecordV5 (u_char **); struct ArgusRecord *ArgusParseCiscoRecordV6 (u_char **); unsigned char *ArgusNetFlowRecordHeader = NULL; unsigned char ArgusNetFlowArgusRecordBuf[1024]; struct ArgusRecord *ArgusNetFlowArgusRecord = (struct ArgusRecord *) ArgusNetFlowArgusRecordBuf; struct ArgusRecord * ArgusParseCiscoRecordV1 (u_char **ptr) { CiscoFlowEntryV1_t *entryPtrV1 = (CiscoFlowEntryV1_t *) *ptr; CiscoFlowHeaderV1_t *hdrPtrV1 = (CiscoFlowHeaderV1_t *) ArgusNetFlowRecordHeader; struct ArgusRecord *argus = ArgusNetFlowArgusRecord; struct ArgusMacStruct mac; *ptr += sizeof(CiscoFlowEntryV1_t); bzero ((char *) argus, sizeof (*argus)); argus->ahdr.type = ARGUS_FAR | ARGUS_CISCO_NETFLOW; argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.length = sizeof(argus->ahdr) + sizeof(argus->argus_far); argus->ahdr.status |= ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); if (hdrPtrV1) { long time; time = ntohl(entryPtrV1->first); argus->argus_far.time.start.tv_sec = (time - (long)hdrPtrV1->sysUptime)/1000; argus->argus_far.time.start.tv_sec += hdrPtrV1->unix_secs; argus->argus_far.time.start.tv_usec = ((time - (long)hdrPtrV1->sysUptime)%1000) * 1000; argus->argus_far.time.start.tv_usec += hdrPtrV1->unix_nsecs/1000; if (argus->argus_far.time.start.tv_usec >= 1000000) { argus->argus_far.time.start.tv_sec++; argus->argus_far.time.start.tv_usec -= 1000000; } if (argus->argus_far.time.start.tv_usec < 0) { argus->argus_far.time.start.tv_sec--; argus->argus_far.time.start.tv_usec += 1000000; } time = ntohl(entryPtrV1->last); argus->argus_far.time.last.tv_sec = (time - (long)hdrPtrV1->sysUptime)/1000; argus->argus_far.time.last.tv_sec += hdrPtrV1->unix_secs; argus->argus_far.time.last.tv_usec = ((time - (long)hdrPtrV1->sysUptime)%1000) * 1000; argus->argus_far.time.last.tv_usec += hdrPtrV1->unix_nsecs/1000; if (argus->argus_far.time.last.tv_usec >= 1000000) { argus->argus_far.time.last.tv_sec++; argus->argus_far.time.last.tv_usec -= 1000000; } if (argus->argus_far.time.last.tv_usec < 0) { argus->argus_far.time.last.tv_sec--; argus->argus_far.time.last.tv_usec += 1000000; } argus->argus_far.time.start.tv_usec = (argus->argus_far.time.start.tv_usec / 1000) * 1000; argus->argus_far.time.last.tv_usec = (argus->argus_far.time.last.tv_usec / 1000) * 1000; } argus->argus_far.flow.ip_flow.ip_src = ntohl(entryPtrV1->srcaddr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(entryPtrV1->dstaddr); argus->argus_far.flow.ip_flow.ip_p = entryPtrV1->prot; argus->argus_far.attr_ip.stos = entryPtrV1->tos; argus->argus_far.src.count = ntohl(entryPtrV1->pkts); argus->argus_far.src.bytes = ntohl(entryPtrV1->bytes); argus->argus_far.src.appbytes = 0; switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: { struct ArgusTCPObject tcpbuf, *tcp = &tcpbuf; bzero ((char *) tcp, sizeof(*tcp)); tcp->type = ARGUS_TCP_DSR; tcp->length = sizeof(struct ArgusTCPObject); tcp->src.flags = entryPtrV1->flags; if (tcp->src.flags & TH_RST) { if (argus->argus_far.src.count == 1) { if (tcp->src.flags == (TH_RST | TH_ACK)) tcp->state |= ARGUS_DST_RESET; else tcp->state |= ARGUS_SRC_RESET; } else tcp->state |= ARGUS_RESET; } if (tcp->src.flags & TH_FIN) tcp->state |= ARGUS_FIN; if ((tcp->src.flags & TH_ACK) || (tcp->src.flags & TH_PUSH) || (tcp->src.flags & TH_URG)) tcp->state |= ARGUS_CON_ESTABLISHED; switch (tcp->src.flags & (TH_SYN|TH_ACK)) { case (TH_SYN): tcp->state |= ARGUS_SAW_SYN; break; case (TH_SYN|TH_ACK): tcp->state |= ARGUS_SAW_SYN_SENT; if ((argus->argus_far.src.count + argus->argus_far.dst.count) == 1) tcp->state &= ~(ARGUS_CON_ESTABLISHED); break; } bcopy ((char *)tcp, &((char *)argus)[argus->ahdr.length], sizeof(*tcp)); argus->ahdr.length += sizeof(*tcp); } /* fall through to UDP switch to get the ports */ case IPPROTO_UDP: argus->argus_far.flow.ip_flow.sport = ntohs(entryPtrV1->srcport); argus->argus_far.flow.ip_flow.dport = ntohs(entryPtrV1->dstport); break; case IPPROTO_ICMP: { argus->argus_far.flow.icmp_flow.type = ((char *)&entryPtrV1->dstport)[0]; argus->argus_far.flow.icmp_flow.code = ((char *)&entryPtrV1->dstport)[1]; } break; } bzero ((char *)&mac, sizeof (mac)); mac.type = ARGUS_MAC_DSR; mac.length = sizeof(mac); mac.status = 0; entryPtrV1->input = ntohs(entryPtrV1->input); entryPtrV1->output = ntohs(entryPtrV1->output); bcopy((char *)&entryPtrV1->input, (char *)&mac.phys_union.ether.ethersrc[4], 2); bcopy((char *)&entryPtrV1->output,(char *)&mac.phys_union.ether.etherdst[4], 2); bcopy ((char *)&mac, &((char *)argus)[argus->ahdr.length], sizeof(mac)); argus->ahdr.length += sizeof(mac); #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusParseCiscoRecordV1 (0x%x) returning 0x%x\n", *ptr, argus); #endif return(argus); } struct ArgusRecord * ArgusParseCiscoRecordV5 (u_char **ptr) { CiscoFlowEntryV5_t *entryPtrV5 = ((CiscoFlowEntryV5_t *) *ptr); CiscoFlowHeaderV5_t *hdrPtrV5 = (CiscoFlowHeaderV5_t *) ArgusNetFlowRecordHeader; struct ArgusRecord *argus = ArgusNetFlowArgusRecord; struct ArgusMacStruct mac; *ptr += sizeof(CiscoFlowEntryV5_t); bzero ((char *) argus, sizeof (*argus)); argus->ahdr.type = ARGUS_FAR | ARGUS_CISCO_NETFLOW; argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.length = sizeof(argus->ahdr) + sizeof(argus->argus_far); argus->ahdr.status |= ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); if (hdrPtrV5) { long time; time = ntohl(entryPtrV5->first); argus->argus_far.time.start.tv_sec = (time - (long)hdrPtrV5->sysUptime)/1000; argus->argus_far.time.start.tv_sec += hdrPtrV5->unix_secs; argus->argus_far.time.start.tv_usec = ((time - (long)hdrPtrV5->sysUptime)%1000) * 1000; argus->argus_far.time.start.tv_usec += hdrPtrV5->unix_nsecs/1000; if (argus->argus_far.time.start.tv_usec >= 1000000) { argus->argus_far.time.start.tv_sec++; argus->argus_far.time.start.tv_usec -= 1000000; } if (argus->argus_far.time.start.tv_usec < 0) { argus->argus_far.time.start.tv_sec--; argus->argus_far.time.start.tv_usec += 1000000; } time = ntohl(entryPtrV5->last); argus->argus_far.time.last.tv_sec = (time - (long)hdrPtrV5->sysUptime)/1000; argus->argus_far.time.last.tv_sec += hdrPtrV5->unix_secs; argus->argus_far.time.last.tv_usec = ((time - (long)hdrPtrV5->sysUptime)%1000) * 1000; argus->argus_far.time.last.tv_usec += hdrPtrV5->unix_nsecs/1000; if (argus->argus_far.time.last.tv_usec >= 1000000) { argus->argus_far.time.last.tv_sec++; argus->argus_far.time.last.tv_usec -= 1000000; } if (argus->argus_far.time.last.tv_usec < 0) { argus->argus_far.time.last.tv_sec--; argus->argus_far.time.last.tv_usec += 1000000; } argus->argus_far.time.start.tv_usec = (argus->argus_far.time.start.tv_usec / 1000) * 1000; argus->argus_far.time.last.tv_usec = (argus->argus_far.time.last.tv_usec / 1000) * 1000; } argus->argus_far.flow.ip_flow.ip_src = ntohl(entryPtrV5->srcaddr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(entryPtrV5->dstaddr); argus->argus_far.flow.ip_flow.sport = ntohs(entryPtrV5->srcport); argus->argus_far.flow.ip_flow.dport = ntohs(entryPtrV5->dstport); argus->argus_far.flow.ip_flow.ip_p = entryPtrV5->prot; argus->argus_far.attr_ip.stos = entryPtrV5->tos; argus->argus_far.src.count = ntohl(entryPtrV5->pkts); argus->argus_far.src.bytes = ntohl(entryPtrV5->bytes); argus->argus_far.src.appbytes = 0; switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: { struct ArgusTCPObject tcpbuf, *tcp = &tcpbuf; bzero ((char *) tcp, sizeof(*tcp)); tcp->type = ARGUS_TCP_DSR; tcp->length = sizeof(struct ArgusTCPObject); tcp->src.flags = entryPtrV5->tcp_flags; if (tcp->src.flags & TH_RST) tcp->status |= ARGUS_RESET; if (tcp->src.flags & TH_FIN) tcp->status |= ARGUS_FIN; if ((tcp->src.flags & TH_ACK) || (tcp->src.flags & TH_PUSH) || (tcp->src.flags & TH_URG)) tcp->status |= ARGUS_CON_ESTABLISHED; switch (tcp->src.flags & (TH_SYN|TH_ACK)) { case (TH_SYN): tcp->status |= ARGUS_SAW_SYN; break; case (TH_SYN|TH_ACK): tcp->state |= ARGUS_SAW_SYN_SENT; if ((argus->argus_far.src.count + argus->argus_far.dst.count) == 1) tcp->state &= ~(ARGUS_CON_ESTABLISHED); break; } bcopy ((char *)tcp, &((char *)argus)[argus->ahdr.length], sizeof(*tcp)); argus->ahdr.length += sizeof(*tcp); } break; } bzero ((char *)&mac, sizeof (mac)); mac.type = ARGUS_MAC_DSR; mac.length = sizeof(mac); mac.status = 0; entryPtrV5->input = ntohs(entryPtrV5->input); entryPtrV5->output = ntohs(entryPtrV5->output); bcopy((char *)&entryPtrV5->input, (char *)&mac.phys_union.ether.ethersrc[4], 2); bcopy((char *)&entryPtrV5->output,(char *)&mac.phys_union.ether.etherdst[4], 2); bcopy ((char *)&mac, &((char *)argus)[argus->ahdr.length], sizeof(mac)); argus->ahdr.length += sizeof(mac); #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusParseCiscoRecordV5 (0x%x) returning 0x%x\n", *ptr, argus); #endif return (argus); } struct ArgusRecord * ArgusParseCiscoRecordV6 (u_char **ptr) { CiscoFlowEntryV6_t *entryPtrV6 = (CiscoFlowEntryV6_t *) *ptr; CiscoFlowHeaderV6_t *hdrPtrV6 = (CiscoFlowHeaderV6_t *) ArgusNetFlowRecordHeader; struct ArgusRecord *argus = ArgusNetFlowArgusRecord; struct ArgusMacStruct mac; *ptr += sizeof(CiscoFlowEntryV6_t); bzero ((char *) argus, sizeof (*argus)); argus->ahdr.type = ARGUS_FAR | ARGUS_CISCO_NETFLOW; argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.length = sizeof(argus->ahdr) + sizeof(argus->argus_far); argus->ahdr.status |= ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); if (hdrPtrV6) { long time; time = ntohl(entryPtrV6->first); argus->argus_far.time.start.tv_sec = (time - (long)hdrPtrV6->sysUptime)/1000; argus->argus_far.time.start.tv_sec += hdrPtrV6->unix_secs; argus->argus_far.time.start.tv_usec = ((time - (long)hdrPtrV6->sysUptime)%1000) * 1000; argus->argus_far.time.start.tv_usec += hdrPtrV6->unix_nsecs/1000; if (argus->argus_far.time.start.tv_usec >= 1000000) { argus->argus_far.time.start.tv_sec++; argus->argus_far.time.start.tv_usec -= 1000000; } if (argus->argus_far.time.start.tv_usec < 0) { argus->argus_far.time.start.tv_sec--; argus->argus_far.time.start.tv_usec += 1000000; } time = ntohl(entryPtrV6->last); argus->argus_far.time.last.tv_sec = (time - (long)hdrPtrV6->sysUptime)/1000; argus->argus_far.time.last.tv_sec += hdrPtrV6->unix_secs; argus->argus_far.time.last.tv_usec = ((time - (long)hdrPtrV6->sysUptime)%1000) * 1000; argus->argus_far.time.last.tv_usec += hdrPtrV6->unix_nsecs/1000; if (argus->argus_far.time.last.tv_usec >= 1000000) { argus->argus_far.time.last.tv_sec++; argus->argus_far.time.last.tv_usec -= 1000000; } if (argus->argus_far.time.last.tv_usec < 0) { argus->argus_far.time.last.tv_sec--; argus->argus_far.time.last.tv_usec += 1000000; } argus->argus_far.time.start.tv_usec = (argus->argus_far.time.start.tv_usec / 1000) * 1000; argus->argus_far.time.last.tv_usec = (argus->argus_far.time.last.tv_usec / 1000) * 1000; } argus->argus_far.flow.ip_flow.ip_src = ntohl(entryPtrV6->srcaddr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(entryPtrV6->dstaddr); argus->argus_far.flow.ip_flow.sport = ntohs(entryPtrV6->srcport); argus->argus_far.flow.ip_flow.dport = ntohs(entryPtrV6->dstport); argus->argus_far.flow.ip_flow.ip_p = entryPtrV6->prot; argus->argus_far.attr_ip.stos = entryPtrV6->tos; argus->argus_far.src.count = ntohl(entryPtrV6->pkts); argus->argus_far.src.bytes = ntohl(entryPtrV6->bytes); argus->argus_far.src.appbytes = 0; switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: { struct ArgusTCPObject tcpbuf, *tcp = &tcpbuf; bzero ((char *) tcp, sizeof(*tcp)); tcp->type = ARGUS_TCP_DSR; tcp->length = sizeof(struct ArgusTCPObject); tcp->src.flags = entryPtrV6->tcp_flags; if (tcp->src.flags & TH_RST) tcp->status |= ARGUS_RESET; if (tcp->src.flags & TH_FIN) tcp->status |= ARGUS_FIN; if ((tcp->src.flags & TH_ACK) || (tcp->src.flags & TH_PUSH) || (tcp->src.flags & TH_URG)) tcp->status |= ARGUS_CON_ESTABLISHED; switch (tcp->src.flags & (TH_SYN|TH_ACK)) { case (TH_SYN): tcp->status |= ARGUS_SAW_SYN; break; case (TH_SYN|TH_ACK): tcp->state |= ARGUS_SAW_SYN_SENT; if ((argus->argus_far.src.count + argus->argus_far.dst.count) == 1) tcp->state &= ~(ARGUS_CON_ESTABLISHED); break; } bcopy ((char *)tcp, &((char *)argus)[argus->ahdr.length], sizeof(*tcp)); argus->ahdr.length += sizeof(*tcp); } break; } bzero ((char *)&mac, sizeof (mac)); mac.type = ARGUS_MAC_DSR; mac.length = sizeof(mac); mac.status = 0; entryPtrV6->input = ntohs(entryPtrV6->input); entryPtrV6->output = ntohs(entryPtrV6->output); bcopy((char *)&entryPtrV6->input, (char *)&mac.phys_union.ether.ethersrc[4], 2); bcopy((char *)&entryPtrV6->output,(char *)&mac.phys_union.ether.etherdst[4], 2); bcopy ((char *)&mac, &((char *)argus)[argus->ahdr.length], sizeof(mac)); argus->ahdr.length += sizeof(mac); #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusParseCiscoRecord (0x%x) returning 0x%x\n", *ptr, argus); #endif return(argus); } struct ArgusRecord * ArgusParseCiscoRecord (u_char **ptr) { struct ArgusRecord *argus = ArgusNetFlowArgusRecord; unsigned short *sptr = (unsigned short *) *ptr; #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusParseCiscoRecord (0x%x) version %h\n", *ptr, *sptr); #endif switch (*sptr) { case Version1: { CiscoFlowHeaderV1_t *hdrPtrV1 = (CiscoFlowHeaderV1_t *) *ptr; CiscoFlowEntryV1_t *entryPtrV1 = (CiscoFlowEntryV1_t *) (hdrPtrV1 + 1); bzero ((char *) argus, sizeof (*argus)); argus->ahdr.type = ARGUS_FAR | ARGUS_CISCO_NETFLOW; argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.length = sizeof(argus->ahdr) + sizeof(argus->argus_far); argus->ahdr.status |= ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); if (hdrPtrV1) { long time; time = ntohl(entryPtrV1->first); argus->argus_far.time.start.tv_sec = (time - (long)hdrPtrV1->sysUptime)/1000; argus->argus_far.time.start.tv_sec += hdrPtrV1->unix_secs; argus->argus_far.time.start.tv_usec = ((time - (long)hdrPtrV1->sysUptime)%1000) * 1000; argus->argus_far.time.start.tv_usec += hdrPtrV1->unix_nsecs/1000; if (argus->argus_far.time.start.tv_usec >= 1000000) { argus->argus_far.time.start.tv_sec++; argus->argus_far.time.start.tv_usec -= 1000000; } if (argus->argus_far.time.start.tv_usec < 0) { argus->argus_far.time.start.tv_sec--; argus->argus_far.time.start.tv_usec += 1000000; } time = ntohl(entryPtrV1->last); argus->argus_far.time.last.tv_sec = (time - (long)hdrPtrV1->sysUptime)/1000; argus->argus_far.time.last.tv_sec += hdrPtrV1->unix_secs; argus->argus_far.time.last.tv_usec = ((time - (long)hdrPtrV1->sysUptime)%1000) * 1000; argus->argus_far.time.last.tv_usec += hdrPtrV1->unix_nsecs/1000; if (argus->argus_far.time.last.tv_usec >= 1000000) { argus->argus_far.time.last.tv_sec++; argus->argus_far.time.last.tv_usec -= 1000000; } if (argus->argus_far.time.last.tv_usec < 0) { argus->argus_far.time.last.tv_sec--; argus->argus_far.time.last.tv_usec += 1000000; } argus->argus_far.time.start.tv_usec = (argus->argus_far.time.start.tv_usec / 1000) * 1000; argus->argus_far.time.last.tv_usec = (argus->argus_far.time.last.tv_usec / 1000) * 1000; } argus->argus_far.flow.ip_flow.ip_src = ntohl(entryPtrV1->srcaddr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(entryPtrV1->dstaddr); argus->argus_far.flow.ip_flow.sport = ntohs(entryPtrV1->srcport); argus->argus_far.flow.ip_flow.dport = ntohs(entryPtrV1->dstport); argus->argus_far.flow.ip_flow.ip_p = entryPtrV1->prot; argus->argus_far.attr_ip.stos = entryPtrV1->tos; argus->argus_far.src.count = ntohl(entryPtrV1->pkts); argus->argus_far.src.bytes = ntohl(entryPtrV1->bytes); #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif break; } case Version5: { CiscoFlowHeaderV5_t *hdrPtrV5 = (CiscoFlowHeaderV5_t *) ptr; CiscoFlowEntryV5_t *entryPtrV5 = (CiscoFlowEntryV5_t *) (hdrPtrV5 + 1); bzero ((char *) argus, sizeof (*argus)); argus->ahdr.type = ARGUS_FAR | ARGUS_CISCO_NETFLOW; argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.length = sizeof(argus->ahdr) + sizeof(argus->argus_far); argus->ahdr.status |= ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); if (hdrPtrV5) { long time; time = ntohl(entryPtrV5->first); argus->argus_far.time.start.tv_sec = (time - (long)hdrPtrV5->sysUptime)/1000; argus->argus_far.time.start.tv_sec += hdrPtrV5->unix_secs; argus->argus_far.time.start.tv_usec = ((time - (long)hdrPtrV5->sysUptime)%1000) * 1000; argus->argus_far.time.start.tv_usec += hdrPtrV5->unix_nsecs/1000; if (argus->argus_far.time.start.tv_usec >= 1000000) { argus->argus_far.time.start.tv_sec++; argus->argus_far.time.start.tv_usec -= 1000000; } if (argus->argus_far.time.start.tv_usec < 0) { argus->argus_far.time.start.tv_sec--; argus->argus_far.time.start.tv_usec += 1000000; } time = ntohl(entryPtrV5->last); argus->argus_far.time.last.tv_sec = (time - (long)hdrPtrV5->sysUptime)/1000; argus->argus_far.time.last.tv_sec += hdrPtrV5->unix_secs; argus->argus_far.time.last.tv_usec = ((time - (long)hdrPtrV5->sysUptime)%1000) * 1000; argus->argus_far.time.last.tv_usec += hdrPtrV5->unix_nsecs/1000; if (argus->argus_far.time.last.tv_usec >= 1000000) { argus->argus_far.time.last.tv_sec++; argus->argus_far.time.last.tv_usec -= 1000000; } if (argus->argus_far.time.last.tv_usec < 0) { argus->argus_far.time.last.tv_sec--; argus->argus_far.time.last.tv_usec += 1000000; } argus->argus_far.time.start.tv_usec = (argus->argus_far.time.start.tv_usec / 1000) * 1000; argus->argus_far.time.last.tv_usec = (argus->argus_far.time.last.tv_usec / 1000) * 1000; } argus->argus_far.flow.ip_flow.ip_src = ntohl(entryPtrV5->srcaddr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(entryPtrV5->dstaddr); argus->argus_far.flow.ip_flow.sport = ntohs(entryPtrV5->srcport); argus->argus_far.flow.ip_flow.dport = ntohs(entryPtrV5->dstport); argus->argus_far.flow.ip_flow.ip_p = entryPtrV5->prot; argus->argus_far.attr_ip.stos = entryPtrV5->tos; argus->argus_far.src.count = ntohl(entryPtrV5->pkts); argus->argus_far.src.bytes = ntohl(entryPtrV5->bytes); argus->argus_far.src.appbytes = 0; #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif break; } case Version6: { CiscoFlowHeaderV6_t *hdrPtrV6 = (CiscoFlowHeaderV6_t *) ptr; CiscoFlowEntryV6_t *entryPtrV6 = (CiscoFlowEntryV6_t *) (hdrPtrV6 + 1); bzero ((char *) argus, sizeof (*argus)); argus->ahdr.type = ARGUS_FAR | ARGUS_CISCO_NETFLOW; argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.length = sizeof(argus->ahdr) + sizeof(argus->argus_far); argus->ahdr.status |= ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); if (hdrPtrV6) { long time; time = ntohl(entryPtrV6->first); argus->argus_far.time.start.tv_sec = (time - (long)hdrPtrV6->sysUptime)/1000; argus->argus_far.time.start.tv_sec += hdrPtrV6->unix_secs; argus->argus_far.time.start.tv_usec = ((time - (long)hdrPtrV6->sysUptime)%1000) * 1000; argus->argus_far.time.start.tv_usec += hdrPtrV6->unix_nsecs/1000; if (argus->argus_far.time.start.tv_usec >= 1000000) { argus->argus_far.time.start.tv_sec++; argus->argus_far.time.start.tv_usec -= 1000000; } if (argus->argus_far.time.start.tv_usec < 0) { argus->argus_far.time.start.tv_sec--; argus->argus_far.time.start.tv_usec += 1000000; } time = ntohl(entryPtrV6->last); argus->argus_far.time.last.tv_sec = (time - (long)hdrPtrV6->sysUptime)/1000; argus->argus_far.time.last.tv_sec += hdrPtrV6->unix_secs; argus->argus_far.time.last.tv_usec = ((time - (long)hdrPtrV6->sysUptime)%1000) * 1000; argus->argus_far.time.last.tv_usec += hdrPtrV6->unix_nsecs/1000; if (argus->argus_far.time.last.tv_usec >= 1000000) { argus->argus_far.time.last.tv_sec++; argus->argus_far.time.last.tv_usec -= 1000000; } if (argus->argus_far.time.last.tv_usec < 0) { argus->argus_far.time.last.tv_sec--; argus->argus_far.time.last.tv_usec += 1000000; } argus->argus_far.time.start.tv_usec = (argus->argus_far.time.start.tv_usec / 1000) * 1000; argus->argus_far.time.last.tv_usec = (argus->argus_far.time.last.tv_usec / 1000) * 1000; } argus->argus_far.flow.ip_flow.ip_src = ntohl(entryPtrV6->srcaddr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(entryPtrV6->dstaddr); argus->argus_far.flow.ip_flow.sport = ntohs(entryPtrV6->srcport); argus->argus_far.flow.ip_flow.dport = ntohs(entryPtrV6->dstport); argus->argus_far.flow.ip_flow.ip_p = entryPtrV6->prot; argus->argus_far.attr_ip.stos = entryPtrV6->tos; argus->argus_far.src.count = ntohl(entryPtrV6->pkts); argus->argus_far.src.bytes = ntohl(entryPtrV6->bytes); argus->argus_far.src.appbytes = 0; #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif break; } case Version8: { break; } } #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusParseCiscoRecord (0x%x) returning 0x%x\n", *ptr, argus); #endif return (argus); } struct ArgusRecord * ArgusNetFlowCallRecord (u_char **ptr) { struct ArgusRecord *argus = ArgusNetFlowArgusRecord; BinaryRecord_CallRecord_V1 *call = (BinaryRecord_CallRecord_V1 *) *ptr; if (*ptr) { bzero ((char *) argus, sizeof (*argus)); argus->ahdr.type = ARGUS_FAR | ARGUS_CISCO_NETFLOW; argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.length = sizeof(argus->ahdr) + sizeof(argus->argus_far); argus->ahdr.status |= ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); argus->argus_far.time.start.tv_sec = ntohl(call->starttime); argus->argus_far.time.last.tv_sec = ntohl(call->endtime); argus->argus_far.time.last.tv_usec = ntohl(call->activetime) % 1000000; argus->argus_far.time.last.tv_sec += ntohl(call->activetime) / 1000000; argus->argus_far.flow.ip_flow.ip_src = ntohl(call->srcaddr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(call->dstaddr); argus->argus_far.flow.ip_flow.sport = ntohs(call->srcport); argus->argus_far.flow.ip_flow.dport = ntohs(call->dstport); argus->argus_far.flow.ip_flow.ip_p = call->prot; argus->argus_far.attr_ip.stos = call->tos; argus->argus_far.src.count = ntohl(call->pkts); argus->argus_far.src.bytes = ntohl(call->octets); argus->argus_far.src.appbytes = 0; #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusNetFlowCallRecord (0x%x) returns 0x%x\n", *ptr, argus); #endif return (argus); } struct ArgusRecord * ArgusNetFlowDetailInt (u_char **ptr) { struct ArgusRecord *argus = ArgusNetFlowArgusRecord; BinaryRecord_DetailInterface_V1 *dint = (BinaryRecord_DetailInterface_V1 *) *ptr; if (*ptr) { dint = NULL; bzero ((char *) argus, sizeof (*argus)); } #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusNetFlowDetailInt (0x%x) returns 0x%x\n", *ptr, argus); #endif return (argus); } ArgusNetFlowHandler ArgusLookUpNetFlow(struct ARGUS_INPUT *, int); struct ArgusNetFlowParsers { int type, size; ArgusNetFlowHandler proc; }; struct ArgusNetFlowParsers ArgusNetFlowParsers [] = { { SourceNode, 0, NULL }, { DestNode, 0, NULL }, { HostMatrix, 0, NULL }, { SourcePort, 0, NULL }, { DestPort, 0, NULL }, { Protocol, 0, NULL }, { DetailDestNode, 0, NULL }, { DetailHostMatrix, 0, NULL }, { DetailInterface, sizeof(BinaryRecord_DetailInterface_V1), ArgusNetFlowDetailInt }, { CallRecord, sizeof(BinaryRecord_CallRecord_V1), ArgusNetFlowCallRecord }, { ASMatrix, 0, NULL }, { NetMatrix, 0, NULL }, { DetailSourceNode, 0, NULL }, { DetailASMatrix, 0, NULL }, { ASHostMatrix, 0, NULL }, { HostMatrixInterface, 0, NULL }, { DetailCallRecord, 0, NULL }, { RouterAS, 0, NULL }, { RouterProtoPort, 0, NULL }, { RouterSrcPrefix, 0, NULL }, { RouterDstPrefix, 0, NULL }, { RouterPrefix, 0, NULL }, { -1, 0, NULL }, }; ArgusNetFlowHandler ArgusCiscoNetFlowParse = NULL; int ArgusWriteConnection (struct ARGUS_INPUT *, unsigned char *, int); ArgusNetFlowHandler ArgusLookUpNetFlow(struct ARGUS_INPUT *input, int type) { ArgusNetFlowHandler retn = NULL; struct ArgusNetFlowParsers *p = ArgusNetFlowParsers; do { if (type == p->type) { retn = p->proc; input->ArgusReadSize = p->size; break; } p++; } while (p->type != -1); #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusLookUpNetFlow (0x%x, %d) returning 0x%x\n", input, type, retn); #endif return (retn); } extern char *ArgusVersionStr; #define CISCO_VERSION_1 1 #define CISCO_VERSION_5 5 #define CISCO_VERSION_6 6 #define CISCO_VERSION_8 8 int ArgusReadConnection (struct ARGUS_INPUT *input, char *filename) { struct ArgusCanonicalRecord canonbuf, *canon = &canonbuf; int cnt, fd = -1, found = 0, pipecmd = 0; struct ArgusRecord argus; u_char *ptr = (u_char *)&argus; unsigned char buf[0x10000]; char cmd[256]; if (input != NULL) { fd = input->fd; } else { fd = 0; } if (fd >= 0) { if (filename || (Sflag && (input->mode != ARGUS_CISCO_DATA_SOURCE))) { if ((cnt = read (fd, &argus, sizeof(argus.ahdr))) != sizeof(argus.ahdr)) ArgusLog (LOG_ERR, "ArgusReadConnection: read() failed. %s", strerror(errno)); #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadConnection() read %d bytes\n", cnt); #endif if (((ptr[0] == 0x1F) && ((ptr[1] == 0x8B) || (ptr[1] == 0x9D))) || ((ptr[0] == 'B') && (ptr[1] == 'Z') && (ptr[2] == 'h'))) { bzero(cmd, 256); close(fd); if (ptr[0] == 'B') strcpy(cmd, "bzip2 -dc "); else if (ptr[1] == 0x8B) strcpy(cmd, "gzip -dc "); else strcpy(cmd, "zcat "); strcat(cmd, filename); if ((input->pipe = popen(cmd, "r")) == NULL) { ArgusLog (LOG_ERR, "ArgusReadConnection: popen(%s) failed. %s", cmd, strerror(errno)); close (fd); return (-1); } else { pipecmd++; fd = fileno(input->pipe); if ((cnt = read (fd, &argus, sizeof(argus.ahdr))) != sizeof(argus.ahdr)) { #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusReadConnection: read from '%s' failed. %s", cmd, strerror(errno)); #endif pclose(input->pipe); input->pipe = NULL; close (fd); return (-1); } else { #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusReadConnection() read %d bytes from pipe\n", cnt); #endif } } } switch (input->mode) { case ARGUS_DATA_SOURCE: if (argus.ahdr.type & ARGUS_MAR) { unsigned short length = ntohs(argus.ahdr.length); unsigned int argusid = ntohl(argus.ahdr.argusid); unsigned int sequence = ntohl(argus.ahdr.seqNumber); unsigned int status = ntohl(argus.ahdr.status); if (argus.ahdr.cause & ARGUS_ERROR) { #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusReadConnection() ARGUS_ERROR Mar.\n"); #endif if (status & ARGUS_MAXLISTENEXCD) { ArgusLog (LOG_ALERT, "remote exceed listen error."); close (fd); return (-1); } } if (argus.ahdr.cause == ARGUS_START) { #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadConnection() ARGUS_START Mar.\n"); #endif input->status |= ARGUS_DATA_SOURCE; if ((argusid == ARGUS_COOKIE) && (sequence == 0)) { int size = length - sizeof(argus.ahdr); if ((cnt = read (fd, &argus.argus_mar, size)) != size) { #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusReadConnection() read failed for ARGUS_START Mar %s.\n", strerror(errno)); #endif close (fd); return (-1); } bcopy ((char *) &argus, (char *)&input->ArgusInitCon, sizeof (argus)); bcopy ((char *) &argus, (char *) ArgusOriginal, length); ArgusInput = input; fstat(fd, &input->statbuf); #ifdef _LITTLE_ENDIAN ArgusNtoH(&argus); #endif bcopy ((char *) &argus, (char *)&input->ArgusManStart, sizeof (argus)); input->major_version = MAJOR_VERSION_2; input->minor_version = MINOR_VERSION_0; input->ArgusReadSize = argus.argus_mar.record_len; #ifdef _LITTLE_ENDIAN ArgusHtoN(&argus); #endif ArgusHandleDatum ((struct ArgusRecord *)&argus, &ArgusFilterCode); #ifdef _LITTLE_ENDIAN ArgusNtoH(&argus); #endif argus_parse_init (input); if (Sflag && (input->major_version >= MAJOR_VERSION_2)) { if (ntohl(argus.ahdr.status) & ARGUS_SASL_AUTHENTICATE) { if (!(ArgusAuthenticate(input))) { ArgusLog (LOG_ALERT, "incorrect password", ArgusProgramName); close(fd); return (-1); } } if ((ArgusRemoteFilter != NULL) && (filename == NULL) && (fd != 0)) { int len; bzero(buf, MAXSTRLEN); snprintf ((char *) buf, MAXSTRLEN-1, "FILTER: man or (%s)", (char *) ArgusRemoteFilter); len = strlen((char *) buf); if (ArgusWriteConnection (input, (unsigned char *) buf, len) < 0) { ArgusLog (LOG_ALERT, "%s: write remote filter error %s.", strerror(errno)); close(fd); return (-1); } } } found++; } else { ArgusLog (LOG_ALERT, "ArgusReadConnection: not Argus-2.0 data stream."); close(fd); fd = -1; } } else { struct WriteStruct *ws = NULL; char *ptr; int size; bcopy ((char *)&argus, buf, sizeof(argus.ahdr)); size = sizeof(*ws) - sizeof(argus.ahdr); if ((cnt = read (fd, &buf[sizeof(argus.ahdr)], size)) != size) { fprintf (stderr, "%s: reading %d bytes, got %d bytes. %s", ArgusProgramName, size, cnt, strerror(errno)); close (fd); return (-1); } else ws = (struct WriteStruct *) buf; if ((ptr = strstr (ws->ws_init.initString, ArgusVersionStr)) != NULL) { ArgusConvertInitialWriteStruct (ws, &argus); input->major_version = argus.argus_mar.major_version; input->minor_version = argus.argus_mar.minor_version; input->ArgusReadSize = sizeof(*ws); if (initCon == NULL) { if ((initCon = (struct ArgusRecord *) calloc (1, sizeof (argus))) != NULL) bcopy ((char *) &argus, (char *) initCon, sizeof (argus)); } bcopy ((char *) &argus, (char *)&input->ArgusInitCon, sizeof (argus)); bcopy ((char *)&argus, (char *) ArgusOriginal, sizeof(argus)); ArgusInput = input; ArgusHandleDatum ((struct ArgusRecord *)&argus, &ArgusFilterCode); #ifdef _LITTLE_ENDIAN ArgusNtoH(&argus); #endif argus_parse_init (input); input->status |= ARGUS_DATA_SOURCE; found++; } else { ArgusLog (LOG_ALERT, "ArgusReadConnection: not Argus-2.0 data stream."); close(fd); fd = -1; } } break; } case ARGUS_CISCO_DATA_SOURCE: { char *ptr = (char *)&argus; #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusReadConnection() testing for CISCO records\n"); #endif if (!(strncmp(&ptr[3], "SOURCE", 6))) { BinaryHeaderF2 *ArgusNetFlow = (BinaryHeaderF2 *) buf; int size; bcopy ((char *)&argus, buf, sizeof(argus.ahdr)); size = sizeof(*ArgusNetFlow) - sizeof(argus.ahdr); if ((cnt = read (fd, &buf[sizeof(argus.ahdr)], size)) != size) { fprintf (stderr, "%s: reading %d bytes, got %d bytes. %s", ArgusProgramName, size, cnt, strerror(errno)); close (fd); return (-1); } else { #ifdef _LITTLE_ENDIAN ArgusNetFlow->starttime = ntohl(ArgusNetFlow->starttime); ArgusNetFlow->endtime = ntohl(ArgusNetFlow->endtime); ArgusNetFlow->flows = ntohl(ArgusNetFlow->flows); ArgusNetFlow->missed = ntohl(ArgusNetFlow->missed); ArgusNetFlow->records = ntohl(ArgusNetFlow->records); #endif bzero ((char *)&argus, sizeof(argus)); argus.ahdr.type = ARGUS_MAR | ARGUS_CISCO_NETFLOW; argus.ahdr.length = sizeof (argus); argus.ahdr.cause = ARGUS_START; argus.ahdr.argusid = ARGUS_COOKIE; argus.argus_mar.startime.tv_sec = ArgusNetFlow->starttime; argus.argus_mar.now.tv_sec = ArgusNetFlow->starttime; argus.argus_mar.major_version = major_version; argus.argus_mar.minor_version = minor_version; argus.argus_mar.flows = ArgusNetFlow->flows; argus.argus_mar.pktsDrop = ArgusNetFlow->missed; argus.argus_mar.record_len = -1; input->major_version = argus.argus_mar.major_version; input->minor_version = argus.argus_mar.minor_version; if ((input->ArgusCiscoNetFlowParse = ArgusLookUpNetFlow(input, ArgusNetFlow->aggregation)) != NULL) { #ifdef _LITTLE_ENDIAN ArgusHtoN(&argus); #endif if (initCon == NULL) { if ((initCon = (struct ArgusRecord *) calloc (1, sizeof (argus))) != NULL) bcopy ((char *) &argus, (char *) initCon, sizeof (argus)); } bcopy ((char *) &argus, (char *)&input->ArgusInitCon, sizeof (argus)); bcopy ((char *) &argus, (char *) ArgusOriginal, sizeof(argus)); ArgusInput = input; ArgusGenerateCanonicalRecord (&argus, canon); #ifdef _LITTLE_ENDIAN ArgusNtoH(&argus); #endif input->mode = ARGUS_DATA_SOURCE; argus_parse_init (input); if (check_time (&argus)) { if (!(ArgusWfileList) || !(ArgusWfileList || RaWriteOut)) RaProcessRecord(&argus); } input->mode = ARGUS_CISCO_DATA_SOURCE; found++; } else { fprintf (stderr, "%s: not supported Cisco data stream.\n", ArgusProgramName); close(fd); fd = -1; } } } else { unsigned short vers; switch (vers = ntohs(*(unsigned short *)ptr)) { case CISCO_VERSION_1: case CISCO_VERSION_5: case CISCO_VERSION_6: case CISCO_VERSION_8: found++; input->mode = ARGUS_CISCO_DATA_SOURCE; if (pipecmd) { pclose (input->pipe); close (fd); if ((input->pipe = popen(cmd, "r")) == NULL) { ArgusLog (LOG_ERR, "ArgusReadConnection: popen(%s) failed. %s", cmd, strerror(errno)); close (fd); return (-1); } else input->fd = fileno(input->pipe); } else lseek(fd, 0, SEEK_SET); argus_parse_init (input); #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusReadConnection() found cflowd record\n"); #endif } } if (!found) { ArgusLog (LOG_ALERT, "ArgusReadConnection: not Argus-2.0 data stream."); close(fd); fd = -1; } } } } else { if (input->mode == ARGUS_CISCO_DATA_SOURCE) { argus_parse_init (input); #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusReadConnection(0x%x) reading Cisco wire format\n", input); #endif } } } #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusReadConnection() returning %d\n", fd); #endif return (fd); } void ArgusRecordDump (struct ArgusRecord *); void ArgusDump (const u_char *, int); int setArgusRemoteFilter(unsigned char *); int setArgusRemoteFilter(unsigned char *str) { int retn = 0, len, i; struct ARGUS_INPUT *input = NULL; char buf[MAXSTRLEN]; if (str != NULL) { if (ArgusRemoteFilter != str) { if (ArgusRemoteFilter != NULL) free(ArgusRemoteFilter); ArgusRemoteFilter = str; } for (i = 0; i < ARGUS_MAX_REMOTE_CONN; i++) { if ((input = ArgusRemoteFDs[i]) != NULL) { if ((input->status & ARGUS_DATA_SOURCE) && (input->filename == NULL)) { bzero(buf, MAXSTRLEN); snprintf ((char *) buf, MAXSTRLEN-1, "FILTER: man or (%s)", (char *) ArgusRemoteFilter); len = strlen((char *) buf); if (ArgusWriteConnection (input, (unsigned char *) buf, len) < 0) { ArgusLog (LOG_ALERT, "%s: write remote filter error %s.", strerror(errno)); } } } } } #ifdef ARGUSDEBUG ArgusDebug (1, "setArgusRemoteFilter(%s) returning %d\n", str, retn); #endif return (retn); } int ArgusWriteConnection (struct ARGUS_INPUT *input, unsigned char *buf, int cnt) { int retn = 0, fd = 0, len = 0; unsigned char *output = NULL; if (input && (!input->filename)) { if ((fd = input->fd) > 2) { #ifdef ARGUS_SASL unsigned char outputbuf[MAXSTRLEN]; output = outputbuf; len = cnt; if (input->sasl_conn) { #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusWriteConnection: sasl_encode(0x%x, 0x%x, %d, 0x%x, 0x%x)\n", input->sasl_conn, buf, cnt, &output, &len); #endif if ((retn = sasl_encode(input->sasl_conn, buf, (unsigned int) cnt, (char **) &output, &len)) != SASL_OK) ArgusLog (LOG_ERR, "sasl_encode: failed returned %d", retn); } #else output = buf; len = cnt; #endif /* ARGUS_SASL */ #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusWriteConnection: write(%d, 0x%x, %d)\n", fd, output, len); #endif if ((retn = write (fd, output, len)) > 0) { } else ArgusLog (LOG_ERR, "ArgusWriteConnection(0x%x) error %s", input, strerror(errno)); #ifdef ARGUS_SASL if (output != outputbuf) free(output); #endif /* ARGUS_SASL */ } } #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusWriteConnection(0x%x, 0x%x, %d) returning %d\n", input, buf, cnt, len); #endif return (retn); } void ArgusCloseInput(struct ARGUS_INPUT *input) { if (input->pipe) { pclose(input->pipe); input->pipe = NULL; } if (Sflag) ArgusWriteConnection (input, (unsigned char *)"DONE: ", strlen("DONE: ")); if (input->ArgusReadBuffer != NULL) { ArgusFree(input->ArgusReadBuffer); input->ArgusReadBuffer = NULL; } if (input->ArgusConvBuffer != NULL) { ArgusFree(input->ArgusConvBuffer); input->ArgusConvBuffer = NULL; } #ifdef ARGUS_SASL if (input->ArgusSaslBuffer != NULL) { ArgusFree(input->ArgusSaslBuffer); input->ArgusSaslBuffer = NULL; } #endif /* ARGUS_SASL */ if (RaCloseInputFd) { close (input->fd); input->fd = -1; } #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusCloseInput(0x%x) done\n", input); #endif } #define HEXDUMP_BYTES_PER_LINE 16 #define HEXDUMP_SHORTS_PER_LINE (HEXDUMP_BYTES_PER_LINE / 2) #define HEXDUMP_HEXSTUFF_PER_SHORT 5 /* 4 hex digits and a space */ #define HEXDUMP_HEXSTUFF_PER_LINE \ (HEXDUMP_HEXSTUFF_PER_SHORT * HEXDUMP_SHORTS_PER_LINE) void ArgusRecordDump (struct ArgusRecord *argus) { int length = argus->ahdr.length; const u_char *cp = (const u_char *) argus; ArgusDump (cp, length); } void ArgusDump (const u_char *cp, int length) { u_int oset = 0; register u_int i; register int s1, s2; register int nshorts; char hexstuff[HEXDUMP_SHORTS_PER_LINE*HEXDUMP_HEXSTUFF_PER_SHORT+1], *hsp; char asciistuff[HEXDUMP_BYTES_PER_LINE+1], *asp; #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusDump(0x%x, %d)\n", cp, length); #endif nshorts = length / sizeof(u_short); i = 0; hsp = hexstuff; asp = asciistuff; while (--nshorts >= 0) { s1 = *cp++; s2 = *cp++; (void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff), " %02x%02x", s1, s2); hsp += HEXDUMP_HEXSTUFF_PER_SHORT; *(asp++) = (isgraph(s1) ? s1 : '.'); *(asp++) = (isgraph(s2) ? s2 : '.'); if (++i >= HEXDUMP_SHORTS_PER_LINE) { *hsp = *asp = '\0'; (void)printf("\n0x%04x\t%-*s\t%s", oset, HEXDUMP_HEXSTUFF_PER_LINE, hexstuff, asciistuff); i = 0; hsp = hexstuff; asp = asciistuff; oset += HEXDUMP_BYTES_PER_LINE; } } if (length & 1) { s1 = *cp++; (void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff), " %02x", s1); hsp += 3; *(asp++) = (isgraph(s1) ? s1 : '.'); ++i; } if (i > 0) { *hsp = *asp = '\0'; (void)printf("\n0x%04x\t%-*s\t%s", oset, HEXDUMP_HEXSTUFF_PER_LINE, hexstuff, asciistuff); } } #ifdef ARGUS_SASL #include int ArgusReadSaslStreamSocket (struct ARGUS_INPUT *); int ArgusReadSaslStreamSocket (struct ARGUS_INPUT *input) { int retn = 0, fd = input->fd, cnt = 0; unsigned int val = 0, *pval = &val; struct ArgusRecord *argus = NULL; char *output = NULL, *end = NULL, *ptr = NULL; unsigned int outputlen = 0; if ((retn = sasl_getprop(input->sasl_conn, SASL_MAXOUTBUF, (void **) &pval)) != SASL_OK) ArgusLog (LOG_ERR, "ArgusReadSaslStreamSocket: sasl_getprop %s", strerror(errno)); if (val == 0) val = MAXSTRLEN; bzero(input->ArgusSaslBuffer, MAXSTRLEN); if ((cnt = read (fd, input->ArgusSaslBuffer, val)) > 0) { ptr = input->ArgusSaslBuffer; #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadSaslStreamSocket (0x%x) read returned %d bytes\n", input, cnt); #endif if ((retn = sasl_decode (input->sasl_conn, ptr, cnt, &output, &outputlen)) == SASL_OK) { #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadSaslStreamSocket (0x%x) sasl_decoded %d bytes\n", input, outputlen); #endif if (outputlen) { argus = (struct ArgusRecord *) output; end = output + outputlen; while ((char *)argus < end) { input->ArgusReadSocketCnt = ntohs(argus->ahdr.length); bcopy ((char *) argus, input->ArgusReadBuffer, input->ArgusReadSocketCnt); if (ArgusHandleDatum (argus, &ArgusFilterCode) == 1) { if (Sflag) ArgusWriteConnection (input, "DONE: ", strlen("DONE: ")); retn = 1; break; } else (char *)argus += input->ArgusReadSocketCnt; } free (output); } } else ArgusLog (LOG_ERR, "ArgusReadSaslStreamSocket: sasl_decode (0x%x, 0x%x, %d, 0x%x, 0x%x) failed %d", input->sasl_conn, ptr, cnt, &output, &outputlen, retn); } else { retn = 1; if ((cnt < 0) && ((errno == EAGAIN) || (errno == EINTR))) { retn = 0; } else ArgusLog (LOG_ERR, "ArgusReadSaslStreamSocket: read (%d, 0x%x, %d) failed %s", fd, input->ArgusSaslBuffer, val, strerror(errno)); } #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadSaslStreamSocket (0x%x) returning %d\n", input, retn); #endif return (retn); } #endif /* ARGUS_SASL */ int ArgusReadStreamSocket (struct ARGUS_INPUT *input) { int retn = 0, fd = input->fd, cnt = 0; unsigned short length; #ifdef ARGUSDEBUG ArgusDebug (8, "ArgusReadStreamSocket (0x%x) starting\n", input); #endif if ((cnt = read (fd, input->ArgusReadPtr + input->ArgusReadSocketCnt, (input->ArgusReadSocketSize - input->ArgusReadSocketCnt))) > 0) { input->ArgusReadSocketCnt += cnt; #ifdef ARGUSDEBUG ArgusDebug (8, "ArgusReadStreamSocket (0x%x) read %d bytes\n", input, cnt); #endif if (input->ArgusReadSocketCnt == input->ArgusReadSocketSize) { if (input->ArgusReadSocketState == ARGUS_READINGHDR) { input->ArgusReadSocketState = ARGUS_READINGBLOCK; bcopy ((char *) &((struct ArgusRecordHeader *)input->ArgusReadPtr)->length, (char *) &length, sizeof(length)); input->ArgusReadSocketSize = ntohs(length) - sizeof(struct ArgusRecordHeader); if ((input->ArgusReadSocketSize >= 0) && (input->ArgusReadSocketSize < MAXSTRLEN)) { input->ArgusReadPtr = &input->ArgusReadBuffer[input->ArgusReadSocketCnt]; input->ArgusReadSocketCnt = 0; } else { ArgusLog(LOG_WARNING, "ArgusReadSocketStream: malformed argus record len %d", input->ArgusReadSocketSize + sizeof(struct ArgusRecordHeader)); return(1); } } else { if (input->major_version < 2) { ArgusConvertWriteStruct ((struct WriteStruct *)input->ArgusReadBuffer, (struct ArgusRecord *)input->ArgusConvBuffer); bcopy ((char *) input->ArgusConvBuffer, input->ArgusReadBuffer, MAXSTRLEN); } if (ArgusHandleDatum ((struct ArgusRecord *)input->ArgusReadBuffer, &ArgusFilterCode) == 1) { if (Sflag) { ArgusWriteConnection (input, (unsigned char *)"DONE: ", strlen("DONE: ")); retn = 1; } } if (input->major_version >= 2) { input->ArgusReadSocketState = ARGUS_READINGHDR; input->ArgusReadSocketSize = sizeof(struct ArgusRecordHeader); input->offset += input->ArgusReadSocketCnt + input->ArgusReadSocketSize; } else { input->offset += input->ArgusReadSocketCnt; } input->ArgusReadPtr = input->ArgusReadBuffer; bzero (input->ArgusReadBuffer, MAXSTRLEN); input->ArgusReadSocketCnt = 0; if (input->ostop != -1) if (input->offset > (input->ostop + sizeof(struct ArgusRecord))) retn = 1; } } } else { #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusReadStreamSocket (0x%x) read returned %d\n", input, cnt); #endif retn = 1; if ((cnt < 0) && ((errno == EAGAIN) || (errno == EINTR))) { retn = 0; } } #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusReadStreamSocket (0x%x) returning %d\n", input, retn); #endif return (retn); } int ArgusReadCiscoStreamSocket (struct ARGUS_INPUT *input) { int cnt = 0, retn = 0; #ifdef ARGUSDEBUG ArgusDebug (8, "ArgusReadCiscoStreamSocket (0x%x) starting\n", input); #endif if ((cnt = read (input->fd, input->ArgusReadPtr + input->ArgusReadSocketCnt, (input->ArgusReadSocketSize - input->ArgusReadSocketCnt))) > 0) { input->ArgusReadSocketCnt += cnt; #ifdef ARGUSDEBUG ArgusDebug (8, "ArgusReadCiscoStreamSocket (0x%x) read %d bytes, total %d need %d\n", input, cnt, input->ArgusReadSocketCnt, input->ArgusReadSocketSize); #endif if (input->ArgusReadSocketCnt == input->ArgusReadSocketSize) { switch (input->ArgusReadSocketState) { case ARGUS_READINGPREHDR: { unsigned short *sptr = (unsigned short *) input->ArgusReadPtr; input->ArgusReadCiscoVersion = ntohs(*sptr++); input->ArgusReadSocketNum = ntohs(*sptr); switch (input->ArgusReadCiscoVersion) { case CISCO_VERSION_1: input->ArgusReadSocketSize = sizeof(CiscoFlowHeaderV1_t) - 4; input->ArgusReadPtr = &input->ArgusReadBuffer[input->ArgusReadSocketCnt]; break; case CISCO_VERSION_5: input->ArgusReadSocketSize = sizeof(CiscoFlowHeaderV5_t) - 4; input->ArgusReadPtr = &input->ArgusReadBuffer[input->ArgusReadSocketCnt]; break; default: { #ifdef ARGUSDEBUG ArgusDebug (8, "ArgusReadCiscoStreamSocket (0x%x) read version %d preheader num %d\n", input, input->ArgusReadCiscoVersion, input->ArgusReadSocketNum); #endif } } input->ArgusReadSocketState = ARGUS_READINGHDR; input->ArgusReadSocketCnt = 0; break; } case ARGUS_READINGHDR: { #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusReadCiscoStreamSocket (0x%x) read record header\n", input); #endif switch (input->ArgusReadCiscoVersion) { case CISCO_VERSION_1: { CiscoFlowHeaderV1_t *ArgusNetFlow = (CiscoFlowHeaderV1_t *) input->ArgusReadBuffer; CiscoFlowHeaderV1_t *nfptr = ArgusNetFlow; input->ArgusCiscoNetFlowParse = ArgusParseCiscoRecordV1; input->ArgusReadSocketSize = sizeof(CiscoFlowEntryV1_t); input->ArgusReadPtr = &input->ArgusReadBuffer[sizeof(CiscoFlowHeaderV1_t)]; ArgusNetFlow->version = ntohs(nfptr->version); ArgusNetFlow->count = ntohs(nfptr->count); ArgusNetFlow->sysUptime = ntohl(nfptr->sysUptime); ArgusNetFlow->unix_secs = ntohl(nfptr->unix_secs); ArgusNetFlow->unix_nsecs = ntohl(nfptr->unix_nsecs); ArgusNetFlowRecordHeader = (char *)ArgusNetFlow; break; } case CISCO_VERSION_5: { CiscoFlowHeaderV5_t *ArgusNetFlow = (CiscoFlowHeaderV5_t *) input->ArgusReadBuffer; CiscoFlowHeaderV5_t *nfptr = ArgusNetFlow; input->ArgusCiscoNetFlowParse = ArgusParseCiscoRecordV5; input->ArgusReadSocketSize = sizeof(CiscoFlowEntryV5_t); input->ArgusReadPtr = &input->ArgusReadBuffer[sizeof(CiscoFlowHeaderV5_t)]; ArgusNetFlow->version = ntohs(nfptr->version); ArgusNetFlow->count = ntohs(nfptr->count); ArgusNetFlow->sysUptime = ntohl(nfptr->sysUptime); ArgusNetFlow->unix_secs = ntohl(nfptr->unix_secs); ArgusNetFlow->unix_nsecs = ntohl(nfptr->unix_nsecs); ArgusNetFlow->flow_sequence = ntohl(nfptr->flow_sequence); ArgusNetFlowRecordHeader = (char *)ArgusNetFlow; break; } default: { #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusReadCiscoStreamSocket (0x%x) read header\n", input); #endif } } input->ArgusReadSocketState = ARGUS_READINGBLOCK; input->ArgusReadBlockPtr = input->ArgusReadPtr; input->ArgusReadSocketCnt = 0; break; } default: #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusReadCiscoStreamSocket (0x%x) read record complete\n", input); #endif if (ArgusHandleDatum (input->ArgusCiscoNetFlowParse (&input->ArgusReadPtr), &ArgusFilterCode)) return(1); if (!(--input->ArgusReadSocketNum)) { input->ArgusReadPtr = input->ArgusReadBuffer; bzero (input->ArgusReadBuffer, k_maxFlowPacketSize); input->ArgusReadSocketState = ARGUS_READINGPREHDR; input->ArgusReadSocketSize = 4; } else { switch (input->ArgusReadCiscoVersion) { case CISCO_VERSION_1: input->ArgusReadPtr = &input->ArgusReadBuffer[sizeof(CiscoFlowHeaderV1_t)]; break; case CISCO_VERSION_5: input->ArgusReadPtr = &input->ArgusReadBuffer[sizeof(CiscoFlowHeaderV5_t)]; break; default: { #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusReadCiscoStreamSocket (0x%x) read header\n", input); #endif } } } input->ArgusReadSocketCnt = 0; break; } } } else { #ifdef ARGUSDEBUG if (cnt < 0) ArgusDebug (3, "ArgusReadCiscoStreamSocket (0x%x) read returned %d error %s\n", input, cnt, strerror(errno)); else ArgusDebug (6, "ArgusReadCiscoStreamSocket (0x%x) read returned %d\n", input, cnt); #endif retn = 1; if ((cnt < 0) && ((errno == EAGAIN) || (errno == EINTR))) { retn = 0; } } #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadCiscoStreamSocket (0x%x) returning %d\n", input, retn); #endif return (retn); } int ArgusCiscoDatagramSocketStart = 1; int ArgusReadCiscoDatagramSocket (struct ARGUS_INPUT *input) { int retn = 0, cnt = 0, count = 0, i = 0; unsigned short *sptr = NULL; unsigned char *ptr = NULL; #ifdef ARGUSDEBUG ArgusDebug (8, "ArgusReadCiscoDatagramSocket (0x%x) starting\n", input); #endif if ((cnt = read (input->fd, input->ArgusReadPtr, input->ArgusReadSocketSize)) > 0) { input->ArgusReadSocketCnt = cnt; sptr = (unsigned short *) input->ArgusReadPtr; ptr = (unsigned char *) input->ArgusReadPtr; #ifdef ARGUSDEBUG ArgusDebug (8, "ArgusReadCiscoDatagramSocket (0x%x) read %d bytes, capacity %d\n", input, cnt, input->ArgusReadSocketCnt, input->ArgusReadSocketSize); #endif #define CISCO_VERSION_1 1 #define CISCO_VERSION_5 5 #define CISCO_VERSION_6 6 #define CISCO_VERSION_8 8 switch (input->ArgusReadCiscoVersion = ntohs(*sptr)) { case CISCO_VERSION_1: { CiscoFlowHeaderV1_t *ArgusNetFlow = (CiscoFlowHeaderV1_t *) ptr; CiscoFlowHeaderV1_t *nfptr = (CiscoFlowHeaderV1_t *) sptr; input->ArgusCiscoNetFlowParse = ArgusParseCiscoRecordV1; ArgusNetFlow->version = ntohs(nfptr->version); ArgusNetFlow->count = ntohs(nfptr->count); ArgusNetFlow->sysUptime = ntohl(nfptr->sysUptime); ArgusNetFlow->unix_secs = ntohl(nfptr->unix_secs); ArgusNetFlow->unix_nsecs = ntohl(nfptr->unix_nsecs); ArgusNetFlowRecordHeader = ptr; ptr = (unsigned char *) (nfptr + 1); count = ArgusNetFlow->count; } break; case CISCO_VERSION_5: { CiscoFlowHeaderV5_t *ArgusNetFlow = (CiscoFlowHeaderV5_t *) ptr; CiscoFlowHeaderV5_t *nfptr = (CiscoFlowHeaderV5_t *) sptr; input->ArgusCiscoNetFlowParse = ArgusParseCiscoRecordV5; ArgusNetFlow->version = ntohs(nfptr->version); ArgusNetFlow->count = ntohs(nfptr->count); ArgusNetFlow->sysUptime = ntohl(nfptr->sysUptime); ArgusNetFlow->unix_secs = ntohl(nfptr->unix_secs); ArgusNetFlow->unix_nsecs = ntohl(nfptr->unix_nsecs); ArgusNetFlow->flow_sequence = ntohl(nfptr->flow_sequence); ArgusNetFlowRecordHeader = ptr; ptr = (unsigned char *) (nfptr + 1); count = ArgusNetFlow->count; } break; case CISCO_VERSION_6: { CiscoFlowHeaderV6_t *ArgusNetFlow = (CiscoFlowHeaderV6_t *) ptr; CiscoFlowHeaderV6_t *nfptr = (CiscoFlowHeaderV6_t *) sptr; input->ArgusCiscoNetFlowParse = ArgusParseCiscoRecordV6; ArgusNetFlow->version = ntohs(nfptr->version); ArgusNetFlow->count = ntohs(nfptr->count); ArgusNetFlow->sysUptime = ntohl(nfptr->sysUptime); ArgusNetFlow->unix_secs = ntohl(nfptr->unix_secs); ArgusNetFlow->unix_nsecs = ntohl(nfptr->unix_nsecs); ArgusNetFlow->flow_sequence = ntohl(nfptr->flow_sequence); ArgusNetFlowRecordHeader = ptr; ptr = (unsigned char *) (nfptr + 1); count = ArgusNetFlow->count; } break; case CISCO_VERSION_8: { CiscoFlowHeaderV8_t *ArgusNetFlow = (CiscoFlowHeaderV8_t *) ptr; CiscoFlowHeaderV8_t *nfptr = (CiscoFlowHeaderV8_t *) sptr; ArgusNetFlow->version = ntohs(nfptr->version); ArgusNetFlow->count = ntohs(nfptr->count); ArgusNetFlow->sysUptime = ntohl(nfptr->sysUptime); ArgusNetFlow->unix_secs = ntohl(nfptr->unix_secs); ArgusNetFlow->unix_nsecs = ntohl(nfptr->unix_nsecs); ArgusNetFlow->flow_sequence = ntohl(nfptr->flow_sequence); ArgusNetFlowRecordHeader = ptr; ptr = (unsigned char *) (nfptr + 1); count = ArgusNetFlow->count; if ((input->ArgusCiscoNetFlowParse = ArgusLookUpNetFlow(input, ArgusNetFlow->agg_method)) != NULL) { } } break; } for (i = 0; i < count; i++) { if (ArgusHandleDatum (input->ArgusCiscoNetFlowParse (&ptr), &ArgusFilterCode)) return(1); } } else { #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusReadCiscoDatagramSocket (0x%x) read returned %d error %s\n", input, cnt, strerror(errno)); #endif if ((cnt < 0) && ((errno == EAGAIN) || (errno == EINTR))) { retn = 0; } else retn = 1; } #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadCiscoDatagramSocket (0x%x) returning %d\n", input, retn); #endif return (retn); } void ArgusReadStream () { int retn = 0, width = -1, i, found = 0; struct timeval wait, timeoutValue; struct ARGUS_INPUT *input = NULL; fd_set readmask; for (i = 0; i < ARGUS_MAX_REMOTE_CONN; i++) if (ArgusRemoteFDs[i] != NULL) found++; if (!(found)) { #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusReadStream() ArgusRemoteFDs is empty\n"); #endif return; } bzero ((char *)&timeoutValue, sizeof(timeoutValue)); if (gettimeofday (&ArgusRealTime, NULL) == 0) { ArgusAdjustGlobalTime(&ArgusRealTime); FD_ZERO (&readmask); for (i = 0; i < ARGUS_MAX_REMOTE_CONN; i++) if (ArgusRemoteFDs[i] != NULL) { FD_SET (ArgusRemoteFDs[i]->fd, &readmask); width = (width < ArgusRemoteFDs[i]->fd) ? ArgusRemoteFDs[i]->fd : width; } width++; wait.tv_sec = 0; wait.tv_usec = 20000; #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusReadStream() starting\n"); #endif for (;;) { if ((retn = select (width, &readmask, NULL, NULL, &wait)) >= 0) { gettimeofday (&ArgusRealTime, NULL); for (i = 0; i < ARGUS_MAX_REMOTE_CONN; i++) { if ((input = ArgusRemoteFDs[i]) != NULL) { if (FD_ISSET (input->fd, &readmask)) { ArgusInput = input; input->ArgusLastTime = ArgusRealTime; switch (input->mode) { case ARGUS_DATA_SOURCE: #ifdef ARGUS_SASL if (input->sasl_conn) { if (ArgusReadSaslStreamSocket (input)) { ArgusCloseInput(input); ArgusRemoteFDs[i] = NULL; } } else #endif /* ARGUS_SASL */ if (ArgusReadStreamSocket (input)) { ArgusCloseInput(input); ArgusRemoteFDs[i] = NULL; } break; case ARGUS_CISCO_DATA_SOURCE: if (ArgusRemoteHostList) if (ArgusReadCiscoDatagramSocket (input)) { ArgusCloseInput(input); ArgusRemoteFDs[i] = NULL; } if (ArgusInputFileList) if (ArgusReadCiscoStreamSocket (input)) { ArgusCloseInput(input); ArgusRemoteFDs[i] = NULL; } break; } } if (ArgusGlobalTime.tv_usec < 0) ArgusGlobalTime.tv_usec = 0; ArgusAdjustGlobalTime(&ArgusRealTime); if (input->hostname && input->ArgusMarInterval) { if (input->ArgusLastTime.tv_sec) { if ((ArgusRealTime.tv_sec - input->ArgusLastTime.tv_sec) > (3 * input->ArgusMarInterval)) { ArgusLog (LOG_WARNING, "ArgusReadStream %s: idle stream: closing", input->hostname); ArgusCloseInput(input); ArgusRemoteFDs[i] = NULL; } } } } } if (timeoutValue.tv_sec == 0) { timeoutValue = ArgusGlobalTime; timeoutValue.tv_sec += RaClientTimeout.tv_sec; timeoutValue.tv_usec += RaClientTimeout.tv_usec; if (timeoutValue.tv_usec >= 1000000) { timeoutValue.tv_sec += 1; timeoutValue.tv_usec -= 1000000; } if (timeoutValue.tv_usec < 0) { timeoutValue.tv_usec = 0; } } if ((ArgusRealTime.tv_sec > timeoutValue.tv_sec) || ((ArgusRealTime.tv_sec == timeoutValue.tv_sec) && (ArgusRealTime.tv_usec > timeoutValue.tv_usec))) { ArgusClientTimeout (); if (Tflag) { if ((Tflag - 1) == 0) { ArgusShutDown(0); } Tflag--; } timeoutValue = ArgusRealTime; timeoutValue.tv_sec += RaClientTimeout.tv_sec; timeoutValue.tv_usec += RaClientTimeout.tv_usec; if (timeoutValue.tv_usec >= 1000000) { timeoutValue.tv_sec += 1; timeoutValue.tv_usec -= 1000000; } if (timeoutValue.tv_usec < 0) { timeoutValue.tv_usec = 0; } } width = -1; FD_ZERO (&readmask); for (i = 0; i < ARGUS_MAX_REMOTE_CONN; i++) if (ArgusRemoteFDs[i] != NULL) { FD_SET (ArgusRemoteFDs[i]->fd, &readmask); width = (width < ArgusRemoteFDs[i]->fd) ? ArgusRemoteFDs[i]->fd : width; } if (width < 0) break; else width++; wait.tv_sec = 0; wait.tv_usec = 20000; } else { #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusReadStream() select returned %s\n", strerror(errno)); #endif if (errno != EINTR) break; } } } #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadStream() returning\n"); #endif } #include int ArgusTotalRecords = 0; /* void ArgusProcessRecord (struct ArgusRecord *ptr) { if (ptr->ahdr.type & ARGUS_MAR) process_man (ptr); else { switch (ptr->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (ptr->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: process_tcp (ptr); break; case IPPROTO_UDP: process_udp (ptr); break; case IPPROTO_ICMP: process_icmp (ptr); break; default: process_ip (ptr); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: process_arp (ptr); break; default: process_non_ip (ptr); break; } } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusProcessRecord (0x%x) returning\n", ptr); #endif } */ #include extern void ArgusLog (int, char *, ...); #define ARGUS_DEFAULTCISCOPORT 9995 char *ArgusRecordType = NULL; extern int ArgusInitializeAuthentication(void); #include #include int ArgusGetServerSocket (struct ARGUS_INPUT *input) { int retn = -1; struct sockaddr_in server; struct servent *sp; struct hostent *hp; int s, type = 0; unsigned short portnum = 0; if (input->status & ARGUS_DATA_SOURCE) { ArgusRecordType = "Argus"; type = SOCK_STREAM; if (!input->portnum) { if (!ArgusPortNum) { if ((sp = getservbyname ("monitor", "tcp")) != NULL) portnum = sp->s_port; else portnum = htons(ARGUS_DEFAULTPORT); } else portnum = htons(ArgusPortNum); input->portnum = ntohs(portnum); } else portnum = htons(input->portnum); } else { if (input->status & ARGUS_CISCO_DATA_SOURCE) { struct ArgusRecord argus; ArgusRecordType = "Netflow"; type = SOCK_DGRAM; if (!input->portnum) { if (!ArgusPortNum) portnum = htons(ARGUS_DEFAULTCISCOPORT); else portnum = htons(ArgusPortNum); input->portnum = ntohs(portnum); } else portnum = htons(input->portnum); bzero ((char *)&argus, sizeof(argus)); argus.ahdr.type = ARGUS_MAR | ARGUS_CISCO_NETFLOW; argus.ahdr.length = sizeof (argus); argus.ahdr.cause = ARGUS_START; argus.ahdr.argusid = ARGUS_COOKIE; argus.argus_mar.startime.tv_sec = ArgusGlobalTime.tv_sec; argus.argus_mar.now.tv_sec = ArgusGlobalTime.tv_sec; argus.argus_mar.major_version = major_version; argus.argus_mar.minor_version = minor_version; argus.argus_mar.record_len = -1; input->major_version = argus.argus_mar.major_version; input->minor_version = argus.argus_mar.minor_version; #ifdef _LITTLE_ENDIAN ArgusHtoN(&argus); #endif bcopy ((char *) &argus, (char *)&input->ArgusInitCon, sizeof (argus)); bcopy ((char *) &argus, (char *) ArgusOriginal, sizeof(argus)); ArgusInput = input; } else ArgusLog (LOG_ERR, "ArgusGetServerSocket(0x%x) unknown type", input); } bzero ((char *) &server, sizeof (server)); if ((s = socket (AF_INET, type, 0)) >= 0) { if (type == SOCK_DGRAM) { if (input->addr != 0) server.sin_addr.s_addr = htonl(input->addr); else server.sin_addr.s_addr = INADDR_ANY; server.sin_family = AF_INET; server.sin_port = portnum; fprintf (stderr, "%s: Binding %s:%d Expecting %s records\n", ArgusProgramName, ipaddr_string(&input->addr), ntohs(portnum), ArgusRecordType); if ((bind (s, (struct sockaddr *)&server, sizeof(server))) < 0) ArgusLog (LOG_ERR, "bind (%d, %s:%hu, %d) failed %s", s, inet_ntoa(server.sin_addr), server.sin_port, sizeof(server), strerror(errno)); retn = s; input->fd = s; } else { int optval = 1; if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(int)) < 0) { #ifdef ARGUSDEBUG ArgusDebug (2, "setsockopt(%d, SOL_SOCKET, SO_KEEPALIVE, 0x%x, %d) failed:", s, optval, sizeof(int)); #endif } input->addr = htonl(input->addr); if ((hp = gethostbyaddr ((char *)&input->addr, sizeof (input->addr), AF_INET)) != NULL) { input->hostname = strdup(hp->h_name); bcopy ((char *) hp->h_addr, (char *)&server.sin_addr, hp->h_length); server.sin_family = hp->h_addrtype; server.sin_port = portnum; #ifdef ARGUSDEBUG ArgusDebug (1, "Trying %s port %d Expecting %s records\n", (hp->h_name) ? (hp->h_name) : intoa (input->addr), ntohs(portnum), ArgusRecordType); #endif } else { server.sin_addr.s_addr = input->addr; server.sin_family = AF_INET; server.sin_port = portnum; #ifdef ARGUSDEBUG ArgusDebug (1, "Trying %s port %d Expecting %s records\n", intoa (input->addr), ntohs(portnum), ArgusRecordType); #endif } input->addr = htonl(input->addr); if ((connect (s, (struct sockaddr *)&server, sizeof(server))) < 0) { ArgusLog (LOG_WARNING, "connect to %s:%hu failed %s", inet_ntoa(server.sin_addr), ntohs(server.sin_port), strerror(errno)); } else { retn = s; input->fd = s; #ifdef ARGUSDEBUG if (type == SOCK_DGRAM) ArgusDebug (1, "receiving\n"); else ArgusDebug (1, "connected\n"); #endif } } } else { ArgusLog (LOG_ERR, "ArgusGetServerSocket: socket() failed. %s", strerror(errno)); } #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusGetServerSocket (0x%x) returning %d\n", input, retn); #endif return (retn); } int ArgusAddModeList (char *ptr) { int retn = 0; struct ArgusModeStruct *mode, *list; if (ptr) { if ((mode = (struct ArgusModeStruct *) ArgusCalloc (1, sizeof(struct ArgusModeStruct))) != NULL) { if ((list = ArgusModeList) != NULL) { while (list->nxt) list = list->nxt; list->nxt = mode; } else ArgusModeList = mode; mode->mode = strdup(ptr); retn = 1; } } #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusAddModeList (%s) returning %d\n", ptr, retn); #endif return (retn); } int ArgusAddFileList (char *ptr, int mode, int ostart, int ostop) { register int retn = 0; register struct ARGUS_INPUT *file, *list; if (ptr) { if ((file = (struct ARGUS_INPUT *) ArgusCalloc (1, sizeof(struct ARGUS_INPUT))) != NULL) { if ((list = ArgusInputFileList) != NULL) { while (list->nxt) list = list->nxt; list->nxt = file; } else ArgusInputFileList = file; file->mode = mode; file->ostart = ostart; file->ostop = ostop; file->filename = strdup(ptr); file->fd = -1; retn = 1; } } #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusAddFileList (%s) returning %d\n", ptr, retn); #endif return (retn); } void ArgusDeleteFileList () { struct ARGUS_INPUT *addr = ArgusInputFileList; while (addr) { if (addr->filename) free(addr->filename); addr = addr->nxt; ArgusFree(ArgusInputFileList); ArgusInputFileList = addr; } #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusDeleteFileList () returning\n"); #endif } #include #include #include int ArgusAddHostList (char *str, int mode) { int retn = 0; struct ARGUS_INPUT *addr = NULL; long int portnum = 0; char *ptr = NULL, *endptr = NULL; unsigned int **p; struct hostent *hp = NULL; if ((ptr = strchr (str, (int)':')) != NULL) { *ptr++ = '\0'; portnum = strtol(ptr, &endptr, 10); if ((hp = gethostbyname(str)) != NULL) { for (p = (unsigned int **)hp->h_addr_list; *p; ++p) **p = ntohl(**p); } else { switch (h_errno) { case HOST_NOT_FOUND: case TRY_AGAIN: ArgusLog (LOG_ERR, "host %s unknown", str); break; case NO_ADDRESS: ArgusLog (LOG_ERR, "host %s has no IP address", str); break; case NO_RECOVERY: ArgusLog (LOG_ERR, "name server error", str); break; } } } else { if (mode == ARGUS_CISCO_DATA_SOURCE) { if (isdigit((int)*str)) portnum = strtol(str, &endptr, 10); else ArgusLog (LOG_ERR, "ArgusAddHostList: format error %s no port value.", str); } else { if ((hp = gethostbyname(str)) != NULL) { for (p = (unsigned int **)hp->h_addr_list; *p; ++p) **p = ntohl(**p); } else { switch (h_errno) { case HOST_NOT_FOUND: case TRY_AGAIN: ArgusLog (LOG_ERR, "host %s unknown", str); break; case NO_ADDRESS: ArgusLog (LOG_ERR, "host %s has no IP address", str); break; case NO_RECOVERY: ArgusLog (LOG_ERR, "name server error", str); break; } } } } if ((addr = (struct ARGUS_INPUT *) ArgusCalloc (1, sizeof (struct ARGUS_INPUT))) != NULL) { addr->nxt = ArgusRemoteHostList; ArgusRemoteHostList = addr; if (hp != NULL) { addr->addr = **(unsigned int **)hp->h_addr_list; addr->hostname = strdup(hp->h_name); } addr->mode = mode; addr->portnum = portnum; addr->status |= mode; addr->ostart = -1; addr->ostop = -1; retn = 1; } else ArgusLog (LOG_ERR, "ArgusAddHostList(%s) ArgusCalloc %s", str, strerror(errno)); #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusAddHostList (%s, %d) returning %d\n", str, mode, retn); #endif return (retn); } void ArgusDeleteHostList () { struct ARGUS_INPUT *addr = ArgusRemoteHostList; while (addr) { if (addr->hostname) free(addr->hostname); addr = addr->nxt; ArgusFree(ArgusRemoteHostList); ArgusRemoteHostList = addr; } #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusDeleteHostList () returning\n"); #endif } int ArgusWriteNewLogfile (struct ArgusWfileStruct *wfile, struct ArgusRecord *argus) { int retn = 0; char *file = NULL; if ((wfile == NULL) || (argus == NULL)) ArgusLog (LOG_ERR, "ArgusWriteNewLogfile() parameter/system init error"); else file = wfile->filename; if (strcmp (file, "-")) { if ((stat (file, &wfile->statbuf) < 0)) { if (wfile->fd != NULL) { fclose (wfile->fd); wfile->fd = NULL; } wfile->firstWrite++; } else { if (wfile->statbuf.st_size == 0) wfile->firstWrite++; } if (wfile->fd == NULL) if ((wfile->fd = fopen (file, "a+")) == NULL) ArgusLog (LOG_ERR, "ArgusWriteNewLogfile(%s, 0x%x) fopen %s", file, argus, strerror(errno)); } else { if (wfile->fd == NULL) { wfile->fd = stdout; wfile->firstWrite++; } } if (wfile->firstWrite) { if (!(fwrite ((char *)&ArgusInput->ArgusInitCon, ntohs(ArgusInput->ArgusInitCon.ahdr.length), 1, wfile->fd))) ArgusLog (LOG_ERR, "ArgusWriteNewLogfile(%s, 0x%x) fwrite error %s", file, argus, strerror(errno)); wfile->firstWrite = 0; } if (argus) if (!(fwrite (argus, ntohs(argus->ahdr.length), 1, wfile->fd))) ArgusLog (LOG_ERR, "ArgusWriteNewLogfile(%s, 0x%x) fwrite error %s", file, argus, strerror(errno)); if (fflush (wfile->fd) != 0) ArgusLog (LOG_ERR, "ArgusWriteNewLogfile(%s, 0x%x) fflush error %s", file, argus, strerror(errno)); #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusWriteNewLogFile (%s, 0x%x) bytes %d returning %d\n", file, argus, ntohs(argus->ahdr.length), retn); #endif return (retn); } #define ARGUS_EXCLUSIVE_TIME 1 #define ARGUS_INCLUSIVE_TIME 2 #define ARGUS_SPAN_TIME 3 int ArgusTimeRangeStrategy = ARGUS_SPAN_TIME; int check_time (struct ArgusRecord *ptr) { struct tm tmbuf, *tm; int retn = 0; struct timeval *start, *last, lastbuf; if (ptr->ahdr.type & ARGUS_MAR) { start = &ptr->argus_mar.startime; last = &ptr->argus_mar.now; if (!(start->tv_sec)) start = &ptr->argus_mar.now; } else { start = &ptr->argus_far.time.start; last = &ptr->argus_far.time.last; if (!(start->tv_sec)) *start = *last; if (ArgusThisFarStatus & ARGUS_AGR_DSR_STATUS) { lastbuf = ((struct ArgusAGRStruct *)ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX])->lasttime; } ArgusGlobalTime = *last; } gettimeofday (&ArgusRealTime, 0L); if ((tm = localtime ((time_t *)&start->tv_sec)) != NULL) bcopy ((char *) tm, (char *)&tm_startime, sizeof (struct tm)); else bzero ((char *)&tm_startime, sizeof (struct tm)); if ((tm = localtime ((time_t *)&last->tv_sec)) != NULL) bcopy ((char *) tm, (char *)&tm_lasttime, sizeof (struct tm)); else bzero ((char *)&tm_startime, sizeof (struct tm)); if (tflag) { time_t *sec; if (!explicit_date) { sec = (time_t *)&start->tv_sec; tm = localtime(sec); bcopy ((char *) tm, (char *) &tmbuf, sizeof (struct tm)); if (check_time_format (&tmbuf, timearg)) ArgusLog (LOG_ERR, "time syntax error %s", timearg); } if (ptr->ahdr.type & ARGUS_MAR) { if (ptr->ahdr.status & ARGUS_START) { if ((ptr->argus_mar.now.tv_sec >= startime_t) && (ptr->argus_mar.now.tv_sec <= lasttime_t)) retn++; } else { if ((ptr->argus_mar.now.tv_sec >= startime_t) && (ptr->argus_mar.now.tv_sec <= lasttime_t)) retn++; } } else { switch (ArgusTimeRangeStrategy) { case ARGUS_EXCLUSIVE_TIME: if (((start->tv_sec >= startime_t) && (start->tv_sec <= lasttime_t)) && ((last->tv_sec >= startime_t) && (last->tv_sec <= lasttime_t))) retn++; break; case ARGUS_INCLUSIVE_TIME: if (((start->tv_sec <= startime_t) && (last->tv_sec >= lasttime_t))) retn++; break; case ARGUS_SPAN_TIME: if (((start->tv_sec >= startime_t) && (start->tv_sec <= lasttime_t)) || ((last->tv_sec >= startime_t) && (last->tv_sec <= lasttime_t)) || ((start->tv_sec < startime_t) && (last->tv_sec > lasttime_t))) retn++; } } } else retn++; return (retn); } #include int parseUserDataArg (char **arg, char *args[], int ind) { int retn = -1; char buf[64], *ptr = buf; bzero (buf, 64); strcpy (buf, *arg); ptr += strlen (buf); if ((ptr = strchr(*arg, ':')) && (*(ptr + 1) != '\0')) { retn = 0; } else { if (args) { if (args[ind] && (*args[ind] == ':')) { if (strlen (args[ind]) == 1) { strcat (buf, ":"); strcat (buf, args[ind + 1]); retn = 2; } else { ptr = args[ind]; if (isdigit((int)*(ptr + 1))) { strcat (buf, args[ind]); retn = 1; } else retn = 0; } } else retn = 0; } else retn = 0; } *arg = savestr(buf); if ((ptr = strchr (buf, ':')) != NULL) { ptr++; if (*buf == 's') ArgusSrcUserDataLen = atoi(buf + 1); else ArgusLog (LOG_ERR, "user data syntax error %s", buf); if (*ptr == 'd') ArgusDstUserDataLen = atoi(ptr + 1); else ArgusLog (LOG_ERR, "user data syntax error %s", buf); } else { if (isdigit((int)*buf)) { ArgusSrcUserDataLen = atoi(buf); ArgusDstUserDataLen = atoi(buf); } else { if (*buf == 's') ArgusSrcUserDataLen = atoi(buf + 1); if (*buf == 'd') ArgusDstUserDataLen = atoi(buf + 1); } } if (retn < 0) ArgusLog (LOG_ERR, "user data syntax error %s", buf); return (retn); } int parseTimeArg ( char **arg, char *args[], int ind, struct tm *tm) { int retn = -1; char buf[64], *ptr = NULL, *tmp, *end = NULL; bzero (buf, 64); if (!(isdigit((int)**arg))) { switch (**arg) { case 'x': ArgusTimeRangeStrategy = ARGUS_EXCLUSIVE_TIME; break; case 'i': ArgusTimeRangeStrategy = ARGUS_INCLUSIVE_TIME; break; case 's': ArgusTimeRangeStrategy = ARGUS_SPAN_TIME; break; } ptr = &buf[1]; } else ptr = buf; strcpy (buf, *arg); end += strlen (buf); if ((tmp = strchr(*arg, '-')) && (*(tmp + 1) != '\0')) { retn = 0; } else { if (args) { if (args[ind] && (*args[ind] == '-')) { if (strlen (args[ind]) == 1) { strcat (buf, "-"); strcat (buf, args[ind + 1]); retn = 2; } else { tmp = args[ind]; if (isdigit((int)*(tmp + 1))) { strcat (buf, args[ind]); retn = 1; } else retn = 0; } } else retn = 0; } } if (check_time_format (tm, ptr)) ArgusLog (LOG_ERR, "time syntax error %s", buf); *arg = savestr(ptr); return (retn); } #define ARGUS_YEAR 1 #define ARGUS_MONTH 2 #define ARGUS_DAY 3 #define ARGUS_HOUR 4 #define ARGUS_MIN 5 #define ARGUS_SEC 6 int RaDaysInAMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int check_time_format (struct tm *tm, char *str) { int retn = 0; char *ptr, buf[64]; /* time - [time]*/ strcpy (buf, str); if ((ptr = strpbrk (buf, "smhdMy")) != NULL) { *tm = *localtime((const time_t *)&ArgusGlobalTime.tv_sec); bcopy ((char *)tm, (char *)&lastTimeFilter, sizeof(struct tm)); explicit_date = 1; } if ((ptr = strchr(buf, '-')) != NULL) { *ptr = '\0'; if ((retn = parseTime (&starTimeFilter, tm, buf)) > 0) parseTime (&lastTimeFilter, &starTimeFilter, ptr + 1); if (retn >= 0) retn = 0; } else { if ((retn = parseTime (&starTimeFilter, tm, buf)) > 0) { bcopy ((char *)&starTimeFilter, (char *)&lastTimeFilter, sizeof(struct tm)); switch (retn) { case ARGUS_YEAR: lastTimeFilter.tm_year++; break; case ARGUS_MONTH: lastTimeFilter.tm_mon++; break; case ARGUS_DAY: lastTimeFilter.tm_mday++; break; case ARGUS_HOUR: lastTimeFilter.tm_hour++; break; case ARGUS_MIN: lastTimeFilter.tm_min++; break; case ARGUS_SEC: lastTimeFilter.tm_sec++; break; } while (tm->tm_sec > 59) {tm->tm_min++; tm->tm_sec -= 60;} while (tm->tm_min > 59) {tm->tm_hour++; tm->tm_min -= 60;} while (tm->tm_hour > 23) {tm->tm_mday++; tm->tm_hour -= 24;} while (tm->tm_mday > RaDaysInAMonth[tm->tm_mon]) {tm->tm_mday -= RaDaysInAMonth[tm->tm_mon]; tm->tm_mon++;} while (tm->tm_mon > 11) {tm->tm_year++; tm->tm_mon -= 12;} retn = 0; } } if (retn == 0) { startime_t = timelocal (&starTimeFilter); lasttime_t = timelocal (&lastTimeFilter); if (!(lasttime_t >= startime_t)) { fprintf (stderr, "error: invalid time range\n"); retn++; } } return (retn); } int parseTime (struct tm *tm, struct tm *ctm, char *str) { char *hptr = NULL, *dptr = NULL, *mptr = NULL, *yptr = NULL; char *minptr = NULL, *secptr = NULL, *ptr; int retn = 0, hour = 0, mins = 0, sec = 0, i; time_t thistime; /*[[[yyyy/]mm/]dd].]hh[:mm[:ss]]*/ /* %d[yMdhms][[+]%d[yMdhms]] */ if (!(isdigit((int)*str))) return -1; if ((ptr = strpbrk (str, "yMdhms")) != NULL) { if (tm != &lastTimeFilter) bcopy ((u_char *) ctm, (u_char *) tm, sizeof (struct tm)); thistime = timelocal (tm); do { i = atoi(str); switch (*ptr) { case 'y': tm->tm_year -= i; break; case 'M': { while (i > tm->tm_mon) { tm->tm_year--; i -= 12; } tm->tm_mon -= i; thistime = timelocal (tm); break; } case 'd': thistime -= (i * ((60 * 60) * 24)); *tm = *localtime ((time_t *)&thistime); break; case 'h': thistime -= (i * (60 * 60)); *tm = *localtime ((time_t *)&thistime); break; case 'm': thistime -= (i * 60); *tm = *localtime ((time_t *)&thistime); break; case 's': thistime -= i; *tm = *localtime ((time_t *)&thistime); break; default: return(-1); } str = ptr + 1; if (!(isdigit((int)*str))) break; } while ((ptr = strpbrk (str, "yMdhms")) != NULL); retn = 1; } else { bcopy ((u_char *) ctm, (u_char *) tm, sizeof (struct tm)); thistime = timelocal (tm); if ((hptr = strchr (str, '.')) != NULL) { *hptr++ = '\0'; if (!(isdigit((int)*hptr))) return -1; } if ((dptr = strrchr (str, '/')) != NULL) { /* mm/dd */ /* ^ */ *dptr++ = '\0'; if ((mptr = strrchr (str, '/')) != NULL) { /* yyyy/mm/dd */ /* ^ */ *mptr++ = '\0'; yptr = str; } else mptr = str; } else { if (hptr != NULL) dptr = str; else hptr = str; } if (yptr) { if (strlen(yptr) != 4) return -1; for (ptr = yptr, i = 0; i < strlen(yptr); i++) if (!(isdigit((int)*ptr++))) return -1; tm->tm_year = atoi(yptr) - 1900; retn = ARGUS_YEAR; } if (mptr) { if (strlen(mptr) != 2) return -1; for (ptr = mptr, i = 0; i < strlen(mptr); i++) if (!(isdigit((int)*ptr++))) return -1; tm->tm_mon = atoi(mptr) - 1; retn = ARGUS_MONTH; } if (dptr) { if (strlen(dptr) != 2) return -1; for (ptr = dptr, i = 0; i < strlen(dptr); i++) if (!(isdigit((int)*ptr++))) return -1; tm->tm_mday = atoi(dptr); retn = ARGUS_DAY; } if (hptr) { if ((minptr = strchr (hptr, ':')) != NULL) { *minptr++ = '\0'; if ((secptr = strchr (minptr, ':')) != NULL) { *secptr++ = '\0'; } } for (ptr = hptr, i = 0; i < strlen(hptr); i++) if (!(isdigit((int)*ptr++))) return -1; hour = atoi(hptr); retn = ARGUS_HOUR; if (minptr != NULL) { for (ptr = minptr, i = 0; i < strlen(minptr); i++) if (!(isdigit((int)*ptr++))) return -1; mins = atoi(minptr); retn = ARGUS_MIN; } if (secptr != NULL) { for (ptr = secptr, i = 0; i < strlen(secptr); i++) if (!(isdigit((int)*ptr++))) return -1; sec = atoi(secptr); retn = ARGUS_SEC; } } tm->tm_hour = hour; tm->tm_min = mins; tm->tm_sec = sec; #if !defined(HAVE_SOLARIS) && !defined(__sgi) && !defined(linux) && !defined(AIX) && !defined(CYGWIN) tm->tm_zone = NULL; tm->tm_gmtoff = 0; #endif if (tm->tm_year < 0) retn = -1; if ((tm->tm_mon > 11) || (tm->tm_mon < 0)) retn = -1; if ((tm->tm_mday > 31) || (tm->tm_mday < 0)) retn = -1; if ((tm->tm_hour > 23) || (tm->tm_hour < 0)) retn = -1; if ((tm->tm_min > 60) || (tm->tm_min < 0)) retn = -1; if ((tm->tm_sec > 60) || (tm->tm_sec < 0)) retn = -1; if (retn >= 0) { thistime = timelocal (tm); *tm = *localtime ((time_t *)&thistime); } } return (retn); } #define ARGUS_RCITEMS 37 #define RA_ARGUS_SERVER 0 #define RA_CISCONETFLOW_PORT 1 #define RA_ARGUS_SERVERPORT 2 #define RA_INPUT_FILE 3 #define RA_NO_OUTPUT 4 #define RA_USER_AUTH 5 #define RA_AUTH_PASS 6 #define RA_OUTPUT_FILE 7 #define RA_EXCEPTION_OUTPUT_FILE 8 #define RA_TIMERANGE 9 #define RA_RUNTIME 10 #define RA_FLOW_MODEL 11 #define RA_FIELD_DELIMITER 12 #define RA_TIME_FORMAT 13 #define RA_USEC_PRECISION 14 #define RA_PRINT_LABELS 15 #define RA_PRINT_SUMMARY 16 #define RA_PRINT_HOSTNAMES 17 #define RA_PRINT_LOCALONLY 18 #define RA_PRINT_RESPONSE_DATA 19 #define RA_PRINT_UNIX_TIME 20 #define RA_PRINT_TCPSTATES 21 #define RA_PRINT_TCPFLAGS 22 #define RAGATOR_TIME_SERIES 23 #define RAGATOR_VALIDATE 24 #define RAMON_MODE 25 #define RAMON_NUMBER 26 #define RA_DEBUG_LEVEL 27 #define RA_PRINT_USERDATA 28 #define RA_USERDATA_ENCODE 29 #define RA_FILTER 30 #define RA_HOST_FIELD_LENGTH 31 #define RA_PORT_FIELD_LENGTH 32 #define RA_FIELD_SPECIFIER 33 #define RA_MIN_SSF 34 #define RA_MAX_SSF 35 #define RA_DATABASE 36 char *ArgusResourceFileStr [] = { "RA_ARGUS_SERVER=", "RA_CISCONETFLOW_PORT=", "RA_ARGUS_SERVERPORT=", "RA_INPUT_FILE=", "RA_NO_OUTPUT=", "RA_USER_AUTH=", "RA_AUTH_PASS=", "RA_OUTPUT_FILE=", "RA_EXCEPTION_OUTPUT_FILE=", "RA_TIMERANGE=", "RA_RUN_TIME=", "RA_FLOW_MODEL=", "RA_FIELD_DELIMITER=", "RA_TIME_FORMAT=", "RA_USEC_PRECISION=", "RA_PRINT_LABELS=", "RA_PRINT_SUMMARY=", "RA_PRINT_HOSTNAMES=", "RA_PRINT_LOCALONLY=", "RA_PRINT_RESPONSE_DATA=", "RA_PRINT_UNIX_TIME=", "RA_PRINT_TCPSTATES=", "RA_PRINT_TCPFLAGS=", "RAGATOR_TIME_SERIES=", "RAGATOR_VALIDATE=", "RAMON_MODE=", "RAMON_NUMBER=", "RA_DEBUG_LEVEL=", "RA_PRINT_USERDATA=", "RA_USERDATA_ENCODE=", "RA_FILTER=", "RA_HOST_FIELD_LENGTH=", "RA_PORT_FIELD_LENGTH=", "RA_FIELD_SPECIFIER=", "RA_MIN_SSF=", "RA_MAX_SSF=", "RA_DATABASE=", }; #include int ArgusParseResourceFile (char *file) { int retn = 0, i, len, Soption = 0, roption = 0, found = 0, lines = 0; char strbuf[MAXSTRLEN], *str = strbuf, *optarg = NULL, *ptr = NULL; FILE *fd; if (file) { if ((fd = fopen (file, "r")) != NULL) { retn = 1; while ((fgets(str, MAXSTRLEN, fd)) != NULL) { lines++; while (*str && isspace((int)*str)) str++; if (*str && (*str != '#') && (*str != '\n') && (*str != '!')) { found = 0; for (i = 0; i < ARGUS_RCITEMS; i++) { len = strlen(ArgusResourceFileStr[i]); if (!(strncmp (str, ArgusResourceFileStr[i], len))) { optarg = &str[len]; if (optarg[strlen(optarg) - 1] == '\n') optarg[strlen(optarg) - 1] = '\0'; if (*optarg == '\"') optarg++; if (optarg[strlen(optarg) - 1] == '\"') optarg[strlen(optarg) - 1] = '\0'; if (*optarg == '\0') optarg = NULL; if (optarg) { switch (i) { case RA_ARGUS_SERVER: ++Sflag; if (!Soption++ && (ArgusRemoteHostList != NULL)) ArgusDeleteHostList(); if (!(ArgusAddHostList (optarg, ARGUS_DATA_SOURCE))) { ArgusLog (LOG_ERR, "host %s unknown\n", optarg); } break; case RA_CISCONETFLOW_PORT: ++Sflag; ++Cflag; if (!Soption++ && (ArgusRemoteHostList != NULL)) ArgusDeleteHostList(); if (!(ArgusAddHostList (optarg, ARGUS_CISCO_DATA_SOURCE))) { ArgusLog (LOG_ERR, "host %s unknown\n", optarg); } break; case RA_ARGUS_SERVERPORT: ArgusPortNum = atoi (optarg); break; break; case RA_INPUT_FILE: if ((!roption++) && (ArgusInputFileList != NULL)) ArgusDeleteFileList(); if (!(ArgusAddFileList (optarg, (Cflag ? ARGUS_CISCO_DATA_SOURCE : ARGUS_DATA_SOURCE), -1, -1))) ArgusLog (LOG_ERR, "error: file arg %s\n", optarg); break; case RA_NO_OUTPUT: if (!(strncasecmp(optarg, "yes", 3))) qflag++; else qflag = 0; break; case RA_USER_AUTH: if (ustr != NULL) free(ustr); ustr = strdup(optarg); break; case RA_AUTH_PASS: if (pstr != NULL) free(pstr); pstr = strdup(optarg); break; case RA_DATABASE: if (dbstr != NULL) free(dbstr); dbstr = strdup(optarg); break; case RA_OUTPUT_FILE: setArgusWfile(optarg, NULL); break; case RA_EXCEPTION_OUTPUT_FILE: exceptfile = optarg; setArgusWfile(optarg, NULL); break; case RA_TIMERANGE: timearg = strdup(optarg); if ((parseTimeArg (&timearg, NULL, 0, RaTmStruct)) < 0) usage (); break; case RA_RUNTIME: Tflag = atoi (optarg); break; case RA_FIELD_DELIMITER: ptr = optarg; if ((ptr = strchr (optarg, '\'')) != NULL) { ptr++; if (ptr[0] == '\'') break; } if (ptr[0] == '\\') { switch (ptr[1]) { case 'a': RaFieldDelimiter = '\a'; break; case 'b': RaFieldDelimiter = '\b'; break; case 't': RaFieldDelimiter = '\t'; break; case 'n': RaFieldDelimiter = '\n'; break; case 'v': RaFieldDelimiter = '\v'; break; case 'f': RaFieldDelimiter = '\f'; break; case 'r': RaFieldDelimiter = '\r'; break; case '\\': RaFieldDelimiter = '\\'; break; } if (RaFieldDelimiter != '\0') break; } else RaFieldDelimiter = *ptr; break; case RA_TIME_FORMAT: RaTimeFormat = strdup(optarg); case RA_USEC_PRECISION: pflag = atoi (optarg); break; case RA_PRINT_SUMMARY: if (!(strncasecmp(optarg, "yes", 3))) aflag = 1; else aflag = 0; break; case RA_PRINT_HOSTNAMES: if (!(strncasecmp(optarg, "yes", 3))) nflag = 0; else nflag = 1; break; case RA_PRINT_LOCALONLY: if (!(strncasecmp(optarg, "yes", 3))) ++fflag; else fflag = 0; break; case RA_FLOW_MODEL: ArgusFlowModelFile = strdup(optarg); break; case RA_PRINT_LABELS: Lflag = atoi(optarg); if (Lflag == 0) Lflag = -1; break; case RA_PRINT_UNIX_TIME: if (!(strncasecmp(optarg, "yes", 3))) ++uflag; else uflag = 0; break; case RA_PRINT_TCPSTATES: if (!(strncasecmp(optarg, "yes", 3))) zflag++; else zflag = 0; break; case RA_PRINT_TCPFLAGS: Zflag = *optarg; break; case RAGATOR_TIME_SERIES: if (!(strncasecmp(optarg, "yes", 3))) Hflag++; else Hflag = 0; break; case RAGATOR_VALIDATE: if (!(strncasecmp(optarg, "yes", 3))) Vflag++; else Vflag = 0; break; case RAMON_MODE: Mflag = optarg; break; case RAMON_NUMBER: Nflag = atoi (optarg); break; case RA_DEBUG_LEVEL: Argusdflag = (atoi(optarg)); break; case RA_PRINT_USERDATA: dflag++; if ((parseUserDataArg (&optarg, NULL, 0)) < 0) usage (); break; case RA_USERDATA_ENCODE: if (!(strncasecmp(optarg, "ascii", 5))) eflag = ARGUS_ENCODE_ASCII; else if (!(strncasecmp(optarg, "encode32", 8))) eflag = ARGUS_ENCODE_32; else eflag = ARGUS_ENCODE_64; break; case RA_FILTER: { char *ptr; if (*RaInputFilter != NULL) free(*RaInputFilter); if ((*RaInputFilter = calloc (1, MAXSTRLEN)) != NULL) { ptr = *RaInputFilter; str = optarg; while (*str) { if ((*str == '\\') && (str[1] == '\n')) { fgets(str, MAXSTRLEN, fd); while (*str && (isspace((int)*str) && (str[1] && isspace((int)str[1])))) str++; } if ((*str != '\n') && (*str != '"')) *ptr++ = *str++; else str++; } } #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusParseResourceFile: ArgusFilter \"%s\" \n", RaInputFilter); #endif break; } case RA_HOST_FIELD_LENGTH: hfield = atoi (optarg); break; case RA_PORT_FIELD_LENGTH: pfield = atoi (optarg); break; case RA_FIELD_SPECIFIER: { char *tok = NULL; while ((tok = strtok(optarg, " ")) != NULL) { RaSOptionStrings[RaSOptionIndex++] = strdup(tok); if (RaSOptionIndex >= ARGUS_MAX_S_OPTIONS) ArgusLog (LOG_ERR, "usage: number of -s options exceeds %d", ARGUS_MAX_S_OPTIONS); optarg = NULL; } break; } case RA_MIN_SSF: { if (*optarg != '\0') { #ifdef ARGUS_SASL ArgusMinSsf = atoi(optarg); #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusParseResourceFile: ArgusMinSsf \"%s\" \n", ArgusMinSsf); #endif #endif } break; } case RA_MAX_SSF: { if (*optarg != '\0') { #ifdef ARGUS_SASL ArgusMaxSsf = atoi(optarg); #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusParseResourceFile: ArgusMaxSsf \"%s\" \n", ArgusMaxSsf); #endif #endif } break; } } } found++; break; } } if (!found) { ArgusLog (LOG_ERR, "%s: syntax error line %d", file, lines); } } } if (RaSOptionIndex > 0) { RaProcessSOptions(); for (i = 0; i < RaSOptionIndex; i++) { if (RaSOptionStrings[i] != NULL) { free(RaSOptionStrings[i]); RaSOptionStrings[i] = NULL; } } RaSOptionIndex = 0; } } else { #ifdef ARGUSDEBUG ArgusDebug (2, "%s: %s\n", file, strerror(errno)); #endif } } #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusParseResourceFile (%s) returning %d\n", file, retn); #endif return (retn); } void clearRaConfiguration () { aflag = 0; Aflag = 0; Argusdflag = 0; bflag = 0; Bflag = 0; cflag = 0; Cflag = 0; dflag = 0; Dflag = 0; eflag = 0; Eflag = 0; estr = NULL; fflag = 0; Fflag = 0; gflag = 0; Gflag = 0; hfield = 15; Hflag = 0; Hstr = NULL; idflag = 0; jflag = 0; lflag = 0; Lflag = 0; mflag = 0; Mflag = NULL; Netflag = 0; nflag = 0; Nflag = 0; Normflag = 0; notNetflag = 0; Oflag = 0; pfield = 5; pflag = 0; Pflag = 0; qflag = 0; sflag = NULL; tflag = 0; uflag = 0; Wflag = 0; Uflag = 6; vflag = 0; Vflag = 0; iflag = 0; Iflag = 0; Tflag = 0; rflag = 0; Rflag = 0; Sflag = 0; xflag = 0; Xflag = 0; XMLflag = 0; zflag = 0; Zflag = 0; RaCumulativeMerge = 1; RaAllocHashTableHeaders = 0; RaAllocArgusRecordStore = 0; RaAllocArgusRecord = 0; ArgusMinuteUpdate = 1; ArgusHourlyUpdate = 1; RaHistoTimeSeries = 1; RaThisActiveIndex = 0; RaThisFlowNum = 0; RaThisModelNum = 0; RaParseError = 0; clearArgusWfile(); if (ustr != NULL) free (ustr); ustr = NULL; if (pstr != NULL) free (pstr); pstr = NULL; if (timearg != NULL) free(timearg); timearg = NULL; if (ArgusRemoteFilter != NULL) free (ArgusRemoteFilter); ArgusRemoteFilter = NULL; ArgusSrcUserDataLen = 0; ArgusDstUserDataLen = 0; if (ArgusInputFileList != NULL) ArgusDeleteFileList(); if (ArgusRemoteHostList != NULL) ArgusDeleteHostList(); #ifdef ARGUSDEBUG ArgusDebug (1, "clearArgusConfiguration () returning\n"); #endif } void clearArgusWfile() { ArgusDeleteList (ArgusWfileList); ArgusWfileList = NULL; } #if !defined(PATH_MAX) #define PATH_MAX 4098 #endif void setArgusWfile(char *file, char *filter) { FILE *fd = NULL; struct ArgusWfileStruct *wfile = NULL; char realpathname[PATH_MAX], *ptr = NULL; if (ArgusWfileList == NULL) ArgusWfileList = ArgusNewList(); if (file) { if (strcmp (file, "-")) { if ((strncmp(ArgusProgramName, "rasplit", 7))) { if ((fd = fopen (file, "a+")) == NULL) ArgusLog (LOG_ERR, "setArgusWfile open %s %s", file, strerror(errno)); else fclose (fd); bzero (realpathname, PATH_MAX); if ((ptr = realpath (file, realpathname)) == NULL) ArgusLog (LOG_ERR, "setArgusWfile, realpath %s %s", file, strerror(errno)); else ptr = strdup(ptr); } else ptr = strdup(file); } else ptr = strdup(file); if ((wfile = (struct ArgusWfileStruct *) ArgusCalloc (1, sizeof (*wfile))) != NULL) { ArgusPushFrontList(ArgusWfileList, wfile); wfile->filename = ptr; if (filter) wfile->filter = strdup(filter); if (exceptfile != NULL) if (!(strcmp(file, exceptfile))) exceptfile = ptr; } else ArgusLog (LOG_ERR, "setArgusWfile, ArgusCalloc %s", strerror(errno)); } else ArgusLog (LOG_ERR, "setArgusWfile, file is null"); } argus-clients-2.0.6.fixes.1/common/argus_util.c0000664000076600007660000033046507764412534015113 /* * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * Copyright (c) 1988-1990 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef ArgusUtil #define ArgusUtil #endif #include #include #include #include #include #include #include #include #include #include #include #include #include int target_flags = 0; extern void ArgusLog (int, char *, ...); void ArgusAdjustGlobalTime (struct timeval *now) { struct timeval ArgusTimeDelta; ArgusTimeDelta.tv_sec = ArgusRealTime.tv_sec - ArgusGlobalTime.tv_sec; ArgusTimeDelta.tv_usec = ArgusRealTime.tv_usec - ArgusGlobalTime.tv_usec; ArgusGlobalTime.tv_sec = now->tv_sec - ArgusTimeDelta.tv_sec; ArgusGlobalTime.tv_usec = now->tv_usec - ArgusTimeDelta.tv_usec; if (ArgusGlobalTime.tv_usec < 0) { ArgusGlobalTime.tv_sec--; ArgusGlobalTime.tv_usec += 1000000; } else { if (ArgusGlobalTime.tv_usec > 1000000) { ArgusGlobalTime.tv_sec++; ArgusGlobalTime.tv_usec -= 1000000; } } ArgusRealTime = *now; } struct ArgusRecord *ArgusSubtractRecord (struct ArgusRecord *, struct ArgusRecord *); struct ArgusRecord * ArgusSubtractRecord (struct ArgusRecord *arg1, struct ArgusRecord *arg2) { struct ArgusRecord *retn = arg1; struct ArgusFarHeaderStruct *a1farhdr[32], *a2farhdr[32]; unsigned int status, status1 = 0, status2 = 0; int i; status1 = ArgusIndexRecord (arg1, a1farhdr); status2 = ArgusIndexRecord (arg2, a2farhdr); status = (status1 & status2); for (i = 0; i < 32; i++) { if (status & 0x01) { switch (i) { case ARGUS_MAC_DSR_INDEX: case ARGUS_VLAN_DSR_INDEX: case ARGUS_MPLS_DSR_INDEX: case ARGUS_ICMP_DSR_INDEX: case ARGUS_IGMP_DSR_INDEX: case ARGUS_ARP_DSR_INDEX: case ARGUS_FRG_DSR_INDEX: case ARGUS_SRCUSRDATA_DSR_INDEX: case ARGUS_DSTUSRDATA_DSR_INDEX: case ARGUS_ESP_DSR_INDEX: break; case ARGUS_TCP_DSR_INDEX: { struct ArgusTCPObject *tcp1 = (struct ArgusTCPObject *) a1farhdr[i]; struct ArgusTCPObject *tcp2 = (struct ArgusTCPObject *) a2farhdr[i]; tcp1->src.ackbytes -= tcp2->src.ackbytes; tcp1->src.bytes -= tcp2->src.bytes; tcp1->src.rpkts -= tcp2->src.rpkts; tcp1->dst.ackbytes -= tcp2->dst.ackbytes; tcp1->dst.bytes -= tcp2->dst.bytes; tcp1->dst.rpkts -= tcp2->dst.rpkts; break; } case ARGUS_FAR_DSR_INDEX: { struct ArgusFarStruct *far1 = (struct ArgusFarStruct *) a1farhdr[i]; struct ArgusFarStruct *far2 = (struct ArgusFarStruct *) a2farhdr[i]; far1->time.start.tv_sec -= far2->time.start.tv_sec; far1->time.start.tv_usec -= far2->time.start.tv_usec; if (far1->time.start.tv_usec < 0) { far1->time.start.tv_sec--; far1->time.start.tv_usec += 1000000; } far1->time.last.tv_sec -= far2->time.last.tv_sec; far1->time.last.tv_usec -= far2->time.last.tv_usec; if (far1->time.last.tv_usec < 0) { far1->time.last.tv_sec--; far1->time.last.tv_usec += 1000000; } far1->src.count -= far2->src.count; far1->src.bytes -= far2->src.bytes; far1->src.appbytes -= far2->src.appbytes; far1->dst.count -= far2->dst.count; far1->dst.bytes -= far2->dst.bytes; far1->dst.appbytes -= far2->dst.appbytes; break; } case ARGUS_RTP_DSR_INDEX: { struct ArgusRTPObject *rtp1 = (struct ArgusRTPObject *) a1farhdr[i]; struct ArgusRTPObject *rtp2 = (struct ArgusRTPObject *) a2farhdr[i]; rtp1->sdrop -= rtp2->sdrop; rtp1->ddrop -= rtp2->ddrop; rtp1->ssdev -= rtp2->ssdev; break; } case ARGUS_TIME_DSR_INDEX: { /* struct ArgusTimeStruct *time1 = (struct ArgusTimeStruct *) a1farhdr[i]; struct ArgusTimeStruct *time2 = (struct ArgusTimeStruct *) a2farhdr[i]; */ break; } case ARGUS_AGR_DSR_INDEX: { /* struct ArgusAGRStruct *agr1 = (struct ArgusAGRStruct *) a1farhdr[i]; struct ArgusAGRStruct *agr2 = (struct ArgusAGRStruct *) a2farhdr[i]; */ break; } } } status >>= 1; } return (retn); } void ArgusZeroRecord (struct ArgusRecord *argus) { struct ArgusFarHeaderStruct *a1farhdr[32]; unsigned int status = 0; int i; status = ArgusIndexRecord (argus, a1farhdr); for (i = 0; i < 32; i++) { if (status & 0x01) { switch (i) { case ARGUS_MAC_DSR_INDEX: case ARGUS_VLAN_DSR_INDEX: case ARGUS_MPLS_DSR_INDEX: case ARGUS_ICMP_DSR_INDEX: case ARGUS_IGMP_DSR_INDEX: case ARGUS_ARP_DSR_INDEX: case ARGUS_FRG_DSR_INDEX: case ARGUS_SRCUSRDATA_DSR_INDEX: case ARGUS_DSTUSRDATA_DSR_INDEX: case ARGUS_ESP_DSR_INDEX: case ARGUS_AGR_DSR_INDEX: break; case ARGUS_TCP_DSR_INDEX: { struct ArgusTCPObject *tcp = (struct ArgusTCPObject *) a1farhdr[i]; bzero ((char *)&tcp->src, sizeof(struct ArgusTCPObjectMetrics)); bzero ((char *)&tcp->dst, sizeof(struct ArgusTCPObjectMetrics)); break; } case ARGUS_FAR_DSR_INDEX: { struct ArgusFarStruct *far = (struct ArgusFarStruct *) a1farhdr[i]; bzero ((char *)&far->src, sizeof(struct ArgusMeter)); bzero ((char *)&far->dst, sizeof(struct ArgusMeter)); break; } case ARGUS_RTP_DSR_INDEX: { struct ArgusRTPObject *rtp = (struct ArgusRTPObject *) a1farhdr[i]; rtp->sdrop = 0; rtp->ssdev = 0; break; } case ARGUS_TIME_DSR_INDEX: { struct ArgusTimeStruct *time = (struct ArgusTimeStruct *) a1farhdr[i]; bzero ((char *)&time->src, sizeof(struct ArgusTimeEntity)); bzero ((char *)&time->dst, sizeof(struct ArgusTimeEntity)); break; } } } status >>= 1; } } void ArgusReverseRecord (struct ArgusRecord *argus) { struct ArgusRecord *tmp = RaCopyArgusRecord(argus); struct ArgusFarHeaderStruct *a1farhdr[32], *a2farhdr[32]; unsigned int a1DSRStatus = 0, a2DSRStatus = 0, status; int i; a1DSRStatus = ArgusIndexRecord (argus, a1farhdr); a2DSRStatus = ArgusIndexRecord (tmp, a2farhdr); status = a1DSRStatus; for (i = 0; i < 32; i++) { if (status & 0x01) { switch (i) { case ARGUS_FAR_DSR_INDEX: { struct ArgusFarStruct *far1 = (struct ArgusFarStruct *) a1farhdr[i]; struct ArgusFarStruct *far2 = (struct ArgusFarStruct *) a2farhdr[i]; if ((argus->ahdr.status & 0xFFFF) == ETHERTYPE_IP) { far2->flow.ip_flow.ip_src = far1->flow.ip_flow.ip_dst; far2->flow.ip_flow.ip_dst = far1->flow.ip_flow.ip_src; switch (far1->flow.ip_flow.ip_p) { case IPPROTO_TCP: case IPPROTO_UDP: far2->flow.ip_flow.sport = far1->flow.ip_flow.dport; far2->flow.ip_flow.dport = far1->flow.ip_flow.sport; break; case IPPROTO_ESP: case IPPROTO_ICMP: case IPPROTO_IGMP: break; } far2->attr_ip.soptions = far1->attr_ip.doptions; far2->attr_ip.doptions = far1->attr_ip.soptions; far2->attr_ip.sttl = far1->attr_ip.dttl; far2->attr_ip.dttl = far1->attr_ip.sttl; far2->attr_ip.stos = far1->attr_ip.dtos; far2->attr_ip.dtos = far1->attr_ip.stos; } bcopy ((char *)&far1->src, (char *)&far2->dst, sizeof(struct ArgusMeter)); bcopy ((char *)&far1->dst, (char *)&far2->src, sizeof(struct ArgusMeter)); break; } case ARGUS_MAC_DSR_INDEX: { struct ArgusMacStruct *mac1 = (struct ArgusMacStruct *) a1farhdr[i]; struct ArgusMacStruct *mac2 = (struct ArgusMacStruct *) a2farhdr[i]; bcopy ((char *)mac1->ether_mac.ethersrc, (char *)mac2->ether_mac.etherdst, 6); bcopy ((char *)mac1->ether_mac.etherdst, (char *)mac2->ether_mac.ethersrc, 6); break; } case ARGUS_VLAN_DSR_INDEX: { struct ArgusVlanStruct *vlan1 = (struct ArgusVlanStruct *) a1farhdr[i]; struct ArgusVlanStruct *vlan2 = (struct ArgusVlanStruct *) a2farhdr[i]; vlan2->sid = vlan1->did; vlan2->did = vlan1->sid; if (vlan1->status & ARGUS_SRC_VLAN) { vlan2->status &= ~ARGUS_SRC_VLAN; vlan2->status |= ARGUS_DST_VLAN; } if (vlan1->status & ARGUS_SRC_CHANGED) { vlan2->status &= ~ARGUS_SRC_CHANGED; vlan2->status |= ARGUS_DST_CHANGED; } if (vlan1->status & ARGUS_DST_VLAN) { vlan2->status &= ~ARGUS_DST_VLAN; vlan2->status |= ARGUS_SRC_VLAN; } if (vlan1->status & ARGUS_DST_CHANGED) { vlan2->status &= ~ARGUS_DST_CHANGED; vlan2->status |= ARGUS_SRC_CHANGED; } break; } case ARGUS_MPLS_DSR_INDEX: { struct ArgusMplsStruct *mpls1 = (struct ArgusMplsStruct *) a1farhdr[i]; struct ArgusMplsStruct *mpls2 = (struct ArgusMplsStruct *) a2farhdr[i]; mpls2->slabel = mpls1->dlabel; mpls2->dlabel = mpls1->slabel; if (mpls1->status & ARGUS_SRC_MPLS) { mpls2->status &= ~ARGUS_SRC_MPLS; mpls2->status |= ARGUS_DST_MPLS; } if (mpls1->status & ARGUS_SRC_CHANGED) { mpls2->status &= ~ARGUS_SRC_CHANGED; mpls2->status |= ARGUS_DST_CHANGED; } if (mpls1->status & ARGUS_DST_MPLS) { mpls2->status &= ~ARGUS_DST_MPLS; mpls2->status |= ARGUS_SRC_MPLS; } if (mpls1->status & ARGUS_DST_CHANGED) { mpls2->status &= ~ARGUS_DST_CHANGED; mpls2->status |= ARGUS_SRC_CHANGED; } break; } case ARGUS_AGR_DSR_INDEX: { break; } case ARGUS_TIME_DSR_INDEX: { struct ArgusTimeStruct *time1 = (struct ArgusTimeStruct *) a1farhdr[i]; struct ArgusTimeStruct *time2 = (struct ArgusTimeStruct *) a2farhdr[i]; bcopy ((char *)&time1->src, (char *)&time2->dst, sizeof(struct ArgusTimeEntity)); bcopy ((char *)&time1->dst, (char *)&time2->src, sizeof(struct ArgusTimeEntity)); break; } case ARGUS_SRCUSRDATA_DSR_INDEX: case ARGUS_DSTUSRDATA_DSR_INDEX: { struct ArgusUserStruct *user2 = (struct ArgusUserStruct *) a2farhdr[i]; if (user2->type == ARGUS_SRCUSRDATA_DSR) user2->type = ARGUS_DSTUSRDATA_DSR; else user2->type = ARGUS_SRCUSRDATA_DSR; break; } case ARGUS_TCP_DSR_INDEX: { struct ArgusTCPObject *tcp1 = (struct ArgusTCPObject *) a1farhdr[i]; struct ArgusTCPObject *tcp2 = (struct ArgusTCPObject *) a2farhdr[i]; bcopy ((char *)&tcp1->src, (char *)&tcp2->dst, sizeof(struct ArgusTCPObjectMetrics)); bcopy ((char *)&tcp1->dst, (char *)&tcp2->src, sizeof(struct ArgusTCPObjectMetrics)); break; } case ARGUS_ICMP_DSR_INDEX: { break; } case ARGUS_RTP_DSR_INDEX: { struct ArgusRTPObject *rtp1 = (struct ArgusRTPObject *) a1farhdr[i]; struct ArgusRTPObject *rtp2 = (struct ArgusRTPObject *) a2farhdr[i]; bcopy ((char *)&rtp1->src, (char *)&rtp2->dst, sizeof(struct rtphdr)); bcopy ((char *)&rtp1->dst, (char *)&rtp2->src, sizeof(struct rtphdr)); rtp2->sdrop = rtp2->ddrop; rtp2->ddrop = rtp2->sdrop; rtp2->ssdev = rtp2->dsdev; rtp2->dsdev = rtp2->ssdev; break; } case ARGUS_IGMP_DSR_INDEX: { break; } case ARGUS_ARP_DSR_INDEX: break; case ARGUS_FRG_DSR_INDEX: break; case ARGUS_ESP_DSR_INDEX: { break; } } } status >>= 1; } bcopy ((char *)tmp, (char *)argus, argus->ahdr.length); ArgusFree(tmp); } unsigned int ArgusIndexRecord (struct ArgusRecord *argus, struct ArgusFarHeaderStruct **hdrs) { unsigned int retn = 0; struct ArgusFarHeaderStruct *far = (struct ArgusFarHeaderStruct *) &argus->argus_far; unsigned int length = argus->ahdr.length - sizeof(argus->ahdr); unsigned int farlen; bzero ((char *) hdrs, 32 * sizeof(struct ArgusFarHeaderStruct *)); if (argus->ahdr.type & ARGUS_FAR) { while ((length > 0) && (length >= far->length)) { switch (far->type) { case ARGUS_FAR: if (retn & ARGUS_FAR_DSR_STATUS) return (retn); retn |= ARGUS_FAR_DSR_STATUS; hdrs[ARGUS_FAR_DSR_INDEX] = far; break; case ARGUS_MAC_DSR: if (retn & ARGUS_MAC_DSR_STATUS) return (retn); retn |= ARGUS_MAC_DSR_STATUS; hdrs[ARGUS_MAC_DSR_INDEX] = far; break; case ARGUS_VLAN_DSR: if (retn & ARGUS_VLAN_DSR_STATUS) return (retn); retn |= ARGUS_VLAN_DSR_STATUS; hdrs[ARGUS_VLAN_DSR_INDEX] = far; break; case ARGUS_MPLS_DSR: if (retn & ARGUS_MPLS_DSR_STATUS) return (retn); retn |= ARGUS_MPLS_DSR_STATUS; hdrs[ARGUS_MPLS_DSR_INDEX] = far; break; case ARGUS_AGR_DSR: if (retn & ARGUS_AGR_DSR_STATUS) return (retn); retn |= ARGUS_AGR_DSR_STATUS; hdrs[ARGUS_AGR_DSR_INDEX] = far; break; case ARGUS_TIME_DSR: if (retn & ARGUS_TIME_DSR_STATUS) return (retn); retn |= ARGUS_TIME_DSR_STATUS; hdrs[ARGUS_TIME_DSR_INDEX] = far; break; case ARGUS_SRCUSRDATA_DSR: if (retn & ARGUS_SRCUSRDATA_DSR_STATUS) return (retn); retn |= ARGUS_SRCUSRDATA_DSR_STATUS; hdrs[ARGUS_SRCUSRDATA_DSR_INDEX] = far; break; case ARGUS_DSTUSRDATA_DSR: if (retn & ARGUS_DSTUSRDATA_DSR_STATUS) return (retn); retn |= ARGUS_DSTUSRDATA_DSR_STATUS; hdrs[ARGUS_DSTUSRDATA_DSR_INDEX] = far; break; case ARGUS_TCP_DSR: if (retn & ARGUS_TCP_DSR_STATUS) return (retn); retn |= ARGUS_TCP_DSR_STATUS; hdrs[ARGUS_TCP_DSR_INDEX] = far; break; case ARGUS_ICMP_DSR: if (retn & ARGUS_ICMP_DSR_STATUS) return (retn); retn |= ARGUS_ICMP_DSR_STATUS; hdrs[ARGUS_ICMP_DSR_INDEX] = far; break; case ARGUS_RTP_DSR: if (retn & ARGUS_RTP_DSR_STATUS) return (retn); retn |= ARGUS_RTP_DSR_STATUS; hdrs[ARGUS_RTP_DSR_INDEX] = far; break; case ARGUS_IGMP_DSR: if (retn & ARGUS_IGMP_DSR_STATUS) return (retn); retn |= ARGUS_IGMP_DSR_STATUS; hdrs[ARGUS_IGMP_DSR_INDEX] = far; break; case ARGUS_ARP_DSR: if (retn & ARGUS_ARP_DSR_STATUS) return (retn); retn |= ARGUS_ARP_DSR_STATUS; hdrs[ARGUS_ARP_DSR_INDEX] = far; break; case ARGUS_FRG_DSR: if (retn & ARGUS_FRG_DSR_STATUS) return (retn); retn |= ARGUS_FRG_DSR_STATUS; hdrs[ARGUS_FRG_DSR_INDEX] = far; break; case ARGUS_ESP_DSR: if (retn & ARGUS_ESP_DSR_STATUS) return (retn); retn |= ARGUS_ESP_DSR_STATUS; hdrs[ARGUS_ESP_DSR_INDEX] = far; break; } if ((farlen = far->length) == 0) break; if ((far->type == ARGUS_SRCUSRDATA_DSR) || (far->type == ARGUS_DSTUSRDATA_DSR)) farlen = farlen * 4; length -= farlen; far = (struct ArgusFarHeaderStruct *)((char *)far + farlen); } } return (retn); } char *ArgusVersionStr = "Argus Version "; int ArgusConvertInitialWriteStruct (struct WriteStruct *ws, struct ArgusRecord *argus) { int retn = 0; char *ptr; if (ws && argus) { bzero ((char *) argus, sizeof (*argus)); if ((ptr = strstr (ws->ws_init.initString, ArgusVersionStr)) != NULL) { ptr = &ptr[strlen(ArgusVersionStr)]; if (sscanf (ptr, "%d.%d", &major_version, &minor_version)) { argus->ahdr.type = ARGUS_MAR | ARGUS_WRITESTRUCT; argus->ahdr.length = sizeof (*argus); argus->ahdr.length = htons(argus->ahdr.length); argus->ahdr.cause = ARGUS_START; argus->ahdr.status = htonl(ARGUS_VERSION); argus->ahdr.argusid = htonl(ARGUS_COOKIE); argus->argus_mar.startime = ws->ws_init.startime; argus->argus_mar.now = ws->ws_init.now; argus->argus_mar.major_version = major_version; argus->argus_mar.minor_version = minor_version; argus->argus_mar.interfaceType = ws->ws_init.interfaceType; argus->argus_mar.interfaceStatus = ws->ws_init.interfaceStatus; argus->argus_mar.reportInterval = ws->ws_init.reportInterval; argus->argus_mar.argusMrInterval = ws->ws_init.dflagInterval; argus->argus_mar.record_len = -1; retn = 1; } } } return (retn); } #include #if !defined(__OpenBSD__) #include #endif extern int ArgusTotalBytes; extern int ArgusTotalCount; extern long long ntohll (long long); int ArgusConvertWriteStruct (struct WriteStruct *ws, struct ArgusRecord *argus) { int retn = 0; unsigned int status; if (ws && argus) { bzero ((char *) argus, sizeof (*argus)); status = ntohl(ws->status); if (status & ARGUSCONTROL) { argus->ahdr.type = ARGUS_MAR | ARGUS_WRITESTRUCT; argus->ahdr.length = sizeof (*argus); argus->ahdr.argusid = 0; argus->ahdr.status = ARGUS_VERSION; argus->argus_mar.major_version = VERSION_MAJOR; argus->argus_mar.minor_version = VERSION_MINOR; argus->argus_mar.interfaceType = ws->ws_stat.interfaceType; argus->argus_mar.interfaceStatus = ws->ws_stat.interfaceStatus; argus->argus_mar.reportInterval = ntohs(ws->ws_stat.reportInterval); argus->argus_mar.argusMrInterval = ntohs(ws->ws_stat.dflagInterval); if (status & CLOSE) { argus->ahdr.cause = ARGUS_STOP; argus->argus_mar.startime.tv_sec = (ws->ws_stat.startime.tv_sec); argus->argus_mar.startime.tv_usec = (ws->ws_stat.startime.tv_usec); argus->argus_mar.now.tv_sec = (ws->ws_stat.now.tv_sec); argus->argus_mar.now.tv_usec = (ws->ws_stat.now.tv_usec); argus->argus_mar.pktsRcvd = ArgusTotalCount; argus->argus_mar.bytesRcvd = ArgusTotalBytes; argus->argus_mar.pktsDrop = ntohl(ws->ws_stat.pktsDrop); argus->argus_mar.actIPcons += ntohl(ws->ws_stat.actTCPcons); argus->argus_mar.actIPcons += ntohl(ws->ws_stat.actUDPcons); argus->argus_mar.actIPcons += ntohl(ws->ws_stat.actIPcons); argus->argus_mar.cloIPcons += ntohl(ws->ws_stat.cloTCPcons); argus->argus_mar.cloIPcons += ntohl(ws->ws_stat.cloUDPcons); argus->argus_mar.cloIPcons += ntohl(ws->ws_stat.cloIPcons); argus->argus_mar.actICMPcons = ntohl(ws->ws_stat.actICMPcons); argus->argus_mar.cloICMPcons = ntohl(ws->ws_stat.cloICMPcons); } else { argus->ahdr.cause = ARGUS_STATUS; argus->argus_mar.startime.tv_sec = ntohl(ws->ws_stat.startime.tv_sec); argus->argus_mar.startime.tv_usec = ntohl(ws->ws_stat.startime.tv_usec); argus->argus_mar.now.tv_sec = ntohl(ws->ws_stat.now.tv_sec); argus->argus_mar.now.tv_usec = ntohl(ws->ws_stat.now.tv_usec); argus->argus_mar.pktsRcvd = ntohl(ws->ws_stat.pktsRcvd); argus->argus_mar.bytesRcvd = ntohl(ws->ws_stat.bytesRcvd); argus->argus_mar.pktsDrop = ntohl(ws->ws_stat.pktsDrop); argus->argus_mar.actIPcons += ntohl(ws->ws_stat.actTCPcons); argus->argus_mar.actIPcons += ntohl(ws->ws_stat.actUDPcons); argus->argus_mar.actIPcons += ntohl(ws->ws_stat.actIPcons); argus->argus_mar.cloIPcons += ntohl(ws->ws_stat.cloTCPcons); argus->argus_mar.cloIPcons += ntohl(ws->ws_stat.cloUDPcons); argus->argus_mar.cloIPcons += ntohl(ws->ws_stat.cloIPcons); argus->argus_mar.actICMPcons = ntohl(ws->ws_stat.actICMPcons); argus->argus_mar.cloICMPcons = ntohl(ws->ws_stat.cloICMPcons); } argus->argus_mar.record_len = -1; retn = 1; } else { struct ArgusMacStruct macbuffer, *mac = &macbuffer; unsigned int lasttime = 0; unsigned short difftime = 0, ttl = 0; argus->ahdr.type = ARGUS_FAR | ARGUS_WRITESTRUCT; argus->ahdr.length = sizeof (argus->ahdr) + sizeof (argus->argus_far); argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.status = ARGUS_VERSION; argus->ahdr.status |= ETHERTYPE_IP; argus->ahdr.argusid = 0; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); argus->argus_far.status = 0; argus->argus_far.ArgusTransRefNum = 0; argus->argus_far.flow.ip_flow.ip_src = ntohl(ws->ws_ip.src.s_addr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(ws->ws_ip.dst.s_addr); if (!(status & (ICMPPROTO | TCPPROTO | UDPPROTO)) && (status & FRAG_ONLY)) { struct ArgusFragObject fragbuf, *frag = &fragbuf; bzero ((char *) frag, sizeof (*frag)); frag->type = ARGUS_FRG_DSR; frag->length = sizeof(*frag); frag->status = ntohs(ws->ws_ip_frag.status); argus->argus_far.flow.ip_flow.sport = ntohs(ws->ws_ip.sport); argus->argus_far.flow.ip_flow.dport = ntohs(ws->ws_ip.dport); argus->argus_far.flow.ip_flow.tp_p = ARGUS_FRAG_FLOWTAG; frag->fragnum = ntohl(ws->ws_ip_frag.fragnum); frag->frag_id = ntohl(ws->ws_ip_frag.frag_id); frag->totlen = ntohs(ws->ws_ip_frag.totlen); frag->currlen = ntohs(ws->ws_ip_frag.currlen); frag->maxfraglen = ntohs(ws->ws_ip_frag.maxfraglen); argus->argus_far.status |= ARGUS_FRAGMENTS; argus->argus_far.src.count = frag->fragnum; argus->argus_far.src.bytes = frag->currlen; bcopy ((char *)frag, &((char *)argus)[argus->ahdr.length], sizeof(*frag)); argus->ahdr.length += sizeof(*frag); } else { switch (status & (ICMPPROTO | TCPPROTO | UDPPROTO)) { case ICMPPROTO: { struct icmpWriteStruct *icmp = &ws->ws_ip_icmp; struct ArgusICMPFlow *icmpFlow = &argus->argus_far.flow.icmp_flow; argus->argus_far.flow.ip_flow.ip_p = IPPROTO_ICMP; argus->argus_far.src.count = ntohl(ws->ws_ip_udp.src_count); argus->argus_far.src.bytes = ntohl(ws->ws_ip_udp.src_bytes); argus->argus_far.dst.count = ntohl(ws->ws_ip_udp.dst_count); argus->argus_far.dst.bytes = ntohl(ws->ws_ip_udp.dst_bytes); if (!(status & (CON_ESTABLISHED | TIMED_OUT))) { icmpFlow->type = icmp->type; icmpFlow->code = icmp->code; icmpFlow->id = icmp->data; icmpFlow->id = ntohs(icmpFlow->id); } else { icmpFlow->type = ((unsigned char *) &ws->ws_ip_udp.src_bytes)[0]; icmpFlow->code = ((unsigned char *) &ws->ws_ip_udp.src_bytes)[1]; icmpFlow->id = ((unsigned short *)&ws->ws_ip_udp.src_bytes)[1]; icmpFlow->id = ntohs(icmpFlow->id); argus->argus_far.src.bytes = 0; argus->argus_far.dst.bytes = 0; } if ((icmpFlow->type == ICMP_UNREACH) && (icmpFlow->code == ICMP_UNREACH_PORT)) argus->argus_far.flow.ip_flow.tp_p = ((char *)&ws->ws_ip_icmp.gwaddr.s_addr)[3]; break; } case TCPPROTO: { struct ArgusTCPObject tcpbuffer, *tcp = &tcpbuffer; bzero ((char *) tcp, sizeof (*tcp)); tcp->type = ARGUS_TCP_DSR; tcp->length = sizeof(*tcp); if (status & SAW_SYN) tcp->state |= ARGUS_SAW_SYN; if (status & SAW_SYN_SENT) tcp->state |= ARGUS_SAW_SYN_SENT; if (status & CON_ESTABLISHED) tcp->state |= ARGUS_CON_ESTABLISHED; if (status & SRC_RESET) tcp->state |= ARGUS_SRC_RESET; if (status & DST_RESET) tcp->state |= ARGUS_DST_RESET; if (status & CLOSE_WAITING) tcp->state |= ARGUS_FIN; if (status & NORMAL_CLOSE) tcp->state |= ARGUS_NORMAL_CLOSE; if (status & PKTS_RETRANS) { if (status & SRC_PKTS_RETRANS) tcp->state |= ARGUS_SRC_PKTS_RETRANS; if (status & DST_PKTS_RETRANS) tcp->state |= ARGUS_DST_PKTS_RETRANS; } argus->argus_far.src.count = ntohl(ws->ws_ip_tcp.src_count); argus->argus_far.dst.count = ntohl(ws->ws_ip_tcp.dst_count); if ((status & SAW_SYN) && !(status & (SAW_SYN_SENT|CON_ESTABLISHED|RESET))) { tcp->src.seqbase = ntohl(ws->ws_ip_inittcp.seq); } else { if ((status & (SAW_SYN | SAW_SYN_SENT)) && !(status & (CON_ESTABLISHED))) { tcp->dst.seqbase = ntohl(ws->ws_ip_inittcp.seq); } else { argus->argus_far.src.bytes = ntohl(ws->ws_ip_tcp.src_bytes); argus->argus_far.dst.bytes = ntohl(ws->ws_ip_tcp.dst_bytes); } } bcopy ((char *)tcp, &((char *)argus)[argus->ahdr.length], sizeof(*tcp)); argus->ahdr.length += sizeof(*tcp); argus->argus_far.flow.ip_flow.ip_p = IPPROTO_TCP; argus->argus_far.flow.ip_flow.sport = ntohs(ws->ws_ip.sport); argus->argus_far.flow.ip_flow.dport = ntohs(ws->ws_ip.dport); break; } case UDPPROTO: argus->argus_far.flow.ip_flow.ip_p = IPPROTO_UDP; argus->argus_far.flow.ip_flow.sport = ntohs(ws->ws_ip.sport); argus->argus_far.flow.ip_flow.dport = ntohs(ws->ws_ip.dport); default: argus->argus_far.src.count = ntohl(ws->ws_ip_udp.src_count); argus->argus_far.src.bytes = ntohl(ws->ws_ip_udp.src_bytes); argus->argus_far.dst.count = ntohl(ws->ws_ip_udp.dst_count); argus->argus_far.dst.bytes = ntohl(ws->ws_ip_udp.dst_bytes); break; } } if (status & TIMED_OUT) argus->ahdr.cause |= ARGUS_TIMEOUT; if (status & FRAGMENTS) argus->argus_far.status |= ARGUS_FRAGMENTS; if (status & IPOPTIONMASK) { argus->argus_far.status |= ARGUS_IPOPTIONS; if (status & SSRCROUTE) { argus->argus_far.attr_ip.soptions |= ARGUS_SSRCROUTE; argus->argus_far.attr_ip.doptions |= ARGUS_SSRCROUTE; } if (status & LSRCROUTE) { argus->argus_far.attr_ip.soptions |= ARGUS_LSRCROUTE; argus->argus_far.attr_ip.doptions |= ARGUS_LSRCROUTE; } if (status & TIMESTAMP) { argus->argus_far.attr_ip.soptions |= ARGUS_TIMESTAMP; argus->argus_far.attr_ip.doptions |= ARGUS_TIMESTAMP; } if (status & SECURITY) { argus->argus_far.attr_ip.soptions |= ARGUS_SECURITY; argus->argus_far.attr_ip.doptions |= ARGUS_SECURITY; } if (status & RECORDROUTE) { argus->argus_far.attr_ip.soptions |= ARGUS_RECORDROUTE; argus->argus_far.attr_ip.doptions |= ARGUS_RECORDROUTE; } if (status & RTRALERT) { argus->argus_far.attr_ip.soptions |= ARGUS_RTRALERT; argus->argus_far.attr_ip.doptions |= ARGUS_RTRALERT; } } if (status & CON_ESTABLISHED) argus->ahdr.status |= ARGUS_CONNECTED; argus->argus_far.time.start.tv_sec = ntohl(ws->ws_ip.startime.tv_sec); argus->argus_far.time.start.tv_usec = ntohl(ws->ws_ip.startime.tv_usec); if ((major_version > 1) || (minor_version > 6)) { difftime = ntohs(((u_short *)&ws->ws_ip.lasttime.tv_sec)[1]); lasttime = ntohl(((arg_uint32)ws->ws_ip.startime.tv_sec)) + difftime; ttl = ((u_short *)&ws->ws_ip.lasttime.tv_sec)[0]; ws->ws_ip.lasttime.tv_sec = lasttime; } argus->argus_far.time.last.tv_sec = ws->ws_ip.lasttime.tv_sec; argus->argus_far.time.last.tv_usec = ntohl(ws->ws_ip.lasttime.tv_usec); mac->type = ARGUS_MAC_DSR; mac->length = sizeof(*mac); bcopy((char *)&ws->ws_ip.ws_phys.ethersrc, (char *)&mac->phys_union.ether.ethersrc, 6); bcopy((char *)&ws->ws_ip.ws_phys.etherdst, (char *)&mac->phys_union.ether.etherdst, 6); bcopy ((char *)mac, &((char *)argus)[argus->ahdr.length], sizeof(*mac)); argus->ahdr.length += sizeof(*mac); retn = 1; } #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif } return (retn); } extern char *ArgusProgramName; void ArgusPrintStartDate (char *date, struct ArgusRecord *ptr) { char delim = ' '; struct timeval *tvp = NULL; if (ptr->ahdr.type & ARGUS_MAR) tvp = &ptr->argus_mar.startime; else tvp = &ptr->argus_far.time.start; if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) delim = RaFieldDelimiter; sprintf (&date[strlen(date)], "%s%c", print_time(tvp), delim); } void ArgusPrintLastDate (char *date, struct ArgusRecord *ptr) { char delim = ' '; struct timeval *tvp = NULL; if (ptr->ahdr.type & ARGUS_MAR) tvp = &ptr->argus_mar.now; else tvp = &ptr->argus_far.time.last; if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) delim = RaFieldDelimiter; sprintf (&date[strlen(date)], "%s%c", print_time(tvp), delim); } void ArgusPrintDate (char *date, struct ArgusRecord *ptr) { char delim = ' '; struct timeval *start = NULL, *last = NULL; if (ptr->ahdr.type & ARGUS_MAR) { start = &ptr->argus_mar.startime; last = &ptr->argus_mar.now; } else { start = &ptr->argus_far.time.start; last = &ptr->argus_far.time.last; } if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) delim = RaFieldDelimiter; if (RaPrintStartTime) sprintf (&date[strlen(date)], "%s%c", print_time(start), delim); if (!((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0'))) if (RaPrintStartTime && RaPrintLastTime) sprintf (&date[strlen(date)], " "); if (RaPrintLastTime) sprintf (&date[strlen(date)], "%s%c", print_time(last), delim); } void ArgusPrintSrcRate (char *, struct ArgusRecord *); void ArgusPrintDstRate (char *, struct ArgusRecord *); void ArgusPrintRate (char *, struct ArgusRecord *); void ArgusPrintLoss (char *, struct ArgusRecord *); void ArgusPrintSrcLoad (char *, struct ArgusRecord *); void ArgusPrintDstLoad (char *, struct ArgusRecord *); void ArgusPrintLoad (char *, struct ArgusRecord *); void ArgusPrintSrcTTL (char *, struct ArgusRecord *); void ArgusPrintDstTTL (char *, struct ArgusRecord *); void ArgusPrintSrcTOS (char *, struct ArgusRecord *); void ArgusPrintDstTOS (char *, struct ArgusRecord *); void ArgusPrintSrcVLAN (char *, struct ArgusRecord *); void ArgusPrintDstMPLS (char *, struct ArgusRecord *); void ArgusPrintWindow (char *, struct ArgusRecord *); void ArgusPrintDuration (char *, struct ArgusRecord *); void ArgusPrintAvgDuration (char *, struct ArgusRecord *); void ArgusPrintTransactions (char *, struct ArgusRecord *); void ArgusPrintTransactions (char *buf, struct ArgusRecord *ptr) { struct ArgusAGRStruct *ArgusThisAgr = NULL; int hits = 1; if (ptr->ahdr.type & ARGUS_MAR) { sprintf(&buf[strlen(buf)], " "); } else { ArgusThisAgr = (struct ArgusAGRStruct *)ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]; if (ArgusThisAgr && (ArgusThisAgr->type == ARGUS_AGR_DSR)) hits = ArgusThisAgr->count; sprintf(&buf[strlen(buf)], "%5d ", hits); } } void ArgusPrintAverageDuration (char *, struct ArgusRecord *); void ArgusPrintAvgDuration (char *date, struct ArgusRecord *ptr) { struct ArgusAGRStruct *ArgusThisAgr = NULL; char *sptr, *iptr, delim = ' '; struct timeval *start = NULL, *last = NULL; struct timeval buf, *time = &buf; if (ptr->ahdr.type & ARGUS_MAR) { start = &ptr->argus_mar.startime; last = &ptr->argus_mar.now; } else { start = &ptr->argus_far.time.start; last = &ptr->argus_far.time.last; } ArgusThisAgr = (struct ArgusAGRStruct *)ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]; if ((ArgusThisAgr && (ArgusThisAgr->type == ARGUS_AGR_DSR))) { int ArgusThisMultiplier = 1000; if (ArgusThisAgr->status & ARGUS_AGR_USECACTTIME) ArgusThisMultiplier = 1000000; time->tv_sec = ArgusThisAgr->act.meanval / ArgusThisMultiplier; time->tv_usec = ArgusThisAgr->act.meanval % ArgusThisMultiplier; } else { *time = *last; time->tv_sec -= start->tv_sec; time->tv_usec -= start->tv_usec; if (time->tv_usec < 0) { time->tv_sec--; time->tv_usec += 1000000; } if (time->tv_usec >= 1000000) { time->tv_sec++; time->tv_usec -= 1000000; } } iptr = &date[strlen(date)]; sptr = &date[strlen(date)]; if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) sprintf(sptr, "%u", (unsigned int) time->tv_sec); else sprintf(sptr, "%8u", (unsigned int) time->tv_sec); if (pflag) { sptr = &date[strlen(date)]; sprintf(sptr, ".%06d", (int) time->tv_usec); sptr[pflag + 1] = '\0'; } if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) sprintf(&date[strlen(date)], "%c", delim); else sprintf(&date[strlen(date)], "%c", ' '); } void ArgusPrintDuration (char *date, struct ArgusRecord *ptr) { char *sptr, *iptr, delim = ' '; struct timeval *start = NULL, *last = NULL; struct timeval buf, *time = &buf; if (ptr->ahdr.type & ARGUS_MAR) { start = &ptr->argus_mar.startime; last = &ptr->argus_mar.now; } else { start = &ptr->argus_far.time.start; last = &ptr->argus_far.time.last; } *time = *last; time->tv_sec -= start->tv_sec; time->tv_usec -= start->tv_usec; if (time->tv_usec < 0) { time->tv_sec--; time->tv_usec += 1000000; } if (time->tv_usec >= 1000000) { time->tv_sec++; time->tv_usec -= 1000000; } iptr = &date[strlen(date)]; sptr = &date[strlen(date)]; if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) sprintf(sptr, "%u", (unsigned int) time->tv_sec); else sprintf(sptr, "%8u", (unsigned int) time->tv_sec); if (pflag) { sptr = &date[strlen(date)]; sprintf(sptr, ".%06d", (int) time->tv_usec); sptr[pflag + 1] = '\0'; } if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) sprintf(&date[strlen(date)], "%c", delim); else sprintf(&date[strlen(date)], "%c", ' '); } void ArgusGetIndicatorString (struct ArgusRecord *, char *); void ArgusGetIndicatorString (struct ArgusRecord *argus, char *buf) { char *ptr = buf; bzero (buf, 16); if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) { if (argus->ahdr.type & ARGUS_MAR) { } else { if (argus->ahdr.status & ARGUS_MPLS) *ptr++ = 'm'; if (argus->ahdr.status & ARGUS_PPPoE) *ptr++ = 'p'; if (argus->ahdr.status & ARGUS_VLAN) *ptr++ = 'q'; if ((argus->ahdr.status & 0xFFFF) == ETHERTYPE_IP) { if (argus->argus_far.status & ARGUS_ICMP_MAPPED) *ptr++ = 'I'; if ((argus->argus_far.attr_ip.soptions & ARGUS_FRAGMENTS) || (argus->argus_far.attr_ip.doptions & ARGUS_FRAGMENTS)) { if (argus->argus_far.flow.ip_flow.tp_p == ARGUS_FRAG_FLOWTAG) *ptr++ = 'f'; else *ptr++ = 'F'; if (argus->argus_far.attr_ip.soptions & ARGUS_FRAGOVERLAP) *ptr++ = 'V'; } if (argus->ahdr.status & ARGUS_MULTIADDR) *ptr++ = 'M'; if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) { struct ArgusTCPObject *tcp = NULL; unsigned int status; tcp = (struct ArgusTCPObject *)ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]; if ((tcp != NULL) && ((status = tcp->state) != 0)) { if (status) { if (status & ARGUS_PKTS_RETRANS) { if ((status & ARGUS_SRC_PKTS_RETRANS) && (status & ARGUS_DST_PKTS_RETRANS)) *ptr++ = '*'; else { if (status & ARGUS_SRC_PKTS_RETRANS) *ptr++ = 's'; if (status & ARGUS_DST_PKTS_RETRANS) *ptr++ = 'd'; } } if (status & ARGUS_WINDOW_SHUT) { if ((status & ARGUS_SRC_WINDOW_SHUT) && (status & ARGUS_DST_WINDOW_SHUT)) *ptr++ = '@'; else { if (status & ARGUS_SRC_WINDOW_SHUT) *ptr++ = 'S'; if (status & ARGUS_DST_WINDOW_SHUT) *ptr++ = 'D'; } } if (status & ARGUS_ECN_CONGESTED) *ptr++ = 'E'; } } } if (ArgusThisFarStatus & ARGUS_ESP_DSR_STATUS) { struct ArgusESPStruct *esp = NULL; if ((esp = (struct ArgusESPStruct *)ArgusThisFarHdrs[ARGUS_ESP_DSR_INDEX]) != NULL) { if ((esp->src.lostseq > 0) && (esp->dst.lostseq > 0)) *ptr++ = '*'; else { if (esp->src.lostseq > 0) *ptr++ = 's'; if (esp->dst.lostseq > 0) *ptr++ = 'd'; } } } } } *ptr = RaFieldDelimiter; } else { int encdone = 0; bcopy (" ", buf, 9); if (argus->ahdr.type & ARGUS_MAR) { } else { if (argus->ahdr.status & ARGUS_MPLS) { buf[0] = 'm'; encdone++; } if (argus->ahdr.status & ARGUS_PPPoE) { buf[0] = 'p'; encdone++; } if (argus->ahdr.status & ARGUS_VLAN) { buf[0] = 'q'; encdone++; } if (encdone > 1) buf[0] = 'E'; if ((argus->ahdr.status & 0xFFFF) == ETHERTYPE_IP) { if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) { struct ArgusTCPObject *tcp = NULL; unsigned int status; tcp = (struct ArgusTCPObject *)ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]; if ((tcp != NULL) && ((status = tcp->state) != 0)) { if (status) { if (status & ARGUS_PKTS_RETRANS) { if ((status & ARGUS_SRC_PKTS_RETRANS) && (status & ARGUS_DST_PKTS_RETRANS)) buf[1] = '*'; else { if (status & ARGUS_SRC_PKTS_RETRANS) buf[1] = 's'; if (status & ARGUS_DST_PKTS_RETRANS) buf[1] = 'd'; } } if (status & ARGUS_WINDOW_SHUT) { if ((status & ARGUS_SRC_WINDOW_SHUT) && (status & ARGUS_DST_WINDOW_SHUT)) buf[2] = '@'; else { if (status & ARGUS_SRC_WINDOW_SHUT) buf[2] = 'S'; if (status & ARGUS_DST_WINDOW_SHUT) buf[2] = 'D'; } } if (status & ARGUS_ECN_CONGESTED) { if ((status & ARGUS_SRC_CONGESTED) && (status & ARGUS_DST_CONGESTED)) buf[2] = 'E'; else { if (status & ARGUS_SRC_CONGESTED) buf[2] = 'x'; if (status & ARGUS_DST_CONGESTED) buf[2] = 't'; } } } } } if (ArgusThisFarStatus & ARGUS_ESP_DSR_STATUS) { struct ArgusESPStruct *esp = NULL; if ((esp = (struct ArgusESPStruct *)ArgusThisFarHdrs[ARGUS_ESP_DSR_INDEX]) != NULL) { if ((esp->src.lostseq > 0) && (esp->dst.lostseq > 0)) buf[1] = '*'; else { if (esp->src.lostseq > 0) buf[1] = 's'; if (esp->dst.lostseq > 0) buf[1] = 'd'; } } } if (argus->ahdr.status & ARGUS_MULTIADDR) buf[3] = 'M'; if (argus->argus_far.status & ARGUS_ICMP_MAPPED) buf[4] = 'I'; if ((argus->argus_far.attr_ip.soptions & ARGUS_FRAGMENTS) || (argus->argus_far.attr_ip.doptions & ARGUS_FRAGMENTS)) { if (argus->argus_far.flow.ip_flow.tp_p == ARGUS_FRAG_FLOWTAG) buf[5] = 'f'; else buf[5] = 'F'; if ((argus->argus_far.attr_ip.soptions & ARGUS_FRAGOVERLAP) || (argus->argus_far.attr_ip.doptions & ARGUS_FRAGOVERLAP)) { buf[5] = 'V'; } } if ((argus->argus_far.attr_ip.soptions & ARGUS_IPOPTIONS) || (argus->argus_far.attr_ip.doptions & ARGUS_IPOPTIONS)) { switch ((argus->argus_far.attr_ip.soptions | argus->argus_far.attr_ip.doptions) & ARGUS_IPOPTIONS) { case ARGUS_SSRCROUTE: buf[6] = 'S'; break; case ARGUS_LSRCROUTE: buf[6] = 'L'; break; case ARGUS_TIMESTAMP: buf[6] = 'T'; break; case ARGUS_SECURITY: buf[6] = '+'; break; case ARGUS_RECORDROUTE: buf[6] = 'R'; break; case ARGUS_RTRALERT: buf[6] = 'A'; break; case ARGUS_IPOPTIONS: buf[6] = 'E'; break; default: buf[6] = 'O'; break; } } } } } return; } struct ArgusInterfaceStruct interfacetypes [] = { { 0, "DLT_NULL", "no link-layer encapsulation"}, { 1, "DLT_EN10MB", "Ethernet (10Mb)"}, { 2, "DLT_EN3MB", "Experimental Ethernet (3Mb)"}, { 3, "DLT_AX25", "Amateur Radio AX.25"}, { 4, "DLT_PRONET", "Proteon ProNET Token Ring"}, { 5, "DLT_CHAOS", "Chaos"}, { 6, "DLT_IEEE802", "IEEE 802 Networks"}, { 7, "DLT_ARCNET", "ARCNET"}, { 8, "DLT_SLIP", "Serial Line IP"}, { 9, "DLT_PPP", "Point-to-point Protocol"}, { 10,"DLT_FDDI", "FDDI"}, { 11, "DLT_ATM_RFC1483", "LLC/SNAP encapsulated atm"}, { 12, "DLT_LOOP", "loopback"}, {100, "DLT_ATM_RFC1483", "LLC/SNAP encapsulated atm"}, {101, "DLT_RAW", "raw IP"}, {102, "DLT_SLIP_BSDOS", "BSD/OS Serial Line IP"}, {103, "DLT_PPP_BSDOS", "BSD/OS Point-to-point Protocol"}, {104, "DLT_CHDLC", "Cisco HDLC"}, {-1, "Undefined", "Undefined"}, }; char argus_strbuf[MAXSTRLEN]; char * get_argus_string (struct ArgusRecord *); char * get_man_string (struct ArgusRecord *argus) { return (get_argus_string(argus)); } unsigned short ArgusThisProto; void ArgusPrintSourceID (char *buf, struct ArgusRecord *argus) { char argusIDStrBuf[32], *argusIDStr = argusIDStrBuf; bzero (argusIDStrBuf, 32); if (ArgusInput->ArgusManStart.ahdr.status & ARGUS_ID_IS_IPADDR) argusIDStr = ipaddr_string (&argus->ahdr.argusid); else sprintf (argusIDStr, "%u", argus->ahdr.argusid); sprintf(buf, "%-15.15s ", argusIDStr); } void ArgusPrintBinNumber (char *, struct ArgusRecord *); void ArgusPrintBins (char *, struct ArgusRecord *); void ArgusPrintBinNumber (char *buf, struct ArgusRecord *argus) { } void ArgusPrintBins (char *buf, struct ArgusRecord *argus) { } void ArgusPrintSequenceNumber (char *buf, struct ArgusRecord *argus) { sprintf(buf, "%d ", argus->ahdr.seqNumber); } void ArgusPrintIndicator (char *buf, struct ArgusRecord *argus) { ArgusGetIndicatorString (argus, buf); } void ArgusPrintMACAddress (char *buf, struct ArgusRecord *argus) { char *blankStr = " ", *esrcString, *edstString; ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); if (ArgusThisFarStatus & ARGUS_MAC_DSR_STATUS) { struct ArgusMacStruct *mac = (struct ArgusMacStruct *) ArgusThisFarHdrs[ARGUS_MAC_DSR_INDEX]; esrcString = etheraddr_string ((u_char *)&mac->phys_union.ether.ethersrc); edstString = etheraddr_string ((u_char *)&mac->phys_union.ether.etherdst); sprintf (buf, "%17.17s %17.17s ", esrcString, edstString); } else sprintf (buf, "%17.17s %17.17s ", blankStr, blankStr); } void ArgusPrintProto (char *buf, struct ArgusRecord *argus) { char protoStrBuf[16], *protoStr = NULL; u_short eproto; u_char proto; bzero (protoStrBuf, 16); if (argus->ahdr.type & ARGUS_MAR) { sprintf (protoStrBuf, " man "); protoStr = protoStrBuf; } else { switch (eproto = argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: { proto = argus->argus_far.flow.ip_flow.ip_p; protoStr = protoStrBuf; sprintf (protoStr, "%u", proto); protoStr = (nflag > 2) ? protoStrBuf : (proto >= IPPROTOSTR) ? "unas" : ip_proto_string[proto]; if ((proto == IPPROTO_UDP) && (argus->argus_far.flow.ip_flow.tp_p == ARGUS_RTP_FLOWTAG)) protoStr = "rtp"; if ((proto == IPPROTO_UDP) && (argus->argus_far.flow.ip_flow.tp_p == ARGUS_RTCP_FLOWTAG)) protoStr = "rtcp"; break; } default: protoStr = etherproto_string(eproto); break; } } if (protoStr != NULL) sprintf (buf, "%4.4s ", protoStr); } int ArgusPrintNet = 0; void ArgusPrintSrcNet (char *buf, struct ArgusRecord *argus) { ArgusPrintNet++; ArgusPrintSrcAddr (buf, argus); ArgusPrintNet--; } void ArgusPrintSrcAddr (char *buf, struct ArgusRecord *argus) { void *addr = NULL; struct ArgusFlow *flow; if (argus->ahdr.type & ARGUS_MAR) { ArgusThisProto = ETHERTYPE_IP; addr = &argus->argus_mar.argusid; } else { flow = &argus->argus_far.flow; ArgusThisProto = argus->ahdr.status & 0xFFFF; switch (ArgusThisProto) { case ETHERTYPE_IP: addr = &flow->ip_flow.ip_src; break; case ETHERTYPE_REVARP: case ETHERTYPE_ARP: ArgusThisProto = ETHERTYPE_IP; if (Rflag) addr = &flow->arp_flow.arp_tpa; else addr = &flow->arp_flow.arp_spa; break; default: addr = &flow->mac_flow.ehdr.ether_shost; break; } } ArgusPrintAddr (&buf[strlen(buf)], ArgusThisProto, addr); } void ArgusPrintDstNet (char *buf, struct ArgusRecord *argus) { ArgusPrintNet++; ArgusPrintDstAddr (buf, argus); ArgusPrintNet--; } void ArgusPrintDstAddr (char *buf, struct ArgusRecord *argus) { void *addr = NULL; struct ArgusFlow *flow; if (argus->ahdr.type & ARGUS_MAR) { sprintf (&buf[strlen(buf)], "%*d ", hfield, argus->argus_mar.nextMrSequenceNum); } else { flow = &argus->argus_far.flow; ArgusThisProto = argus->ahdr.status & 0xFFFF; switch (ArgusThisProto) { case ETHERTYPE_IP: addr = &flow->ip_flow.ip_dst; break; case ETHERTYPE_REVARP: ArgusThisProto = ETHERTYPE_IP; break; case ETHERTYPE_ARP: if (Rflag) { ArgusThisProto = ARGUS_ETHERTYPE; addr = argus->argus_far.attr_arp.response; } else { ArgusThisProto = ETHERTYPE_IP; addr = &flow->arp_flow.arp_tpa; } break; default: addr = &flow->mac_flow.ehdr.ether_dhost; break; } ArgusPrintAddr (&buf[strlen(buf)], ArgusThisProto, addr); } } void ArgusPrintAddr (char *buf, unsigned short proto, void *addr) { char *addrstr = NULL; int thishfield = hfield; switch (proto) { case ETHERTYPE_IP: if (ArgusPrintNet) { unsigned int naddr = (*(unsigned int *)addr & ipaddrtonetmask(*(unsigned int *)addr)); addrstr = ipaddr_string (&naddr); } else addrstr = ipaddr_string (addr); break; default: case ARGUS_ETHERTYPE: addrstr = etheraddr_string ((unsigned char *) addr); break; } if (addr != NULL) sprintf (buf, "%*.*s ", thishfield, thishfield, addrstr); else sprintf (buf, "%*.*s ", thishfield, thishfield, " "); } void ArgusPrintSrcPort (char *buf, struct ArgusRecord *argus) { struct ArgusFlow *flow = &argus->argus_far.flow; ArgusThisProto = argus->ahdr.status & 0xFFFF; if (argus->ahdr.type & ARGUS_MAR) { int thispfield = pfield; char marVersionBuf[32]; sprintf (marVersionBuf, " v%d.%d", argus->argus_mar.major_version, argus->argus_mar.minor_version); sprintf (&buf[strlen(buf)], "%-*.*s ", thispfield, thispfield, marVersionBuf); } else { switch (ArgusThisProto) { case ETHERTYPE_IP: { int adjnflag = 0; if (flow->ip_flow.sport != 20) { adjnflag = 2; nflag += adjnflag; } ArgusPrintPort (&buf[strlen(buf)], argus, flow->ip_flow.sport); if (adjnflag) { nflag -= adjnflag;} break; } case ETHERTYPE_REVARP: case ETHERTYPE_ARP: sprintf (&buf[strlen(buf)], "%*s", pfield - 1, " "); if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) sprintf (buf, "%c", RaFieldDelimiter); break; default: ArgusPrintPort (&buf[strlen(buf)], argus, flow->mac_flow.ssap); break; } } } int RaPrintIndex = 0; void ArgusPrintDstPort (char *buf, struct ArgusRecord *argus) { if (argus->ahdr.type & ARGUS_MAR) { sprintf (&buf[strlen(buf)], "%-*d", pfield + 1, argus->argus_mar.flows); } else { struct ArgusFlow *flow = &argus->argus_far.flow; ArgusThisProto = argus->ahdr.status & 0xFFFF; switch (ArgusThisProto) { case ETHERTYPE_IP: { ArgusPrintPort (&buf[strlen(buf)], argus, flow->ip_flow.dport); break; } case ETHERTYPE_REVARP: case ETHERTYPE_ARP: if (RaPrintIndex > 0) { if ((RaPrintAlgorithms[RaPrintIndex - 1] == ArgusPrintSrcAddr) || (RaPrintAlgorithms[RaPrintIndex - 1] == ArgusPrintDstAddr)) sprintf (&buf[strlen(buf)], "%*s", pfield - 1, " "); else sprintf (&buf[strlen(buf)], "%*s", pfield + 1, " "); } else sprintf (&buf[strlen(buf)], "%*s", pfield - 1, " "); if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) sprintf (buf, "%c", RaFieldDelimiter); break; default: ArgusPrintPort (&buf[strlen(buf)], argus, flow->mac_flow.dsap); break; } } } void ArgusPrintPort (char *buf, struct ArgusRecord *argus, unsigned short port) { int thispfield = pfield; unsigned char proto = argus->argus_far.flow.ip_flow.ip_p; switch (ArgusThisProto) { case ETHERTYPE_IP: { if (port != 0xFFFF) { if (nflag > 1) { switch (proto) { case IPPROTO_TCP: case IPPROTO_UDP: if (RaPrintIndex > 0) if ((RaPrintAlgorithms[RaPrintIndex - 1] == ArgusPrintSrcAddr) || (RaPrintAlgorithms[RaPrintIndex - 1] == ArgusPrintDstAddr)) if (RaFieldDelimiter == '\0') if (buf[strlen(buf) - 1] == ' ') buf[strlen(buf) - 1] = '.'; sprintf (buf, "%-*d ", thispfield, port); break; default: if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) sprintf (&buf[strlen(buf)], "%c", RaFieldDelimiter); else sprintf (buf, "%-*.*s ", thispfield, thispfield, " "); break; } } else { switch (proto) { case IPPROTO_TCP: case IPPROTO_UDP: if (RaPrintIndex > 0) if ((RaPrintAlgorithms[RaPrintIndex - 1] == ArgusPrintSrcAddr) || (RaPrintAlgorithms[RaPrintIndex - 1] == ArgusPrintDstAddr)) if (RaFieldDelimiter == '\0') if (buf[strlen(buf) - 1] == ' ') buf[strlen(buf) - 1] = '.'; if (proto == IPPROTO_TCP) sprintf (buf, "%-*.*s ", thispfield, thispfield, tcpport_string(port)); else sprintf (buf, "%-*.*s ", thispfield, thispfield, udpport_string(port)); break; default: if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) sprintf (&buf[strlen(buf)], "%c", RaFieldDelimiter); else sprintf (buf, "%-*.*s ", thispfield, thispfield, " "); break; } } } else { if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) { sprintf (buf, "%c", RaFieldDelimiter); } else { switch (proto) { default: sprintf (buf, "%-*.*s ", thispfield, thispfield, " "); break; case IPPROTO_TCP: case IPPROTO_UDP: if (RaPrintIndex > 0) if ((RaPrintAlgorithms[RaPrintIndex - 1] == ArgusPrintSrcAddr) || (RaPrintAlgorithms[RaPrintIndex - 1] == ArgusPrintDstAddr)) if (RaFieldDelimiter == '\0') if (buf[strlen(buf) - 1] == ' ') buf[strlen(buf) - 1] = '.'; if (argus->ahdr.status & ARGUS_MERGED) sprintf (buf, "%-*.*s ", thispfield, thispfield, "*"); else sprintf (buf, "%-*d ", thispfield, port); break; } } } break; } default: thispfield -= 2; if ((ArgusThisProto == 0) && (proto != 0)) { sprintf (buf, "%-*.*s ", thispfield, thispfield, llcsap_string((unsigned char) port)); } else { if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) { sprintf (buf, "%c", RaFieldDelimiter); } else { sprintf (buf, "%-*.*s ", thispfield, thispfield, " "); } } } } void ArgusPrintIpId (char *buf, struct ArgusRecord *argus) { struct ArgusFlow *flow = &argus->argus_far.flow; ArgusThisProto = argus->ahdr.status & 0xFFFF; if (argus->ahdr.type & ARGUS_MAR) { sprintf (&buf[strlen(buf)], " "); } else { switch (ArgusThisProto) { case ETHERTYPE_IP: { sprintf (&buf[strlen(buf)], "0x%04hx ", flow->ip_flow.ip_id); break; } default: sprintf (&buf[strlen(buf)], " "); break; } } } char *ArgusProcessStr = NULL; void ArgusPrintDir (char *buf, struct ArgusRecord *argus) { struct ArgusTCPObject *tcp = NULL; unsigned int status; int src_count = 0, dst_count = 0; char dirStr[8]; bzero (dirStr, 8); if (argus->ahdr.type & ARGUS_MAR) { sprintf (dirStr, " "); } else { ArgusThisProto = argus->ahdr.status & 0xFFFF; switch (ArgusThisProto) { case ETHERTYPE_IP: { strcpy (dirStr, "<->"); src_count = argus->argus_far.src.count; dst_count = argus->argus_far.dst.count; if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) tcp = (struct ArgusTCPObject *)ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]; if ((tcp != NULL) && ((status = tcp->state) != 0)) { if (!(status & (ARGUS_SAW_SYN | ARGUS_SAW_SYN_SENT))) { dirStr[1] = '?'; if (src_count) dirStr[2] = '>'; if (dst_count) dirStr[0] = '<'; } if (Rflag && (status & ARGUS_RESET)) { dirStr[0] = ' '; dirStr[2] = ' '; if (status & ARGUS_DST_RESET) { dirStr[0] = '<'; } if (status & ARGUS_SRC_RESET) { dirStr[2] = '>'; } dirStr[1] = '|'; ArgusProcessStr = process_state_strings[RA_RST_STATE]; } else if (status & ARGUS_RESET) { dirStr[0] = ' '; dirStr[2] = '>'; ArgusProcessStr = process_state_strings[RA_RST_STATE]; } else if (status & ARGUS_NORMAL_CLOSE) { dirStr[0] = ' '; dirStr[2] = '>'; ArgusProcessStr = process_state_strings[RA_CLO_STATE]; } else if (status & (ARGUS_FIN | ARGUS_FIN_ACK)) { dirStr[0] = ' '; dirStr[2] = '>'; ArgusProcessStr = process_state_strings[RA_FIN_STATE]; } else if (argus->ahdr.cause & ARGUS_TIMEOUT) { if (src_count) dirStr[2] = '>'; if (dst_count) dirStr[0] = '<'; ArgusProcessStr = process_state_strings[RA_TIM_STATE]; } else if (status & ARGUS_CON_ESTABLISHED) { dirStr[0] = ' '; dirStr[2] = '>'; if ((argus->argus_far.src.bytes == 0) && (argus->argus_far.dst.bytes == 0)) ArgusProcessStr = process_state_strings[RA_STA_STATE]; else ArgusProcessStr = process_state_strings[RA_CON_STATE]; } else if (status & ARGUS_SAW_SYN_SENT) { dirStr[0] = '<'; dirStr[2] = ' '; ArgusProcessStr = process_state_strings[RA_ACC_STATE]; } else if (status & ARGUS_SAW_SYN) { dirStr[0] = ' '; dirStr[2] = '>'; ArgusProcessStr = process_state_strings[RA_REQ_STATE]; } } else { if (argus->argus_far.src.count == 0) dirStr[2] = ' '; if (argus->argus_far.dst.count == 0) dirStr[0] = ' '; switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: dirStr[1] = '?'; if (argus->ahdr.cause & ARGUS_START) ArgusProcessStr = "REQ"; if (argus->ahdr.cause & ARGUS_STATUS) ArgusProcessStr = "CON"; if (argus->ahdr.cause & ARGUS_STOP) ArgusProcessStr = "CLO"; if (argus->ahdr.cause & ARGUS_TIMEOUT) ArgusProcessStr = "TIM"; if (argus->ahdr.cause & ARGUS_ERROR) ArgusProcessStr = "ERR"; break; default: if ((argus->ahdr.cause & ARGUS_TIMEOUT)) ArgusProcessStr = "TIM"; else if (src_count && dst_count) { if ((src_count == 1) && (dst_count == 1)) ArgusProcessStr = "ACC"; else ArgusProcessStr = "CON"; } else if (argus->ahdr.cause & ARGUS_START) ArgusProcessStr = "INT"; break; } } break; } case ETHERTYPE_REVARP: case ETHERTYPE_ARP: { if (Rflag) sprintf (dirStr, " is-at "); else sprintf (dirStr, "who-has"); break; } default: src_count = argus->argus_far.src.count; dst_count = argus->argus_far.dst.count; if (src_count == 0) sprintf (dirStr, " <- "); else if (dst_count == 0) sprintf (dirStr, " -> "); else sprintf (dirStr, " <-> "); break; } } sprintf (buf, "%s ", dirStr); } void ArgusPrintCounts (char *buf, struct ArgusRecord *argus) { int src_count = 0, dst_count = 0; if (argus->ahdr.type & ARGUS_MAR) { src_count = argus->argus_mar.pktsRcvd; dst_count = argus->argus_mar.pktsDrop; } else { src_count = argus->argus_far.src.count; dst_count = argus->argus_far.dst.count; } sprintf (buf, "%-8u %-8u ", src_count, dst_count); } void ArgusPrintSrcPackets (char *buf, struct ArgusRecord *argus) { int src_count = 0; if (argus->ahdr.type & ARGUS_MAR) { src_count = argus->argus_mar.pktsRcvd; } else { src_count = argus->argus_far.src.count; } sprintf (buf, "%-8u ", src_count); } void ArgusPrintDstPackets (char *buf, struct ArgusRecord *argus) { int dst_count = 0; if (argus->ahdr.type & ARGUS_MAR) { dst_count = argus->argus_mar.pktsDrop; } else { dst_count = argus->argus_far.dst.count; } sprintf (buf, "%-8u ", dst_count); } void ArgusPrintBytes (char *buf, struct ArgusRecord *argus) { int src_bytes = 0, dst_bytes = 0; if (argus->ahdr.type & ARGUS_MAR) { src_bytes = argus->argus_mar.bytesRcvd; dst_bytes = argus->argus_mar.flowsClosed; } else { if (Aflag) { src_bytes = argus->argus_far.src.appbytes; dst_bytes = argus->argus_far.dst.appbytes; } else { src_bytes = argus->argus_far.src.bytes; dst_bytes = argus->argus_far.dst.bytes; } } sprintf (buf, "%-12u %-12u", src_bytes, dst_bytes); } void ArgusPrintSrcBytes (char *buf, struct ArgusRecord *argus) { int src_bytes = 0; if (argus->ahdr.type & ARGUS_MAR) src_bytes = argus->argus_mar.bytesRcvd; else { if (Aflag) { src_bytes = argus->argus_far.src.appbytes; } else { src_bytes = argus->argus_far.src.bytes; } } sprintf (buf, "%-12u", src_bytes); } void ArgusPrintDstBytes (char *buf, struct ArgusRecord *argus) { int dst_bytes = 0; if (argus->ahdr.type & ARGUS_MAR) dst_bytes = argus->argus_mar.flowsClosed; else if (Aflag) { dst_bytes = argus->argus_far.dst.appbytes; } else { dst_bytes = argus->argus_far.dst.bytes; } sprintf (buf, "%-12u", dst_bytes); } #include void ArgusPrintSrcJitter (char *buf, struct ArgusRecord *argus) { RaPrintSrcTime = 1; RaPrintDstTime = 0; ArgusPrintJitter (buf, argus); } void ArgusPrintDstJitter (char *buf, struct ArgusRecord *argus) { RaPrintSrcTime = 1; RaPrintDstTime = 0; ArgusPrintJitter (buf, argus); } void ArgusPrintJitter (char *buf, struct ArgusRecord *argus) { struct ArgusTimeStruct *time = NULL; char stdstr[128], jitterstr[128]; int maxval = 0, minval = 0x7FFFFFFF, n, meanval = 0; long long sumtime = 0, tmpsumtime = 0; double sumsqrd = 0.0, stdev = 0.0; ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); time = (struct ArgusTimeStruct *) ArgusThisFarHdrs[ARGUS_TIME_DSR_INDEX]; if (RaPrintSrcTime) { bzero (stdstr, 128); bzero (jitterstr, 128); maxval = 0; minval = 0x7FFFFFFF; n = 0; if (time != NULL) { if (RaPrintActTime && time->src.act.n) { n += time->src.act.n; tmpsumtime = (time->src.act.meanval * time->src.act.n); sumtime += tmpsumtime; sumsqrd += (time->src.act.n * pow(time->src.act.stdev, 2.0)) + pow(tmpsumtime, 2.0)/time->src.act.n; maxval = (maxval < time->src.act.maxval) ? time->src.act.maxval : maxval; minval = (minval > time->src.act.minval) ? time->src.act.minval : minval; } if (RaPrintIdleTime && time->src.idle.n) { n += time->src.idle.n; tmpsumtime = (time->src.idle.meanval * time->src.idle.n); sumtime += tmpsumtime; sumsqrd += (time->src.idle.n * pow(time->src.idle.stdev, 2.0)) + pow(tmpsumtime, 2.0)/time->src.idle.n; maxval = (maxval < time->src.idle.maxval) ? time->src.idle.maxval : maxval; minval = (minval > time->src.idle.minval) ? time->src.idle.minval : minval; } } if (n > 0) { meanval = sumtime/n; /* stdev = sqrt (sumsqrd/n - pow (meanval, 2.0)); istdev = (stdev) * 1; sprintf (stdstr, "%d.%03d", istdev/1000, istdev%1000); stdstr[6] = '\0'; sprintf (jitterstr, "%6d.%03d (%6s)", meanval/1000, meanval%1000, stdstr); */ sprintf (jitterstr, "%6d.%03d", meanval/1000, meanval%1000); sprintf (&buf[strlen(buf)], "%-12s ", jitterstr); } else { sprintf (jitterstr, "%6d.%03d", meanval/1000, meanval%1000); sprintf (&buf[strlen(buf)], "%-12s ", jitterstr); } } if (RaPrintDstTime) { bzero (stdstr, 128); bzero (jitterstr, 128); sumtime = 0; sumsqrd = 0.0; meanval = 0; stdev = 0.0; maxval = 0; minval = 0x7FFFFFFF; n = 0; if (time != NULL) { if (RaPrintActTime && time->dst.act.n) { n += time->dst.act.n; tmpsumtime = (time->dst.act.meanval * time->dst.act.n); sumtime += tmpsumtime; sumsqrd += (time->dst.act.n * pow(time->dst.act.stdev, 2.0)) + pow(tmpsumtime, 2.0)/time->dst.act.n; maxval = (maxval < time->dst.act.maxval) ? time->dst.act.maxval : maxval; minval = (minval > time->dst.act.minval) ? time->dst.act.minval : minval; } if (RaPrintIdleTime && time->dst.idle.n) { n += time->dst.idle.n; tmpsumtime = (time->dst.idle.meanval * time->dst.idle.n); sumtime += tmpsumtime; sumsqrd += (time->dst.idle.n * pow(time->dst.idle.stdev, 2.0)) + pow(tmpsumtime, 2.0)/time->dst.idle.n; maxval = (maxval < time->dst.idle.maxval) ? time->dst.idle.maxval : maxval; minval = (minval > time->dst.idle.minval) ? time->dst.idle.minval : minval; } } if (n > 0) { meanval = sumtime/n; /* stdev = sqrt (sumsqrd/n - pow (meanval, 2.0)); istdev = (stdev)*1; sprintf (stdstr, "%d.%03d", istdev/1000, istdev%1000); stdstr[6] = '\0'; sprintf (jitterstr, "%6d.%03d (%s)", meanval/1000, meanval%1000, stdstr); */ sprintf (jitterstr, "%6d.%03d", meanval/1000, meanval%1000); sprintf (&buf[strlen(buf)], "%-12s", jitterstr); } else { sprintf (jitterstr, "%6d.%03d", meanval/1000, meanval%1000); sprintf (&buf[strlen(buf)], "%-12s", jitterstr); } } } void ArgusPrintSrcRate (char *buf, struct ArgusRecord *argus) { int src_count = 0; struct timeval *start = NULL, *last = NULL; struct timeval timebuf, *time = &timebuf; char tmpbuf[128], *ptr = tmpbuf; double seconds; start = &argus->argus_far.time.start; last = &argus->argus_far.time.last; *time = *last; time->tv_sec -= start->tv_sec; time->tv_usec -= start->tv_usec; if (time->tv_usec < 0) { time->tv_sec--; time->tv_usec += 1000000; } if (time->tv_usec >= 1000000) { time->tv_sec++; time->tv_usec -= 1000000; } seconds = (double)(time->tv_sec * 1.0) + (double)(time->tv_usec/1000000.0); src_count = argus->argus_far.src.count; if (src_count > 1) sprintf (ptr, "%.2f", ((double)(src_count)/seconds)); else sprintf (ptr, "%.2f", 0.0); sprintf (&buf[strlen(buf)], "%10s ", ptr); } void ArgusPrintDstRate (char *buf, struct ArgusRecord *argus) { int dst_count = 0; struct timeval *start = NULL, *last = NULL; struct timeval timebuf, *time = &timebuf; char tmpbuf[128], *ptr = tmpbuf; double seconds; start = &argus->argus_far.time.start; last = &argus->argus_far.time.last; *time = *last; time->tv_sec -= start->tv_sec; time->tv_usec -= start->tv_usec; if (time->tv_usec < 0) { time->tv_sec--; time->tv_usec += 1000000; } if (time->tv_usec >= 1000000) { time->tv_sec++; time->tv_usec -= 1000000; } seconds = (double)(time->tv_sec * 1.0) + (double)(time->tv_usec/1000000.0); dst_count = argus->argus_far.dst.count; if (dst_count > 1) sprintf (ptr, "%.2f", ((double)(dst_count)/seconds)); else sprintf (ptr, "%.2f", 0.0); sprintf (&buf[strlen(buf)], "%10s ", ptr); } void ArgusPrintRate (char *buf, struct ArgusRecord *argus) { int src_count = 0, dst_count = 0; struct timeval *start = NULL, *last = NULL; struct timeval timebuf, *time = &timebuf; char tmpbuf[128], *ptr = tmpbuf; double seconds; start = &argus->argus_far.time.start; last = &argus->argus_far.time.last; *time = *last; time->tv_sec -= start->tv_sec; time->tv_usec -= start->tv_usec; if (time->tv_usec < 0) { time->tv_sec--; time->tv_usec += 1000000; } if (time->tv_usec >= 1000000) { time->tv_sec++; time->tv_usec -= 1000000; } seconds = (double)(time->tv_sec * 1.0) + (double)(time->tv_usec/1000000.0); src_count = argus->argus_far.src.count; dst_count = argus->argus_far.dst.count; if (src_count > 1) sprintf (ptr, "%.2f", ((double)(src_count)/seconds)); else sprintf (ptr, "%.2f", 0.0); sprintf (buf, "%10s", ptr); if (dst_count > 1) sprintf (ptr, "%.2f", ((double)(dst_count)/seconds)); else sprintf (ptr, "%.2f", 0.0); sprintf (&buf[strlen(buf)], "%10s ", ptr); } /* struct ArgusTCPObjectMetrics { unsigned int seqbase, ackbytes; unsigned int bytes, rpkts; unsigned short win; unsigned char flags, pad; }; struct ArgusTCPObject { unsigned char type, length; unsigned short status; unsigned int state; unsigned int options; unsigned int synAckuSecs, ackDatauSecs; struct ArgusTCPObjectMetrics src, dst; }; */ void ArgusPrintLoss (char *buf, struct ArgusRecord *argus) { struct timeval *start = NULL, *last = NULL; struct timeval timebuf, *time = &timebuf; char tmpbuf[128], *ptr = tmpbuf; double seconds, srcLossPkts = 0.0, dstLossPkts = 0.0; if (argus->ahdr.type & ARGUS_MAR) { sprintf (&buf[strlen(buf)], "%22s", " "); } else { switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_UDP: { if (argus->argus_far.flow.ip_flow.tp_p == ARGUS_RTP_FLOWTAG) { if (ArgusThisFarStatus & ARGUS_RTP_DSR_STATUS) { struct ArgusRTPObject *rtp = (void *)ArgusThisFarHdrs[ARGUS_RTP_DSR_INDEX]; srcLossPkts = rtp->sdrop; dstLossPkts = rtp->ddrop; } } break; } case IPPROTO_ICMP: { struct ArgusICMPFlow *icmpFlow = &argus->argus_far.flow.icmp_flow; struct ArgusICMPObject *icmp = NULL; unsigned char ra_icmp_type = 0, ArgusRevIndicator = 0; if (ArgusThisFarStatus & ARGUS_ICMP_DSR_STATUS) { icmp = (struct ArgusICMPObject *)ArgusThisFarHdrs[ARGUS_ICMP_DSR_INDEX]; ra_icmp_type = icmp->icmp_type; } else ra_icmp_type = icmpFlow->type; switch (ra_icmp_type) { case ICMP_ECHOREPLY: ArgusRevIndicator = 1; case ICMP_ECHO: if (ArgusRevIndicator) { if (argus->argus_far.src.count > 0) srcLossPkts = (((argus->argus_far.src.count - argus->argus_far.dst.count) * 100.0) / ((argus->argus_far.src.count) * 1.0)); } else { if (argus->argus_far.src.count > 0) dstLossPkts = (((argus->argus_far.src.count - argus->argus_far.dst.count) * 100.0) / ((argus->argus_far.src.count) * 1.0)); } break; } break; } case IPPROTO_TCP: { struct ArgusTCPObject *tcp = NULL; unsigned int status; if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) tcp = (struct ArgusTCPObject *)ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]; if ((tcp != NULL) && ((status = tcp->state) != 0)) { if (argus->argus_far.src.count) srcLossPkts = (tcp->src.rpkts * 100.0)/(argus->argus_far.src.count * 1.0); if (argus->argus_far.dst.count) dstLossPkts = (tcp->dst.rpkts * 100.0)/(argus->argus_far.dst.count * 1.0); } break; } } start = &argus->argus_far.time.start; last = &argus->argus_far.time.last; *time = *last; time->tv_sec -= start->tv_sec; time->tv_usec -= start->tv_usec; if (time->tv_usec < 0) { time->tv_sec--; time->tv_usec += 1000000; } if (time->tv_usec >= 1000000) { time->tv_sec++; time->tv_usec -= 1000000; } seconds = (double)(time->tv_sec * 1.0) + (double)(time->tv_usec/1000000.0); if (seconds) { sprintf (ptr, "%.4f", ((double)srcLossPkts)); sprintf (buf, "%10s", ptr); sprintf (ptr, "%.4f", ((double)dstLossPkts)); sprintf (&buf[strlen(buf)], "%10s ", ptr); } else { sprintf (ptr, "%.4f", 0.0); sprintf (buf, "%10s", ptr); sprintf (ptr, "%.4f", 0.0); sprintf (&buf[strlen(buf)], "%10s ", ptr); } } } void ArgusPrintSrcLoad (char *buf, struct ArgusRecord *argus) { int src_count = 0, src_bytes = 0; struct timeval *start = NULL, *last = NULL; struct timeval timebuf, *time = &timebuf; char tmpbuf[128], *ptr = tmpbuf; double seconds; start = &argus->argus_far.time.start; last = &argus->argus_far.time.last; *time = *last; time->tv_sec -= start->tv_sec; time->tv_usec -= start->tv_usec; if (time->tv_usec < 0) { time->tv_sec--; time->tv_usec += 1000000; } if (time->tv_usec >= 1000000) { time->tv_sec++; time->tv_usec -= 1000000; } seconds = (double)(time->tv_sec * 1.0) + (double)(time->tv_usec/1000000.0); src_count = argus->argus_far.src.count; if (Aflag) { src_bytes = argus->argus_far.src.appbytes; } else { src_bytes = argus->argus_far.src.bytes; } if (seconds) { sprintf (ptr, "%.2f", ((double)(src_bytes * 8.0))/seconds); sprintf (&buf[strlen(buf)], "%11s ", ptr); } else { sprintf (ptr, "%.2f", 0.0); sprintf (&buf[strlen(buf)], "%11s ", ptr); } } void ArgusPrintDstLoad (char *buf, struct ArgusRecord *argus) { int dst_count = 0, dst_bytes = 0; struct timeval *start = NULL, *last = NULL; struct timeval timebuf, *time = &timebuf; char tmpbuf[128], *ptr = tmpbuf; double seconds; start = &argus->argus_far.time.start; last = &argus->argus_far.time.last; *time = *last; time->tv_sec -= start->tv_sec; time->tv_usec -= start->tv_usec; if (time->tv_usec < 0) { time->tv_sec--; time->tv_usec += 1000000; } if (time->tv_usec >= 1000000) { time->tv_sec++; time->tv_usec -= 1000000; } seconds = (double)(time->tv_sec * 1.0) + (double)(time->tv_usec/1000000.0); dst_count = argus->argus_far.dst.count; if (Aflag) { dst_bytes = argus->argus_far.dst.appbytes; } else { dst_bytes = argus->argus_far.dst.bytes; } if (seconds) { sprintf (ptr, "%.2f", ((double)(dst_bytes * 8.0))/seconds); sprintf (&buf[strlen(buf)], "%13s ", ptr); } else { sprintf (ptr, "%.2f", 0.0); sprintf (&buf[strlen(buf)], "%13s ", ptr); } } void ArgusPrintLoad (char *buf, struct ArgusRecord *argus) { int src_count = 0, dst_count = 0, src_bytes = 0, dst_bytes = 0; struct timeval *start = NULL, *last = NULL; struct timeval timebuf, *time = &timebuf; char tmpbuf[128], *ptr = tmpbuf; double seconds; start = &argus->argus_far.time.start; last = &argus->argus_far.time.last; *time = *last; time->tv_sec -= start->tv_sec; time->tv_usec -= start->tv_usec; if (time->tv_usec < 0) { time->tv_sec--; time->tv_usec += 1000000; } if (time->tv_usec >= 1000000) { time->tv_sec++; time->tv_usec -= 1000000; } seconds = (double)(time->tv_sec * 1.0) + (double)(time->tv_usec/1000000.0); src_count = argus->argus_far.src.count; dst_count = argus->argus_far.dst.count; if (Aflag) { src_bytes = argus->argus_far.src.appbytes; dst_bytes = argus->argus_far.dst.appbytes; } else { src_bytes = argus->argus_far.src.bytes; dst_bytes = argus->argus_far.dst.bytes; } if (seconds) { sprintf (ptr, "%.2f", ((double)(src_bytes * 8.0))/seconds); sprintf (buf, "%13s", ptr); sprintf (ptr, "%.2f", ((double)(dst_bytes * 8.0))/seconds); sprintf (&buf[strlen(buf)], "%13s ", ptr); } else { sprintf (ptr, "%.2f", 0.0); sprintf (buf, "%13s", ptr); sprintf (ptr, "%.2f", 0.0); sprintf (&buf[strlen(buf)], "%13s ", ptr); } } void ArgusPrintSrcTTL (char *buf, struct ArgusRecord *argus) { int i; if (RaPrintDistance) { int sdis = -1; for (i = 1; i < 257; i <<= 1) { if ((sdis < 0) && (argus->argus_far.attr_ip.sttl <= i)) { sdis = i - argus->argus_far.attr_ip.sttl; } } sprintf (&buf[strlen(buf)], " %3d ", sdis); } else sprintf (&buf[strlen(buf)], " %3d ", argus->argus_far.attr_ip.sttl); } void ArgusPrintDstTTL (char *buf, struct ArgusRecord *argus) { int i; if (RaPrintDistance) { int ddis = -1; for (i = 1; i < 257; i <<= 1) { if ((ddis < 0) && (argus->argus_far.attr_ip.dttl <= i)) { ddis = i - argus->argus_far.attr_ip.dttl; } } sprintf (&buf[strlen(buf)], " %3d ", ddis); } else sprintf (&buf[strlen(buf)], " %3d ", argus->argus_far.attr_ip.dttl); } void ArgusPrintVLAN (char *buf, struct ArgusRecord *argus) { if (ArgusThisFarStatus & ARGUS_VLAN_DSR_STATUS) { struct ArgusVlanStruct *vlan = (struct ArgusVlanStruct *) ArgusThisFarHdrs[ARGUS_VLAN_DSR_INDEX]; if (vlan->status & ARGUS_SRC_VLAN) sprintf (&buf[strlen(buf)], "0x%04x ", vlan->sid); else sprintf(&buf[strlen(buf)], " "); if (vlan->status & ARGUS_DST_VLAN) sprintf (&buf[strlen(buf)], "0x%04x ", vlan->did); else sprintf(&buf[strlen(buf)], " "); } else sprintf (&buf[strlen(buf)], " "); } void ArgusPrintMPLS (char *buf, struct ArgusRecord *argus) { if (ArgusThisFarStatus & ARGUS_MPLS_DSR_STATUS) { struct ArgusMplsStruct *mpls = (struct ArgusMplsStruct *) ArgusThisFarHdrs[ARGUS_MPLS_DSR_INDEX]; if (mpls->status & ARGUS_SRC_MPLS) sprintf (&buf[strlen(buf)], " %5x ", mpls->slabel); else sprintf(&buf[strlen(buf)], " "); if (mpls->status & ARGUS_DST_MPLS) sprintf (&buf[strlen(buf)], " %5x ", mpls->dlabel); else sprintf(&buf[strlen(buf)], " "); } else sprintf (&buf[strlen(buf)], " "); } void ArgusPrintSrcTOS (char *buf, struct ArgusRecord *argus) { sprintf (&buf[strlen(buf)], " %3d ", argus->argus_far.attr_ip.stos); } void ArgusPrintDstTOS (char *buf, struct ArgusRecord *argus) { sprintf (&buf[strlen(buf)], " %3d ", argus->argus_far.attr_ip.dtos); } void ArgusPrintWindow (char *buf, struct ArgusRecord *argus) { switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: { unsigned short srcwin, dstwin; struct ArgusTCPObject *tcp = NULL; if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) tcp = (struct ArgusTCPObject *)ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]; if (tcp != NULL) { srcwin = tcp->src.win; dstwin = tcp->dst.win; sprintf (&buf[strlen(buf)], "%-5d %-5d ", srcwin, dstwin); } else { sprintf (&buf[strlen(buf)], "%14s", " "); } break; } default: sprintf (&buf[strlen(buf)], "%14s", " "); } } void ArgusPrintTCPExtensions (char *buf, struct ArgusRecord *argus) { } char *ArgusTCPFlags [] = { "F", "S", "R", "P", "A", "U", "E", "C" }; void ArgusPrintStatus (char *buf, struct ArgusRecord *argus) { if (ArgusProcessStr == NULL) ArgusProcessStr = "UNK"; if (zflag) sprintf (buf, " "); if (Zflag) sprintf (buf, " "); if (argus->ahdr.type & ARGUS_MAR) { ArgusProcessStr = ArgusGetManStatus (argus); } else { switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: { struct ArgusTCPObject *tcp = NULL; char statusbuf[64], *TCPStatusString = statusbuf; char SrcTCPFlagsStr[16], DstTCPFlagsStr[16]; unsigned int status; if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) tcp = (struct ArgusTCPObject *)ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]; if ((tcp != NULL) && ((status = tcp->state) != 0)) { if (zflag || Zflag) { if (zflag) { bzero ((char *)TCPStatusString, sizeof(statusbuf)); if (status & ARGUS_SAW_SYN) strcat (TCPStatusString, "s"); if (status & ARGUS_SAW_SYN_SENT) strcat (TCPStatusString, "S"); if (status & ARGUS_CON_ESTABLISHED) strcat (TCPStatusString, "E"); if (status & ARGUS_FIN) strcat (TCPStatusString, "f"); if (status & ARGUS_FIN_ACK) strcat (TCPStatusString, "F"); if (status & ARGUS_NORMAL_CLOSE) strcat (TCPStatusString, "C"); if (status & ARGUS_RESET) strcat (TCPStatusString, "R"); } else { if (Zflag) { int i, index; bzero(SrcTCPFlagsStr, sizeof(SrcTCPFlagsStr)); bzero(DstTCPFlagsStr, sizeof(DstTCPFlagsStr)); for (i = 0, index = 1; i < 8; i++) { if (tcp->src.flags & index) { strcat (SrcTCPFlagsStr, ArgusTCPFlags[i]); } if (tcp->dst.flags & index) { strcat (DstTCPFlagsStr, ArgusTCPFlags[i]); } index <<= 1; } switch (Zflag) { case 'b': sprintf(TCPStatusString, "%s_%s", SrcTCPFlagsStr, DstTCPFlagsStr); break; case 's': sprintf(TCPStatusString, "%s", SrcTCPFlagsStr); break; case 'd': sprintf(TCPStatusString, "%s", DstTCPFlagsStr); break; } } } ArgusProcessStr = TCPStatusString; } } break; } case IPPROTO_ICMP: { ArgusProcessStr = ArgusGetICMPStatus (argus); break; } default: ArgusProcessStr = ArgusGetIPStatus (argus); break; } } sprintf (buf, "%s ", ArgusProcessStr); } char * get_tcp_string (struct ArgusRecord *argus) { return (get_argus_string(argus)); } char * get_udp_string (struct ArgusRecord *argus) { return (get_argus_string(argus)); } char * get_icmp_string (struct ArgusRecord *argus) { return (get_argus_string(argus)); } char * get_ip_string (struct ArgusRecord *argus) { return (get_argus_string(argus)); } char * get_nonip_string (struct ArgusRecord *argus) { return (get_argus_string(argus)); } char * get_argus_string (struct ArgusRecord *argus) { char tmpbuf[MAXSTRLEN], *ptr = tmpbuf; char *str = argus_strbuf, lastchr = ' '; char date[128]; int len = 0; ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); bzero (argus_strbuf, MAXSTRLEN); bzero (tmpbuf, MAXSTRLEN); for (RaPrintIndex = 0; RaPrintIndex < MAX_PRINT_ALG_TYPES; RaPrintIndex++) { if (RaPrintAlgorithms[RaPrintIndex] != NULL) RaPrintAlgorithms[RaPrintIndex](&argus_strbuf[strlen(argus_strbuf)], argus); else break; } while (isspace((int)(argus_strbuf[strlen(argus_strbuf) - 1]))) argus_strbuf[strlen(argus_strbuf) - 1] = '\0'; if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) { if (RaPrintDate) { bzero (date, 128); bzero (tmpbuf, MAXSTRLEN); ArgusPrintDate (date, argus); if (strlen(date) > 0) { len = strlen(date) - 1; lastchr = date[len]; } bcopy (str, ptr, len); str += len; ptr += len; if (len > 1) { if ((ptr[-1] == ' ') && (ptr > tmpbuf)) *--ptr = '\0'; } } while (*str) { if (*str == ' ') { if (lastchr != RaFieldDelimiter) *ptr++ = RaFieldDelimiter; while (isspace((int)*str)) str++; } lastchr = *str; *ptr++ = *str++; } if (tmpbuf[strlen(tmpbuf) - 1] == RaFieldDelimiter) tmpbuf[strlen(tmpbuf) - 1] = '\0'; bzero (argus_strbuf, MAXSTRLEN); bcopy (tmpbuf, argus_strbuf, strlen(tmpbuf)); } return (argus_strbuf); } char ArgusIPStatus[32]; char * ArgusGetIPStatus (struct ArgusRecord *argus) { if (argus->argus_far.src.count && argus->argus_far.dst.count) { strcpy (ArgusIPStatus, "CON"); } else { if (IN_MULTICAST(argus->argus_far.flow.ip_flow.ip_dst)) strcpy (ArgusIPStatus, "CON"); else strcpy (ArgusIPStatus, "INT"); } return (ArgusIPStatus); } char ArgusManStatus[32]; char * ArgusGetManStatus (struct ArgusRecord *argus) { bzero (ArgusManStatus, 32); if (argus->ahdr.cause & ARGUS_START) sprintf (ArgusManStatus, "STA"); else if (argus->ahdr.cause & ARGUS_STATUS) sprintf (ArgusManStatus, "CON"); else if (argus->ahdr.cause & ARGUS_STOP) sprintf (ArgusManStatus, "STP"); else if (argus->ahdr.cause & ARGUS_SHUTDOWN) sprintf (ArgusManStatus, "SHT"); else if (argus->ahdr.cause & ARGUS_ERROR) sprintf (ArgusManStatus, "ERR"); else if (argus->ahdr.cause & ARGUS_MAXLISTENEXCD) sprintf (ArgusManStatus, "MAX"); return(ArgusManStatus); } int ArgusRevIndicator = 0; char ArgusICMPStatus[32]; char * ArgusGetICMPStatus (struct ArgusRecord *argus) { struct ArgusICMPFlow *icmpFlow = &argus->argus_far.flow.icmp_flow; struct ArgusICMPObject *icmp = NULL; char ArgusResponseString[32]; char icmptype[32]; unsigned char ra_icmp_type = 0, ra_icmp_code = 0; unsigned short ra_icmp_data = 0; unsigned int ra_src_addr = 0, ra_dst_addr = 0, ra_gw_addr = 0; bzero (ArgusICMPStatus, 32); bzero (ArgusResponseString, 32); bzero (icmptype, 32); if (argus) { if (ArgusThisFarStatus & ARGUS_ICMP_DSR_STATUS) { icmp = (struct ArgusICMPObject *)ArgusThisFarHdrs[ARGUS_ICMP_DSR_INDEX]; if (icmp->type != ARGUS_ICMP_DSR) { icmp = NULL; } else { ra_src_addr = icmp->isrcaddr; ra_dst_addr = icmp->idstaddr; ra_gw_addr = icmp->igwaddr; ra_icmp_type = icmp->icmp_type; ra_icmp_code = icmpFlow->code; } } else { ra_icmp_type = icmpFlow->type; ra_icmp_code = icmpFlow->code; } ra_icmp_data = icmpFlow->id; if (ra_icmp_type < (unsigned char) (ICMP_MAXTYPE + 1)) strcpy (icmptype, icmptypestr[ra_icmp_type]); else strcpy (icmptype, "UNK"); switch (ra_icmp_type) { case ICMP_UNREACH: switch (ra_icmp_code) { case ICMP_UNREACH_NET: strcat (icmptype, "N"); if (ra_dst_addr) { u_long addr = ra_dst_addr; sprintf (ArgusResponseString, "net %s", ipaddr_string (&addr)); } break; case ICMP_UNREACH_HOST: strcat (icmptype, "H"); if (ra_dst_addr) sprintf (ArgusResponseString, "host %s", ipaddr_string (&ra_dst_addr)); break; case ICMP_UNREACH_PROTOCOL: strcat (icmptype, "O"); if (ra_icmp_data && (ra_icmp_data < IPPROTOSTR)) sprintf (ArgusResponseString,"proto %s", ip_proto_string[ra_icmp_data]); break; case ICMP_UNREACH_PORT: { int index = icmpFlow->tp_p; strcat (icmptype, "P"); if ((ra_icmp_data && ((index < IPPROTOSTR)) && (index > 0))) { sprintf (ArgusResponseString, "%s_port %d", ip_proto_string[index], ra_icmp_data); } else if (ra_icmp_data) sprintf (ArgusResponseString, "port %d", ra_icmp_data); break; } case ICMP_UNREACH_NEEDFRAG: strcat (icmptype, "F"); break; case ICMP_UNREACH_SRCFAIL: strcat (icmptype, "S"); break; #ifndef ICMP_UNREACH_NET_UNKNOWN #define ICMP_UNREACH_NET_UNKNOWN 6 #endif case ICMP_UNREACH_NET_UNKNOWN: strcat (icmptype, "NU"); sprintf (ArgusResponseString, "dst_net unknown"); break; #ifndef ICMP_UNREACH_HOST_UNKNOWN #define ICMP_UNREACH_HOST_UNKNOWN 7 #endif case ICMP_UNREACH_HOST_UNKNOWN: strcat (icmptype, "HU"); sprintf (ArgusResponseString, "dst_host unknown"); break; #ifndef ICMP_UNREACH_ISOLATED #define ICMP_UNREACH_ISOLATED 8 #endif case ICMP_UNREACH_ISOLATED: strcat (icmptype, "ISO"); sprintf (ArgusResponseString, "src_host isolated"); break; #ifndef ICMP_UNREACH_NET_PROHIB #define ICMP_UNREACH_NET_PROHIB 9 #endif case ICMP_UNREACH_NET_PROHIB: strcat (icmptype, "NPRO"); sprintf (ArgusResponseString, "admin_net prohib"); break; #ifndef ICMP_UNREACH_HOST_PROHIB #define ICMP_UNREACH_HOST_PROHIB 10 #endif case ICMP_UNREACH_HOST_PROHIB: strcat (icmptype, "HPRO"); sprintf (ArgusResponseString, "admin_host prohib"); break; #ifndef ICMP_UNREACH_TOSNET #define ICMP_UNREACH_TOSNET 11 #endif case ICMP_UNREACH_TOSNET: strcat (icmptype, "NTOS"); sprintf (ArgusResponseString, "tos_net prohib"); break; #ifndef ICMP_UNREACH_TOSHOST #define ICMP_UNREACH_TOSHOST 12 #endif case ICMP_UNREACH_TOSHOST: strcat (icmptype, "HTOS"); sprintf (ArgusResponseString, "tos_host prohib"); break; #ifndef ICMP_UNREACH_FILTER_PROHIB #define ICMP_UNREACH_FILTER_PROHIB 13 #endif case ICMP_UNREACH_FILTER_PROHIB: strcat (icmptype, "FIL"); sprintf (ArgusResponseString, "admin_filter prohib"); break; #ifndef ICMP_UNREACH_HOST_PRECEDENCE #define ICMP_UNREACH_HOST_PRECEDENCE 14 #endif case ICMP_UNREACH_HOST_PRECEDENCE: strcat (icmptype, "PRE"); sprintf (ArgusResponseString, "precedence violation"); break; #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 #endif case ICMP_UNREACH_PRECEDENCE_CUTOFF: strcat (icmptype, "CUT"); sprintf (ArgusResponseString, "precedence cutoff"); break; } break; case ICMP_MASKREPLY: ArgusRevIndicator = 1; if (ra_src_addr) sprintf (ArgusResponseString, "mask 0x%08x", ra_src_addr); break; case ICMP_REDIRECT: switch (ra_icmp_code) { case ICMP_REDIRECT_NET: (void) sprintf (ArgusResponseString, "net %s", ipaddr_string (&ra_gw_addr)); break; case ICMP_REDIRECT_HOST: (void) sprintf (ArgusResponseString, "host %s", ipaddr_string (&ra_gw_addr)); break; case ICMP_REDIRECT_TOSNET: (void) sprintf (ArgusResponseString, "tosN %s", ipaddr_string (&ra_gw_addr)); break; case ICMP_REDIRECT_TOSHOST: (void) sprintf (ArgusResponseString, "tosH %s", ipaddr_string (&ra_gw_addr)); break; } break; #ifndef ICMP_ROUTERADVERT #define ICMP_ROUTERADVERT 9 #endif case ICMP_ROUTERADVERT: sprintf (ArgusResponseString, "router advertisement"); break; #ifndef ICMP_ROUTERSOLICIT #define ICMP_ROUTERSOLICIT 10 #endif case ICMP_ROUTERSOLICIT: sprintf (ArgusResponseString, "router solicitation"); break; case ICMP_ECHOREPLY: case ICMP_TSTAMPREPLY: case ICMP_IREQREPLY: ArgusRevIndicator = 1; sprintf (ArgusResponseString, "%-6d %-6d", argus->argus_far.src.bytes, argus->argus_far.dst.bytes); break; case ICMP_TIMXCEED: (void) sprintf (ArgusResponseString, "timexceed %s", ra_icmp_code ? "reassembly" : "in-transit"); break; case ICMP_PARAMPROB: case ICMP_SOURCEQUENCH: case ICMP_ECHO: case ICMP_TSTAMP: case ICMP_IREQ: case ICMP_MASKREQ: sprintf (ArgusResponseString, "%-6d %-6d", argus->argus_far.src.bytes, argus->argus_far.dst.bytes); default: sprintf (ArgusResponseString, "%-6d %-6d", argus->argus_far.src.bytes, argus->argus_far.dst.bytes); break; } if (!(Rflag)) { sprintf (ArgusResponseString, "%-6d %-6d", argus->argus_far.src.bytes, argus->argus_far.dst.bytes); } strcpy (ArgusICMPStatus, icmptype); } return (ArgusICMPStatus); } char * get_arp_string (argus) struct ArgusRecord *argus; { return (get_argus_string(argus)); } #ifdef NOVFPRINTF /* * Stock 4.3 doesn't have vfprintf. * This routine is due to Chris Torek. */ vfprintf(f, fmt, args) FILE *f; char *fmt; va_list args; { int ret; if ((f->_flag & _IOWRT) == 0) { if (f->_flag & _IORW) f->_flag |= _IOWRT; else return EOF; } ret = _doprnt(fmt, args, f); return ferror(f) ? EOF : ret; } #endif extern int ArgusSrcUserDataLen; extern int ArgusDstUserDataLen; int ArgusEncode (const char *, const char *, int, char *, int); int ArgusEncode32 (const char *, int, char *, int); int ArgusEncode64 (const char *, int, char *, int); int ArgusEncodeAscii (const char *, int, char *, int); void ArgusPrintUserData (char *RaUserDataStr, struct ArgusRecord *argus) { char strbuf[MAXSTRLEN], *str = strbuf; char conbuf[MAXSTRLEN], *con = conbuf; int len = 0, exlen = 0; char delim = ' '; if ((RaFieldDelimiter != ' ') && (RaFieldDelimiter != '\0')) delim = RaFieldDelimiter; if ((ArgusSrcUserDataLen > 0) || (ArgusDstUserDataLen)) { if (ArgusSrcUserDataLen > 0) { switch (eflag) { case ARGUS_ENCODE_ASCII: exlen = ArgusSrcUserDataLen; break; case ARGUS_ENCODE_32: case ARGUS_ENCODE_64: exlen = ArgusSrcUserDataLen; exlen *= 2; break; } exlen += 8; if (ArgusSrcUserDataLen > 10) exlen++; if (ArgusThisFarStatus & ARGUS_SRCUSRDATA_DSR_STATUS) { struct ArgusUserStruct *user = (struct ArgusUserStruct *) ArgusThisFarHdrs[ARGUS_SRCUSRDATA_DSR_INDEX]; len = (user->length - 1) * 4; len = (len < argus->argus_far.src.appbytes) ? len : argus->argus_far.src.appbytes; len = len > ArgusSrcUserDataLen ? ArgusSrcUserDataLen : len; bzero (strbuf, sizeof(strbuf)); bzero (conbuf, sizeof(conbuf)); if ((len = ArgusEncode (&user->data, NULL, len, str, sizeof(strbuf))) > 0) sprintf (con, "%cs[%d]=%s", delim, len, str); else sprintf (con, " "); if (delim == ' ') sprintf (&RaUserDataStr[strlen(RaUserDataStr)], "%-*s ", exlen, con); else sprintf (&RaUserDataStr[strlen(RaUserDataStr)], "%-s ", con); } else { if (delim != ' ') sprintf (&RaUserDataStr[strlen(RaUserDataStr)], "%c", delim); else sprintf (&RaUserDataStr[strlen(RaUserDataStr)], "%-*s ", exlen, " "); } } if (ArgusDstUserDataLen > 0) { switch (eflag) { case ARGUS_ENCODE_ASCII: exlen = ArgusDstUserDataLen; break; case ARGUS_ENCODE_32: case ARGUS_ENCODE_64: exlen = ArgusDstUserDataLen; exlen *= 2; break; } exlen += 8; if (ArgusDstUserDataLen > 10) exlen++; if (ArgusThisFarStatus & ARGUS_DSTUSRDATA_DSR_STATUS) { struct ArgusUserStruct *user = (struct ArgusUserStruct *) ArgusThisFarHdrs[ARGUS_DSTUSRDATA_DSR_INDEX]; len = (user->length - 1) * 4; len = (len < argus->argus_far.dst.appbytes) ? len : argus->argus_far.dst.appbytes; len = len > ArgusDstUserDataLen ? ArgusDstUserDataLen : len; bzero (strbuf, sizeof(strbuf)); bzero (conbuf, sizeof(conbuf)); if ((len = ArgusEncode (&user->data, NULL, len, str, sizeof(strbuf))) > 0) sprintf (con, "%cd[%d]=%s", delim, len, str); else sprintf (con, " "); if (delim == ' ') sprintf (&RaUserDataStr[strlen(RaUserDataStr)], "%-*s ", exlen, con); else sprintf (&RaUserDataStr[strlen(RaUserDataStr)], "%-s ", con); } else if (delim != ' ') sprintf (&RaUserDataStr[strlen(RaUserDataStr)], "%c", delim); else sprintf (&RaUserDataStr[strlen(RaUserDataStr)], "%-*s ", exlen, " "); } sprintf (&RaUserDataStr[strlen(RaUserDataStr)], " "); } } static char basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????"; int ArgusEncode (const char *ptr, const char *mask, int len, char *str, int slen) { int retn = 0, i; switch (eflag) { case ARGUS_ENCODE_32: sprintf (str, "\""); retn = ArgusEncode32(ptr, len, &str[strlen(str)], slen - strlen(str)); strcat (str, "\""); if (mask != NULL) { for (i = 0; i < len; i++) { if ((mask[i/8] & (0x80 >> (i % 8)))) { str[(1+(2*i))] = ' '; str[(1+(2*i)) + 1] = ' '; } } } break; case ARGUS_ENCODE_64: sprintf (str, "\""); retn = ArgusEncode64(ptr, len, &str[strlen(str)], slen - strlen(str)); strcat (str, "\""); break; case ARGUS_ENCODE_ASCII: sprintf (str, "\""); retn = ArgusEncodeAscii(ptr, len, &str[strlen(str)], slen - strlen(str)); strcat (str, "\""); if (mask != NULL) { for (i = 0; i < len; i++) if ((mask[i/8] & (0x80 >> (i % 8)))) str[(1+i)] = ' '; } break; default: ArgusLog (LOG_ERR, "ArgusEncode: error encode method %d unknown", eflag); break; } return (retn); } static char basis_16[] = "0123456789ABCDEF"; int ArgusEncode32 (const char *ptr, int len, char *str, int slen) { int retn = 0, i; unsigned char *buf = (unsigned char *) str; unsigned newlen; if (ptr && ((newlen = (((len + 1) & ~0x01) * 2)) < slen)) { for (i = 0; i < len; i++) { *buf++ = basis_16[((ptr[i] & 0xF0) >> 4)]; *buf++ = basis_16[((ptr[i] & 0x0F))]; } retn = newlen; } return (retn); } int ArgusEncode64 (const char *ptr, int len, char *str, int slen) { int retn = 0; const unsigned char *in = (const unsigned char *)ptr; unsigned char *buf = (unsigned char *) str; unsigned char oval; unsigned newlen; if (ptr && ((newlen = (len + 2) / 3 * 4) < slen)) { while (len >= 3) { *buf++ = basis_64[in[0] >> 2]; *buf++ = basis_64[((in[0] << 4) & 0x30) | (in[1] >> 4)]; *buf++ = basis_64[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; *buf++ = basis_64[in[2] & 0x3f]; in += 3; len -= 3; } if (len > 0) { *buf++ = basis_64[in[0] >> 2]; oval = (in[0] << 4) & 0x30; if (len > 1) oval |= in[1] >> 4; *buf++ = basis_64[oval]; *buf++ = (len < 2) ? '=' : basis_64[(in[1] << 2) & 0x3c]; *buf++ = '='; } retn = newlen; } return (retn); } #include int ArgusEncodeAscii (const char *ptr, int len, char *str, int slen) { int retn = 0, newlen = len; unsigned char *buf = (unsigned char *) str; if (ptr && (len < slen)) { while (len > 0) { if (isascii((int)*ptr) && isprint((int)*ptr)) *buf = *ptr; else *buf = '.'; buf++; ptr++; len--; } if (!(Pflag)) { if ((buf = (unsigned char *) strstr (str, "PASS")) != NULL) { buf += 5; while (((void *)(str + newlen) > (void *) buf) && ((*buf != ' ') && (*buf != '.'))) *buf++ = 'x'; } } retn = newlen; } return (retn); } argus-clients-2.0.6.fixes.1/common/gencode.c0000664000076600007660000014151310043234437014317 /* * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #ifndef linux #include #include #include #endif #include #include #include #ifdef linux #include #include #include #endif #include #include #include #include #include #include #include #ifndef __GNUC__ #define inline #endif #define JMP(c) ((c)|BPF_JMP|BPF_K) static jmp_buf top_ctx; static u_int off_nl = 0; static int alloc_reg(void); static void free_reg(int); static struct ablock *root; /* * We divy out chunks of memory rather than call malloc each time so * we don't have to worry about leaking memory. It's probably * not a big deal if all this memory was wasted but it this ever * goes into a library that would probably not be a good idea. */ #define NCHUNKS 16 #define CHUNK0SIZE 1024 struct chunk { u_int n_left; void *m; }; static struct chunk chunks[NCHUNKS]; static int cur_chunk; static void *newchunk(u_int); static void freechunks(void); static struct ablock *new_block(int); static struct slist *new_stmt(int); static struct ablock *Argusgen_retblk(int); static void syntax(void); static void backpatch(struct ablock *, struct ablock *); static void merge(struct ablock *, struct ablock *); static struct ablock *Argusgen_cmp(u_int, u_int, u_int); static struct ablock *Argusgen_mcmp(u_int, u_int, u_int, u_int); static struct ablock *Argusgen_bcmp(u_int, u_int, u_char *); static struct ablock *Argusgen_prototype(u_int); static struct ablock *Argusgen_hostop(u_int, u_int, int, u_int, u_int, u_int); static struct ablock *Argusgen_ehostop(u_char *, int); static struct ablock *Argusgen_host(u_int, u_int, int, int); static struct ablock *Argusgen_srcid(u_int, u_int); static struct ablock *Argusgen_gateway(u_char *, u_int **, int, int); static struct ablock *Argusgen_portatom(int, long); struct ablock *Argusgen_portop(int, int, int); static struct ablock *Argusgen_port(int, u_int, int); static int lookup_proto(char *, int); static struct ablock *Argusgen_proto(int, int, int); static struct ablock *Argusgen_ttl(int, int); static struct ablock *Argusgen_tos(int, int); static struct ablock *Argusgen_vid(int, int); static struct ablock *Argusgen_mid(int, int); static u_int net_mask(u_int *); static struct slist *xfer_to_x(struct arth *); static struct slist *xfer_to_a(struct arth *); static struct ablock *Argusgen_len(int, int); extern void ArgusLog (int, char *, ...); static void * newchunk(n) u_int n; { struct chunk *cp; int k, size; /* XXX Round up to nearest long. */ n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1); cp = &chunks[cur_chunk]; if (n > cp->n_left) { ++cp, k = ++cur_chunk; if (k >= NCHUNKS) ArgusLog(LOG_ERR, "out of memory"); size = CHUNK0SIZE << k; cp->m = (void *)malloc(size); memset((char *)cp->m, 0, size); cp->n_left = size; if (n > size) ArgusLog(LOG_ERR, "out of memory"); } cp->n_left -= n; return (void *)((char *)cp->m + cp->n_left); } static void freechunks() { int i; for (i = 0; i < NCHUNKS; ++i) if (chunks[i].m) free(chunks[i].m); } /* * A strdup whose allocations are freed after code generation is over. */ char * Argussdup(s) char *s; { int n = strlen(s) + 1; char *cp = newchunk(n); strcpy(cp, s); return (cp); } static struct ablock * new_block(code) int code; { struct ablock *p; p = (struct ablock *)newchunk(sizeof(*p)); p->s.code = code; p->head = p; return p; } static struct slist * new_stmt(code) int code; { struct slist *p; p = (struct slist *)newchunk(sizeof(*p)); p->s.code = code; return p; } static struct ablock * Argusgen_retblk(v) int v; { struct ablock *b = new_block(BPF_RET|BPF_K); b->s.k = v; return b; } static void syntax() { ArgusLog(LOG_ERR, "syntax error in filter expression"); } #include #include static u_int ArgusNetMask; static int snaplen; int ArgusFilterCompile(struct bpf_program *program, char *buf, int optimize, unsigned int mask) { extern int argus_n_errors; int retn = 0, len, filedes[2], width, status = 0; pid_t pid; if ((pipe (filedes)) < 0) ArgusLog (LOG_ERR, "pipe %s", strerror(errno)); if ((pid = fork()) > 0) { fd_set readmask; struct timeval wait; wait.tv_sec = 0; wait.tv_usec = 200000; FD_ZERO (&readmask); FD_SET (filedes[0], &readmask); width = filedes[0] + 1; #if defined(ARGUSDEBUG) ArgusDebug (4, "ArgusFilterCompile () waiting for filter process %d on pipe %d\n", pid, filedes[0]); #endif while ((retn = select (width, &readmask, NULL, NULL, &wait)) >= 0) { if (FD_ISSET (filedes[0], &readmask)) { if ((len = read (filedes[0], &program->bf_len, sizeof(program->bf_len))) > 0) { #if defined(ARGUSDEBUG) ArgusDebug (4, "ArgusFilterCompile () read filter length %d\n", program->bf_len); #endif if (program->bf_len > 0) { if ((program->bf_insns = (void *) calloc (program->bf_len, sizeof(*program->bf_insns))) != NULL) { if ((len = read (filedes[0], program->bf_insns, (program->bf_len * sizeof(*program->bf_insns)))) > 0) { #if defined(ARGUSDEBUG) ArgusDebug (4, "ArgusFilterCompile () read filter body %d\n", len); #endif retn = 0; status++; } } else ArgusLog(LOG_ERR, "ArgusFilterCompile: calloc error %s\n", strerror(errno)); } else retn = 0; } else ArgusLog(LOG_ERR, "ArgusFilterCompile: Error getting filter %s\n", strerror(errno)); } if (!status) { len = waitpid(pid, &status, WNOHANG); if ((len == pid) || (len == -1)) { #if defined(ARGUSDEBUG) ArgusDebug (4, "ArgusFilterCompile () filter process %d terminated\n", pid); #endif return (-1); } FD_SET (filedes[0], &readmask); width = filedes[0] + 1; wait.tv_sec = 0; wait.tv_usec = 200000; } else break; } waitpid(pid, &status, WNOHANG); } else { if (setjmp(top_ctx)) { syntax(); _exit(0); } ArgusNetMask = mask; snaplen = 96; argus_lex_init(buf ? buf : ""); argus_parse(); if (argus_n_errors) syntax(); if (root == NULL) root = Argusgen_retblk(snaplen); if (optimize) Argusbpf_optimize(&root); if (!(root == NULL || (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))) { program->bf_insns = Argusicode_to_fcode(root, &len); program->bf_len = len; freechunks(); } else ArgusLog (LOG_ALERT, "ArgusFilterCompile: expression rejects all packets\n"); #if defined(ARGUSDEBUG) ArgusDebug (3, "ArgusFilterCompile () returning\n"); #endif if ((len = write (filedes[1], &program->bf_len, sizeof(program->bf_len))) > 0) { if (program->bf_len > 0) { len = write (filedes[1], program->bf_insns, program->bf_len * sizeof(*program->bf_insns)); } } else ArgusLog (LOG_ERR, "ArgusFilterCompile: write retn %s\n", strerror(errno)); _exit(0); } close(filedes[0]); close(filedes[1]); #if defined(ARGUSDEBUG) ArgusDebug (2, "ArgusFilterCompile () returning %d\n", retn); #endif return (retn); } /* * Backpatch the blocks in 'list' to 'target'. The 'sense' field indicates * which of the jt and jf fields has been resolved and which is a pointer * back to another unresolved block (or nil). At least one of the fields * in each block is already resolved. */ static void backpatch(list, target) struct ablock *list, *target; { struct ablock *next; while (list) { if (!list->sense) { next = JT(list); JT(list) = target; } else { next = JF(list); JF(list) = target; } list = next; } } /* * Merge the lists in b0 and b1, using the 'sense' field to indicate * which of jt and jf is the link. */ static void merge(b0, b1) struct ablock *b0, *b1; { register struct ablock **p = &b0; /* Find end of list. */ while (*p) p = !((*p)->sense) ? &JT(*p) : &JF(*p); /* Concatenate the lists. */ *p = b1; } void Argusfinish_parse(p) struct ablock *p; { backpatch(p, Argusgen_retblk(snaplen)); p->sense = !p->sense; backpatch(p, Argusgen_retblk(0)); root = p->head; } void Argusgen_and(b0, b1) struct ablock *b0, *b1; { if (b0 != b1) { backpatch(b0, b1->head); b0->sense = !b0->sense; b1->sense = !b1->sense; merge(b1, b0); b1->sense = !b1->sense; b1->head = b0->head; } } void Argusgen_or(b0, b1) struct ablock *b0, *b1; { if (b0 != b1) { b0->sense = !b0->sense; backpatch(b0, b1->head); b0->sense = !b0->sense; merge(b1, b0); b1->head = b0->head; } } void Argusgen_not(b) struct ablock *b; { b->sense = !b->sense; } static struct ablock * Argusgen_cmp(offset, size, v) u_int offset, size; u_int v; { struct slist *s; struct ablock *b; s = new_stmt(BPF_LD|BPF_ABS|size); s->s.k = offset; b = new_block(JMP(BPF_JEQ)); b->stmts = s; b->s.k = v; return b; } static struct ablock * Argusgen_mcmp(offset, size, v, mask) u_int offset, size; u_int v; u_int mask; { struct ablock *b = Argusgen_cmp(offset, size, (v & mask)); struct slist *s; if (mask != 0xffffffff) { s = new_stmt(BPF_ALU|BPF_AND|BPF_K); s->s.k = mask; b->stmts->next = s; } return b; } static struct ablock * Argusgen_bcmp(offset, size, v) u_int offset, size; u_char *v; { struct ablock *b, *tmp; b = NULL; while (size >= 4) { u_char *p = &v[size - 4]; u_int w = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; tmp = Argusgen_cmp(offset + size - 4, BPF_W, w); if (b != NULL) Argusgen_and(b, tmp); b = tmp; size -= 4; } while (size >= 2) { u_char *p = &v[size - 2]; u_int w = (p[0] << 8) | p[1]; tmp = Argusgen_cmp(offset + size - 2, BPF_H, w); if (b != NULL) Argusgen_and(b, tmp); b = tmp; size -= 2; } if (size > 0) { tmp = Argusgen_cmp(offset, BPF_B, (u_int)v[0]); if (b != NULL) Argusgen_and(b, tmp); b = tmp; } return b; } static struct ablock * Argusgen_espstatustype(unsigned int proto) { struct ablock *b0 = NULL, *b1 = NULL; b1 = Argusgen_prototype(IPPROTO_ESP); switch (proto) { case ARGUS_SRC_PKTS_RETRANS: b0 = Argusgen_cmp(116, BPF_W, 0); Argusgen_not(b0); break; case ARGUS_DST_PKTS_RETRANS: b0 = Argusgen_cmp(128, BPF_W, 0); Argusgen_not(b0); break; } if (b0) Argusgen_and(b0, b1); return (b1); } static struct ablock * Argusgen_tcpstatustype(unsigned int proto) { struct ablock *b0, *b1; unsigned int value = proto; b0 = Argusgen_prototype(IPPROTO_TCP); switch (proto) { case ARGUS_SRC_CONGESTED: case ARGUS_DST_CONGESTED: case ARGUS_SRC_RESET: case ARGUS_DST_RESET: case ARGUS_SRC_WINDOW_SHUT: case ARGUS_DST_WINDOW_SHUT: case ARGUS_NORMAL_CLOSE: case ARGUS_SAW_SYN: case ARGUS_SAW_SYN_SENT: case ARGUS_CON_ESTABLISHED: case ARGUS_CLOSE_WAITING: case ARGUS_SRC_PKTS_RETRANS: case ARGUS_DST_PKTS_RETRANS: default: b1 = Argusgen_mcmp(108, BPF_W, value, value); break; } Argusgen_and(b0, b1); return (b1); } static struct ablock * Argusgen_causetype(unsigned int cause) { struct ablock *b0 = NULL; switch (cause) { case ARGUS_START: case ARGUS_STATUS: case ARGUS_STOP: case ARGUS_TIMEOUT: b0 = Argusgen_mcmp(1, BPF_B, (u_int) cause, cause); break; } return (b0); } static struct ablock * Argusgen_recordtype(unsigned int proto) { struct ablock *b0 = NULL; switch (proto) { case ARGUS_MAR: case ARGUS_FAR: case ARGUS_DATASUP: b0 = Argusgen_mcmp(0, BPF_B, (u_int) proto, proto); break; } return (b0); } static struct ablock * Argusgen_Farstatustype(unsigned int proto) { struct ablock *b0 = NULL, *b1 = NULL; switch (proto) { case ARGUS_MULTIADDR: case ARGUS_ICMPUNREACH_MAPPED: case ARGUS_ICMPREDIREC_MAPPED: case ARGUS_ICMPTIMXCED_MAPPED: b0 = Argusgen_recordtype(ARGUS_MAR); Argusgen_not(b0); b1 = Argusgen_mcmp(18, BPF_H, (u_int) proto, proto); Argusgen_and(b0, b1); break; case ARGUS_VLAN: case ARGUS_MPLS: case ARGUS_ANON: case ARGUS_MERGED: case ARGUS_CONNECTED: b0 = Argusgen_recordtype(ARGUS_MAR); Argusgen_not(b0); b1 = Argusgen_mcmp(4, BPF_W, (u_int) proto, proto); Argusgen_and(b0, b1); break; default: b0 = Argusgen_recordtype(ARGUS_MAR); Argusgen_not(b0); b1 = Argusgen_cmp(6, BPF_H, (u_int) proto); Argusgen_and(b0, b1); break; } return (b1); } /* static struct ablock * Argusgen_FarAttrtype(unsigned int proto) { struct ablock *b0 = NULL, *b1 = NULL; switch (proto) { case ARGUS_FRAGMENTS: b0 = Argusgen_mcmp(56, BPF_H, (u_int) proto, proto); b1 = Argusgen_mcmp(58, BPF_H, (u_int) proto, proto); Argusgen_or(b0, b1); b0 = Argusgen_recordtype(ARGUS_MAR); Argusgen_not(b0); Argusgen_and(b0, b1); break; } return (b1); } */ static struct ablock * Argusgen_prototype(unsigned int proto) { struct ablock *b0, *b1; switch (proto) { case IPPROTO_RTP: b0 = Argusgen_cmp(48, BPF_B, (u_int) IPPROTO_UDP); b1 = Argusgen_cmp(49, BPF_B, (u_int) ARGUS_RTP_FLOWTAG); Argusgen_and(b0, b1); break; case IPPROTO_RTCP: b0 = Argusgen_cmp(48, BPF_B, (u_int) IPPROTO_UDP); b1 = Argusgen_cmp(49, BPF_B, (u_int) ARGUS_RTCP_FLOWTAG); Argusgen_and(b0, b1); break; default: /* all the flow protocols */ b1 = Argusgen_cmp(48, BPF_B, (u_int) proto); break; } return b1; } static struct ablock * Argusgen_hostop(unsigned int addr, unsigned int mask, int dir, unsigned int proto, unsigned int src_off, unsigned int dst_off) { struct ablock *b0, *b1; u_int offset; switch (dir) { case Q_SRC: offset = src_off; break; case Q_DST: offset = dst_off; break; case Q_AND: b0 = Argusgen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); b1 = Argusgen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); Argusgen_and(b0, b1); return b1; case Q_OR: case Q_DEFAULT: b0 = Argusgen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); b1 = Argusgen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); Argusgen_or(b0, b1); return b1; default: abort(); } b0 = Argusgen_Farstatustype(proto); b1 = Argusgen_mcmp(offset, BPF_W, (u_int)addr, mask); Argusgen_and(b0, b1); return b1; } static struct ablock * Argusgen_ehostop(eaddr, dir) u_char *eaddr; int dir; { struct ablock *b0, *b1; switch (dir) { case Q_SRC: return Argusgen_bcmp (92, 6, eaddr); case Q_DST: return Argusgen_bcmp (98, 6, eaddr); case Q_AND: b0 = Argusgen_ehostop(eaddr, Q_SRC); b1 = Argusgen_ehostop(eaddr, Q_DST); Argusgen_and(b0, b1); return b1; case Q_DEFAULT: case Q_OR: b0 = Argusgen_ehostop(eaddr, Q_SRC); b1 = Argusgen_ehostop(eaddr, Q_DST); Argusgen_or(b0, b1); return b1; } abort(); /* NOTREACHED */ } static struct ablock * Argusgen_host(addr, mask, proto, dir) u_int addr; u_int mask; int proto; int dir; { struct ablock *b0, *b1 = NULL; switch (proto) { case Q_DEFAULT: b0 = Argusgen_hostop(addr, mask, dir, ETHERTYPE_ARP, 40, 44); b1 = Argusgen_hostop(addr, mask, dir, ETHERTYPE_IP, 40, 44); Argusgen_or(b0, b1); break; case Q_IP: b1 = Argusgen_hostop(addr, mask, dir, ETHERTYPE_IP, 40, 44); break; case Q_ARP: b1 = Argusgen_hostop(addr, mask, dir, ETHERTYPE_ARP, 40, 44); break; case Q_RARP: b1 = Argusgen_hostop(addr, mask, dir, ETHERTYPE_REVARP, 40, 44); break; case Q_TCP: ArgusLog(LOG_ERR, "'tcp' modifier applied to host"); case Q_UDP: ArgusLog(LOG_ERR, "'udp' modifier applied to host"); case Q_RTP: ArgusLog(LOG_ERR, "'rtp' modifier applied to host"); case Q_RTCP: ArgusLog(LOG_ERR, "'rtcp' modifier applied to host"); case Q_ICMP: b1 = Argusgen_hostop(addr, mask, dir, ETHERTYPE_IP, 112, 116); break; default: abort(); } return (b1); } static struct ablock * Argusgen_srcid(addr, mask) u_int addr; u_int mask; { struct ablock *b1 = NULL; b1 = Argusgen_mcmp(8, BPF_W, (u_int)addr, mask); return (b1); } static struct ablock * Argusgen_gateway(eaddr, alist, proto, dir) u_char *eaddr; u_int **alist; int proto; int dir; { struct ablock *b0, *b1 = NULL, *tmp; if (dir != 0) ArgusLog(LOG_ERR, "direction applied to 'gateway'"); switch (proto) { case Q_DEFAULT: case Q_IP: case Q_ARP: case Q_RARP: b0 = Argusgen_ehostop(eaddr, Q_OR); b1 = Argusgen_host(**alist++, 0xffffffffL, proto, Q_OR); while (*alist) { tmp = Argusgen_host(**alist++, 0xffffffffL, proto, Q_OR); Argusgen_or(b1, tmp); b1 = tmp; } Argusgen_not(b1); Argusgen_and(b0, b1); break; default: ArgusLog(LOG_ERR, "illegal modifier of 'gateway'"); } return b1; } struct ablock * Argusgen_proto_abbrev(proto) int proto; { struct ablock *b0, *b1; switch (proto) { case Q_TCP: b1 = Argusgen_prototype(IPPROTO_TCP); break; case Q_ESP: b1 = Argusgen_prototype(IPPROTO_ESP); break; case Q_RTP: b1 = Argusgen_prototype(IPPROTO_RTP); break; case Q_RTCP: b1 = Argusgen_prototype(IPPROTO_RTCP); break; case Q_UDP: b0 = Argusgen_Farstatustype(ETHERTYPE_IP); b1 = Argusgen_prototype(IPPROTO_UDP); Argusgen_and(b0, b1); break; case Q_ICMP: b1 = Argusgen_prototype(IPPROTO_ICMP); break; case Q_IGMP: b1 = Argusgen_prototype(IPPROTO_IGMP); break; #ifndef IPPROTO_IGRP #define IPPROTO_IGRP 9 #endif case Q_IGRP: b1 = Argusgen_prototype(IPPROTO_IGRP); break; case Q_MPLS: b1 = Argusgen_Farstatustype(ARGUS_MPLS); break; case Q_VLAN: b1 = Argusgen_Farstatustype(ARGUS_VLAN); break; case Q_RARP: b1 = Argusgen_Farstatustype(ETHERTYPE_REVARP); break; case Q_ARP: b1 = Argusgen_Farstatustype(ETHERTYPE_ARP); break; case Q_IP: b1 = Argusgen_Farstatustype(ETHERTYPE_IP); break; case Q_MAN: b1 = Argusgen_recordtype(ARGUS_MAR); break; /* case Q_MULTIPATH: b1 = Argusgen_Farstatustype(ARGUS_MULTIADDR); break; case Q_FRAG: b1 = Argusgen_FarAttrtype(ARGUS_FRAGMENTS); break; */ case Q_CONNECTED: case Q_ESTABLISHED: b1 = Argusgen_Farstatustype(ARGUS_CONNECTED); break; case Q_MERGED: b1 = Argusgen_Farstatustype(ARGUS_MERGED); break; case Q_ANON: b1 = Argusgen_Farstatustype(ARGUS_ANON); break; case Q_ECHO: b0 = Argusgen_cmp(50, BPF_B, (u_int) 0x08); b1 = Argusgen_cmp(50, BPF_B, (u_int) 0x00); Argusgen_or(b0, b1); b0 = Argusgen_prototype(IPPROTO_ICMP); Argusgen_and(b0, b1); break; case Q_UNREACH: b1 = Argusgen_prototype(IPPROTO_ICMP); b0 = Argusgen_cmp(50, BPF_B, (u_int) 0x03); Argusgen_and(b0, b1); b0 = Argusgen_Farstatustype(ARGUS_ICMPUNREACH_MAPPED); Argusgen_or(b0, b1); break; case Q_REDIRECT: b1 = Argusgen_prototype(IPPROTO_ICMP); b0 = Argusgen_cmp(50, BPF_B, (u_int) 0x05); Argusgen_and(b0, b1); b0 = Argusgen_Farstatustype(ARGUS_ICMPREDIREC_MAPPED); Argusgen_or(b0, b1); break; case Q_TIMEXED: b1 = Argusgen_prototype(IPPROTO_ICMP); b0 = Argusgen_cmp(50, BPF_B, (u_int) 0x0B); Argusgen_and(b0, b1); b0 = Argusgen_Farstatustype(ARGUS_ICMPTIMXCED_MAPPED); Argusgen_or(b0, b1); break; case Q_TIMEDOUT: b1 = Argusgen_causetype(ARGUS_TIMEOUT); break; case Q_RETRANS: b0 = Argusgen_espstatustype(ARGUS_SRC_PKTS_RETRANS); b1 = Argusgen_tcpstatustype(ARGUS_SRC_PKTS_RETRANS); Argusgen_or(b0, b1); b0 = Argusgen_espstatustype(ARGUS_DST_PKTS_RETRANS); Argusgen_or(b0, b1); b0 = Argusgen_tcpstatustype(ARGUS_DST_PKTS_RETRANS); Argusgen_or(b0, b1); break; case Q_SRCRETRANS: b0 = Argusgen_espstatustype(ARGUS_SRC_PKTS_RETRANS); b1 = Argusgen_tcpstatustype(ARGUS_SRC_PKTS_RETRANS); Argusgen_or(b0, b1); break; case Q_DSTRETRANS: b0 = Argusgen_espstatustype(ARGUS_DST_PKTS_RETRANS); b1 = Argusgen_tcpstatustype(ARGUS_DST_PKTS_RETRANS); Argusgen_or(b0, b1); break; case Q_SYN: b1 = Argusgen_tcpstatustype(ARGUS_SAW_SYN); break; case Q_SYNACK: b1 = Argusgen_tcpstatustype(ARGUS_SAW_SYN_SENT); break; case Q_DATA: b1 = Argusgen_tcpstatustype(ARGUS_CON_ESTABLISHED); break; case Q_FIN: b1 = Argusgen_tcpstatustype(ARGUS_FIN); break; case Q_FINACK: b1 = Argusgen_tcpstatustype(ARGUS_FIN_ACK); break; case Q_WAIT: b1 = Argusgen_tcpstatustype(ARGUS_CLOSE_WAITING); break; case Q_NORMAL: b1 = Argusgen_tcpstatustype(ARGUS_NORMAL_CLOSE); break; case Q_LINK: ArgusLog(LOG_ERR, "link layer applied in wrong context"); default: abort(); } return b1; } static struct ablock * Argusgen_ttlatom(int off, u_int v) { return Argusgen_cmp(60 + off, BPF_B, (u_int)v); } static struct ablock * Argusgen_tosatom(int off, u_int v) { return Argusgen_cmp(62 + off, BPF_B, v); } static struct ablock * Argusgen_vidatom(int off, u_int v) { return Argusgen_cmp(316 + off, BPF_H, v); } static struct ablock * Argusgen_midatom(int off, u_int v) { return Argusgen_cmp(324 + off, BPF_W, v); } static struct ablock * Argusgen_portatom(off, v) int off; long v; { return Argusgen_cmp(50 + off, BPF_H, (u_int)v); } struct ablock * Argusgen_portop(port, proto, dir) int port, proto, dir; { struct ablock *b0, *b1, *tmp; /* ip proto 'proto' */ b0 = Argusgen_prototype(proto); switch (dir) { case Q_SRC: b1 = Argusgen_portatom(0, (long)port); break; case Q_DST: b1 = Argusgen_portatom(2, (long)port); break; case Q_OR: case Q_DEFAULT: tmp = Argusgen_portatom(0, (long)port); b1 = Argusgen_portatom(2, (long)port); Argusgen_or(tmp, b1); break; case Q_AND: tmp = Argusgen_portatom(0, (long)port); b1 = Argusgen_portatom(2, (long)port); Argusgen_and(tmp, b1); break; default: abort(); } Argusgen_and(b0, b1); return b1; } static struct ablock * Argusgen_port(port, ip_proto, dir) int port; u_int ip_proto; int dir; { struct ablock *b1, *tmp; switch (ip_proto) { case IPPROTO_TCP: b1 = Argusgen_portop(port, IPPROTO_TCP, dir); break; case IPPROTO_UDP: b1 = Argusgen_portop(port, IPPROTO_UDP, dir); break; case IPPROTO_RTP: tmp = Argusgen_portop(port, IPPROTO_UDP, dir); b1 = Argusgen_portop(port, IPPROTO_RTP, dir); Argusgen_and(tmp, b1); break; case IPPROTO_RTCP: tmp = Argusgen_portop(port, IPPROTO_UDP, dir); b1 = Argusgen_portop(port, IPPROTO_RTCP, dir); Argusgen_and(tmp, b1); break; case PROTO_UNDEF: tmp = Argusgen_portop(port, IPPROTO_TCP, dir); b1 = Argusgen_portop(port, IPPROTO_UDP, dir); Argusgen_or(tmp, b1); break; default: abort(); } return b1; } static int lookup_proto(name, proto) char *name; int proto; { int v = 0; switch (proto) { case Q_DEFAULT: case Q_IP: v = argus_nametoproto(name); if (v == PROTO_UNDEF) ArgusLog(LOG_ERR, "unknown proto '%s'", name); break; case Q_LINK: /* XXX should look up h/w protocol type based on linktype */ v = argus_nametoeproto(name); if (v == PROTO_UNDEF) ArgusLog(LOG_ERR, "unknown ether proto '%s'", name); break; case Q_MAN: ArgusLog (LOG_ERR, "man proto called '%s'", name); break; default: v = PROTO_UNDEF; break; } return v; } static struct ablock * Argusgen_proto(v, proto, dir) int v; int proto; int dir; { struct ablock *b0, *b1; if (dir != Q_DEFAULT) ArgusLog(LOG_ERR, "direction applied to 'proto'"); switch (proto) { case Q_DEFAULT: case Q_IP: b0 = Argusgen_recordtype(ARGUS_MAR); Argusgen_not(b0); b1 = Argusgen_Farstatustype(ETHERTYPE_IP); Argusgen_and(b0, b1); b0 = Argusgen_prototype(v); Argusgen_and(b0, b1); return b1; case Q_ARP: b0 = Argusgen_recordtype(ARGUS_MAR); Argusgen_not(b0); b1 = Argusgen_Farstatustype(ETHERTYPE_ARP); Argusgen_and(b0, b1); return b1; case Q_RARP: ArgusLog(LOG_ERR, "rarp does not encapsulate another protocol"); /* NOTREACHED */ case Q_MAN: /* case Q_MULTIPATH: */ return Argusgen_recordtype(ARGUS_MAR); case Q_LINK: return Argusgen_Farstatustype(v); case Q_UDP: ArgusLog(LOG_ERR, "'udp proto' is bogus"); /* NOTREACHED */ case Q_RTP: ArgusLog(LOG_ERR, "'rtp proto' is bogus"); /* NOTREACHED */ case Q_RTCP: ArgusLog(LOG_ERR, "'rtcp proto' is bogus"); /* NOTREACHED */ case Q_TCP: ArgusLog(LOG_ERR, "'tcp proto' is bogus"); /* NOTREACHED */ case Q_ICMP: ArgusLog(LOG_ERR, "'icmp proto' is bogus"); /* NOTREACHED */ case Q_IGMP: ArgusLog(LOG_ERR, "'igmp proto' is bogus"); /* NOTREACHED */ default: abort(); /* NOTREACHED */ } /* NOTREACHED */ } static struct ablock * Argusgen_ttl(int v, int dir) { struct ablock *b0, *b1 = NULL, *tmp; b0 = Argusgen_proto(v, Q_IP, Q_DEFAULT); switch (dir) { case Q_SRC: b1 = Argusgen_ttlatom(0, (u_int)v); break; case Q_DST: b1 = Argusgen_ttlatom(1, (u_int)v); break; case Q_OR: case Q_DEFAULT: tmp = Argusgen_ttlatom(0, (u_int)v); b1 = Argusgen_ttlatom(1, (u_int)v); Argusgen_or(tmp, b1); break; case Q_AND: tmp = Argusgen_ttlatom(0, (u_int)v); b1 = Argusgen_ttlatom(1, (u_int)v); Argusgen_and(tmp, b1); break; default: abort(); } Argusgen_and(b0, b1); return b1; } static struct ablock * Argusgen_tos(int v, int dir) { struct ablock *b0, *b1 = NULL, *tmp; b0 = Argusgen_proto(v, Q_IP, Q_DEFAULT); switch (dir) { case Q_SRC: b1 = Argusgen_tosatom(0, (u_int)v); break; case Q_DST: b1 = Argusgen_tosatom(1, (u_int)v); break; case Q_OR: case Q_DEFAULT: tmp = Argusgen_tosatom(0, (u_int)v); b1 = Argusgen_tosatom(1, (u_int)v); Argusgen_or(tmp, b1); break; case Q_AND: tmp = Argusgen_tosatom(0, (u_int)v); b1 = Argusgen_tosatom(1, (u_int)v); Argusgen_and(tmp, b1); break; default: abort(); } Argusgen_and(b0, b1); return b1; } static struct ablock * Argusgen_vid(int v, int dir) { struct ablock *b0, *b1 = NULL; switch (dir) { case Q_SRC: b1 = Argusgen_vidatom(0, (u_int)v); break; case Q_DST: b1 = Argusgen_vidatom(2, (u_int)v); break; case Q_OR: case Q_DEFAULT: b0 = Argusgen_vidatom(0, (u_int)v); b1 = Argusgen_vidatom(1, (u_int)v); Argusgen_or(b0, b1); break; case Q_AND: b0 = Argusgen_vidatom(0, (u_int)v); b1 = Argusgen_vidatom(1, (u_int)v); Argusgen_and(b0, b1); break; default: abort(); } return b1; } static struct ablock * Argusgen_mid(int v, int dir) { struct ablock *b0, *b1 = NULL; switch (dir) { case Q_SRC: b1 = Argusgen_midatom(0, (u_int)v); break; case Q_DST: b1 = Argusgen_midatom(4, (u_int)v); break; case Q_OR: case Q_DEFAULT: b0 = Argusgen_midatom(0, (u_int)v); b1 = Argusgen_midatom(4, (u_int)v); Argusgen_or(b0, b1); break; case Q_AND: b0 = Argusgen_midatom(0, (u_int)v); b1 = Argusgen_midatom(4, (u_int)v); Argusgen_and(b0, b1); break; default: abort(); } return b1; } /* * Left justify 'addr' and return its resulting network mask. */ static u_int net_mask(addr) u_int *addr; { register u_int m = 0xffffffff; if (*addr) while ((*addr & 0xff000000) == 0) *addr <<= 8, m <<= 8; return m; } struct ablock * Argusgen_tcode(name, q) int name; struct qual q; { int proto = q.proto; int dir = q.dir; struct ablock *b0 = NULL, *b1 = NULL; switch (name) { case Q_RETRANS: { switch (dir) { case Q_SRC: b1 = Argusgen_proto_abbrev(Q_SRCRETRANS); break; case Q_DST: b1 = Argusgen_proto_abbrev(Q_DSTRETRANS); break; case Q_AND: b0 = Argusgen_proto_abbrev(Q_SRCRETRANS); b1 = Argusgen_proto_abbrev(Q_DSTRETRANS); Argusgen_and(b0, b1); break; default: case Q_OR: b1 = Argusgen_proto_abbrev(Q_RETRANS); break; } break; } case Q_FRAG: { proto = ARGUS_FRAGMENTS; switch (dir) { case Q_SRC: b1 = Argusgen_mcmp(56, BPF_H, (u_int) proto, proto); break; case Q_DST: b1 = Argusgen_mcmp(58, BPF_H, (u_int) proto, proto); break; case Q_AND: b0 = Argusgen_mcmp(56, BPF_H, (u_int) proto, proto); b1 = Argusgen_mcmp(58, BPF_H, (u_int) proto, proto); Argusgen_or(b0, b1); break; default: case Q_OR: b0 = Argusgen_mcmp(56, BPF_H, (u_int) proto, proto); b1 = Argusgen_mcmp(58, BPF_H, (u_int) proto, proto); Argusgen_or(b0, b1); break; } b0 = Argusgen_tcode(Q_FRAG_ONLY, q); Argusgen_or(b0, b1); break; } case Q_FRAG_ONLY: { b1 = Argusgen_cmp(49, BPF_B, (u_int) ARGUS_FRAG_FLOWTAG); break; } case Q_WINSHUT: { switch (dir) { case Q_SRC: b1 = Argusgen_tcpstatustype(ARGUS_SRC_WINDOW_SHUT); break; case Q_DST: b1 = Argusgen_tcpstatustype(ARGUS_DST_WINDOW_SHUT); break; case Q_AND: b0 = Argusgen_tcpstatustype(ARGUS_SRC_WINDOW_SHUT); b1 = Argusgen_tcpstatustype(ARGUS_DST_WINDOW_SHUT); Argusgen_and(b0, b1); break; default: case Q_OR: b0 = Argusgen_tcpstatustype(ARGUS_SRC_WINDOW_SHUT); b1 = Argusgen_tcpstatustype(ARGUS_DST_WINDOW_SHUT); Argusgen_or(b0, b1); break; } break; } case Q_ECN: { switch (dir) { case Q_SRC: b1 = Argusgen_tcpstatustype(ARGUS_SRC_CONGESTED); break; case Q_DST: b1 = Argusgen_tcpstatustype(ARGUS_DST_CONGESTED); break; case Q_AND: b0 = Argusgen_tcpstatustype(ARGUS_SRC_CONGESTED); b1 = Argusgen_tcpstatustype(ARGUS_DST_CONGESTED); Argusgen_and(b0, b1); break; default: case Q_OR: b0 = Argusgen_tcpstatustype(ARGUS_SRC_CONGESTED); b1 = Argusgen_tcpstatustype(ARGUS_DST_CONGESTED); Argusgen_or(b0, b1); break; } break; } case Q_RESET: { switch (dir) { case Q_SRC: b1 = Argusgen_tcpstatustype(ARGUS_SRC_RESET); break; case Q_DST: b1 = Argusgen_tcpstatustype(ARGUS_DST_RESET); break; case Q_AND: b0 = Argusgen_tcpstatustype(ARGUS_SRC_RESET); b1 = Argusgen_tcpstatustype(ARGUS_DST_RESET); Argusgen_and(b0, b1); break; default: case Q_OR: b0 = Argusgen_tcpstatustype(ARGUS_SRC_RESET); b1 = Argusgen_tcpstatustype(ARGUS_DST_RESET); Argusgen_or(b0, b1); break; } break; } } return b1; } struct ablock * Argusgen_scode(name, q) char *name; struct qual q; { int proto = q.proto; int dir = q.dir; u_char *eaddr; u_int mask, addr; u_int **alist; struct ablock *b, *tmp; int port, real_proto = -1; switch (q.addr) { case Q_NET: addr = argus_nametonetaddr(name); if (addr == 0) ArgusLog(LOG_ERR, "unknown network '%s'", name); mask = net_mask(&addr); return Argusgen_host(addr, mask, proto, dir); case Q_DEFAULT: case Q_HOST: if (proto == Q_LINK) { eaddr = argus_ether_hostton(name); if (eaddr == NULL) ArgusLog(LOG_ERR, "unknown ether host '%s'", name); return Argusgen_ehostop(eaddr, dir); } else if (proto == Q_DECNET) { unsigned short dn_addr = __argus_nametodnaddr(name); /* * I don't think DECNET hosts can be multihomed, so * there is no need to build up a list of addresses */ return (Argusgen_host(dn_addr, 0, proto, dir)); } else { alist = argus_nametoaddr(name); if (alist == NULL || *alist == NULL) ArgusLog(LOG_ERR, "unknown host '%s'", name); b = Argusgen_host(**alist++, 0xffffffffL, proto, dir); while (*alist) { tmp = Argusgen_host(**alist++, 0xffffffffL, proto, dir); Argusgen_or(b, tmp); b = tmp; } return b; } case Q_SRCID: { alist = argus_nametoaddr(name); if (alist == NULL || *alist == NULL) ArgusLog(LOG_ERR, "unknown srcid '%s'", name); b = Argusgen_srcid(**alist++, 0xffffffffL); while (*alist) { tmp = Argusgen_srcid(**alist++, 0xffffffffL); Argusgen_or(b, tmp); b = tmp; } return b; } case Q_PORT: if ((proto != Q_DEFAULT) && (proto != Q_UDP) && (proto != Q_TCP) && (proto != Q_RTP) && (proto != Q_RTCP)) ArgusLog(LOG_ERR, "illegal qualifier of 'port'"); if (argus_nametoport(name, &port, &real_proto) == 0) ArgusLog(LOG_ERR, "unknown port '%s'", name); if ((proto == Q_UDP) || (proto == Q_RTP) || (proto == Q_RTCP)) { if (real_proto == IPPROTO_TCP) ArgusLog(LOG_ERR, "port '%s' is tcp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_UDP; } if (proto == Q_TCP) { if (real_proto == IPPROTO_UDP) ArgusLog(LOG_ERR, "port '%s' is udp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_TCP; } return Argusgen_port(port, real_proto, dir); case Q_GATEWAY: eaddr = argus_ether_hostton(name); if (eaddr == NULL) ArgusLog(LOG_ERR, "unknown ether host: %s", name); alist = argus_nametoaddr(name); if (alist == NULL || *alist == NULL) ArgusLog(LOG_ERR, "unknown host '%s'", name); return Argusgen_gateway(eaddr, alist, proto, dir); case Q_PROTO: real_proto = lookup_proto(name, proto); if (real_proto >= 0) return Argusgen_proto(real_proto, proto, dir); else ArgusLog(LOG_ERR, "unknown protocol: %s", name); case Q_UNDEF: syntax(); /* NOTREACHED */ } abort(); /* NOTREACHED */ } struct ablock * Argusgen_mcode(s1, s2, masklen, q) char *s1, *s2; int masklen; struct qual q; { struct ablock *b0 = NULL; int nlen, mlen; u_int n, m; nlen = __argus_atoin(s1, &n); /* Promote short ipaddr */ n <<= 32 - nlen; if (s2 != NULL) { mlen = __argus_atoin(s2, &m); /* Promote short ipaddr */ m <<= 32 - mlen; } else { /* Convert mask len to mask */ if (masklen > 32) ArgusLog(LOG_ERR, "mask length must be <= 32"); m = 0xffffffff << (32 - masklen); } switch (q.addr) { case Q_NET: b0 = Argusgen_host(n, m, q.proto, q.dir); break; default: ArgusLog(LOG_ERR, "Mask syntax for networks only"); /* NOTREACHED */ } return b0; } struct ablock * Argusgen_ncode(char *s, u_int v, struct qual q) { u_int mask; int proto = q.proto; int dir = q.dir; int vlen; if (s == NULL) vlen = 32; else vlen = __argus_atoin(s, &v); switch (q.addr) { case Q_DEFAULT: case Q_HOST: case Q_NET: if (proto == Q_LINK) { ArgusLog(LOG_ERR, "illegal link layer address"); } else { /* mask = net_mask(&v); */ mask = 0xffffffff; if ((s == NULL) && (q.addr == Q_NET)) { /* Promote short net number */ while (v && (v & 0xff000000) == 0) { v <<= 8; mask <<= 8; } } else { /* Promote short ipaddr */ v <<= 32 - vlen; mask <<= 32 - vlen; } return Argusgen_host(v, mask, proto, dir); } case Q_SRCID: mask = 0xffffffff; return Argusgen_srcid(v, mask); case Q_PORT: if (proto == Q_UDP) proto = IPPROTO_UDP; else if (proto == Q_RTP) proto = IPPROTO_RTP; else if (proto == Q_RTCP) proto = IPPROTO_RTCP; else if (proto == Q_TCP) proto = IPPROTO_TCP; else if (proto == Q_DEFAULT) proto = PROTO_UNDEF; else ArgusLog(LOG_ERR, "illegal qualifier of 'port'"); return Argusgen_port((int)v, proto, dir); case Q_GATEWAY: ArgusLog(LOG_ERR, "'gateway' requires a name"); /* NOTREACHED */ case Q_PROTO: return Argusgen_proto((int)v, proto, dir); case Q_TTL: return Argusgen_ttl((int)v, dir); case Q_TOS: return Argusgen_tos((int)v, dir); case Q_VLANID: return Argusgen_vid((int)v, dir); case Q_MPLSID: return Argusgen_mid((int)v, dir); case Q_UNDEF: syntax(); /* NOTREACHED */ default: abort(); /* NOTREACHED */ } /* NOTREACHED */ } struct ablock * Argusgen_ecode(eaddr, q) u_char *eaddr; struct qual q; { struct ablock *b0 = NULL; if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) b0 = Argusgen_ehostop(eaddr, (int)q.dir); else ArgusLog(LOG_ERR, "ethernet address used in non-ether expression"); return b0; } void Argussappend(s0, s1) struct slist *s0, *s1; { /* * This is definitely not the best way to do this, but the * lists will rarely get long. */ while (s0->next) s0 = s0->next; s0->next = s1; } static struct slist * xfer_to_x(a) struct arth *a; { struct slist *s; s = new_stmt(BPF_LDX|BPF_MEM); s->s.k = a->regno; return s; } static struct slist * xfer_to_a(a) struct arth *a; { struct slist *s; s = new_stmt(BPF_LD|BPF_MEM); s->s.k = a->regno; return s; } struct arth * Argusgen_load(proto, index, size) int proto; struct arth *index; int size; { struct slist *s, *tmp; struct ablock *b; int regno = alloc_reg(); free_reg(index->regno); switch (size) { default: ArgusLog(LOG_ERR, "data size must be 1, 2, or 4"); case 1: size = BPF_B; break; case 2: size = BPF_H; break; case 4: size = BPF_W; break; } switch (proto) { default: ArgusLog(LOG_ERR, "unsupported index operation"); case Q_LINK: s = xfer_to_x(index); tmp = new_stmt(BPF_LD|BPF_IND|size); Argussappend(s, tmp); Argussappend(index->s, s); break; case Q_IP: case Q_ARP: case Q_RARP: s = xfer_to_x(index); tmp = new_stmt(BPF_LD|BPF_IND|size); tmp->s.k = off_nl; Argussappend(s, tmp); Argussappend(index->s, s); b = Argusgen_proto_abbrev(proto); if (index->b) Argusgen_and(index->b, b); index->b = b; break; case Q_TCP: case Q_RTP: case Q_RTCP: case Q_UDP: case Q_ICMP: case Q_IGMP: case Q_IGRP: s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); s->s.k = off_nl; Argussappend(s, xfer_to_a(index)); Argussappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); Argussappend(s, new_stmt(BPF_MISC|BPF_TAX)); Argussappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size)); tmp->s.k = off_nl; Argussappend(index->s, s); b = Argusgen_proto_abbrev(proto); if (index->b) Argusgen_and(index->b, b); index->b = b; break; } index->regno = regno; s = new_stmt(BPF_ST); s->s.k = regno; Argussappend(index->s, s); return index; } struct ablock * Argusgen_relation(code, a0, a1, reversed) int code; struct arth *a0, *a1; int reversed; { struct slist *s0, *s1, *s2; struct ablock *b, *tmp; s0 = xfer_to_x(a1); s1 = xfer_to_a(a0); s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X); b = new_block(JMP(code)); if (reversed) Argusgen_not(b); Argussappend(s1, s2); Argussappend(s0, s1); Argussappend(a1->s, s0); Argussappend(a0->s, a1->s); b->stmts = a0->s; free_reg(a0->regno); free_reg(a1->regno); /* 'and' together protocol checks */ if (a0->b) { if (a1->b) { Argusgen_and(a0->b, tmp = a1->b); } else tmp = a0->b; } else tmp = a1->b; if (tmp) Argusgen_and(tmp, b); return b; } struct arth * Argusgen_loadlen() { int regno = alloc_reg(); struct arth *a = (struct arth *)newchunk(sizeof(*a)); struct slist *s; s = new_stmt(BPF_LD|BPF_LEN); s->next = new_stmt(BPF_ST); s->next->s.k = regno; a->s = s; a->regno = regno; return a; } struct arth * Argusgen_loadi(val) int val; { struct arth *a; struct slist *s; int reg; a = (struct arth *)newchunk(sizeof(*a)); reg = alloc_reg(); s = new_stmt(BPF_LD|BPF_IMM); s->s.k = val; s->next = new_stmt(BPF_ST); s->next->s.k = reg; a->s = s; a->regno = reg; return a; } struct arth * Argusgen_neg(a) struct arth *a; { struct slist *s; s = xfer_to_a(a); Argussappend(a->s, s); s = new_stmt(BPF_ALU|BPF_NEG); s->s.k = 0; Argussappend(a->s, s); s = new_stmt(BPF_ST); s->s.k = a->regno; Argussappend(a->s, s); return a; } struct arth * Argusgen_arth(code, a0, a1) int code; struct arth *a0, *a1; { struct slist *s0, *s1, *s2; s0 = xfer_to_x(a1); s1 = xfer_to_a(a0); s2 = new_stmt(BPF_ALU|BPF_X|code); Argussappend(s1, s2); Argussappend(s0, s1); Argussappend(a1->s, s0); Argussappend(a0->s, a1->s); free_reg(a1->regno); s0 = new_stmt(BPF_ST); a0->regno = s0->s.k = alloc_reg(); Argussappend(a0->s, s0); return a0; } /* * Here we handle simple allocation of the scratch registers. * If too many registers are alloc'd, the allocator punts. */ static int regused[BPF_MEMWORDS]; static int curreg; /* * Return the next free register. */ static int alloc_reg() { int retn = -1; int n = BPF_MEMWORDS; while (--n >= 0) { if (regused[curreg]) curreg = (curreg + 1) % BPF_MEMWORDS; else { regused[curreg] = 1; retn = curreg; break; } } if (retn == -1) ArgusLog(LOG_ERR, "too many registers needed to evaluate expression"); return (retn); } /* * Return a register to the table so it can * be used later. */ static void free_reg(n) int n; { regused[n] = 0; } static struct ablock * Argusgen_len(jmp, n) int jmp, n; { struct slist *s; struct ablock *b; s = new_stmt(BPF_LD|BPF_LEN); s->next = new_stmt(BPF_ALU|BPF_SUB|BPF_K); s->next->s.k = n; b = new_block(JMP(jmp)); b->stmts = s; return b; } struct ablock * Argusgen_greater(n) int n; { fprintf (stderr, "Argusgen_greater(%d)\n", n); return Argusgen_len(BPF_JGE, n); } struct ablock * Argusgen_less(n) int n; { struct ablock *b; b = Argusgen_len(BPF_JGT, n); Argusgen_not(b); return b; } struct ablock * Argusgen_byteop(op, idx, val) int op, idx, val; { struct ablock *b; struct slist *s; switch (op) { default: abort(); case '=': return Argusgen_cmp((u_int)idx, BPF_B, (u_int)val); case '<': b = Argusgen_cmp((u_int)idx, BPF_B, (u_int)val); b->s.code = JMP(BPF_JGE); Argusgen_not(b); return b; case '>': b = Argusgen_cmp((u_int)idx, BPF_B, (u_int)val); b->s.code = JMP(BPF_JGT); return b; case '|': s = new_stmt(BPF_ALU|BPF_OR|BPF_K); break; case '&': s = new_stmt(BPF_ALU|BPF_AND|BPF_K); break; } s->s.k = val; b = new_block(JMP(BPF_JEQ)); b->stmts = s; Argusgen_not(b); return b; } struct ablock * Argusgen_broadcast(proto) int proto; { u_int classmask; u_int netaddr; struct ablock *b0, *b1; static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; extern u_int ArgusLocalNet; switch (proto) { case Q_LINK: return Argusgen_ehostop(ebroadcast, Q_OR); case Q_IP: case Q_DEFAULT: netaddr = ArgusLocalNet & ArgusNetMask; classmask = ipaddrtonetmask(ArgusLocalNet); b1 = Argusgen_host(netaddr, 0xffffffffL, proto, Q_OR); netaddr |= ~(~0 & ArgusNetMask); b0 = Argusgen_host(netaddr, 0xffffffffL, proto, Q_OR); Argusgen_or(b1, b0); if (classmask != ArgusNetMask) { netaddr = ArgusLocalNet & classmask; b1 = Argusgen_host(netaddr, 0xffffffffL, proto, Q_OR); Argusgen_or(b1, b0); } b1 = Argusgen_host( ~0, 0xffffffffL, proto, Q_OR); Argusgen_or(b1, b0); return b0; } ArgusLog(LOG_ERR, "only ether/ip broadcast filters supported"); return NULL; } struct ablock * Argusgen_multicast(proto) int proto; { register struct ablock *b0, *b1; register struct slist *s; switch (proto) { case Q_LINK: s = new_stmt(BPF_LD|BPF_B|BPF_ABS); s->s.k = 92; b0 = new_block(JMP(BPF_JSET)); b0->s.k = 1; b0->stmts = s; s = new_stmt(BPF_LD|BPF_B|BPF_ABS); s->s.k = 98; b1 = new_block(JMP(BPF_JSET)); b1->s.k = 1; b1->stmts = s; Argusgen_or(b0, b1); return b1; case Q_IP: case Q_DEFAULT: b1 = Argusgen_cmp(40, BPF_B, (u_int) 224); b1->s.code = JMP(BPF_JGE); b0 = Argusgen_cmp(44, BPF_B, (u_int) 224); b0->s.code = JMP(BPF_JGE); Argusgen_or(b0, b1); b0 = Argusgen_Farstatustype(ETHERTYPE_IP); Argusgen_and(b0, b1); return b1; } return NULL; } /* * generate command for inbound/outbound. It's here so we can * make it link-type specific. 'dir' = 0 implies "inbound", * = 1 implies "outbound". */ struct ablock * Argusgen_inbound(dir) int dir; { register struct ablock *b0; b0 = Argusgen_relation(BPF_JEQ, Argusgen_load(Q_LINK, Argusgen_loadi(0), 1), Argusgen_loadi(0), dir); return (b0); } argus-clients-2.0.6.fixes.1/common/grammar.y0000664000076600007660000002244707764412760014410 %{ /* * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * */ #include #if defined(HAVE_SOLARIS) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #include #endif #include #include #include #include #include #include extern void ArgusLog (int, char *, ...); #define YYDEBUG 2 #define QSET(q, p, d, a) (q).proto = (p),\ (q).dir = (d),\ (q).addr = (a) int argus_n_errors = 0; static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF }; static void yyerror(char *msg) { ++argus_n_errors; ArgusLog (LOG_ERR, msg); /* NOTREACHED */ } /* #ifndef YYBISON argus_parse() { return (yyparse()); } #endif */ %} %union { int i; u_long h; u_char *e; char *s; struct stmt *stmt; struct arth *a; struct { struct qual q; struct ablock *b; } blk; struct ablock *rblk; } %type expr id nid pid term rterm qid tid %type head thead %type pqual dqual aqual ndaqual %type arth narth %type byteop pname tname pnum relop irelop %type and or paren not null prog %type other %token DST SRC HOST GATEWAY TEST TTL TOS SRCID %token NET MASK PORT LESS GREATER PROTO BYTE %token ARP RARP IP TCP UDP ICMP IGMP MAN FRAG FRAG_ONLY %token MPLS VLAN ANON VLANID MPLSID MBR QRY %token RTP RTCP ESP DECNET LAT MOPRC MOPDL %token TK_BROADCAST TK_MULTICAST %token NUM INBOUND OUTBOUND %token LINK %token GEQ LEQ NEQ %token ID EID HID %token LSH RSH %token LEN %token OUTOFORDER RETRANS NORMAL WAIT MULTIPATH RESET TIMEDOUT WINSHUT %token SYN SYNACK DATA FIN FINACK ECHO UNREACH REDIRECT %token ECN TIMEXED ESTABLISHED CONNECTED CORRELATED %token RTR MBR LVG %type ID %type EID %type HID %type NUM %left OR AND %nonassoc '!' %left '|' %left '&' %left LSH RSH %left '+' '-' %left '*' '/' %nonassoc UMINUS %% prog: null expr { Argusfinish_parse($2.b); } | null ; null: /* null */ { $$.q = qerr; } ; expr: term | expr and term { Argusgen_and($1.b, $3.b); $$ = $3; } | expr and id { Argusgen_and($1.b, $3.b); $$ = $3; } | expr or term { Argusgen_or($1.b, $3.b); $$ = $3; } | expr or id { Argusgen_or($1.b, $3.b); $$ = $3; } ; and: AND { $$ = $0; } ; or: OR { $$ = $0; } ; id: nid | pnum { $$.b = Argusgen_ncode(NULL, (arg_uint32)$1, $$.q = $0.q); } | paren pid ')' { $$ = $2; } ; tid: tname { $$.b = Argusgen_tcode($1, $$.q = $0.q); } ; nid: ID { $$.b = Argusgen_scode($1, $$.q = $0.q); } | HID '/' NUM { $$.b = Argusgen_mcode($1, NULL, $3, $$.q = $0.q); } | HID MASK HID { $$.b = Argusgen_mcode($1, $3, 0, $$.q = $0.q); } | HID { /* Decide how to parse HID based on proto */ $$.q = $0.q; $$.b = Argusgen_ncode($1, 0, $$.q); } | EID { $$.b = Argusgen_ecode($1, $$.q = $0.q); } | not id { Argusgen_not($2.b); $$ = $2; } ; not: '!' { $$ = $0; } ; paren: '(' { $$ = $0; } ; pid: nid | qid and id { Argusgen_and($1.b, $3.b); $$ = $3; } | qid or id { Argusgen_or($1.b, $3.b); $$ = $3; } ; qid: pnum { $$.b = Argusgen_ncode(NULL, (arg_uint32)$1, $$.q = $0.q); } | pid ; term: rterm | not term { Argusgen_not($2.b); $$ = $2; } ; head: pqual dqual aqual { QSET($$.q, $1, $2, $3); } | pqual dqual { QSET($$.q, $1, $2, Q_DEFAULT); } | pqual aqual { QSET($$.q, $1, Q_DEFAULT, $2); } | pqual PROTO { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); } | pqual ndaqual { QSET($$.q, $1, Q_DEFAULT, $2); } ; thead: pqual dqual { QSET($$.q, $1, $2, Q_DEFAULT); } ; rterm: head id { $$ = $2; } | thead tid { $$ = $2; } | paren expr ')' { $$.b = $2.b; $$.q = $1.q; } | pname { $$.b = Argusgen_proto_abbrev($1); $$.q = qerr; } | tid { $$ = $1; } | arth relop arth { $$.b = Argusgen_relation($2, $1, $3, 0); $$.q = qerr; } | arth irelop arth { $$.b = Argusgen_relation($2, $1, $3, 1); $$.q = qerr; } | other { $$.b = $1; $$.q = qerr; } ; /* protocol level qualifiers */ pqual: pname | { $$ = Q_DEFAULT; } ; /* 'direction' qualifiers */ dqual: SRC { $$ = Q_SRC; } | DST { $$ = Q_DST; } | SRC OR DST { $$ = Q_OR; } | DST OR SRC { $$ = Q_OR; } | SRC AND DST { $$ = Q_AND; } | DST AND SRC { $$ = Q_AND; } ; /* address type qualifiers */ aqual: HOST { $$ = Q_HOST; } | SRCID { $$ = Q_SRCID; } | NET { $$ = Q_NET; } | PORT { $$ = Q_PORT; } | TTL { $$ = Q_TTL; } | TOS { $$ = Q_TOS; } | VLANID { $$ = Q_VLANID; } | MPLSID { $$ = Q_MPLSID; } ; /* non-directional address type qualifiers */ ndaqual: GATEWAY { $$ = Q_GATEWAY; } ; pname: LINK { $$ = Q_LINK; } | IP { $$ = Q_IP; } | ARP { $$ = Q_ARP; } | RARP { $$ = Q_RARP; } | ESP { $$ = Q_ESP; } | RTP { $$ = Q_RTP; } | RTCP { $$ = Q_RTCP; } | TCP { $$ = Q_TCP; } | UDP { $$ = Q_UDP; } | ICMP { $$ = Q_ICMP; } | IGMP { $$ = Q_IGMP; } | MPLS { $$ = Q_MPLS; } | VLAN { $$ = Q_VLAN; } | ANON { $$ = Q_ANON; } | DECNET { $$ = Q_DECNET; } | LAT { $$ = Q_LAT; } | MOPDL { $$ = Q_MOPDL; } | MOPRC { $$ = Q_MOPRC; } | MAN { $$ = Q_MAN; } | NORMAL { $$ = Q_NORMAL; } | WAIT { $$ = Q_WAIT; } | MULTIPATH { $$ = Q_MULTIPATH; } | ESTABLISHED { $$ = Q_ESTABLISHED; } | CONNECTED { $$ = Q_CONNECTED; } | CORRELATED { $$ = Q_CORRELATED; } | TIMEDOUT { $$ = Q_TIMEDOUT; } | SYN { $$ = Q_SYN; } | SYNACK { $$ = Q_SYNACK; } | DATA { $$ = Q_DATA; } | FIN { $$ = Q_FIN; } | FINACK { $$ = Q_FINACK; } | ECHO { $$ = Q_ECHO; } | UNREACH { $$ = Q_UNREACH; } | REDIRECT { $$ = Q_REDIRECT; } | TIMEXED { $$ = Q_TIMEXED; } ; tname: OUTOFORDER { $$ = Q_OUTOFORDER; } | RETRANS { $$ = Q_RETRANS; } | WINSHUT { $$ = Q_WINSHUT; } | RESET { $$ = Q_RESET; } | FRAG { $$ = Q_FRAG; } | FRAG_ONLY { $$ = Q_FRAG_ONLY; } | ECN { $$ = Q_ECN; } | RTR { $$ = Q_RTR; } | MBR { $$ = Q_MBR; } | LVG { $$ = Q_LVG; } ; other: pqual TK_BROADCAST { $$ = Argusgen_broadcast($1); } | pqual TK_MULTICAST { $$ = Argusgen_multicast($1); } | LESS NUM { $$ = Argusgen_less($2); } | GREATER NUM { $$ = Argusgen_greater($2); } | BYTE NUM byteop NUM { $$ = Argusgen_byteop($3, $2, $4); } | INBOUND { $$ = Argusgen_inbound(0); } | OUTBOUND { $$ = Argusgen_inbound(1); } ; relop: '>' { $$ = BPF_JGT; } | GEQ { $$ = BPF_JGE; } | '=' { $$ = BPF_JEQ; } ; irelop: LEQ { $$ = BPF_JGT; } | '<' { $$ = BPF_JGE; } | NEQ { $$ = BPF_JEQ; } ; arth: pnum { $$ = Argusgen_loadi($1); } | narth ; narth: pname '[' arth ']' { $$ = Argusgen_load($1, $3, 1); } | pname '[' arth ':' NUM ']' { $$ = Argusgen_load($1, $3, $5); } | arth '+' arth { $$ = Argusgen_arth(BPF_ADD, $1, $3); } | arth '-' arth { $$ = Argusgen_arth(BPF_SUB, $1, $3); } | arth '*' arth { $$ = Argusgen_arth(BPF_MUL, $1, $3); } | arth '/' arth { $$ = Argusgen_arth(BPF_DIV, $1, $3); } | arth '&' arth { $$ = Argusgen_arth(BPF_AND, $1, $3); } | arth '|' arth { $$ = Argusgen_arth(BPF_OR, $1, $3); } | arth LSH arth { $$ = Argusgen_arth(BPF_LSH, $1, $3); } | arth RSH arth { $$ = Argusgen_arth(BPF_RSH, $1, $3); } | '-' arth %prec UMINUS { $$ = Argusgen_neg($2); } | paren narth ')' { $$ = $2; } | LEN { $$ = Argusgen_loadlen(); } ; byteop: '&' { $$ = '&'; } | '|' { $$ = '|'; } | '<' { $$ = '<'; } | '>' { $$ = '>'; } | '=' { $$ = '='; } ; pnum: NUM | paren pnum ')' { $$ = $2; } ; %% argus-clients-2.0.6.fixes.1/common/scanner.l0000775000076600007660000001343607764413030014366 %{ /* * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include extern void ArgusLog (int, char *, ...); #ifndef __GNUC__ #define inline #endif int argus_lex(void); static int stoi(char *); static inline int xdtoi(int); #ifdef FLEX_SCANNER #undef YY_INPUT #define YY_INPUT(buf, result, max)\ {\ char *src = in_buffer;\ int i;\ \ if (*src == 0)\ result = YY_NULL;\ else {\ for (i = 0; *src && i < max; ++i)\ buf[i] = *src++;\ in_buffer += i;\ result = i;\ }\ } #else #undef getc #define getc(fp) (*in_buffer == 0 ? EOF : *in_buffer++) #endif #define yylval argus_lval extern YYSTYPE yylval; static char *in_buffer = NULL; %} N ([0-9]+|(0X|0x)[0-9A-Fa-f]+) B ([0-9A-Fa-f][0-9A-Fa-f]?) %a 3000 %% dst return DST; src return SRC; link|ether|ppp|slip return LINK; fddi return LINK; arp return ARP; rarp return RARP; ip return IP; tcp return TCP; udp return UDP; rtp return RTP; rtcp return RTCP; esp return ESP; man return MAN; icmp return ICMP; igmp return IGMP; mpls return MPLS; vlan return VLAN; vid return VLANID; mid return MPLSID; anon return ANON; test return TEST; host return HOST; srcid return SRCID; net return NET; mask return MASK; port return PORT; proto return PROTO; ttl return TTL; tos return TOS; gateway return GATEWAY; less return LESS; greater return GREATER; byte return BYTE; broadcast return TK_BROADCAST; multicast return TK_MULTICAST; and|"&&" return AND; or|"||" return OR; not return '!'; len|length return LEN; inbound return INBOUND; outbound return OUTBOUND; syn return SYN; synack return SYNACK; data return DATA; fin return FIN; finack return FINACK; rtr return RTR; mbr return MBR; lvg return LVG; reset return RESET; normal return NORMAL; wait return WAIT; timeout return TIMEDOUT; est return ESTABLISHED; con return CONNECTED; cor return CORRELATED; corolated return CORRELATED; ecn return ECN; drop return RETRANS; retrans return RETRANS; outoforder return OUTOFORDER; ooo return OUTOFORDER; multipath return MULTIPATH; winshut return WINSHUT; frag return FRAG; fragonly return FRAG_ONLY; echo return ECHO; unreach return UNREACH; redirect return REDIRECT; timexed return TIMEXED; [ \n\t] ; [+\-*/:\[\]!<>()&|=] return yytext[0]; ">=" return GEQ; "<=" return LEQ; "!=" return NEQ; "==" return '='; "<<" return LSH; ">>" return RSH; {N} { yylval.i = stoi((char *)yytext); return NUM; } ({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) { yylval.s = Argussdup((char *)yytext); return HID; } {B}:{B}:{B}:{B}:{B}:{B} { yylval.e = argus_ether_aton((char *)yytext); return EID; } {B}:+({B}:+)+ { ArgusLog(LOG_ERR, "bogus ethernet address %s", yytext); } [A-Za-z0-9][-_.A-Za-z0-9]*[.A-Za-z0-9] { yylval.s = Argussdup((char *)yytext); return ID; } "\\"[^ !()\n\t]+ { yylval.s = Argussdup((char *)yytext + 1); return ID; } [^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+i { ArgusLog(LOG_ERR, "illegal token: %s\n", yytext); } . { ArgusLog (LOG_ERR, "illegal char '%c'", *yytext); } %% void argus_lex_init(buf) char *buf; { in_buffer = strdup(buf); } /* * Also define a yywrap. Note that if we're using flex, it will * define a macro to map this identifier to pcap_wrap. */ int yywrap() { return 1; } /* Hex digit to integer. */ static inline int xdtoi(c) int c; { if (isdigit(c)) return c - '0'; else if (islower(c)) return c - 'a' + 10; else return c - 'A' + 10; } /* * Convert string to integer. Just like atoi(), but checks for * preceding 0x or 0 and uses hex or octal instead of decimal. */ static int stoi(s) char *s; { int base = 10; int n = 0; if (*s == '0') { if (s[1] == 'x' || s[1] == 'X') { s += 2; base = 16; } else { base = 8; s += 1; } } while (*s) n = n * base + xdtoi(*s++); return n; } argus-clients-2.0.6.fixes.1/ragrep/0000775000076600007660000000000010047734056012620 5argus-clients-2.0.6.fixes.1/ragrep/COPYING0000664000076600007660000004311007310146216013564 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. argus-clients-2.0.6.fixes.1/ragrep/INSTALL0000664000076600007660000000054207310146216013564 Specific Installation ===================== In order to make this distribution, you must untar the distribution into the ./clients directory of an Argus-2.0 source distriubtion. Making in this directory will create ragrep and install it in the ./bin directory of the Argus-2.0 distribution. A "make install" will install ragrep into /usr/local/bin. argus-clients-2.0.6.fixes.1/ragrep/Makefile.in0000664000076600007660000003427407703321100014602 # Generated automatically from Makefile.in by configure. # Makefile.in generated automatically by automake 1.4 from Makefile.am # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. SHELL = /bin/sh # Top level hierarchy prefix = $(DESTDIR)@prefix@ exec_prefix = @exec_prefix@ # Pathname of directory to install the system binaries SBINDIR = @sbindir@ # Pathname of directory to install the system binaries BINDIR = @bindir@ # Pathname of directory to install the include files INCLDEST = @includedir@ # Pathname of directory to install the library LIBDEST = @libdir@ # Pathname of directory to install the man page MANDEST = @mandir@ # VPATH srcdir = @srcdir@ VPATH = @srcdir@ # # You shouldn't need to edit anything below. # CC = @CC@ CCOPT = @V_CCOPT@ INCLS = -I. -I../include -I../common @V_INCLS@ DEFS = @DEFS@ COMPATLIB = @COMPATLIB@ @LIB_SASL@ # Standard CFLAGS CFLAGS = $(CCOPT) $(INCLS) $(DEFS) INSTALL = @INSTALL@ RANLIB = @V_RANLIB@ #srcdir = . #top_srcdir = ../ #prefix = /usr/local #exec_prefix = ${prefix} #bindir = ${exec_prefix}/bin #sbindir = ${exec_prefix}/sbin #libexecdir = ${exec_prefix}/libexec #sysconfdir = ${prefix}/etc #sharedstatedir = ${prefix}/com #localstatedir = ${prefix}/var #libdir = ${exec_prefix}/lib #infodir = ${prefix}/info #mandir = ${prefix}/man #includedir = ${prefix}/include #oldincludedir = /usr/include #pkgdatadir = $(datadir)/ragrep #pkglibdir = $(libdir)/ragrep #pkgincludedir = $(includedir)/ragrep # #top_builddir = .. ACLOCAL = aclocal AUTOCONF = autoconf AUTOMAKE = automake AUTOHEADER = autoheader INSTALL = /usr/bin/install -c INSTALL_PROGRAM = ${INSTALL} $(AM_INSTALL_PROGRAM_FLAGS) INSTALL_DATA = ${INSTALL} -m 644 INSTALL_SCRIPT = ${INSTALL_PROGRAM} transform = s,x,x, NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = i686-pc-linux-gnu host_triplet = i686-pc-linux-gnu AWK = mawk #CC = gcc #CPP = gcc -E DATADIRNAME = share EXEEXT = GENCAT = GETCONF = getconf GMSGFMT = /usr/bin/msgfmt GT_NO = GT_YES = #YES# INCLUDE_LOCALE_H = #include INSTOBJEXT = .mo INTLDEPS = INTLLIBS = INTLOBJS = LIBOBJS = regex$U.o MAKEINFO = makeinfo MKINSTALLDIRS = mkinstalldirs MSGFMT = /usr/bin/msgfmt PACKAGE = ragrep RANLIB = ranlib SEP = : U = USE_INCLUDED_LIBINTL = no USE_NLS = yes VERSION = 2.4.2 l = LN = ln # We let configure figure out if we need the regex.c or not # it is provided in GNU/Linux system # regex.c regex.h bin_PROGRAMS = ../bin/ragrep base_sources = ragrep.c ragrep.h ragrep_SOURCES = $(base_sources) egrepmat.c LDADD = regex$U.o datadir = $(prefix)/share localedir = $(datadir)/locale INCLUDES = -I. -I../include -DLOCALEDIR=\"$(localedir)\" EXTRA_DIST = dosbuf.c vms_fab.c vms_fab.h regex.h mkinstalldirs = $(SHELL) ../config/mkinstalldirs CONFIG_HEADER = ./config.h CONFIG_CLEAN_FILES = #bin_PROGRAMS = ragrep$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) CPPFLAGS = LDFLAGS = LIBS = ../lib/argus_common.a ../lib/argus_parse.a ../lib/argus_client.a -lm $(COMPATLIB) ANSI2KNR = #ragrep_OBJECTS = ragrep$U.o dfa$U.o kwset$U.o obstack$U.o search$U.o egrepmat$U.o ragrep_OBJECTS = ragrep$U.o dfa$U.o kwset$U.o obstack$U.o search$U.o egrepmat$U.o ragrep_LDADD = $(LDADD) ragrep_DEPENDENCIES = regex$U.o ragrep_LDFLAGS = #CFLAGS = -g -O2 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ DIST_COMMON = Makefile.am Makefile.in alloca.c regex.c stpcpy.c DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = gtar GZIP_ENV = --best SOURCES = $(ragrep_SOURCES) OBJECTS = $(ragrep_OBJECTS) all: all-redirect .SUFFIXES: .SUFFIXES: .S .c .o .s #$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) # cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile #Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status # cd $(top_builddir) \ # && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status mostlyclean-binPROGRAMS: clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) distclean-binPROGRAMS: maintainer-clean-binPROGRAMS: install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(BINDIR) @list='$(bin_PROGRAMS)'; for p in $$list; do \ if test -f $$p; then \ echo " $(INSTALL_PROGRAM) $$p $(BINDIR)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ $(INSTALL_PROGRAM) $$p $(BINDIR)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) list='$(bin_PROGRAMS)'; for p in $$list; do \ rm -f $(BINDIR)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ done .c.o: $(COMPILE) -c $< .s.o: $(COMPILE) -c $< .S.o: $(COMPILE) -c $< mostlyclean-compile: -rm -f *.o core *.core clean-compile: distclean-compile: -rm -f *.tab.c maintainer-clean-compile: mostlyclean-krextra: distclean-krextra: maintainer-clean-krextra: mostlyclean-kr: -rm -f *_.c force: /tmp depend: $(GENSRC) force ../bin/mkdep -c $(COMPILE) ragrep.c clean-kr: distclean-kr: maintainer-clean-kr: ../bin/ragrep$(EXEEXT): $(ragrep_OBJECTS) $(ragrep_DEPENDENCIES) @rm -f ../bin/ragrep$(EXEEXT) $(LINK) $(ragrep_LDFLAGS) $(ragrep_OBJECTS) $(ragrep_LDADD) $(LIBS) alloca_.c: alloca.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/alloca.c; then echo $(srcdir)/alloca.c; else echo alloca.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > alloca_.c dfa_.c: dfa.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/dfa.c; then echo $(srcdir)/dfa.c; else echo dfa.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > dfa_.c egrepmat_.c: egrepmat.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/egrepmat.c; then echo $(srcdir)/egrepmat.c; else echo egrepmat.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > egrepmat_.c getopt_.c: getopt.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/getopt.c; then echo $(srcdir)/getopt.c; else echo getopt.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > getopt_.c getopt1_.c: getopt1.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/getopt1.c; then echo $(srcdir)/getopt1.c; else echo getopt1.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > getopt1_.c kwset_.c: kwset.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/kwset.c; then echo $(srcdir)/kwset.c; else echo kwset.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > kwset_.c ragrep_.c: ragrep.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ragrep.c; then echo $(srcdir)/ragrep.c; else echo ragrep.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > ragrep_.c regex_.c: regex.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/regex.c; then echo $(srcdir)/regex.c; else echo regex.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > regex_.c search_.c: search.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/search.c; then echo $(srcdir)/search.c; else echo search.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > search_.c stpcpy_.c: stpcpy.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/stpcpy.c; then echo $(srcdir)/stpcpy.c; else echo stpcpy.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > stpcpy_.c alloca_.o dfa_.o egrepmat_.o getopt_.o getopt1_.o kwset_.o \ ragrep_.o regex_.o search_.o stpcpy_.o : \ $(ANSI2KNR) # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. all-recursive install-data-recursive install-exec-recursive \ installdirs-recursive install-recursive uninstall-recursive \ check-recursive installcheck-recursive info-recursive dvi-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ rev="$$subdir $$rev"; \ test "$$subdir" = "." && dot_seen=yes; \ done; \ test "$$dot_seen" = "no" && rev=". $$rev"; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ here=`pwd` && cd $(srcdir) \ && mkid -f$$here/ID $$unique $(LISP) TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) tags=; \ here=`pwd`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) mostlyclean-tags: clean-tags: distclean-tags: -rm -f TAGS ID maintainer-clean-tags: distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) subdir = src distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $$d/$$file $(distdir)/$$file || :; \ fi; \ done for subdir in $(SUBDIRS); do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ chmod 777 $(distdir)/$$subdir; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \ || exit 1; \ fi; \ done info-am: info: info-recursive dvi-am: dvi: dvi-recursive check-am: all-am check: check-recursive installcheck-am: installcheck: installcheck-recursive install-exec-am: install-binPROGRAMS install-exec: install-exec-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install: install-recursive uninstall-am: uninstall-binPROGRAMS uninstall: uninstall-recursive all-am: Makefile $(ANSI2KNR) $(PROGRAMS) all-redirect: all-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install installdirs: installdirs-recursive installdirs-am: $(mkinstalldirs) $(DESTDIR)$(bindir) mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log stamp-h stamp-h[0-9]* maintainer-clean-generic: mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-compile \ mostlyclean-krextra mostlyclean-kr mostlyclean-tags \ mostlyclean-generic mostlyclean: mostlyclean-recursive clean-am: clean-binPROGRAMS clean-compile clean-kr \ clean-tags clean-generic mostlyclean-am clean: clean-recursive distclean-am: distclean-binPROGRAMS distclean-compile distclean-krextra \ distclean-kr distclean-tags distclean-generic clean-am clobber distclean: distclean-recursive maintainer-clean-am: maintainer-clean-binPROGRAMS \ maintainer-clean-compile maintainer-clean-krextra \ maintainer-clean-kr maintainer-clean-tags \ maintainer-clean-generic distclean-am @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." maintainer-clean: maintainer-clean-recursive .PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ mostlyclean-compile distclean-compile clean-compile \ maintainer-clean-compile mostlyclean-krextra distclean-krextra \ maintainer-clean-krextra mostlyclean-kr distclean-kr \ clean-kr maintainer-clean-kr install-data-recursive \ uninstall-data-recursive install-exec-recursive \ uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ all-recursive check-recursive installcheck-recursive info-recursive \ dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ install-exec install-data-am install-data install-am install \ uninstall-am uninstall all-redirect all-am all installdirs-am \ installdirs mostlyclean-generic distclean-generic clean-generic \ maintainer-clean-generic clean mostlyclean distclean maintainer-clean # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: argus-clients-2.0.6.fixes.1/ragrep/README0000664000076600007660000000314607310146216013416 This is ragrep(), an adaptation of the GNU egrep routing. This provides egrep() support for searching captured user data in Argus-2.0 data records, using regular expression syntax. Only the files needed to support ragrep() from the original GNU grep() distribution are provided here. If you have any problems send bug reports to argus-info@lists.andrew.cmu.edu. Original GNU grep-2.4.2 README file This is GNU grep, the "fastest grep in the west" (we hope). All bugs reported in previous releases have been fixed. Many exciting new bugs have probably been introduced in this revision. GNU grep is provided "as is" with no warranty. The exact terms under which you may use and (re)distribute this program are detailed in the GNU General Public License, in the file COPYING. GNU grep is based on a fast lazy-state deterministic matcher (about twice as fast as stock Unix egrep) hybridized with a Boyer-Moore-Gosper search for a fixed string that eliminates impossible text from being considered by the full regexp matcher without necessarily having to look at every character. The result is typically many times faster than Unix grep or egrep. (Regular expressions containing backreferencing will run more slowly, however.) See the files AUTHORS and THANKS for a list of authors and other contributors. See the file INSTALL for compilation and installation instructions. See the file NEWS for a description of major changes in this release. See the file TODO for ideas on how you could help us improve grep. Send bug reports to bug-gnu-utils@gnu.org. Be sure to include the word "grep" in your Subject: header field. argus-clients-2.0.6.fixes.1/ragrep/dfa.c0000664000076600007660000020605307323102313013430 /* dfa.c - deterministic extended regexp routines for GNU Copyright 1988, 1998, 2000 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* Written June, 1988 by Mike Haertel Modified July, 1988 by Arthur David Olson to assist BMG speedups */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #ifdef STDC_HEADERS #include #else extern char *calloc(), *malloc(), *realloc(); extern void free(); #endif #if defined(HAVE_STRING_H) || defined(STDC_HEADERS) #include #undef index #define index strchr #else #include #endif #ifndef DEBUG /* use the same approach as regex.c */ #undef assert #define assert(e) #endif /* DEBUG */ #ifndef isgraph #define isgraph(C) (isprint(C) && !isspace(C)) #endif #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) #define ISALPHA(C) isalpha(C) #define ISUPPER(C) isupper(C) #define ISLOWER(C) islower(C) #define ISDIGIT(C) isdigit(C) #define ISXDIGIT(C) isxdigit(C) #define ISSPACE(C) isspace(C) #define ISPUNCT(C) ispunct(C) #define ISALNUM(C) isalnum(C) #define ISPRINT(C) isprint(C) #define ISGRAPH(C) isgraph(C) #define ISCNTRL(C) iscntrl(C) #else #define ISALPHA(C) (isascii(C) && isalpha(C)) #define ISUPPER(C) (isascii(C) && isupper(C)) #define ISLOWER(C) (isascii(C) && islower(C)) #define ISDIGIT(C) (isascii(C) && isdigit(C)) #define ISXDIGIT(C) (isascii(C) && isxdigit(C)) #define ISSPACE(C) (isascii(C) && isspace(C)) #define ISPUNCT(C) (isascii(C) && ispunct(C)) #define ISALNUM(C) (isascii(C) && isalnum(C)) #define ISPRINT(C) (isascii(C) && isprint(C)) #define ISGRAPH(C) (isascii(C) && isgraph(C)) #define ISCNTRL(C) (isascii(C) && iscntrl(C)) #endif /* ISASCIIDIGIT differs from ISDIGIT, as follows: - Its arg may be any int or unsigned int; it need not be an unsigned char. - It's guaranteed to evaluate its argument exactly once. - It's typically faster. Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that only '0' through '9' are digits. Prefer ISASCIIDIGIT to ISDIGIT unless it's important to use the locale's definition of `digit' even when the host does not conform to Posix. */ #define ISASCIIDIGIT(c) ((unsigned) (c) - '0' <= 9) /* If we (don't) have I18N. */ /* glibc defines _ */ #ifndef _ # ifdef HAVE_LIBINTL_H # include # ifndef _ # define _(Str) gettext (Str) # endif # else # define _(Str) (Str) # endif #endif #include "regex.h" #include "dfa.h" /* HPUX, define those as macros in sys/param.h */ #ifdef setbit # undef setbit #endif #ifdef clrbit # undef clrbit #endif static void dfamust PARAMS ((struct dfa *dfa)); extern ptr_t xcalloc PARAMS ((size_t n, size_t s)); extern ptr_t xmalloc PARAMS ((size_t n)); extern ptr_t xrealloc PARAMS ((ptr_t p, size_t n)); #ifdef DEBUG static void prtok PARAMS ((token t)); #endif static int tstbit PARAMS ((int b, charclass c)); static void setbit PARAMS ((int b, charclass c)); static void clrbit PARAMS ((int b, charclass c)); static void copyset PARAMS ((charclass src, charclass dst)); static void zeroset PARAMS ((charclass s)); static void notset PARAMS ((charclass s)); static int equal PARAMS ((charclass s1, charclass s2)); static int charclass_index PARAMS ((charclass s)); static int looking_at PARAMS ((const char *s)); static token lex PARAMS ((void)); static void addtok PARAMS ((token t)); static void atom PARAMS ((void)); static int nsubtoks PARAMS ((int tindex)); static void copytoks PARAMS ((int tindex, int ntokens)); static void closure PARAMS ((void)); static void branch PARAMS ((void)); static void regexp PARAMS ((int toplevel)); static void copy PARAMS ((position_set *src, position_set *dst)); static void insert PARAMS ((position p, position_set *s)); static void merge PARAMS ((position_set *s1, position_set *s2, position_set *m)); static void delete PARAMS ((position p, position_set *s)); static int state_index PARAMS ((struct dfa *d, position_set *s, int newline, int letter)); static void build_state PARAMS ((int s, struct dfa *d)); static void build_state_zero PARAMS ((struct dfa *d)); static char *icatalloc PARAMS ((char *old, char *new)); static char *icpyalloc PARAMS ((char *string)); static char *istrstr PARAMS ((char *lookin, char *lookfor)); static void ifree PARAMS ((char *cp)); static void freelist PARAMS ((char **cpp)); static char **enlist PARAMS ((char **cpp, char *new, size_t len)); static char **comsubs PARAMS ((char *left, char *right)); static char **addlists PARAMS ((char **old, char **new)); static char **inboth PARAMS ((char **left, char **right)); /* static ptr_t xcalloc (size_t n, size_t s) { ptr_t r = calloc(n, s); if (!r) dfaerror(_("Memory exhausted")); return r; } static ptr_t xmalloc (size_t n) { ptr_t r = malloc(n); assert(n != 0); if (!r) dfaerror(_("Memory exhausted")); return r; } static ptr_t xrealloc (ptr_t p, size_t n) { ptr_t r = realloc(p, n); assert(n != 0); if (!r) dfaerror(_("Memory exhausted")); return r; } */ #define CALLOC(p, t, n) ((p) = (t *) xcalloc((size_t)(n), sizeof (t))) #define MALLOC(p, t, n) ((p) = (t *) xmalloc((n) * sizeof (t))) #define REALLOC(p, t, n) ((p) = (t *) xrealloc((ptr_t) (p), (n) * sizeof (t))) /* Reallocate an array of type t if nalloc is too small for index. */ #define REALLOC_IF_NECESSARY(p, t, nalloc, index) \ if ((index) >= (nalloc)) \ { \ while ((index) >= (nalloc)) \ (nalloc) *= 2; \ REALLOC(p, t, nalloc); \ } #ifdef DEBUG static void prtok (token t) { char *s; if (t < 0) fprintf(stderr, "END"); else if (t < NOTCHAR) fprintf(stderr, "%c", t); else { switch (t) { case EMPTY: s = "EMPTY"; break; case BACKREF: s = "BACKREF"; break; case BEGLINE: s = "BEGLINE"; break; case ENDLINE: s = "ENDLINE"; break; case BEGWORD: s = "BEGWORD"; break; case ENDWORD: s = "ENDWORD"; break; case LIMWORD: s = "LIMWORD"; break; case NOTLIMWORD: s = "NOTLIMWORD"; break; case QMARK: s = "QMARK"; break; case STAR: s = "STAR"; break; case PLUS: s = "PLUS"; break; case CAT: s = "CAT"; break; case OR: s = "OR"; break; case ORTOP: s = "ORTOP"; break; case LPAREN: s = "LPAREN"; break; case RPAREN: s = "RPAREN"; break; default: s = "CSET"; break; } fprintf(stderr, "%s", s); } } #endif /* DEBUG */ /* Stuff pertaining to charclasses. */ static int tstbit (int b, charclass c) { return c[b / INTBITS] & 1 << b % INTBITS; } static void setbit (int b, charclass c) { c[b / INTBITS] |= 1 << b % INTBITS; } static void clrbit (int b, charclass c) { c[b / INTBITS] &= ~(1 << b % INTBITS); } static void copyset (charclass src, charclass dst) { int i; for (i = 0; i < CHARCLASS_INTS; ++i) dst[i] = src[i]; } static void zeroset (charclass s) { int i; for (i = 0; i < CHARCLASS_INTS; ++i) s[i] = 0; } static void notset (charclass s) { int i; for (i = 0; i < CHARCLASS_INTS; ++i) s[i] = ~s[i]; } static int equal (charclass s1, charclass s2) { int i; for (i = 0; i < CHARCLASS_INTS; ++i) if (s1[i] != s2[i]) return 0; return 1; } /* A pointer to the current dfa is kept here during parsing. */ static struct dfa *dfa; /* Find the index of charclass s in dfa->charclasses, or allocate a new charclass. */ static int charclass_index (charclass s) { int i; for (i = 0; i < dfa->cindex; ++i) if (equal(s, dfa->charclasses[i])) return i; REALLOC_IF_NECESSARY(dfa->charclasses, charclass, dfa->calloc, dfa->cindex); ++dfa->cindex; copyset(s, dfa->charclasses[i]); return i; } /* Syntax bits controlling the behavior of the lexical analyzer. */ static reg_syntax_t syntax_bits, syntax_bits_set; /* Flag for case-folding letters into sets. */ static int case_fold; /* End-of-line byte in data. */ static unsigned char eolbyte; /* Entry point to set syntax options. */ void dfasyntax (reg_syntax_t bits, int fold, int eol) { syntax_bits_set = 1; syntax_bits = bits; case_fold = fold; eolbyte = eol; } /* Lexical analyzer. All the dross that deals with the obnoxious GNU Regex syntax bits is located here. The poor, suffering reader is referred to the GNU Regex documentation for the meaning of the @#%!@#%^!@ syntax bits. */ static char *lexstart; /* Pointer to beginning of input string. */ static char *lexptr; /* Pointer to next input character. */ static int lexleft; /* Number of characters remaining. */ static token lasttok; /* Previous token returned; initially END. */ static int laststart; /* True if we're separated from beginning or (, | only by zero-width characters. */ static int parens; /* Count of outstanding left parens. */ static int minrep, maxrep; /* Repeat counts for {m,n}. */ /* Note that characters become unsigned here. */ #define FETCH(c, eoferr) \ { \ if (! lexleft) \ { \ if (eoferr != 0) \ dfaerror (eoferr); \ else \ return lasttok = END; \ } \ (c) = (unsigned char) *lexptr++; \ --lexleft; \ } #ifdef __STDC__ #define FUNC(F, P) static int F(int c) { return P(c); } #else #define FUNC(F, P) static int F(c) int c; { return P(c); } #endif FUNC(is_alpha, ISALPHA) FUNC(is_upper, ISUPPER) FUNC(is_lower, ISLOWER) FUNC(is_digit, ISDIGIT) FUNC(is_xdigit, ISXDIGIT) FUNC(is_space, ISSPACE) FUNC(is_punct, ISPUNCT) FUNC(is_alnum, ISALNUM) FUNC(is_print, ISPRINT) FUNC(is_graph, ISGRAPH) FUNC(is_cntrl, ISCNTRL) static int is_blank (int c) { return (c == ' ' || c == '\t'); } /* The following list maps the names of the Posix named character classes to predicate functions that determine whether a given character is in the class. The leading [ has already been eaten by the lexical analyzer. */ static struct { const char *name; int (*pred) PARAMS ((int)); } prednames[] = { { ":alpha:]", is_alpha }, { ":upper:]", is_upper }, { ":lower:]", is_lower }, { ":digit:]", is_digit }, { ":xdigit:]", is_xdigit }, { ":space:]", is_space }, { ":punct:]", is_punct }, { ":alnum:]", is_alnum }, { ":print:]", is_print }, { ":graph:]", is_graph }, { ":cntrl:]", is_cntrl }, { ":blank:]", is_blank }, { 0 } }; /* Return non-zero if C is a `word-constituent' byte; zero otherwise. */ #define IS_WORD_CONSTITUENT(C) (ISALNUM(C) || (C) == '_') static int looking_at (char const *s) { size_t len; len = strlen(s); if (lexleft < len) return 0; return strncmp(s, lexptr, len) == 0; } static token lex (void) { token c, c1, c2; int backslash = 0, invert; charclass ccl; int i; char lo[2]; char hi[2]; /* Basic plan: We fetch a character. If it's a backslash, we set the backslash flag and go through the loop again. On the plus side, this avoids having a duplicate of the main switch inside the backslash case. On the minus side, it means that just about every case begins with "if (backslash) ...". */ for (i = 0; i < 2; ++i) { FETCH(c, 0); switch (c) { case '\\': if (backslash) goto normal_char; if (lexleft == 0) dfaerror(_("Unfinished \\ escape")); backslash = 1; break; case '^': if (backslash) goto normal_char; if (syntax_bits & RE_CONTEXT_INDEP_ANCHORS || lasttok == END || lasttok == LPAREN || lasttok == OR) return lasttok = BEGLINE; goto normal_char; case '$': if (backslash) goto normal_char; if (syntax_bits & RE_CONTEXT_INDEP_ANCHORS || lexleft == 0 || (syntax_bits & RE_NO_BK_PARENS ? lexleft > 0 && *lexptr == ')' : lexleft > 1 && lexptr[0] == '\\' && lexptr[1] == ')') || (syntax_bits & RE_NO_BK_VBAR ? lexleft > 0 && *lexptr == '|' : lexleft > 1 && lexptr[0] == '\\' && lexptr[1] == '|') || ((syntax_bits & RE_NEWLINE_ALT) && lexleft > 0 && *lexptr == '\n')) return lasttok = ENDLINE; goto normal_char; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (backslash && !(syntax_bits & RE_NO_BK_REFS)) { laststart = 0; return lasttok = BACKREF; } goto normal_char; case '`': if (backslash && !(syntax_bits & RE_NO_GNU_OPS)) return lasttok = BEGLINE; /* FIXME: should be beginning of string */ goto normal_char; case '\'': if (backslash && !(syntax_bits & RE_NO_GNU_OPS)) return lasttok = ENDLINE; /* FIXME: should be end of string */ goto normal_char; case '<': if (backslash && !(syntax_bits & RE_NO_GNU_OPS)) return lasttok = BEGWORD; goto normal_char; case '>': if (backslash && !(syntax_bits & RE_NO_GNU_OPS)) return lasttok = ENDWORD; goto normal_char; case 'b': if (backslash && !(syntax_bits & RE_NO_GNU_OPS)) return lasttok = LIMWORD; goto normal_char; case 'B': if (backslash && !(syntax_bits & RE_NO_GNU_OPS)) return lasttok = NOTLIMWORD; goto normal_char; case '?': if (syntax_bits & RE_LIMITED_OPS) goto normal_char; if (backslash != ((syntax_bits & RE_BK_PLUS_QM) != 0)) goto normal_char; if (!(syntax_bits & RE_CONTEXT_INDEP_OPS) && laststart) goto normal_char; return lasttok = QMARK; case '*': if (backslash) goto normal_char; if (!(syntax_bits & RE_CONTEXT_INDEP_OPS) && laststart) goto normal_char; return lasttok = STAR; case '+': if (syntax_bits & RE_LIMITED_OPS) goto normal_char; if (backslash != ((syntax_bits & RE_BK_PLUS_QM) != 0)) goto normal_char; if (!(syntax_bits & RE_CONTEXT_INDEP_OPS) && laststart) goto normal_char; return lasttok = PLUS; case '{': if (!(syntax_bits & RE_INTERVALS)) goto normal_char; if (backslash != ((syntax_bits & RE_NO_BK_BRACES) == 0)) goto normal_char; if (!(syntax_bits & RE_CONTEXT_INDEP_OPS) && laststart) goto normal_char; if (syntax_bits & RE_NO_BK_BRACES) { /* Scan ahead for a valid interval; if it's not valid, treat it as a literal '{'. */ int lo = -1, hi = -1; char const *p = lexptr; char const *lim = p + lexleft; for (; p != lim && ISASCIIDIGIT (*p); p++) lo = (lo < 0 ? 0 : lo * 10) + *p - '0'; if (p != lim && *p == ',') while (++p != lim && ISASCIIDIGIT (*p)) hi = (hi < 0 ? 0 : hi * 10) + *p - '0'; else hi = lo; if (p == lim || *p != '}' || lo < 0 || RE_DUP_MAX < hi || (0 <= hi && hi < lo)) goto normal_char; } minrep = 0; /* Cases: {M} - exact count {M,} - minimum count, maximum is infinity {M,N} - M through N */ FETCH(c, _("unfinished repeat count")); if (ISASCIIDIGIT (c)) { minrep = c - '0'; for (;;) { FETCH(c, _("unfinished repeat count")); if (! ISASCIIDIGIT (c)) break; minrep = 10 * minrep + c - '0'; } } else dfaerror(_("malformed repeat count")); if (c == ',') { FETCH (c, _("unfinished repeat count")); if (! ISASCIIDIGIT (c)) maxrep = -1; else { maxrep = c - '0'; for (;;) { FETCH (c, _("unfinished repeat count")); if (! ISASCIIDIGIT (c)) break; maxrep = 10 * maxrep + c - '0'; } if (0 <= maxrep && maxrep < minrep) dfaerror (_("malformed repeat count")); } } else maxrep = minrep; if (!(syntax_bits & RE_NO_BK_BRACES)) { if (c != '\\') dfaerror(_("malformed repeat count")); FETCH(c, _("unfinished repeat count")); } if (c != '}') dfaerror(_("malformed repeat count")); laststart = 0; return lasttok = REPMN; case '|': if (syntax_bits & RE_LIMITED_OPS) goto normal_char; if (backslash != ((syntax_bits & RE_NO_BK_VBAR) == 0)) goto normal_char; laststart = 1; return lasttok = OR; case '\n': if (syntax_bits & RE_LIMITED_OPS || backslash || !(syntax_bits & RE_NEWLINE_ALT)) goto normal_char; laststart = 1; return lasttok = OR; case '(': if (backslash != ((syntax_bits & RE_NO_BK_PARENS) == 0)) goto normal_char; ++parens; laststart = 1; return lasttok = LPAREN; case ')': if (backslash != ((syntax_bits & RE_NO_BK_PARENS) == 0)) goto normal_char; if (parens == 0 && syntax_bits & RE_UNMATCHED_RIGHT_PAREN_ORD) goto normal_char; --parens; laststart = 0; return lasttok = RPAREN; case '.': if (backslash) goto normal_char; zeroset(ccl); notset(ccl); if (!(syntax_bits & RE_DOT_NEWLINE)) clrbit(eolbyte, ccl); if (syntax_bits & RE_DOT_NOT_NULL) clrbit('\0', ccl); laststart = 0; return lasttok = CSET + charclass_index(ccl); case 'w': case 'W': if (!backslash || (syntax_bits & RE_NO_GNU_OPS)) goto normal_char; zeroset(ccl); for (c2 = 0; c2 < NOTCHAR; ++c2) if (IS_WORD_CONSTITUENT(c2)) setbit(c2, ccl); if (c == 'W') notset(ccl); laststart = 0; return lasttok = CSET + charclass_index(ccl); case '[': if (backslash) goto normal_char; zeroset(ccl); FETCH(c, _("Unbalanced [")); if (c == '^') { FETCH(c, _("Unbalanced [")); invert = 1; } else invert = 0; do { /* Nobody ever said this had to be fast. :-) Note that if we're looking at some other [:...:] construct, we just treat it as a bunch of ordinary characters. We can do this because we assume regex has checked for syntax errors before dfa is ever called. */ if (c == '[' && (syntax_bits & RE_CHAR_CLASSES)) for (c1 = 0; prednames[c1].name; ++c1) if (looking_at(prednames[c1].name)) { int (*pred)(int) = prednames[c1].pred; if (case_fold && (pred == is_upper || pred == is_lower)) pred = is_alpha; for (c2 = 0; c2 < NOTCHAR; ++c2) if ((*pred)(c2)) setbit(c2, ccl); lexptr += strlen(prednames[c1].name); lexleft -= strlen(prednames[c1].name); FETCH(c1, _("Unbalanced [")); goto skip; } if (c == '\\' && (syntax_bits & RE_BACKSLASH_ESCAPE_IN_LISTS)) FETCH(c, _("Unbalanced [")); FETCH(c1, _("Unbalanced [")); if (c1 == '-') { FETCH(c2, _("Unbalanced [")); if (c2 == ']') { /* In the case [x-], the - is an ordinary hyphen, which is left in c1, the lookahead character. */ --lexptr; ++lexleft; c2 = c; } else { if (c2 == '\\' && (syntax_bits & RE_BACKSLASH_ESCAPE_IN_LISTS)) FETCH(c2, _("Unbalanced [")); FETCH(c1, _("Unbalanced [")); } } else c2 = c; lo[0] = c; lo[1] = '\0'; hi[0] = c2; hi[1] = '\0'; for (c = 0; c < NOTCHAR; c++) { char ch[2]; ch[0] = c; ch[1] = '\0'; if (strcoll (lo, ch) <= 0 && strcoll (ch, hi) <= 0) { setbit (c, ccl); if (case_fold) { if (ISUPPER (c)) setbit (tolower (c), ccl); else if (ISLOWER (c)) setbit (toupper (c), ccl); } } } skip: ; } while ((c = c1) != ']'); if (invert) { notset(ccl); if (syntax_bits & RE_HAT_LISTS_NOT_NEWLINE) clrbit(eolbyte, ccl); } laststart = 0; return lasttok = CSET + charclass_index(ccl); default: normal_char: laststart = 0; if (case_fold && ISALPHA(c)) { zeroset(ccl); setbit(c, ccl); if (isupper(c)) setbit(tolower(c), ccl); else setbit(toupper(c), ccl); return lasttok = CSET + charclass_index(ccl); } return c; } } /* The above loop should consume at most a backslash and some other character. */ abort(); return END; /* keeps pedantic compilers happy. */ } /* Recursive descent parser for regular expressions. */ static token tok; /* Lookahead token. */ static int depth; /* Current depth of a hypothetical stack holding deferred productions. This is used to determine the depth that will be required of the real stack later on in dfaanalyze(). */ /* Add the given token to the parse tree, maintaining the depth count and updating the maximum depth if necessary. */ static void addtok (token t) { REALLOC_IF_NECESSARY(dfa->tokens, token, dfa->talloc, dfa->tindex); dfa->tokens[dfa->tindex++] = t; switch (t) { case QMARK: case STAR: case PLUS: break; case CAT: case OR: case ORTOP: --depth; break; default: ++dfa->nleaves; case EMPTY: ++depth; break; } if (depth > dfa->depth) dfa->depth = depth; } /* The grammar understood by the parser is as follows. regexp: regexp OR branch branch branch: branch closure closure closure: closure QMARK closure STAR closure PLUS atom atom: CSET BACKREF BEGLINE ENDLINE BEGWORD ENDWORD LIMWORD NOTLIMWORD The parser builds a parse tree in postfix form in an array of tokens. */ static void atom (void) { if ((tok >= 0 && tok < NOTCHAR) || tok >= CSET || tok == BACKREF || tok == BEGLINE || tok == ENDLINE || tok == BEGWORD || tok == ENDWORD || tok == LIMWORD || tok == NOTLIMWORD) { addtok(tok); tok = lex(); } else if (tok == LPAREN) { tok = lex(); regexp(0); if (tok != RPAREN) dfaerror(_("Unbalanced (")); tok = lex(); } else addtok(EMPTY); } /* Return the number of tokens in the given subexpression. */ static int nsubtoks (int tindex) { int ntoks1; switch (dfa->tokens[tindex - 1]) { default: return 1; case QMARK: case STAR: case PLUS: return 1 + nsubtoks(tindex - 1); case CAT: case OR: case ORTOP: ntoks1 = nsubtoks(tindex - 1); return 1 + ntoks1 + nsubtoks(tindex - 1 - ntoks1); } } /* Copy the given subexpression to the top of the tree. */ static void copytoks (int tindex, int ntokens) { int i; for (i = 0; i < ntokens; ++i) addtok(dfa->tokens[tindex + i]); } static void closure (void) { int tindex, ntokens, i; atom(); while (tok == QMARK || tok == STAR || tok == PLUS || tok == REPMN) if (tok == REPMN) { ntokens = nsubtoks(dfa->tindex); tindex = dfa->tindex - ntokens; if (maxrep < 0) addtok(PLUS); if (minrep == 0) addtok(QMARK); for (i = 1; i < minrep; ++i) { copytoks(tindex, ntokens); addtok(CAT); } for (; i < maxrep; ++i) { copytoks(tindex, ntokens); addtok(QMARK); addtok(CAT); } tok = lex(); } else { addtok(tok); tok = lex(); } } static void branch (void) { closure(); while (tok != RPAREN && tok != OR && tok >= 0) { closure(); addtok(CAT); } } static void regexp (int toplevel) { branch(); while (tok == OR) { tok = lex(); branch(); if (toplevel) addtok(ORTOP); else addtok(OR); } } /* Main entry point for the parser. S is a string to be parsed, len is the length of the string, so s can include NUL characters. D is a pointer to the struct dfa to parse into. */ void dfaparse (char *s, size_t len, struct dfa *d) { dfa = d; lexstart = lexptr = s; lexleft = len; lasttok = END; laststart = 1; parens = 0; if (! syntax_bits_set) dfaerror(_("No syntax specified")); tok = lex(); depth = d->depth; regexp(1); if (tok != END) dfaerror(_("Unbalanced )")); addtok(END - d->nregexps); addtok(CAT); if (d->nregexps) addtok(ORTOP); ++d->nregexps; } /* Some primitives for operating on sets of positions. */ /* Copy one set to another; the destination must be large enough. */ static void copy (position_set *src, position_set *dst) { int i; for (i = 0; i < src->nelem; ++i) dst->elems[i] = src->elems[i]; dst->nelem = src->nelem; } /* Insert a position in a set. Position sets are maintained in sorted order according to index. If position already exists in the set with the same index then their constraints are logically or'd together. S->elems must point to an array large enough to hold the resulting set. */ static void insert (position p, position_set *s) { int i; position t1, t2; for (i = 0; i < s->nelem && p.index < s->elems[i].index; ++i) continue; if (i < s->nelem && p.index == s->elems[i].index) s->elems[i].constraint |= p.constraint; else { t1 = p; ++s->nelem; while (i < s->nelem) { t2 = s->elems[i]; s->elems[i++] = t1; t1 = t2; } } } /* Merge two sets of positions into a third. The result is exactly as if the positions of both sets were inserted into an initially empty set. */ static void merge (position_set *s1, position_set *s2, position_set *m) { int i = 0, j = 0; m->nelem = 0; while (i < s1->nelem && j < s2->nelem) if (s1->elems[i].index > s2->elems[j].index) m->elems[m->nelem++] = s1->elems[i++]; else if (s1->elems[i].index < s2->elems[j].index) m->elems[m->nelem++] = s2->elems[j++]; else { m->elems[m->nelem] = s1->elems[i++]; m->elems[m->nelem++].constraint |= s2->elems[j++].constraint; } while (i < s1->nelem) m->elems[m->nelem++] = s1->elems[i++]; while (j < s2->nelem) m->elems[m->nelem++] = s2->elems[j++]; } /* Delete a position from a set. */ static void delete (position p, position_set *s) { int i; for (i = 0; i < s->nelem; ++i) if (p.index == s->elems[i].index) break; if (i < s->nelem) for (--s->nelem; i < s->nelem; ++i) s->elems[i] = s->elems[i + 1]; } /* Find the index of the state corresponding to the given position set with the given preceding context, or create a new state if there is no such state. Newline and letter tell whether we got here on a newline or letter, respectively. */ static int state_index (struct dfa *d, position_set *s, int newline, int letter) { int hash = 0; int constraint; int i, j; newline = newline ? 1 : 0; letter = letter ? 1 : 0; for (i = 0; i < s->nelem; ++i) hash ^= s->elems[i].index + s->elems[i].constraint; /* Try to find a state that exactly matches the proposed one. */ for (i = 0; i < d->sindex; ++i) { if (hash != d->states[i].hash || s->nelem != d->states[i].elems.nelem || newline != d->states[i].newline || letter != d->states[i].letter) continue; for (j = 0; j < s->nelem; ++j) if (s->elems[j].constraint != d->states[i].elems.elems[j].constraint || s->elems[j].index != d->states[i].elems.elems[j].index) break; if (j == s->nelem) return i; } /* We'll have to create a new state. */ REALLOC_IF_NECESSARY(d->states, dfa_state, d->salloc, d->sindex); d->states[i].hash = hash; MALLOC(d->states[i].elems.elems, position, s->nelem); copy(s, &d->states[i].elems); d->states[i].newline = newline; d->states[i].letter = letter; d->states[i].backref = 0; d->states[i].constraint = 0; d->states[i].first_end = 0; for (j = 0; j < s->nelem; ++j) if (d->tokens[s->elems[j].index] < 0) { constraint = s->elems[j].constraint; if (SUCCEEDS_IN_CONTEXT(constraint, newline, 0, letter, 0) || SUCCEEDS_IN_CONTEXT(constraint, newline, 0, letter, 1) || SUCCEEDS_IN_CONTEXT(constraint, newline, 1, letter, 0) || SUCCEEDS_IN_CONTEXT(constraint, newline, 1, letter, 1)) d->states[i].constraint |= constraint; if (! d->states[i].first_end) d->states[i].first_end = d->tokens[s->elems[j].index]; } else if (d->tokens[s->elems[j].index] == BACKREF) { d->states[i].constraint = NO_CONSTRAINT; d->states[i].backref = 1; } ++d->sindex; return i; } /* Find the epsilon closure of a set of positions. If any position of the set contains a symbol that matches the empty string in some context, replace that position with the elements of its follow labeled with an appropriate constraint. Repeat exhaustively until no funny positions are left. S->elems must be large enough to hold the result. */ static void epsclosure (position_set *s, struct dfa *d) { int i, j; int *visited; position p, old; MALLOC(visited, int, d->tindex); for (i = 0; i < d->tindex; ++i) visited[i] = 0; for (i = 0; i < s->nelem; ++i) if (d->tokens[s->elems[i].index] >= NOTCHAR && d->tokens[s->elems[i].index] != BACKREF && d->tokens[s->elems[i].index] < CSET) { old = s->elems[i]; p.constraint = old.constraint; delete(s->elems[i], s); if (visited[old.index]) { --i; continue; } visited[old.index] = 1; switch (d->tokens[old.index]) { case BEGLINE: p.constraint &= BEGLINE_CONSTRAINT; break; case ENDLINE: p.constraint &= ENDLINE_CONSTRAINT; break; case BEGWORD: p.constraint &= BEGWORD_CONSTRAINT; break; case ENDWORD: p.constraint &= ENDWORD_CONSTRAINT; break; case LIMWORD: p.constraint &= LIMWORD_CONSTRAINT; break; case NOTLIMWORD: p.constraint &= NOTLIMWORD_CONSTRAINT; break; default: break; } for (j = 0; j < d->follows[old.index].nelem; ++j) { p.index = d->follows[old.index].elems[j].index; insert(p, s); } /* Force rescan to start at the beginning. */ i = -1; } free(visited); } /* Perform bottom-up analysis on the parse tree, computing various functions. Note that at this point, we're pretending constructs like \< are real characters rather than constraints on what can follow them. Nullable: A node is nullable if it is at the root of a regexp that can match the empty string. * EMPTY leaves are nullable. * No other leaf is nullable. * A QMARK or STAR node is nullable. * A PLUS node is nullable if its argument is nullable. * A CAT node is nullable if both its arguments are nullable. * An OR node is nullable if either argument is nullable. Firstpos: The firstpos of a node is the set of positions (nonempty leaves) that could correspond to the first character of a string matching the regexp rooted at the given node. * EMPTY leaves have empty firstpos. * The firstpos of a nonempty leaf is that leaf itself. * The firstpos of a QMARK, STAR, or PLUS node is the firstpos of its argument. * The firstpos of a CAT node is the firstpos of the left argument, union the firstpos of the right if the left argument is nullable. * The firstpos of an OR node is the union of firstpos of each argument. Lastpos: The lastpos of a node is the set of positions that could correspond to the last character of a string matching the regexp at the given node. * EMPTY leaves have empty lastpos. * The lastpos of a nonempty leaf is that leaf itself. * The lastpos of a QMARK, STAR, or PLUS node is the lastpos of its argument. * The lastpos of a CAT node is the lastpos of its right argument, union the lastpos of the left if the right argument is nullable. * The lastpos of an OR node is the union of the lastpos of each argument. Follow: The follow of a position is the set of positions that could correspond to the character following a character matching the node in a string matching the regexp. At this point we consider special symbols that match the empty string in some context to be just normal characters. Later, if we find that a special symbol is in a follow set, we will replace it with the elements of its follow, labeled with an appropriate constraint. * Every node in the firstpos of the argument of a STAR or PLUS node is in the follow of every node in the lastpos. * Every node in the firstpos of the second argument of a CAT node is in the follow of every node in the lastpos of the first argument. Because of the postfix representation of the parse tree, the depth-first analysis is conveniently done by a linear scan with the aid of a stack. Sets are stored as arrays of the elements, obeying a stack-like allocation scheme; the number of elements in each set deeper in the stack can be used to determine the address of a particular set's array. */ void dfaanalyze (struct dfa *d, int searchflag) { int *nullable; /* Nullable stack. */ int *nfirstpos; /* Element count stack for firstpos sets. */ position *firstpos; /* Array where firstpos elements are stored. */ int *nlastpos; /* Element count stack for lastpos sets. */ position *lastpos; /* Array where lastpos elements are stored. */ int *nalloc; /* Sizes of arrays allocated to follow sets. */ position_set tmp; /* Temporary set for merging sets. */ position_set merged; /* Result of merging sets. */ int wants_newline; /* True if some position wants newline info. */ int *o_nullable; int *o_nfirst, *o_nlast; position *o_firstpos, *o_lastpos; int i, j; position *pos; #ifdef DEBUG fprintf(stderr, "dfaanalyze:\n"); for (i = 0; i < d->tindex; ++i) { fprintf(stderr, " %d:", i); prtok(d->tokens[i]); } putc('\n', stderr); #endif d->searchflag = searchflag; MALLOC(nullable, int, d->depth); o_nullable = nullable; MALLOC(nfirstpos, int, d->depth); o_nfirst = nfirstpos; MALLOC(firstpos, position, d->nleaves); o_firstpos = firstpos, firstpos += d->nleaves; MALLOC(nlastpos, int, d->depth); o_nlast = nlastpos; MALLOC(lastpos, position, d->nleaves); o_lastpos = lastpos, lastpos += d->nleaves; MALLOC(nalloc, int, d->tindex); for (i = 0; i < d->tindex; ++i) nalloc[i] = 0; MALLOC(merged.elems, position, d->nleaves); CALLOC(d->follows, position_set, d->tindex); for (i = 0; i < d->tindex; ++i) #ifdef DEBUG { /* Nonsyntactic #ifdef goo... */ #endif switch (d->tokens[i]) { case EMPTY: /* The empty set is nullable. */ *nullable++ = 1; /* The firstpos and lastpos of the empty leaf are both empty. */ *nfirstpos++ = *nlastpos++ = 0; break; case STAR: case PLUS: /* Every element in the firstpos of the argument is in the follow of every element in the lastpos. */ tmp.nelem = nfirstpos[-1]; tmp.elems = firstpos; pos = lastpos; for (j = 0; j < nlastpos[-1]; ++j) { merge(&tmp, &d->follows[pos[j].index], &merged); REALLOC_IF_NECESSARY(d->follows[pos[j].index].elems, position, nalloc[pos[j].index], merged.nelem - 1); copy(&merged, &d->follows[pos[j].index]); } case QMARK: /* A QMARK or STAR node is automatically nullable. */ if (d->tokens[i] != PLUS) nullable[-1] = 1; break; case CAT: /* Every element in the firstpos of the second argument is in the follow of every element in the lastpos of the first argument. */ tmp.nelem = nfirstpos[-1]; tmp.elems = firstpos; pos = lastpos + nlastpos[-1]; for (j = 0; j < nlastpos[-2]; ++j) { merge(&tmp, &d->follows[pos[j].index], &merged); REALLOC_IF_NECESSARY(d->follows[pos[j].index].elems, position, nalloc[pos[j].index], merged.nelem - 1); copy(&merged, &d->follows[pos[j].index]); } /* The firstpos of a CAT node is the firstpos of the first argument, union that of the second argument if the first is nullable. */ if (nullable[-2]) nfirstpos[-2] += nfirstpos[-1]; else firstpos += nfirstpos[-1]; --nfirstpos; /* The lastpos of a CAT node is the lastpos of the second argument, union that of the first argument if the second is nullable. */ if (nullable[-1]) nlastpos[-2] += nlastpos[-1]; else { pos = lastpos + nlastpos[-2]; for (j = nlastpos[-1] - 1; j >= 0; --j) pos[j] = lastpos[j]; lastpos += nlastpos[-2]; nlastpos[-2] = nlastpos[-1]; } --nlastpos; /* A CAT node is nullable if both arguments are nullable. */ nullable[-2] = nullable[-1] && nullable[-2]; --nullable; break; case OR: case ORTOP: /* The firstpos is the union of the firstpos of each argument. */ nfirstpos[-2] += nfirstpos[-1]; --nfirstpos; /* The lastpos is the union of the lastpos of each argument. */ nlastpos[-2] += nlastpos[-1]; --nlastpos; /* An OR node is nullable if either argument is nullable. */ nullable[-2] = nullable[-1] || nullable[-2]; --nullable; break; default: /* Anything else is a nonempty position. (Note that special constructs like \< are treated as nonempty strings here; an "epsilon closure" effectively makes them nullable later. Backreferences have to get a real position so we can detect transitions on them later. But they are nullable. */ *nullable++ = d->tokens[i] == BACKREF; /* This position is in its own firstpos and lastpos. */ *nfirstpos++ = *nlastpos++ = 1; --firstpos, --lastpos; firstpos->index = lastpos->index = i; firstpos->constraint = lastpos->constraint = NO_CONSTRAINT; /* Allocate the follow set for this position. */ nalloc[i] = 1; MALLOC(d->follows[i].elems, position, nalloc[i]); break; } #ifdef DEBUG /* ... balance the above nonsyntactic #ifdef goo... */ fprintf(stderr, "node %d:", i); prtok(d->tokens[i]); putc('\n', stderr); fprintf(stderr, nullable[-1] ? " nullable: yes\n" : " nullable: no\n"); fprintf(stderr, " firstpos:"); for (j = nfirstpos[-1] - 1; j >= 0; --j) { fprintf(stderr, " %d:", firstpos[j].index); prtok(d->tokens[firstpos[j].index]); } fprintf(stderr, "\n lastpos:"); for (j = nlastpos[-1] - 1; j >= 0; --j) { fprintf(stderr, " %d:", lastpos[j].index); prtok(d->tokens[lastpos[j].index]); } putc('\n', stderr); } #endif /* For each follow set that is the follow set of a real position, replace it with its epsilon closure. */ for (i = 0; i < d->tindex; ++i) if (d->tokens[i] < NOTCHAR || d->tokens[i] == BACKREF || d->tokens[i] >= CSET) { #ifdef DEBUG fprintf(stderr, "follows(%d:", i); prtok(d->tokens[i]); fprintf(stderr, "):"); for (j = d->follows[i].nelem - 1; j >= 0; --j) { fprintf(stderr, " %d:", d->follows[i].elems[j].index); prtok(d->tokens[d->follows[i].elems[j].index]); } putc('\n', stderr); #endif copy(&d->follows[i], &merged); epsclosure(&merged, d); if (d->follows[i].nelem < merged.nelem) REALLOC(d->follows[i].elems, position, merged.nelem); copy(&merged, &d->follows[i]); } /* Get the epsilon closure of the firstpos of the regexp. The result will be the set of positions of state 0. */ merged.nelem = 0; for (i = 0; i < nfirstpos[-1]; ++i) insert(firstpos[i], &merged); epsclosure(&merged, d); /* Check if any of the positions of state 0 will want newline context. */ wants_newline = 0; for (i = 0; i < merged.nelem; ++i) if (PREV_NEWLINE_DEPENDENT(merged.elems[i].constraint)) wants_newline = 1; /* Build the initial state. */ d->salloc = 1; d->sindex = 0; MALLOC(d->states, dfa_state, d->salloc); state_index(d, &merged, wants_newline, 0); free(o_nullable); free(o_nfirst); free(o_firstpos); free(o_nlast); free(o_lastpos); free(nalloc); free(merged.elems); } /* Find, for each character, the transition out of state s of d, and store it in the appropriate slot of trans. We divide the positions of s into groups (positions can appear in more than one group). Each group is labeled with a set of characters that every position in the group matches (taking into account, if necessary, preceding context information of s). For each group, find the union of the its elements' follows. This set is the set of positions of the new state. For each character in the group's label, set the transition on this character to be to a state corresponding to the set's positions, and its associated backward context information, if necessary. If we are building a searching matcher, we include the positions of state 0 in every state. The collection of groups is constructed by building an equivalence-class partition of the positions of s. For each position, find the set of characters C that it matches. Eliminate any characters from C that fail on grounds of backward context. Search through the groups, looking for a group whose label L has nonempty intersection with C. If L - C is nonempty, create a new group labeled L - C and having the same positions as the current group, and set L to the intersection of L and C. Insert the position in this group, set C = C - L, and resume scanning. If after comparing with every group there are characters remaining in C, create a new group labeled with the characters of C and insert this position in that group. */ void dfastate (int s, struct dfa *d, int trans[]) { position_set grps[NOTCHAR]; /* As many as will ever be needed. */ charclass labels[NOTCHAR]; /* Labels corresponding to the groups. */ int ngrps = 0; /* Number of groups actually used. */ position pos; /* Current position being considered. */ charclass matches; /* Set of matching characters. */ int matchesf; /* True if matches is nonempty. */ charclass intersect; /* Intersection with some label set. */ int intersectf; /* True if intersect is nonempty. */ charclass leftovers; /* Stuff in the label that didn't match. */ int leftoversf; /* True if leftovers is nonempty. */ static charclass letters; /* Set of characters considered letters. */ static charclass newline; /* Set of characters that aren't newline. */ position_set follows; /* Union of the follows of some group. */ position_set tmp; /* Temporary space for merging sets. */ int state; /* New state. */ int wants_newline; /* New state wants to know newline context. */ int state_newline; /* New state on a newline transition. */ int wants_letter; /* New state wants to know letter context. */ int state_letter; /* New state on a letter transition. */ static int initialized; /* Flag for static initialization. */ int i, j, k; /* Initialize the set of letters, if necessary. */ if (! initialized) { initialized = 1; for (i = 0; i < NOTCHAR; ++i) if (IS_WORD_CONSTITUENT(i)) setbit(i, letters); setbit(eolbyte, newline); } zeroset(matches); for (i = 0; i < d->states[s].elems.nelem; ++i) { pos = d->states[s].elems.elems[i]; if (d->tokens[pos.index] >= 0 && d->tokens[pos.index] < NOTCHAR) setbit(d->tokens[pos.index], matches); else if (d->tokens[pos.index] >= CSET) copyset(d->charclasses[d->tokens[pos.index] - CSET], matches); else continue; /* Some characters may need to be eliminated from matches because they fail in the current context. */ if (pos.constraint != 0xFF) { if (! MATCHES_NEWLINE_CONTEXT(pos.constraint, d->states[s].newline, 1)) clrbit(eolbyte, matches); if (! MATCHES_NEWLINE_CONTEXT(pos.constraint, d->states[s].newline, 0)) for (j = 0; j < CHARCLASS_INTS; ++j) matches[j] &= newline[j]; if (! MATCHES_LETTER_CONTEXT(pos.constraint, d->states[s].letter, 1)) for (j = 0; j < CHARCLASS_INTS; ++j) matches[j] &= ~letters[j]; if (! MATCHES_LETTER_CONTEXT(pos.constraint, d->states[s].letter, 0)) for (j = 0; j < CHARCLASS_INTS; ++j) matches[j] &= letters[j]; /* If there are no characters left, there's no point in going on. */ for (j = 0; j < CHARCLASS_INTS && !matches[j]; ++j) continue; if (j == CHARCLASS_INTS) continue; } for (j = 0; j < ngrps; ++j) { /* If matches contains a single character only, and the current group's label doesn't contain that character, go on to the next group. */ if (d->tokens[pos.index] >= 0 && d->tokens[pos.index] < NOTCHAR && !tstbit(d->tokens[pos.index], labels[j])) continue; /* Check if this group's label has a nonempty intersection with matches. */ intersectf = 0; for (k = 0; k < CHARCLASS_INTS; ++k) (intersect[k] = matches[k] & labels[j][k]) ? (intersectf = 1) : 0; if (! intersectf) continue; /* It does; now find the set differences both ways. */ leftoversf = matchesf = 0; for (k = 0; k < CHARCLASS_INTS; ++k) { /* Even an optimizing compiler can't know this for sure. */ int match = matches[k], label = labels[j][k]; (leftovers[k] = ~match & label) ? (leftoversf = 1) : 0; (matches[k] = match & ~label) ? (matchesf = 1) : 0; } /* If there were leftovers, create a new group labeled with them. */ if (leftoversf) { copyset(leftovers, labels[ngrps]); copyset(intersect, labels[j]); MALLOC(grps[ngrps].elems, position, d->nleaves); copy(&grps[j], &grps[ngrps]); ++ngrps; } /* Put the position in the current group. Note that there is no reason to call insert() here. */ grps[j].elems[grps[j].nelem++] = pos; /* If every character matching the current position has been accounted for, we're done. */ if (! matchesf) break; } /* If we've passed the last group, and there are still characters unaccounted for, then we'll have to create a new group. */ if (j == ngrps) { copyset(matches, labels[ngrps]); zeroset(matches); MALLOC(grps[ngrps].elems, position, d->nleaves); grps[ngrps].nelem = 1; grps[ngrps].elems[0] = pos; ++ngrps; } } MALLOC(follows.elems, position, d->nleaves); MALLOC(tmp.elems, position, d->nleaves); /* If we are a searching matcher, the default transition is to a state containing the positions of state 0, otherwise the default transition is to fail miserably. */ if (d->searchflag) { wants_newline = 0; wants_letter = 0; for (i = 0; i < d->states[0].elems.nelem; ++i) { if (PREV_NEWLINE_DEPENDENT(d->states[0].elems.elems[i].constraint)) wants_newline = 1; if (PREV_LETTER_DEPENDENT(d->states[0].elems.elems[i].constraint)) wants_letter = 1; } copy(&d->states[0].elems, &follows); state = state_index(d, &follows, 0, 0); if (wants_newline) state_newline = state_index(d, &follows, 1, 0); else state_newline = state; if (wants_letter) state_letter = state_index(d, &follows, 0, 1); else state_letter = state; for (i = 0; i < NOTCHAR; ++i) trans[i] = (IS_WORD_CONSTITUENT(i)) ? state_letter : state; trans[eolbyte] = state_newline; } else for (i = 0; i < NOTCHAR; ++i) trans[i] = -1; for (i = 0; i < ngrps; ++i) { follows.nelem = 0; /* Find the union of the follows of the positions of the group. This is a hideously inefficient loop. Fix it someday. */ for (j = 0; j < grps[i].nelem; ++j) for (k = 0; k < d->follows[grps[i].elems[j].index].nelem; ++k) insert(d->follows[grps[i].elems[j].index].elems[k], &follows); /* If we are building a searching matcher, throw in the positions of state 0 as well. */ if (d->searchflag) for (j = 0; j < d->states[0].elems.nelem; ++j) insert(d->states[0].elems.elems[j], &follows); /* Find out if the new state will want any context information. */ wants_newline = 0; if (tstbit(eolbyte, labels[i])) for (j = 0; j < follows.nelem; ++j) if (PREV_NEWLINE_DEPENDENT(follows.elems[j].constraint)) wants_newline = 1; wants_letter = 0; for (j = 0; j < CHARCLASS_INTS; ++j) if (labels[i][j] & letters[j]) break; if (j < CHARCLASS_INTS) for (j = 0; j < follows.nelem; ++j) if (PREV_LETTER_DEPENDENT(follows.elems[j].constraint)) wants_letter = 1; /* Find the state(s) corresponding to the union of the follows. */ state = state_index(d, &follows, 0, 0); if (wants_newline) state_newline = state_index(d, &follows, 1, 0); else state_newline = state; if (wants_letter) state_letter = state_index(d, &follows, 0, 1); else state_letter = state; /* Set the transitions for each character in the current label. */ for (j = 0; j < CHARCLASS_INTS; ++j) for (k = 0; k < INTBITS; ++k) if (labels[i][j] & 1 << k) { int c = j * INTBITS + k; if (c == eolbyte) trans[c] = state_newline; else if (IS_WORD_CONSTITUENT(c)) trans[c] = state_letter; else if (c < NOTCHAR) trans[c] = state; } } for (i = 0; i < ngrps; ++i) free(grps[i].elems); free(follows.elems); free(tmp.elems); } /* Some routines for manipulating a compiled dfa's transition tables. Each state may or may not have a transition table; if it does, and it is a non-accepting state, then d->trans[state] points to its table. If it is an accepting state then d->fails[state] points to its table. If it has no table at all, then d->trans[state] is NULL. TODO: Improve this comment, get rid of the unnecessary redundancy. */ static void build_state (int s, struct dfa *d) { int *trans; /* The new transition table. */ int i; /* Set an upper limit on the number of transition tables that will ever exist at once. 1024 is arbitrary. The idea is that the frequently used transition tables will be quickly rebuilt, whereas the ones that were only needed once or twice will be cleared away. */ if (d->trcount >= 1024) { for (i = 0; i < d->tralloc; ++i) if (d->trans[i]) { free((ptr_t) d->trans[i]); d->trans[i] = NULL; } else if (d->fails[i]) { free((ptr_t) d->fails[i]); d->fails[i] = NULL; } d->trcount = 0; } ++d->trcount; /* Set up the success bits for this state. */ d->success[s] = 0; if (ACCEPTS_IN_CONTEXT(d->states[s].newline, 1, d->states[s].letter, 0, s, *d)) d->success[s] |= 4; if (ACCEPTS_IN_CONTEXT(d->states[s].newline, 0, d->states[s].letter, 1, s, *d)) d->success[s] |= 2; if (ACCEPTS_IN_CONTEXT(d->states[s].newline, 0, d->states[s].letter, 0, s, *d)) d->success[s] |= 1; MALLOC(trans, int, NOTCHAR); dfastate(s, d, trans); /* Now go through the new transition table, and make sure that the trans and fail arrays are allocated large enough to hold a pointer for the largest state mentioned in the table. */ for (i = 0; i < NOTCHAR; ++i) if (trans[i] >= d->tralloc) { int oldalloc = d->tralloc; while (trans[i] >= d->tralloc) d->tralloc *= 2; REALLOC(d->realtrans, int *, d->tralloc + 1); d->trans = d->realtrans + 1; REALLOC(d->fails, int *, d->tralloc); REALLOC(d->success, int, d->tralloc); REALLOC(d->newlines, int, d->tralloc); while (oldalloc < d->tralloc) { d->trans[oldalloc] = NULL; d->fails[oldalloc++] = NULL; } } /* Keep the newline transition in a special place so we can use it as a sentinel. */ d->newlines[s] = trans[eolbyte]; trans[eolbyte] = -1; if (ACCEPTING(s, *d)) d->fails[s] = trans; else d->trans[s] = trans; } static void build_state_zero (struct dfa *d) { d->tralloc = 1; d->trcount = 0; CALLOC(d->realtrans, int *, d->tralloc + 1); d->trans = d->realtrans + 1; CALLOC(d->fails, int *, d->tralloc); MALLOC(d->success, int, d->tralloc); MALLOC(d->newlines, int, d->tralloc); build_state(0, d); } /* Search through a buffer looking for a match to the given struct dfa. Find the first occurrence of a string matching the regexp in the buffer, and the shortest possible version thereof. Return a pointer to the first character after the match, or NULL if none is found. Begin points to the beginning of the buffer, and end points to the first character after its end. We store a newline in *end to act as a sentinel, so end had better point somewhere valid. Newline is a flag indicating whether to allow newlines to be in the matching string. If count is non- NULL it points to a place we're supposed to increment every time we see a newline. Finally, if backref is non-NULL it points to a place where we're supposed to store a 1 if backreferencing happened and the match needs to be verified by a backtracking matcher. Otherwise we store a 0 in *backref. */ char * dfaexec (struct dfa *d, char *begin, char *end, int newline, int *count, int *backref) { register int s, s1, tmp; /* Current state. */ register unsigned char *p; /* Current input character. */ register int **trans, *t; /* Copy of d->trans so it can be optimized into a register. */ register unsigned char eol = eolbyte; /* Likewise for eolbyte. */ static int sbit[NOTCHAR]; /* Table for anding with d->success. */ static int sbit_init; if (! sbit_init) { int i; sbit_init = 1; for (i = 0; i < NOTCHAR; ++i) sbit[i] = (IS_WORD_CONSTITUENT(i)) ? 2 : 1; sbit[eol] = 4; } if (! d->tralloc) build_state_zero(d); s = s1 = 0; p = (unsigned char *) begin; trans = d->trans; *end = eol; for (;;) { while ((t = trans[s]) != 0) { /* hand-optimized loop */ s1 = t[*p++]; if ((t = trans[s1]) == 0) { tmp = s ; s = s1 ; s1 = tmp ; /* swap */ break; } s = t[*p++]; } if (s >= 0 && p <= (unsigned char *) end && d->fails[s]) { if (d->success[s] & sbit[*p]) { if (backref) *backref = (d->states[s].backref != 0); return (char *) p; } s1 = s; s = d->fails[s][*p++]; continue; } /* If the previous character was a newline, count it. */ if (count && (char *) p <= end && p[-1] == eol) ++*count; /* Check if we've run off the end of the buffer. */ if ((char *) p > end) return NULL; if (s >= 0) { build_state(s, d); trans = d->trans; continue; } if (p[-1] == eol && newline) { s = d->newlines[s1]; continue; } s = 0; } } /* Initialize the components of a dfa that the other routines don't initialize for themselves. */ void dfainit (struct dfa *d) { d->calloc = 1; MALLOC(d->charclasses, charclass, d->calloc); d->cindex = 0; d->talloc = 1; MALLOC(d->tokens, token, d->talloc); d->tindex = d->depth = d->nleaves = d->nregexps = 0; d->searchflag = 0; d->tralloc = 0; d->musts = 0; } /* Parse and analyze a single string of the given length. */ void dfacomp (char *s, size_t len, struct dfa *d, int searchflag) { if (case_fold) /* dummy folding in service of dfamust() */ { char *lcopy; int i; lcopy = xmalloc(len); if (!lcopy) dfaerror(_("out of memory")); /* This is a kludge. */ case_fold = 0; for (i = 0; i < len; ++i) if (ISUPPER ((unsigned char) s[i])) lcopy[i] = tolower ((unsigned char) s[i]); else lcopy[i] = s[i]; dfainit(d); dfaparse(lcopy, len, d); free(lcopy); dfamust(d); d->cindex = d->tindex = d->depth = d->nleaves = d->nregexps = 0; case_fold = 1; dfaparse(s, len, d); dfaanalyze(d, searchflag); } else { dfainit(d); dfaparse(s, len, d); dfamust(d); dfaanalyze(d, searchflag); } } /* Free the storage held by the components of a dfa. */ void dfafree (struct dfa *d) { int i; struct dfamust *dm, *ndm; free((ptr_t) d->charclasses); free((ptr_t) d->tokens); for (i = 0; i < d->sindex; ++i) free((ptr_t) d->states[i].elems.elems); free((ptr_t) d->states); for (i = 0; i < d->tindex; ++i) if (d->follows[i].elems) free((ptr_t) d->follows[i].elems); free((ptr_t) d->follows); for (i = 0; i < d->tralloc; ++i) if (d->trans[i]) free((ptr_t) d->trans[i]); else if (d->fails[i]) free((ptr_t) d->fails[i]); if (d->realtrans) free((ptr_t) d->realtrans); if (d->fails) free((ptr_t) d->fails); if (d->newlines) free((ptr_t) d->newlines); if (d->success) free((ptr_t) d->success); for (dm = d->musts; dm; dm = ndm) { ndm = dm->next; free(dm->must); free((ptr_t) dm); } } /* Having found the postfix representation of the regular expression, try to find a long sequence of characters that must appear in any line containing the r.e. Finding a "longest" sequence is beyond the scope here; we take an easy way out and hope for the best. (Take "(ab|a)b"--please.) We do a bottom-up calculation of sequences of characters that must appear in matches of r.e.'s represented by trees rooted at the nodes of the postfix representation: sequences that must appear at the left of the match ("left") sequences that must appear at the right of the match ("right") lists of sequences that must appear somewhere in the match ("in") sequences that must constitute the match ("is") When we get to the root of the tree, we use one of the longest of its calculated "in" sequences as our answer. The sequence we find is returned in d->must (where "d" is the single argument passed to "dfamust"); the length of the sequence is returned in d->mustn. The sequences calculated for the various types of node (in pseudo ANSI c) are shown below. "p" is the operand of unary operators (and the left-hand operand of binary operators); "q" is the right-hand operand of binary operators. "ZERO" means "a zero-length sequence" below. Type left right is in ---- ---- ----- -- -- char c # c # c # c # c CSET ZERO ZERO ZERO ZERO STAR ZERO ZERO ZERO ZERO QMARK ZERO ZERO ZERO ZERO PLUS p->left p->right ZERO p->in CAT (p->is==ZERO)? (q->is==ZERO)? (p->is!=ZERO && p->in plus p->left : q->right : q->is!=ZERO) ? q->in plus p->is##q->left p->right##q->is p->is##q->is : p->right##q->left ZERO OR longest common longest common (do p->is and substrings common to leading trailing q->is have same p->in and q->in (sub)sequence (sub)sequence length and of p->left of p->right content) ? and q->left and q->right p->is : NULL If there's anything else we recognize in the tree, all four sequences get set to zero-length sequences. If there's something we don't recognize in the tree, we just return a zero-length sequence. Break ties in favor of infrequent letters (choosing 'zzz' in preference to 'aaa')? And. . .is it here or someplace that we might ponder "optimizations" such as egrep 'psi|epsilon' -> egrep 'psi' egrep 'pepsi|epsilon' -> egrep 'epsi' (Yes, we now find "epsi" as a "string that must occur", but we might also simplify the *entire* r.e. being sought) grep '[c]' -> grep 'c' grep '(ab|a)b' -> grep 'ab' grep 'ab*' -> grep 'a' grep 'a*b' -> grep 'b' There are several issues: Is optimization easy (enough)? Does optimization actually accomplish anything, or is the automaton you get from "psi|epsilon" (for example) the same as the one you get from "psi" (for example)? Are optimizable r.e.'s likely to be used in real-life situations (something like 'ab*' is probably unlikely; something like is 'psi|epsilon' is likelier)? */ static char * icatalloc (char *old, char *new) { char *result; size_t oldsize, newsize; newsize = (new == NULL) ? 0 : strlen(new); if (old == NULL) oldsize = 0; else if (newsize == 0) return old; else oldsize = strlen(old); if (old == NULL) result = (char *) xmalloc(newsize + 1); else result = (char *) realloc((void *) old, oldsize + newsize + 1); if (result != NULL && new != NULL) (void) strcpy(result + oldsize, new); return result; } static char * icpyalloc (char *string) { return icatalloc((char *) NULL, string); } static char * istrstr (char *lookin, char *lookfor) { char *cp; size_t len; len = strlen(lookfor); for (cp = lookin; *cp != '\0'; ++cp) if (strncmp(cp, lookfor, len) == 0) return cp; return NULL; } static void ifree (char *cp) { if (cp != NULL) free(cp); } static void freelist (char **cpp) { int i; if (cpp == NULL) return; for (i = 0; cpp[i] != NULL; ++i) { free(cpp[i]); cpp[i] = NULL; } } static char ** enlist (char **cpp, char *new, size_t len) { int i, j; if (cpp == NULL) return NULL; if ((new = icpyalloc(new)) == NULL) { freelist(cpp); return NULL; } new[len] = '\0'; /* Is there already something in the list that's new (or longer)? */ for (i = 0; cpp[i] != NULL; ++i) if (istrstr(cpp[i], new) != NULL) { free(new); return cpp; } /* Eliminate any obsoleted strings. */ j = 0; while (cpp[j] != NULL) if (istrstr(new, cpp[j]) == NULL) ++j; else { free(cpp[j]); if (--i == j) break; cpp[j] = cpp[i]; cpp[i] = NULL; } /* Add the new string. */ cpp = (char **) realloc((char *) cpp, (i + 2) * sizeof *cpp); if (cpp == NULL) return NULL; cpp[i] = new; cpp[i + 1] = NULL; return cpp; } /* Given pointers to two strings, return a pointer to an allocated list of their distinct common substrings. Return NULL if something seems wild. */ static char ** comsubs (char *left, char *right) { char **cpp; char *lcp; char *rcp; size_t i, len; if (left == NULL || right == NULL) return NULL; cpp = (char **) xmalloc(sizeof *cpp); if (cpp == NULL) return NULL; cpp[0] = NULL; for (lcp = left; *lcp != '\0'; ++lcp) { len = 0; rcp = index(right, *lcp); while (rcp != NULL) { for (i = 1; lcp[i] != '\0' && lcp[i] == rcp[i]; ++i) continue; if (i > len) len = i; rcp = index(rcp + 1, *lcp); } if (len == 0) continue; if ((cpp = enlist(cpp, lcp, len)) == NULL) break; } return cpp; } static char ** addlists (char **old, char **new) { int i; if (old == NULL || new == NULL) return NULL; for (i = 0; new[i] != NULL; ++i) { old = enlist(old, new[i], strlen(new[i])); if (old == NULL) break; } return old; } /* Given two lists of substrings, return a new list giving substrings common to both. */ static char ** inboth (char **left, char **right) { char **both; char **temp; int lnum, rnum; if (left == NULL || right == NULL) return NULL; both = (char **) xmalloc(sizeof *both); if (both == NULL) return NULL; both[0] = NULL; for (lnum = 0; left[lnum] != NULL; ++lnum) { for (rnum = 0; right[rnum] != NULL; ++rnum) { temp = comsubs(left[lnum], right[rnum]); if (temp == NULL) { freelist(both); return NULL; } both = addlists(both, temp); freelist(temp); free(temp); if (both == NULL) return NULL; } } return both; } typedef struct { char **in; char *left; char *right; char *is; } must; static void resetmust (must *mp) { mp->left[0] = mp->right[0] = mp->is[0] = '\0'; freelist(mp->in); } static void dfamust (struct dfa *dfa) { must *musts; must *mp; char *result; int ri; int i; int exact; token t; static must must0; struct dfamust *dm; static char empty_string[] = ""; result = empty_string; exact = 0; musts = (must *) xmalloc((dfa->tindex + 1) * sizeof *musts); if (musts == NULL) return; mp = musts; for (i = 0; i <= dfa->tindex; ++i) mp[i] = must0; for (i = 0; i <= dfa->tindex; ++i) { mp[i].in = (char **) xmalloc(sizeof *mp[i].in); mp[i].left = xmalloc(2); mp[i].right = xmalloc(2); mp[i].is = xmalloc(2); if (mp[i].in == NULL || mp[i].left == NULL || mp[i].right == NULL || mp[i].is == NULL) goto done; mp[i].left[0] = mp[i].right[0] = mp[i].is[0] = '\0'; mp[i].in[0] = NULL; } #ifdef DEBUG fprintf(stderr, "dfamust:\n"); for (i = 0; i < dfa->tindex; ++i) { fprintf(stderr, " %d:", i); prtok(dfa->tokens[i]); } putc('\n', stderr); #endif for (ri = 0; ri < dfa->tindex; ++ri) { switch (t = dfa->tokens[ri]) { case LPAREN: case RPAREN: goto done; /* "cannot happen" */ case EMPTY: case BEGLINE: case ENDLINE: case BEGWORD: case ENDWORD: case LIMWORD: case NOTLIMWORD: case BACKREF: resetmust(mp); break; case STAR: case QMARK: if (mp <= musts) goto done; /* "cannot happen" */ --mp; resetmust(mp); break; case OR: case ORTOP: if (mp < &musts[2]) goto done; /* "cannot happen" */ { char **new; must *lmp; must *rmp; int j, ln, rn, n; rmp = --mp; lmp = --mp; /* Guaranteed to be. Unlikely, but. . . */ if (strcmp(lmp->is, rmp->is) != 0) lmp->is[0] = '\0'; /* Left side--easy */ i = 0; while (lmp->left[i] != '\0' && lmp->left[i] == rmp->left[i]) ++i; lmp->left[i] = '\0'; /* Right side */ ln = strlen(lmp->right); rn = strlen(rmp->right); n = ln; if (n > rn) n = rn; for (i = 0; i < n; ++i) if (lmp->right[ln - i - 1] != rmp->right[rn - i - 1]) break; for (j = 0; j < i; ++j) lmp->right[j] = lmp->right[(ln - i) + j]; lmp->right[j] = '\0'; new = inboth(lmp->in, rmp->in); if (new == NULL) goto done; freelist(lmp->in); free((char *) lmp->in); lmp->in = new; } break; case PLUS: if (mp <= musts) goto done; /* "cannot happen" */ --mp; mp->is[0] = '\0'; break; case END: if (mp != &musts[1]) goto done; /* "cannot happen" */ for (i = 0; musts[0].in[i] != NULL; ++i) if (strlen(musts[0].in[i]) > strlen(result)) result = musts[0].in[i]; if (strcmp(result, musts[0].is) == 0) exact = 1; goto done; case CAT: if (mp < &musts[2]) goto done; /* "cannot happen" */ { must *lmp; must *rmp; rmp = --mp; lmp = --mp; /* In. Everything in left, plus everything in right, plus catenation of left's right and right's left. */ lmp->in = addlists(lmp->in, rmp->in); if (lmp->in == NULL) goto done; if (lmp->right[0] != '\0' && rmp->left[0] != '\0') { char *tp; tp = icpyalloc(lmp->right); if (tp == NULL) goto done; tp = icatalloc(tp, rmp->left); if (tp == NULL) goto done; lmp->in = enlist(lmp->in, tp, strlen(tp)); free(tp); if (lmp->in == NULL) goto done; } /* Left-hand */ if (lmp->is[0] != '\0') { lmp->left = icatalloc(lmp->left, rmp->left); if (lmp->left == NULL) goto done; } /* Right-hand */ if (rmp->is[0] == '\0') lmp->right[0] = '\0'; lmp->right = icatalloc(lmp->right, rmp->right); if (lmp->right == NULL) goto done; /* Guaranteed to be */ if (lmp->is[0] != '\0' && rmp->is[0] != '\0') { lmp->is = icatalloc(lmp->is, rmp->is); if (lmp->is == NULL) goto done; } else lmp->is[0] = '\0'; } break; default: if (t < END) { /* "cannot happen" */ goto done; } else if (t == '\0') { /* not on *my* shift */ goto done; } else if (t >= CSET) { /* easy enough */ resetmust(mp); } else { /* plain character */ resetmust(mp); mp->is[0] = mp->left[0] = mp->right[0] = t; mp->is[1] = mp->left[1] = mp->right[1] = '\0'; mp->in = enlist(mp->in, mp->is, (size_t)1); if (mp->in == NULL) goto done; } break; } #ifdef DEBUG fprintf(stderr, " node: %d:", ri); prtok(dfa->tokens[ri]); fprintf(stderr, "\n in:"); for (i = 0; mp->in[i]; ++i) fprintf(stderr, " \"%s\"", mp->in[i]); fprintf(stderr, "\n is: \"%s\"\n", mp->is); fprintf(stderr, " left: \"%s\"\n", mp->left); fprintf(stderr, " right: \"%s\"\n", mp->right); #endif ++mp; } done: if (strlen(result)) { dm = (struct dfamust *) xmalloc(sizeof (struct dfamust)); dm->exact = exact; dm->must = xmalloc(strlen(result) + 1); strcpy(dm->must, result); dm->next = dfa->musts; dfa->musts = dm; } mp = musts; for (i = 0; i <= dfa->tindex; ++i) { freelist(mp[i].in); ifree((char *) mp[i].in); ifree(mp[i].left); ifree(mp[i].right); ifree(mp[i].is); } free((char *) mp); } argus-clients-2.0.6.fixes.1/ragrep/dfa.h0000664000076600007660000003505407310146216013444 /* dfa.h - declarations for GNU deterministic regexp compiler Copyright (C) 1988, 1998 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* Written June, 1988 by Mike Haertel */ /* FIXME: 2. We should not export so much of the DFA internals. In addition to clobbering modularity, we eat up valuable name space. */ # undef PARAMS #if __STDC__ # ifndef _PTR_T # define _PTR_T typedef void * ptr_t; # endif # define PARAMS(x) x #else # ifndef _PTR_T # define _PTR_T typedef char * ptr_t; # endif # define PARAMS(x) () #endif /* Number of bits in an unsigned char. */ #ifndef CHARBITS #define CHARBITS 8 #endif /* First integer value that is greater than any character code. */ #define NOTCHAR (1 << CHARBITS) /* INTBITS need not be exact, just a lower bound. */ #ifndef INTBITS #define INTBITS (CHARBITS * sizeof (int)) #endif /* Number of ints required to hold a bit for every character. */ #define CHARCLASS_INTS ((NOTCHAR + INTBITS - 1) / INTBITS) /* Sets of unsigned characters are stored as bit vectors in arrays of ints. */ typedef int charclass[CHARCLASS_INTS]; /* The regexp is parsed into an array of tokens in postfix form. Some tokens are operators and others are terminal symbols. Most (but not all) of these codes are returned by the lexical analyzer. */ typedef enum { END = -1, /* END is a terminal symbol that matches the end of input; any value of END or less in the parse tree is such a symbol. Accepting states of the DFA are those that would have a transition on END. */ /* Ordinary character values are terminal symbols that match themselves. */ EMPTY = NOTCHAR, /* EMPTY is a terminal symbol that matches the empty string. */ BACKREF, /* BACKREF is generated by \; it it not completely handled. If the scanner detects a transition on backref, it returns a kind of "semi-success" indicating that the match will have to be verified with a backtracking matcher. */ BEGLINE, /* BEGLINE is a terminal symbol that matches the empty string if it is at the beginning of a line. */ ENDLINE, /* ENDLINE is a terminal symbol that matches the empty string if it is at the end of a line. */ BEGWORD, /* BEGWORD is a terminal symbol that matches the empty string if it is at the beginning of a word. */ ENDWORD, /* ENDWORD is a terminal symbol that matches the empty string if it is at the end of a word. */ LIMWORD, /* LIMWORD is a terminal symbol that matches the empty string if it is at the beginning or the end of a word. */ NOTLIMWORD, /* NOTLIMWORD is a terminal symbol that matches the empty string if it is not at the beginning or end of a word. */ QMARK, /* QMARK is an operator of one argument that matches zero or one occurences of its argument. */ STAR, /* STAR is an operator of one argument that matches the Kleene closure (zero or more occurrences) of its argument. */ PLUS, /* PLUS is an operator of one argument that matches the positive closure (one or more occurrences) of its argument. */ REPMN, /* REPMN is a lexical token corresponding to the {m,n} construct. REPMN never appears in the compiled token vector. */ CAT, /* CAT is an operator of two arguments that matches the concatenation of its arguments. CAT is never returned by the lexical analyzer. */ OR, /* OR is an operator of two arguments that matches either of its arguments. */ ORTOP, /* OR at the toplevel in the parse tree. This is used for a boyer-moore heuristic. */ LPAREN, /* LPAREN never appears in the parse tree, it is only a lexeme. */ RPAREN, /* RPAREN never appears in the parse tree. */ CSET /* CSET and (and any value greater) is a terminal symbol that matches any of a class of characters. */ } token; /* Sets are stored in an array in the compiled dfa; the index of the array corresponding to a given set token is given by SET_INDEX(t). */ #define SET_INDEX(t) ((t) - CSET) /* Sometimes characters can only be matched depending on the surrounding context. Such context decisions depend on what the previous character was, and the value of the current (lookahead) character. Context dependent constraints are encoded as 8 bit integers. Each bit that is set indicates that the constraint succeeds in the corresponding context. bit 7 - previous and current are newlines bit 6 - previous was newline, current isn't bit 5 - previous wasn't newline, current is bit 4 - neither previous nor current is a newline bit 3 - previous and current are word-constituents bit 2 - previous was word-constituent, current isn't bit 1 - previous wasn't word-constituent, current is bit 0 - neither previous nor current is word-constituent Word-constituent characters are those that satisfy isalnum(). The macro SUCCEEDS_IN_CONTEXT determines whether a a given constraint succeeds in a particular context. Prevn is true if the previous character was a newline, currn is true if the lookahead character is a newline. Prevl and currl similarly depend upon whether the previous and current characters are word-constituent letters. */ #define MATCHES_NEWLINE_CONTEXT(constraint, prevn, currn) \ ((constraint) & 1 << (((prevn) ? 2 : 0) + ((currn) ? 1 : 0) + 4)) #define MATCHES_LETTER_CONTEXT(constraint, prevl, currl) \ ((constraint) & 1 << (((prevl) ? 2 : 0) + ((currl) ? 1 : 0))) #define SUCCEEDS_IN_CONTEXT(constraint, prevn, currn, prevl, currl) \ (MATCHES_NEWLINE_CONTEXT(constraint, prevn, currn) \ && MATCHES_LETTER_CONTEXT(constraint, prevl, currl)) /* The following macros give information about what a constraint depends on. */ #define PREV_NEWLINE_DEPENDENT(constraint) \ (((constraint) & 0xc0) >> 2 != ((constraint) & 0x30)) #define PREV_LETTER_DEPENDENT(constraint) \ (((constraint) & 0x0c) >> 2 != ((constraint) & 0x03)) /* Tokens that match the empty string subject to some constraint actually work by applying that constraint to determine what may follow them, taking into account what has gone before. The following values are the constraints corresponding to the special tokens previously defined. */ #define NO_CONSTRAINT 0xff #define BEGLINE_CONSTRAINT 0xcf #define ENDLINE_CONSTRAINT 0xaf #define BEGWORD_CONSTRAINT 0xf2 #define ENDWORD_CONSTRAINT 0xf4 #define LIMWORD_CONSTRAINT 0xf6 #define NOTLIMWORD_CONSTRAINT 0xf9 /* States of the recognizer correspond to sets of positions in the parse tree, together with the constraints under which they may be matched. So a position is encoded as an index into the parse tree together with a constraint. */ typedef struct { unsigned index; /* Index into the parse array. */ unsigned constraint; /* Constraint for matching this position. */ } position; /* Sets of positions are stored as arrays. */ typedef struct { position *elems; /* Elements of this position set. */ int nelem; /* Number of elements in this set. */ } position_set; /* A state of the dfa consists of a set of positions, some flags, and the token value of the lowest-numbered position of the state that contains an END token. */ typedef struct { int hash; /* Hash of the positions of this state. */ position_set elems; /* Positions this state could match. */ char newline; /* True if previous state matched newline. */ char letter; /* True if previous state matched a letter. */ char backref; /* True if this state matches a \. */ unsigned char constraint; /* Constraint for this state to accept. */ int first_end; /* Token value of the first END in elems. */ } dfa_state; /* Element of a list of strings, at least one of which is known to appear in any R.E. matching the DFA. */ struct dfamust { int exact; char *must; struct dfamust *next; }; /* A compiled regular expression. */ struct dfa { /* Stuff built by the scanner. */ charclass *charclasses; /* Array of character sets for CSET tokens. */ int cindex; /* Index for adding new charclasses. */ int calloc; /* Number of charclasses currently allocated. */ /* Stuff built by the parser. */ token *tokens; /* Postfix parse array. */ int tindex; /* Index for adding new tokens. */ int talloc; /* Number of tokens currently allocated. */ int depth; /* Depth required of an evaluation stack used for depth-first traversal of the parse tree. */ int nleaves; /* Number of leaves on the parse tree. */ int nregexps; /* Count of parallel regexps being built with dfaparse(). */ /* Stuff owned by the state builder. */ dfa_state *states; /* States of the dfa. */ int sindex; /* Index for adding new states. */ int salloc; /* Number of states currently allocated. */ /* Stuff built by the structure analyzer. */ position_set *follows; /* Array of follow sets, indexed by position index. The follow of a position is the set of positions containing characters that could conceivably follow a character matching the given position in a string matching the regexp. Allocated to the maximum possible position index. */ int searchflag; /* True if we are supposed to build a searching as opposed to an exact matcher. A searching matcher finds the first and shortest string matching a regexp anywhere in the buffer, whereas an exact matcher finds the longest string matching, but anchored to the beginning of the buffer. */ /* Stuff owned by the executor. */ int tralloc; /* Number of transition tables that have slots so far. */ int trcount; /* Number of transition tables that have actually been built. */ int **trans; /* Transition tables for states that can never accept. If the transitions for a state have not yet been computed, or the state could possibly accept, its entry in this table is NULL. */ int **realtrans; /* Trans always points to realtrans + 1; this is so trans[-1] can contain NULL. */ int **fails; /* Transition tables after failing to accept on a state that potentially could do so. */ int *success; /* Table of acceptance conditions used in dfaexec and computed in build_state. */ int *newlines; /* Transitions on newlines. The entry for a newline in any transition table is always -1 so we can count lines without wasting too many cycles. The transition for a newline is stored separately and handled as a special case. Newline is also used as a sentinel at the end of the buffer. */ struct dfamust *musts; /* List of strings, at least one of which is known to appear in any r.e. matching the dfa. */ }; /* Some macros for user access to dfa internals. */ /* ACCEPTING returns true if s could possibly be an accepting state of r. */ #define ACCEPTING(s, r) ((r).states[s].constraint) /* ACCEPTS_IN_CONTEXT returns true if the given state accepts in the specified context. */ #define ACCEPTS_IN_CONTEXT(prevn, currn, prevl, currl, state, dfa) \ SUCCEEDS_IN_CONTEXT((dfa).states[state].constraint, \ prevn, currn, prevl, currl) /* FIRST_MATCHING_REGEXP returns the index number of the first of parallel regexps that a given state could accept. Parallel regexps are numbered starting at 1. */ #define FIRST_MATCHING_REGEXP(state, dfa) (-(dfa).states[state].first_end) /* Entry points. */ /* dfasyntax() takes three arguments; the first sets the syntax bits described earlier in this file, the second sets the case-folding flag, and the third specifies the line terminator. */ extern void dfasyntax PARAMS ((reg_syntax_t, int, int)); /* Compile the given string of the given length into the given struct dfa. Final argument is a flag specifying whether to build a searching or an exact matcher. */ extern void dfacomp PARAMS ((char *, size_t, struct dfa *, int)); /* Execute the given struct dfa on the buffer of characters. The first char * points to the beginning, and the second points to the first character after the end of the buffer, which must be a writable place so a sentinel end-of-buffer marker can be stored there. The second-to-last argument is a flag telling whether to allow newlines to be part of a string matching the regexp. The next-to-last argument, if non-NULL, points to a place to increment every time we see a newline. The final argument, if non-NULL, points to a flag that will be set if further examination by a backtracking matcher is needed in order to verify backreferencing; otherwise the flag will be cleared. Returns NULL if no match is found, or a pointer to the first character after the first & shortest matching string in the buffer. */ extern char *dfaexec PARAMS ((struct dfa *, char *, char *, int, int *, int *)); /* Free the storage held by the components of a struct dfa. */ extern void dfafree PARAMS ((struct dfa *)); /* Entry points for people who know what they're doing. */ /* Initialize the components of a struct dfa. */ extern void dfainit PARAMS ((struct dfa *)); /* Incrementally parse a string of given length into a struct dfa. */ extern void dfaparse PARAMS ((char *, size_t, struct dfa *)); /* Analyze a parsed regexp; second argument tells whether to build a searching or an exact matcher. */ extern void dfaanalyze PARAMS ((struct dfa *, int)); /* Compute, for each possible character, the transitions out of a given state, storing them in an array of integers. */ extern void dfastate PARAMS ((int, struct dfa *, int [])); /* Error handling. */ /* dfaerror() is called by the regexp routines whenever an error occurs. It takes a single argument, a NUL-terminated string describing the error. The default dfaerror() prints the error message to stderr and exits. The user can provide a different dfafree() if so desired. */ extern void dfaerror PARAMS ((const char *)); argus-clients-2.0.6.fixes.1/ragrep/egrepmat.c0000664000076600007660000000017007310146216014500 #ifdef HAVE_CONFIG_H # include #endif #include "system.h" #include "ragrep.h" char const *matcher = "egrep"; argus-clients-2.0.6.fixes.1/ragrep/getpagesize.h0000664000076600007660000000136707310146216015221 /* Emulate getpagesize on systems that lack it. */ #ifndef HAVE_GETPAGESIZE #ifdef HAVE_UNISTD_H # include #endif #if !defined getpagesize && defined _SC_PAGESIZE # if !(defined VMS && __VMS_VER < 70000000) # define getpagesize() sysconf (_SC_PAGESIZE) # endif #endif #if !defined getpagesize && defined VMS # ifdef __ALPHA # define getpagesize() 8192 # else # define getpagesize() 512 # endif #endif #ifndef getpagesize # include # ifdef EXEC_PAGESIZE # define getpagesize() EXEC_PAGESIZE # else # ifdef NBPG # ifndef CLSIZE # define CLSIZE 1 # endif # define getpagesize() (NBPG * CLSIZE) # else # ifdef NBPC # define getpagesize() NBPC # endif # endif # endif #endif #endif /* not HAVE_GETPAGESIZE */ argus-clients-2.0.6.fixes.1/ragrep/grepmat.c0000664000076600007660000000015407310146216014335 #ifdef HAVE_CONFIG_H # include #endif #include "system.h" #include "grep.h" char const *matcher; argus-clients-2.0.6.fixes.1/ragrep/kwset.c0000664000076600007660000005107407551062142014044 /* kwset.c - search for any of a set of keywords. Copyright 1989, 1998, 2000 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Written August 1989 by Mike Haertel. The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ /* The algorithm implemented by these routines bears a startling resemblence to one discovered by Beate Commentz-Walter, although it is not identical. See "A String Matching Algorithm Fast on the Average," Technical Report, IBM-Germany, Scientific Center Heidelberg, Tiergartenstrasse 15, D-6900 Heidelberg, Germany. See also Aho, A.V., and M. Corasick, "Efficient String Matching: An Aid to Bibliographic Search," CACM June 1975, Vol. 18, No. 6, which describes the failure function used below. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "system.h" #include "kwset.h" #include "obstack.h" extern char *xmalloc(size_t); # undef malloc # define malloc xmalloc #define NCHAR (UCHAR_MAX + 1) #define obstack_chunk_alloc malloc #define obstack_chunk_free free /* Balanced tree of edges and labels leaving a given trie node. */ struct tree { struct tree *llink; /* Left link; MUST be first field. */ struct tree *rlink; /* Right link (to larger labels). */ struct trie *trie; /* Trie node pointed to by this edge. */ unsigned char label; /* Label on this edge. */ char balance; /* Difference in depths of subtrees. */ }; /* Node of a trie representing a set of reversed keywords. */ struct trie { unsigned int accepting; /* Word index of accepted word, or zero. */ struct tree *links; /* Tree of edges leaving this node. */ struct trie *parent; /* Parent of this node. */ struct trie *next; /* List of all trie nodes in level order. */ struct trie *fail; /* Aho-Corasick failure function. */ int depth; /* Depth of this node from the root. */ int shift; /* Shift function for search failures. */ int maxshift; /* Max shift of self and descendents. */ }; /* Structure returned opaquely to the caller, containing everything. */ struct kwset { struct obstack obstack; /* Obstack for node allocation. */ int words; /* Number of words in the trie. */ struct trie *trie; /* The trie itself. */ int mind; /* Minimum depth of an accepting node. */ int maxd; /* Maximum depth of any node. */ unsigned char delta[NCHAR]; /* Delta table for rapid search. */ struct trie *next[NCHAR]; /* Table of children of the root. */ char *target; /* Target string if there's only one. */ int mind2; /* Used in Boyer-Moore search for one string. */ char *trans; /* Character translation table. */ }; /* prototypes */ static void enqueue PARAMS((struct tree *, struct trie **)); static void treefails PARAMS((register struct tree *, struct trie *, struct trie *)); static void treedelta PARAMS((register struct tree *,register unsigned int, unsigned char *)); static int hasevery PARAMS((register struct tree *, register struct tree *)); static void treenext PARAMS((struct tree *, struct trie **)); static char * bmexec PARAMS((kwset_t, char *, size_t)); static char * cwexec PARAMS((kwset_t, char *, size_t, struct kwsmatch *)); /* Allocate and initialize a keyword set object, returning an opaque pointer to it. Return NULL if memory is not available. */ kwset_t kwsalloc (char *trans) { struct kwset *kwset; kwset = (struct kwset *) malloc(sizeof (struct kwset)); if (!kwset) return 0; obstack_init(&kwset->obstack); kwset->words = 0; kwset->trie = (struct trie *) obstack_alloc(&kwset->obstack, sizeof (struct trie)); if (!kwset->trie) { kwsfree((kwset_t) kwset); return 0; } kwset->trie->accepting = 0; kwset->trie->links = 0; kwset->trie->parent = 0; kwset->trie->next = 0; kwset->trie->fail = 0; kwset->trie->depth = 0; kwset->trie->shift = 0; kwset->mind = INT_MAX; kwset->maxd = -1; kwset->target = 0; kwset->trans = trans; return (kwset_t) kwset; } /* Add the given string to the contents of the keyword set. Return NULL for success, an error message otherwise. */ char * kwsincr (kwset_t kws, char *text, size_t len) { struct kwset *kwset; register struct trie *trie; register unsigned char label; register struct tree *link; register int depth; struct tree *links[12]; enum { L, R } dirs[12]; struct tree *t, *r, *l, *rl, *lr; kwset = (struct kwset *) kws; trie = kwset->trie; text += len; /* Descend the trie (built of reversed keywords) character-by-character, installing new nodes when necessary. */ while (len--) { label = kwset->trans ? kwset->trans[(unsigned char) *--text] : *--text; /* Descend the tree of outgoing links for this trie node, looking for the current character and keeping track of the path followed. */ link = trie->links; links[0] = (struct tree *) &trie->links; dirs[0] = L; depth = 1; while (link && label != link->label) { links[depth] = link; if (label < link->label) dirs[depth++] = L, link = link->llink; else dirs[depth++] = R, link = link->rlink; } /* The current character doesn't have an outgoing link at this trie node, so build a new trie node and install a link in the current trie node's tree. */ if (!link) { link = (struct tree *) obstack_alloc(&kwset->obstack, sizeof (struct tree)); if (!link) return _("memory exhausted"); link->llink = 0; link->rlink = 0; link->trie = (struct trie *) obstack_alloc(&kwset->obstack, sizeof (struct trie)); if (!link->trie) return _("memory exhausted"); link->trie->accepting = 0; link->trie->links = 0; link->trie->parent = trie; link->trie->next = 0; link->trie->fail = 0; link->trie->depth = trie->depth + 1; link->trie->shift = 0; link->label = label; link->balance = 0; /* Install the new tree node in its parent. */ if (dirs[--depth] == L) links[depth]->llink = link; else links[depth]->rlink = link; /* Back up the tree fixing the balance flags. */ while (depth && !links[depth]->balance) { if (dirs[depth] == L) --links[depth]->balance; else ++links[depth]->balance; --depth; } /* Rebalance the tree by pointer rotations if necessary. */ if (depth && ((dirs[depth] == L && --links[depth]->balance) || (dirs[depth] == R && ++links[depth]->balance))) { switch (links[depth]->balance) { case (char) -2: switch (dirs[depth + 1]) { case L: r = links[depth], t = r->llink, rl = t->rlink; t->rlink = r, r->llink = rl; t->balance = r->balance = 0; break; case R: r = links[depth], l = r->llink, t = l->rlink; rl = t->rlink, lr = t->llink; t->llink = l, l->rlink = lr, t->rlink = r, r->llink = rl; l->balance = t->balance != 1 ? 0 : -1; r->balance = t->balance != (char) -1 ? 0 : 1; t->balance = 0; break; default: abort (); } break; case 2: switch (dirs[depth + 1]) { case R: l = links[depth], t = l->rlink, lr = t->llink; t->llink = l, l->rlink = lr; t->balance = l->balance = 0; break; case L: l = links[depth], r = l->rlink, t = r->llink; lr = t->llink, rl = t->rlink; t->llink = l, l->rlink = lr, t->rlink = r, r->llink = rl; l->balance = t->balance != 1 ? 0 : -1; r->balance = t->balance != (char) -1 ? 0 : 1; t->balance = 0; break; default: abort (); } break; default: abort (); } if (dirs[depth - 1] == L) links[depth - 1]->llink = t; else links[depth - 1]->rlink = t; } } trie = link->trie; } /* Mark the node we finally reached as accepting, encoding the index number of this word in the keyword set so far. */ if (!trie->accepting) trie->accepting = 1 + 2 * kwset->words; ++kwset->words; /* Keep track of the longest and shortest string of the keyword set. */ if (trie->depth < kwset->mind) kwset->mind = trie->depth; if (trie->depth > kwset->maxd) kwset->maxd = trie->depth; return 0; } /* Enqueue the trie nodes referenced from the given tree in the given queue. */ static void enqueue (struct tree *tree, struct trie **last) { if (!tree) return; enqueue(tree->llink, last); enqueue(tree->rlink, last); (*last) = (*last)->next = tree->trie; } /* Compute the Aho-Corasick failure function for the trie nodes referenced from the given tree, given the failure function for their parent as well as a last resort failure node. */ static void treefails (register struct tree *tree, struct trie *fail, struct trie *recourse) { register struct tree *link; if (!tree) return; treefails(tree->llink, fail, recourse); treefails(tree->rlink, fail, recourse); /* Find, in the chain of fails going back to the root, the first node that has a descendent on the current label. */ while (fail) { link = fail->links; while (link && tree->label != link->label) if (tree->label < link->label) link = link->llink; else link = link->rlink; if (link) { tree->trie->fail = link->trie; return; } fail = fail->fail; } tree->trie->fail = recourse; } /* Set delta entries for the links of the given tree such that the preexisting delta value is larger than the current depth. */ static void treedelta (register struct tree *tree, register unsigned int depth, unsigned char delta[]) { if (!tree) return; treedelta(tree->llink, depth, delta); treedelta(tree->rlink, depth, delta); if (depth < delta[tree->label]) delta[tree->label] = depth; } /* Return true if A has every label in B. */ static int hasevery (register struct tree *a, register struct tree *b) { if (!b) return 1; if (!hasevery(a, b->llink)) return 0; if (!hasevery(a, b->rlink)) return 0; while (a && b->label != a->label) if (b->label < a->label) a = a->llink; else a = a->rlink; return !!a; } /* Compute a vector, indexed by character code, of the trie nodes referenced from the given tree. */ static void treenext (struct tree *tree, struct trie *next[]) { if (!tree) return; treenext(tree->llink, next); treenext(tree->rlink, next); next[tree->label] = tree->trie; } /* Compute the shift for each trie node, as well as the delta table and next cache for the given keyword set. */ char * kwsprep (kwset_t kws) { register struct kwset *kwset; register int i; register struct trie *curr, *fail; register char *trans; unsigned char delta[NCHAR]; struct trie *last, *next[NCHAR]; kwset = (struct kwset *) kws; /* Initial values for the delta table; will be changed later. The delta entry for a given character is the smallest depth of any node at which an outgoing edge is labeled by that character. */ if (kwset->mind < 256) for (i = 0; i < NCHAR; ++i) delta[i] = kwset->mind; else for (i = 0; i < NCHAR; ++i) delta[i] = 255; /* Check if we can use the simple boyer-moore algorithm, instead of the hairy commentz-walter algorithm. */ if (kwset->words == 1 && kwset->trans == 0) { /* Looking for just one string. Extract it from the trie. */ kwset->target = obstack_alloc(&kwset->obstack, kwset->mind); for (i = kwset->mind - 1, curr = kwset->trie; i >= 0; --i) { kwset->target[i] = curr->links->label; curr = curr->links->trie; } /* Build the Boyer Moore delta. Boy that's easy compared to CW. */ for (i = 0; i < kwset->mind; ++i) delta[(unsigned char) kwset->target[i]] = kwset->mind - (i + 1); kwset->mind2 = kwset->mind; /* Find the minimal delta2 shift that we might make after a backwards match has failed. */ for (i = 0; i < kwset->mind - 1; ++i) if (kwset->target[i] == kwset->target[kwset->mind - 1]) kwset->mind2 = kwset->mind - (i + 1); } else { /* Traverse the nodes of the trie in level order, simultaneously computing the delta table, failure function, and shift function. */ for (curr = last = kwset->trie; curr; curr = curr->next) { /* Enqueue the immediate descendents in the level order queue. */ enqueue(curr->links, &last); curr->shift = kwset->mind; curr->maxshift = kwset->mind; /* Update the delta table for the descendents of this node. */ treedelta(curr->links, curr->depth, delta); /* Compute the failure function for the decendents of this node. */ treefails(curr->links, curr->fail, kwset->trie); /* Update the shifts at each node in the current node's chain of fails back to the root. */ for (fail = curr->fail; fail; fail = fail->fail) { /* If the current node has some outgoing edge that the fail doesn't, then the shift at the fail should be no larger than the difference of their depths. */ if (!hasevery(fail->links, curr->links)) if (curr->depth - fail->depth < fail->shift) fail->shift = curr->depth - fail->depth; /* If the current node is accepting then the shift at the fail and its descendents should be no larger than the difference of their depths. */ if (curr->accepting && fail->maxshift > curr->depth - fail->depth) fail->maxshift = curr->depth - fail->depth; } } /* Traverse the trie in level order again, fixing up all nodes whose shift exceeds their inherited maxshift. */ for (curr = kwset->trie->next; curr; curr = curr->next) { if (curr->maxshift > curr->parent->maxshift) curr->maxshift = curr->parent->maxshift; if (curr->shift > curr->maxshift) curr->shift = curr->maxshift; } /* Create a vector, indexed by character code, of the outgoing links from the root node. */ for (i = 0; i < NCHAR; ++i) next[i] = 0; treenext(kwset->trie->links, next); if ((trans = kwset->trans) != 0) for (i = 0; i < NCHAR; ++i) kwset->next[i] = next[(unsigned char) trans[i]]; else for (i = 0; i < NCHAR; ++i) kwset->next[i] = next[i]; } /* Fix things up for any translation table. */ if ((trans = kwset->trans) != 0) for (i = 0; i < NCHAR; ++i) kwset->delta[i] = delta[(unsigned char) trans[i]]; else for (i = 0; i < NCHAR; ++i) kwset->delta[i] = delta[i]; return 0; } #define U(C) ((unsigned char) (C)) /* Fast boyer-moore search. */ static char * bmexec (kwset_t kws, char *text, size_t size) { struct kwset *kwset; register unsigned char *d1; register char *ep, *sp, *tp; register int d, gc, i, len, md2; kwset = (struct kwset *) kws; len = kwset->mind; if (len == 0) return text; if (len > size) return 0; if (len == 1) return memchr(text, kwset->target[0], size); d1 = kwset->delta; sp = kwset->target + len; gc = U(sp[-2]); md2 = kwset->mind2; tp = text + len; /* Significance of 12: 1 (initial offset) + 10 (skip loop) + 1 (md2). */ if (size > 12 * len) /* 11 is not a bug, the initial offset happens only once. */ for (ep = text + size - 11 * len;;) { while (tp <= ep) { d = d1[U(tp[-1])], tp += d; d = d1[U(tp[-1])], tp += d; if (d == 0) goto found; d = d1[U(tp[-1])], tp += d; d = d1[U(tp[-1])], tp += d; d = d1[U(tp[-1])], tp += d; if (d == 0) goto found; d = d1[U(tp[-1])], tp += d; d = d1[U(tp[-1])], tp += d; d = d1[U(tp[-1])], tp += d; if (d == 0) goto found; d = d1[U(tp[-1])], tp += d; d = d1[U(tp[-1])], tp += d; } break; found: if (U(tp[-2]) == gc) { for (i = 3; i <= len && U(tp[-i]) == U(sp[-i]); ++i) ; if (i > len) return tp - len; } tp += md2; } /* Now we have only a few characters left to search. We carefully avoid ever producing an out-of-bounds pointer. */ ep = text + size; d = d1[U(tp[-1])]; while (d <= ep - tp) { d = d1[U((tp += d)[-1])]; if (d != 0) continue; if (U(tp[-2]) == gc) { for (i = 3; i <= len && U(tp[-i]) == U(sp[-i]); ++i) ; if (i > len) return tp - len; } d = md2; } return 0; } /* Hairy multiple string search. */ static char * cwexec (kwset_t kws, char *text, size_t len, struct kwsmatch *kwsmatch) { struct kwset *kwset; struct trie **next, *trie, *accept = NULL; char *beg, *lim, *mch, *lmch; register unsigned char c, *delta; register int d; register char *end, *qlim; register struct tree *tree; register char *trans; #ifdef lint accept = NULL; #endif /* Initialize register copies and look for easy ways out. */ kwset = (struct kwset *) kws; if (len < kwset->mind) return 0; next = kwset->next; delta = kwset->delta; trans = kwset->trans; lim = text + len; end = text; if ((d = kwset->mind) != 0) mch = 0; else { mch = text, accept = kwset->trie; goto match; } if (len >= 4 * kwset->mind) qlim = lim - 4 * kwset->mind; else qlim = 0; while (lim - end >= d) { if (qlim && end <= qlim) { end += d - 1; while ((d = delta[c = *end]) && end < qlim) { end += d; end += delta[(unsigned char) *end]; end += delta[(unsigned char) *end]; } ++end; } else d = delta[c = (end += d)[-1]]; if (d) continue; beg = end - 1; trie = next[c]; if (trie->accepting) { mch = beg; accept = trie; } d = trie->shift; while (beg > text) { c = trans ? trans[(unsigned char) *--beg] : *--beg; tree = trie->links; while (tree && c != tree->label) if (c < tree->label) tree = tree->llink; else tree = tree->rlink; if (tree) { trie = tree->trie; if (trie->accepting) { mch = beg; accept = trie; } } else break; d = trie->shift; } if (mch) goto match; } return 0; match: /* Given a known match, find the longest possible match anchored at or before its starting point. This is nearly a verbatim copy of the preceding main search loops. */ if (lim - mch > kwset->maxd) lim = mch + kwset->maxd; lmch = 0; d = 1; while (lim - end >= d) { if ((d = delta[c = (end += d)[-1]]) != 0) continue; beg = end - 1; if (!(trie = next[c])) { d = 1; continue; } if (trie->accepting && beg <= mch) { lmch = beg; accept = trie; } d = trie->shift; while (beg > text) { c = trans ? trans[(unsigned char) *--beg] : *--beg; tree = trie->links; while (tree && c != tree->label) if (c < tree->label) tree = tree->llink; else tree = tree->rlink; if (tree) { trie = tree->trie; if (trie->accepting && beg <= mch) { lmch = beg; accept = trie; } } else break; d = trie->shift; } if (lmch) { mch = lmch; goto match; } if (!d) d = 1; } if (kwsmatch) { kwsmatch->index = accept->accepting / 2; kwsmatch->beg[0] = mch; kwsmatch->size[0] = accept->depth; } return mch; } /* Search through the given text for a match of any member of the given keyword set. Return a pointer to the first character of the matching substring, or NULL if no match is found. If FOUNDLEN is non-NULL store in the referenced location the length of the matching substring. Similarly, if FOUNDIDX is non-NULL, store in the referenced location the index number of the particular keyword matched. */ char * kwsexec (kwset_t kws, char *text, size_t size, struct kwsmatch *kwsmatch) { struct kwset *kwset; char *ret; kwset = (struct kwset *) kws; if (kwset->words == 1 && kwset->trans == 0) { ret = bmexec(kws, text, size); if (kwsmatch != 0 && ret != 0) { kwsmatch->index = 0; kwsmatch->beg[0] = ret; kwsmatch->size[0] = kwset->mind; } return ret; } else return cwexec(kws, text, size, kwsmatch); } /* Free the components of the given keyword set. */ void kwsfree (kwset_t kws) { struct kwset *kwset; kwset = (struct kwset *) kws; obstack_free(&kwset->obstack, 0); free(kws); } argus-clients-2.0.6.fixes.1/ragrep/kwset.h0000664000076600007660000000461007310146216014041 /* kwset.h - header declaring the keyword set library. Copyright (C) 1989, 1998 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Written August 1989 by Mike Haertel. The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ struct kwsmatch { int index; /* Index number of matching keyword. */ char *beg[1]; /* Begin pointer for each submatch. */ size_t size[1]; /* Length of each submatch. */ }; typedef ptr_t kwset_t; /* Return an opaque pointer to a newly allocated keyword set, or NULL if enough memory cannot be obtained. The argument if non-NULL specifies a table of character translations to be applied to all pattern and search text. */ extern kwset_t kwsalloc PARAMS((char *)); /* Incrementally extend the keyword set to include the given string. Return NULL for success, or an error message. Remember an index number for each keyword included in the set. */ extern char *kwsincr PARAMS((kwset_t, char *, size_t)); /* When the keyword set has been completely built, prepare it for use. Return NULL for success, or an error message. */ extern char *kwsprep PARAMS((kwset_t)); /* Search through the given buffer for a member of the keyword set. Return a pointer to the leftmost longest match found, or NULL if no match is found. If foundlen is non-NULL, store the length of the matching substring in the integer it points to. Similarly, if foundindex is non-NULL, store the index of the particular keyword found therein. */ extern char *kwsexec PARAMS((kwset_t, char *, size_t, struct kwsmatch *)); /* Deallocate the given keyword set and all its associated storage. */ extern void kwsfree PARAMS((kwset_t)); argus-clients-2.0.6.fixes.1/ragrep/obstack.c0000664000076600007660000004327407606552732014352 /* obstack.c - subroutines used implicitly by object stack macros Copyright (C) 1988-1994,96,97,98,99 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include "obstack.h" /* NOTE BEFORE MODIFYING THIS FILE: This version number must be incremented whenever callers compiled using an old obstack.h can no longer properly call the functions in this obstack.c. */ #define OBSTACK_INTERFACE_VERSION 1 /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself, and the installed library supports the same library interface we do. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #include /* Random thing to get __GNU_LIBRARY__. */ #if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 #include #if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE #if defined (__STDC__) && __STDC__ #define POINTER void * #else #define POINTER char * #endif /* Determine default alignment. */ struct fooalign {char x; double d;}; #define DEFAULT_ALIGNMENT \ ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0)) /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. But in fact it might be less smart and round addresses to as much as DEFAULT_ROUNDING. So we prepare for it to do that. */ union fooround {long x; double d;}; #define DEFAULT_ROUNDING (sizeof (union fooround)) /* When we copy a long block of data, this is the unit to do it with. On some machines, copying successive ints does not work; in such a case, redefine COPYING_UNIT to `long' (if that works) or `char' as a last resort. */ #ifndef COPYING_UNIT #define COPYING_UNIT int #endif /* The functions allocating more room by calling `obstack_chunk_alloc' jump to the handler pointed to by `obstack_alloc_failed_handler'. This can be set to a user defined function which should either abort gracefully or use longjump - but shouldn't return. This variable by default points to the internal function `print_and_abort'. */ #if defined (__STDC__) && __STDC__ static void print_and_abort (void); void (*obstack_alloc_failed_handler) (void) = print_and_abort; #else static void print_and_abort (); void (*obstack_alloc_failed_handler) () = print_and_abort; #endif /* Exit value used when `print_and_abort' is used. */ #if defined __GNU_LIBRARY__ || defined HAVE_STDLIB_H #include #endif #ifndef EXIT_FAILURE #define EXIT_FAILURE 1 #endif int obstack_exit_failure = EXIT_FAILURE; /* The non-GNU-C macros copy the obstack into this global variable to avoid multiple evaluation. */ struct obstack *_obstack; /* Define a macro that either calls functions with the traditional malloc/free calling interface, or calls functions with the mmalloc/mfree interface (that adds an extra first argument), based on the state of use_extra_arg. For free, do not use ?:, since some compilers, like the MIPS compilers, do not allow (expr) ? void : void. */ #if defined (__STDC__) && __STDC__ #define CALL_CHUNKFUN(h, size) \ (((h) -> use_extra_arg) \ ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size))) #define CALL_FREEFUN(h, old_chunk) \ do { \ if ((h) -> use_extra_arg) \ (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ else \ (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \ } while (0) #else #define CALL_CHUNKFUN(h, size) \ (((h) -> use_extra_arg) \ ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ : (*(struct _obstack_chunk *(*) ()) (h)->chunkfun) ((size))) #define CALL_FREEFUN(h, old_chunk) \ do { \ if ((h) -> use_extra_arg) \ (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ else \ (*(void (*) ()) (h)->freefun) ((old_chunk)); \ } while (0) #endif /* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). Objects start on multiples of ALIGNMENT (0 means use default). CHUNKFUN is the function to use to allocate chunks, and FREEFUN the function to free them. Return nonzero if successful, calls obstack_alloc_failed_handler if allocation fails. */ int _obstack_begin (h, size, alignment, chunkfun, freefun) struct obstack *h; int size; int alignment; #if defined (__STDC__) && __STDC__ POINTER (*chunkfun) (long); void (*freefun) (void *); #else POINTER (*chunkfun) (); void (*freefun) (); #endif { register struct _obstack_chunk *chunk; /* points to new chunk */ if (alignment == 0) alignment = (int) DEFAULT_ALIGNMENT; if (size == 0) /* Default size is what GNU malloc can fit in a 4096-byte block. */ { /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. Use the values for range checking, because if range checking is off, the extra bytes won't be missed terribly, but if range checking is on and we used a larger request, a whole extra 4096 bytes would be allocated. These number are irrelevant to the new GNU malloc. I suspect it is less sensitive to the size of the request. */ int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + 4 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)); size = 4096 - extra; } #if defined (__STDC__) && __STDC__ h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun; h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; #else h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; h->freefun = freefun; #endif h->chunk_size = size; h->alignment_mask = alignment - 1; h->use_extra_arg = 0; chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); if (!chunk) (*obstack_alloc_failed_handler) (); h->next_free = h->object_base = chunk->contents; h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size; chunk->prev = 0; /* The initial chunk now contains no empty object. */ h->maybe_empty_object = 0; h->alloc_failed = 0; return 1; } int _obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg) struct obstack *h; int size; int alignment; #if defined (__STDC__) && __STDC__ POINTER (*chunkfun) (POINTER, long); void (*freefun) (POINTER, POINTER); #else POINTER (*chunkfun) (); void (*freefun) (); #endif POINTER arg; { register struct _obstack_chunk *chunk; /* points to new chunk */ if (alignment == 0) alignment = (int) DEFAULT_ALIGNMENT; if (size == 0) /* Default size is what GNU malloc can fit in a 4096-byte block. */ { /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. Use the values for range checking, because if range checking is off, the extra bytes won't be missed terribly, but if range checking is on and we used a larger request, a whole extra 4096 bytes would be allocated. These number are irrelevant to the new GNU malloc. I suspect it is less sensitive to the size of the request. */ int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + 4 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)); size = 4096 - extra; } #if defined(__STDC__) && __STDC__ h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun; h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; #else h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; h->freefun = freefun; #endif h->chunk_size = size; h->alignment_mask = alignment - 1; h->extra_arg = arg; h->use_extra_arg = 1; chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); if (!chunk) (*obstack_alloc_failed_handler) (); h->next_free = h->object_base = chunk->contents; h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size; chunk->prev = 0; /* The initial chunk now contains no empty object. */ h->maybe_empty_object = 0; h->alloc_failed = 0; return 1; } /* Allocate a new current chunk for the obstack *H on the assumption that LENGTH bytes need to be added to the current object, or a new object of length LENGTH allocated. Copies any partial object from the end of the old chunk to the beginning of the new one. */ void _obstack_newchunk (h, length) struct obstack *h; int length; { register struct _obstack_chunk *old_chunk = h->chunk; register struct _obstack_chunk *new_chunk; register long new_size; register long obj_size = h->next_free - h->object_base; register long i; long already; /* Compute size for new chunk. */ new_size = (obj_size + length) + (obj_size >> 3) + 100; if (new_size < h->chunk_size) new_size = h->chunk_size; /* Allocate and initialize the new chunk. */ new_chunk = CALL_CHUNKFUN (h, new_size); if (!new_chunk) (*obstack_alloc_failed_handler) (); h->chunk = new_chunk; new_chunk->prev = old_chunk; new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; /* Move the existing object to the new chunk. Word at a time is fast and is safe if the object is sufficiently aligned. */ if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT) { for (i = obj_size / sizeof (COPYING_UNIT) - 1; i >= 0; i--) ((COPYING_UNIT *)new_chunk->contents)[i] = ((COPYING_UNIT *)h->object_base)[i]; /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT, but that can cross a page boundary on a machine which does not do strict alignment for COPYING_UNITS. */ already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT); } else already = 0; /* Copy remaining bytes one by one. */ for (i = already; i < obj_size; i++) new_chunk->contents[i] = h->object_base[i]; /* If the object just copied was the only data in OLD_CHUNK, free that chunk and remove it from the chain. But not if that chunk might contain an empty object. */ if (h->object_base == old_chunk->contents && ! h->maybe_empty_object) { new_chunk->prev = old_chunk->prev; CALL_FREEFUN (h, old_chunk); } h->object_base = new_chunk->contents; h->next_free = h->object_base + obj_size; /* The new chunk certainly contains no empty object yet. */ h->maybe_empty_object = 0; } /* Return nonzero if object OBJ has been allocated from obstack H. This is here for debugging. If you use it in a program, you are probably losing. */ #if defined (__STDC__) && __STDC__ /* Suppress -Wmissing-prototypes warning. We don't want to declare this in obstack.h because it is just for debugging. */ int _obstack_allocated_p (struct obstack *h, POINTER obj); #endif int _obstack_allocated_p (h, obj) struct obstack *h; POINTER obj; { register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ register struct _obstack_chunk *plp; /* point to previous chunk if any */ lp = (h)->chunk; /* We use >= rather than > since the object cannot be exactly at the beginning of the chunk but might be an empty object exactly at the end of an adjacent chunk. */ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) { plp = lp->prev; lp = plp; } return lp != 0; } /* Free objects in obstack H, including OBJ and everything allocate more recently than OBJ. If OBJ is zero, free everything in H. */ #undef obstack_free /* This function has two names with identical definitions. This is the first one, called from non-ANSI code. */ void _obstack_free (h, obj) struct obstack *h; POINTER obj; { register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ register struct _obstack_chunk *plp; /* point to previous chunk if any */ lp = h->chunk; /* We use >= because there cannot be an object at the beginning of a chunk. But there can be an empty object at that address at the end of another chunk. */ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) { plp = lp->prev; CALL_FREEFUN (h, lp); lp = plp; /* If we switch chunks, we can't tell whether the new current chunk contains an empty object, so assume that it may. */ h->maybe_empty_object = 1; } if (lp) { h->object_base = h->next_free = (char *) (obj); h->chunk_limit = lp->limit; h->chunk = lp; } else if (obj != 0) /* obj is not in any of the chunks! */ abort (); } /* This function is used from ANSI code. */ void obstack_free (h, obj) struct obstack *h; POINTER obj; { register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ register struct _obstack_chunk *plp; /* point to previous chunk if any */ lp = h->chunk; /* We use >= because there cannot be an object at the beginning of a chunk. But there can be an empty object at that address at the end of another chunk. */ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) { plp = lp->prev; CALL_FREEFUN (h, lp); lp = plp; /* If we switch chunks, we can't tell whether the new current chunk contains an empty object, so assume that it may. */ h->maybe_empty_object = 1; } if (lp) { h->object_base = h->next_free = (char *) (obj); h->chunk_limit = lp->limit; h->chunk = lp; } else if (obj != 0) /* obj is not in any of the chunks! */ abort (); } int _obstack_memory_used (h) struct obstack *h; { register struct _obstack_chunk* lp; register int nbytes = 0; for (lp = h->chunk; lp != 0; lp = lp->prev) { nbytes += lp->limit - (char *) lp; } return nbytes; } /* Define the error handler. */ #ifndef _ # ifdef HAVE_LIBINTL_H # include # ifndef _ # define _(Str) gettext (Str) # endif # else # define _(Str) (Str) # endif #endif #if defined _LIBC && defined USE_IN_LIBIO # include # define fputs(s, f) _IO_fputs (s, f) #endif static void print_and_abort () { fputs (_("memory exhausted"), stderr); fputc ('\n', stderr); exit (obstack_exit_failure); } #if 0 /* These are now turned off because the applications do not use it and it uses bcopy via obstack_grow, which causes trouble on sysV. */ /* Now define the functional versions of the obstack macros. Define them to simply use the corresponding macros to do the job. */ #if defined (__STDC__) && __STDC__ /* These function definitions do not work with non-ANSI preprocessors; they won't pass through the macro names in parentheses. */ /* The function names appear in parentheses in order to prevent the macro-definitions of the names from being expanded there. */ POINTER (obstack_base) (obstack) struct obstack *obstack; { return obstack_base (obstack); } POINTER (obstack_next_free) (obstack) struct obstack *obstack; { return obstack_next_free (obstack); } int (obstack_object_size) (obstack) struct obstack *obstack; { return obstack_object_size (obstack); } int (obstack_room) (obstack) struct obstack *obstack; { return obstack_room (obstack); } int (obstack_make_room) (obstack, length) struct obstack *obstack; int length; { return obstack_make_room (obstack, length); } void (obstack_grow) (obstack, pointer, length) struct obstack *obstack; POINTER pointer; int length; { obstack_grow (obstack, pointer, length); } void (obstack_grow0) (obstack, pointer, length) struct obstack *obstack; POINTER pointer; int length; { obstack_grow0 (obstack, pointer, length); } void (obstack_1grow) (obstack, character) struct obstack *obstack; int character; { obstack_1grow (obstack, character); } void (obstack_blank) (obstack, length) struct obstack *obstack; int length; { obstack_blank (obstack, length); } void (obstack_1grow_fast) (obstack, character) struct obstack *obstack; int character; { obstack_1grow_fast (obstack, character); } void (obstack_blank_fast) (obstack, length) struct obstack *obstack; int length; { obstack_blank_fast (obstack, length); } POINTER (obstack_finish) (obstack) struct obstack *obstack; { return obstack_finish (obstack); } POINTER (obstack_alloc) (obstack, length) struct obstack *obstack; int length; { return obstack_alloc (obstack, length); } POINTER (obstack_copy) (obstack, pointer, length) struct obstack *obstack; POINTER pointer; int length; { return obstack_copy (obstack, pointer, length); } POINTER (obstack_copy0) (obstack, pointer, length) struct obstack *obstack; POINTER pointer; int length; { return obstack_copy0 (obstack, pointer, length); } #endif /* __STDC__ */ #endif /* 0 */ #endif /* !ELIDE_CODE */ argus-clients-2.0.6.fixes.1/ragrep/obstack.h0000664000076600007660000005461707313720656014357 /* obstack.h - object stack macros Copyright (C) 1988,89,90,91,92,93,94,96,97,98,99 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Summary: All the apparent functions defined here are macros. The idea is that you would use these pre-tested macros to solve a very specific set of problems, and they would run fast. Caution: no side-effects in arguments please!! They may be evaluated MANY times!! These macros operate a stack of objects. Each object starts life small, and may grow to maturity. (Consider building a word syllable by syllable.) An object can move while it is growing. Once it has been "finished" it never changes address again. So the "top of the stack" is typically an immature growing object, while the rest of the stack is of mature, fixed size and fixed address objects. These routines grab large chunks of memory, using a function you supply, called `obstack_chunk_alloc'. On occasion, they free chunks, by calling `obstack_chunk_free'. You must define them and declare them before using any obstack macros. Each independent stack is represented by a `struct obstack'. Each of the obstack macros expects a pointer to such a structure as the first argument. One motivation for this package is the problem of growing char strings in symbol tables. Unless you are "fascist pig with a read-only mind" --Gosper's immortal quote from HAKMEM item 154, out of context--you would not like to put any arbitrary upper limit on the length of your symbols. In practice this often means you will build many short symbols and a few long symbols. At the time you are reading a symbol you don't know how long it is. One traditional method is to read a symbol into a buffer, realloc()ating the buffer every time you try to read a symbol that is longer than the buffer. This is beaut, but you still will want to copy the symbol from the buffer to a more permanent symbol-table entry say about half the time. With obstacks, you can work differently. Use one obstack for all symbol names. As you read a symbol, grow the name in the obstack gradually. When the name is complete, finalize it. Then, if the symbol exists already, free the newly read name. The way we do this is to take a large chunk, allocating memory from low addresses. When you want to build a symbol in the chunk you just add chars above the current "high water mark" in the chunk. When you have finished adding chars, because you got to the end of the symbol, you know how long the chars are, and you can create a new object. Mostly the chars will not burst over the highest address of the chunk, because you would typically expect a chunk to be (say) 100 times as long as an average object. In case that isn't clear, when we have enough chars to make up the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed) so we just point to it where it lies. No moving of chars is needed and this is the second win: potentially long strings need never be explicitly shuffled. Once an object is formed, it does not change its address during its lifetime. When the chars burst over a chunk boundary, we allocate a larger chunk, and then copy the partly formed object from the end of the old chunk to the beginning of the new larger chunk. We then carry on accreting characters to the end of the object as we normally would. A special macro is provided to add a single char at a time to a growing object. This allows the use of register variables, which break the ordinary 'growth' macro. Summary: We allocate large chunks. We carve out one object at a time from the current chunk. Once carved, an object never moves. We are free to append data of any size to the currently growing object. Exactly one object is growing in an obstack at any one time. You can run one obstack per control block. You may have as many control blocks as you dare. Because of the way we do it, you can `unwind' an obstack back to a previous state. (You may remove objects much as you would with a stack.) */ /* Don't do the contents of this file more than once. */ #ifndef _OBSTACK_H #define _OBSTACK_H 1 #ifdef __cplusplus extern "C" { #endif /* We use subtraction of (char *) 0 instead of casting to int because on word-addressable machines a simple cast to int may ignore the byte-within-word field of the pointer. */ #ifndef __PTR_TO_INT # define __PTR_TO_INT(P) ((P) - (char *) 0) #endif #ifndef __INT_TO_PTR # define __INT_TO_PTR(P) ((P) + (char *) 0) #endif /* We need the type of the resulting object. If __PTRDIFF_TYPE__ is defined, as with GNU C, use that; that way we don't pollute the namespace with 's symbols. Otherwise, if is available, include it and use ptrdiff_t. In traditional C, long is the best that we can do. */ #ifdef __PTRDIFF_TYPE__ # define PTR_INT_TYPE __PTRDIFF_TYPE__ #else # ifdef HAVE_STDDEF_H # include # define PTR_INT_TYPE ptrdiff_t # else # define PTR_INT_TYPE long # endif #endif #if defined _LIBC || defined HAVE_STRING_H # include # define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N)) #else # ifdef memcpy # define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N)) # else # define _obstack_memcpy(To, From, N) bcopy ((From), (To), (N)) # endif #endif struct _obstack_chunk /* Lives at front of each chunk. */ { char *limit; /* 1 past end of this chunk */ struct _obstack_chunk *prev; /* address of prior chunk or NULL */ char contents[4]; /* objects begin here */ }; struct obstack /* control current object in current chunk */ { long chunk_size; /* preferred size to allocate chunks in */ struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */ char *object_base; /* address of object we are building */ char *next_free; /* where to add next char to current object */ char *chunk_limit; /* address of char after current chunk */ PTR_INT_TYPE temp; /* Temporary for some macros. */ int alignment_mask; /* Mask of alignment for each object. */ #if defined __STDC__ && __STDC__ /* These prototypes vary based on `use_extra_arg', and we use casts to the prototypeless function type in all assignments, but having prototypes here quiets -Wstrict-prototypes. */ struct _obstack_chunk *(*chunkfun) (void *, long); void (*freefun) (void *, struct _obstack_chunk *); void *extra_arg; /* first arg for chunk alloc/dealloc funcs */ #else struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */ void (*freefun) (); /* User's function to free a chunk. */ char *extra_arg; /* first arg for chunk alloc/dealloc funcs */ #endif unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */ unsigned maybe_empty_object:1;/* There is a possibility that the current chunk contains a zero-length object. This prevents freeing the chunk if we allocate a bigger chunk to replace it. */ unsigned alloc_failed:1; /* No longer used, as we now call the failed handler on error, but retained for binary compatibility. */ }; /* Declare the external functions we use; they are in obstack.c. */ #if defined __STDC__ && __STDC__ extern void _obstack_newchunk (struct obstack *, int); extern void _obstack_free (struct obstack *, void *); extern int _obstack_begin (struct obstack *, int, int, void *(*) (long), void (*) (void *)); extern int _obstack_begin_1 (struct obstack *, int, int, void *(*) (void *, long), void (*) (void *, void *), void *); extern int _obstack_memory_used (struct obstack *); #else extern void _obstack_newchunk (); extern void _obstack_free (); extern int _obstack_begin (); extern int _obstack_begin_1 (); extern int _obstack_memory_used (); #endif #if defined __STDC__ && __STDC__ /* Do the function-declarations after the structs but before defining the macros. */ void obstack_init (struct obstack *obstack); void * obstack_alloc (struct obstack *obstack, int size); void * obstack_copy (struct obstack *obstack, const void *address, int size); void * obstack_copy0 (struct obstack *obstack, const void *address, int size); void obstack_free (struct obstack *obstack, void *block); void obstack_blank (struct obstack *obstack, int size); void obstack_grow (struct obstack *obstack, const void *data, int size); void obstack_grow0 (struct obstack *obstack, const void *data, int size); void obstack_1grow (struct obstack *obstack, int data_char); void obstack_ptr_grow (struct obstack *obstack, const void *data); void obstack_int_grow (struct obstack *obstack, int data); void * obstack_finish (struct obstack *obstack); int obstack_object_size (struct obstack *obstack); int obstack_room (struct obstack *obstack); void obstack_make_room (struct obstack *obstack, int size); void obstack_1grow_fast (struct obstack *obstack, int data_char); void obstack_ptr_grow_fast (struct obstack *obstack, const void *data); void obstack_int_grow_fast (struct obstack *obstack, int data); void obstack_blank_fast (struct obstack *obstack, int size); void * obstack_base (struct obstack *obstack); void * obstack_next_free (struct obstack *obstack); int obstack_alignment_mask (struct obstack *obstack); int obstack_chunk_size (struct obstack *obstack); int obstack_memory_used (struct obstack *obstack); #endif /* __STDC__ */ /* Non-ANSI C cannot really support alternative functions for these macros, so we do not declare them. */ /* Error handler called when `obstack_chunk_alloc' failed to allocate more memory. This can be set to a user defined function which should either abort gracefully or use longjump - but shouldn't return. The default action is to print a message and abort. */ #if defined __STDC__ && __STDC__ extern void (*obstack_alloc_failed_handler) (void); #else extern void (*obstack_alloc_failed_handler) (); #endif /* Exit value used when `print_and_abort' is used. */ extern int obstack_exit_failure; /* Pointer to beginning of object being allocated or to be allocated next. Note that this might not be the final address of the object because a new chunk might be needed to hold the final size. */ #define obstack_base(h) ((h)->object_base) /* Size for allocating ordinary chunks. */ #define obstack_chunk_size(h) ((h)->chunk_size) /* Pointer to next byte not yet allocated in current chunk. */ #define obstack_next_free(h) ((h)->next_free) /* Mask specifying low bits that should be clear in address of an object. */ #define obstack_alignment_mask(h) ((h)->alignment_mask) /* To prevent prototype warnings provide complete argument list in standard C version. */ #if defined __STDC__ && __STDC__ # define obstack_init(h) \ _obstack_begin ((h), 0, 0, \ (void *(*) (long)) obstack_chunk_alloc, \ (void (*) (void *)) obstack_chunk_free) # define obstack_begin(h, size) \ _obstack_begin ((h), (size), 0, \ (void *(*) (long)) obstack_chunk_alloc, \ (void (*) (void *)) obstack_chunk_free) # define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ _obstack_begin ((h), (size), (alignment), \ (void *(*) (long)) (chunkfun), \ (void (*) (void *)) (freefun)) # define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ _obstack_begin_1 ((h), (size), (alignment), \ (void *(*) (void *, long)) (chunkfun), \ (void (*) (void *, void *)) (freefun), (arg)) # define obstack_chunkfun(h, newchunkfun) \ ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun)) # define obstack_freefun(h, newfreefun) \ ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun)) #else # define obstack_init(h) \ _obstack_begin ((h), 0, 0, \ (void *(*) ()) obstack_chunk_alloc, \ (void (*) ()) obstack_chunk_free) # define obstack_begin(h, size) \ _obstack_begin ((h), (size), 0, \ (void *(*) ()) obstack_chunk_alloc, \ (void (*) ()) obstack_chunk_free) # define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ _obstack_begin ((h), (size), (alignment), \ (void *(*) ()) (chunkfun), \ (void (*) ()) (freefun)) # define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ _obstack_begin_1 ((h), (size), (alignment), \ (void *(*) ()) (chunkfun), \ (void (*) ()) (freefun), (arg)) # define obstack_chunkfun(h, newchunkfun) \ ((h) -> chunkfun = (struct _obstack_chunk *(*)()) (newchunkfun)) # define obstack_freefun(h, newfreefun) \ ((h) -> freefun = (void (*)()) (newfreefun)) #endif #define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar) #define obstack_blank_fast(h,n) ((h)->next_free += (n)) #define obstack_memory_used(h) _obstack_memory_used (h) #if defined __GNUC__ && defined __STDC__ && __STDC__ /* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and does not implement __extension__. But that compiler doesn't define __GNUC_MINOR__. */ # if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__) # define __extension__ # endif /* For GNU C, if not -traditional, we can define these macros to compute all args only once without using a global variable. Also, we can avoid using the `temp' slot, to make faster code. */ # define obstack_object_size(OBSTACK) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ (unsigned) (__o->next_free - __o->object_base); }) # define obstack_room(OBSTACK) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ (unsigned) (__o->chunk_limit - __o->next_free); }) # define obstack_make_room(OBSTACK,length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ int __len = (length); \ if (__o->chunk_limit - __o->next_free < __len) \ _obstack_newchunk (__o, __len); \ (void) 0; }) # define obstack_empty_p(OBSTACK) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ (__o->chunk->prev == 0 && __o->next_free - __o->chunk->contents == 0); }) # define obstack_grow(OBSTACK,where,length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ int __len = (length); \ if (__o->next_free + __len > __o->chunk_limit) \ _obstack_newchunk (__o, __len); \ _obstack_memcpy (__o->next_free, (where), __len); \ __o->next_free += __len; \ (void) 0; }) # define obstack_grow0(OBSTACK,where,length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ int __len = (length); \ if (__o->next_free + __len + 1 > __o->chunk_limit) \ _obstack_newchunk (__o, __len + 1); \ _obstack_memcpy (__o->next_free, (where), __len); \ __o->next_free += __len; \ *(__o->next_free)++ = 0; \ (void) 0; }) # define obstack_1grow(OBSTACK,datum) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ if (__o->next_free + 1 > __o->chunk_limit) \ _obstack_newchunk (__o, 1); \ *(__o->next_free)++ = (datum); \ (void) 0; }) /* These assume that the obstack alignment is good enough for pointers or ints, and that the data added so far to the current object shares that much alignment. */ # define obstack_ptr_grow(OBSTACK,datum) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ if (__o->next_free + sizeof (void *) > __o->chunk_limit) \ _obstack_newchunk (__o, sizeof (void *)); \ *((void **)__o->next_free)++ = (datum); \ (void) 0; }) # define obstack_int_grow(OBSTACK,datum) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ if (__o->next_free + sizeof (int) > __o->chunk_limit) \ _obstack_newchunk (__o, sizeof (int)); \ *((int *)__o->next_free)++ = (datum); \ (void) 0; }) # define obstack_ptr_grow_fast(h,aptr) \ (*((void **) (h)->next_free)++ = (aptr)) # define obstack_int_grow_fast(h,aint) \ (*((int *) (h)->next_free)++ = (aint)) # define obstack_blank(OBSTACK,length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ int __len = (length); \ if (__o->chunk_limit - __o->next_free < __len) \ _obstack_newchunk (__o, __len); \ __o->next_free += __len; \ (void) 0; }) # define obstack_alloc(OBSTACK,length) \ __extension__ \ ({ struct obstack *__h = (OBSTACK); \ obstack_blank (__h, (length)); \ obstack_finish (__h); }) # define obstack_copy(OBSTACK,where,length) \ __extension__ \ ({ struct obstack *__h = (OBSTACK); \ obstack_grow (__h, (where), (length)); \ obstack_finish (__h); }) # define obstack_copy0(OBSTACK,where,length) \ __extension__ \ ({ struct obstack *__h = (OBSTACK); \ obstack_grow0 (__h, (where), (length)); \ obstack_finish (__h); }) /* The local variable is named __o1 to avoid a name conflict when obstack_blank is called. */ # define obstack_finish(OBSTACK) \ __extension__ \ ({ struct obstack *__o1 = (OBSTACK); \ void *value; \ value = (void *) __o1->object_base; \ if (__o1->next_free == value) \ __o1->maybe_empty_object = 1; \ __o1->next_free \ = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\ & ~ (__o1->alignment_mask)); \ if (__o1->next_free - (char *)__o1->chunk \ > __o1->chunk_limit - (char *)__o1->chunk) \ __o1->next_free = __o1->chunk_limit; \ __o1->object_base = __o1->next_free; \ value; }) # define obstack_free(OBSTACK, OBJ) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ void *__obj = (OBJ); \ if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \ __o->next_free = __o->object_base = (char *)__obj; \ else (obstack_free) (__o, __obj); }) #else /* not __GNUC__ or not __STDC__ */ # define obstack_object_size(h) \ (unsigned) ((h)->next_free - (h)->object_base) # define obstack_room(h) \ (unsigned) ((h)->chunk_limit - (h)->next_free) # define obstack_empty_p(h) \ ((h)->chunk->prev == 0 && (h)->next_free - (h)->chunk->contents == 0) /* Note that the call to _obstack_newchunk is enclosed in (..., 0) so that we can avoid having void expressions in the arms of the conditional expression. Casting the third operand to void was tried before, but some compilers won't accept it. */ # define obstack_make_room(h,length) \ ( (h)->temp = (length), \ (((h)->next_free + (h)->temp > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0)) # define obstack_grow(h,where,length) \ ( (h)->temp = (length), \ (((h)->next_free + (h)->temp > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ _obstack_memcpy ((h)->next_free, (where), (h)->temp), \ (h)->next_free += (h)->temp) # define obstack_grow0(h,where,length) \ ( (h)->temp = (length), \ (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \ _obstack_memcpy ((h)->next_free, (where), (h)->temp), \ (h)->next_free += (h)->temp, \ *((h)->next_free)++ = 0) # define obstack_1grow(h,datum) \ ( (((h)->next_free + 1 > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), 1), 0) : 0), \ (*((h)->next_free)++ = (datum))) # define obstack_ptr_grow(h,datum) \ ( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ (*((const char **) (((h)->next_free+=sizeof(char *))-sizeof(char *))) = (datum))) # define obstack_int_grow(h,datum) \ ( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ (*((int *) (((h)->next_free+=sizeof(int))-sizeof(int))) = (datum))) # define obstack_ptr_grow_fast(h,aptr) \ (*((const char **) (h)->next_free)++ = (aptr)) # define obstack_int_grow_fast(h,aint) \ (*((int *) (h)->next_free)++ = (aint)) # define obstack_blank(h,length) \ ( (h)->temp = (length), \ (((h)->chunk_limit - (h)->next_free < (h)->temp) \ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ ((h)->next_free += (h)->temp)) # define obstack_alloc(h,length) \ (obstack_blank ((h), (length)), obstack_finish ((h))) # define obstack_copy(h,where,length) \ (obstack_grow ((h), (where), (length)), obstack_finish ((h))) # define obstack_copy0(h,where,length) \ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h))) # define obstack_finish(h) \ ( ((h)->next_free == (h)->object_base \ ? (((h)->maybe_empty_object = 1), 0) \ : 0), \ (h)->temp = __PTR_TO_INT ((h)->object_base), \ (h)->next_free \ = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \ & ~ ((h)->alignment_mask)), \ (((h)->next_free - (char *) (h)->chunk \ > (h)->chunk_limit - (char *) (h)->chunk) \ ? ((h)->next_free = (h)->chunk_limit) : 0), \ (h)->object_base = (h)->next_free, \ __INT_TO_PTR ((h)->temp)) # if defined __STDC__ && __STDC__ # define obstack_free(h,obj) \ ( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \ (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ ? (int) ((h)->next_free = (h)->object_base \ = (h)->temp + (char *) (h)->chunk) \ : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0))) # else # define obstack_free(h,obj) \ ( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \ (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ ? (int) ((h)->next_free = (h)->object_base \ = (h)->temp + (char *) (h)->chunk) \ : (_obstack_free ((h), (h)->temp + (char *) (h)->chunk), 0))) # endif #endif /* not __GNUC__ or not __STDC__ */ #ifdef __cplusplus } /* C++ */ #endif #endif /* obstack.h */ argus-clients-2.0.6.fixes.1/ragrep/ragrep.c0000664000076600007660000006751107640610353014174 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * ragrep - egrep expression from captured user data. * * written by Carter Bullard * QoSient, LLC * */ #include #ifdef HAVE_CONFIG_H # include #endif #include #include #if defined(HAVE_MMAP) # include #endif #if defined(HAVE_SETRLIMIT) # include # include #endif #include #include "system.h" /* #if !defined(__FreeBSD__) #include "getopt.h" #endif */ #include "getpagesize.h" #include "ragrep.h" #undef MAX #define MAX(A,B) ((A) > (B) ? (A) : (B)) struct stats { struct stats *parent; struct stat stat; }; /* Short options. */ static char const short_options[] = "0123456789A:B:C::EFGHIUVX:abcd:e:f:hiLlnqrsuvwxyZz"; /* Non-boolean long options that have no corresponding short equivalents. */ enum { BINARY_FILES_OPTION = CHAR_MAX + 1 }; /* Long options equivalences. */ /* static struct option long_options[] = { {"after-context", required_argument, NULL, 'A'}, {"basic-regexp", no_argument, NULL, 'G'}, {"before-context", required_argument, NULL, 'B'}, {"binary-files", required_argument, NULL, BINARY_FILES_OPTION}, {"byte-offset", no_argument, NULL, 'b'}, {"context", optional_argument, NULL, 'C'}, {"count", no_argument, NULL, 'c'}, {"directories", required_argument, NULL, 'd'}, {"extended-regexp", no_argument, NULL, 'E'}, {"file", required_argument, NULL, 'f'}, {"files-with-matches", no_argument, NULL, 'l'}, {"files-without-match", no_argument, NULL, 'L'}, {"fixed-regexp", no_argument, NULL, 'F'}, {"fixed-strings", no_argument, NULL, 'F'}, {"help", no_argument, &show_help, 1}, {"ignore-case", no_argument, NULL, 'i'}, {"line-number", no_argument, NULL, 'n'}, {"line-regexp", no_argument, NULL, 'x'}, {"mmap", no_argument, &mmap_option, 1}, {"no-filename", no_argument, NULL, 'h'}, {"no-messages", no_argument, NULL, 's'}, {"null", no_argument, NULL, 'Z'}, {"null-data", no_argument, NULL, 'z'}, {"quiet", no_argument, NULL, 'q'}, {"recursive", no_argument, NULL, 'r'}, {"regexp", required_argument, NULL, 'e'}, {"invert-match", no_argument, NULL, 'v'}, {"silent", no_argument, NULL, 'q'}, {"text", no_argument, NULL, 'a'}, {"binary", no_argument, NULL, 'U'}, {"unix-byte-offsets", no_argument, NULL, 'u'}, {"version", no_argument, NULL, 'V'}, {"with-filename", no_argument, NULL, 'H'}, {"word-regexp", no_argument, NULL, 'w'}, {0, 0, 0, 0} }; */ /* Define flags declared in grep.h. */ int match_icase; int match_words; int match_lines; unsigned char eolbyte; /* For error messages. */ static char *prog; static int errseen; /* How to handle directories. */ /* static enum { READ_DIRECTORIES, RECURSE_DIRECTORIES, SKIP_DIRECTORIES } directories; */ static int install_matcher PARAMS ((char const *)); static int grepbuf PARAMS ((char *, char *)); /* Functions we'll use to search. */ static void (*compile) PARAMS ((char *, size_t)); static char *(*execute) PARAMS ((char *, size_t, char **)); /* Flags controlling the style of output. */ static int filename_mask = 0; /* If zero, output nulls after filenames. */ static int out_invert = 0; /* Print nonmatching stuff. */ static int out_before = 0; /* Lines of leading context. */ static int out_after = 0; /* Lines of trailing context. */ /* Internal variables to keep track of byte count, context, etc. */ static int done_on_match; /* Stop scanning file on first match */ int RaInitialized = 0; struct ArgusRecordStore *RaGblStore = NULL; void ArgusClientInit () { char *keys; size_t keycc = 0; int with_filenames; int default_context; unsigned digit_args_val; if (!(RaInitialized)) { RaWriteOut = 0; RaInitialized++; if (Hflag) RaHistoTimeSeries = ARGUS_TIMESERIES; if (nflag > 0) hfield = 15; if (nflag > 1) pfield = 5; if (!(estr)) usage (); if (idflag > 0) { match_icase = 1; idflag = 0; } else match_icase = 0; if ((keys = (char *) ArgusCalloc (1, strlen(estr) + 2)) != NULL) { bcopy (estr, keys, strlen(estr)); keycc = strlen(keys); } else ArgusLog (LOG_ERR, "ArgusClientInit: ArgusCalloc failed %s\n", strerror(errno)); with_filenames = 0; eolbyte = '\n'; filename_mask = ~0; SET_BINARY (desc); if (!install_matcher(matcher)) abort (); (*compile)(keys, keycc); /* The value -1 means to use DEFAULT_CONTEXT. */ out_after = out_before = -1; /* Default before/after context: chaged by -C/-NUM options */ default_context = 0; /* Accumulated value of individual digits in a -NUM option */ digit_args_val = 0; /* Internationalization. */ #if HAVE_SETLOCALE setlocale (LC_ALL, ""); #endif #if ENABLE_NLS bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); #endif } } int RaParseCompleting = 0; void RaParseComplete (int sig) { if ((sig >= 0) && (!RaParseCompleting)) { RaParseCompleting++; } } void ArgusClientTimeout () { } void parse_arg (int argc, char**argv) { } void usage () { fprintf (stderr, "Ragrep Version %d.%d\n", major_version, minor_version); fprintf (stderr, "usage: %s \n", ArgusProgramName); fprintf (stderr, "usage: %s -e PATTERN [ra-options] [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "options: -e match captured user data against regular expression.\n\n"); fprintf (stderr, "ra-options: -a print record summaries on termination.\n"); fprintf (stderr, " -A print application bytes.\n"); fprintf (stderr, " -b dump packet-matching code.\n"); fprintf (stderr, " -c print packet and byte counts.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); #if defined (ARGUSDEBUG) fprintf (stderr, " -D specify debug level\n"); #endif fprintf (stderr, " -E write records that are rejected by the filter into \n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -g print record time duration.\n"); fprintf (stderr, " -G print both start and last time values.\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -i print source probe id.\n"); fprintf (stderr, " -I print transaction state and option indicators.\n"); fprintf (stderr, " -l print last time values [default is start time].\n"); fprintf (stderr, " -m print MAC addresses.\n"); fprintf (stderr, " -n don't convert numbers to names.\n"); fprintf (stderr, " -p print fractional time with precision.\n"); fprintf (stderr, " -P specify remote argus (tcp/561).\n"); fprintf (stderr, " -q quiet mode. don't print record outputs.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -R print out response data when availabile.\n"); fprintf (stderr, " -S specify remote argus .\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [[[yyyy/]mm/]dd.]hh[:mm[:ss]]\n"); fprintf (stderr, " [yyyy/]mm/dd\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); fprintf (stderr, " -u print time in Unix time format.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif fprintf (stderr, " -w write output to . '-' denotes stdout.\n"); fprintf (stderr, " -z print Argus TCP state changes.\n"); fprintf (stderr, " -Z print actual TCP flag values.<'s'rc | 'd'st | 'b'oth>\n"); exit(1); } void RaProcessRecord (struct ArgusRecord *argus) { int len, retn; if (!(RaGblStore)) { if ((RaGblStore = RaNewArgusStore(argus)) != NULL) { if ((RaGblStore->data[0] = RaNewArgusData(argus)) == NULL) ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); } else ArgusLog (LOG_ERR, "RaNewArgusStore failed %s\n", strerror(errno)); } RaGblStore->data[0]->argus = argus; if (ArgusThisFarStatus & (ARGUS_SRCUSRDATA_DSR_STATUS | ARGUS_SRCUSRDATA_DSR_STATUS)) { if (ArgusThisFarStatus & ARGUS_SRCUSRDATA_DSR_STATUS) { struct ArgusUserStruct *user = (struct ArgusUserStruct *) ArgusThisFarHdrs[ARGUS_SRCUSRDATA_DSR_INDEX]; char *buf = &user->data; if (ArgusGrepSource) { len = (user->length - 1) * 4; len = (len > argus->argus_far.src.appbytes) ? argus->argus_far.src.appbytes : len; if ((retn = grepbuf (buf, &buf[len]))) { RaGblStore->data[0]->status |= RA_MODIFIED; RaSendArgusRecord(RaGblStore); return; } } } if (ArgusThisFarStatus & ARGUS_DSTUSRDATA_DSR_STATUS) { struct ArgusUserStruct *user = (struct ArgusUserStruct *) ArgusThisFarHdrs[ARGUS_DSTUSRDATA_DSR_INDEX]; char *buf = &user->data; if (ArgusGrepDestination) { len = (user->length - 1) * 4; len = (len > argus->argus_far.dst.appbytes) ? argus->argus_far.dst.appbytes : len; if ((retn = grepbuf (buf, &buf[len]))) { RaGblStore->data[0]->status |= RA_MODIFIED; RaSendArgusRecord(RaGblStore); return; } } } } } #include int RaSendArgusRecord(struct ArgusRecordStore *store) { unsigned char buf[MAXSTRLEN]; struct ArgusRecordData *data; struct ArgusRecord *argus = NULL; struct ArgusFarHeaderStruct *farhdr; struct ArgusAGRStruct *agr = NULL; int retn = 0, i; for (i = 0; i < RaHistoTimeSeries; i++) { if ((data = store->data[i]) != NULL) { argus = data->argus; if (argus && (data->status & RA_MODIFIED)) { if (data->act.n > 0) { data->agr.act.n = data->act.n; data->agr.act.meanval = data->act.sumtime/data->act.n; data->agr.act.stdev = (unsigned int) sqrt (data->act.sumsqrd/data->act.n - pow (data->act.sumtime/data->act.n, 2.0)); } if (data->idle.n > 0) { data->agr.idle.n = data->idle.n; data->agr.idle.meanval = data->idle.sumtime/data->idle.n; data->agr.idle.stdev = (unsigned int) sqrt (data->idle.sumsqrd/data->idle.n - pow (data->idle.sumtime/data->idle.n, 2.0)); } if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) != NULL) { bcopy ((char *)&data->agr, (char *)agr, data->agr.length); } bcopy ((char *) argus, buf, argus->ahdr.length); argus = (struct ArgusRecord *) buf; ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) == NULL) { if (ArgusFlowModelFile && (data->agr.count > 1)) { bcopy ((char *)&data->agr, &buf[argus->ahdr.length], data->agr.length); argus->ahdr.length += data->agr.length; argus->ahdr.status |= ARGUS_MERGED; ArgusFree (data->argus); data->argus = RaCopyArgusRecord(argus); ArgusThisFarStatus = ArgusIndexRecord(data->argus, ArgusThisFarHdrs); } else { argus->ahdr.status &= ~(ARGUS_MERGED); } } if ((ArgusWfileList != NULL) && (!(ArgusListEmpty(ArgusWfileList)))) { struct ArgusWfileStruct *wfile = NULL, *start = NULL; if ((wfile = ArgusFrontList(ArgusWfileList)) != NULL) { start = wfile; do { if ((exceptfile == NULL) || strcmp(wfile->filename, exceptfile)) { #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif ArgusWriteNewLogfile (wfile, argus); #ifdef _LITTLE_ENDIAN ArgusNtoH(argus); #endif } ArgusPopFrontList(ArgusWfileList); ArgusPushBackList(ArgusWfileList, wfile); wfile = ArgusFrontList(ArgusWfileList); } while (wfile != start); } } else { if (argus->ahdr.type & ARGUS_MAR) printf ("%s\n", get_man_string (argus)); else { ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: printf ("%s", get_tcp_string (argus)); break; case IPPROTO_ICMP: printf ("%s", get_icmp_string (argus)); break; default: printf ("%s", get_ip_string (argus)); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: printf ("%s", get_arp_string (argus)); break; default: printf ("%s", get_nonip_string (argus)); break; } if (ArgusSrcUserDataLen || ArgusDstUserDataLen) printf ("%s\n", RaGetUserDataString(argus)); else printf ("\n"); } fflush (stdout); } argus = data->argus; if (argus->ahdr.type & ARGUS_FAR) { int farlen, length = argus->ahdr.length - sizeof(argus->ahdr); farhdr = (struct ArgusFarHeaderStruct *)((char *)argus + sizeof(argus->ahdr)); while (length > 0) { switch (farhdr->type) { case ARGUS_FAR: { struct ArgusFarStruct *far = (struct ArgusFarStruct *) farhdr; far->time.start.tv_sec = 0x7FFFFFFF; far->time.start.tv_usec = 0; far->time.last.tv_sec = 0; far->time.last.tv_usec = 0; far->src.count = 0; far->src.bytes = 0; far->dst.count = 0; far->dst.bytes = 0; break; } case ARGUS_TCP_DSR: { struct ArgusTCPObject *tcp = (struct ArgusTCPObject *) farhdr; tcp->state = 0; tcp->src.seqbase = 0; tcp->src.ackbytes = 0; tcp->src.rpkts = 0; tcp->src.win = 0; tcp->src.flags = 0; tcp->dst.seqbase = 0; tcp->dst.ackbytes = 0; tcp->dst.rpkts = 0; tcp->dst.win = 0; tcp->dst.flags = 0; break; } case ARGUS_TIME_DSR: { struct ArgusTimeStruct *time = (struct ArgusTimeStruct *) farhdr; time->src.act.n = 0; time->src.act.meanval = 0; time->src.act.stdev = 0; time->src.act.maxval = 0; time->src.act.minval = 0x7FFFFFFF; time->src.idle.n = 0; time->src.idle.meanval = 0; time->src.idle.stdev = 0; time->src.idle.maxval = 0; time->src.idle.minval = 0x7FFFFFFF; time->dst.act.n = 0; time->dst.act.meanval = 0; time->dst.act.stdev = 0; time->dst.act.maxval = 0; time->dst.act.minval = 0x7FFFFFFF; time->dst.idle.n = 0; time->dst.idle.meanval = 0; time->dst.idle.stdev = 0; time->dst.idle.maxval = 0; time->dst.idle.minval = 0x7FFFFFFF; break; } case ARGUS_VLAN_DSR: { struct ArgusVlanStruct *vlan = (struct ArgusVlanStruct *) farhdr; vlan->status &= ~(ARGUS_SRC_CHANGED | ARGUS_DST_CHANGED); break; } case ARGUS_MPLS_DSR: { struct ArgusMplsStruct *mpls = (struct ArgusMplsStruct *) farhdr; mpls->status &= ~(ARGUS_SRC_CHANGED | ARGUS_DST_CHANGED); break; } case ARGUS_AGR_DSR: { struct ArgusAGRStruct *agr = (struct ArgusAGRStruct *) farhdr; agr->count = 0; agr->act.n = 0; agr->act.minval = 0x7FFFFFFF; agr->act.meanval = 0; agr->act.stdev = 0; agr->act.maxval = 0; agr->idle.n = 0; agr->idle.minval = 0x7FFFFFFF; agr->idle.meanval = 0; agr->idle.stdev = 0; agr->idle.maxval = 0; break; } } if ((farlen = farhdr->length) == 0) break; if ((farhdr->type == ARGUS_SRCUSRDATA_DSR) || (farhdr->type == ARGUS_DSTUSRDATA_DSR)) farlen = farlen * 4; length -= farlen; farhdr = (struct ArgusFarHeaderStruct *)((char *)farhdr + farlen); } } data->agr.count = 0; data->agr.act.n = 0; data->agr.act.meanval = 0; data->agr.act.stdev = 0; data->agr.act.maxval = 0; data->agr.act.minval = 0x7FFFFFFF; data->agr.idle.n = 0; data->agr.idle.meanval = 0; data->agr.idle.stdev = 0; data->agr.idle.maxval = 0; data->agr.idle.minval = 0x7FFFFFFF; data->act.n = 0; data->act.sumtime = 0; data->act.sumsqrd = 0; data->idle.n = 0; data->idle.sumtime = 0; data->idle.sumtime = 0; data->argus->ahdr.status &= ~ARGUS_MERGED; data->status &= ~RA_MODIFIED; } } } store->qhdr.logtime = ArgusGlobalTime; #ifdef ARGUSDEBUG ArgusDebug (4, "RaSendArgusRecord(0x%x) done.\n", store); #endif return (retn); } /* ragrep.c - main driver file for ragrep. * Copyright 2000, QoSient, LLC. * Completely derived from grep-2.4.2. */ /* grep.c - main driver file for grep. Copyright 1992, 1997-1999, 2000 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Written July 1992 by Mike Haertel. */ static void error (const char *mesg, int errnum) { if (errnum) fprintf (stderr, "%s: %s: %s\n", prog, mesg, strerror (errnum)); else fprintf (stderr, "%s: %s\n", prog, mesg); errseen = 1; } /* Like error (), but die horribly after printing. */ void fatal (const char *mesg, int errnum) { error (mesg, errnum); exit (2); } /* Interface to handle errors and fix library lossage. */ char * xmalloc (size_t size) { char *result; result = malloc (size); if (size && !result) fatal (_("memory exhausted"), 0); return result; } char * xcalloc (size_t, size_t); char * xcalloc (size_t num, size_t size) { char *result; result = calloc (num, size); if (size && !result) fatal (_("memory exhausted"), 0); return result; } /* Interface to handle errors and fix some library lossage. */ char * xrealloc (char *ptr, size_t size) { char *result; if (ptr) result = realloc (ptr, size); else result = malloc (size); if (size && !result) fatal (_("memory exhausted"), 0); return result; } /* Convert STR to a positive integer, storing the result in *OUT. If STR is not a valid integer, return -1 (otherwise 0). */ /* static int ck_atoi (char const *str, int *out) { char const *p; for (p = str; *p; p++) if (*p < '0' || *p > '9') return -1; *out = atoi (optarg); return 0; } */ /* Hairy buffering mechanism for grep. The intent is to keep all reads aligned on a page boundary and multiples of the page size. */ #define PREFERRED_SAVE_FACTOR 5 /* Preferred value of bufalloc / bufsalloc. */ #if defined(HAVE_MMAP) static int bufmapped; /* True if buffer is memory-mapped. */ static off_t initial_bufoffset; /* Initial value of bufoffset. */ #endif /* Return VAL aligned to the next multiple of ALIGNMENT. VAL can be an integer or a pointer. Both args must be free of side effects. */ #define ALIGN_TO(val, alignment) \ ((size_t) (val) % (alignment) == 0 \ ? (val) \ : (val) + ((alignment) - (size_t) (val) % (alignment))) /* Return the address of a page-aligned buffer of size SIZE, reallocating it from *UP. Set *UP to the newly allocated (but possibly unaligned) buffer used to build the aligned buffer. To free the buffer, free (*UP). */ /* static char * page_alloc (size_t size, char **up) { size_t asize = size + pagesize - 1; if (size <= asize) { char *p = *up ? xrealloc (*up, asize) : xmalloc (asize); if (p) { *up = p; return ALIGN_TO (p, pagesize); } } return NULL; } */ #if O_BINARY #include "dosbuf.c" #endif /* static void nlscan (char *lim) { char *beg; for (beg = lastnl; (beg = memchr (beg, eolbyte, lim - beg)); beg++) totalnl++; lastnl = lim; } */ /* Scan the specified portion of the buffer, matching lines (or between matching lines if OUT_INVERT is true). Return a count of lines printed. */ static int grepbuf (char *beg, char *lim) { int nlines; register char *p, *b; char *endp; char eol = eolbyte; nlines = 0; p = beg; while ((b = (*execute)(p, lim - p, &endp)) != 0) { /* Avoid matching the empty line at the end of the buffer. */ if (b == lim && ((b > beg && b[-1] == eol) || b == beg)) break; if (!out_invert) { nlines += 1; if (done_on_match) return nlines; } else if (p < b) { nlines += 1; } p = endp; } if (out_invert && p < lim) nlines += 1; if (vflag) nlines = (nlines > 0) ? 0 : 1; return nlines; } /* Set the matcher to M, reporting any conflicts. */ /* static void setmatcher (char const *m) { if (matcher && strcmp (matcher, m) != 0) fatal (_("conflicting matchers specified"), 0); matcher = m; } */ /* Go through the matchers vector and look for the specified matcher. If we find it, install it in compile and execute, and return 1. */ static int install_matcher (char const *name) { int i; #ifdef HAVE_SETRLIMIT struct rlimit rlim; #endif for (i = 0; matchers[i].name; ++i) { if (strcmp (name, matchers[i].name) == 0) { compile = matchers[i].compile; execute = matchers[i].execute; #if HAVE_SETRLIMIT && defined(RLIMIT_STACK) /* I think every platform needs to do this, so that regex.c doesn't oveflow the stack. The default value of `re_max_failures' is too large for some platforms: it needs more than 3MB-large stack. The test for HAVE_SETRLIMIT should go into `configure'. */ if (!getrlimit (RLIMIT_STACK, &rlim)) { long newlim; extern long int re_max_failures; /* from regex.c */ /* Approximate the amount regex.c needs, plus some more. */ newlim = re_max_failures * 2 * 20 * sizeof (char *); if (newlim > rlim.rlim_max) { newlim = rlim.rlim_max; re_max_failures = newlim / (2 * 20 * sizeof (char *)); } if (rlim.rlim_cur < newlim) rlim.rlim_cur = newlim; setrlimit (RLIMIT_STACK, &rlim); } #endif return 1; } } return 0; } /* Find the white-space-separated options specified by OPTIONS, and using BUF to store copies of these options, set ARGV[0], ARGV[1], etc. to the option copies. Return the number N of options found. Do not set ARGV[N] to NULL. If ARGV is NULL, do not store ARGV[0] etc. Backslash can be used to escape whitespace (and backslashes). */ /* static int prepend_args (char const *options, char *buf, char **argv) { char const *o = options; char *b = buf; int n = 0; for (;;) { while (ISSPACE ((unsigned char) *o)) o++; if (!*o) return n; if (argv) argv[n] = b; n++; do if ((*b++ = *o++) == '\\' && *o) b[-1] = *o++; while (*o && ! ISSPACE ((unsigned char) *o)); *b++ = '\0'; } } */ /* Prepend the whitespace-separated options in OPTIONS to the argument vector of a main program with argument count *PARGC and argument vector *PARGV. */ /* static void prepend_default_options (char const *options, int *pargc, char ***pargv) { if (options) { char *buf = xmalloc (strlen (options) + 1); int prepended = prepend_args (options, buf, (char **) NULL); int argc = *pargc; char * const *argv = *pargv; char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp); *pargc = prepended + argc; *pargv = pp; *pp++ = *argv++; pp += prepend_args (options, buf, pp); while ((*pp++ = *argv++)) continue; } } */ argus-clients-2.0.6.fixes.1/ragrep/ragrep.h0000664000076600007660000000327007310146216014165 /* grep.h - interface to grep driver for searching subroutines. Copyright (C) 1992, 1998 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6) || __STRICT_ANSI__ # define __attribute__(x) #endif extern void fatal PARAMS ((const char *, int)) __attribute__((noreturn)); extern char *xmalloc PARAMS ((size_t size)); extern char *xrealloc PARAMS ((char *ptr, size_t size)); /* Grep.c expects the matchers vector to be terminated by an entry with a NULL name, and to contain at least an entry named "default". */ extern struct matcher { char *name; void (*compile) PARAMS ((char *, size_t)); char *(*execute) PARAMS ((char *, size_t, char **)); } matchers[]; /* Exported from fgrepmat.c, egrepmat.c, grepmat.c. */ extern char const *matcher; /* The following flags are exported from grep for the matchers to look at. */ extern int match_icase; /* -i */ extern int match_words; /* -w */ extern int match_lines; /* -x */ extern unsigned char eolbyte; /* -z */ argus-clients-2.0.6.fixes.1/ragrep/regex.c0000664000076600007660000056044507725257001014033 /* Extended regular expression matching and search library, version 0.12. (Implements POSIX draft P1003.2/D11.2, except for some of the internationalization features.) Copyright (C) 1993, 94, 95, 96, 97, 98, 99 Free Software Foundation, Inc. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* AIX requires this to be the first thing in the file. */ #if defined _AIX && !defined REGEX_MALLOC #pragma alloca #endif #undef _GNU_SOURCE #define _GNU_SOURCE #ifdef HAVE_CONFIG_H # include #endif #ifndef PARAMS # if defined __GNUC__ || (defined __STDC__ && __STDC__) # define PARAMS(args) args # else # define PARAMS(args) () # endif /* GCC. */ #endif /* Not PARAMS. */ #if defined STDC_HEADERS && !defined emacs # include #else /* We need this for `regex.h', and perhaps for the Emacs include files. */ # include #endif #define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC) /* For platform which support the ISO C amendement 1 functionality we support user defined character classes. */ #if defined _LIBC || WIDE_CHAR_SUPPORT /* Solaris 2.5 has a bug: must be included before . */ # include # include #endif #ifdef _LIBC /* We have to keep the namespace clean. */ # define Rregfree(preg) __Rregfree (preg) # define Rregexec(pr, st, nm, pm, ef) __Rregexec (pr, st, nm, pm, ef) # define Rregcomp(preg, pattern, cflags) __Rregcomp (preg, pattern, cflags) # define Rregerror(errcode, preg, errbuf, errbuf_size) \ __Rregerror(errcode, preg, errbuf, errbuf_size) # define re_set_registers(bu, re, nu, st, en) \ __re_set_registers (bu, re, nu, st, en) # define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) # define re_match(bufp, string, size, pos, regs) \ __re_match (bufp, string, size, pos, regs) # define re_search(bufp, string, size, startpos, range, regs) \ __re_search (bufp, string, size, startpos, range, regs) # define re_compile_pattern(pattern, length, bufp) \ __re_compile_pattern (pattern, length, bufp) # define re_set_syntax(syntax) __re_set_syntax (syntax) # define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) # define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) #define btowc __btowc #endif #ifndef _ /* This is for other GNU distributions with internationalized messages. When compiling libc, the _ and N_ macros are predefined. */ # ifdef HAVE_LIBINTL_H # include # else # define gettext(msgid) (msgid) # endif # define N_(msgid) (msgid) #endif /* The `emacs' switch turns on certain matching commands that make sense only in Emacs. */ #ifdef emacs # include "lisp.h" # include "buffer.h" # include "syntax.h" #else /* not emacs */ /* If we are not linking with Emacs proper, we can't use the relocating allocator even if config.h says that we can. */ # undef REL_ALLOC # if defined STDC_HEADERS || defined _LIBC # include # endif extern char *xmalloc (size_t); extern char *xrealloc (size_t); /* When used in Emacs's lib-src, we need to get bzero and bcopy somehow. If nothing else has been done, use the method below. */ # ifdef INHIBIT_STRING_HEADER # if !(defined HAVE_BZERO && defined HAVE_BCOPY) # if !defined bzero && !defined bcopy # undef INHIBIT_STRING_HEADER # endif # endif # endif /* This is the normal way of making sure we have a bcopy and a bzero. This is used in most programs--a few other programs avoid this by defining INHIBIT_STRING_HEADER. */ # ifndef INHIBIT_STRING_HEADER # if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC # include # ifndef bzero # ifndef _LIBC # define bzero(s, n) (memset (s, '\0', n), (s)) # else # define bzero(s, n) __bzero (s, n) # endif # endif # else # include # ifndef memcmp # define memcmp(s1, s2, n) bcmp (s1, s2, n) # endif # ifndef memcpy # define memcpy(d, s, n) (bcopy (s, d, n), (d)) # endif # endif # endif /* Define the syntax stuff for \<, \>, etc. */ /* This must be nonzero for the wordchar and notwordchar pattern commands in re_match_2. */ # ifndef Sword # define Sword 1 # endif # ifdef SWITCH_ENUM_BUG # define SWITCH_ENUM_CAST(x) ((int)(x)) # else # define SWITCH_ENUM_CAST(x) (x) # endif #endif /* not emacs */ /* Get the interface, including the syntax bits. */ #include /* isalpha etc. are used for the character classes. */ #include /* Jim Meyering writes: "... Some ctype macros are valid only for character codes that isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when using /bin/cc or gcc but without giving an ansi option). So, all ctype uses should be through macros like ISPRINT... If STDC_HEADERS is defined, then autoconf has verified that the ctype macros don't need to be guarded with references to isascii. ... Defining isascii to 1 should let any compiler worth its salt eliminate the && through constant folding." Solaris defines some of these symbols so we must undefine them first. */ #undef ISASCII #if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) # define ISASCII(c) 1 #else # define ISASCII(c) isascii(c) #endif #ifdef isblank # define ISBLANK(c) (ISASCII (c) && isblank (c)) #else # define ISBLANK(c) ((c) == ' ' || (c) == '\t') #endif #ifdef isgraph # define ISGRAPH(c) (ISASCII (c) && isgraph (c)) #else # define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) #endif #undef ISPRINT #define ISPRINT(c) (ISASCII (c) && isprint (c)) #define ISDIGIT(c) (ISASCII (c) && isdigit (c)) #define ISALNUM(c) (ISASCII (c) && isalnum (c)) #define ISALPHA(c) (ISASCII (c) && isalpha (c)) #define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) #define ISLOWER(c) (ISASCII (c) && islower (c)) #define ISPUNCT(c) (ISASCII (c) && ispunct (c)) #define ISSPACE(c) (ISASCII (c) && isspace (c)) #define ISUPPER(c) (ISASCII (c) && isupper (c)) #define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) #ifdef _tolower # define TOLOWER(c) _tolower(c) #else # define TOLOWER(c) tolower(c) #endif #ifndef NULL # define NULL (void *)0 #endif /* We remove any previous definition of `SIGN_EXTEND_CHAR', since ours (we hope) works properly with all combinations of machines, compilers, `char' and `unsigned char' argument types. (Per Bothner suggested the basic approach.) */ #undef SIGN_EXTEND_CHAR #if __STDC__ # define SIGN_EXTEND_CHAR(c) ((signed char) (c)) #else /* not __STDC__ */ /* As in Harbison and Steele. */ # define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) #endif #ifndef emacs /* How many characters in the character set. */ # define CHAR_SET_SIZE 256 # ifdef SYNTAX_TABLE extern char *re_syntax_table; # else /* not SYNTAX_TABLE */ static char re_syntax_table[CHAR_SET_SIZE]; static void init_syntax_once (void); static void init_syntax_once () { register int c; static int done = 0; if (done) return; bzero (re_syntax_table, sizeof re_syntax_table); for (c = 0; c < CHAR_SET_SIZE; ++c) if (ISALNUM (c)) re_syntax_table[c] = Sword; re_syntax_table['_'] = Sword; done = 1; } # endif /* not SYNTAX_TABLE */ # define SYNTAX(c) re_syntax_table[((c) & 0xFF)] #endif /* emacs */ /* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we use `alloca' instead of `malloc'. This is because using malloc in re_search* or re_match* could cause memory leaks when C-g is used in Emacs; also, malloc is slower and causes storage fragmentation. On the other hand, malloc is more portable, and easier to debug. Because we sometimes use alloca, some routines have to be macros, not functions -- `alloca'-allocated space disappears at the end of the function it is called in. */ #ifdef REGEX_MALLOC # define REGEX_ALLOCATE malloc # define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) # define REGEX_FREE free #else /* not REGEX_MALLOC */ /* Emacs already defines alloca, sometimes. */ # ifndef alloca /* Make alloca work the best possible way. */ # ifdef __GNUC__ # define alloca __builtin_alloca # else /* not __GNUC__ */ # ifdef HAVE_SOLARIS # include # endif # if HAVE_ALLOCA_H # include # endif /* HAVE_ALLOCA_H */ # endif /* not __GNUC__ */ # endif /* not alloca */ # define REGEX_ALLOCATE alloca /* Assumes a `char *destination' variable. */ # define REGEX_REALLOCATE(source, osize, nsize) \ (destination = (char *) alloca (nsize), \ memcpy (destination, source, osize)) /* No need to do anything to free, after alloca. */ # define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */ #endif /* not REGEX_MALLOC */ /* Define how to allocate the failure stack. */ #if defined REL_ALLOC && defined REGEX_MALLOC # define REGEX_ALLOCATE_STACK(size) \ r_alloc (&failure_stack_ptr, (size)) # define REGEX_REALLOCATE_STACK(source, osize, nsize) \ r_re_alloc (&failure_stack_ptr, (nsize)) # define REGEX_FREE_STACK(ptr) \ r_alloc_free (&failure_stack_ptr) #else /* not using relocating allocator */ # ifdef REGEX_MALLOC # define REGEX_ALLOCATE_STACK xmalloc # define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize) # define REGEX_FREE_STACK free # else /* not REGEX_MALLOC */ # define REGEX_ALLOCATE_STACK alloca # define REGEX_REALLOCATE_STACK(source, osize, nsize) \ REGEX_REALLOCATE (source, osize, nsize) /* No need to explicitly free anything. */ # define REGEX_FREE_STACK(arg) # endif /* not REGEX_MALLOC */ #endif /* not using relocating allocator */ /* True if `size1' is non-NULL and PTR is pointing anywhere inside `string1' or just past its end. This works if PTR is NULL, which is a good thing. */ #define FIRST_STRING_P(ptr) \ (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) /* (Re)Allocate N items of type T using malloc, or fail. */ #define TALLOC(n, t) ((t *) xmalloc ((n) * sizeof (t))) #define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) #define RETALLOC_IF(addr, n, t) \ if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t) #define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) #define BYTEWIDTH 8 /* In bits. */ #define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) #undef MAX #undef MIN #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) typedef char boolean; #define false 0 #define true 1 static int re_match_2_internal PARAMS ((struct re_pattern_buffer *bufp, const char *string1, int size1, const char *string2, int size2, int pos, struct re_registers *regs, int stop)); /* These are the command codes that appear in compiled regular expressions. Some opcodes are followed by argument bytes. A command code can specify any interpretation whatsoever for its arguments. Zero bytes may appear in the compiled regular expression. */ typedef enum { no_op = 0, /* Succeed right away--no more backtracking. */ succeed, /* Followed by one byte giving n, then by n literal bytes. */ exactn, /* Matches any (more or less) character. */ anychar, /* Matches any one char belonging to specified set. First following byte is number of bitmap bytes. Then come bytes for a bitmap saying which chars are in. Bits in each byte are ordered low-bit-first. A character is in the set if its bit is 1. A character too large to have a bit in the map is automatically not in the set. */ charset, /* Same parameters as charset, but match any character that is not one of those specified. */ charset_not, /* Start remembering the text that is matched, for storing in a register. Followed by one byte with the register number, in the range 0 to one less than the pattern buffer's re_nsub field. Then followed by one byte with the number of groups inner to this one. (This last has to be part of the start_memory only because we need it in the on_failure_jump of re_match_2.) */ start_memory, /* Stop remembering the text that is matched and store it in a memory register. Followed by one byte with the register number, in the range 0 to one less than `re_nsub' in the pattern buffer, and one byte with the number of inner groups, just like `start_memory'. (We need the number of inner groups here because we don't have any easy way of finding the corresponding start_memory when we're at a stop_memory.) */ stop_memory, /* Match a duplicate of something remembered. Followed by one byte containing the register number. */ duplicate, /* Fail unless at beginning of line. */ begline, /* Fail unless at end of line. */ endline, /* Succeeds if at beginning of buffer (if emacs) or at beginning of string to be matched (if not). */ begbuf, /* Analogously, for end of buffer/string. */ endbuf, /* Followed by two byte relative address to which to jump. */ jump, /* Same as jump, but marks the end of an alternative. */ jump_past_alt, /* Followed by two-byte relative address of place to resume at in case of failure. */ on_failure_jump, /* Like on_failure_jump, but pushes a placeholder instead of the current string position when executed. */ on_failure_keep_string_jump, /* Throw away latest failure point and then jump to following two-byte relative address. */ pop_failure_jump, /* Change to pop_failure_jump if know won't have to backtrack to match; otherwise change to jump. This is used to jump back to the beginning of a repeat. If what follows this jump clearly won't match what the repeat does, such that we can be sure that there is no use backtracking out of repetitions already matched, then we change it to a pop_failure_jump. Followed by two-byte address. */ maybe_pop_jump, /* Jump to following two-byte address, and push a dummy failure point. This failure point will be thrown away if an attempt is made to use it for a failure. A `+' construct makes this before the first repeat. Also used as an intermediary kind of jump when compiling an alternative. */ dummy_failure_jump, /* Push a dummy failure point and continue. Used at the end of alternatives. */ push_dummy_failure, /* Followed by two-byte relative address and two-byte number n. After matching N times, jump to the address upon failure. */ succeed_n, /* Followed by two-byte relative address, and two-byte number n. Jump to the address N times, then fail. */ jump_n, /* Set the following two-byte relative address to the subsequent two-byte number. The address *includes* the two bytes of number. */ set_number_at, wordchar, /* Matches any word-constituent character. */ notwordchar, /* Matches any char that is not a word-constituent. */ wordbeg, /* Succeeds if at word beginning. */ wordend, /* Succeeds if at word end. */ wordbound, /* Succeeds if at a word boundary. */ notwordbound /* Succeeds if not at a word boundary. */ #ifdef emacs ,before_dot, /* Succeeds if before point. */ at_dot, /* Succeeds if at point. */ after_dot, /* Succeeds if after point. */ /* Matches any character whose syntax is specified. Followed by a byte which contains a syntax code, e.g., Sword. */ syntaxspec, /* Matches any character whose syntax is not that specified. */ notsyntaxspec #endif /* emacs */ } re_opcode_t; /* Common operations on the compiled pattern. */ /* Store NUMBER in two contiguous bytes starting at DESTINATION. */ #define STORE_NUMBER(destination, number) \ do { \ (destination)[0] = (number) & 0377; \ (destination)[1] = (number) >> 8; \ } while (0) /* Same as STORE_NUMBER, except increment DESTINATION to the byte after where the number is stored. Therefore, DESTINATION must be an lvalue. */ #define STORE_NUMBER_AND_INCR(destination, number) \ do { \ STORE_NUMBER (destination, number); \ (destination) += 2; \ } while (0) /* Put into DESTINATION a number stored in two contiguous bytes starting at SOURCE. */ #define EXTRACT_NUMBER(destination, source) \ do { \ (destination) = *(source) & 0377; \ (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ } while (0) #ifdef DEBUG static void extract_number _RE_ARGS ((int *dest, unsigned char *source)); static void extract_number (dest, source) int *dest; unsigned char *source; { int temp = SIGN_EXTEND_CHAR (*(source + 1)); *dest = *source & 0377; *dest += temp << 8; } # ifndef EXTRACT_MACROS /* To debug the macros. */ # undef EXTRACT_NUMBER # define EXTRACT_NUMBER(dest, src) extract_number (&dest, src) # endif /* not EXTRACT_MACROS */ #endif /* DEBUG */ /* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. SOURCE must be an lvalue. */ #define EXTRACT_NUMBER_AND_INCR(destination, source) \ do { \ EXTRACT_NUMBER (destination, source); \ (source) += 2; \ } while (0) #ifdef DEBUG static void extract_number_and_incr _RE_ARGS ((int *destination, unsigned char **source)); static void extract_number_and_incr (destination, source) int *destination; unsigned char **source; { extract_number (destination, *source); *source += 2; } # ifndef EXTRACT_MACROS # undef EXTRACT_NUMBER_AND_INCR # define EXTRACT_NUMBER_AND_INCR(dest, src) \ extract_number_and_incr (&dest, &src) # endif /* not EXTRACT_MACROS */ #endif /* DEBUG */ /* If DEBUG is defined, Regex prints many voluminous messages about what it is doing (if the variable `debug' is nonzero). If linked with the main program in `iregex.c', you can enter patterns and strings interactively. And if linked with the main program in `main.c' and the other test files, you can run the already-written tests. */ #ifdef DEBUG /* We use standard I/O for debugging. */ # include /* It is useful to test things that ``must'' be true when debugging. */ # include static int debug; # define DEBUG_STATEMENT(e) e # define DEBUG_PRINT1(x) if (debug) printf (x) # define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) # define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) # define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) # define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ if (debug) print_partial_compiled_pattern (s, e) # define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ if (debug) print_double_string (w, s1, sz1, s2, sz2) /* Print the fastmap in human-readable form. */ void print_fastmap (fastmap) char *fastmap; { unsigned was_a_range = 0; unsigned i = 0; while (i < (1 << BYTEWIDTH)) { if (fastmap[i++]) { was_a_range = 0; putchar (i - 1); while (i < (1 << BYTEWIDTH) && fastmap[i]) { was_a_range = 1; i++; } if (was_a_range) { printf ("-"); putchar (i - 1); } } } putchar ('\n'); } /* Print a compiled pattern string in human-readable form, starting at the START pointer into it and ending just before the pointer END. */ void print_partial_compiled_pattern (start, end) unsigned char *start; unsigned char *end; { int mcnt, mcnt2; unsigned char *p1; unsigned char *p = start; unsigned char *pend = end; if (start == NULL) { printf ("(null)\n"); return; } /* Loop over pattern commands. */ while (p < pend) { printf ("%d:\t", p - start); switch ((re_opcode_t) *p++) { case no_op: printf ("/no_op"); break; case exactn: mcnt = *p++; printf ("/exactn/%d", mcnt); do { putchar ('/'); putchar (*p++); } while (--mcnt); break; case start_memory: mcnt = *p++; printf ("/start_memory/%d/%d", mcnt, *p++); break; case stop_memory: mcnt = *p++; printf ("/stop_memory/%d/%d", mcnt, *p++); break; case duplicate: printf ("/duplicate/%d", *p++); break; case anychar: printf ("/anychar"); break; case charset: case charset_not: { register int c, last = -100; register int in_range = 0; printf ("/charset [%s", (re_opcode_t) *(p - 1) == charset_not ? "^" : ""); assert (p + *p < pend); for (c = 0; c < 256; c++) if (c / 8 < *p && (p[1 + (c/8)] & (1 << (c % 8)))) { /* Are we starting a range? */ if (last + 1 == c && ! in_range) { putchar ('-'); in_range = 1; } /* Have we broken a range? */ else if (last + 1 != c && in_range) { putchar (last); in_range = 0; } if (! in_range) putchar (c); last = c; } if (in_range) putchar (last); putchar (']'); p += 1 + *p; } break; case begline: printf ("/begline"); break; case endline: printf ("/endline"); break; case on_failure_jump: extract_number_and_incr (&mcnt, &p); printf ("/on_failure_jump to %d", p + mcnt - start); break; case on_failure_keep_string_jump: extract_number_and_incr (&mcnt, &p); printf ("/on_failure_keep_string_jump to %d", p + mcnt - start); break; case dummy_failure_jump: extract_number_and_incr (&mcnt, &p); printf ("/dummy_failure_jump to %d", p + mcnt - start); break; case push_dummy_failure: printf ("/push_dummy_failure"); break; case maybe_pop_jump: extract_number_and_incr (&mcnt, &p); printf ("/maybe_pop_jump to %d", p + mcnt - start); break; case pop_failure_jump: extract_number_and_incr (&mcnt, &p); printf ("/pop_failure_jump to %d", p + mcnt - start); break; case jump_past_alt: extract_number_and_incr (&mcnt, &p); printf ("/jump_past_alt to %d", p + mcnt - start); break; case jump: extract_number_and_incr (&mcnt, &p); printf ("/jump to %d", p + mcnt - start); break; case succeed_n: extract_number_and_incr (&mcnt, &p); p1 = p + mcnt; extract_number_and_incr (&mcnt2, &p); printf ("/succeed_n to %d, %d times", p1 - start, mcnt2); break; case jump_n: extract_number_and_incr (&mcnt, &p); p1 = p + mcnt; extract_number_and_incr (&mcnt2, &p); printf ("/jump_n to %d, %d times", p1 - start, mcnt2); break; case set_number_at: extract_number_and_incr (&mcnt, &p); p1 = p + mcnt; extract_number_and_incr (&mcnt2, &p); printf ("/set_number_at location %d to %d", p1 - start, mcnt2); break; case wordbound: printf ("/wordbound"); break; case notwordbound: printf ("/notwordbound"); break; case wordbeg: printf ("/wordbeg"); break; case wordend: printf ("/wordend"); # ifdef emacs case before_dot: printf ("/before_dot"); break; case at_dot: printf ("/at_dot"); break; case after_dot: printf ("/after_dot"); break; case syntaxspec: printf ("/syntaxspec"); mcnt = *p++; printf ("/%d", mcnt); break; case notsyntaxspec: printf ("/notsyntaxspec"); mcnt = *p++; printf ("/%d", mcnt); break; # endif /* emacs */ case wordchar: printf ("/wordchar"); break; case notwordchar: printf ("/notwordchar"); break; case begbuf: printf ("/begbuf"); break; case endbuf: printf ("/endbuf"); break; default: printf ("?%d", *(p-1)); } putchar ('\n'); } printf ("%d:\tend of pattern.\n", p - start); } void print_compiled_pattern (bufp) struct re_pattern_buffer *bufp; { unsigned char *buffer = bufp->buffer; print_partial_compiled_pattern (buffer, buffer + bufp->used); printf ("%ld bytes used/%ld bytes allocated.\n", bufp->used, bufp->allocated); if (bufp->fastmap_accurate && bufp->fastmap) { printf ("fastmap: "); print_fastmap (bufp->fastmap); } printf ("re_nsub: %d\t", bufp->re_nsub); printf ("regs_alloc: %d\t", bufp->regs_allocated); printf ("can_be_null: %d\t", bufp->can_be_null); printf ("newline_anchor: %d\n", bufp->newline_anchor); printf ("no_sub: %d\t", bufp->no_sub); printf ("not_bol: %d\t", bufp->not_bol); printf ("not_eol: %d\t", bufp->not_eol); printf ("syntax: %lx\n", bufp->syntax); /* Perhaps we should print the translate table? */ } void print_double_string (where, string1, size1, string2, size2) const char *where; const char *string1; const char *string2; int size1; int size2; { int this_char; if (where == NULL) printf ("(null)"); else { if (FIRST_STRING_P (where)) { for (this_char = where - string1; this_char < size1; this_char++) putchar (string1[this_char]); where = string2; } for (this_char = where - string2; this_char < size2; this_char++) putchar (string2[this_char]); } } void printchar (c) int c; { putc (c, stderr); } #else /* not DEBUG */ # undef assert # define assert(e) # define DEBUG_STATEMENT(e) # define DEBUG_PRINT1(x) # define DEBUG_PRINT2(x1, x2) # define DEBUG_PRINT3(x1, x2, x3) # define DEBUG_PRINT4(x1, x2, x3, x4) # define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) # define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) #endif /* not DEBUG */ /* Set by `re_set_syntax' to the current regexp syntax to recognize. Can also be assigned to arbitrarily: each pattern buffer stores its own syntax, so it can be changed between regex compilations. */ /* This has no initializer because initialized variables in Emacs become read-only after dumping. */ reg_syntax_t re_syntax_options; /* Specify the precise syntax of regexps for compilation. This provides for compatibility for various utilities which historically have different, incompatible syntaxes. The argument SYNTAX is a bit mask comprised of the various bits defined in regex.h. We return the old syntax. */ reg_syntax_t re_set_syntax (syntax) reg_syntax_t syntax; { reg_syntax_t ret = re_syntax_options; re_syntax_options = syntax; #ifdef DEBUG if (syntax & RE_DEBUG) debug = 1; else if (debug) /* was on but now is not */ debug = 0; #endif /* DEBUG */ return ret; } #ifdef _LIBC weak_alias (__re_set_syntax, re_set_syntax) #endif /* This table gives an error message for each of the error codes listed in regex.h. Obviously the order here has to be same as there. POSIX doesn't require that we do anything for REG_NOERROR, but why not be nice? */ #if 0 /* This section is for xgettext; it sees the strings wrapped inside N_() and marks them as needing translation. They should match the strings in re_error_msgid. We can't use the usual string concatenation trick to initialize re_error_msgid, since other GNU distributions use this file with traditional C, and traditional C lacks string concatenation. */ N_("Success") /* REG_NOERROR */ N_("No match") /* REG_NOMATCH */ N_("Invalid regular expression") /* REG_BADPAT */ N_("Invalid collation character") /* REG_ECOLLATE */ N_("Invalid character class name") /* REG_ECTYPE */ N_("Trailing backslash") /* REG_EESCAPE */ N_("Invalid back reference") /* REG_ESUBREG */ N_("Unmatched [ or [^") /* REG_EBRACK */ N_("Unmatched ( or \\(") /* REG_EPAREN */ N_("Unmatched \\{") /* REG_EBRACE */ N_("Invalid content of \\{\\}") /* REG_BADBR */ N_("Invalid range end") /* REG_ERANGE */ N_("Memory exhausted") /* REG_ESPACE */ N_("Invalid preceding regular expression") /* REG_BADRPT */ N_("Premature end of regular expression") /* REG_EEND */ N_("Regular expression too big") /* REG_ESIZE */ N_("Unmatched ) or \\)") /* REG_ERPAREN */ #endif static const char re_error_msgid[] = "\ Success\0\ No match\0\ Invalid regular expression\0\ Invalid collation character\0\ Invalid character class name\0\ Trailing backslash\0\ Invalid back reference\0\ Unmatched [ or [^\0\ Unmatched ( or \\(\0\ Unmatched \\{\0\ Invalid content of \\{\\}\0\ Invalid range end\0\ Memory exhausted\0\ Invalid preceding regular expression\0\ Premature end of regular expression\0\ Regular expression too big\0\ Unmatched ) or \\)"; #define REG_NOERROR_IDX 0 #define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") #define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") #define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") #define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") #define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") #define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") #define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") #define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") #define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") #define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") #define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") #define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") #define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") #define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") #define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") #define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") static const size_t re_error_msgid_idx[] = { REG_NOERROR_IDX, REG_NOMATCH_IDX, REG_BADPAT_IDX, REG_ECOLLATE_IDX, REG_ECTYPE_IDX, REG_EESCAPE_IDX, REG_ESUBREG_IDX, REG_EBRACK_IDX, REG_EPAREN_IDX, REG_EBRACE_IDX, REG_BADBR_IDX, REG_ERANGE_IDX, REG_ESPACE_IDX, REG_BADRPT_IDX, REG_EEND_IDX, REG_ESIZE_IDX, REG_ERPAREN_IDX }; /* Avoiding alloca during matching, to placate r_alloc. */ /* Define MATCH_MAY_ALLOCATE unless we need to make sure that the searching and matching functions should not call alloca. On some systems, alloca is implemented in terms of malloc, and if we're using the relocating allocator routines, then malloc could cause a relocation, which might (if the strings being searched are in the ralloc heap) shift the data out from underneath the regexp routines. Here's another reason to avoid allocation: Emacs processes input from X in a signal handler; processing X input may call malloc; if input arrives while a matching routine is calling malloc, then we're scrod. But Emacs can't just block input while calling matching routines; then we don't notice interrupts when they come in. So, Emacs blocks input around all regexp calls except the matching calls, which it leaves unprotected, in the faith that they will not malloc. */ /* Normally, this is fine. */ #define MATCH_MAY_ALLOCATE /* When using GNU C, we are not REALLY using the C alloca, no matter what config.h may say. So don't take precautions for it. */ #ifdef __GNUC__ # undef C_ALLOCA #endif /* The match routines may not allocate if (1) they would do it with malloc and (2) it's not safe for them to use malloc. Note that if REL_ALLOC is defined, matching would not use malloc for the failure stack, but we would still use it for the register vectors; so REL_ALLOC should not affect this. */ #if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs # undef MATCH_MAY_ALLOCATE #endif /* Failure stack declarations and macros; both re_compile_fastmap and re_match_2 use a failure stack. These have to be macros because of REGEX_ALLOCATE_STACK. */ /* Number of failure points for which to initially allocate space when matching. If this number is exceeded, we allocate more space, so it is not a hard limit. */ #ifndef INIT_FAILURE_ALLOC # define INIT_FAILURE_ALLOC 5 #endif /* Roughly the maximum number of failure points on the stack. Would be exactly that if always used MAX_FAILURE_ITEMS items each time we failed. This is a variable only so users of regex can assign to it; we never change it ourselves. */ #ifdef INT_IS_16BIT # if defined MATCH_MAY_ALLOCATE /* 4400 was enough to cause a crash on Alpha OSF/1, whose default stack limit is 2mb. */ long int re_max_failures = 4000; # else long int re_max_failures = 2000; # endif union fail_stack_elt { unsigned char *pointer; long int integer; }; typedef union fail_stack_elt fail_stack_elt_t; typedef struct { fail_stack_elt_t *stack; unsigned long int size; unsigned long int avail; /* Offset of next open position. */ } fail_stack_type; #else /* not INT_IS_16BIT */ # if defined MATCH_MAY_ALLOCATE /* 4400 was enough to cause a crash on Alpha OSF/1, whose default stack limit is 2mb. */ int re_max_failures = 20000; # else int re_max_failures = 2000; # endif union fail_stack_elt { unsigned char *pointer; int integer; }; typedef union fail_stack_elt fail_stack_elt_t; typedef struct { fail_stack_elt_t *stack; unsigned size; unsigned avail; /* Offset of next open position. */ } fail_stack_type; #endif /* INT_IS_16BIT */ #define FAIL_STACK_EMPTY() (fail_stack.avail == 0) #define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) #define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) /* Define macros to initialize and free the failure stack. Do `return -2' if the alloc fails. */ #ifdef MATCH_MAY_ALLOCATE # define INIT_FAIL_STACK() \ do { \ fail_stack.stack = (fail_stack_elt_t *) \ REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ \ if (fail_stack.stack == NULL) \ return -2; \ \ fail_stack.size = INIT_FAILURE_ALLOC; \ fail_stack.avail = 0; \ } while (0) # define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack) #else # define INIT_FAIL_STACK() \ do { \ fail_stack.avail = 0; \ } while (0) # define RESET_FAIL_STACK() #endif /* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. Return 1 if succeeds, and 0 if either ran out of memory allocating space for it or it was already too large. REGEX_REALLOCATE_STACK requires `destination' be declared. */ #define DOUBLE_FAIL_STACK(fail_stack) \ ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \ ? 0 \ : ((fail_stack).stack = (fail_stack_elt_t *) \ REGEX_REALLOCATE_STACK ((fail_stack).stack, \ (fail_stack).size * sizeof (fail_stack_elt_t), \ ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ \ (fail_stack).stack == NULL \ ? 0 \ : ((fail_stack).size <<= 1, \ 1))) /* Push pointer POINTER on FAIL_STACK. Return 1 if was able to do so and 0 if ran out of memory allocating space to do so. */ #define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \ ((FAIL_STACK_FULL () \ && !DOUBLE_FAIL_STACK (FAIL_STACK)) \ ? 0 \ : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \ 1)) /* Push a pointer value onto the failure stack. Assumes the variable `fail_stack'. Probably should only be called from within `PUSH_FAILURE_POINT'. */ #define PUSH_FAILURE_POINTER(item) \ fail_stack.stack[fail_stack.avail++].pointer = (unsigned char *) (item) /* This pushes an integer-valued item onto the failure stack. Assumes the variable `fail_stack'. Probably should only be called from within `PUSH_FAILURE_POINT'. */ #define PUSH_FAILURE_INT(item) \ fail_stack.stack[fail_stack.avail++].integer = (item) /* Push a fail_stack_elt_t value onto the failure stack. Assumes the variable `fail_stack'. Probably should only be called from within `PUSH_FAILURE_POINT'. */ #define PUSH_FAILURE_ELT(item) \ fail_stack.stack[fail_stack.avail++] = (item) /* These three POP... operations complement the three PUSH... operations. All assume that `fail_stack' is nonempty. */ #define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer #define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer #define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail] /* Used to omit pushing failure point id's when we're not debugging. */ #ifdef DEBUG # define DEBUG_PUSH PUSH_FAILURE_INT # define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT () #else # define DEBUG_PUSH(item) # define DEBUG_POP(item_addr) #endif /* Push the information about the state we will need if we ever fail back to it. Requires variables fail_stack, regstart, regend, reg_info, and num_regs_pushed be declared. DOUBLE_FAIL_STACK requires `destination' be declared. Does `return FAILURE_CODE' if runs out of memory. */ #define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ do { \ char *destination; \ /* Must be int, so when we don't save any registers, the arithmetic \ of 0 + -1 isn't done as unsigned. */ \ /* Can't be int, since there is not a shred of a guarantee that int \ is wide enough to hold a value of something to which pointer can \ be assigned */ \ active_reg_t this_reg; \ \ DEBUG_STATEMENT (failure_id++); \ DEBUG_STATEMENT (nfailure_points_pushed++); \ DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ \ DEBUG_PRINT2 (" slots needed: %ld\n", NUM_FAILURE_ITEMS); \ DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ \ /* Ensure we have enough space allocated for what we will push. */ \ while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ { \ if (!DOUBLE_FAIL_STACK (fail_stack)) \ return failure_code; \ \ DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ (fail_stack).size); \ DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ } \ \ /* Push the info, starting with the registers. */ \ DEBUG_PRINT1 ("\n"); \ \ if (1) \ for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ this_reg++) \ { \ DEBUG_PRINT2 (" Pushing reg: %lu\n", this_reg); \ DEBUG_STATEMENT (num_regs_pushed++); \ \ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ PUSH_FAILURE_POINTER (regstart[this_reg]); \ \ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ PUSH_FAILURE_POINTER (regend[this_reg]); \ \ DEBUG_PRINT2 (" info: %p\n ", \ reg_info[this_reg].word.pointer); \ DEBUG_PRINT2 (" match_null=%d", \ REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ DEBUG_PRINT2 (" matched_something=%d", \ MATCHED_SOMETHING (reg_info[this_reg])); \ DEBUG_PRINT2 (" ever_matched=%d", \ EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ DEBUG_PRINT1 ("\n"); \ PUSH_FAILURE_ELT (reg_info[this_reg].word); \ } \ \ DEBUG_PRINT2 (" Pushing low active reg: %ld\n", lowest_active_reg);\ PUSH_FAILURE_INT (lowest_active_reg); \ \ DEBUG_PRINT2 (" Pushing high active reg: %ld\n", highest_active_reg);\ PUSH_FAILURE_INT (highest_active_reg); \ \ DEBUG_PRINT2 (" Pushing pattern %p:\n", pattern_place); \ DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ PUSH_FAILURE_POINTER (pattern_place); \ \ DEBUG_PRINT2 (" Pushing string %p: `", string_place); \ DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ size2); \ DEBUG_PRINT1 ("'\n"); \ PUSH_FAILURE_POINTER (string_place); \ \ DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ DEBUG_PUSH (failure_id); \ } while (0) /* This is the number of items that are pushed and popped on the stack for each register. */ #define NUM_REG_ITEMS 3 /* Individual items aside from the registers. */ #ifdef DEBUG # define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ #else # define NUM_NONREG_ITEMS 4 #endif /* We push at most this many items on the stack. */ /* We used to use (num_regs - 1), which is the number of registers this regexp will save; but that was changed to 5 to avoid stack overflow for a regexp with lots of parens. */ #define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS) /* We actually push this many items. */ #define NUM_FAILURE_ITEMS \ (((0 \ ? 0 : highest_active_reg - lowest_active_reg + 1) \ * NUM_REG_ITEMS) \ + NUM_NONREG_ITEMS) /* How many items can still be added to the stack without overflowing it. */ #define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) /* Pops what PUSH_FAIL_STACK pushes. We restore into the parameters, all of which should be lvalues: STR -- the saved data position. PAT -- the saved pattern position. LOW_REG, HIGH_REG -- the highest and lowest active registers. REGSTART, REGEND -- arrays of string positions. REG_INFO -- array of information about each subexpression. Also assumes the variables `fail_stack' and (if debugging), `bufp', `pend', `string1', `size1', `string2', and `size2'. */ #define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ { \ DEBUG_STATEMENT (unsigned failure_id;) \ active_reg_t this_reg; \ const unsigned char *string_temp; \ \ assert (!FAIL_STACK_EMPTY ()); \ \ /* Remove failure points and point to how many regs pushed. */ \ DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ \ assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ \ DEBUG_POP (&failure_id); \ DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ \ /* If the saved string location is NULL, it came from an \ on_failure_keep_string_jump opcode, and we want to throw away the \ saved NULL, thus retaining our current position in the string. */ \ string_temp = POP_FAILURE_POINTER (); \ if (string_temp != NULL) \ str = (const char *) string_temp; \ \ DEBUG_PRINT2 (" Popping string %p: `", str); \ DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ DEBUG_PRINT1 ("'\n"); \ \ pat = (unsigned char *) POP_FAILURE_POINTER (); \ DEBUG_PRINT2 (" Popping pattern %p:\n", pat); \ DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ \ /* Restore register info. */ \ high_reg = (active_reg_t) POP_FAILURE_INT (); \ DEBUG_PRINT2 (" Popping high active reg: %ld\n", high_reg); \ \ low_reg = (active_reg_t) POP_FAILURE_INT (); \ DEBUG_PRINT2 (" Popping low active reg: %ld\n", low_reg); \ \ if (1) \ for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ { \ DEBUG_PRINT2 (" Popping reg: %ld\n", this_reg); \ \ reg_info[this_reg].word = POP_FAILURE_ELT (); \ DEBUG_PRINT2 (" info: %p\n", \ reg_info[this_reg].word.pointer); \ \ regend[this_reg] = (const char *) POP_FAILURE_POINTER (); \ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ \ regstart[this_reg] = (const char *) POP_FAILURE_POINTER (); \ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ } \ else \ { \ for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \ { \ reg_info[this_reg].word.integer = 0; \ regend[this_reg] = 0; \ regstart[this_reg] = 0; \ } \ highest_active_reg = high_reg; \ } \ \ set_regs_matched_done = 0; \ DEBUG_STATEMENT (nfailure_points_popped++); \ } /* POP_FAILURE_POINT */ /* Structure for per-register (a.k.a. per-group) information. Other register information, such as the starting and ending positions (which are addresses), and the list of inner groups (which is a bits list) are maintained in separate variables. We are making a (strictly speaking) nonportable assumption here: that the compiler will pack our bit fields into something that fits into the type of `word', i.e., is something that fits into one item on the failure stack. */ /* Declarations and macros for re_match_2. */ typedef union { fail_stack_elt_t word; struct { /* This field is one if this group can match the empty string, zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ #define MATCH_NULL_UNSET_VALUE 3 unsigned match_null_string_p : 2; unsigned is_active : 1; unsigned matched_something : 1; unsigned ever_matched_something : 1; } bits; } register_info_type; #define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) #define IS_ACTIVE(R) ((R).bits.is_active) #define MATCHED_SOMETHING(R) ((R).bits.matched_something) #define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) /* Call this when have matched a real character; it sets `matched' flags for the subexpressions which we are currently inside. Also records that those subexprs have matched. */ #define SET_REGS_MATCHED() \ do \ { \ if (!set_regs_matched_done) \ { \ active_reg_t r; \ set_regs_matched_done = 1; \ for (r = lowest_active_reg; r <= highest_active_reg; r++) \ { \ MATCHED_SOMETHING (reg_info[r]) \ = EVER_MATCHED_SOMETHING (reg_info[r]) \ = 1; \ } \ } \ } \ while (0) /* Registers are set to a sentinel when they haven't yet matched. */ static char reg_unset_dummy; #define REG_UNSET_VALUE (®_unset_dummy) #define REG_UNSET(e) ((e) == REG_UNSET_VALUE) /* Subroutine declarations and macros for regex_compile. */ static reg_errcode_t regex_compile _RE_ARGS ((const char *pattern, size_t size, reg_syntax_t syntax, struct re_pattern_buffer *bufp)); static void store_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, int arg)); static void store_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc, int arg1, int arg2)); static void insert_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, int arg, unsigned char *end)); static void insert_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc, int arg1, int arg2, unsigned char *end)); static boolean at_begline_loc_p _RE_ARGS ((const char *pattern, const char *p, reg_syntax_t syntax)); static boolean at_endline_loc_p _RE_ARGS ((const char *p, const char *pend, reg_syntax_t syntax)); static reg_errcode_t compile_range _RE_ARGS ((const char **p_ptr, const char *pend, char *translate, reg_syntax_t syntax, unsigned char *b)); /* Fetch the next character in the uncompiled pattern---translating it if necessary. Also cast from a signed character in the constant string passed to us by the user to an unsigned char that we can use as an array index (in, e.g., `translate'). */ #ifndef PATFETCH # define PATFETCH(c) \ do {if (p == pend) return REG_EEND; \ c = (unsigned char) *p++; \ if (translate) c = (unsigned char) translate[c]; \ } while (0) #endif /* Fetch the next character in the uncompiled pattern, with no translation. */ #define PATFETCH_RAW(c) \ do {if (p == pend) return REG_EEND; \ c = (unsigned char) *p++; \ } while (0) /* Go backwards one character in the pattern. */ #define PATUNFETCH p-- /* If `translate' is non-null, return translate[D], else just D. We cast the subscript to translate because some data is declared as `char *', to avoid warnings when a string constant is passed. But when we use a character as a subscript we must make it unsigned. */ #ifndef TRANSLATE # define TRANSLATE(d) \ (translate ? (char) translate[(unsigned char) (d)] : (d)) #endif /* Macros for outputting the compiled pattern into `buffer'. */ /* If the buffer isn't allocated when it comes in, use this. */ #define INIT_BUF_SIZE 32 /* Make sure we have at least N more bytes of space in buffer. */ #define GET_BUFFER_SPACE(n) \ while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \ EXTEND_BUFFER () /* Make sure we have one more byte of buffer space and then add C to it. */ #define BUF_PUSH(c) \ do { \ GET_BUFFER_SPACE (1); \ *b++ = (unsigned char) (c); \ } while (0) /* Ensure we have two more bytes of buffer space and then append C1 and C2. */ #define BUF_PUSH_2(c1, c2) \ do { \ GET_BUFFER_SPACE (2); \ *b++ = (unsigned char) (c1); \ *b++ = (unsigned char) (c2); \ } while (0) /* As with BUF_PUSH_2, except for three bytes. */ #define BUF_PUSH_3(c1, c2, c3) \ do { \ GET_BUFFER_SPACE (3); \ *b++ = (unsigned char) (c1); \ *b++ = (unsigned char) (c2); \ *b++ = (unsigned char) (c3); \ } while (0) /* Store a jump with opcode OP at LOC to location TO. We store a relative address offset by the three bytes the jump itself occupies. */ #define STORE_JUMP(op, loc, to) \ store_op1 (op, loc, (int) ((to) - (loc) - 3)) /* Likewise, for a two-argument jump. */ #define STORE_JUMP2(op, loc, to, arg) \ store_op2 (op, loc, (int) ((to) - (loc) - 3), arg) /* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ #define INSERT_JUMP(op, loc, to) \ insert_op1 (op, loc, (int) ((to) - (loc) - 3), b) /* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ #define INSERT_JUMP2(op, loc, to, arg) \ insert_op2 (op, loc, (int) ((to) - (loc) - 3), arg, b) /* This is not an arbitrary limit: the arguments which represent offsets into the pattern are two bytes long. So if 2^16 bytes turns out to be too small, many things would have to change. */ /* Any other compiler which, like MSC, has allocation limit below 2^16 bytes will have to use approach similar to what was done below for MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up reallocating to 0 bytes. Such thing is not going to work too well. You have been warned!! */ #if defined _MSC_VER && !defined WIN32 /* Microsoft C 16-bit versions limit malloc to approx 65512 bytes. The REALLOC define eliminates a flurry of conversion warnings, but is not required. */ # define MAX_BUF_SIZE 65500L # define REALLOC(p,s) realloc ((p), (size_t) (s)) #else # define MAX_BUF_SIZE (1L << 16) # define REALLOC(p,s) realloc ((p), (s)) #endif /* Extend the buffer by twice its current size via realloc and reset the pointers that pointed into the old block to point to the correct places in the new one. If extending the buffer results in it being larger than MAX_BUF_SIZE, then flag memory exhausted. */ #define EXTEND_BUFFER() \ do { \ unsigned char *old_buffer = bufp->buffer; \ if (bufp->allocated == MAX_BUF_SIZE) \ return REG_ESIZE; \ bufp->allocated <<= 1; \ if (bufp->allocated > MAX_BUF_SIZE) \ bufp->allocated = MAX_BUF_SIZE; \ bufp->buffer = (unsigned char *) REALLOC (bufp->buffer, bufp->allocated);\ if (bufp->buffer == NULL) \ return REG_ESPACE; \ /* If the buffer moved, move all the pointers into it. */ \ if (old_buffer != bufp->buffer) \ { \ b = (b - old_buffer) + bufp->buffer; \ begalt = (begalt - old_buffer) + bufp->buffer; \ if (fixup_alt_jump) \ fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ if (laststart) \ laststart = (laststart - old_buffer) + bufp->buffer; \ if (pending_exact) \ pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ } \ } while (0) /* Since we have one byte reserved for the register number argument to {start,stop}_memory, the maximum number of groups we can report things about is what fits in that byte. */ #define MAX_REGNUM 255 /* But patterns can have more than `MAX_REGNUM' registers. We just ignore the excess. */ typedef unsigned regnum_t; /* Macros for the compile stack. */ /* Since offsets can go either forwards or backwards, this type needs to be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ /* int may be not enough when sizeof(int) == 2. */ typedef long pattern_offset_t; typedef struct { pattern_offset_t begalt_offset; pattern_offset_t fixup_alt_jump; pattern_offset_t inner_group_offset; pattern_offset_t laststart_offset; regnum_t regnum; } compile_stack_elt_t; typedef struct { compile_stack_elt_t *stack; unsigned size; unsigned avail; /* Offset of next open position. */ } compile_stack_type; #define INIT_COMPILE_STACK_SIZE 32 #define COMPILE_STACK_EMPTY (compile_stack.avail == 0) #define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) /* The next available element. */ #define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) /* Set the bit for character C in a list. */ #define SET_LIST_BIT(c) \ (b[((unsigned char) (c)) / BYTEWIDTH] \ |= 1 << (((unsigned char) c) % BYTEWIDTH)) /* Get the next unsigned number in the uncompiled pattern. */ #define GET_UNSIGNED_NUMBER(num) \ { if (p != pend) \ { \ PATFETCH (c); \ while ('0' <= c && c <= '9') \ { \ if (num < 0) \ num = 0; \ num = num * 10 + c - '0'; \ if (p == pend) \ break; \ PATFETCH (c); \ } \ } \ } #if defined _LIBC || WIDE_CHAR_SUPPORT /* The GNU C library provides support for user-defined character classes and the functions from ISO C amendement 1. */ # ifdef CHARCLASS_NAME_MAX # define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX # else /* This shouldn't happen but some implementation might still have this problem. Use a reasonable default value. */ # define CHAR_CLASS_MAX_LENGTH 256 # endif # ifdef _LIBC # define IS_CHAR_CLASS(string) __wctype (string) # else # define IS_CHAR_CLASS(string) wctype (string) # endif #else # define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ # define IS_CHAR_CLASS(string) \ (STREQ (string, "alpha") || STREQ (string, "upper") \ || STREQ (string, "lower") || STREQ (string, "digit") \ || STREQ (string, "alnum") || STREQ (string, "xdigit") \ || STREQ (string, "space") || STREQ (string, "print") \ || STREQ (string, "punct") || STREQ (string, "graph") \ || STREQ (string, "cntrl") || STREQ (string, "blank")) #endif #ifndef MATCH_MAY_ALLOCATE /* If we cannot allocate large objects within re_match_2_internal, we make the fail stack and register vectors global. The fail stack, we grow to the maximum size when a regexp is compiled. The register vectors, we adjust in size each time we compile a regexp, according to the number of registers it needs. */ static fail_stack_type fail_stack; /* Size with which the following vectors are currently allocated. That is so we can make them bigger as needed, but never make them smaller. */ static int regs_allocated_size; static const char ** regstart, ** regend; static const char ** old_regstart, ** old_regend; static const char **best_regstart, **best_regend; static register_info_type *reg_info; static const char **reg_dummy; static register_info_type *reg_info_dummy; /* Make the register vectors big enough for NUM_REGS registers, but don't make them smaller. */ static regex_grow_registers (num_regs) int num_regs; { if (num_regs > regs_allocated_size) { RETALLOC_IF (regstart, num_regs, const char *); RETALLOC_IF (regend, num_regs, const char *); RETALLOC_IF (old_regstart, num_regs, const char *); RETALLOC_IF (old_regend, num_regs, const char *); RETALLOC_IF (best_regstart, num_regs, const char *); RETALLOC_IF (best_regend, num_regs, const char *); RETALLOC_IF (reg_info, num_regs, register_info_type); RETALLOC_IF (reg_dummy, num_regs, const char *); RETALLOC_IF (reg_info_dummy, num_regs, register_info_type); regs_allocated_size = num_regs; } } #endif /* not MATCH_MAY_ALLOCATE */ static boolean group_in_compile_stack _RE_ARGS ((compile_stack_type compile_stack, regnum_t regnum)); /* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. Returns one of error codes defined in `regex.h', or zero for success. Assumes the `allocated' (and perhaps `buffer') and `translate' fields are set in BUFP on entry. If it succeeds, results are put in BUFP (if it returns an error, the contents of BUFP are undefined): `buffer' is the compiled pattern; `syntax' is set to SYNTAX; `used' is set to the length of the compiled pattern; `fastmap_accurate' is zero; `re_nsub' is the number of subexpressions in PATTERN; `not_bol' and `not_eol' are zero; The `fastmap' and `newline_anchor' fields are neither examined nor set. */ /* Return, freeing storage we allocated. */ #define FREE_STACK_RETURN(value) \ return (free (compile_stack.stack), value) static reg_errcode_t regex_compile (pattern, size, syntax, bufp) const char *pattern; size_t size; reg_syntax_t syntax; struct re_pattern_buffer *bufp; { /* We fetch characters from PATTERN here. Even though PATTERN is `char *' (i.e., signed), we declare these variables as unsigned, so they can be reliably used as array indices. */ register unsigned char c, c1; /* A random temporary spot in PATTERN. */ const char *p1; /* Points to the end of the buffer, where we should append. */ register unsigned char *b; /* Keeps track of unclosed groups. */ compile_stack_type compile_stack; /* Points to the current (ending) position in the pattern. */ const char *p = pattern; const char *pend = pattern + size; /* How to translate the characters in the pattern. */ RE_TRANSLATE_TYPE translate = bufp->translate; /* Address of the count-byte of the most recently inserted `exactn' command. This makes it possible to tell if a new exact-match character can be added to that command or if the character requires a new `exactn' command. */ unsigned char *pending_exact = 0; /* Address of start of the most recently finished expression. This tells, e.g., postfix * where to find the start of its operand. Reset at the beginning of groups and alternatives. */ unsigned char *laststart = 0; /* Address of beginning of regexp, or inside of last group. */ unsigned char *begalt; /* Place in the uncompiled pattern (i.e., the {) to which to go back if the interval is invalid. */ const char *beg_interval; /* Address of the place where a forward jump should go to the end of the containing expression. Each alternative of an `or' -- except the last -- ends with a forward jump of this sort. */ unsigned char *fixup_alt_jump = 0; /* Counts open-groups as they are encountered. Remembered for the matching close-group on the compile stack, so the same register number is put in the stop_memory as the start_memory. */ regnum_t regnum = 0; #ifdef DEBUG DEBUG_PRINT1 ("\nCompiling pattern: "); if (debug) { unsigned debug_count; for (debug_count = 0; debug_count < size; debug_count++) putchar (pattern[debug_count]); putchar ('\n'); } #endif /* DEBUG */ /* Initialize the compile stack. */ compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); if (compile_stack.stack == NULL) return REG_ESPACE; compile_stack.size = INIT_COMPILE_STACK_SIZE; compile_stack.avail = 0; /* Initialize the pattern buffer. */ bufp->syntax = syntax; bufp->fastmap_accurate = 0; bufp->not_bol = bufp->not_eol = 0; /* Set `used' to zero, so that if we return an error, the pattern printer (for debugging) will think there's no pattern. We reset it at the end. */ bufp->used = 0; /* Always count groups, whether or not bufp->no_sub is set. */ bufp->re_nsub = 0; #if !defined emacs && !defined SYNTAX_TABLE /* Initialize the syntax table. */ init_syntax_once (); #endif if (bufp->allocated == 0) { if (bufp->buffer) { /* If zero allocated, but buffer is non-null, try to realloc enough space. This loses if buffer's address is bogus, but that is the user's responsibility. */ RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char); } else { /* Caller did not allocate a buffer. Do it for them. */ bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char); } if (!bufp->buffer) FREE_STACK_RETURN (REG_ESPACE); bufp->allocated = INIT_BUF_SIZE; } begalt = b = bufp->buffer; /* Loop through the uncompiled pattern until we're at the end. */ while (p != pend) { PATFETCH (c); switch (c) { case '^': { if ( /* If at start of pattern, it's an operator. */ p == pattern + 1 /* If context independent, it's an operator. */ || syntax & RE_CONTEXT_INDEP_ANCHORS /* Otherwise, depends on what's come before. */ || at_begline_loc_p (pattern, p, syntax)) BUF_PUSH (begline); else goto normal_char; } break; case '$': { if ( /* If at end of pattern, it's an operator. */ p == pend /* If context independent, it's an operator. */ || syntax & RE_CONTEXT_INDEP_ANCHORS /* Otherwise, depends on what's next. */ || at_endline_loc_p (p, pend, syntax)) BUF_PUSH (endline); else goto normal_char; } break; case '+': case '?': if ((syntax & RE_BK_PLUS_QM) || (syntax & RE_LIMITED_OPS)) goto normal_char; handle_plus: case '*': /* If there is no previous pattern... */ if (!laststart) { if (syntax & RE_CONTEXT_INVALID_OPS) FREE_STACK_RETURN (REG_BADRPT); else if (!(syntax & RE_CONTEXT_INDEP_OPS)) goto normal_char; } { /* Are we optimizing this jump? */ boolean keep_string_p = false; /* 1 means zero (many) matches is allowed. */ char zero_times_ok = 0, many_times_ok = 0; /* If there is a sequence of repetition chars, collapse it down to just one (the right one). We can't combine interval operators with these because of, e.g., `a{2}*', which should only match an even number of `a's. */ for (;;) { zero_times_ok |= c != '+'; many_times_ok |= c != '?'; if (p == pend) break; PATFETCH (c); if (c == '*' || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) ; else if (syntax & RE_BK_PLUS_QM && c == '\\') { if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); PATFETCH (c1); if (!(c1 == '+' || c1 == '?')) { PATUNFETCH; PATUNFETCH; break; } c = c1; } else { PATUNFETCH; break; } /* If we get here, we found another repeat character. */ } /* Star, etc. applied to an empty pattern is equivalent to an empty pattern. */ if (!laststart) break; /* Now we know whether or not zero matches is allowed and also whether or not two or more matches is allowed. */ if (many_times_ok) { /* More than one repetition is allowed, so put in at the end a backward relative jump from `b' to before the next jump we're going to put in below (which jumps from laststart to after this jump). But if we are at the `*' in the exact sequence `.*\n', insert an unconditional jump backwards to the ., instead of the beginning of the loop. This way we only push a failure point once, instead of every time through the loop. */ assert (p - 1 > pattern); /* Allocate the space for the jump. */ GET_BUFFER_SPACE (3); /* We know we are not at the first character of the pattern, because laststart was nonzero. And we've already incremented `p', by the way, to be the character after the `*'. Do we have to do something analogous here for null bytes, because of RE_DOT_NOT_NULL? */ if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') && zero_times_ok && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') && !(syntax & RE_DOT_NEWLINE)) { /* We have .*\n. */ STORE_JUMP (jump, b, laststart); keep_string_p = true; } else /* Anything else. */ STORE_JUMP (maybe_pop_jump, b, laststart - 3); /* We've added more stuff to the buffer. */ b += 3; } /* On failure, jump from laststart to b + 3, which will be the end of the buffer after this jump is inserted. */ GET_BUFFER_SPACE (3); INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump : on_failure_jump, laststart, b + 3); pending_exact = 0; b += 3; if (!zero_times_ok) { /* At least one repetition is required, so insert a `dummy_failure_jump' before the initial `on_failure_jump' instruction of the loop. This effects a skip over that instruction the first time we hit that loop. */ GET_BUFFER_SPACE (3); INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6); b += 3; } } break; case '.': laststart = b; BUF_PUSH (anychar); break; case '[': { boolean had_char_class = false; if (p == pend) FREE_STACK_RETURN (REG_EBRACK); /* Ensure that we have enough space to push a charset: the opcode, the length count, and the bitset; 34 bytes in all. */ GET_BUFFER_SPACE (34); laststart = b; /* We test `*p == '^' twice, instead of using an if statement, so we only need one BUF_PUSH. */ BUF_PUSH (*p == '^' ? charset_not : charset); if (*p == '^') p++; /* Remember the first position in the bracket expression. */ p1 = p; /* Push the number of bytes in the bitmap. */ BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); /* Clear the whole map. */ bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); /* charset_not matches newline according to a syntax bit. */ if ((re_opcode_t) b[-2] == charset_not && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) SET_LIST_BIT ('\n'); /* Read in characters and ranges, setting map bits. */ for (;;) { if (p == pend) FREE_STACK_RETURN (REG_EBRACK); PATFETCH (c); /* \ might escape characters inside [...] and [^...]. */ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') { if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); PATFETCH (c1); SET_LIST_BIT (c1); continue; } /* Could be the end of the bracket expression. If it's not (i.e., when the bracket expression is `[]' so far), the ']' character bit gets set way below. */ if (c == ']' && p != p1 + 1) break; /* Look ahead to see if it's a range when the last thing was a character class. */ if (had_char_class && c == '-' && *p != ']') FREE_STACK_RETURN (REG_ERANGE); /* Look ahead to see if it's a range when the last thing was a character: if this is a hyphen not at the beginning or the end of a list, then it's the range operator. */ if (c == '-' && !(p - 2 >= pattern && p[-2] == '[') && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') && *p != ']') { reg_errcode_t ret = compile_range (&p, pend, translate, syntax, b); if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); } else if (p[0] == '-' && p[1] != ']') { /* This handles ranges made up of characters only. */ reg_errcode_t ret; /* Move past the `-'. */ PATFETCH (c1); ret = compile_range (&p, pend, translate, syntax, b); if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); } /* See if we're at the beginning of a possible character class. */ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') { /* Leave room for the null. */ char str[CHAR_CLASS_MAX_LENGTH + 1]; PATFETCH (c); c1 = 0; /* If pattern is `[[:'. */ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); for (;;) { PATFETCH (c); if ((c == ':' && *p == ']') || p == pend) break; if (c1 < CHAR_CLASS_MAX_LENGTH) str[c1++] = c; else /* This is in any case an invalid class name. */ str[0] = '\0'; } str[c1] = '\0'; /* If isn't a word bracketed by `[:' and `:]': undo the ending character, the letters, and leave the leading `:' and `[' (but set bits for them). */ if (c == ':' && *p == ']') { #if defined _LIBC || WIDE_CHAR_SUPPORT boolean is_lower = STREQ (str, "lower"); boolean is_upper = STREQ (str, "upper"); wctype_t wt; int ch; wt = IS_CHAR_CLASS (str); if (wt == 0) FREE_STACK_RETURN (REG_ECTYPE); /* Throw away the ] at the end of the character class. */ PATFETCH (c); if (p == pend) FREE_STACK_RETURN (REG_EBRACK); for (ch = 0; ch < 1 << BYTEWIDTH; ++ch) { # ifdef _LIBC if (__iswctype (__btowc (ch), wt)) SET_LIST_BIT (ch); # else if (iswctype (btowc (ch), wt)) SET_LIST_BIT (ch); # endif if (translate && (is_upper || is_lower) && (ISUPPER (ch) || ISLOWER (ch))) SET_LIST_BIT (ch); } had_char_class = true; #else int ch; boolean is_alnum = STREQ (str, "alnum"); boolean is_alpha = STREQ (str, "alpha"); boolean is_blank = STREQ (str, "blank"); boolean is_cntrl = STREQ (str, "cntrl"); boolean is_digit = STREQ (str, "digit"); boolean is_graph = STREQ (str, "graph"); boolean is_lower = STREQ (str, "lower"); boolean is_print = STREQ (str, "print"); boolean is_punct = STREQ (str, "punct"); boolean is_space = STREQ (str, "space"); boolean is_upper = STREQ (str, "upper"); boolean is_xdigit = STREQ (str, "xdigit"); if (!IS_CHAR_CLASS (str)) FREE_STACK_RETURN (REG_ECTYPE); /* Throw away the ] at the end of the character class. */ PATFETCH (c); if (p == pend) FREE_STACK_RETURN (REG_EBRACK); for (ch = 0; ch < 1 << BYTEWIDTH; ch++) { /* This was split into 3 if's to avoid an arbitrary limit in some compiler. */ if ( (is_alnum && ISALNUM (ch)) || (is_alpha && ISALPHA (ch)) || (is_blank && ISBLANK (ch)) || (is_cntrl && ISCNTRL (ch))) SET_LIST_BIT (ch); if ( (is_digit && ISDIGIT (ch)) || (is_graph && ISGRAPH (ch)) || (is_lower && ISLOWER (ch)) || (is_print && ISPRINT (ch))) SET_LIST_BIT (ch); if ( (is_punct && ISPUNCT (ch)) || (is_space && ISSPACE (ch)) || (is_upper && ISUPPER (ch)) || (is_xdigit && ISXDIGIT (ch))) SET_LIST_BIT (ch); if ( translate && (is_upper || is_lower) && (ISUPPER (ch) || ISLOWER (ch))) SET_LIST_BIT (ch); } had_char_class = true; #endif /* libc || wctype.h */ } else { c1++; while (c1--) PATUNFETCH; SET_LIST_BIT ('['); SET_LIST_BIT (':'); had_char_class = false; } } else { had_char_class = false; SET_LIST_BIT (c); } } /* Discard any (non)matching list bytes that are all 0 at the end of the map. Decrease the map-length byte too. */ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) b[-1]--; b += b[-1]; } break; case '(': if (syntax & RE_NO_BK_PARENS) goto handle_open; else goto normal_char; case ')': if (syntax & RE_NO_BK_PARENS) goto handle_close; else goto normal_char; case '\n': if (syntax & RE_NEWLINE_ALT) goto handle_alt; else goto normal_char; case '|': if (syntax & RE_NO_BK_VBAR) goto handle_alt; else goto normal_char; case '{': if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) goto handle_interval; else goto normal_char; case '\\': if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); /* Do not translate the character after the \, so that we can distinguish, e.g., \B from \b, even if we normally would translate, e.g., B to b. */ PATFETCH_RAW (c); switch (c) { case '(': if (syntax & RE_NO_BK_PARENS) goto normal_backslash; handle_open: bufp->re_nsub++; regnum++; if (COMPILE_STACK_FULL) { RETALLOC (compile_stack.stack, compile_stack.size << 1, compile_stack_elt_t); if (compile_stack.stack == NULL) return REG_ESPACE; compile_stack.size <<= 1; } /* These are the values to restore when we hit end of this group. They are all relative offsets, so that if the whole pattern moves because of realloc, they will still be valid. */ COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer; COMPILE_STACK_TOP.fixup_alt_jump = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0; COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer; COMPILE_STACK_TOP.regnum = regnum; /* We will eventually replace the 0 with the number of groups inner to this one. But do not push a start_memory for groups beyond the last one we can represent in the compiled pattern. */ if (regnum <= MAX_REGNUM) { COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2; BUF_PUSH_3 (start_memory, regnum, 0); } compile_stack.avail++; fixup_alt_jump = 0; laststart = 0; begalt = b; /* If we've reached MAX_REGNUM groups, then this open won't actually generate any code, so we'll have to clear pending_exact explicitly. */ pending_exact = 0; break; case ')': if (syntax & RE_NO_BK_PARENS) goto normal_backslash; if (COMPILE_STACK_EMPTY) { if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) goto normal_backslash; else FREE_STACK_RETURN (REG_ERPAREN); } handle_close: if (fixup_alt_jump) { /* Push a dummy failure point at the end of the alternative for a possible future `pop_failure_jump' to pop. See comments at `push_dummy_failure' in `re_match_2'. */ BUF_PUSH (push_dummy_failure); /* We allocated space for this jump when we assigned to `fixup_alt_jump', in the `handle_alt' case below. */ STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); } /* See similar code for backslashed left paren above. */ if (COMPILE_STACK_EMPTY) { if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) goto normal_char; else FREE_STACK_RETURN (REG_ERPAREN); } /* Since we just checked for an empty stack above, this ``can't happen''. */ assert (compile_stack.avail != 0); { /* We don't just want to restore into `regnum', because later groups should continue to be numbered higher, as in `(ab)c(de)' -- the second group is #2. */ regnum_t this_group_regnum; compile_stack.avail--; begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset; fixup_alt_jump = COMPILE_STACK_TOP.fixup_alt_jump ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1 : 0; laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset; this_group_regnum = COMPILE_STACK_TOP.regnum; /* If we've reached MAX_REGNUM groups, then this open won't actually generate any code, so we'll have to clear pending_exact explicitly. */ pending_exact = 0; /* We're at the end of the group, so now we know how many groups were inside this one. */ if (this_group_regnum <= MAX_REGNUM) { unsigned char *inner_group_loc = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset; *inner_group_loc = regnum - this_group_regnum; BUF_PUSH_3 (stop_memory, this_group_regnum, regnum - this_group_regnum); } } break; case '|': /* `\|'. */ if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) goto normal_backslash; handle_alt: if (syntax & RE_LIMITED_OPS) goto normal_char; /* Insert before the previous alternative a jump which jumps to this alternative if the former fails. */ GET_BUFFER_SPACE (3); INSERT_JUMP (on_failure_jump, begalt, b + 6); pending_exact = 0; b += 3; /* The alternative before this one has a jump after it which gets executed if it gets matched. Adjust that jump so it will jump to this alternative's analogous jump (put in below, which in turn will jump to the next (if any) alternative's such jump, etc.). The last such jump jumps to the correct final destination. A picture: _____ _____ | | | | | v | v a | b | c If we are at `b', then fixup_alt_jump right now points to a three-byte space after `a'. We'll put in the jump, set fixup_alt_jump to right after `b', and leave behind three bytes which we'll fill in when we get to after `c'. */ if (fixup_alt_jump) STORE_JUMP (jump_past_alt, fixup_alt_jump, b); /* Mark and leave space for a jump after this alternative, to be filled in later either by next alternative or when know we're at the end of a series of alternatives. */ fixup_alt_jump = b; GET_BUFFER_SPACE (3); b += 3; laststart = 0; begalt = b; break; case '{': /* If \{ is a literal. */ if (!(syntax & RE_INTERVALS) /* If we're at `\{' and it's not the open-interval operator. */ || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) || (p - 2 == pattern && p == pend)) goto normal_backslash; handle_interval: { /* If got here, then the syntax allows intervals. */ /* At least (most) this many matches must be made. */ int lower_bound = -1, upper_bound = -1; beg_interval = p - 1; if (p == pend) { if (syntax & RE_NO_BK_BRACES) goto unfetch_interval; else FREE_STACK_RETURN (REG_EBRACE); } GET_UNSIGNED_NUMBER (lower_bound); if (c == ',') { GET_UNSIGNED_NUMBER (upper_bound); if (upper_bound < 0) upper_bound = RE_DUP_MAX; } else /* Interval such as `{1}' => match exactly once. */ upper_bound = lower_bound; if (lower_bound < 0 || upper_bound > RE_DUP_MAX || lower_bound > upper_bound) { if (syntax & RE_NO_BK_BRACES) goto unfetch_interval; else FREE_STACK_RETURN (REG_BADBR); } if (!(syntax & RE_NO_BK_BRACES)) { if (c != '\\') FREE_STACK_RETURN (REG_EBRACE); PATFETCH (c); } if (c != '}') { if (syntax & RE_NO_BK_BRACES) goto unfetch_interval; else FREE_STACK_RETURN (REG_BADBR); } /* We just parsed a valid interval. */ /* If it's invalid to have no preceding re. */ if (!laststart) { if (syntax & RE_CONTEXT_INVALID_OPS) FREE_STACK_RETURN (REG_BADRPT); else if (syntax & RE_CONTEXT_INDEP_OPS) laststart = b; else goto unfetch_interval; } /* If the upper bound is zero, don't want to succeed at all; jump from `laststart' to `b + 3', which will be the end of the buffer after we insert the jump. */ if (upper_bound == 0) { GET_BUFFER_SPACE (3); INSERT_JUMP (jump, laststart, b + 3); b += 3; } /* Otherwise, we have a nontrivial interval. When we're all done, the pattern will look like: set_number_at set_number_at succeed_n jump_n (The upper bound and `jump_n' are omitted if `upper_bound' is 1, though.) */ else { /* If the upper bound is > 1, we need to insert more at the end of the loop. */ unsigned nbytes = 10 + (upper_bound > 1) * 10; GET_BUFFER_SPACE (nbytes); /* Initialize lower bound of the `succeed_n', even though it will be set during matching by its attendant `set_number_at' (inserted next), because `re_compile_fastmap' needs to know. Jump to the `jump_n' we might insert below. */ INSERT_JUMP2 (succeed_n, laststart, b + 5 + (upper_bound > 1) * 5, lower_bound); b += 5; /* Code to initialize the lower bound. Insert before the `succeed_n'. The `5' is the last two bytes of this `set_number_at', plus 3 bytes of the following `succeed_n'. */ insert_op2 (set_number_at, laststart, 5, lower_bound, b); b += 5; if (upper_bound > 1) { /* More than one repetition is allowed, so append a backward jump to the `succeed_n' that starts this interval. When we've reached this during matching, we'll have matched the interval once, so jump back only `upper_bound - 1' times. */ STORE_JUMP2 (jump_n, b, laststart + 5, upper_bound - 1); b += 5; /* The location we want to set is the second parameter of the `jump_n'; that is `b-2' as an absolute address. `laststart' will be the `set_number_at' we're about to insert; `laststart+3' the number to set, the source for the relative address. But we are inserting into the middle of the pattern -- so everything is getting moved up by 5. Conclusion: (b - 2) - (laststart + 3) + 5, i.e., b - laststart. We insert this at the beginning of the loop so that if we fail during matching, we'll reinitialize the bounds. */ insert_op2 (set_number_at, laststart, b - laststart, upper_bound - 1, b); b += 5; } } pending_exact = 0; beg_interval = NULL; } break; unfetch_interval: /* If an invalid interval, match the characters as literals. */ assert (beg_interval); p = beg_interval; beg_interval = NULL; /* normal_char and normal_backslash need `c'. */ PATFETCH (c); if (!(syntax & RE_NO_BK_BRACES)) { if (p > pattern && p[-1] == '\\') goto normal_backslash; } goto normal_char; #ifdef emacs /* There is no way to specify the before_dot and after_dot operators. rms says this is ok. --karl */ case '=': BUF_PUSH (at_dot); break; case 's': laststart = b; PATFETCH (c); BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); break; case 'S': laststart = b; PATFETCH (c); BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); break; #endif /* emacs */ case 'w': if (syntax & RE_NO_GNU_OPS) goto normal_char; laststart = b; BUF_PUSH (wordchar); break; case 'W': if (syntax & RE_NO_GNU_OPS) goto normal_char; laststart = b; BUF_PUSH (notwordchar); break; case '<': if (syntax & RE_NO_GNU_OPS) goto normal_char; BUF_PUSH (wordbeg); break; case '>': if (syntax & RE_NO_GNU_OPS) goto normal_char; BUF_PUSH (wordend); break; case 'b': if (syntax & RE_NO_GNU_OPS) goto normal_char; BUF_PUSH (wordbound); break; case 'B': if (syntax & RE_NO_GNU_OPS) goto normal_char; BUF_PUSH (notwordbound); break; case '`': if (syntax & RE_NO_GNU_OPS) goto normal_char; BUF_PUSH (begbuf); break; case '\'': if (syntax & RE_NO_GNU_OPS) goto normal_char; BUF_PUSH (endbuf); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (syntax & RE_NO_BK_REFS) goto normal_char; c1 = c - '0'; if (c1 > regnum) FREE_STACK_RETURN (REG_ESUBREG); /* Can't back reference to a subexpression if inside of it. */ if (group_in_compile_stack (compile_stack, (regnum_t) c1)) goto normal_char; laststart = b; BUF_PUSH_2 (duplicate, c1); break; case '+': case '?': if (syntax & RE_BK_PLUS_QM) goto handle_plus; else goto normal_backslash; default: normal_backslash: /* You might think it would be useful for \ to mean not to translate; but if we don't translate it it will never match anything. */ c = TRANSLATE (c); goto normal_char; } break; default: /* Expects the character in `c'. */ normal_char: /* If no exactn currently being built. */ if (!pending_exact /* If last exactn not at current position. */ || pending_exact + *pending_exact + 1 != b /* We have only one byte following the exactn for the count. */ || *pending_exact == (1 << BYTEWIDTH) - 1 /* If followed by a repetition operator. */ || *p == '*' || *p == '^' || ((syntax & RE_BK_PLUS_QM) ? *p == '\\' && (p[1] == '+' || p[1] == '?') : (*p == '+' || *p == '?')) || ((syntax & RE_INTERVALS) && ((syntax & RE_NO_BK_BRACES) ? *p == '{' : (p[0] == '\\' && p[1] == '{')))) { /* Start building a new exactn. */ laststart = b; BUF_PUSH_2 (exactn, 0); pending_exact = b - 1; } BUF_PUSH (c); (*pending_exact)++; break; } /* switch (c) */ } /* while p != pend */ /* Through the pattern now. */ if (fixup_alt_jump) STORE_JUMP (jump_past_alt, fixup_alt_jump, b); if (!COMPILE_STACK_EMPTY) FREE_STACK_RETURN (REG_EPAREN); /* If we don't want backtracking, force success the first time we reach the end of the compiled pattern. */ if (syntax & RE_NO_POSIX_BACKTRACKING) BUF_PUSH (succeed); free (compile_stack.stack); /* We have succeeded; set the length of the buffer. */ bufp->used = b - bufp->buffer; #ifdef DEBUG if (debug) { DEBUG_PRINT1 ("\nCompiled pattern: \n"); print_compiled_pattern (bufp); } #endif /* DEBUG */ #ifndef MATCH_MAY_ALLOCATE /* Initialize the failure stack to the largest possible stack. This isn't necessary unless we're trying to avoid calling alloca in the search and match routines. */ { int num_regs = bufp->re_nsub + 1; /* Since DOUBLE_FAIL_STACK refuses to double only if the current size is strictly greater than re_max_failures, the largest possible stack is 2 * re_max_failures failure points. */ if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS)) { fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS); # ifdef emacs if (! fail_stack.stack) fail_stack.stack = (fail_stack_elt_t *) xmalloc (fail_stack.size * sizeof (fail_stack_elt_t)); else fail_stack.stack = (fail_stack_elt_t *) xrealloc (fail_stack.stack, (fail_stack.size * sizeof (fail_stack_elt_t))); # else /* not emacs */ if (! fail_stack.stack) fail_stack.stack = (fail_stack_elt_t *) xmalloc (fail_stack.size * sizeof (fail_stack_elt_t)); else fail_stack.stack = (fail_stack_elt_t *) xrealloc (fail_stack.stack, (fail_stack.size * sizeof (fail_stack_elt_t))); # endif /* not emacs */ } regex_grow_registers (num_regs); } #endif /* not MATCH_MAY_ALLOCATE */ return REG_NOERROR; } /* regex_compile */ /* Subroutines for `regex_compile'. */ /* Store OP at LOC followed by two-byte integer parameter ARG. */ static void store_op1 (op, loc, arg) re_opcode_t op; unsigned char *loc; int arg; { *loc = (unsigned char) op; STORE_NUMBER (loc + 1, arg); } /* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ static void store_op2 (op, loc, arg1, arg2) re_opcode_t op; unsigned char *loc; int arg1, arg2; { *loc = (unsigned char) op; STORE_NUMBER (loc + 1, arg1); STORE_NUMBER (loc + 3, arg2); } /* Copy the bytes from LOC to END to open up three bytes of space at LOC for OP followed by two-byte integer parameter ARG. */ static void insert_op1 (op, loc, arg, end) re_opcode_t op; unsigned char *loc; int arg; unsigned char *end; { register unsigned char *pfrom = end; register unsigned char *pto = end + 3; while (pfrom != loc) *--pto = *--pfrom; store_op1 (op, loc, arg); } /* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ static void insert_op2 (op, loc, arg1, arg2, end) re_opcode_t op; unsigned char *loc; int arg1, arg2; unsigned char *end; { register unsigned char *pfrom = end; register unsigned char *pto = end + 5; while (pfrom != loc) *--pto = *--pfrom; store_op2 (op, loc, arg1, arg2); } /* P points to just after a ^ in PATTERN. Return true if that ^ comes after an alternative or a begin-subexpression. We assume there is at least one character before the ^. */ static boolean at_begline_loc_p (pattern, p, syntax) const char *pattern, *p; reg_syntax_t syntax; { const char *prev = p - 2; boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; return /* After a subexpression? */ (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) /* After an alternative? */ || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); } /* The dual of at_begline_loc_p. This one is for $. We assume there is at least one character after the $, i.e., `P < PEND'. */ static boolean at_endline_loc_p (p, pend, syntax) const char *p, *pend; reg_syntax_t syntax; { const char *next = p; boolean next_backslash = *next == '\\'; const char *next_next = p + 1 < pend ? p + 1 : 0; return /* Before a subexpression? */ (syntax & RE_NO_BK_PARENS ? *next == ')' : next_backslash && next_next && *next_next == ')') /* Before an alternative? */ || (syntax & RE_NO_BK_VBAR ? *next == '|' : next_backslash && next_next && *next_next == '|'); } /* Returns true if REGNUM is in one of COMPILE_STACK's elements and false if it's not. */ static boolean group_in_compile_stack (compile_stack, regnum) compile_stack_type compile_stack; regnum_t regnum; { int this_element; for (this_element = compile_stack.avail - 1; this_element >= 0; this_element--) if (compile_stack.stack[this_element].regnum == regnum) return true; return false; } /* Read the ending character of a range (in a bracket expression) from the uncompiled pattern *P_PTR (which ends at PEND). We assume the starting character is in `P[-2]'. (`P[-1]' is the character `-'.) Then we set the translation of all bits between the starting and ending characters (inclusive) in the compiled pattern B. Return an error code. We use these short variable names so we can use the same macros as `regex_compile' itself. */ static reg_errcode_t compile_range (p_ptr, pend, translate, syntax, b) const char **p_ptr, *pend; RE_TRANSLATE_TYPE translate; reg_syntax_t syntax; unsigned char *b; { unsigned this_char; const char *p = *p_ptr; reg_errcode_t ret; char range_start[2]; char range_end[2]; if (p == pend) return REG_ERANGE; /* Fetch the endpoints without translating them; the appropriate translation is done in the bit-setting loop below. */ range_start[0] = p[-2]; range_start[1] = '\0'; range_end[0] = p[ 0]; range_end[1] = '\0'; /* Have to increment the pointer into the pattern string, so the caller isn't still at the ending character. */ (*p_ptr)++; /* Report an error if the range is empty and the syntax prohibits this. */ ret = syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; /* Here we see why `this_char' has to be larger than an `unsigned char' -- we would otherwise go into an infinite loop, since all characters <= 0xff. */ for (this_char = 0; this_char <= (unsigned char) -1; this_char++) { char ch[2]; ch[0] = this_char; ch[1] = '\0'; if (strcoll (range_start, ch) <= 0 && strcoll (ch, range_end) <= 0) { SET_LIST_BIT (TRANSLATE (this_char)); ret = REG_NOERROR; } } return ret; } /* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible characters can start a string that matches the pattern. This fastmap is used by re_search to skip quickly over impossible starting points. The caller must supply the address of a (1 << BYTEWIDTH)-byte data area as BUFP->fastmap. We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in the pattern buffer. Returns 0 if we succeed, -2 if an internal error. */ int re_compile_fastmap (bufp) struct re_pattern_buffer *bufp; { int j, k; #ifdef MATCH_MAY_ALLOCATE fail_stack_type fail_stack; #endif #ifndef REGEX_MALLOC char *destination; #endif register char *fastmap = bufp->fastmap; unsigned char *pattern = bufp->buffer; unsigned char *p = pattern; register unsigned char *pend = pattern + bufp->used; #ifdef REL_ALLOC /* This holds the pointer to the failure stack, when it is allocated relocatably. */ fail_stack_elt_t *failure_stack_ptr; #endif /* Assume that each path through the pattern can be null until proven otherwise. We set this false at the bottom of switch statement, to which we get only if a particular path doesn't match the empty string. */ boolean path_can_be_null = true; /* We aren't doing a `succeed_n' to begin with. */ boolean succeed_n_p = false; assert (fastmap != NULL && p != NULL); INIT_FAIL_STACK (); bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ bufp->fastmap_accurate = 1; /* It will be when we're done. */ bufp->can_be_null = 0; while (1) { if (p == pend || *p == succeed) { /* We have reached the (effective) end of pattern. */ if (!FAIL_STACK_EMPTY ()) { bufp->can_be_null |= path_can_be_null; /* Reset for next path. */ path_can_be_null = true; p = fail_stack.stack[--fail_stack.avail].pointer; continue; } else break; } /* We should never be about to go beyond the end of the pattern. */ assert (p < pend); switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) { /* I guess the idea here is to simply not bother with a fastmap if a backreference is used, since it's too hard to figure out the fastmap for the corresponding group. Setting `can_be_null' stops `re_search_2' from using the fastmap, so that is all we do. */ case duplicate: bufp->can_be_null = 1; goto done; /* Following are the cases which match a character. These end with `break'. */ case exactn: fastmap[p[1]] = 1; break; case charset: for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) fastmap[j] = 1; break; case charset_not: /* Chars beyond end of map must be allowed. */ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) fastmap[j] = 1; for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) fastmap[j] = 1; break; case wordchar: for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) == Sword) fastmap[j] = 1; break; case notwordchar: for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) != Sword) fastmap[j] = 1; break; case anychar: { int fastmap_newline = fastmap['\n']; /* `.' matches anything ... */ for (j = 0; j < (1 << BYTEWIDTH); j++) fastmap[j] = 1; /* ... except perhaps newline. */ if (!(bufp->syntax & RE_DOT_NEWLINE)) fastmap['\n'] = fastmap_newline; /* Return if we have already set `can_be_null'; if we have, then the fastmap is irrelevant. Something's wrong here. */ else if (bufp->can_be_null) goto done; /* Otherwise, have to check alternative paths. */ break; } #ifdef emacs case syntaxspec: k = *p++; for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) == (enum syntaxcode) k) fastmap[j] = 1; break; case notsyntaxspec: k = *p++; for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) != (enum syntaxcode) k) fastmap[j] = 1; break; /* All cases after this match the empty string. These end with `continue'. */ case before_dot: case at_dot: case after_dot: continue; #endif /* emacs */ case no_op: case begline: case endline: case begbuf: case endbuf: case wordbound: case notwordbound: case wordbeg: case wordend: case push_dummy_failure: continue; case jump_n: case pop_failure_jump: case maybe_pop_jump: case jump: case jump_past_alt: case dummy_failure_jump: EXTRACT_NUMBER_AND_INCR (j, p); p += j; if (j > 0) continue; /* Jump backward implies we just went through the body of a loop and matched nothing. Opcode jumped to should be `on_failure_jump' or `succeed_n'. Just treat it like an ordinary jump. For a * loop, it has pushed its failure point already; if so, discard that as redundant. */ if ((re_opcode_t) *p != on_failure_jump && (re_opcode_t) *p != succeed_n) continue; p++; EXTRACT_NUMBER_AND_INCR (j, p); p += j; /* If what's on the stack is where we are now, pop it. */ if (!FAIL_STACK_EMPTY () && fail_stack.stack[fail_stack.avail - 1].pointer == p) fail_stack.avail--; continue; case on_failure_jump: case on_failure_keep_string_jump: handle_on_failure_jump: EXTRACT_NUMBER_AND_INCR (j, p); /* For some patterns, e.g., `(a?)?', `p+j' here points to the end of the pattern. We don't want to push such a point, since when we restore it above, entering the switch will increment `p' past the end of the pattern. We don't need to push such a point since we obviously won't find any more fastmap entries beyond `pend'. Such a pattern can match the null string, though. */ if (p + j < pend) { if (!PUSH_PATTERN_OP (p + j, fail_stack)) { RESET_FAIL_STACK (); return -2; } } else bufp->can_be_null = 1; if (succeed_n_p) { EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ succeed_n_p = false; } continue; case succeed_n: /* Get to the number of times to succeed. */ p += 2; /* Increment p past the n for when k != 0. */ EXTRACT_NUMBER_AND_INCR (k, p); if (k == 0) { p -= 4; succeed_n_p = true; /* Spaghetti code alert. */ goto handle_on_failure_jump; } continue; case set_number_at: p += 4; continue; case start_memory: case stop_memory: p += 2; continue; default: abort (); /* We have listed all the cases. */ } /* switch *p++ */ /* Getting here means we have found the possible starting characters for one path of the pattern -- and that the empty string does not match. We need not follow this path further. Instead, look at the next alternative (remembered on the stack), or quit if no more. The test at the top of the loop does these things. */ path_can_be_null = false; p = pend; } /* while p */ /* Set `can_be_null' for the last path (also the first path, if the pattern is empty). */ bufp->can_be_null |= path_can_be_null; done: RESET_FAIL_STACK (); return 0; } /* re_compile_fastmap */ #ifdef _LIBC weak_alias (__re_compile_fastmap, re_compile_fastmap) #endif /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use this memory for recording register information. STARTS and ENDS must be allocated using the malloc library routine, and must each be at least NUM_REGS * sizeof (regoff_t) bytes long. If NUM_REGS == 0, then subsequent matches should allocate their own register data. Unless this function is called, the first search or match using PATTERN_BUFFER will allocate its own register data, without freeing the old data. */ void re_set_registers (bufp, regs, num_regs, starts, ends) struct re_pattern_buffer *bufp; struct re_registers *regs; unsigned num_regs; regoff_t *starts, *ends; { if (num_regs) { bufp->regs_allocated = REGS_REALLOCATE; regs->num_regs = num_regs; regs->start = starts; regs->end = ends; } else { bufp->regs_allocated = REGS_UNALLOCATED; regs->num_regs = 0; regs->start = regs->end = (regoff_t *) 0; } } #ifdef _LIBC weak_alias (__re_set_registers, re_set_registers) #endif /* Searching routines. */ /* Like re_search_2, below, but only one string is specified, and doesn't let you say where to stop matching. */ int re_search (bufp, string, size, startpos, range, regs) struct re_pattern_buffer *bufp; const char *string; int size, startpos, range; struct re_registers *regs; { return re_search_2 (bufp, NULL, 0, string, size, startpos, range, regs, size); } #ifdef _LIBC weak_alias (__re_search, re_search) #endif /* Using the compiled pattern in BUFP->buffer, first tries to match the virtual concatenation of STRING1 and STRING2, starting first at index STARTPOS, then at STARTPOS + 1, and so on. STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. RANGE is how far to scan while trying to match. RANGE = 0 means try only at STARTPOS; in general, the last start tried is STARTPOS + RANGE. In REGS, return the indices of the virtual concatenation of STRING1 and STRING2 that matched the entire BUFP->buffer and its contained subexpressions. Do not consider matching one past the index STOP in the virtual concatenation of STRING1 and STRING2. We return either the position in the strings at which the match was found, -1 if no match, or -2 if error (such as failure stack overflow). */ int re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) struct re_pattern_buffer *bufp; const char *string1, *string2; int size1, size2; int startpos; int range; struct re_registers *regs; int stop; { int val; register char *fastmap = bufp->fastmap; register RE_TRANSLATE_TYPE translate = bufp->translate; int total_size = size1 + size2; int endpos = startpos + range; /* Check for out-of-range STARTPOS. */ if (startpos < 0 || startpos > total_size) return -1; /* Fix up RANGE if it might eventually take us outside the virtual concatenation of STRING1 and STRING2. Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */ if (endpos < 0) range = 0 - startpos; else if (endpos > total_size) range = total_size - startpos; /* If the search isn't to be a backwards one, don't waste time in a search for a pattern that must be anchored. */ if (bufp->used > 0 && range > 0 && ((re_opcode_t) bufp->buffer[0] == begbuf /* `begline' is like `begbuf' if it cannot match at newlines. */ || ((re_opcode_t) bufp->buffer[0] == begline && !bufp->newline_anchor))) { if (startpos > 0) return -1; else range = 1; } #ifdef emacs /* In a forward search for something that starts with \=. don't keep searching past point. */ if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0) { range = PT - startpos; if (range <= 0) return -1; } #endif /* emacs */ /* Update the fastmap now if not correct already. */ if (fastmap && !bufp->fastmap_accurate) if (re_compile_fastmap (bufp) == -2) return -2; /* Loop through the string, looking for a place to start matching. */ for (;;) { /* If a fastmap is supplied, skip quickly over characters that cannot be the start of a match. If the pattern can match the null string, however, we don't need to skip characters; we want the first null string. */ if (fastmap && startpos < total_size && !bufp->can_be_null) { if (range > 0) /* Searching forwards. */ { register const char *d; register int lim = 0; int irange = range; if (startpos < size1 && startpos + range >= size1) lim = range - (size1 - startpos); d = (startpos >= size1 ? string2 - size1 : string1) + startpos; /* Written out as an if-else to avoid testing `translate' inside the loop. */ if (translate) while (range > lim && !fastmap[(unsigned char) translate[(unsigned char) *d++]]) range--; else while (range > lim && !fastmap[(unsigned char) *d++]) range--; startpos += irange - range; } else /* Searching backwards. */ { register char c = (size1 == 0 || startpos >= size1 ? string2[startpos - size1] : string1[startpos]); if (!fastmap[(unsigned char) TRANSLATE (c)]) goto advance; } } /* If can't match the null string, and that's all we have left, fail. */ if (range >= 0 && startpos == total_size && fastmap && !bufp->can_be_null) return -1; val = re_match_2_internal (bufp, string1, size1, string2, size2, startpos, regs, stop); #ifndef REGEX_MALLOC # ifdef C_ALLOCA alloca (0); # endif #endif if (val >= 0) return startpos; if (val == -2) return -2; advance: if (!range) break; else if (range > 0) { range--; startpos++; } else { range++; startpos--; } } return -1; } /* re_search_2 */ #ifdef _LIBC weak_alias (__re_search_2, re_search_2) #endif /* This converts PTR, a pointer into one of the search strings `string1' and `string2' into an offset from the beginning of that string. */ #define POINTER_TO_OFFSET(ptr) \ (FIRST_STRING_P (ptr) \ ? ((regoff_t) ((ptr) - string1)) \ : ((regoff_t) ((ptr) - string2 + size1))) /* Macros for dealing with the split strings in re_match_2. */ #define MATCHING_IN_FIRST_STRING (dend == end_match_1) /* Call before fetching a character with *d. This switches over to string2 if necessary. */ #define PREFETCH() \ while (d == dend) \ { \ /* End of string2 => fail. */ \ if (dend == end_match_2) \ goto fail; \ /* End of string1 => advance to string2. */ \ d = string2; \ dend = end_match_2; \ } /* Test if at very beginning or at very end of the virtual concatenation of `string1' and `string2'. If only one string, it's `string2'. */ #define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) #define AT_STRINGS_END(d) ((d) == end2) /* Test if D points to a character which is word-constituent. We have two special cases to check for: if past the end of string1, look at the first character in string2; and if before the beginning of string2, look at the last character in string1. */ #define WORDCHAR_P(d) \ (SYNTAX ((d) == end1 ? *string2 \ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ == Sword) /* Disabled due to a compiler bug -- see comment at case wordbound */ #if 0 /* Test if the character before D and the one at D differ with respect to being word-constituent. */ #define AT_WORD_BOUNDARY(d) \ (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) #endif /* Free everything we malloc. */ #ifdef MATCH_MAY_ALLOCATE # define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL # define FREE_VARIABLES() \ do { \ REGEX_FREE_STACK (fail_stack.stack); \ FREE_VAR (regstart); \ FREE_VAR (regend); \ FREE_VAR (old_regstart); \ FREE_VAR (old_regend); \ FREE_VAR (best_regstart); \ FREE_VAR (best_regend); \ FREE_VAR (reg_info); \ FREE_VAR (reg_dummy); \ FREE_VAR (reg_info_dummy); \ } while (0) #else # define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */ #endif /* not MATCH_MAY_ALLOCATE */ /* These values must meet several constraints. They must not be valid register values; since we have a limit of 255 registers (because we use only one byte in the pattern for the register number), we can use numbers larger than 255. They must differ by 1, because of NUM_FAILURE_ITEMS above. And the value for the lowest register must be larger than the value for the highest register, so we do not try to actually save any registers when none are active. */ #define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) #define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) /* Matching routines. */ #ifndef emacs /* Emacs never uses this. */ /* re_match is like re_match_2 except it takes only a single string. */ int re_match (bufp, string, size, pos, regs) struct re_pattern_buffer *bufp; const char *string; int size, pos; struct re_registers *regs; { int result = re_match_2_internal (bufp, NULL, 0, string, size, pos, regs, size); # ifndef REGEX_MALLOC # ifdef C_ALLOCA alloca (0); # endif # endif return result; } # ifdef _LIBC weak_alias (__re_match, re_match) # endif #endif /* not emacs */ static boolean group_match_null_string_p _RE_ARGS ((unsigned char **p, unsigned char *end, register_info_type *reg_info)); static boolean alt_match_null_string_p _RE_ARGS ((unsigned char *p, unsigned char *end, register_info_type *reg_info)); static boolean common_op_match_null_string_p _RE_ARGS ((unsigned char **p, unsigned char *end, register_info_type *reg_info)); static int bcmp_translate _RE_ARGS ((const char *s1, const char *s2, int len, char *translate)); /* re_match_2 matches the compiled pattern in BUFP against the the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 and SIZE2, respectively). We start matching at POS, and stop matching at STOP. If REGS is non-null and the `no_sub' field of BUFP is nonzero, we store offsets for the substring each group matched in REGS. See the documentation for exactly how many groups we fill. We return -1 if no match, -2 if an internal error (such as the failure stack overflowing). Otherwise, we return the length of the matched substring. */ int re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) struct re_pattern_buffer *bufp; const char *string1, *string2; int size1, size2; int pos; struct re_registers *regs; int stop; { int result = re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop); #ifndef REGEX_MALLOC # ifdef C_ALLOCA alloca (0); # endif #endif return result; } #ifdef _LIBC weak_alias (__re_match_2, re_match_2) #endif /* This is a separate function so that we can force an alloca cleanup afterwards. */ static int re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) struct re_pattern_buffer *bufp; const char *string1, *string2; int size1, size2; int pos; struct re_registers *regs; int stop; { /* General temporaries. */ int mcnt; unsigned char *p1; /* Just past the end of the corresponding string. */ const char *end1, *end2; /* Pointers into string1 and string2, just past the last characters in each to consider matching. */ const char *end_match_1, *end_match_2; /* Where we are in the data, and the end of the current string. */ const char *d, *dend; /* Where we are in the pattern, and the end of the pattern. */ unsigned char *p = bufp->buffer; register unsigned char *pend = p + bufp->used; /* Mark the opcode just after a start_memory, so we can test for an empty subpattern when we get to the stop_memory. */ unsigned char *just_past_start_mem = 0; /* We use this to map every character in the string. */ RE_TRANSLATE_TYPE translate = bufp->translate; /* Failure point stack. Each place that can handle a failure further down the line pushes a failure point on this stack. It consists of restart, regend, and reg_info for all registers corresponding to the subexpressions we're currently inside, plus the number of such registers, and, finally, two char *'s. The first char * is where to resume scanning the pattern; the second one is where to resume scanning the strings. If the latter is zero, the failure point is a ``dummy''; if a failure happens and the failure point is a dummy, it gets discarded and the next next one is tried. */ #ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ fail_stack_type fail_stack; #endif #ifdef DEBUG static unsigned failure_id; unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; #endif #ifdef REL_ALLOC /* This holds the pointer to the failure stack, when it is allocated relocatably. */ fail_stack_elt_t *failure_stack_ptr; #endif /* We fill all the registers internally, independent of what we return, for use in backreferences. The number here includes an element for register zero. */ size_t num_regs = bufp->re_nsub + 1; /* The currently active registers. */ active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG; active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG; /* Information on the contents of registers. These are pointers into the input strings; they record just what was matched (on this attempt) by a subexpression part of the pattern, that is, the regnum-th regstart pointer points to where in the pattern we began matching and the regnum-th regend points to right after where we stopped matching the regnum-th subexpression. (The zeroth register keeps track of what the whole pattern matches.) */ #ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ const char **regstart, **regend; #endif /* If a group that's operated upon by a repetition operator fails to match anything, then the register for its start will need to be restored because it will have been set to wherever in the string we are when we last see its open-group operator. Similarly for a register's end. */ #ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ const char **old_regstart, **old_regend; #endif /* The is_active field of reg_info helps us keep track of which (possibly nested) subexpressions we are currently in. The matched_something field of reg_info[reg_num] helps us tell whether or not we have matched any of the pattern so far this time through the reg_num-th subexpression. These two fields get reset each time through any loop their register is in. */ #ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ register_info_type *reg_info; #endif /* The following record the register info as found in the above variables when we find a match better than any we've seen before. This happens as we backtrack through the failure points, which in turn happens only if we have not yet matched the entire string. */ unsigned best_regs_set = false; #ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ const char **best_regstart, **best_regend; #endif /* Logically, this is `best_regend[0]'. But we don't want to have to allocate space for that if we're not allocating space for anything else (see below). Also, we never need info about register 0 for any of the other register vectors, and it seems rather a kludge to treat `best_regend' differently than the rest. So we keep track of the end of the best match so far in a separate variable. We initialize this to NULL so that when we backtrack the first time and need to test it, it's not garbage. */ const char *match_end = NULL; /* This helps SET_REGS_MATCHED avoid doing redundant work. */ int set_regs_matched_done = 0; /* Used when we pop values we don't care about. */ #ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ const char **reg_dummy; register_info_type *reg_info_dummy; #endif #ifdef DEBUG /* Counts the total number of registers pushed. */ unsigned num_regs_pushed = 0; #endif DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); INIT_FAIL_STACK (); #ifdef MATCH_MAY_ALLOCATE /* Do not bother to initialize all the register variables if there are no groups in the pattern, as it takes a fair amount of time. If there are groups, we include space for register 0 (the whole pattern), even though we never use it, since it simplifies the array indexing. We should fix this. */ if (bufp->re_nsub) { regstart = REGEX_TALLOC (num_regs, const char *); regend = REGEX_TALLOC (num_regs, const char *); old_regstart = REGEX_TALLOC (num_regs, const char *); old_regend = REGEX_TALLOC (num_regs, const char *); best_regstart = REGEX_TALLOC (num_regs, const char *); best_regend = REGEX_TALLOC (num_regs, const char *); reg_info = REGEX_TALLOC (num_regs, register_info_type); reg_dummy = REGEX_TALLOC (num_regs, const char *); reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type); if (!(regstart && regend && old_regstart && old_regend && reg_info && best_regstart && best_regend && reg_dummy && reg_info_dummy)) { FREE_VARIABLES (); return -2; } } else { /* We must initialize all our variables to NULL, so that `FREE_VARIABLES' doesn't try to free them. */ regstart = regend = old_regstart = old_regend = best_regstart = best_regend = reg_dummy = NULL; reg_info = reg_info_dummy = (register_info_type *) NULL; } #endif /* MATCH_MAY_ALLOCATE */ /* The starting position is bogus. */ if (pos < 0 || pos > size1 + size2) { FREE_VARIABLES (); return -1; } /* Initialize subexpression text positions to -1 to mark ones that no start_memory/stop_memory has been seen for. Also initialize the register information struct. */ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) { regstart[mcnt] = regend[mcnt] = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; IS_ACTIVE (reg_info[mcnt]) = 0; MATCHED_SOMETHING (reg_info[mcnt]) = 0; EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; } /* We move `string1' into `string2' if the latter's empty -- but not if `string1' is null. */ if (size2 == 0 && string1 != NULL) { string2 = string1; size2 = size1; string1 = 0; size1 = 0; } end1 = string1 + size1; end2 = string2 + size2; /* Compute where to stop matching, within the two strings. */ if (stop <= size1) { end_match_1 = string1 + stop; end_match_2 = string2; } else { end_match_1 = end1; end_match_2 = string2 + stop - size1; } /* `p' scans through the pattern as `d' scans through the data. `dend' is the end of the input string that `d' points within. `d' is advanced into the following input string whenever necessary, but this happens before fetching; therefore, at the beginning of the loop, `d' can be pointing at the end of a string, but it cannot equal `string2'. */ if (size1 > 0 && pos <= size1) { d = string1 + pos; dend = end_match_1; } else { d = string2 + pos - size1; dend = end_match_2; } DEBUG_PRINT1 ("The compiled pattern is:\n"); DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); DEBUG_PRINT1 ("The string to match is: `"); DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); DEBUG_PRINT1 ("'\n"); /* This loops over pattern commands. It exits by returning from the function if the match is complete, or it drops through if the match fails at this starting point in the input data. */ for (;;) { #ifdef _LIBC DEBUG_PRINT2 ("\n%p: ", p); #else DEBUG_PRINT2 ("\n0x%x: ", p); #endif if (p == pend) { /* End of pattern means we might have succeeded. */ DEBUG_PRINT1 ("end of pattern ... "); /* If we haven't matched the entire string, and we want the longest match, try backtracking. */ if (d != end_match_2) { /* 1 if this match ends in the same string (string1 or string2) as the best previous match. */ boolean same_str_p = (FIRST_STRING_P (match_end) == MATCHING_IN_FIRST_STRING); /* 1 if this match is the best seen so far. */ boolean best_match_p; /* AIX compiler got confused when this was combined with the previous declaration. */ if (same_str_p) best_match_p = d > match_end; else best_match_p = !MATCHING_IN_FIRST_STRING; DEBUG_PRINT1 ("backtracking.\n"); if (!FAIL_STACK_EMPTY ()) { /* More failure points to try. */ /* If exceeds best match so far, save it. */ if (!best_regs_set || best_match_p) { best_regs_set = true; match_end = d; DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) { best_regstart[mcnt] = regstart[mcnt]; best_regend[mcnt] = regend[mcnt]; } } goto fail; } /* If no failure points, don't restore garbage. And if last match is real best match, don't restore second best one. */ else if (best_regs_set && !best_match_p) { restore_best_regs: /* Restore best match. It may happen that `dend == end_match_1' while the restored d is in string2. For example, the pattern `x.*y.*z' against the strings `x-' and `y-z-', if the two strings are not consecutive in memory. */ DEBUG_PRINT1 ("Restoring best registers.\n"); d = match_end; dend = ((d >= string1 && d <= end1) ? end_match_1 : end_match_2); for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) { regstart[mcnt] = best_regstart[mcnt]; regend[mcnt] = best_regend[mcnt]; } } } /* d != end_match_2 */ succeed_label: DEBUG_PRINT1 ("Accepting match.\n"); /* If caller wants register contents data back, do it. */ if (regs && !bufp->no_sub) { /* Have the register data arrays been allocated? */ if (bufp->regs_allocated == REGS_UNALLOCATED) { /* No. So allocate them with malloc. We need one extra element beyond `num_regs' for the `-1' marker GNU code uses. */ regs->num_regs = MAX (RE_NREGS, num_regs + 1); regs->start = TALLOC (regs->num_regs, regoff_t); regs->end = TALLOC (regs->num_regs, regoff_t); if (regs->start == NULL || regs->end == NULL) { FREE_VARIABLES (); return -2; } bufp->regs_allocated = REGS_REALLOCATE; } else if (bufp->regs_allocated == REGS_REALLOCATE) { /* Yes. If we need more elements than were already allocated, reallocate them. If we need fewer, just leave it alone. */ if (regs->num_regs < num_regs + 1) { regs->num_regs = num_regs + 1; RETALLOC (regs->start, regs->num_regs, regoff_t); RETALLOC (regs->end, regs->num_regs, regoff_t); if (regs->start == NULL || regs->end == NULL) { FREE_VARIABLES (); return -2; } } } else { /* These braces fend off a "empty body in an else-statement" warning under GCC when assert expands to nothing. */ assert (bufp->regs_allocated == REGS_FIXED); } /* Convert the pointer data in `regstart' and `regend' to indices. Register zero has to be set differently, since we haven't kept track of any info for it. */ if (regs->num_regs > 0) { regs->start[0] = pos; regs->end[0] = (MATCHING_IN_FIRST_STRING ? ((regoff_t) (d - string1)) : ((regoff_t) (d - string2 + size1))); } /* Go through the first `min (num_regs, regs->num_regs)' registers, since that is all we initialized. */ for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs); mcnt++) { if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) regs->start[mcnt] = regs->end[mcnt] = -1; else { regs->start[mcnt] = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); regs->end[mcnt] = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); } } /* If the regs structure we return has more elements than were in the pattern, set the extra elements to -1. If we (re)allocated the registers, this is the case, because we always allocate enough to have at least one -1 at the end. */ for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++) regs->start[mcnt] = regs->end[mcnt] = -1; } /* regs && !bufp->no_sub */ DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", nfailure_points_pushed, nfailure_points_popped, nfailure_points_pushed - nfailure_points_popped); DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); mcnt = d - pos - (MATCHING_IN_FIRST_STRING ? string1 : string2 - size1); DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); FREE_VARIABLES (); return mcnt; } /* Otherwise match next pattern command. */ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) { /* Ignore these. Used to ignore the n of succeed_n's which currently have n == 0. */ case no_op: DEBUG_PRINT1 ("EXECUTING no_op.\n"); break; case succeed: DEBUG_PRINT1 ("EXECUTING succeed.\n"); goto succeed_label; /* Match the next n pattern characters exactly. The following byte in the pattern defines n, and the n bytes after that are the characters to match. */ case exactn: mcnt = *p++; DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); /* This is written out as an if-else so we don't waste time testing `translate' inside the loop. */ if (translate) { do { PREFETCH (); if ((unsigned char) translate[(unsigned char) *d++] != (unsigned char) *p++) goto fail; } while (--mcnt); } else { do { PREFETCH (); if (*d++ != (char) *p++) goto fail; } while (--mcnt); } SET_REGS_MATCHED (); break; /* Match any character except possibly a newline or a null. */ case anychar: DEBUG_PRINT1 ("EXECUTING anychar.\n"); PREFETCH (); if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) goto fail; SET_REGS_MATCHED (); DEBUG_PRINT2 (" Matched `%d'.\n", *d); d++; break; case charset: case charset_not: { register unsigned char c; boolean not = (re_opcode_t) *(p - 1) == charset_not; DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); PREFETCH (); c = TRANSLATE (*d); /* The character to match. */ /* Cast to `unsigned' instead of `unsigned char' in case the bit list is a full 32 bytes long. */ if (c < (unsigned) (*p * BYTEWIDTH) && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) not = !not; p += 1 + *p; if (!not) goto fail; SET_REGS_MATCHED (); d++; break; } /* The beginning of a group is represented by start_memory. The arguments are the register number in the next byte, and the number of groups inner to this one in the next. The text matched within the group is recorded (in the internal registers data structure) under the register number. */ case start_memory: DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]); /* Find out if this group can match the empty string. */ p1 = p; /* To send to group_match_null_string_p. */ if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) REG_MATCH_NULL_STRING_P (reg_info[*p]) = group_match_null_string_p (&p1, pend, reg_info); /* Save the position in the string where we were the last time we were at this open-group operator in case the group is operated upon by a repetition operator, e.g., with `(a*)*b' against `ab'; then we want to ignore where we are now in the string in case this attempt to match fails. */ old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) ? REG_UNSET (regstart[*p]) ? d : regstart[*p] : regstart[*p]; DEBUG_PRINT2 (" old_regstart: %d\n", POINTER_TO_OFFSET (old_regstart[*p])); regstart[*p] = d; DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); IS_ACTIVE (reg_info[*p]) = 1; MATCHED_SOMETHING (reg_info[*p]) = 0; /* Clear this whenever we change the register activity status. */ set_regs_matched_done = 0; /* This is the new highest active register. */ highest_active_reg = *p; /* If nothing was active before, this is the new lowest active register. */ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) lowest_active_reg = *p; /* Move past the register number and inner group count. */ p += 2; just_past_start_mem = p; break; /* The stop_memory opcode represents the end of a group. Its arguments are the same as start_memory's: the register number, and the number of inner groups. */ case stop_memory: DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]); /* We need to save the string position the last time we were at this close-group operator in case the group is operated upon by a repetition operator, e.g., with `((a*)*(b*)*)*' against `aba'; then we want to ignore where we are now in the string in case this attempt to match fails. */ old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) ? REG_UNSET (regend[*p]) ? d : regend[*p] : regend[*p]; DEBUG_PRINT2 (" old_regend: %d\n", POINTER_TO_OFFSET (old_regend[*p])); regend[*p] = d; DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); /* This register isn't active anymore. */ IS_ACTIVE (reg_info[*p]) = 0; /* Clear this whenever we change the register activity status. */ set_regs_matched_done = 0; /* If this was the only register active, nothing is active anymore. */ if (lowest_active_reg == highest_active_reg) { lowest_active_reg = NO_LOWEST_ACTIVE_REG; highest_active_reg = NO_HIGHEST_ACTIVE_REG; } else { /* We must scan for the new highest active register, since it isn't necessarily one less than now: consider (a(b)c(d(e)f)g). When group 3 ends, after the f), the new highest active register is 1. */ unsigned char r = *p - 1; while (r > 0 && !IS_ACTIVE (reg_info[r])) r--; /* If we end up at register zero, that means that we saved the registers as the result of an `on_failure_jump', not a `start_memory', and we jumped to past the innermost `stop_memory'. For example, in ((.)*) we save registers 1 and 2 as a result of the *, but when we pop back to the second ), we are at the stop_memory 1. Thus, nothing is active. */ if (r == 0) { lowest_active_reg = NO_LOWEST_ACTIVE_REG; highest_active_reg = NO_HIGHEST_ACTIVE_REG; } else highest_active_reg = r; } /* If just failed to match something this time around with a group that's operated on by a repetition operator, try to force exit from the ``loop'', and restore the register information for this group that we had before trying this last match. */ if ((!MATCHED_SOMETHING (reg_info[*p]) || just_past_start_mem == p - 1) && (p + 2) < pend) { boolean is_a_jump_n = false; p1 = p + 2; mcnt = 0; switch ((re_opcode_t) *p1++) { case jump_n: is_a_jump_n = true; case pop_failure_jump: case maybe_pop_jump: case jump: case dummy_failure_jump: EXTRACT_NUMBER_AND_INCR (mcnt, p1); if (is_a_jump_n) p1 += 2; break; default: /* do nothing */ ; } p1 += mcnt; /* If the next operation is a jump backwards in the pattern to an on_failure_jump right before the start_memory corresponding to this stop_memory, exit from the loop by forcing a failure after pushing on the stack the on_failure_jump's jump in the pattern, and d. */ if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump && (re_opcode_t) p1[3] == start_memory && p1[4] == *p) { /* If this group ever matched anything, then restore what its registers were before trying this last failed match, e.g., with `(a*)*b' against `ab' for regstart[1], and, e.g., with `((a*)*(b*)*)*' against `aba' for regend[3]. Also restore the registers for inner groups for, e.g., `((a*)(b*))*' against `aba' (register 3 would otherwise get trashed). */ if (EVER_MATCHED_SOMETHING (reg_info[*p])) { unsigned r; EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; /* Restore this and inner groups' (if any) registers. */ for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1); r++) { regstart[r] = old_regstart[r]; /* xx why this test? */ if (old_regend[r] >= regstart[r]) regend[r] = old_regend[r]; } } p1++; EXTRACT_NUMBER_AND_INCR (mcnt, p1); PUSH_FAILURE_POINT (p1 + mcnt, d, -2); goto fail; } } /* Move past the register number and the inner group count. */ p += 2; break; /* \ has been turned into a `duplicate' command which is followed by the numeric value of as the register number. */ case duplicate: { register const char *d2, *dend2; int regno = *p++; /* Get which register to match against. */ DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); /* Can't back reference a group which we've never matched. */ if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) goto fail; /* Where in input to try to start matching. */ d2 = regstart[regno]; /* Where to stop matching; if both the place to start and the place to stop matching are in the same string, then set to the place to stop, otherwise, for now have to use the end of the first string. */ dend2 = ((FIRST_STRING_P (regstart[regno]) == FIRST_STRING_P (regend[regno])) ? regend[regno] : end_match_1); for (;;) { /* If necessary, advance to next segment in register contents. */ while (d2 == dend2) { if (dend2 == end_match_2) break; if (dend2 == regend[regno]) break; /* End of string1 => advance to string2. */ d2 = string2; dend2 = regend[regno]; } /* At end of register contents => success */ if (d2 == dend2) break; /* If necessary, advance to next segment in data. */ PREFETCH (); /* How many characters left in this segment to match. */ mcnt = dend - d; /* Want how many consecutive characters we can match in one shot, so, if necessary, adjust the count. */ if (mcnt > dend2 - d2) mcnt = dend2 - d2; /* Compare that many; failure if mismatch, else move past them. */ if (translate ? bcmp_translate (d, d2, mcnt, translate) : memcmp (d, d2, mcnt)) goto fail; d += mcnt, d2 += mcnt; /* Do this because we've match some characters. */ SET_REGS_MATCHED (); } } break; /* begline matches the empty string at the beginning of the string (unless `not_bol' is set in `bufp'), and, if `newline_anchor' is set, after newlines. */ case begline: DEBUG_PRINT1 ("EXECUTING begline.\n"); if (AT_STRINGS_BEG (d)) { if (!bufp->not_bol) break; } else if (d[-1] == '\n' && bufp->newline_anchor) { break; } /* In all other cases, we fail. */ goto fail; /* endline is the dual of begline. */ case endline: DEBUG_PRINT1 ("EXECUTING endline.\n"); if (AT_STRINGS_END (d)) { if (!bufp->not_eol) break; } /* We have to ``prefetch'' the next character. */ else if ((d == end1 ? *string2 : *d) == '\n' && bufp->newline_anchor) { break; } goto fail; /* Match at the very beginning of the data. */ case begbuf: DEBUG_PRINT1 ("EXECUTING begbuf.\n"); if (AT_STRINGS_BEG (d)) break; goto fail; /* Match at the very end of the data. */ case endbuf: DEBUG_PRINT1 ("EXECUTING endbuf.\n"); if (AT_STRINGS_END (d)) break; goto fail; /* on_failure_keep_string_jump is used to optimize `.*\n'. It pushes NULL as the value for the string on the stack. Then `pop_failure_point' will keep the current value for the string, instead of restoring it. To see why, consider matching `foo\nbar' against `.*\n'. The .* matches the foo; then the . fails against the \n. But the next thing we want to do is match the \n against the \n; if we restored the string value, we would be back at the foo. Because this is used only in specific cases, we don't need to check all the things that `on_failure_jump' does, to make sure the right things get saved on the stack. Hence we don't share its code. The only reason to push anything on the stack at all is that otherwise we would have to change `anychar's code to do something besides goto fail in this case; that seems worse than this. */ case on_failure_keep_string_jump: DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); EXTRACT_NUMBER_AND_INCR (mcnt, p); #ifdef _LIBC DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt); #else DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); #endif PUSH_FAILURE_POINT (p + mcnt, NULL, -2); break; /* Uses of on_failure_jump: Each alternative starts with an on_failure_jump that points to the beginning of the next alternative. Each alternative except the last ends with a jump that in effect jumps past the rest of the alternatives. (They really jump to the ending jump of the following alternative, because tensioning these jumps is a hassle.) Repeats start with an on_failure_jump that points past both the repetition text and either the following jump or pop_failure_jump back to this on_failure_jump. */ case on_failure_jump: on_failure: DEBUG_PRINT1 ("EXECUTING on_failure_jump"); EXTRACT_NUMBER_AND_INCR (mcnt, p); #ifdef _LIBC DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt); #else DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); #endif /* If this on_failure_jump comes right before a group (i.e., the original * applied to a group), save the information for that group and all inner ones, so that if we fail back to this point, the group's information will be correct. For example, in \(a*\)*\1, we need the preceding group, and in \(zz\(a*\)b*\)\2, we need the inner group. */ /* We can't use `p' to check ahead because we push a failure point to `p + mcnt' after we do this. */ p1 = p; /* We need to skip no_op's before we look for the start_memory in case this on_failure_jump is happening as the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 against aba. */ while (p1 < pend && (re_opcode_t) *p1 == no_op) p1++; if (p1 < pend && (re_opcode_t) *p1 == start_memory) { /* We have a new highest active register now. This will get reset at the start_memory we are about to get to, but we will have saved all the registers relevant to this repetition op, as described above. */ highest_active_reg = *(p1 + 1) + *(p1 + 2); if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) lowest_active_reg = *(p1 + 1); } DEBUG_PRINT1 (":\n"); PUSH_FAILURE_POINT (p + mcnt, d, -2); break; /* A smart repeat ends with `maybe_pop_jump'. We change it to either `pop_failure_jump' or `jump'. */ case maybe_pop_jump: EXTRACT_NUMBER_AND_INCR (mcnt, p); DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); { register unsigned char *p2 = p; /* Compare the beginning of the repeat with what in the pattern follows its end. If we can establish that there is nothing that they would both match, i.e., that we would have to backtrack because of (as in, e.g., `a*a') then we can change to pop_failure_jump, because we'll never have to backtrack. This is not true in the case of alternatives: in `(a|ab)*' we do need to backtrack to the `ab' alternative (e.g., if the string was `ab'). But instead of trying to detect that here, the alternative has put on a dummy failure point which is what we will end up popping. */ /* Skip over open/close-group commands. If what follows this loop is a ...+ construct, look at what begins its body, since we will have to match at least one of that. */ while (1) { if (p2 + 2 < pend && ((re_opcode_t) *p2 == stop_memory || (re_opcode_t) *p2 == start_memory)) p2 += 3; else if (p2 + 6 < pend && (re_opcode_t) *p2 == dummy_failure_jump) p2 += 6; else break; } p1 = p + mcnt; /* p1[0] ... p1[2] are the `on_failure_jump' corresponding to the `maybe_finalize_jump' of this case. Examine what follows. */ /* If we're at the end of the pattern, we can change. */ if (p2 == pend) { /* Consider what happens when matching ":\(.*\)" against ":/". I don't really understand this code yet. */ p[-3] = (unsigned char) pop_failure_jump; DEBUG_PRINT1 (" End of pattern: change to `pop_failure_jump'.\n"); } else if ((re_opcode_t) *p2 == exactn || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) { register unsigned char c = *p2 == (unsigned char) endline ? '\n' : p2[2]; if ((re_opcode_t) p1[3] == exactn && p1[5] != c) { p[-3] = (unsigned char) pop_failure_jump; DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", c, p1[5]); } else if ((re_opcode_t) p1[3] == charset || (re_opcode_t) p1[3] == charset_not) { int not = (re_opcode_t) p1[3] == charset_not; if (c < (unsigned char) (p1[4] * BYTEWIDTH) && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) not = !not; /* `not' is equal to 1 if c would match, which means that we can't change to pop_failure_jump. */ if (!not) { p[-3] = (unsigned char) pop_failure_jump; DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); } } } else if ((re_opcode_t) *p2 == charset) { /* We win if the first character of the loop is not part of the charset. */ if ((re_opcode_t) p1[3] == exactn && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5] && (p2[2 + p1[5] / BYTEWIDTH] & (1 << (p1[5] % BYTEWIDTH))))) { p[-3] = (unsigned char) pop_failure_jump; DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); } else if ((re_opcode_t) p1[3] == charset_not) { int idx; /* We win if the charset_not inside the loop lists every character listed in the charset after. */ for (idx = 0; idx < (int) p2[1]; idx++) if (! (p2[2 + idx] == 0 || (idx < (int) p1[4] && ((p2[2 + idx] & ~ p1[5 + idx]) == 0)))) break; if (idx == p2[1]) { p[-3] = (unsigned char) pop_failure_jump; DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); } } else if ((re_opcode_t) p1[3] == charset) { int idx; /* We win if the charset inside the loop has no overlap with the one after the loop. */ for (idx = 0; idx < (int) p2[1] && idx < (int) p1[4]; idx++) if ((p2[2 + idx] & p1[5 + idx]) != 0) break; if (idx == p2[1] || idx == p1[4]) { p[-3] = (unsigned char) pop_failure_jump; DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); } } } } p -= 2; /* Point at relative address again. */ if ((re_opcode_t) p[-1] != pop_failure_jump) { p[-1] = (unsigned char) jump; DEBUG_PRINT1 (" Match => jump.\n"); goto unconditional_jump; } /* Note fall through. */ /* The end of a simple repeat has a pop_failure_jump back to its matching on_failure_jump, where the latter will push a failure point. The pop_failure_jump takes off failure points put on by this pop_failure_jump's matching on_failure_jump; we got through the pattern to here from the matching on_failure_jump, so didn't fail. */ case pop_failure_jump: { /* We need to pass separate storage for the lowest and highest registers, even though we don't care about the actual values. Otherwise, we will restore only one register from the stack, since lowest will == highest in `pop_failure_point'. */ active_reg_t dummy_low_reg, dummy_high_reg; unsigned char *pdummy; const char *sdummy; DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); POP_FAILURE_POINT (sdummy, pdummy, dummy_low_reg, dummy_high_reg, reg_dummy, reg_dummy, reg_info_dummy); } /* Note fall through. */ unconditional_jump: #ifdef _LIBC DEBUG_PRINT2 ("\n%p: ", p); #else DEBUG_PRINT2 ("\n0x%x: ", p); #endif /* Note fall through. */ /* Unconditionally jump (without popping any failure points). */ case jump: EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); p += mcnt; /* Do the jump. */ #ifdef _LIBC DEBUG_PRINT2 ("(to %p).\n", p); #else DEBUG_PRINT2 ("(to 0x%x).\n", p); #endif break; /* We need this opcode so we can detect where alternatives end in `group_match_null_string_p' et al. */ case jump_past_alt: DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); goto unconditional_jump; /* Normally, the on_failure_jump pushes a failure point, which then gets popped at pop_failure_jump. We will end up at pop_failure_jump, also, and with a pattern of, say, `a+', we are skipping over the on_failure_jump, so we have to push something meaningless for pop_failure_jump to pop. */ case dummy_failure_jump: DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); /* It doesn't matter what we push for the string here. What the code at `fail' tests is the value for the pattern. */ PUSH_FAILURE_POINT (NULL, NULL, -2); goto unconditional_jump; /* At the end of an alternative, we need to push a dummy failure point in case we are followed by a `pop_failure_jump', because we don't want the failure point for the alternative to be popped. For example, matching `(a|ab)*' against `aab' requires that we match the `ab' alternative. */ case push_dummy_failure: DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); /* See comments just above at `dummy_failure_jump' about the two zeroes. */ PUSH_FAILURE_POINT (NULL, NULL, -2); break; /* Have to succeed matching what follows at least n times. After that, handle like `on_failure_jump'. */ case succeed_n: EXTRACT_NUMBER (mcnt, p + 2); DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); assert (mcnt >= 0); /* Originally, this is how many times we HAVE to succeed. */ if (mcnt > 0) { mcnt--; p += 2; STORE_NUMBER_AND_INCR (p, mcnt); #ifdef _LIBC DEBUG_PRINT3 (" Setting %p to %d.\n", p - 2, mcnt); #else DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p - 2, mcnt); #endif } else if (mcnt == 0) { #ifdef _LIBC DEBUG_PRINT2 (" Setting two bytes from %p to no_op.\n", p+2); #else DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2); #endif p[2] = (unsigned char) no_op; p[3] = (unsigned char) no_op; goto on_failure; } break; case jump_n: EXTRACT_NUMBER (mcnt, p + 2); DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); /* Originally, this is how many times we CAN jump. */ if (mcnt) { mcnt--; STORE_NUMBER (p + 2, mcnt); #ifdef _LIBC DEBUG_PRINT3 (" Setting %p to %d.\n", p + 2, mcnt); #else DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p + 2, mcnt); #endif goto unconditional_jump; } /* If don't have to jump any more, skip over the rest of command. */ else p += 4; break; case set_number_at: { DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); EXTRACT_NUMBER_AND_INCR (mcnt, p); p1 = p + mcnt; EXTRACT_NUMBER_AND_INCR (mcnt, p); #ifdef _LIBC DEBUG_PRINT3 (" Setting %p to %d.\n", p1, mcnt); #else DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); #endif STORE_NUMBER (p1, mcnt); break; } #if 0 /* The DEC Alpha C compiler 3.x generates incorrect code for the test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of AT_WORD_BOUNDARY, so this code is disabled. Expanding the macro and introducing temporary variables works around the bug. */ case wordbound: DEBUG_PRINT1 ("EXECUTING wordbound.\n"); if (AT_WORD_BOUNDARY (d)) break; goto fail; case notwordbound: DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); if (AT_WORD_BOUNDARY (d)) goto fail; break; #else case wordbound: { boolean prevchar, thischar; DEBUG_PRINT1 ("EXECUTING wordbound.\n"); if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) break; prevchar = WORDCHAR_P (d - 1); thischar = WORDCHAR_P (d); if (prevchar != thischar) break; goto fail; } case notwordbound: { boolean prevchar, thischar; DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) goto fail; prevchar = WORDCHAR_P (d - 1); thischar = WORDCHAR_P (d); if (prevchar != thischar) goto fail; break; } #endif case wordbeg: DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) break; goto fail; case wordend: DEBUG_PRINT1 ("EXECUTING wordend.\n"); if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) && (!WORDCHAR_P (d) || AT_STRINGS_END (d))) break; goto fail; #ifdef emacs case before_dot: DEBUG_PRINT1 ("EXECUTING before_dot.\n"); if (PTR_CHAR_POS ((unsigned char *) d) >= point) goto fail; break; case at_dot: DEBUG_PRINT1 ("EXECUTING at_dot.\n"); if (PTR_CHAR_POS ((unsigned char *) d) != point) goto fail; break; case after_dot: DEBUG_PRINT1 ("EXECUTING after_dot.\n"); if (PTR_CHAR_POS ((unsigned char *) d) <= point) goto fail; break; case syntaxspec: DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); mcnt = *p++; goto matchsyntax; case wordchar: DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); mcnt = (int) Sword; matchsyntax: PREFETCH (); /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ d++; if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt) goto fail; SET_REGS_MATCHED (); break; case notsyntaxspec: DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); mcnt = *p++; goto matchnotsyntax; case notwordchar: DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); mcnt = (int) Sword; matchnotsyntax: PREFETCH (); /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ d++; if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt) goto fail; SET_REGS_MATCHED (); break; #else /* not emacs */ case wordchar: DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); PREFETCH (); if (!WORDCHAR_P (d)) goto fail; SET_REGS_MATCHED (); d++; break; case notwordchar: DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); PREFETCH (); if (WORDCHAR_P (d)) goto fail; SET_REGS_MATCHED (); d++; break; #endif /* not emacs */ default: abort (); } continue; /* Successfully executed one pattern command; keep going. */ /* We goto here if a matching operation fails. */ fail: if (!FAIL_STACK_EMPTY ()) { /* A restart point is known. Restore to that state. */ DEBUG_PRINT1 ("\nFAIL:\n"); POP_FAILURE_POINT (d, p, lowest_active_reg, highest_active_reg, regstart, regend, reg_info); /* If this failure point is a dummy, try the next one. */ if (!p) goto fail; /* If we failed to the end of the pattern, don't examine *p. */ assert (p <= pend); if (p < pend) { boolean is_a_jump_n = false; /* If failed to a backwards jump that's part of a repetition loop, need to pop this failure point and use the next one. */ switch ((re_opcode_t) *p) { case jump_n: is_a_jump_n = true; case maybe_pop_jump: case pop_failure_jump: case jump: p1 = p + 1; EXTRACT_NUMBER_AND_INCR (mcnt, p1); p1 += mcnt; if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) || (!is_a_jump_n && (re_opcode_t) *p1 == on_failure_jump)) goto fail; break; default: /* do nothing */ ; } } if (d >= string1 && d <= end1) dend = end_match_1; } else break; /* Matching at this starting point really fails. */ } /* for (;;) */ if (best_regs_set) goto restore_best_regs; FREE_VARIABLES (); return -1; /* Failure to match. */ } /* re_match_2 */ /* Subroutine definitions for re_match_2. */ /* We are passed P pointing to a register number after a start_memory. Return true if the pattern up to the corresponding stop_memory can match the empty string, and false otherwise. If we find the matching stop_memory, sets P to point to one past its number. Otherwise, sets P to an undefined byte less than or equal to END. We don't handle duplicates properly (yet). */ static boolean group_match_null_string_p (p, end, reg_info) unsigned char **p, *end; register_info_type *reg_info; { int mcnt; /* Point to after the args to the start_memory. */ unsigned char *p1 = *p + 2; while (p1 < end) { /* Skip over opcodes that can match nothing, and return true or false, as appropriate, when we get to one that can't, or to the matching stop_memory. */ switch ((re_opcode_t) *p1) { /* Could be either a loop or a series of alternatives. */ case on_failure_jump: p1++; EXTRACT_NUMBER_AND_INCR (mcnt, p1); /* If the next operation is not a jump backwards in the pattern. */ if (mcnt >= 0) { /* Go through the on_failure_jumps of the alternatives, seeing if any of the alternatives cannot match nothing. The last alternative starts with only a jump, whereas the rest start with on_failure_jump and end with a jump, e.g., here is the pattern for `a|b|c': /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 /exactn/1/c So, we have to first go through the first (n-1) alternatives and then deal with the last one separately. */ /* Deal with the first (n-1) alternatives, which start with an on_failure_jump (see above) that jumps to right past a jump_past_alt. */ while ((re_opcode_t) p1[mcnt-3] == jump_past_alt) { /* `mcnt' holds how many bytes long the alternative is, including the ending `jump_past_alt' and its number. */ if (!alt_match_null_string_p (p1, p1 + mcnt - 3, reg_info)) return false; /* Move to right after this alternative, including the jump_past_alt. */ p1 += mcnt; /* Break if it's the beginning of an n-th alternative that doesn't begin with an on_failure_jump. */ if ((re_opcode_t) *p1 != on_failure_jump) break; /* Still have to check that it's not an n-th alternative that starts with an on_failure_jump. */ p1++; EXTRACT_NUMBER_AND_INCR (mcnt, p1); if ((re_opcode_t) p1[mcnt-3] != jump_past_alt) { /* Get to the beginning of the n-th alternative. */ p1 -= 3; break; } } /* Deal with the last alternative: go back and get number of the `jump_past_alt' just before it. `mcnt' contains the length of the alternative. */ EXTRACT_NUMBER (mcnt, p1 - 2); if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info)) return false; p1 += mcnt; /* Get past the n-th alternative. */ } /* if mcnt > 0 */ break; case stop_memory: assert (p1[1] == **p); *p = p1 + 2; return true; default: if (!common_op_match_null_string_p (&p1, end, reg_info)) return false; } } /* while p1 < end */ return false; } /* group_match_null_string_p */ /* Similar to group_match_null_string_p, but doesn't deal with alternatives: It expects P to be the first byte of a single alternative and END one byte past the last. The alternative can contain groups. */ static boolean alt_match_null_string_p (p, end, reg_info) unsigned char *p, *end; register_info_type *reg_info; { int mcnt; unsigned char *p1 = p; while (p1 < end) { /* Skip over opcodes that can match nothing, and break when we get to one that can't. */ switch ((re_opcode_t) *p1) { /* It's a loop. */ case on_failure_jump: p1++; EXTRACT_NUMBER_AND_INCR (mcnt, p1); p1 += mcnt; break; default: if (!common_op_match_null_string_p (&p1, end, reg_info)) return false; } } /* while p1 < end */ return true; } /* alt_match_null_string_p */ /* Deals with the ops common to group_match_null_string_p and alt_match_null_string_p. Sets P to one after the op and its arguments, if any. */ static boolean common_op_match_null_string_p (p, end, reg_info) unsigned char **p, *end; register_info_type *reg_info; { int mcnt; boolean ret; int reg_no; unsigned char *p1 = *p; switch ((re_opcode_t) *p1++) { case no_op: case begline: case endline: case begbuf: case endbuf: case wordbeg: case wordend: case wordbound: case notwordbound: #ifdef emacs case before_dot: case at_dot: case after_dot: #endif break; case start_memory: reg_no = *p1; assert (reg_no > 0 && reg_no <= MAX_REGNUM); ret = group_match_null_string_p (&p1, end, reg_info); /* Have to set this here in case we're checking a group which contains a group and a back reference to it. */ if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; if (!ret) return false; break; /* If this is an optimized succeed_n for zero times, make the jump. */ case jump: EXTRACT_NUMBER_AND_INCR (mcnt, p1); if (mcnt >= 0) p1 += mcnt; else return false; break; case succeed_n: /* Get to the number of times to succeed. */ p1 += 2; EXTRACT_NUMBER_AND_INCR (mcnt, p1); if (mcnt == 0) { p1 -= 4; EXTRACT_NUMBER_AND_INCR (mcnt, p1); p1 += mcnt; } else return false; break; case duplicate: if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) return false; break; case set_number_at: p1 += 4; default: /* All other opcodes mean we cannot match the empty string. */ return false; } *p = p1; return true; } /* common_op_match_null_string_p */ /* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN bytes; nonzero otherwise. */ static int bcmp_translate (s1, s2, len, translate) const char *s1, *s2; register int len; RE_TRANSLATE_TYPE translate; { register const unsigned char *p1 = (const unsigned char *) s1; register const unsigned char *p2 = (const unsigned char *) s2; while (len) { if (translate[*p1++] != translate[*p2++]) return 1; len--; } return 0; } /* Entry points for GNU code. */ /* re_compile_pattern is the GNU regular expression compiler: it compiles PATTERN (of length SIZE) and puts the result in BUFP. Returns 0 if the pattern was valid, otherwise an error string. Assumes the `allocated' (and perhaps `buffer') and `translate' fields are set in BUFP on entry. We call regex_compile to do the actual compilation. */ const char * re_compile_pattern (pattern, length, bufp) const char *pattern; size_t length; struct re_pattern_buffer *bufp; { reg_errcode_t ret; /* GNU code is written to assume at least RE_NREGS registers will be set (and at least one extra will be -1). */ bufp->regs_allocated = REGS_UNALLOCATED; /* And GNU code determines whether or not to get register information by passing null for the REGS argument to re_match, etc., not by setting no_sub. */ bufp->no_sub = 0; /* Match anchors at newline. */ bufp->newline_anchor = 1; ret = regex_compile (pattern, length, re_syntax_options, bufp); if (!ret) return NULL; return gettext (re_error_msgid + re_error_msgid_idx[(int) ret]); } #ifdef _LIBC weak_alias (__re_compile_pattern, re_compile_pattern) #endif /* Entry points compatible with 4.2 BSD regex library. We don't define them unless specifically requested. */ #if defined _REGEX_RE_COMP || defined _LIBC /* BSD has one and only one pattern buffer. */ static struct re_pattern_buffer re_comp_buf; char * #ifdef _LIBC /* Make these definitions weak in libc, so POSIX programs can redefine these names if they don't use our functions, and still use Rregcomp/Rregexec below without link errors. */ weak_function #endif re_comp (s) const char *s; { reg_errcode_t ret; if (!s) { if (!re_comp_buf.buffer) return gettext ("No previous regular expression"); return 0; } if (!re_comp_buf.buffer) { re_comp_buf.buffer = (unsigned char *) xmalloc (200); if (re_comp_buf.buffer == NULL) return (char *) gettext (re_error_msgid + re_error_msgid_idx[(int) REG_ESPACE]); re_comp_buf.allocated = 200; re_comp_buf.fastmap = (char *) xmalloc (1 << BYTEWIDTH); if (re_comp_buf.fastmap == NULL) return (char *) gettext (re_error_msgid + re_error_msgid_idx[(int) REG_ESPACE]); } /* Since `re_exec' always passes NULL for the `regs' argument, we don't need to initialize the pattern buffer fields which affect it. */ /* Match anchors at newlines. */ re_comp_buf.newline_anchor = 1; ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); if (!ret) return NULL; /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ return (char *) gettext (re_error_msgid + re_error_msgid_idx[(int) ret]); } int #ifdef _LIBC weak_function #endif re_exec (s) const char *s; { const int len = strlen (s); return 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); } #endif /* _REGEX_RE_COMP */ /* POSIX.2 functions. Don't define these for Emacs. */ #ifndef emacs /* Rregcomp takes a regular expression as a string and compiles it. PREG is a regex_t *. We do not expect any fields to be initialized, since POSIX says we shouldn't. Thus, we set `buffer' to the compiled pattern; `used' to the length of the compiled pattern; `syntax' to RE_SYNTAX_POSIX_EXTENDED if the REG_EXTENDED bit in CFLAGS is set; otherwise, to RE_SYNTAX_POSIX_BASIC; `newline_anchor' to REG_NEWLINE being set in CFLAGS; `fastmap' to an allocated space for the fastmap; `fastmap_accurate' to zero; `re_nsub' to the number of subexpressions in PATTERN. PATTERN is the address of the pattern string. CFLAGS is a series of bits which affect compilation. If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we use POSIX basic syntax. If REG_NEWLINE is set, then . and [^...] don't match newline. Also, Rregexec will try a match beginning after every newline. If REG_ICASE is set, then we considers upper- and lowercase versions of letters to be equivalent when matching. If REG_NOSUB is set, then when PREG is passed to Rregexec, that routine will report only success or failure, and nothing about the registers. It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for the return codes and their meanings.) */ int Rregcomp (regex_t *preg, const char *pattern, int cflags) { reg_errcode_t ret; reg_syntax_t syntax = (cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; /* regex_compile will allocate the space for the compiled pattern. */ preg->buffer = 0; preg->allocated = 0; preg->used = 0; /* Try to allocate space for the fastmap. */ preg->fastmap = (char *) xmalloc (1 << BYTEWIDTH); if (cflags & REG_ICASE) { unsigned i; preg->translate = (RE_TRANSLATE_TYPE) xmalloc (CHAR_SET_SIZE * sizeof (*(RE_TRANSLATE_TYPE)0)); if (preg->translate == NULL) return (int) REG_ESPACE; /* Map uppercase characters to corresponding lowercase ones. */ for (i = 0; i < CHAR_SET_SIZE; i++) preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i; } else preg->translate = NULL; /* If REG_NEWLINE is set, newlines are treated differently. */ if (cflags & REG_NEWLINE) { /* REG_NEWLINE implies neither . nor [^...] match newline. */ syntax &= ~RE_DOT_NEWLINE; syntax |= RE_HAT_LISTS_NOT_NEWLINE; /* It also changes the matching behavior. */ preg->newline_anchor = 1; } else preg->newline_anchor = 0; preg->no_sub = !!(cflags & REG_NOSUB); /* POSIX says a null character in the pattern terminates it, so we can use strlen here in compiling the pattern. */ ret = regex_compile (pattern, strlen (pattern), syntax, preg); /* POSIX doesn't distinguish between an unmatched open-group and an unmatched close-group: both are REG_EPAREN. */ if (ret == REG_ERPAREN) ret = REG_EPAREN; if (ret == REG_NOERROR && preg->fastmap) { /* Compute the fastmap now, since Rregexec cannot modify the pattern buffer. */ if (re_compile_fastmap (preg) == -2) { /* Some error occured while computing the fastmap, just forget about it. */ free (preg->fastmap); preg->fastmap = NULL; } } return (int) ret; } #ifdef _LIBC weak_alias (__Rregcomp, Rregcomp) #endif /* Rregexec searches for a given pattern, specified by PREG, in the string STRING. If NMATCH is zero or REG_NOSUB was set in the cflags argument to `Rregcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at least NMATCH elements, and we set them to the offsets of the corresponding matched substrings. EFLAGS specifies `execution flags' which affect matching: if REG_NOTBOL is set, then ^ does not match at the beginning of the string; if REG_NOTEOL is set, then $ does not match at the end. We return 0 if we find a match and REG_NOMATCH if not. */ int Rregexec (const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) { int ret; struct re_registers regs; regex_t private_preg; int len = strlen (string); boolean want_reg_info = !preg->no_sub && nmatch > 0; private_preg = *preg; private_preg.not_bol = !!(eflags & REG_NOTBOL); private_preg.not_eol = !!(eflags & REG_NOTEOL); /* The user has told us exactly how many registers to return information about, via `nmatch'. We have to pass that on to the matching routines. */ private_preg.regs_allocated = REGS_FIXED; if (want_reg_info) { regs.num_regs = nmatch; regs.start = TALLOC (nmatch * 2, regoff_t); if (regs.start == NULL) return (int) REG_NOMATCH; regs.end = regs.start + nmatch; } /* Perform the searching operation. */ ret = re_search (&private_preg, string, len, /* start: */ 0, /* range: */ len, want_reg_info ? ®s : (struct re_registers *) 0); /* Copy the register information to the POSIX structure. */ if (want_reg_info) { if (ret >= 0) { unsigned r; for (r = 0; r < nmatch; r++) { pmatch[r].rm_so = regs.start[r]; pmatch[r].rm_eo = regs.end[r]; } } /* If we needed the temporary register info, free the space now. */ free (regs.start); } /* We want zero return to mean success, unlike `re_search'. */ return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; } #ifdef _LIBC weak_alias (__Rregexec, Rregexec) #endif /* Returns a message corresponding to an error code, ERRCODE, returned from either Rregcomp or Rregexec. We don't use PREG here. */ size_t Rregerror ( int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) { const char *msg; size_t msg_size; if (errcode < 0 || errcode >= (int) (sizeof (re_error_msgid_idx) / sizeof (re_error_msgid_idx[0]))) /* Only error codes returned by the rest of the code should be passed to this routine. If we are given anything else, or if other regex code generates an invalid error code, then the program has a bug. Dump core so we can fix it. */ abort (); msg = gettext (re_error_msgid + re_error_msgid_idx[errcode]); msg_size = strlen (msg) + 1; /* Includes the null. */ if (errbuf_size != 0) { if (msg_size > errbuf_size) { #if defined HAVE_MEMPCPY || defined _LIBC *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0'; #else memcpy (errbuf, msg, errbuf_size - 1); errbuf[errbuf_size - 1] = 0; #endif } else memcpy (errbuf, msg, msg_size); } return msg_size; } #ifdef _LIBC weak_alias (__Rregerror, Rregerror) #endif /* Free dynamically allocated space used by PREG. */ void Rregfree (regex_t *preg) { if (preg->buffer != NULL) free (preg->buffer); preg->buffer = NULL; preg->allocated = 0; preg->used = 0; if (preg->fastmap != NULL) free (preg->fastmap); preg->fastmap = NULL; preg->fastmap_accurate = 0; if (preg->translate != NULL) free (preg->translate); preg->translate = NULL; } #ifdef _LIBC weak_alias (__Rregfree, Rregfree) #endif #endif /* not emacs */ argus-clients-2.0.6.fixes.1/ragrep/regex.h0000664000076600007660000000330207725257001014020 #ifndef _REGEX_H #include /* Document internal interfaces. */ extern reg_syntax_t __re_set_syntax _RE_ARGS ((reg_syntax_t syntax)); extern const char *__re_compile_pattern _RE_ARGS ((const char *pattern, size_t length, struct re_pattern_buffer *buffer)); extern int __re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer)); extern int __re_search _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, int length, int start, int range, struct re_registers *regs)); extern int __re_search_2 _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, int length1, const char *string2, int length2, int start, int range, struct re_registers *regs, int stop)); extern int __re_match _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, int length, int start, struct re_registers *regs)); extern int __re_match_2 _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, int length1, const char *string2, int length2, int start, struct re_registers *regs, int stop)); extern void __re_set_registers _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, unsigned num_regs, regoff_t *starts, regoff_t *ends)); extern int __Rregcomp _RE_ARGS ((regex_t *__preg, const char *__pattern, int __cflags)); extern int __Rregexec _RE_ARGS ((const regex_t *__preg, const char *__string, size_t __nmatch, regmatch_t __pmatch[], int __eflags)); extern size_t __Rregerror _RE_ARGS ((int __errcode, const regex_t *__preg, char *__errbuf, size_t __errbuf_size)); extern void __Rregfree _RE_ARGS ((regex_t *__preg)); #endif argus-clients-2.0.6.fixes.1/ragrep/savedir.h0000664000076600007660000000041607310146216014341 #if !defined SAVEDIR_H_ # define SAVEDIR_H_ # ifndef PARAMS # if defined PROTOTYPES || (defined __STDC__ && __STDC__) # define PARAMS(Args) Args # else # define PARAMS(Args) () # endif # endif char * savedir PARAMS ((const char *dir, off_t name_size)); #endif argus-clients-2.0.6.fixes.1/ragrep/search.c0000664000076600007660000002513607310427101014145 /* search.c - searching subroutines using dfa, kwset and regex for grep. Copyright 1992, 1998, 2000 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Written August 1992 by Mike Haertel. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "system.h" #include "ragrep.h" #include "regex.h" #include "dfa.h" #include "kwset.h" #define NCHAR (UCHAR_MAX + 1) static void Gcompile PARAMS((char *, size_t)); static void Ecompile PARAMS((char *, size_t)); static char *EGexecute PARAMS((char *, size_t, char **)); static void Fcompile PARAMS((char *, size_t)); static char *Fexecute PARAMS((char *, size_t, char **)); static void kwsinit PARAMS((void)); /* Here is the matchers vector for the main program. */ struct matcher matchers[] = { { "default", Gcompile, EGexecute }, { "grep", Gcompile, EGexecute }, { "egrep", Ecompile, EGexecute }, { "awk", Ecompile, EGexecute }, { "fgrep", Fcompile, Fexecute }, { 0, 0, 0 }, }; /* For -w, we also consider _ to be word constituent. */ #define WCHAR(C) (ISALNUM(C) || (C) == '_') /* DFA compiled regexp. */ static struct dfa dfa; /* Regex compiled regexp. */ static struct re_pattern_buffer regexbuf; /* KWset compiled pattern. For Ecompile and Gcompile, we compile a list of strings, at least one of which is known to occur in any string matching the regexp. */ static kwset_t kwset; /* Last compiled fixed string known to exactly match the regexp. If kwsexec() returns < lastexact, then we don't need to call the regexp matcher at all. */ static int lastexact; void dfaerror (char const *mesg) { fatal(mesg, 0); } static void kwsinit (void) { static char trans[NCHAR]; int i; if (match_icase) for (i = 0; i < NCHAR; ++i) trans[i] = TOLOWER(i); if (!(kwset = kwsalloc(match_icase ? trans : (char *) 0))) fatal("memory exhausted", 0); } /* If the DFA turns out to have some set of fixed strings one of which must occur in the match, then we build a kwset matcher to find those strings, and thus quickly filter out impossible matches. */ static void kwsmusts (void) { struct dfamust *dm; char *err; if (dfa.musts) { kwsinit(); /* First, we compile in the substrings known to be exact matches. The kwset matcher will return the index of the matching string that it chooses. */ for (dm = dfa.musts; dm; dm = dm->next) { if (!dm->exact) continue; ++lastexact; if ((err = kwsincr(kwset, dm->must, strlen(dm->must))) != 0) fatal(err, 0); } /* Now, we compile the substrings that will require the use of the regexp matcher. */ for (dm = dfa.musts; dm; dm = dm->next) { if (dm->exact) continue; if ((err = kwsincr(kwset, dm->must, strlen(dm->must))) != 0) fatal(err, 0); } if ((err = kwsprep(kwset)) != 0) fatal(err, 0); } } static void Gcompile (char *pattern, size_t size) { const char *err; re_set_syntax(RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE); dfasyntax(RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE, match_icase, eolbyte); if ((err = re_compile_pattern(pattern, size, ®exbuf)) != 0) fatal(err, 0); /* In the match_words and match_lines cases, we use a different pattern for the DFA matcher that will quickly throw out cases that won't work. Then if DFA succeeds we do some hairy stuff using the regex matcher to decide whether the match should really count. */ if (match_words || match_lines) { /* In the whole-word case, we use the pattern: (^|[^A-Za-z_])(userpattern)([^A-Za-z_]|$). In the whole-line case, we use the pattern: ^(userpattern)$. BUG: Using [A-Za-z_] is locale-dependent! So will use [:alnum:] */ char *n = xmalloc(size + 50); int i = 0; strcpy(n, ""); if (match_lines) strcpy(n, "^\\("); if (match_words) strcpy(n, "\\(^\\|[^[:alnum:]_]\\)\\("); i = strlen(n); memcpy(n + i, pattern, size); i += size; if (match_words) strcpy(n + i, "\\)\\([^[:alnum:]_]\\|$\\)"); if (match_lines) strcpy(n + i, "\\)$"); i += strlen(n + i); dfacomp(n, i, &dfa, 1); } else dfacomp(pattern, size, &dfa, 1); kwsmusts(); } static void Ecompile (char *pattern, size_t size) { const char *err; if (strcmp(matcher, "awk") == 0) { re_set_syntax(RE_SYNTAX_AWK); dfasyntax(RE_SYNTAX_AWK, match_icase, eolbyte); } else { re_set_syntax (RE_SYNTAX_POSIX_EGREP); dfasyntax (RE_SYNTAX_POSIX_EGREP, match_icase, eolbyte); } if ((err = re_compile_pattern(pattern, size, ®exbuf)) != 0) fatal(err, 0); /* In the match_words and match_lines cases, we use a different pattern for the DFA matcher that will quickly throw out cases that won't work. Then if DFA succeeds we do some hairy stuff using the regex matcher to decide whether the match should really count. */ if (match_words || match_lines) { /* In the whole-word case, we use the pattern: (^|[^A-Za-z_])(userpattern)([^A-Za-z_]|$). In the whole-line case, we use the pattern: ^(userpattern)$. BUG: Using [A-Za-z_] is locale-dependent! so will use the char class */ char *n = xmalloc(size + 50); int i = 0; strcpy(n, ""); if (match_lines) strcpy(n, "^("); if (match_words) strcpy(n, "(^|[^[:alnum:]_])("); i = strlen(n); memcpy(n + i, pattern, size); i += size; if (match_words) strcpy(n + i, ")([^[:alnum:]_]|$)"); if (match_lines) strcpy(n + i, ")$"); i += strlen(n + i); dfacomp(n, i, &dfa, 1); } else dfacomp(pattern, size, &dfa, 1); kwsmusts(); } static char * EGexecute (char *buf, size_t size, char **endp) { register char *buflim, *beg, *end, save; char eol = eolbyte; int backref, start, len; struct kwsmatch kwsm; static struct re_registers regs; /* This is static on account of a BRAIN-DEAD Q@#%!# library interface in regex.c. */ buflim = buf + size; for (beg = end = buf; end < buflim; beg = end + 1) { if (kwset) { /* Find a possible match using the KWset matcher. */ beg = kwsexec(kwset, beg, buflim - beg, &kwsm); if (!beg) goto failure; /* Narrow down to the line containing the candidate, and run it through DFA. */ end = memchr(beg, eol, buflim - beg); if (!end) end = buflim; while (beg > buf && beg[-1] != eol) --beg; save = *end; if (kwsm.index < lastexact) goto success; if (!dfaexec(&dfa, beg, end, 0, (int *) 0, &backref)) { *end = save; continue; } *end = save; /* Successful, no backreferences encountered. */ if (!backref) goto success; } else { /* No good fixed strings; start with DFA. */ save = *buflim; beg = dfaexec(&dfa, beg, buflim, 0, (int *) 0, &backref); *buflim = save; if (!beg) goto failure; /* Narrow down to the line we've found. */ end = memchr(beg, eol, buflim - beg); if (!end) end = buflim; while (beg > buf && beg[-1] != eol) --beg; /* Successful, no backreferences encountered! */ if (!backref) goto success; } /* If we've made it to this point, this means DFA has seen a probable match, and we need to run it through Regex. */ regexbuf.not_eol = 0; if ((start = re_search(®exbuf, beg, end - beg, 0, end - beg, ®s)) >= 0) { len = regs.end[0] - start; if ((!match_lines && !match_words) || (match_lines && len == end - beg)) goto success; /* If -w, check if the match aligns with word boundaries. We do this iteratively because: (a) the line may contain more than one occurence of the pattern, and (b) Several alternatives in the pattern might be valid at a given point, and we may need to consider a shorter one to find a word boundary. */ if (match_words) while (start >= 0) { if ((start == 0 || !WCHAR ((unsigned char) beg[start - 1])) && (len == end - beg || !WCHAR ((unsigned char) beg[start + len]))) goto success; if (len > 0) { /* Try a shorter length anchored at the same place. */ --len; regexbuf.not_eol = 1; len = re_match(®exbuf, beg, start + len, start, ®s); } if (len <= 0) { /* Try looking further on. */ if (start == end - beg) break; ++start; regexbuf.not_eol = 0; start = re_search(®exbuf, beg, end - beg, start, end - beg - start, ®s); len = regs.end[0] - start; } } } } failure: return 0; success: *endp = end < buflim ? end + 1 : end; return beg; } static void Fcompile (char *pattern, size_t size) { char *beg, *lim, *err; kwsinit(); beg = pattern; do { for (lim = beg; lim < pattern + size && *lim != '\n'; ++lim) ; if ((err = kwsincr(kwset, beg, lim - beg)) != 0) fatal(err, 0); if (lim < pattern + size) ++lim; beg = lim; } while (beg < pattern + size); if ((err = kwsprep(kwset)) != 0) fatal(err, 0); } static char * Fexecute (char *buf, size_t size, char **endp) { register char *beg, *try, *end; register size_t len; char eol = eolbyte; struct kwsmatch kwsmatch; for (beg = buf; beg <= buf + size; ++beg) { if (!(beg = kwsexec(kwset, beg, buf + size - beg, &kwsmatch))) return 0; len = kwsmatch.size[0]; if (match_lines) { if (beg > buf && beg[-1] != eol) continue; if (beg + len < buf + size && beg[len] != eol) continue; goto success; } else if (match_words) for (try = beg; len && try;) { if (try > buf && WCHAR((unsigned char) try[-1])) break; if (try + len < buf + size && WCHAR((unsigned char) try[len])) { try = kwsexec(kwset, beg, --len, &kwsmatch); len = kwsmatch.size[0]; } else goto success; } else goto success; } return 0; success: if ((end = memchr(beg + len, eol, (buf + size) - (beg + len))) != 0) ++end; else end = buf + size; *endp = end; while (beg > buf && beg[-1] != '\n') --beg; return beg; } argus-clients-2.0.6.fixes.1/ragrep/system.h0000664000076600007660000001201107551062142014224 /* Portability cruft. Include after config.h and sys/types.h. Copyright 1996, 1998, 1999, 2000 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #undef PARAMS #if defined (__STDC__) && __STDC__ # ifndef _PTR_T # define _PTR_T typedef void * ptr_t; # endif # define PARAMS(x) x #else # ifndef _PTR_T # define _PTR_T typedef char * ptr_t; # endif # define PARAMS(x) () #endif #ifdef HAVE_UNISTD_H # include # include #else # define O_RDONLY 0 # define SEEK_SET 0 # define SEEK_CUR 1 #endif #include #ifndef errno extern int errno; #endif /* #ifndef HAVE_STRERROR extern int sys_nerr; extern char *sys_errlist[]; # define strerror(E) (0 <= (E) && (E) < sys_nerr ? _(sys_errlist[E]) : _("Unknown system error")) #endif */ /* Some operating systems treat text and binary files differently. */ #if O_BINARY # include # ifdef HAVE_SETMODE # define SET_BINARY(fd) setmode (fd, O_BINARY) # else # define SET_BINARY(fd) _setmode (fd, O_BINARY) # endif #else # ifndef O_BINARY # define O_BINARY 0 # define SET_BINARY(fd) (void)0 # endif #endif #ifdef HAVE_DOS_FILE_NAMES # define IS_SLASH(c) ((c) == '/' || (c) == '\\') # define FILESYSTEM_PREFIX_LEN(f) ((f)[0] && (f)[1] == ':' ? 2 : 0) #endif #ifndef IS_SLASH # define IS_SLASH(c) ((c) == '/') #endif #ifndef FILESYSTEM_PREFIX_LEN # define FILESYSTEM_PREFIX_LEN(f) 0 #endif /* This assumes _WIN32, like DJGPP, has D_OK. Does it? In what header? */ #ifdef D_OK # ifdef EISDIR # define is_EISDIR(e, f) \ ((e) == EISDIR \ || ((e) == EACCES && access (f, D_OK) == 0 && ((e) = EISDIR, 1))) # else # define is_EISDIR(e, f) ((e) == EACCES && access (f, D_OK) == 0) # endif #endif #ifndef is_EISDIR # ifdef EISDIR # define is_EISDIR(e, f) ((e) == EISDIR) # else # define is_EISDIR(e, f) 0 # endif #endif #if STAT_MACROS_BROKEN # undef S_ISDIR # undef S_ISREG #endif #if !defined(S_ISDIR) && defined(S_IFDIR) # define S_ISDIR(Mode) (((Mode) & S_IFMT) == S_IFDIR) #endif #if !defined(S_ISREG) && defined(S_IFREG) # define S_ISREG(Mode) (((Mode) & S_IFMT) == S_IFREG) #endif #ifdef STDC_HEADERS # include #else char *getenv (); ptr_t malloc(), realloc(), calloc(); void free(); #endif #if __STDC__ # include #endif #ifdef STDC_HEADERS # include #endif #ifndef CHAR_BIT # define CHAR_BIT 8 #endif /* The extra casts work around common compiler bugs. */ #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) #define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \ : (t) 0)) #define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t))) #ifndef CHAR_MAX # define CHAR_MAX TYPE_MAXIMUM (char) #endif #ifndef INT_MAX # define INT_MAX TYPE_MAXIMUM (int) #endif #ifndef UCHAR_MAX # define UCHAR_MAX TYPE_MAXIMUM (unsigned char) #endif #if !defined(STDC_HEADERS) && defined(HAVE_STRING_H) && defined(HAVE_MEMORY_H) # include #endif #if defined(STDC_HEADERS) || defined(HAVE_STRING_H) # include #else # include # undef strchr # define strchr index # undef strrchr # define strrchr rindex # undef memcpy # define memcpy(d, s, n) bcopy (s, d, n) #endif #if ! defined HAVE_MEMMOVE && ! defined memmove # define memmove(d, s, n) bcopy (s, d, n) #endif #include #ifndef isgraph # define isgraph(C) (isprint(C) && !isspace(C)) #endif #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) # define IN_CTYPE_DOMAIN(c) 1 #else # define IN_CTYPE_DOMAIN(c) isascii(c) #endif #define ISALPHA(C) (IN_CTYPE_DOMAIN (C) && isalpha (C)) #define ISUPPER(C) (IN_CTYPE_DOMAIN (C) && isupper (C)) #define ISLOWER(C) (IN_CTYPE_DOMAIN (C) && islower (C)) #define ISDIGIT(C) (IN_CTYPE_DOMAIN (C) && isdigit (C)) #define ISXDIGIT(C) (IN_CTYPE_DOMAIN (C) && isxdigit (C)) #define ISSPACE(C) (IN_CTYPE_DOMAIN (C) && isspace (C)) #define ISPUNCT(C) (IN_CTYPE_DOMAIN (C) && ispunct (C)) #define ISALNUM(C) (IN_CTYPE_DOMAIN (C) && isalnum (C)) #define ISPRINT(C) (IN_CTYPE_DOMAIN (C) && isprint (C)) #define ISGRAPH(C) (IN_CTYPE_DOMAIN (C) && isgraph (C)) #define ISCNTRL(C) (IN_CTYPE_DOMAIN (C) && iscntrl (C)) #define TOLOWER(C) (ISUPPER(C) ? tolower(C) : (C)) #if ENABLE_NLS # include # define _(String) gettext (String) #else # define _(String) String #endif #define N_(String) String #if HAVE_SETLOCALE # include #endif #ifndef initialize_main #define initialize_main(argcp, argvp) #endif argus-clients-2.0.6.fixes.1/ragrep/posix/0000775000076600007660000000000007764241724013771 5argus-clients-2.0.6.fixes.1/ragrep/posix/regex.h0000664000076600007660000005030707725257001015171 /* Definitions for data structures and routines for the regular expression library, version 0.12. Copyright (C) 1985,89,90,91,92,93,95,96,97,98 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _REGEX_H #define _REGEX_H 1 /* Allow the use in C++ code. */ #ifdef __cplusplus extern "C" { #endif /* POSIX says that must be included (by the caller) before . */ #if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS /* VMS doesn't have `size_t' in , even though POSIX says it should be there. */ # include #endif /* The following two types have to be signed and unsigned integer type wide enough to hold a value of a pointer. For most ANSI compilers ptrdiff_t and size_t should be likely OK. Still size of these two types is 2 for Microsoft C. Ugh... */ typedef long int s_reg_t; typedef unsigned long int active_reg_t; /* The following bits are used to determine the regexp syntax we recognize. The set/not-set meanings are chosen so that Emacs syntax remains the value 0. The bits are given in alphabetical order, and the definitions shifted by one from the previous bit; thus, when we add or remove a bit, only one other definition need change. */ typedef unsigned long int reg_syntax_t; /* If this bit is not set, then \ inside a bracket expression is literal. If set, then such a \ quotes the following character. */ #define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) /* If this bit is not set, then + and ? are operators, and \+ and \? are literals. If set, then \+ and \? are operators and + and ? are literals. */ #define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) /* If this bit is set, then character classes are supported. They are: [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. If not set, then character classes are not supported. */ #define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) /* If this bit is set, then ^ and $ are always anchors (outside bracket expressions, of course). If this bit is not set, then it depends: ^ is an anchor if it is at the beginning of a regular expression or after an open-group or an alternation operator; $ is an anchor if it is at the end of a regular expression, or before a close-group or an alternation operator. This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because POSIX draft 11.2 says that * etc. in leading positions is undefined. We already implemented a previous draft which made those constructs invalid, though, so we haven't changed the code back. */ #define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) /* If this bit is set, then special characters are always special regardless of where they are in the pattern. If this bit is not set, then special characters are special only in some contexts; otherwise they are ordinary. Specifically, * + ? and intervals are only special when not after the beginning, open-group, or alternation operator. */ #define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) /* If this bit is set, then *, +, ?, and { cannot be first in an re or immediately after an alternation or begin-group operator. */ #define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) /* If this bit is set, then . matches newline. If not set, then it doesn't. */ #define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) /* If this bit is set, then . doesn't match NUL. If not set, then it does. */ #define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) /* If this bit is set, nonmatching lists [^...] do not match newline. If not set, they do. */ #define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) /* If this bit is set, either \{...\} or {...} defines an interval, depending on RE_NO_BK_BRACES. If not set, \{, \}, {, and } are literals. */ #define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) /* If this bit is set, +, ? and | aren't recognized as operators. If not set, they are. */ #define RE_LIMITED_OPS (RE_INTERVALS << 1) /* If this bit is set, newline is an alternation operator. If not set, newline is literal. */ #define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) /* If this bit is set, then `{...}' defines an interval, and \{ and \} are literals. If not set, then `\{...\}' defines an interval. */ #define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) /* If this bit is set, (...) defines a group, and \( and \) are literals. If not set, \(...\) defines a group, and ( and ) are literals. */ #define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) /* If this bit is set, then \ matches . If not set, then \ is a back-reference. */ #define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) /* If this bit is set, then | is an alternation operator, and \| is literal. If not set, then \| is an alternation operator, and | is literal. */ #define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) /* If this bit is set, then an ending range point collating higher than the starting range point, as in [z-a], is invalid. If not set, then when ending range point collates higher than the starting range point, the range is ignored. */ #define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) /* If this bit is set, then an unmatched ) is ordinary. If not set, then an unmatched ) is invalid. */ #define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) /* If this bit is set, succeed as soon as we match the whole pattern, without further backtracking. */ #define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) /* If this bit is set, do not process the GNU regex operators. If not set, then the GNU regex operators are recognized. */ #define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) /* If this bit is set, turn on internal regex debugging. If not set, and debugging was on, turn it off. This only works if regex.c is compiled -DDEBUG. We define this bit always, so that all that's needed to turn on debugging is to recompile regex.c; the calling code can always have this bit set, and it won't affect anything in the normal case. */ #define RE_DEBUG (RE_NO_GNU_OPS << 1) /* This global variable defines the particular regexp syntax to use (for some interfaces). When a regexp is compiled, the syntax used is stored in the pattern buffer, so changing this does not affect already-compiled regexps. */ extern reg_syntax_t re_syntax_options; /* Define combinations of the above bits for the standard possibilities. (The [[[ comments delimit what gets put into the Texinfo file, so don't delete them!) */ /* [[[begin syntaxes]]] */ #define RE_SYNTAX_EMACS 0 #define RE_SYNTAX_AWK \ (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ | RE_NO_BK_PARENS | RE_NO_BK_REFS \ | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) #define RE_SYNTAX_GNU_AWK \ ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS)) #define RE_SYNTAX_POSIX_AWK \ (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ | RE_INTERVALS | RE_NO_GNU_OPS) #define RE_SYNTAX_GREP \ (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ | RE_NEWLINE_ALT) #define RE_SYNTAX_EGREP \ (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ | RE_NO_BK_VBAR) #define RE_SYNTAX_POSIX_EGREP \ (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES) /* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ #define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC #define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC /* Syntax bits common to both basic and extended POSIX regex syntax. */ #define _RE_SYNTAX_POSIX_COMMON \ (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ | RE_INTERVALS | RE_NO_EMPTY_RANGES) #define RE_SYNTAX_POSIX_BASIC \ (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM) /* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this isn't minimal, since other operators, such as \`, aren't disabled. */ #define RE_SYNTAX_POSIX_MINIMAL_BASIC \ (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) #define RE_SYNTAX_POSIX_EXTENDED \ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ | RE_UNMATCHED_RIGHT_PAREN_ORD) /* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added. */ #define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ | RE_NO_BK_PARENS | RE_NO_BK_REFS \ | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) /* [[[end syntaxes]]] */ /* Maximum number of duplicates an interval can allow. Some systems (erroneously) define this in other header files, but we want our value, so remove any previous define. */ #ifdef RE_DUP_MAX # undef RE_DUP_MAX #endif /* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */ #define RE_DUP_MAX (0x7fff) /* POSIX `cflags' bits (i.e., information for `regcomp'). */ /* If this bit is set, then use extended regular expression syntax. If not set, then use basic regular expression syntax. */ #define REG_EXTENDED 1 /* If this bit is set, then ignore case when matching. If not set, then case is significant. */ #define REG_ICASE (REG_EXTENDED << 1) /* If this bit is set, then anchors do not match at newline characters in the string. If not set, then anchors do match at newlines. */ #define REG_NEWLINE (REG_ICASE << 1) /* If this bit is set, then report only success or fail in regexec. If not set, then returns differ between not matching and errors. */ #define REG_NOSUB (REG_NEWLINE << 1) /* POSIX `eflags' bits (i.e., information for regexec). */ /* If this bit is set, then the beginning-of-line operator doesn't match the beginning of the string (presumably because it's not the beginning of a line). If not set, then the beginning-of-line operator does match the beginning of the string. */ #define REG_NOTBOL 1 /* Like REG_NOTBOL, except for the end-of-line. */ #define REG_NOTEOL (1 << 1) /* If any error codes are removed, changed, or added, update the `re_error_msg' table in regex.c. */ typedef enum { #ifdef _XOPEN_SOURCE REG_ENOSYS = -1, /* This will never happen for this implementation. */ #endif REG_NOERROR = 0, /* Success. */ REG_NOMATCH, /* Didn't find a match (for regexec). */ /* POSIX regcomp return error codes. (In the order listed in the standard.) */ REG_BADPAT, /* Invalid pattern. */ REG_ECOLLATE, /* Not implemented. */ REG_ECTYPE, /* Invalid character class name. */ REG_EESCAPE, /* Trailing backslash. */ REG_ESUBREG, /* Invalid back reference. */ REG_EBRACK, /* Unmatched left bracket. */ REG_EPAREN, /* Parenthesis imbalance. */ REG_EBRACE, /* Unmatched \{. */ REG_BADBR, /* Invalid contents of \{\}. */ REG_ERANGE, /* Invalid range end. */ REG_ESPACE, /* Ran out of memory. */ REG_BADRPT, /* No preceding re for repetition op. */ /* Error codes we've added. */ REG_EEND, /* Premature end. */ REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ } reg_errcode_t; /* This data structure represents a compiled pattern. Before calling the pattern compiler, the fields `buffer', `allocated', `fastmap', `translate', and `no_sub' can be set. After the pattern has been compiled, the `re_nsub' field is available. All other fields are private to the regex routines. */ #ifndef RE_TRANSLATE_TYPE # define RE_TRANSLATE_TYPE char * #endif struct re_pattern_buffer { /* [[[begin pattern_buffer]]] */ /* Space that holds the compiled pattern. It is declared as `unsigned char *' because its elements are sometimes used as array indexes. */ unsigned char *buffer; /* Number of bytes to which `buffer' points. */ unsigned long int allocated; /* Number of bytes actually used in `buffer'. */ unsigned long int used; /* Syntax setting with which the pattern was compiled. */ reg_syntax_t syntax; /* Pointer to a fastmap, if any, otherwise zero. re_search uses the fastmap, if there is one, to skip over impossible starting points for matches. */ char *fastmap; /* Either a translate table to apply to all characters before comparing them, or zero for no translation. The translation is applied to a pattern when it is compiled and to a string when it is matched. */ RE_TRANSLATE_TYPE translate; /* Number of subexpressions found by the compiler. */ size_t re_nsub; /* Zero if this pattern cannot match the empty string, one else. Well, in truth it's used only in `re_search_2', to see whether or not we should use the fastmap, so we don't set this absolutely perfectly; see `re_compile_fastmap' (the `duplicate' case). */ unsigned can_be_null : 1; /* If REGS_UNALLOCATED, allocate space in the `regs' structure for `max (RE_NREGS, re_nsub + 1)' groups. If REGS_REALLOCATE, reallocate space if necessary. If REGS_FIXED, use what's there. */ #define REGS_UNALLOCATED 0 #define REGS_REALLOCATE 1 #define REGS_FIXED 2 unsigned regs_allocated : 2; /* Set to zero when `regex_compile' compiles a pattern; set to one by `re_compile_fastmap' if it updates the fastmap. */ unsigned fastmap_accurate : 1; /* If set, `re_match_2' does not return information about subexpressions. */ unsigned no_sub : 1; /* If set, a beginning-of-line anchor doesn't match at the beginning of the string. */ unsigned not_bol : 1; /* Similarly for an end-of-line anchor. */ unsigned not_eol : 1; /* If true, an anchor at a newline matches. */ unsigned newline_anchor : 1; /* [[[end pattern_buffer]]] */ }; typedef struct re_pattern_buffer regex_t; /* Type for byte offsets within the string. POSIX mandates this. */ typedef int regoff_t; /* This is the structure we store register match data in. See regex.texinfo for a full description of what registers match. */ struct re_registers { unsigned num_regs; regoff_t *start; regoff_t *end; }; /* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, `re_match_2' returns information about at least this many registers the first time a `regs' structure is passed. */ #ifndef RE_NREGS # define RE_NREGS 30 #endif /* POSIX specification for registers. Aside from the different names than `re_registers', POSIX uses an array of structures, instead of a structure of arrays. */ typedef struct { regoff_t rm_so; /* Byte offset from string's start to substring's start. */ regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ } regmatch_t; /* Declarations for routines. */ /* To avoid duplicating every routine declaration -- once with a prototype (if we are ANSI), and once without (if we aren't) -- we use the following macro to declare argument types. This unfortunately clutters up the declarations a bit, but I think it's worth it. */ #if __STDC__ # define _RE_ARGS(args) args #else /* not __STDC__ */ # define _RE_ARGS(args) () #endif /* not __STDC__ */ /* Sets the current default syntax to SYNTAX, and return the old syntax. You can also simply assign to the `re_syntax_options' variable. */ extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax)); /* Compile the regular expression PATTERN, with length LENGTH and syntax given by the global `re_syntax_options', into the buffer BUFFER. Return NULL if successful, and an error string if not. */ extern const char *re_compile_pattern _RE_ARGS ((const char *pattern, size_t length, struct re_pattern_buffer *buffer)); /* Compile a fastmap for the compiled pattern in BUFFER; used to accelerate searches. Return 0 if successful and -2 if was an internal error. */ extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer)); /* Search in the string STRING (with length LENGTH) for the pattern compiled into BUFFER. Start searching at position START, for RANGE characters. Return the starting position of the match, -1 for no match, or -2 for an internal error. Also return register information in REGS (if REGS and BUFFER->no_sub are nonzero). */ extern int re_search _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, int length, int start, int range, struct re_registers *regs)); /* Like `re_search', but search in the concatenation of STRING1 and STRING2. Also, stop searching at index START + STOP. */ extern int re_search_2 _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, int length1, const char *string2, int length2, int start, int range, struct re_registers *regs, int stop)); /* Like `re_search', but return how many characters in STRING the regexp in BUFFER matched, starting at position START. */ extern int re_match _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, int length, int start, struct re_registers *regs)); /* Relates to `re_match' as `re_search_2' relates to `re_search'. */ extern int re_match_2 _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, int length1, const char *string2, int length2, int start, struct re_registers *regs, int stop)); /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using BUFFER and REGS will use this memory for recording register information. STARTS and ENDS must be allocated with malloc, and must each be at least `NUM_REGS * sizeof (regoff_t)' bytes long. If NUM_REGS == 0, then subsequent matches should allocate their own register data. Unless this function is called, the first search or match using PATTERN_BUFFER will allocate its own register data, without freeing the old data. */ extern void re_set_registers _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, unsigned num_regs, regoff_t *starts, regoff_t *ends)); #if defined _REGEX_RE_COMP || defined _LIBC # ifndef _CRAY /* 4.2 bsd compatibility. */ extern char *re_comp _RE_ARGS ((const char *)); extern int re_exec _RE_ARGS ((const char *)); # endif #endif /* POSIX compatibility. */ extern int Rregcomp _RE_ARGS ((regex_t *__preg, const char *__pattern, int __cflags)); extern int Rregexec _RE_ARGS ((const regex_t *__preg, const char *__string, size_t __nmatch, regmatch_t __pmatch[], int __eflags)); extern size_t Rregerror _RE_ARGS ((int __errcode, const regex_t *__preg, char *__errbuf, size_t __errbuf_size)); extern void Rregfree _RE_ARGS ((regex_t *__preg)); #ifdef __cplusplus } #endif /* C++ */ #endif /* regex.h */ /* Local variables: make-backup-files: t version-control: t trim-versions-without-asking: nil End: */ argus-clients-2.0.6.fixes.1/ragraph/0000775000076600007660000000000010047734056012764 5argus-clients-2.0.6.fixes.1/ragraph/Makefile.in0000664000076600007660000000726107703321100014742 # # Argus Client Software. Tools to read, analyze and manage Argus data. # Copyright (c) 2000-2003 QoSient, LLC # All rights reserved. # # 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 # # # Various configurable paths (remember to edit Makefile.in, not Makefile) # # Top level hierarchy prefix = $(DESTDIR)@prefix@ exec_prefix = @exec_prefix@ # Pathname of directory to install the system binaries SBINDIR = @sbindir@ # Pathname of directory to install the system binaries BINDIR = @bindir@ # Pathname of directory to install the include files INCLDEST = @includedir@ # Pathname of directory to install the library LIBDEST = @libdir@ # Pathname of directory to install the man page MANDEST = @mandir@ # VPATH srcdir = @srcdir@ VPATH = @srcdir@ # # You shouldn't need to edit anything below. # CC = @CC@ CCOPT = @V_CCOPT@ INCLS = -I. -I../include -I../common @V_INCLS@ DEFS = @DEFS@ COMPATLIB = @COMPATLIB@ @LIB_SASL@ # Standard CFLAGS CFLAGS = $(CCOPT) $(INCLS) $(DEFS) INSTALL = @INSTALL@ RANLIB = @V_RANLIB@ # # Flex and bison allow you to specify the prefixes of the global symbols # used by the generated parser. This allows programs to use lex/yacc # and link against libpcap. If you don't have flex or bison, get them. # LEX = @V_LEX@ YACC = @V_YACC@ # Explicitly define compilation rule since SunOS 4's make doesn't like gcc. # Also, gcc does not remove the .o before forking 'as', which can be a # problem if you don't own the file but can write to the directory. .c.o: @rm -f $@ $(CC) $(CFLAGS) -c $(srcdir)/$*.c LIB = @INSTALL_LIB@/argus_parse.a @INSTALL_LIB@/argus_common.a @INSTALL_LIB@/argus_client.a SRC = rahistogram.c PROGS = @INSTALL_BIN@/rahistogram @INSTALL_BIN@/ragraph all: $(PROGS) @INSTALL_BIN@/rahistogram: rahistogram.o $(LIB) $(CC) $(CCOPT) -o $@ rahistogram.o $(LIB) $(COMPATLIB) -lm @INSTALL_BIN@/ragraph: ragraph.pl $(INSTALL) ragraph.pl $@ # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot # hack the extra indirection OBJ = $(SRC:.c=.o) CLEANFILES = $(OBJ) $(PROGS) install: force all [ -d $(DESTDIR) ] || \ (mkdir -p $(DESTDIR); chmod 755 $(DESTDIR)) [ -d $(BINDIR) ] || \ (mkdir -p $(BINDIR); chmod 755 $(BINDIR)) $(INSTALL) @INSTALL_BIN@/rahistogram $(BINDIR) $(INSTALL) @INSTALL_BIN@/ragraph $(BINDIR) clean: rm -f $(CLEANFILES) distclean: rm -f $(CLEANFILES) Makefile config.cache config.log config.status \ gnuc.h os-proto.h bpf_filter.c net tags: $(TAGFILES) ctags -wtd $(TAGFILES) tar: force @cwd=`pwd` ; dir=`basename $$cwd` ; name=libpcap-`cat VERSION` ; \ list="" ; tar="tar chFFf" ; \ for i in `cat FILES` ; do list="$$list $$name/$$i" ; done; \ echo \ "rm -f ../$$name; ln -s $$dir ../$$name" ; \ rm -f ../$$name; ln -s $$dir ../$$name ; \ echo \ "(cd .. ; $$tar - [lots of files]) | compress > /tmp/$$name.tar.Z" ; \ (cd .. ; $$tar - $$list) | compress > /tmp/$$name.tar.Z ; \ echo \ "rm -f ../$$name" ; \ rm -f ../$$name force: /tmp depend: $(GENSRC) force ../bin/mkdep -c $(CC) $(DEFS) $(INCLS) $(SRC) argus-clients-2.0.6.fixes.1/ragraph/ragraph.pl0000775000076600007660000005640307764133225014703 #! /usr/bin/perl # # Argus Client Software. Tools to read, analyze and manage Argus data. # Copyright (c) 2000-2003 QoSient, LLC # All rights reserved. # # 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 # # ragraph-histogram.pl # # use lib qw( /usr/local/rrdtool-1.0.40/lib/perl ../lib/perl ); use RRDs; use POSIX; use strict; my $tmpfile = tmpnam(); my $RRD = $tmpfile.".rrd"; my $GIF = "ragraph.gif"; my @arglist = (); my $title = ""; my $fill = 1; my $stack = 1; my $split = 1; my $log = 0; my $rigid = 0; my $upper = 0; my $lower = 0; my $height = 275; my $width = 800; my $xaxisstr; my $timeindex = -1; my $saddrindex = -1; my $daddrindex = -1; my $dportindex = -1; my $protoindex = -1; my $probeindex = -1; my $transindex = -1; my $avgdurindex = -1; my $ddurindex = -1; my $dstimeindex = -1; my $dltimeindex = -1; my $srcpktindex = -1; my $dstpktindex = -1; my $srcbyteindex = -1; my $dstbyteindex = -1; my $srclossindex = -1; my $dstlossindex = -1; my $srcjitterindex = -1; my $dstjitterindex = -1; my $srcdataindex = -1; my $dstdataindex = -1; my $minval = 'U'; my $maxval = 'U'; my @opts = (); my @columns = (); my @power = (); my @objects = (); my @objectlist = (); my $objectindex = -1; my $histo = 0; my $objects; my $num = 0; my ($START, $FRAC, $END, $STEP, $COLUMNS, $PROTOS, $PROBES, $RUNS, $ERROR); my @line_args; ARG: while (my $arg = shift(@ARGV)) { for ($arg) { s/^-log// && do { $log++; next ARG; }; s/^-fill// && do { $fill = 0; next ARG; }; s/^-stack// && do { $stack = 0; next ARG; }; s/^-split// && do { $split = 0; next ARG; }; s/^-rigid// && do { $rigid++; next ARG; }; s/^-height// && do { $height = shift (@ARGV); next ARG; }; s/^-width// && do { $width = shift (@ARGV); next ARG; }; s/^-upper// && do { $upper = shift (@ARGV); next ARG; }; s/^-lower// && do { $lower = shift (@ARGV); next ARG; }; s/^-title// && do { $title = shift (@ARGV); next ARG; }; s/^-w// && do { $GIF = shift (@ARGV); next ARG; }; s/^-N// && do { $num = shift (@ARGV); next ARG; }; /^-H/ && do { $histo++; }; s/\(/\\\(/ && do { ; }; s/\)/\\\)/ && do { ; }; } $arglist[@arglist + 0] = $arg; } RagraphProcessArgusData (); RagraphReadInitialValues ($tmpfile); RagraphGenerateRRDParameters ($tmpfile); RagraphGenerateRRD (); RagraphGenerateGIF (); RagraphCleanUp (); exit; sub RagraphCleanUp { `rm $tmpfile $RRD` } sub RagraphReadInitialValues { my $file = shift; my ($i, $k, $v); open(SESAME, $file); for (1 .. 7) { if (my $data = ) { if ( ($k, $v) = $data =~ m/(\w+)=(.*)/ ) { for ($k) { /StartTime/ and do {(($START, $FRAC) = $v =~ m/(\d*)\.(.*)/) ;}; /StopTime/ and do {(($END, $FRAC) = $v =~ m/(\d*)\.(.*)/) ;}; /BinSize/ and do {(($STEP, $FRAC) = $v =~ m/(\d*)\.(.*)/) ;}; /Columns/ and do { $COLUMNS = $v;}; /Bins/ and do {$RUNS = $v;}; /Protos/ and do {$PROTOS = $v;}; /Probes/ and do {$PROBES = $v;}; } } } } close(SESAME); } sub RagraphProcessArgusData { my @args = ""; if ($histo) { @args = ("rahistogram -p6 -G -s ", @arglist, "> $tmpfile"); } else { @args = ("rahistogram -p6 -G -s lasttime ", @arglist, "> $tmpfile"); } my $input = `@args`; } my @dataobjects = (); my @typeobjects = (); my $objwidth = 0; sub RagraphGenerateRRDParameters { my $file = shift; my $x; @columns = split(/,/, $COLUMNS); for ($x = 0; $x < (@columns + 0); $x++) { for ($columns[$x]) { /Time/ and do {$timeindex = $x; }; /Host/ and do {push @typeobjects, $x; $saddrindex = $x; $objwidth = 15; }; /SrcAddr/ and do {push @typeobjects, $x; $saddrindex = $x; $objwidth = 15; }; /InAddr/ and do {push @typeobjects, $x; $saddrindex = $x; $objwidth = 15; }; /OutAddr/ and do {push @typeobjects, $x; $daddrindex = $x; $objwidth = 15; }; /DstAddr/ and do {push @typeobjects, $x; $daddrindex = $x; $objwidth = 15; }; /Type/ and do {push @typeobjects, $x; $protoindex = $x; $objwidth = 6; }; /ProbeId/ and do {push @typeobjects, $x; $probeindex = $x; $objwidth = 15; }; /Dport/ and do {push @typeobjects, $x; $dportindex = $x; $objwidth = 12; }; /SrcPkt/ and do {push @dataobjects, $x; $srcpktindex = $x; }; /InPkt/ and do {push @dataobjects, $x; $srcpktindex = $x; }; /DstPkt/ and do {push @dataobjects, $x; $dstpktindex = $x; }; /OutPkt/ and do {push @dataobjects, $x; $dstpktindex = $x; }; /InAppBytes/ and do {push @dataobjects, $x; $srcbyteindex = $x; }; /SAppBytes/ and do {push @dataobjects, $x; $srcbyteindex = $x; }; /SrcBytes/ and do {push @dataobjects, $x; $srcbyteindex = $x; }; /InBytes/ and do {push @dataobjects, $x; $srcbyteindex = $x; }; /OutAppBytes/ and do {push @dataobjects, $x; $dstbyteindex = $x; }; /DAppBytes/ and do {push @dataobjects, $x; $dstbyteindex = $x; }; /DstBytes/ and do {push @dataobjects, $x; $dstbyteindex = $x; }; /OutBytes/ and do {push @dataobjects, $x; $dstbyteindex = $x; }; /pSrc_Loss/ and do {push @dataobjects, $x; $srclossindex = $x; }; /pDst_Loss/ and do {push @dataobjects, $x; $dstlossindex = $x; }; /Src_Loss/ and do {push @dataobjects, $x; $srclossindex = $x; }; /Dst_Loss/ and do {push @dataobjects, $x; $dstlossindex = $x; }; /SrcJitter/ and do {push @dataobjects, $x; $srcbyteindex = $x; }; /DstJitter/ and do {push @dataobjects, $x; $dstbyteindex = $x; }; /Trans/ and do {push @dataobjects, $x; $transindex = $x; }; /AvgDur/ and do {push @dataobjects, $x; $avgdurindex = $x; }; /dDur/ and do {push @dataobjects, $x; $ddurindex = $x; }; /dsTime/ and do {push @dataobjects, $x; $dstimeindex = $x; }; /dlTime/ and do {push @dataobjects, $x; $dltimeindex = $x; }; } } if (($srcpktindex >= 0) || ($srcpktindex >= 0)) { if ($srcpktindex >= 0) { $srcdataindex = $srcpktindex; } if ($dstpktindex >= 0) { $dstdataindex = $dstpktindex; } } else { if (($srcbyteindex >= 0) || ($srcbyteindex >= 0)) { if ($srcbyteindex >= 0) { $srcdataindex = $srcbyteindex; } if ($dstbyteindex >= 0) { $dstdataindex = $dstbyteindex; } } else { if (($srcjitterindex >= 0) || ($dstjitterindex >= 0)) { if ($srcjitterindex >= 0) { $srcdataindex = $srcjitterindex; } if ($dstjitterindex >= 0) { $dstdataindex = $dstjitterindex; } } else { if (($srclossindex >= 0) || ($dstlossindex >= 0)) { if ($srclossindex >= 0) { $srcdataindex = $srclossindex; } if ($dstlossindex >= 0) { $dstdataindex = $dstlossindex; } } } } if ($avgdurindex >= 0) { $srcdataindex = -1; $dstdataindex = $avgdurindex; $minval = 0.000001; } if ($ddurindex >= 0) { $srcdataindex = -1; $dstdataindex = $ddurindex; } if ($transindex >= 0) { $srcdataindex = -1; $dstdataindex = $transindex; } if ($dstimeindex >= 0) { $srcdataindex = -1; $dstdataindex = $dstimeindex; } if ($dltimeindex >= 0) { $srcdataindex = -1; $dstdataindex = $dltimeindex; } } my $ind = 4; my $cnt = 1; my $lineind = 0; my $xaxislabel; @opts = ("--start", $START, "--step", $STEP); if (@typeobjects + 0) { my %objectlist = (); open(SESAME, $file); for (1 .. 7) { my $data = ; } while (my $data = ) { my @items = split(/,/, $data); for (my $i = 0; $i < (@typeobjects + 0); $i++) { chomp $items[$typeobjects[$i]]; $objectlist{$items[$typeobjects[$i]]}[0]++; for (my $x = 0; $x < (@dataobjects + 0); $x++) { chomp $items[$dataobjects[$x]]; $objectlist{$items[$typeobjects[$i]]}[1] += $items[$dataobjects[$x]]; } } } for my $objs (sort { $objectlist{$b}[0] <=> $objectlist{$a}[0] } keys %objectlist) { if (!($objs eq "0.0.0.0")) { push @objects, $objs; } } if ($num > 0) { splice @objects, $num; } seek(SESAME, 0, 0); for (1 .. 7) { my $data = ; } if ($protoindex >= 0) { if ($daddrindex >= 0) { push @objects, "mcast"; } } my $ncnt = 0; my $ocnt = 0; for (my $i = 0; $i < (@objects + 0); $i++) { for (my $x = 0; $x < (@dataobjects + 0); $x++) { for ($columns[$dataobjects[$x]]) { /Host|Src|In|SApp/ and do { $opts[$ind++] = "DS:objectIn$ncnt:GAUGE:$STEP:U:$maxval"; $line_args[$lineind++] = "DEF:alphaIn$ncnt=$RRD:objectIn$ncnt:AVERAGE"; $line_args[$lineind++] = "CDEF:ralphaIn$ncnt=alphaIn$ncnt,$STEP,/"; $ncnt++; }; /Dst|Out|DApp|Trans|Dur|Time/ and do { $opts[$ind++] = "DS:objectOut$ocnt:GAUGE:$STEP:$minval:U"; $line_args[$lineind++] = "DEF:alphaOut$ocnt=$RRD:objectOut$ocnt:AVERAGE"; $line_args[$lineind++] = "CDEF:ralphaOut$ocnt=alphaOut$ocnt,$STEP,/"; $ocnt++; }; } } } } else { my $ncnt = 0; my $ocnt = 0; shift @columns; push @objects, @columns; @columns = split(/,/, $COLUMNS); for (my $i = 0; $i < (@objects + 0); $i++) { for ($objects[$i]) { /Host|Src|In|SApp/ and do { $opts[$ind++] = "DS:objectIn$ncnt:GAUGE:$STEP:U:$maxval"; $line_args[$lineind++] = "DEF:alphaIn$ncnt=$RRD:objectIn$ncnt:AVERAGE"; $line_args[$lineind++] = "CDEF:ralphaIn$ncnt=alphaIn$ncnt,$STEP,/"; $ncnt++; }; /Dst|Out|DApp|Trans|Dur|Time/ and do { $opts[$ind++] = "DS:objectOut$ocnt:GAUGE:$STEP:$minval:U"; $line_args[$lineind++] = "DEF:alphaOut$ocnt=$RRD:objectOut$ocnt:AVERAGE"; $line_args[$lineind++] = "CDEF:ralphaOut$ocnt=alphaOut$ocnt,$STEP,/"; $ocnt++; }; } } } my %inColors; my %outColors; my @incolors = ("#900000", "#008000", "#002275", "#ead00e", "#de2d1a", "#800080", "#008080", "#808080", "#808000"); my @outcolors = ("#f00000", "#00e000", "#0000f0", "#ffff66", "#f68d00", "#e000e0", "#00e0e0", "#e0e0e0", "#e0e000"); if ($protoindex >= 0) { %inColors = ( tcp => "#a00000", udp => "#008000", icmp => "#000080", igmp => "#008080", ospf => "#800080", pim => "#808080", mcast => "#808000", ip => "#707070" ); %outColors = ( tcp => "#f00000", udp => "#00f000", icmp => "#0000e0", igmp => "#00e0e0", ospf => "#e000e0", pim => "#e0e0e0", mcast => "#e0e000", ip => "#b0b0b0" ); } else { if (@typeobjects + 0) { for (my $i = 0; $i < (@objects + 0); $i++) { $inColors{$objects[$i]} = $incolors[$i]; $outColors{$objects[$i]} = $outcolors[$i]; } } else { $inColors{$objects[0]} = $incolors[0]; $outColors{$objects[0]} = $outcolors[0]; } } if ((@dataobjects + 0) == 0) { printf "usage: $0 metric (srcid | proto [daddr] | dport) [-title \"title\"] [ra-options]\n"; } if (($srcdataindex < 0) || ($dstdataindex < 0)) { $split = 0; } my $col; my $date; if (($END - $START) > (60 * 60 * 24)) { $date = strftime "%a %b %e %Y", localtime($START); $date .= " - "; $date .= strftime "%a %b %e %Y", localtime($END); } else { $date = strftime "%a %b %e %Y", localtime($START); } $line_args[$lineind++] = "COMMENT:$date\\c"; $line_args[$lineind++] = "COMMENT:\\s"; if ($fill && $split) { $line_args[$lineind++] = "HRULE:0#ffffff"; } else { $line_args[$lineind++] = "HRULE:0#888888"; } my $style; my $method; if ($fill) { $style = "AREA"; } else { $style = "LINE2"; } if ($stack) { $method = "STACK"; } else { $method = $style; } if (@typeobjects + 0) { my $ncnt = 0; my $ocnt = 0; my $object; for (my $i = 0; $i < (@objects + 0); $i++) { for (my $x = 0; $x < (@dataobjects + 0); $x++) { for ($columns[$dataobjects[$x]]) { /Dst|Out|DApp/ and do { if (!($col = $outColors{$objects[$i]})) { $col = "#707070"; } $object = sprintf "%-4.4s%-*.*s\\J", "out ", $objwidth, $objwidth, $objects[$i]; if ($ocnt == 0) { $line_args[$lineind++] = "$style:ralphaOut$ocnt$col:$object:"; } else { $line_args[$lineind++] = "$method:ralphaOut$ocnt$col:$object:"; } $ocnt++; }; /Trans|Dur|Time/ and do { if (!($col = $inColors{$objects[$i]})) { $col = "#707070"; } $object = sprintf "%-*.*s\\J", $objwidth, $objwidth, $objects[$i]; if ($ocnt == 0) { $line_args[$lineind++] = "$style:ralphaOut$ocnt$col:$object:"; } else { $line_args[$lineind++] = "$method:ralphaOut$ocnt$col:$object:"; } $ocnt++; }; } } } if ($ocnt > 0) { $line_args[$lineind++] = "COMMENT:\\s"; $line_args[$lineind++] = "COMMENT:\\s"; if ($ocnt > 7) { $line_args[$lineind++] = "COMMENT:\\s"; } } for (my $i = 0; $i < (@objects + 0); $i++) { for (my $x = 0; $x < (@dataobjects + 0); $x++) { for ($columns[$dataobjects[$x]]) { /Host|Src|In|SApp/ and do { if (!($col = $inColors{$objects[$i]})) { $col = "#b0b0b0"; } $object = sprintf "%-4.4s%-*.*s\\J", " in ", $objwidth, $objwidth, $objects[$i]; if ($ncnt == 0) { $line_args[$lineind++] = "$style:ralphaIn$ncnt$col:$object:"; } else { $line_args[$lineind++] = "$method:ralphaIn$ncnt$col:$object:"; } $ncnt++; }; } } } } else { my $ncnt = 0; my $ocnt = 0; for (my $x = 0; $x < (@objects + 0); $x++) { for (my $object = $objects[$x]) { /Host|Src|In|SApp/ and do { if (!($col = $incolors[$ncnt])) { $col = "#707070"; } if ($ncnt == 0) { $line_args[$lineind++] = "$style:ralphaIn$ncnt$col:$object"; } else { $line_args[$lineind++] = "$method:ralphaIn$ncnt$col:$object"; } $ncnt++; }; /Dst|Out|DApp|Trans|Dur|Time/ and do { if (!($col = $outcolors[$ocnt])) { $col = "#b0b0b0"; } if ($ocnt == 0) { $line_args[$lineind++] = "$style:ralphaOut$ocnt$col:$object"; } else { $line_args[$lineind++] = "$method:ralphaOut$ocnt$col:$object"; } $ocnt++; }; } } } my $xaxislabels = 0; for (my $x = 0; $x < (@columns + 0); $x++) { for ($columns[$x]) { /Pkt/ and do {$power[$x] = 1.0 ; $xaxislabels++; $xaxislabel = " pkts/sec" ;}; /Bytes/ and do {$power[$x] = 1.0 * 8.0; $xaxislabels++; $xaxislabel = "bits/sec" ;}; /Jitter/ and do {$power[$x] = $STEP; $xaxislabels++; $xaxislabel = "Jitter (uSecs)" ;}; /Loss/ and do {$power[$x] = 1.0 ; $xaxislabels++; $xaxislabel = "Loss (pkts/sec)" ;}; /Trans/ and do {$power[$x] = 1.0 ; $xaxislabels++; $xaxislabel = "Concurrent Transactions" ;}; /AvgDur/ and do {$power[$x] = $STEP ; $xaxislabels++; $xaxislabel = "Average Transaction Time (secs)" ;}; /dDur/ and do {$power[$x] = $STEP ; $xaxislabels++; $xaxislabel = "Network Transit Time (secs)" ;}; /dsTime/ and do {$power[$x] = $STEP ; $xaxislabels++; $xaxislabel = "Delta StartTime (secs)" ;}; /dlTime/ and do {$power[$x] = $STEP ; $xaxislabels++; $xaxislabel = "Delta LastTime (secs)" ;}; } } if ($xaxislabels > 1) { if (($ddurindex >= 0) && (($dstimeindex >= 0) || ($dltimeindex >= 0))) { $xaxislabel = "Delta Time (secs)" ; } } if ($split) { if ($objectindex >= 0) { $xaxisstr = "inbound(-).outbound(+) "; } else { $xaxisstr = "dest(-).src(+) "; } } else { $xaxisstr = ""; } $xaxisstr .= $xaxislabel; $opts[$ind] = "RRA:AVERAGE:0.5:1:$RUNS"; } sub RagraphGenerateRRD { my $data; open(SESAME, $tmpfile); for (1 .. 7) { $data = ; } RRDs::create $RRD, @opts; $ERROR = RRDs::error; if ($ERROR) { die "$0: unable to create `$RRD': $ERROR\n"; } my $last = RRDs::last $RRD; if ($ERROR = RRDs::error) { die "$0: unable to get last `$RRD': $ERROR\n"; } @opts = (); my $startime = $START; my $lasttime = $START + $STEP; my %objectvals; my %bins; my @vals; for (my $i = 0; $i < (@objects + 0); $i++) { $objectvals{$objects[$i], 'in'} = 0; $objectvals{$objects[$i], 'out'} = 0; } while (my $data = ) { @opts = split(/,/, $data); my $thistime = $opts[0]; if ($bins{$thistime}++ == 0) { } if (@typeobjects + 0) { for (my $i = 0; $i < (@typeobjects + 0); $i++) { my $thisobject = $opts[$typeobjects[$i]]; chomp $thisobject; if ($daddrindex >= 0) { my @addr = split(/./, $opts[2]); if (($addr[0] & 0xF0) == 0xE0) { $thisobject = "mcast"; } } for (my $x = 0; $x < (@dataobjects + 0); $x++) { my $dataindex = $dataobjects[$x]; for ($columns[$dataindex]) { /Host|Src|In|SApp/ and do { $objectvals{$thistime, $thisobject, 'in'} += $opts[$dataindex] * $power[$dataindex]; }; /Dst|Out|DApp|Trans|Dur|Time/ and do { $objectvals{$thistime, $thisobject,'out'} += $opts[$dataindex] * $power[$dataindex]; }; } } } } else { my $label; for (my $i = 0; $i < (@objects + 0); $i++) { for ($objects[$i]) { /Host|Src|In|SApp/ and do { $label = 'in'; }; /Dst|Out|DApp|Trans|Dur|Time/ and do { $label = 'out'; }; } my $value = $opts[$i+1]; my $power = $power[$i+1]; $objectvals{$thistime, $objects[$i], $label} += $opts[$i + 1] * $power[$i + 1]; } } } close(SESAME); for my $thisbin (sort keys %bins) { my $prime = $thisbin; my $nvalue = 0; my $ovalue = 0; for (my $i = 0; $i < (@objects + 0); $i++) { if (@typeobjects + 0) { for (my $x = 0; $x < (@dataobjects + 0); $x++) { my $dataindex = $dataobjects[$x]; for ($columns[$dataindex]) { /Host|Src|In|SApp/ and do { if (!($nvalue = $objectvals{$thisbin, $objects[$i], 'in'})) { $nvalue = 0; } if ($split) { if ($nvalue == 0) { $prime .= ":$nvalue"; } else { $prime .= ":-$nvalue"; } } else { $prime .= ":$nvalue"; } }; /Dst|Out|DApp|Trans|Dur|Time/ and do { if (!($ovalue = $objectvals{$thisbin, $objects[$i], 'out'})) { $ovalue = 0; } $prime .= ":$ovalue"; }; } } } else { my $label; for ($objects[$i]) { /Host|Src|In|SApp/ and do { $label = 'in'; }; /Dst|Out|DApp|Trans|Dur|Time/ and do { $label = 'out'; }; } $nvalue = $objectvals{$thisbin, $objects[$i], $label}; if ($split && ($label eq 'in')) { $prime .= ":-$nvalue"; } else { $prime .= ":$nvalue"; } } } RRDs::update $RRD, "$prime"; if ($ERROR = RRDs::error) { die "$0: unable to update `$RRD': $ERROR\n"; } } } sub RagraphGenerateGIF { my @rrd_gifs = ($RRD, $GIF); my @rrd_args = ( "--base", "1000", "--vertical-label", $xaxisstr, "--start", $START, "--end", $END, "--interlace", "--imgformat","GIF", ); if ($title) { push @rrd_args, ("--title", $title); } if ($rigid) { @rrd_args[++$#rrd_args] = "--rigid"; } if ($log) { @rrd_args[++$#rrd_args] = "--log"; } if ($width) { @rrd_args[++$#rrd_args] = "--width"; @rrd_args[++$#rrd_args] = $width; } if ($height) { @rrd_args[++$#rrd_args] = "--height"; @rrd_args[++$#rrd_args] = $height; } if (!($rigid) && ($upper || $lower)) { @rrd_args[++$#rrd_args] = "--rigid"; } if ($upper) { @rrd_args[++$#rrd_args] = "--upper-limit"; @rrd_args[++$#rrd_args] = $upper; } if ($lower) { @rrd_args[++$#rrd_args] = "--lower-limit"; @rrd_args[++$#rrd_args] = $lower; } push @rrd_args, @line_args; while (@rrd_gifs) { my $RRD = shift(@rrd_gifs); my $GIF = shift(@rrd_gifs); my ($graphret,$xs,$ys) = RRDs::graph $GIF, @rrd_args; if ($ERROR = RRDs::error) { print "ERROR: $ERROR\n"; } } } argus-clients-2.0.6.fixes.1/ragraph/rahistogram.c0000664000076600007660000030561207640610166015377 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * rahistogram - argus record collector and time bin output processor * * written by Carter Bullard * QoSient, LLC * */ #include #include #include #include #define RA_PRINTPROTO 1 #define RA_PRINTSRCID 2 #define RAMON_TOPN 1 #define RAMON_MATRIX 2 #define RAMON_SVCS 3 #define RAMON_SINGLE 4 int RaPrintMode = 0; extern int RaHistoStart, RaHistoEnd, RaHistoBins; struct RaBinStruct { struct timeval start, end; int status, timeout; struct RaQueueStruct *queue; struct RaHashTableStruct hashtable; }; struct RaBinStruct *RaThisBin; struct RaBinStruct *RaNewBin(struct ArgusRecord *); void RaDeleteBin (struct RaBinStruct *); int RaLabelCounter = 0; int RaFirstArgusRecord = 1; int RaSeconds = 0; int RaScaleSeconds = 0; int RaStartSeconds = 0; int RaEndSeconds = 0; struct timeval RaStartTime = {0x7FFFFFFF, 0x7FFFFFFF}; struct timeval RaEndTime = {0,0}; struct timeval RaStartPoint = {0x7FFFFFFF, 0x7FFFFFFF}; struct timeval RaEndPoint = {0,0}; int RaBinCount = 0; float RaBinSize = 0.0; void RaInitializeMergeArray(void); void RaReInitializeMergeArray(int); #define RACRICKET_HASHTABLESIZE 128 void RaProcessArray(struct RaBinStruct **, unsigned char); struct ArgusRecord * RaAdjustArgusRecord (struct ArgusRecord *); struct ArgusRecord * RaRmonArgusRecord (struct ArgusRecord *); void RaProcessThisSrvRecord (struct ArgusServiceRecord *); int RaCreateEtherFlow (struct ArgusRecord *); void RaModifyEtherFlow(struct ArgusRecord *); struct RaBinStruct **RaBinMergeArray = NULL; struct RaBinStruct **RaBinOldMergeArray = NULL; struct tm RaThisTmStructBuf, *RaThisTmStruct = &RaThisTmStructBuf; struct tm RaEndTmStructBuf, *RaEndTmStruct = &RaEndTmStructBuf; struct tm RaStartTmStructBuf, *RaStartTmStruct = &RaStartTmStructBuf; int RaAdjustCount = 0; int RaHoldTime = 0; int RaNoZeroMode = 0; int RaStreamMode = 0; int RaProbeMode = 0; int RaNetMode = 0; int RaMonMode = 0; int RaMonMask = 0; extern int ArgusPassNum; int RaPassNum = 0; int RaPrintMACAddress = 0; struct RaQueueStruct *RaProbeQueue = NULL; struct timeval * RaMaxTime (struct timeval *, struct timeval *); struct timeval * RaMinTime (struct timeval *, struct timeval *); struct timeval * RaDiffTime (struct timeval *, struct timeval *); struct timeval * RaMinTime (struct timeval *s1, struct timeval *s2) { struct timeval *retn = s2; if ((s1->tv_sec < s2->tv_sec) || ((s1->tv_sec == s2->tv_sec) && (s1->tv_usec < s2->tv_usec))) retn = s1; return (retn); } struct timeval * RaMaxTime (struct timeval *s1, struct timeval *s2) { struct timeval *retn = s2; if ((s1->tv_sec > s2->tv_sec) || ((s1->tv_sec == s2->tv_sec) && (s1->tv_usec > s2->tv_usec))) retn = s1; return (retn); } struct timeval RaDiffTimeBuf; struct timeval * RaDiffTime (struct timeval *s1, struct timeval *s2) { struct timeval *retn = NULL; bzero ((char *)&RaDiffTimeBuf, sizeof(RaDiffTimeBuf)); if (s1 && s2) { RaDiffTimeBuf.tv_sec = s1->tv_sec - s2->tv_sec; RaDiffTimeBuf.tv_usec = s1->tv_usec - s2->tv_usec; if (RaDiffTimeBuf.tv_usec < 0) { RaDiffTimeBuf.tv_usec += 1000000; RaDiffTimeBuf.tv_sec--; } retn = &RaDiffTimeBuf; } return (retn); } void RaProcessRecord (struct ArgusRecord *argus) { if (RaFirstArgusRecord && (!(argus->ahdr.type & ARGUS_MAR))) { RaStartTime = argus->argus_far.time.start; RaInitializeMergeArray(); RaFirstArgusRecord = 0; } if (argus->ahdr.type & ARGUS_MAR) RaProcessManRecord (argus); else { switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: RaProcessTCPRecord (argus); break; case IPPROTO_UDP: RaProcessUDPRecord (argus); break; case IPPROTO_ICMP: RaProcessICMPRecord (argus); break; default: RaProcessIPRecord (argus); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: RaProcessARPRecord (argus); break; default: RaProcessNonIPRecord (argus); break; } } /* if (Nflag > 0) { if (Nflag-- == 1) { RaParseComplete(SIGINT); } } */ } char *RaMonTopNModelString = "Model 200 ip %s 0.0.0.0 %s %s %s"; char *RaMonMatrixModelString = "Model 200 ip %s %s %s %s %s"; char *RaMonSingleFlowModelFile [] = { "RAGATOR_PRESERVE_FIELDS=yes", "RAGATOR_REPORT_AGGREGATION=yes", "Flow 100 ip * * * * * 200 0 0", "Model 200 ip 0.0.0.0 0.0.0.0 no no no", NULL, }; char *RaMonMatrixFlowModelFile [] = { "RAGATOR_PRESERVE_FIELDS=yes", "RAGATOR_REPORT_AGGREGATION=yes", "Flow 100 ip * * * * * 200 0 0", "Model 200 ip 255.255.255.255 255.255.255.255 no no no", NULL, }; char *RaMonTopNFlowModelFile [] = { "RAGATOR_PRESERVE_FIELDS=yes", "RAGATOR_REPORT_AGGREGATION=yes", "Flow 100 ip * * * * * 200 0 0", "Model 200 ip 255.255.255.255 0.0.0.0 no no no", NULL, }; char *RaMonServicesFlowModelFile [] = { "RAGATOR_PRESERVE_FIELDS=yes", "RAGATOR_REPORT_AGGREGATION=yes", "Flow 10 ip * * tcp 20 * 100 0 0", "Flow 100 ip * * * * * 200 0 0", "Model 100 ip 0.0.0.0 0.0.0.0 yes yes yes", "Model 200 ip 0.0.0.0 0.0.0.0 yes no yes", NULL, }; void RaProcessSrvRecord (struct ArgusServiceRecord *); int RaInitialized = 0; int RaTimeout = 0x1FFFFFFF; int RaIdleTimeout = 0; #define RAHISTOGRAMMODENUM 8 #define RASECONDS 0 #define RAMINUTE 1 #define RAHOURLY 2 #define RADAILY 3 #define RAWEEKLY 4 #define RAMONTHLY 5 #define RANNUALY 6 #define RAONEBIN 7 int RaModeValue = RAONEBIN; char *RaHistogramModes[RAHISTOGRAMMODENUM] = { "second", "minute", "hourly", "dayly", "weekly", "Monthly", "annually", "onebin", }; extern struct timeval RaClientTimeout; extern int RaFlowMajorModified; struct RaFlowModelStruct *RaFlowModel = NULL; char *RaPrintProtoStr = "no"; char *RaPrintSrcPortStr = "no"; char *RaPrintDstPortStr = "no"; void ArgusClientInit () { struct ArgusModeStruct *mode = NULL; int i = 0, found = 0; char *ptr = NULL; if (!(RaInitialized)) { RaWriteOut = 0; RaCumulativeMerge = 1; RaFlowMajorModified = 1; if (dflag == 0) dflag++; if (ArgusFlowModelFile) if ((RaFlowModel = RaReadFlowModelFile(NULL)) == NULL) ArgusLog(LOG_ERR, "ArgusClientInit RaReadFlowModelFile %s", strerror(errno)); if ((mode = ArgusModeList) != NULL) { while (mode) { found = 0; if (isdigit((int) *mode->mode)) { if (sscanf(mode->mode, "%d", &dflag) == 1) while (isdigit((int) *mode->mode)) mode->mode++; } for (i = 0; i < RAHISTOGRAMMODENUM; i++) { if (!(strncasecmp (mode->mode, RaHistogramModes[i], strlen(mode->mode)))) { RaModeValue = i; found++; break; } } if (!found) { if (!(strcasecmp (mode->mode, "nozero"))) { found++; RaNoZeroMode++; } else if (!(strcasecmp (mode->mode, "Single"))) { found++; if (RaMonMode == RAMON_TOPN) ArgusLog(LOG_ERR, "-M Single conflicts with -M Addrs"); if (RaMonMode == RAMON_MATRIX) ArgusLog(LOG_ERR, "-M Single conflicts with -M Matrix"); if (RaMonMode == RAMON_SVCS) ArgusLog(LOG_ERR, "-M Single conflicts with -M Ports"); RaMonMode = RAMON_SINGLE; if (RaFlowModelFile) { ArgusLog(LOG_ERR, "multiple models specified"); } else { RaFlowModelFile = RaMonSingleFlowModelFile; } if (!(RaSOptionIndex)) { bzero ((char *) RaPrintAlgorithms, sizeof(RaPrintAlgorithms)); RaPrintAlgorithms[0] = ArgusPrintDate; RaPrintAlgorithms[1] = ArgusPrintCounts; RaPrintAlgorithms[2] = ArgusPrintBytes; } } else if (!(strcasecmp (mode->mode, "Addrs"))) { found++; if (RaMonMode == RAMON_MATRIX) ArgusLog(LOG_ERR, "-M Addrs conflicts with -M Matrix"); RaMonMode = RAMON_TOPN; if (RaFlowModelFile) { ArgusLog(LOG_ERR, "multiple models specified"); } else { RaFlowModelFile = RaMonTopNFlowModelFile; } if (!(RaSOptionIndex)) { bzero ((char *) RaPrintAlgorithms, sizeof(RaPrintAlgorithms)); RaPrintAlgorithms[0] = ArgusPrintDate; RaPrintAlgorithms[1] = ArgusPrintSrcAddr; RaPrintAlgorithms[2] = ArgusPrintProto; RaPrintAlgorithms[3] = ArgusPrintCounts; RaPrintAlgorithms[4] = ArgusPrintBytes; } } else if (!(strcasecmp (mode->mode, "Matrix"))) { found++; if (RaMonMode == RAMON_TOPN) ArgusLog(LOG_ERR, "-M Matrix conflicts with -M Addrs"); RaMonMode = RAMON_MATRIX; if (RaFlowModelFile) { ArgusLog(LOG_ERR, "multiple models specified"); } else { RaFlowModelFile = RaMonMatrixFlowModelFile; } if (!(RaSOptionIndex)) { bzero ((char *) RaPrintAlgorithms, sizeof(RaPrintAlgorithms)); RaPrintAlgorithms[0] = ArgusPrintDate; RaPrintAlgorithms[1] = ArgusPrintSrcAddr; RaPrintAlgorithms[2] = ArgusPrintDstAddr; RaPrintAlgorithms[3] = ArgusPrintProto; RaPrintAlgorithms[4] = ArgusPrintCounts; RaPrintAlgorithms[5] = ArgusPrintBytes; } } else if (!(strcasecmp (mode->mode, "Ports"))) { found++; if (RaMonMode == RAMON_TOPN) ArgusLog(LOG_ERR, "-M Svc conflicts with -M TopN"); if (RaMonMode == RAMON_MATRIX) ArgusLog(LOG_ERR, "-M Svc conflicts with -M Matrix"); RaMonMode = RAMON_SVCS; if (RaFlowModelFile) { ArgusLog(LOG_ERR, "multiple models specified"); } else { RaFlowModelFile = RaMonServicesFlowModelFile; } if (!(RaSOptionIndex)) { bzero ((char *) RaPrintAlgorithms, sizeof(RaPrintAlgorithms)); RaPrintAlgorithms[0] = ArgusPrintDate; RaPrintAlgorithms[1] = ArgusPrintDstPort; RaPrintAlgorithms[2] = ArgusPrintProto; RaPrintAlgorithms[3] = ArgusPrintCounts; RaPrintAlgorithms[4] = ArgusPrintBytes; } } else if (!(strncasecmp (mode->mode, "Net", 3))) { found++; if ((ptr = strchr (mode->mode, '/')) != NULL) { if (sscanf(&ptr[1], "%d", &RaMonMask) != 1) usage(); } RaNetMode++; } else if (!(strcasecmp (mode->mode, "Probe"))) { found++; RaProbeMode++; } else if (!(strcasecmp (mode->mode, "Stream"))) { found++; RaStreamMode++; } } if (!found) usage(); mode = mode->nxt; } } if (Gflag) { uflag++; RaFieldDelimiter = ','; } for (i = 0; RaPrintAlgorithms[i] != NULL; i++) { if (RaPrintAlgorithms[i] == ArgusPrintProto) { RaPrintMode |= RA_PRINTPROTO; RaPrintProtoStr = "yes"; break; } if (RaPrintAlgorithms[i] == ArgusPrintSrcPort) { RaPrintProtoStr = "yes"; break; } if (RaPrintAlgorithms[i] == ArgusPrintDstPort) { RaPrintProtoStr = "yes"; break; } if (RaPrintAlgorithms[i] == ArgusPrintSourceID) { RaPrintMode |= RA_PRINTSRCID; break; } } if (!RaNetMode) RaMonMask = 32; switch (RaMonMode) { case RAMON_TOPN: { char buf[MAXSTRLEN]; char addrstr[128]; if (RaMonMask != 0) { sprintf (addrstr, "255.255.255.255/%d", RaMonMask); } else sprintf (addrstr, "class"); sprintf (buf, RaMonTopNModelString, addrstr, RaPrintProtoStr, RaPrintSrcPortStr, RaPrintDstPortStr); RaMonTopNFlowModelFile [1] = strdup(buf); RaFlowModel = RaReadFlowModelFile (RaMonTopNFlowModelFile); break; } case RAMON_MATRIX: { char buf[MAXSTRLEN]; char addrstr[128]; if (RaMonMask != 0) { sprintf (addrstr, "255.255.255.255/%d", RaMonMask); } else sprintf (addrstr, "class"); sprintf (buf, RaMonMatrixModelString, addrstr, addrstr, RaPrintProtoStr, RaPrintSrcPortStr, RaPrintDstPortStr); RaMonMatrixFlowModelFile [1] = strdup(buf); RaFlowModel = RaReadFlowModelFile (RaMonMatrixFlowModelFile); break; } case RAMON_SINGLE: RaFlowModel = RaReadFlowModelFile (RaMonSingleFlowModelFile); break; case RAMON_SVCS: RaFlowModel = RaReadFlowModelFile (RaMonServicesFlowModelFile); break; default: break; } if (ArgusFlowModelFile != NULL) ArgusFlowModelFile = "dummy"; if ((RaModelerQueue = RaNewQueue()) == NULL) exit(0); if ((RaProbeQueue = RaNewQueue()) == NULL) exit(0); if ((RaHashTable.array = (struct RaHashTableHeader **) ArgusCalloc (RACRICKET_HASHTABLESIZE, sizeof (struct RaHashTableHeader *))) != NULL) { RaHashTable.size = RACRICKET_HASHTABLESIZE; } if ((RaProbeTable.array = (struct RaHashTableHeader **) ArgusCalloc (RA_HASHTABLESIZE, sizeof (struct RaHashTableHeader *))) != NULL) { RaProbeTable.size = RA_HASHTABLESIZE; } if (Hflag) { if (!(RaHistoTimeParse (Hstr))) usage(); } RaClientTimeout.tv_sec = 1; RaClientTimeout.tv_usec = 0; if (nflag > 1) { hfield = 15; pfield = 5; } else { pfield = 15; } RaInitialized++; } } int RaParseCompleting = 0; void RaParseComplete (int sig) { if (sig >= 0) { if ((ArgusInput != NULL) && (RaMonMode == RAMON_TOPN)) ArgusInput->ArgusManStart.ahdr.type |= ARGUS_RMON; if (RaPassNum++ == 1) { RaFirstArgusRecord = 1; totalrecords = 0; } else { if (!RaParseCompleting) { RaParseCompleting++; if (RaModelerQueue) RaProcessArray (RaBinMergeArray, ARGUS_STOP); } if (sig == SIGINT) _exit(0); } } #ifdef ARGUSDEBUG ArgusDebug (1, "RaParseComplete: returning ArgusPassNum %d RaPassNum %d\n", ArgusPassNum, RaPassNum); #endif } struct timeval ArgusClientLastTimeout = {0,0}; void ArgusClientTimeout () { struct timeval tvpbuf, *tvp = &tvpbuf; gettimeofday(tvp, 0L); ArgusAdjustGlobalTime (tvp); if (Sflag || Cflag || Bflag) RaProcessArray (RaBinMergeArray, ARGUS_STATUS); #ifdef ARGUSDEBUG if ((tvp->tv_sec % 60) == 0) { if (ArgusClientLastTimeout.tv_sec < tvp->tv_sec) { struct RaBinStruct *bin = NULL; int i, qcount = 0, hcount = 0; for (i = 0; i < RaBinCount; i++) { if ((bin = RaBinMergeArray[i]) != NULL) { if (bin->queue && (bin->queue->count > 0)) qcount += bin->queue->count; if (bin->hashtable.count > 0) hcount += bin->hashtable.count; } } ArgusDebug (2, "ArgusClientTimeout: RaBinCount %d RaHoldTime %d Hash %d HashHdrs %d Queue %d\n", RaBinCount, RaHoldTime, hcount, RaAllocHashTableHeaders, qcount); } ArgusClientLastTimeout = *tvp; } ArgusDebug (7, "ArgusClientTimeout: done\n"); #endif } void parse_arg (int argc, char**argv) { } void usage () { extern char version[]; fprintf (stderr, "Ragator Version %s\n", version); fprintf (stderr, "usage: %s [-f flowfile]\n", ArgusProgramName); fprintf (stderr, "usage: %s [-f flowfile] [ra-options] [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "options: -f read flow model from .\n"); fprintf (stderr, "ra-options: -a print record summaries on termination.\n"); fprintf (stderr, " -A print application bytes.\n"); fprintf (stderr, " -b dump packet-matching code.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); fprintf (stderr, " -D specify debug level\n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -n don't convert numbers to names.\n"); fprintf (stderr, " -p print fractional time with precision.\n"); fprintf (stderr, " -q quiet mode. don't print record outputs.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -R print out response data when availabile.\n"); fprintf (stderr, " -S specify remote argus and optional port number.\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [mm/dd[/yy].]hh[:mm[:ss]]\n"); fprintf (stderr, " mm/dd[/yy]\n"); fprintf (stderr, " -%%d{yMhdms}\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); fprintf (stderr, " -u print time in Unix time format.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif fprintf (stderr, " -w write output to . '-' denotes stdout.\n"); fprintf (stderr, " -z print Argus TCP state changes.\n"); fprintf (stderr, " -Z print actual TCP flag values.<'s'rc | 'd'st | 'b'oth>\n"); exit(1); } int RaBinsCheckTimeout (struct RaBinStruct *, struct ArgusRecord *); int RaBinsCheckTimeout (struct RaBinStruct *bin, struct ArgusRecord *argus) { int retn = 0, lapseTime; struct timeval *tvp; if (Sflag || Cflag) tvp = &ArgusRealTime; else tvp = &ArgusGlobalTime; if (bin->timeout > 0) { lapseTime = bin->end.tv_sec + bin->timeout; if ((tvp->tv_sec > lapseTime) || ((tvp->tv_sec == lapseTime) && (tvp->tv_usec > bin->end.tv_usec))) retn++; } #ifdef ARGUSDEBUG ArgusDebug (6, "RaCheckTimeout: returning %d \n", retn); #endif return (retn); } void RaProcessSrvRecord (struct ArgusServiceRecord *srv) { struct ArgusRecord *argus = NULL; struct ArgusRecord *arg2 = NULL; struct RaHashTableHeader *rtblhdr = NULL; unsigned int key = 0; if (srv && ((argus = srv->argus) != NULL)) { unsigned int probe = srv->argus->ahdr.argusid; unsigned short proto = srv->argus->argus_far.flow.ip_flow.ip_p; struct RaHashStruct ArgusHash; struct ArgusRecordStore *store; bzero ((char *)&ArgusHash, sizeof(ArgusHash)); ArgusHash.len = sizeof(ArgusHash.buf); ArgusHash.hash = 0; switch (RaPrintMode) { case RA_PRINTSRCID: key = probe; break; case RA_PRINTPROTO: key = proto; break; } ArgusHash.buf[0] = key; if ((rtblhdr = RaFindHash(&RaProbeTable, &ArgusHash)) == NULL) { if ((store = RaNewArgusStore(argus)) == NULL) ArgusLog (LOG_ERR, "RaProcessSrvRecord: RaNewArgusStore %s", strerror(errno)); else { if ((store->data[RaThisActiveIndex] = RaNewArgusData(argus)) == NULL) ArgusLog (LOG_ERR, "RaProcessSrvRecord: RaNewArgusData %s", strerror(errno)); } if ((store->rahtblhdr = RaAddHashObject (&RaProbeTable, (void *) key, &ArgusHash)) == NULL) ArgusLog (LOG_ERR, "RaProcessSrvRecord: RaAddHashObject %s", strerror(errno)); RaAddToQueue(RaProbeQueue, &store->qhdr); } if (RaMonMode == RAMON_TOPN) { if ((arg2 = RaRmonArgusRecord(argus)) != NULL) { RaProcessThisSrvRecord(srv); srv->argus = arg2; RaProcessThisSrvRecord(srv); ArgusFree(arg2); } } else { if (RaProbeMode && RaMonitorTable) { switch (srv->argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: { unsigned int saddr = srv->argus->argus_far.flow.ip_flow.ip_src; if ((RaProbeMonitorsThisAddr (probe, saddr))) ArgusReverseDataRecord(srv->argus); } } } RaProcessThisSrvRecord(srv); } } #ifdef ARGUSDEBUG ArgusDebug (5, "RaProcessSrvRecord: returning.\n"); #endif } struct timeval RaThisStartTime; int RaNumBlanks = 0; void RaProcessThisSrvRecord (struct ArgusServiceRecord *srv) { struct ArgusRecord *argus = srv->argus, *thisArgus; struct ArgusRecordStore *store; struct RaPolicyStruct *rap; struct ArgusFlow *flow = &argus->argus_far.flow; int RaStartSec = 0; int retn = 0, i = 0, index = 0; extern struct ArgusCanonicalRecord *RaThisCanon; if (xflag && (srv->status == RA_SVCFAILED)) return; if ((retn = argus_filter (ArgusFilterCode.bf_insns, RaThisCanon)) == 0) return; bcopy((char *) flow, (char *) RaArgusFlow, sizeof(struct ArgusFlow)); if (!(RaPrintMACAddress)) { if ((rap = RaFlowModelOverRides(argus, RaFlowModel)) != NULL) { RaModifyFlow(rap, argus, RaFlowModel); RaTimeout = rap->ArgusTimeout; RaIdleTimeout = rap->ArgusIdleTimeout; } else { RaModifyDefaultFlow(argus); } } else RaModifyEtherFlow(argus); RaThisActiveDuration = RaGetActiveDuration(argus); RaThisActiveIndex = RaHistoTimeSeries; if (Hflag) { if (RaThisActiveDuration < RaHistoStart) return; for (i = 0; i < RaHistoTimeSeries; i++) { if (RaThisActiveDuration < RaHistoTimeValues[i]) { RaThisActiveIndex = i; break; } } if (i == RaHistoTimeSeries) return; } else RaThisActiveIndex = 0; RaTimeout = RaHoldTime; RaIdleTimeout = 0; RaThisStartTime = argus->argus_far.time.start; if (!(RaStreamMode)) { while ((thisArgus = RaAdjustArgusRecord (argus)) != NULL) { RaAdjustCount++; if ((thisArgus->argus_far.src.count + thisArgus->argus_far.dst.count) > 0) { RaStartSec = thisArgus->argus_far.time.start.tv_sec - RaStartSeconds; if (RaStartSec < 0) { if (!(Sflag || Cflag || Bflag)) { RaReInitializeMergeArray(thisArgus->argus_far.time.start.tv_sec); RaStartSec = thisArgus->argus_far.time.start.tv_sec - RaStartSeconds; } } if (RaEndSeconds < thisArgus->argus_far.time.last.tv_sec) { RaReInitializeMergeArray(thisArgus->argus_far.time.last.tv_sec); } flow = &thisArgus->argus_far.flow; bcopy((char *) flow, (char *) RaArgusFlow, sizeof(struct ArgusFlow)); if (RaModeValue == RAONEBIN) { index = 0; } else { index = (int) (RaStartSec/RaBinSize); } if (index < RaBinCount) { if (index >= 0) { if ((RaThisBin = RaBinMergeArray[index]) == NULL) { if ((RaThisBin = RaNewBin(thisArgus)) == NULL) { ArgusLog (LOG_ERR, "RaProcessThisSrvRecord: RaNewBin error %s\n", strerror(errno)); } else { RaThisBin->status |= RA_MODIFIED; RaThisBin->timeout = RaTimeout; RaBinMergeArray[index] = RaThisBin; } } } RaStartPoint = *RaMinTime (&RaStartPoint, &RaThisBin->start); RaEndPoint = *RaMaxTime (&RaEndPoint, &RaThisBin->end); if ((store = RaFindArgusRecord(&RaThisBin->hashtable, thisArgus)) == NULL) if ((store = RaFindRevArgusRecord(&RaThisBin->hashtable, thisArgus)) != NULL) { } if (store) { RaThisArgusStore = store; if (!(store->data[RaThisActiveIndex])) { struct ArgusRecordData *data = NULL; if ((data = RaNewArgusData(thisArgus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; data->status |= srv->status & RA_SVCTEST; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *)&data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } store->data[RaThisActiveIndex] = data; } else ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); } else RaMergeArgusRecord(thisArgus, store, RaThisActiveIndex); RaUpdateArgusStore(thisArgus, store); } else { if ((store = RaNewArgusStore(thisArgus)) != NULL) { struct ArgusRecordData *data = NULL; store->ArgusTimeout = RaTimeout; store->ArgusIdleTimeout = RaIdleTimeout; store->startime = RaThisBin->start; store->lasttime = RaThisBin->end; RaThisArgusStore = store; store->status |= RA_MODIFIED; store->status |= srv->status & RA_SVCTEST; if ((data = RaNewArgusData(thisArgus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *)&data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } store->data[RaThisActiveIndex] = data; if ((store->rahtblhdr = RaAddHashEntry (&RaThisBin->hashtable, store)) != NULL) RaAddToQueue(RaThisBin->queue, &store->qhdr); } else ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); } else ArgusLog (LOG_ERR, "RaNewArgusStore failed %s\n", strerror(errno)); } } else ArgusLog (LOG_ERR, "index %d exceeds bin count %d startsec %d\n", index, RaBinCount, RaStartSec); } ArgusFree(thisArgus); } } else { /* streaming mode, no aggregation, just put it in the bin and crank out the data as the hold timer allows. so no merging, no hashing, no nada. */ thisArgus = argus; RaStartSec = thisArgus->argus_far.time.start.tv_sec - RaStartSeconds; if (RaStartSec < 0) { RaReInitializeMergeArray(thisArgus->argus_far.time.start.tv_sec); RaStartSec = thisArgus->argus_far.time.start.tv_sec - RaStartSeconds; } if (RaEndSeconds < thisArgus->argus_far.time.last.tv_sec) { RaReInitializeMergeArray(thisArgus->argus_far.time.last.tv_sec); } flow = &thisArgus->argus_far.flow; bcopy((char *) flow, (char *) RaArgusFlow, sizeof(struct ArgusFlow)); if (RaModeValue == RAONEBIN) { index = 0; } else { index = (int) (RaStartSec/RaBinSize); } if (index < RaBinCount) { if (index >= 0) { if ((RaThisBin = RaBinMergeArray[index]) == NULL) { if ((RaThisBin = RaNewBin(thisArgus)) == NULL) { ArgusLog (LOG_ERR, "RaProcessThisSrvRecord: RaNewBin error %s\n", strerror(errno)); } else { RaThisBin->status |= RA_MODIFIED; RaThisBin->timeout = RaTimeout; RaBinMergeArray[index] = RaThisBin; } } } else { } RaStartPoint = *RaMinTime (&RaStartPoint, &RaThisBin->start); RaEndPoint = *RaMaxTime (&RaEndPoint, &RaThisBin->end); if ((store = RaNewArgusStore(thisArgus)) != NULL) { struct ArgusRecordData *data = NULL; store->ArgusTimeout = RaTimeout; store->ArgusIdleTimeout = RaIdleTimeout; store->startime = RaThisBin->start; store->lasttime = RaThisBin->end; RaThisArgusStore = store; store->status |= RA_MODIFIED; store->status |= srv->status & RA_SVCTEST; if ((data = RaNewArgusData(thisArgus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *)&data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } store->data[RaThisActiveIndex] = data; if ((store->rahtblhdr = RaAddHashEntry (&RaThisBin->hashtable, store)) != NULL) RaAddToQueue(RaThisBin->queue, &store->qhdr); } else ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); } else ArgusLog (LOG_ERR, "RaNewArgusStore failed %s\n", strerror(errno)); } else ArgusLog (LOG_ERR, "index %d exceeds bin count %d startsec %d\n", index, RaBinCount, RaStartSec); } #ifdef ARGUSDEBUG ArgusDebug (7, "RaProcessSrvRecord: done\n"); #endif } void RaProcessManRecord (struct ArgusRecord *argus) { struct ArgusRecordStore *srv = NULL; if ((srv = RaNewArgusStore(argus)) != NULL) { srv->startime = argus->argus_far.time.start; srv->lasttime = argus->argus_far.time.last; srv->status |= RA_MODIFIED; if ((srv->data[RaThisActiveIndex] = RaNewArgusData(argus)) != NULL) { srv->data[RaThisActiveIndex]->status |= RA_MODIFIED; /* RaSendArgusRecord (srv); */ } RaDeleteArgusStore(srv); } #ifdef ARGUSDEBUG ArgusDebug (2, "RaProcessManRecord (0x%x): done\n", argus); #endif } struct ArgusServiceRecord ArgusThisSrv; void RaProcessTCPRecord (struct ArgusRecord *argus) { struct ArgusTCPObject *tcp = NULL; ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Vflag) { if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) { if ((tcp = (struct ArgusTCPObject *) ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]) != NULL) { if (tcp->state & (ARGUS_SAW_SYN || ARGUS_SAW_SYN_SENT)) { if (tcp->state & ARGUS_RESET) { if (tcp->state & ARGUS_DST_RESET) if (argus->argus_far.src.count && argus->argus_far.dst.count) if (!(argus->argus_far.src.bytes && argus->argus_far.dst.bytes)) ArgusThisSrv.status = RA_SVCFAILED; if (tcp->state & ARGUS_SRC_RESET) if (argus->argus_far.src.count && !(argus->argus_far.dst.count)) ArgusThisSrv.status = RA_SVCFAILED; } } if (tcp->state & ARGUS_TIMEOUT) if (argus->argus_far.src.count && !(argus->argus_far.dst.count)) ArgusThisSrv.status = RA_SVCFAILED; } } } RaProcessSrvRecord (&ArgusThisSrv); } void RaProcessICMPRecord (struct ArgusRecord *argus) { ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Vflag) { if ((argus->argus_far.src.count > 0) && (argus->argus_far.dst.count == 0)) { ArgusThisSrv.status = RA_SVCFAILED; } else { ArgusThisSrv.status = RA_SVCPASSED; } } RaProcessSrvRecord (&ArgusThisSrv); } void RaProcessUDPRecord (struct ArgusRecord *argus) { int srccount, dstcount; ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; srccount = argus->argus_far.src.count; dstcount = argus->argus_far.dst.count; if (Vflag) if ((srccount == 0) || (dstcount == 0)) ArgusThisSrv.status = RA_SVCFAILED; if (argus->argus_far.flow.ip_flow.tp_p == ARGUS_RTP_FLOWTAG) if (!((argus->argus_far.src.count > 3) || (argus->argus_far.dst.count > 3))) argus->argus_far.flow.ip_flow.tp_p = 0; if (Rflag) { struct ArgusAGRStruct *agr; if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) != NULL) { if (!((srccount == dstcount) && (srccount == agr->count))) ArgusThisSrv.status = RA_SVCFAILED; } else { if (!((srccount == 1) && (dstcount == 1))) ArgusThisSrv.status = RA_SVCFAILED; } } RaProcessSrvRecord (&ArgusThisSrv); } void RaProcessIPRecord (struct ArgusRecord *argus) { ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Vflag) { if ((argus->argus_far.src.count > 0) && (argus->argus_far.dst.count == 0)) { ArgusThisSrv.status = RA_SVCFAILED; } else { ArgusThisSrv.status = RA_SVCPASSED; } } if (Rflag) if (!((argus->argus_far.src.count == 1) && (argus->argus_far.dst.count == 1))) ArgusThisSrv.status = RA_SVCFAILED; RaProcessSrvRecord (&ArgusThisSrv); } void RaProcessARPRecord (struct ArgusRecord *argus) { ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Rflag) if (!((argus->argus_far.src.count == 1) && (argus->argus_far.dst.count == 1))) ArgusThisSrv.status = RA_SVCFAILED; RaProcessSrvRecord (&ArgusThisSrv); } void RaProcessNonIPRecord (struct ArgusRecord *argus) { ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; RaProcessSrvRecord (&ArgusThisSrv); } #include #include void RaAdjustArray(struct RaBinStruct **); void RaAdjustArray(struct RaBinStruct **array) { struct ArgusRecord argusbuf, *argus = &argusbuf; int i, start; if (array[0] == NULL) { for (i = 0, start = 0; i < RaBinCount; i++) { if (array[i] != NULL) { start = i; break; } } if (start > 0) { for (i = 0; i < RaBinCount; i++) { array[i] = array[i + 1]; } } RaStartTime.tv_sec += RaBinSize; RaStartSeconds = RaStartTime.tv_sec; bzero((char *)argus, sizeof(*argus)); argus->ahdr.type = ARGUS_FAR; argus->ahdr.length = sizeof(*argus); argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); argus->argus_far.time.start.tv_sec = RaStartSeconds + (RaBinSize * RaBinCount); argus->argus_far.time.last.tv_sec = RaStartSeconds + (RaBinSize * (RaBinCount + 1)); if ((array[RaBinCount] = RaNewBin (argus)) == NULL) { ArgusLog (LOG_ERR, "RaProcessRecord() RaNewBin %s\n", strerror(errno)); } else { array[RaBinCount]->status |= RA_MODIFIED; array[RaBinCount]->timeout = RaHoldTime; } RaEndTime.tv_sec += RaBinSize; RaEndSeconds = RaEndTime.tv_sec; } } void RaSendBlank(void); #define RA_MAXQSCAN 25600 #define RA_MAXQSIZE 250000 void RaProcessArray(struct RaBinStruct **array, unsigned char status) { struct RaBinStruct *bin = NULL; int cnt = 0, i, retn; if (!(RaStreamMode)) RaSortAlgorithms[0] = RaSortAlgorithmTable[RASORTPKTSCOUNT]; else RaSortAlgorithms[0] = RaSortAlgorithmTable[RASORTSTARTTIME]; if (array != NULL) { switch (status) { case ARGUS_STOP: if (!(Sflag || Cflag || Bflag || Hflag)) { if (startime_t > 0) { if (startime_t < RaStartPoint.tv_sec) { RaStartPoint.tv_sec = startime_t; } if (lasttime_t > RaEndPoint.tv_sec) { RaEndPoint.tv_sec = lasttime_t; } } } for (i = 0; i < RaBinCount; i++) { if ((bin = array[i]) != NULL) { if (Hflag) { } if ((bin->start.tv_sec >= RaStartPoint.tv_sec) && (bin->end.tv_sec <= RaEndPoint.tv_sec)) { RaSortQueue(bin->queue); RaProcessQueue(bin->queue, ARGUS_STOP); } RaDeleteBin (bin); array[i] = NULL; } else { RaSendBlank(); } RaStartTime.tv_sec += RaBinSize; RaStartSeconds = RaStartTime.tv_sec; cnt++; } break; default: { if (array[0] == NULL) RaAdjustArray(array); while (((bin = array[0]) != NULL) && ((retn = RaBinsCheckTimeout(bin, NULL)) > 0)) { RaSortQueue(bin->queue); RaProcessQueue(bin->queue, ARGUS_STOP); RaDeleteBin (bin); array[0] = NULL; RaAdjustArray(array); } } break; } } #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessArray (0x%x, %d) returning\n", array, status); #endif } extern struct ArgusCanonicalRecord *RaThisCanon; int RaSendArgusRecord(struct ArgusRecordStore *store) { unsigned char buf[MAXSTRLEN]; struct ArgusRecordData *data; struct ArgusRecord *argus = NULL; struct ArgusFarHeaderStruct *farhdr; struct ArgusFlow *flow = NULL; struct ArgusAGRStruct *agr = NULL; int i, retn = 1; for (i = 0; i < RaHistoTimeSeries; i++) { if ((data = store->data[i]) != NULL) { argus = data->argus; if ((argus->argus_far.src.count + argus->argus_far.dst.count) != 0) { if (aflag == 0) { #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif ArgusGenerateCanonicalRecord (argus, RaThisCanon); #ifdef _LITTLE_ENDIAN ArgusNtoH(argus); #endif if (argus_filter (ArgusFilterCode.bf_insns, RaThisCanon) == 0) return 0; } } if (argus && (data->status & RA_MODIFIED)) { if (data->act.n > 0) { data->agr.act.n = data->act.n; data->agr.act.meanval = data->act.sumtime/data->act.n; data->agr.act.stdev = sqrt (data->act.sumsqrd/data->act.n - pow (data->act.sumtime/data->act.n, 2.0)); } if (data->idle.n > 0) { data->agr.idle.n = data->idle.n; data->agr.idle.meanval = data->idle.sumtime/data->idle.n; data->agr.idle.stdev = sqrt (data->idle.sumsqrd/data->idle.n - pow (data->idle.sumtime/data->idle.n, 2.0)); } ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) != NULL) { bcopy ((char *)&data->agr, (char *)agr, data->agr.length); } else { bcopy ((char *) argus, buf, argus->ahdr.length); argus = (struct ArgusRecord *) buf; ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); bcopy ((char *)&data->agr, &buf[argus->ahdr.length], data->agr.length); argus->ahdr.length += data->agr.length; argus->ahdr.status |= ARGUS_MERGED; ArgusFree (data->argus); data->argus = RaCopyArgusRecord(argus); ArgusThisFarStatus = ArgusIndexRecord(data->argus, ArgusThisFarHdrs); } flow = &argus->argus_far.flow; if (!(data->status & ARGUS_FAR_SRCADDR_MODIFIED)) flow->ip_flow.ip_src = data->flow.ip_flow.ip_src; if (!(data->status & ARGUS_FAR_DSTADDR_MODIFIED)) flow->ip_flow.ip_dst = data->flow.ip_flow.ip_dst; if (!(data->status & ARGUS_FAR_PROTO_MODIFIED)) flow->ip_flow.ip_p = data->flow.ip_flow.ip_p; if (!(data->status & ARGUS_FAR_SRCPORT_MODIFIED)) flow->ip_flow.sport = data->flow.ip_flow.sport; if (!(data->status & ARGUS_FAR_DSTPORT_MODIFIED)) flow->ip_flow.dport = data->flow.ip_flow.dport; if (!(data->status & ARGUS_FAR_TPVAL_MODIFIED)) flow->ip_flow.tp_p = data->flow.ip_flow.tp_p; if (!(RaStreamMode)) { argus->argus_far.time.start = store->startime; argus->argus_far.time.last = store->lasttime; } if (!(RaNoZeroMode) || (RaNoZeroMode && ((argus->argus_far.src.count + argus->argus_far.dst.count) > 0))) { if ((ArgusWfileList != NULL) && (!(ArgusListEmpty(ArgusWfileList)))) { struct ArgusWfileStruct *wfile = NULL, *start = NULL; if ((wfile = ArgusFrontList(ArgusWfileList)) != NULL) { start = wfile; do { if ((exceptfile == NULL) || strcmp(wfile->filename, exceptfile)) { #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif ArgusWriteNewLogfile (wfile, argus); #ifdef _LITTLE_ENDIAN ArgusNtoH(argus); #endif } ArgusPopFrontList(ArgusWfileList); ArgusPushBackList(ArgusWfileList, wfile); wfile = ArgusFrontList(ArgusWfileList); } while (wfile != start); } } else { if (argus->ahdr.type & ARGUS_MAR) printf ("%s\n", get_man_string (argus)); else { ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); if (Hflag) { RaThisActiveDuration = RaGetuSecAvgDuration(argus); for (i = 0; i < RaHistoTimeSeries; i++) { if (RaThisActiveDuration < RaHistoTimeValues[i]) { RaThisActiveIndex = i; break; } } printf ("%1.*f", pflag, (RaHistoStart + (RaThisActiveIndex + 1) * ((RaHistoEnd - RaHistoStart)/(RaHistoBins * 1.0)))/1000000.0); } switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: printf ("%s", get_tcp_string (argus)); break; case IPPROTO_ICMP: printf ("%s", get_icmp_string (argus)); break; default: printf ("%s", get_ip_string (argus)); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: printf ("%s", get_arp_string (argus)); break; default: printf ("%s", get_nonip_string (argus)); break; } printf ("\n"); } fflush (stdout); } } argus = data->argus; if (argus->ahdr.type & ARGUS_FAR) { int farlen, length = argus->ahdr.length - sizeof(argus->ahdr); farhdr = (struct ArgusFarHeaderStruct *)((char *)argus + sizeof(argus->ahdr)); while (length > 0) { switch (farhdr->type) { case ARGUS_FAR: { struct ArgusFarStruct *far = (struct ArgusFarStruct *) farhdr; far->time.start.tv_sec = 0x7FFFFFFF; far->time.start.tv_usec = 0; far->time.last.tv_sec = 0; far->time.last.tv_usec = 0; far->src.count = 0; far->src.bytes = 0; far->dst.count = 0; far->dst.bytes = 0; break; } case ARGUS_TCP_DSR: { struct ArgusTCPObject *tcp = (struct ArgusTCPObject *) farhdr; tcp->state = 0; tcp->src.seqbase = 0; tcp->src.ackbytes = 0; tcp->src.rpkts = 0; tcp->src.win = 0; tcp->src.flags = 0; tcp->dst.seqbase = 0; tcp->dst.ackbytes = 0; tcp->dst.rpkts = 0; tcp->dst.win = 0; tcp->dst.flags = 0; break; } case ARGUS_TIME_DSR: { struct ArgusTimeStruct *time = (struct ArgusTimeStruct *) farhdr; time->src.act.n = 0; time->src.act.meanval = 0; time->src.act.stdev = 0; time->src.act.maxval = 0; time->src.act.minval = 0x7FFFFFFF; time->src.idle.n = 0; time->src.idle.meanval = 0; time->src.idle.stdev = 0; time->src.idle.maxval = 0; time->src.idle.minval = 0x7FFFFFFF; time->dst.act.n = 0; time->dst.act.meanval = 0; time->dst.act.stdev = 0; time->dst.act.maxval = 0; time->dst.act.minval = 0x7FFFFFFF; time->dst.idle.n = 0; time->dst.idle.meanval = 0; time->dst.idle.stdev = 0; time->dst.idle.maxval = 0; time->dst.idle.minval = 0x7FFFFFFF; break; } case ARGUS_VLAN_DSR: { struct ArgusVlanStruct *vlan = (struct ArgusVlanStruct *) farhdr; vlan->status &= ~(ARGUS_SRC_CHANGED | ARGUS_DST_CHANGED); break; } case ARGUS_MPLS_DSR: { struct ArgusMplsStruct *mpls = (struct ArgusMplsStruct *) farhdr; mpls->status &= ~(ARGUS_SRC_CHANGED | ARGUS_DST_CHANGED); break; } case ARGUS_AGR_DSR: { struct ArgusAGRStruct *agr = (struct ArgusAGRStruct *) farhdr; agr->count = 0; agr->act.n = 0; agr->act.minval = 0x7FFFFFFF; agr->act.meanval = 0; agr->act.stdev = 0; agr->act.maxval = 0; agr->idle.n = 0; agr->idle.minval = 0x7FFFFFFF; agr->idle.meanval = 0; agr->idle.stdev = 0; agr->idle.maxval = 0; break; } } if ((farlen = farhdr->length) == 0) break; if ((farhdr->type == ARGUS_SRCUSRDATA_DSR) || (farhdr->type == ARGUS_DSTUSRDATA_DSR)) farlen = farlen * 4; length -= farlen; farhdr = (struct ArgusFarHeaderStruct *)((char *)farhdr + farlen); } } data->agr.count = 0; data->agr.act.n = 0; data->agr.act.meanval = 0; data->agr.act.stdev = 0; data->agr.act.maxval = 0; data->agr.act.minval = 0x7FFFFFFF; data->agr.idle.n = 0; data->agr.idle.meanval = 0; data->agr.idle.stdev = 0; data->agr.idle.maxval = 0; data->agr.idle.minval = 0x7FFFFFFF; data->act.n = 0; data->act.sumtime = 0; data->act.sumsqrd = 0; data->idle.n = 0; data->idle.sumtime = 0; data->idle.sumtime = 0; data->argus->ahdr.status &= ~ARGUS_MERGED; data->status &= ~RA_MODIFIED; } } } store->status &= ~RA_MODIFIED; store->qhdr.logtime = ArgusGlobalTime; #ifdef ARGUSDEBUG ArgusDebug (4, "RaSendArgusRecord(0x%x) done.\n", store); #endif return (retn); } #define RA_BASE_GMT_YEAR 70 void RaReInitializeMergeArray(int secs) { int offset, oldbin = RaBinCount, bins; if (secs < RaStartTime.tv_sec) { offset = secs - RaStartTime.tv_sec; RaStartTime.tv_sec = secs; *RaStartTmStruct = *localtime((time_t *) &RaStartTime.tv_sec); } else { offset = secs - RaEndTime.tv_sec; if (RaModeValue == RAONEBIN) { bins = 1; } else { bins = (offset/RaBinSize); } RaEndTime.tv_sec += (bins < 1000) ? (1000 * RaBinSize) : (bins * RaBinSize); *RaEndTmStruct = *localtime((time_t *) &RaEndTime.tv_sec); } switch (RaModeValue) { case RASECONDS: { if (offset < 0) { RaStartTmStruct->tm_sec = ((RaStartTmStruct->tm_sec/dflag)*dflag); } else { RaEndTmStruct->tm_sec = ((RaEndTmStruct->tm_sec/dflag)*dflag); } break; } case RAMINUTE: { if (offset < 0) { RaStartTmStruct->tm_sec = 0; RaStartTmStruct->tm_min = ((RaStartTmStruct->tm_min/dflag)*dflag); } else { if (RaEndTmStruct->tm_sec > 0) { RaEndTmStruct->tm_sec = 0; if (++RaEndTmStruct->tm_min == 0) if (++RaEndTmStruct->tm_hour == 0) if (++RaEndTmStruct->tm_mday == 0) if (++RaEndTmStruct->tm_mon == 0) RaEndTmStruct->tm_year++; } } break; } case RAHOURLY: { if (offset < 0) { RaStartTmStruct->tm_sec = 0; RaStartTmStruct->tm_min = 0; RaStartTmStruct->tm_hour = ((RaStartTmStruct->tm_hour/dflag)*dflag); } else { if ((RaEndTmStruct->tm_sec > 0) || (RaEndTmStruct->tm_min > 0)) { RaEndTmStruct->tm_sec = 0; RaEndTmStruct->tm_min = 0; if (++RaEndTmStruct->tm_hour == 0) if (++RaEndTmStruct->tm_mday == 0) if (++RaEndTmStruct->tm_mon == 0) RaEndTmStruct->tm_year++; } } break; } case RADAILY: { if (offset < 0) { RaStartTmStruct->tm_sec = 0; RaStartTmStruct->tm_min = 0; RaStartTmStruct->tm_hour = 0; } else { if ((RaEndTmStruct->tm_sec > 0) || (RaEndTmStruct->tm_min > 0) || (RaEndTmStruct->tm_hour > 0)) { RaEndTmStruct->tm_sec = 0; RaEndTmStruct->tm_min = 0; RaEndTmStruct->tm_hour = 0; if (++RaEndTmStruct->tm_mday == 0) if (++RaEndTmStruct->tm_mon == 0) RaEndTmStruct->tm_year++; } } break; } /* case RAWEEKLY: { if ((RaEndTmStruct->tm_sec > 0) || (RaEndTmStruct->tm_min > 0) || (RaEndTmStruct->tm_hour > 0) || (RaEndTmStruct->tm_{ if (++RaEndTmStruct->tm_mday == 0) if (++RaThisTmStruct->tm_mon == 0) RaThisTmStruct->tm_year++; } break; } */ case RAMONTHLY: { if (offset < 0) { RaStartTmStruct->tm_sec = 0; RaStartTmStruct->tm_min = 0; RaStartTmStruct->tm_hour = 0; RaStartTmStruct->tm_mday = 0; } else { if ((RaEndTmStruct->tm_sec > 0) || (RaEndTmStruct->tm_min > 0) || (RaEndTmStruct->tm_hour > 0) || (RaEndTmStruct->tm_mday > 0)) { RaEndTmStruct->tm_sec = 0; RaEndTmStruct->tm_min = 0; RaEndTmStruct->tm_hour = 0; RaEndTmStruct->tm_mday = 0; if (++RaEndTmStruct->tm_mon == 0) RaEndTmStruct->tm_year++; } } break; } case RANNUALY: { if (offset < 0) { RaStartTmStruct->tm_sec = 0; RaStartTmStruct->tm_min = 0; RaStartTmStruct->tm_hour = 0; RaStartTmStruct->tm_mday = 0; RaStartTmStruct->tm_mon = 0; } else { if ((RaEndTmStruct->tm_sec > 0) || (RaEndTmStruct->tm_min > 0) || (RaEndTmStruct->tm_hour > 0) || (RaEndTmStruct->tm_mday > 0) || (RaThisTmStruct->tm_mon > 0)) { RaEndTmStruct->tm_sec = 0; RaEndTmStruct->tm_min = 0; RaEndTmStruct->tm_hour = 0; RaEndTmStruct->tm_mday = 0; RaEndTmStruct->tm_mon = 0; RaEndTmStruct->tm_year++; } } break; } case RAONEBIN: { break; } } if (offset < 0) { RaStartSeconds = mktime(RaStartTmStruct); RaStartTime.tv_sec = RaStartSeconds; } else { RaEndSeconds = mktime(RaEndTmStruct); RaEndTime.tv_sec = RaEndSeconds; RaSeconds = RaEndTime.tv_sec - RaStartTime.tv_sec; } *RaThisTmStruct = *localtime((time_t *) &RaSeconds); if ((Nflag == 0)) { RaScaleSeconds = RaEndSeconds - RaStartSeconds; if (RaModeValue == RAONEBIN) { RaBinCount = 1; } else { RaBinCount = (RaScaleSeconds/RaBinSize); } } else { RaBinCount = Nflag; RaEndSeconds = RaStartSeconds + (Nflag * RaBinSize); RaScaleSeconds = RaEndSeconds - RaStartSeconds; } RaBinOldMergeArray = RaBinMergeArray; if ((RaBinMergeArray = (struct RaBinStruct **) ArgusCalloc (sizeof(void *), (RaBinCount + 1))) == NULL) { ArgusLog (LOG_ERR, "RaInitializeMergeArray() ArgusCalloc %s\n", strerror(errno)); } else { int i, cnt = (offset < 0) ? oldbin - RaBinCount : RaBinCount - oldbin; for (i = 0; i < oldbin; i++) { struct ArgusRecord argusbuf, *argus = &argusbuf; if (((cnt < 0) && (i < -cnt)) || ((cnt > 0) && (i > (RaBinCount - cnt)))) { bzero((char *)argus, sizeof(*argus)); argus->ahdr.type = ARGUS_FAR; argus->ahdr.length = sizeof(*argus); argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); argus->argus_far.time.start.tv_sec = RaStartSeconds + (RaBinSize * i); argus->argus_far.time.last.tv_sec = RaStartSeconds + (RaBinSize * (i + 1)); if ((RaBinMergeArray[i] = RaNewBin (argus)) == NULL) { ArgusLog (LOG_ERR, "RaInitializeMergeArray() RaNewArgusStore %s\n", strerror(errno)); } else { RaBinMergeArray[i]->status |= RA_MODIFIED; RaBinMergeArray[i]->timeout = RaHoldTime; } } else { RaBinMergeArray[i] = RaBinOldMergeArray[i + ((cnt < 0) ? cnt : 0)]; } } } ArgusFree(RaBinOldMergeArray); } void RaInitializeMergeArray() { double RaBinSeconds; short intervalTime; int reportTime; RaStartTime.tv_usec = 0; if (RaEndTime.tv_usec > 0) { RaEndTime.tv_sec++; RaEndTime.tv_usec = 0; } if (startime_t > 0) { if (RaStartTime.tv_sec > startime_t) RaStartTime.tv_sec = startime_t; if (RaEndTime.tv_sec < lasttime_t) RaEndTime.tv_sec = lasttime_t; } *RaStartTmStruct = *localtime((time_t *) &RaStartTime.tv_sec); *RaEndTmStruct = *localtime((time_t *) &RaEndTime.tv_sec); switch (RaModeValue) { case RASECONDS: { RaStartTmStruct->tm_sec = ((RaStartTmStruct->tm_sec/dflag)*dflag); RaBinSize = 1.0 * dflag; break; } case RAMINUTE: { RaStartTmStruct->tm_sec = 0; RaStartTmStruct->tm_min = ((RaStartTmStruct->tm_min/dflag)*dflag); if (RaEndTmStruct->tm_sec > 0) { RaEndTmStruct->tm_sec = 0; if (++RaEndTmStruct->tm_min == 0) if (++RaEndTmStruct->tm_hour == 0) if (++RaEndTmStruct->tm_mday == 0) if (++RaEndTmStruct->tm_mon == 0) RaEndTmStruct->tm_year++; } RaBinSize = 60.0 * dflag; break; } case RAHOURLY: { RaStartTmStruct->tm_sec = 0; RaStartTmStruct->tm_min = 0; RaStartTmStruct->tm_hour = ((RaStartTmStruct->tm_hour/dflag)*dflag); if ((RaEndTmStruct->tm_sec > 0) || (RaEndTmStruct->tm_min > 0)) { RaEndTmStruct->tm_sec = 0; RaEndTmStruct->tm_min = 0; if (++RaEndTmStruct->tm_hour == 0) if (++RaEndTmStruct->tm_mday == 0) if (++RaEndTmStruct->tm_mon == 0) RaEndTmStruct->tm_year++; } RaBinSize = 3600.0 * dflag; break; } case RADAILY: { RaStartTmStruct->tm_sec = 0; RaStartTmStruct->tm_min = 0; RaStartTmStruct->tm_hour = 0; if ((RaEndTmStruct->tm_sec > 0) || (RaEndTmStruct->tm_min > 0) || (RaEndTmStruct->tm_hour > 0)) { RaEndTmStruct->tm_sec = 0; RaEndTmStruct->tm_min = 0; RaEndTmStruct->tm_hour = 0; if (++RaEndTmStruct->tm_mday == 0) if (++RaEndTmStruct->tm_mon == 0) RaEndTmStruct->tm_year++; } RaBinSize = 3600.0 * 24.0 * dflag; break; } /* case RAWEEKLY: { if ((RaEndTmStruct->tm_sec > 0) || (RaEndTmStruct->tm_min > 0) || (RaEndTmStruct->tm_hour > 0) || (RaEndTmStruct->tm_{ if (++RaEndTmStruct->tm_mday == 0) if (++RaThisTmStruct->tm_mon == 0) RaThisTmStruct->tm_year++; } RaBinSize = 3600.0 * 24.0; break; } */ case RAMONTHLY: { RaStartTmStruct->tm_sec = 0; RaStartTmStruct->tm_min = 0; RaStartTmStruct->tm_hour = 0; RaStartTmStruct->tm_mday = 0; if ((RaEndTmStruct->tm_sec > 0) || (RaEndTmStruct->tm_min > 0) || (RaEndTmStruct->tm_hour > 0) || (RaEndTmStruct->tm_mday > 0)) { RaEndTmStruct->tm_sec = 0; RaEndTmStruct->tm_min = 0; RaEndTmStruct->tm_hour = 0; RaEndTmStruct->tm_mday = 0; if (++RaEndTmStruct->tm_mon == 0) RaEndTmStruct->tm_year++; } RaBinSize = 3600.0 * 24.0 * 30 * dflag; break; } case RANNUALY: { RaStartTmStruct->tm_sec = 0; RaStartTmStruct->tm_min = 0; RaStartTmStruct->tm_hour = 0; RaStartTmStruct->tm_mday = 0; RaStartTmStruct->tm_mon = 0; if ((RaEndTmStruct->tm_sec > 0) || (RaEndTmStruct->tm_min > 0) || (RaEndTmStruct->tm_hour > 0) || (RaEndTmStruct->tm_mday > 0) || (RaThisTmStruct->tm_mon > 0)) { RaEndTmStruct->tm_sec = 0; RaEndTmStruct->tm_min = 0; RaEndTmStruct->tm_hour = 0; RaEndTmStruct->tm_mday = 0; RaEndTmStruct->tm_mon = 0; RaEndTmStruct->tm_year++; } RaBinSize = 3600.0 * 24.0 * 30 * 12 * dflag; break; } case RAONEBIN: { RaBinSize = 0.0; break; } } if ((intervalTime = ntohs(ArgusInput->ArgusInitCon.argus_mar.reportInterval)) > 0) reportTime = intervalTime * 3; else reportTime = RaBinSize * 3; if (Bflag) RaHoldTime = Bflag; else RaHoldTime = 0; if (RaStartTime.tv_sec) { RaStartSeconds = mktime(RaStartTmStruct); RaStartTime.tv_sec = RaStartSeconds; } if (RaEndTime.tv_sec == 0) { RaEndTime.tv_usec = 0; if (RaModeValue == RAONEBIN) { RaBinCount = 1; RaEndTime.tv_sec = RaStartTime.tv_sec; } else { RaBinCount = 1000 + (RaBinSize + RaHoldTime)/RaBinSize; RaEndTime.tv_sec = RaStartTime.tv_sec + RaBinCount * RaBinSize; } *RaEndTmStruct = *localtime((time_t *) &RaEndTime.tv_sec); } RaEndSeconds = mktime(RaEndTmStruct); RaEndTime.tv_sec = RaEndSeconds; RaSeconds = RaEndTime.tv_sec - RaStartTime.tv_sec; *RaThisTmStruct = *localtime((time_t *) &RaSeconds); if ((Nflag == 0)) { RaScaleSeconds = RaEndSeconds - RaStartSeconds; if (RaModeValue == RAONEBIN) { RaBinCount = 1; } else { RaBinCount = (RaScaleSeconds + (RaBinSize - 1))/RaBinSize; } } else { RaBinCount = Nflag; RaEndSeconds = RaStartSeconds + (Nflag * RaBinSize); RaScaleSeconds = RaEndSeconds - RaStartSeconds; } if ((RaBinMergeArray = (struct RaBinStruct **) ArgusCalloc (sizeof(void *), (RaBinCount + 1))) == NULL) { ArgusLog (LOG_ERR, "RaInitializeMergeArray() ArgusCalloc %s\n", strerror(errno)); } else { int i; for (i = 0; i < RaBinCount; i++) { struct ArgusRecord argusbuf, *argus = &argusbuf; bzero((char *)argus, sizeof(*argus)); argus->ahdr.type = ARGUS_FAR; argus->ahdr.length = sizeof(*argus); argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); argus->argus_far.time.start.tv_sec = RaStartSeconds + (RaBinSize * i); argus->argus_far.time.last.tv_sec = RaStartSeconds + (RaBinSize * (i + 1)); if ((RaBinMergeArray[i] = RaNewBin (argus)) == NULL) { ArgusLog (LOG_ERR, "RaInitializeMergeArray() RaNewArgusStore %s\n", strerror(errno)); } else { RaBinMergeArray[i]->status |= RA_MODIFIED; RaBinMergeArray[i]->timeout = RaHoldTime; } } } modf(RaBinSize, &RaBinSeconds); if (RaBinSize != RaBinSeconds) RaBinSize = RaBinSeconds + 1.0; #ifdef ARGUSDEBUG ArgusDebug (3, "RaInitializeMergeArray(0x%x) RaStartTime %d RaBinSize %f.\n", RaStartTime.tv_sec, RaBinSize); #endif } int RaQueueCount = 0; int RaAdjustBinCount = 0; int RaAdjustLastBinCount = 0; float RaSrcPeriod = 0.0; float RaDstPeriod = 0.0; struct ArgusRecord * RaAdjustArgusRecord (struct ArgusRecord *argus) { struct ArgusRecord *retn = NULL; if (RaNumBlanks > 0) { struct timeval tvpbuf, *tvp = &tvpbuf; retn = RaCopyArgusRecord (argus); ArgusZeroRecord (retn); *tvp = argus->argus_far.time.start; retn->argus_far.time.start = *tvp; tvp->tv_usec = 0; tvp->tv_sec += RaBinSize; retn->argus_far.time.last = *tvp; argus->argus_far.time.start = *tvp; RaNumBlanks--; return (retn); } if ((argus->argus_far.src.count != 0) || (argus->argus_far.dst.count != 0)) { struct timeval tvpbuf, *tvp = &tvpbuf; struct ArgusTCPObject *tcp = NULL, *rtcp = NULL; float startsec = 0.0, duration = 0.0, thisduration = 0.0, actduration = 0.0; int timeindex = 0, count = 0, bytes = 0, srcABpp, srcBpp, dstABpp, dstBpp, thisCount; struct ArgusAGRStruct *agr; double RaBinSeconds; ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) tcp = (struct ArgusTCPObject *) ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]; startsec = (float)(argus->argus_far.time.start.tv_sec - RaStartSeconds) + (argus->argus_far.time.start.tv_usec/1000000.0); duration = (float)((argus->argus_far.time.last.tv_sec - argus->argus_far.time.start.tv_sec) + (argus->argus_far.time.last.tv_usec - argus->argus_far.time.start.tv_usec)/1000000.0); if (startsec < 0.0) { if (argus->argus_far.time.last.tv_sec < RaStartSeconds) return (retn); thisduration = (float)((argus->argus_far.time.last.tv_sec - RaStartSeconds) + (argus->argus_far.time.last.tv_usec)/1000000.0); if (argus->argus_far.src.count) { srcABpp = (argus->argus_far.src.appbytes * thisduration)/duration; srcBpp = (argus->argus_far.src.bytes * thisduration)/duration; thisCount = (argus->argus_far.src.count * thisduration)/duration; argus->argus_far.src.count = thisCount; argus->argus_far.src.bytes = srcBpp; argus->argus_far.src.appbytes = srcABpp; if (tcp != NULL) { tcp->src.ackbytes = (tcp->src.ackbytes * thisduration)/duration; tcp->src.bytes = (tcp->src.bytes * thisduration)/duration; tcp->src.rpkts = (tcp->src.rpkts * thisduration)/duration; } } if (argus->argus_far.dst.count) { dstABpp = (argus->argus_far.dst.appbytes * thisduration)/duration; dstBpp = (argus->argus_far.dst.bytes * thisduration)/duration; thisCount = (argus->argus_far.dst.count * thisduration)/duration; argus->argus_far.dst.count = thisCount; argus->argus_far.dst.bytes = dstBpp; argus->argus_far.dst.appbytes = dstABpp; if (tcp != NULL) { tcp->dst.ackbytes = (tcp->dst.ackbytes * thisduration)/duration; tcp->dst.bytes = (tcp->dst.bytes * thisduration)/duration; tcp->dst.rpkts = (tcp->dst.rpkts * thisduration)/duration; } } duration -= thisduration; startsec = 0.0; argus->argus_far.time.start.tv_sec = RaStartSeconds; argus->argus_far.time.start.tv_usec = 0; } if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) != NULL) { int ArgusThisMultiplier = 1000; if (agr->status & ARGUS_AGR_USECACTTIME) ArgusThisMultiplier = 1000000; if (agr->act.n) actduration = agr->act.meanval / ArgusThisMultiplier; retn = RaCopyArgusRecord (argus); } else { struct ArgusAGRStruct agrbuf; char buf[0x10000]; agr = &agrbuf; bzero ((char *) agr, sizeof(*agr)); bzero ((char *) buf, (argus->ahdr.length + sizeof(*agr) + 1)); agr->laststartime = argus->argus_far.time.start; agr->lasttime = argus->argus_far.time.last; agr->type = ARGUS_AGR_DSR; agr->length = sizeof(*agr); agr->act.maxval = RaThisActiveDuration; agr->act.minval = RaThisActiveDuration; agr->act.meanval = RaThisActiveDuration; agr->act.n = 1; agr->count = 1; agr->idle.minval = 0x7FFFFFFF; agr->status |= ARGUS_AGR_USECACTTIME; agr->status |= ARGUS_AGR_USECIDLETIME; bcopy ((char *) argus, buf, argus->ahdr.length); retn = (struct ArgusRecord *) buf; bcopy ((char *)agr, &buf[retn->ahdr.length], agr->length); retn->ahdr.length += agr->length; retn = RaCopyArgusRecord (retn); } ArgusThisFarStatus = ArgusIndexRecord(retn, ArgusThisFarHdrs); if ((RaModeValue == RAONEBIN) || Hflag) { ArgusZeroRecord (argus); } else { timeindex = (int) (startsec/RaBinSize); if ((duration > 0.0) && ((startsec + duration) > (RaBinSize * (timeindex + 1)))) { /* we span out of this bin */ if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) rtcp = (struct ArgusTCPObject *) ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]; if ((count = (retn->argus_far.src.count + retn->argus_far.dst.count)) == 2) { if (actduration == 0.0) { startsec = (RaBinSize * (timeindex + 1)); /* where is the start of the next bin */ modf(startsec, &RaBinSeconds); /* where is the start of the next bin */ tvp->tv_sec = RaBinSeconds + RaStartSeconds; tvp->tv_usec = (int)((startsec - RaBinSeconds)*1000000); if (tvp->tv_usec >= 1000000) { tvp->tv_sec++; tvp->tv_usec -= 1000000; } } else { modf(actduration, &RaBinSeconds); /* where is the start of the next bin */ tvp->tv_sec = RaBinSeconds + retn->argus_far.time.start.tv_sec; tvp->tv_usec = (int)((startsec - RaBinSeconds)*1000000) + retn->argus_far.time.start.tv_usec; if (tvp->tv_usec >= 1000000) { tvp->tv_sec++; tvp->tv_usec -= 1000000; } } if (RaSrcPeriod == RaDstPeriod) { retn->argus_far.time.last = *tvp; /* this is the new end for this record */ argus->argus_far.time.start = *tvp; } else { retn->argus_far.time.last = retn->argus_far.time.start; argus->argus_far.time.start = argus->argus_far.time.last; if (retn->argus_far.src.count) { if (retn->argus_far.src.count == 1) { retn->argus_far.dst.count = 0; retn->argus_far.dst.bytes = 0; } else { retn->argus_far.src.count = 1; bytes = retn->argus_far.src.bytes; retn->argus_far.src.bytes /= 2; if (bytes & 0x01) retn->argus_far.src.bytes += 1; } } else { retn->argus_far.dst.count = 1; bytes = retn->argus_far.dst.bytes; retn->argus_far.dst.bytes /= 2; if (bytes & 0x01) retn->argus_far.dst.bytes += 1; } } argus->argus_far.src.count -= retn->argus_far.src.count; argus->argus_far.dst.count -= retn->argus_far.dst.count; argus->argus_far.src.bytes -= retn->argus_far.src.bytes; argus->argus_far.dst.bytes -= retn->argus_far.dst.bytes; } else { if (RaAdjustCount == 0) { RaAdjustBinCount = 0; RaAdjustLastBinCount = 0; } startsec = (RaBinSize * (timeindex + 1)); /* where is the start of the next bin */ modf(startsec, &RaBinSeconds); /* where is the start of the next bin */ tvp->tv_sec = RaBinSeconds + RaStartSeconds; tvp->tv_usec = (int)((startsec - RaBinSeconds)*1000000); if (tvp->tv_usec >= 1000000) { tvp->tv_sec++; tvp->tv_usec -= 1000000; } retn->argus_far.time.last = *tvp; /* this is the new end for this record */ if (((argus->argus_far.time.last.tv_sec - argus->argus_far.time.start.tv_sec) == 1) && ((argus->argus_far.time.last.tv_usec - argus->argus_far.time.start.tv_usec) == 0)) { thisduration = 1.0; } else { thisduration = (float)(((retn->argus_far.time.last.tv_sec - retn->argus_far.time.start.tv_sec) * 1.0) + (retn->argus_far.time.last.tv_usec - retn->argus_far.time.start.tv_usec)/1000000.0); } if ((count = (retn->argus_far.src.count > retn->argus_far.dst.count) ? retn->argus_far.src.count : retn->argus_far.dst.count) > 0) { if ((duration / count) > RaBinSize) { /* we've got fewer pkts than bins */ startsec = (duration/count); /* where is the start of the next bin (round up)*/ modf(startsec, &RaBinSeconds); /* where is the start of the next bin */ RaNumBlanks = (duration/count)/RaBinSize; } else { RaBinSeconds = RaBinSize; } } argus->argus_far.time.start = *tvp; if (argus->argus_far.src.count) { thisCount = (argus->argus_far.src.count * (thisduration /duration)); if (thisCount > argus->argus_far.src.count) thisCount = argus->argus_far.src.count; if ((thisCount == 0) && (argus->argus_far.src.count > 1)) { thisCount = 1; } retn->argus_far.src.count = thisCount; if (retn->argus_far.src.count == argus->argus_far.src.count) { srcBpp = argus->argus_far.src.bytes; srcABpp = argus->argus_far.src.appbytes; } else { if (retn->argus_far.src.count > 0) { srcBpp = (argus->argus_far.src.bytes * (thisduration / duration)); srcABpp = (argus->argus_far.src.appbytes * (thisduration / duration)); } else { srcBpp = 0; srcABpp = 0; } } retn->argus_far.src.bytes = srcBpp; retn->argus_far.src.appbytes = srcABpp; if ((tcp != NULL) && (rtcp != NULL)) { rtcp->src.ackbytes = (rtcp->src.ackbytes * (thisduration / duration)); rtcp->src.bytes = (rtcp->src.bytes * (thisduration / duration)); rtcp->src.rpkts = (rtcp->src.rpkts * (thisduration / duration)); } } if (argus->argus_far.dst.count) { thisCount = (argus->argus_far.dst.count * (thisduration /duration)); if (thisCount > argus->argus_far.dst.count) thisCount = argus->argus_far.dst.count; if ((thisCount == 0) && (argus->argus_far.dst.count > 1)) thisCount = 1; retn->argus_far.dst.count = thisCount; if (retn->argus_far.dst.count == argus->argus_far.dst.count) { dstABpp = argus->argus_far.dst.appbytes; dstBpp = argus->argus_far.dst.bytes; } else { if (retn->argus_far.dst.count > 0) { dstABpp = (argus->argus_far.dst.appbytes * (thisduration /duration)); dstBpp = (argus->argus_far.dst.bytes * (thisduration /duration)); } else { dstABpp = 0; dstBpp = 0; } } retn->argus_far.dst.bytes = dstBpp; retn->argus_far.dst.appbytes = dstABpp; if ((tcp != NULL) && (rtcp != NULL)) { rtcp->dst.ackbytes = (rtcp->dst.ackbytes * (thisduration /duration)); rtcp->dst.bytes = (rtcp->dst.bytes * (thisduration /duration)); rtcp->dst.rpkts = (rtcp->dst.rpkts * (thisduration /duration)); } } argus->argus_far.src.count -= retn->argus_far.src.count; argus->argus_far.dst.count -= retn->argus_far.dst.count; argus->argus_far.src.bytes -= retn->argus_far.src.bytes; argus->argus_far.dst.bytes -= retn->argus_far.dst.bytes; argus->argus_far.src.appbytes -= retn->argus_far.src.appbytes; argus->argus_far.dst.appbytes -= retn->argus_far.dst.appbytes; if ((tcp != NULL) && (rtcp != NULL)) { tcp->src.ackbytes -= rtcp->src.ackbytes; tcp->src.bytes -= rtcp->src.bytes; tcp->src.rpkts -= rtcp->src.rpkts; tcp->dst.ackbytes -= rtcp->dst.ackbytes; tcp->dst.bytes -= rtcp->dst.bytes; tcp->dst.rpkts -= rtcp->dst.rpkts; } } } else { startsec = (RaBinSize * timeindex); /* where is the start of the current bin */ modf(startsec, &RaBinSeconds); /* where is the start of the current bin */ tvp->tv_sec = RaBinSeconds + RaStartSeconds; tvp->tv_usec = 0; tvp->tv_usec = (int)((startsec - RaBinSeconds)*1000000); if (tvp->tv_usec >= 1000000) { tvp->tv_sec++; tvp->tv_usec -= 1000000; } retn->argus_far.time.start = *tvp; /* this is the new start for this record */ startsec = (RaBinSize * (timeindex + 1)); /* where is the start of the next bin */ modf(startsec, &RaBinSeconds); /* where is the start of the next bin */ tvp->tv_sec = RaBinSeconds + RaStartSeconds; tvp->tv_usec = 0; tvp->tv_usec = (int)((startsec - RaBinSeconds)*1000000); if (tvp->tv_usec >= 1000000) { tvp->tv_sec++; tvp->tv_usec -= 1000000; } retn->argus_far.time.last = *tvp; /* this is the new end for this record */ argus->argus_far.src.count = 0; argus->argus_far.dst.count = 0; } } } return(retn); } void RaModifyEtherFlow (struct ArgusRecord *argus) { struct ArgusFlow *flow = &argus->argus_far.flow; bzero ((char *) &flow->mac_flow.ehdr.ether_dhost, 6); } int RaCreateEtherFlow (struct ArgusRecord *argus) { struct ArgusFlow *flow = &argus->argus_far.flow; struct ArgusMacStruct *mac = NULL; struct ArgusETHERObject *ether = NULL; int retn = 0; if (ArgusThisFarStatus & ARGUS_MAC_DSR_STATUS) { if ((mac = (struct ArgusMacStruct *) ArgusThisFarHdrs[ARGUS_MAC_DSR_INDEX]) != NULL) { ether = &mac->ether_mac; bzero ((char *) flow, sizeof(*flow)); bcopy ((char *) ether, (char *) &flow->mac_flow.ehdr, 12); argus->ahdr.status &= ~0xFFFF; retn++; } } return (retn); } struct ArgusRecord * RaRmonArgusRecord (struct ArgusRecord *argus) { struct ArgusRecord *retn = NULL; struct ArgusMeter meter; struct ArgusFlow *flow1, *flow2; struct ArgusFarHeaderStruct *a1farhdr[32], *a2farhdr[32]; unsigned int a1DSRStatus = 0, a2DSRStatus = 0; if (RaPrintMACAddress) if (!(RaCreateEtherFlow (argus))) return (retn); if ((retn = RaCopyArgusRecord (argus)) != NULL) { a1DSRStatus = ArgusIndexRecord (argus, a1farhdr); a2DSRStatus = ArgusIndexRecord (retn, a2farhdr); flow1 = &argus->argus_far.flow; flow2 = &retn->argus_far.flow; switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: flow2->ip_flow.ip_src = flow1->ip_flow.ip_dst; flow2->ip_flow.ip_dst = flow1->ip_flow.ip_src; switch (flow1->ip_flow.ip_p) { case IPPROTO_UDP: case IPPROTO_TCP: break; } meter = argus->argus_far.src; argus->argus_far.src = argus->argus_far.dst; argus->argus_far.dst = meter; break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: break; default: bcopy ((char *)&flow1->mac_flow.ehdr.ether_dhost, (char *)&flow2->mac_flow.ehdr.ether_shost, 6); bzero ((char *)&flow1->mac_flow.ehdr.ether_dhost, 6); bzero ((char *)&flow2->mac_flow.ehdr.ether_dhost, 6); meter = retn->argus_far.src; retn->argus_far.src = retn->argus_far.dst; retn->argus_far.dst = meter; break; } if ((a1DSRStatus & ARGUS_MAC_DSR_STATUS) && (a2DSRStatus & ARGUS_MAC_DSR_STATUS)) { struct ArgusMacStruct *mac1 = NULL, *mac2 = NULL; mac1 = (struct ArgusMacStruct *) a1farhdr[ARGUS_MAC_DSR_INDEX]; mac2 = (struct ArgusMacStruct *) a2farhdr[ARGUS_MAC_DSR_INDEX]; bcopy ((char *)&mac2->ether_mac.etherdst, (char *)&mac1->ether_mac.ethersrc, 6); bzero ((char *)&mac1->ether_mac.etherdst, 6); bzero ((char *)&mac2->ether_mac.etherdst, 6); } retn->ahdr.type |= ARGUS_RMON; argus->ahdr.type |= ARGUS_RMON; } return (retn); } struct RaBinStruct * RaNewBin(struct ArgusRecord *argus) { struct RaBinStruct *retn = NULL; if ((retn = (struct RaBinStruct *) ArgusCalloc (1, sizeof(*retn))) != NULL) { if ((retn->queue = RaNewQueue()) == NULL) ArgusLog (LOG_ERR, "RaMergeQueue: RaNewQueue error %s\n", strerror(errno)); if ((retn->hashtable.array = (struct RaHashTableHeader **) ArgusCalloc (RACRICKET_HASHTABLESIZE, sizeof (struct RaHashTableHeader *))) == NULL) { ArgusLog (LOG_ERR, "RaMergeQueue: ArgusCalloc error %s\n", strerror(errno)); } else { retn->hashtable.size = RACRICKET_HASHTABLESIZE; } if (argus != NULL) { retn->start = argus->argus_far.time.start; retn->end = argus->argus_far.time.last; } } else ArgusLog (LOG_ERR, "RaNewBin: ArgusCalloc error %s\n", strerror(errno)); return (retn); } void RaDeleteBin (struct RaBinStruct *bin) { struct ArgusRecordStore *obj = NULL; if (bin->queue) { while ((obj = (struct ArgusRecordStore *) RaPopQueue(bin->queue))) { if (obj->rahtblhdr) ArgusFree(obj->rahtblhdr); ArgusFree(obj); } ArgusFree(bin->queue); } if (bin->hashtable.array != NULL) ArgusFree(bin->hashtable.array); ArgusFree(bin); return; } int RaPrintHeader = 0; void RaProcessQueue(struct RaQueueStruct *queue, unsigned char status) { struct ArgusRecordStore *obj = NULL; struct ArgusRecord argusbuf, *argus = &argusbuf; struct ArgusRecordStore *srv = NULL; char stimebuf[128], dtimebuf[128]; strcpy (stimebuf, print_time(&RaStartPoint)); strcpy (dtimebuf, print_time(&RaEndPoint)); RaScaleSeconds = RaEndPoint.tv_sec - RaStartPoint.tv_sec; if (RaLabel == NULL) RaLabel = RaGenerateLabel(argus); if (ArgusWfileList == NULL) { if (RaPrintHeader++ == 0 ) { if (Gflag) { if (Hflag) { fprintf (stdout, "StartTime=%1.*f\n", pflag, (RaHistoStart/1000000.0)); fprintf (stdout, "StopTime=%1.*f\n", pflag, (RaHistoEnd/1000000.0)); fprintf (stdout, "Seconds=%d\n", RaScaleSeconds); } else { fprintf (stdout, "StartTime=%s\n", stimebuf); fprintf (stdout, "StopTime=%s\n", dtimebuf); fprintf (stdout, "Seconds=%d\n", RaScaleSeconds); } if (RaModeValue == RAONEBIN) { if (Hflag) { fprintf (stdout, "BinSize=%1.*f\n", pflag, (RaHistoEnd - RaHistoStart)/(RaHistoBins * 1000000.0)); fprintf (stdout, "Bins=%d\n", RaHistoBins); } else { fprintf (stdout, "BinSize=%d.00\n", (int)((RaEndPoint.tv_sec - RaStartPoint.tv_sec))); fprintf (stdout, "Bins=1\n"); } } else { fprintf (stdout, "BinSize=%f\n", RaBinSize); fprintf (stdout, "Bins=%d\n", (int)((RaEndPoint.tv_sec - RaStartPoint.tv_sec)/RaBinSize)); } bzero ((char *) RaSortAlgorithms, sizeof(RaSortAlgorithms)); if (Hflag) { fprintf (stdout, "Columns=BinTime,%s\n", RaLabel); } else { fprintf (stdout, "Columns=%s\n", RaLabel); switch (RaPrintMode) { case RA_PRINTSRCID: RaSortAlgorithms[0] = RaSortAlgorithmTable[RASORTSRCID]; RaSortQueue(RaProbeQueue); fprintf (stdout, "Probes="); while ((srv = (struct ArgusRecordStore *) RaPopQueue(RaProbeQueue)) != NULL) fprintf (stdout, "%s ", ipaddr_string((unsigned int *)&srv->rahtblhdr->object)); break; case RA_PRINTPROTO: { int i; RaSortAlgorithms[0] = RaSortAlgorithmTable[RASORTPROTOCOL]; RaSortQueue(RaProbeQueue); for (i = 0; i < RaProbeQueue->count; i++) { unsigned int proto; srv = (void *) RaProbeQueue->start; if ((proto = (unsigned int) srv->rahtblhdr->object) == IPPROTO_TCP) break; else RaProbeQueue->start = RaProbeQueue->start->nxt; } fprintf (stdout, "Protos="); while ((srv = (struct ArgusRecordStore *) RaPopQueue(RaProbeQueue)) != NULL) { unsigned int proto = (unsigned int) srv->rahtblhdr->object; fprintf (stdout, "%4.4s ", ip_proto_string[(unsigned short) proto]); } break; } } } fprintf (stdout, "\n"); } else { if (Lflag) { printf ("%s\n", RaLabel); fflush (stdout); } if (Lflag < 0) Lflag = 0; } } } switch (status) { default: { int cnt = 0; while ((obj = (struct ArgusRecordStore *) RaPopQueue(queue)) != NULL) { if (!(Sflag || Cflag || Bflag || Hflag)) { if ((argus = obj->data[RaThisActiveIndex]->argus) != NULL) { if ((argus->argus_far.time.start.tv_sec >= RaStartPoint.tv_sec) && (argus->argus_far.time.last.tv_sec <= RaEndPoint.tv_sec)) { if (RaTimeoutArgusStore(obj) != 0) cnt++; } } } else if (RaTimeoutArgusStore(obj) != 0) cnt++; } if (cnt == 0) RaSendBlank(); break; } } #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessQueue (0x%x, %d) returning\n", queue, status); #endif } void RaSendBlank(void) { struct ArgusRecord argusbuf, *argus = &argusbuf; struct ArgusRecordStore *srv = NULL; bzero((char *)argus, sizeof(*argus)); argus->ahdr.type = ARGUS_FAR; argus->ahdr.length = sizeof(*argus); if (!mflag) argus->ahdr.status = ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); argus->argus_far.time.start.tv_sec = RaStartSeconds; argus->argus_far.time.last.tv_sec = RaStartSeconds + RaBinSize; bzero ((char *) RaArgusFlow, sizeof(struct ArgusFlow)); if ((srv = RaNewArgusStore(argus)) != NULL) { srv->startime = argus->argus_far.time.start; srv->lasttime = argus->argus_far.time.last; srv->status |= RA_MODIFIED; if ((srv->data[RaThisActiveIndex] = RaNewArgusData(argus)) != NULL) { srv->data[RaThisActiveIndex]->status |= RA_MODIFIED; RaSendArgusRecord (srv); } RaDeleteArgusStore(srv); } } void * RaFindHashObject (struct RaHashTableStruct *thisHashTable, struct RaHashStruct *thisHash) { void *retn = NULL; struct RaHashTableHeader *rahtblhdr = NULL; if ((rahtblhdr = RaFindHash(thisHashTable, thisHash)) != NULL) retn = rahtblhdr->object; return (retn); } struct RaHashTableHeader * RaFindHash (struct RaHashTableStruct *thisHashTable, struct RaHashStruct *thisHash) { struct RaHashTableHeader *retn = NULL; struct RaHashTableHeader *head = NULL, *target; unsigned short *ptr = (unsigned short *) thisHash->buf; int i, len = 0; if (thisHashTable->size > 0) { thisHash->hash = 0; for (i = 0, len = (thisHash->len / sizeof(unsigned short)); i < len; i++) thisHash->hash += *ptr++; if ((target = thisHashTable->array[thisHash->hash % thisHashTable->size]) != NULL) { len = (thisHash->len < target->hstruct.len) ? thisHash->len : target->hstruct.len; if (len > 0) { head = target; do { if (!(bcmp ((char *) thisHash->buf, (char *) target->hstruct.buf, len))) { retn = target; break; } else target = target->nxt; } while (target != head); } } } #ifdef ARGUSDEBUG ArgusDebug (7, "RaFindHash: returning 0x%x\n", retn); #endif return (retn); } struct RaHashTableHeader * RaAddHashObject (struct RaHashTableStruct *thisHashTable, void *obj, struct RaHashStruct *hstruct) { struct RaHashTableHeader *retn = NULL; struct RaHashTableHeader *start = NULL; unsigned short *ptr = (unsigned short *) hstruct->buf; int i, len; hstruct->hash = 0; if (thisHashTable) { if ((retn = (struct RaHashTableHeader *) ArgusCalloc (1, sizeof (struct RaHashTableHeader))) != NULL) { RaAllocHashTableHeaders++; for (i = 0, len = (hstruct->len / sizeof(unsigned short)); i < len; i++) hstruct->hash += *ptr++; retn->object = obj; retn->hstruct.len = sizeof(hstruct->buf); retn->hstruct.hash = hstruct->hash; bcopy((char *)hstruct->buf, (char *)retn->hstruct.buf, hstruct->len); if ((start = thisHashTable->array[hstruct->hash % thisHashTable->size]) != NULL) { retn->nxt = start; retn->prv = start->prv; retn->prv->nxt = retn; retn->nxt->prv = retn; } else retn->prv = retn->nxt = retn; thisHashTable->array[hstruct->hash % thisHashTable->size] = retn; thisHashTable->count++; retn->htable = thisHashTable; } } #ifdef ARGUSDEBUG ArgusDebug (7, "RaAddHashObject (0x%x, 0x%x, 0x%x) returning 0x%x\n", thisHashTable, obj, hstruct, retn); #endif return (retn); } int RaProbeMonitorsThisAddr (unsigned int probe, unsigned int saddr) { int retn = 0; struct ArgusListStruct *list = NULL; struct RaHashStruct ArgusHash; struct RaCIDRAddr *addr, *start; bzero ((char *)&ArgusHash, sizeof(ArgusHash)); ArgusHash.len = sizeof(ArgusHash.buf); ArgusHash.hash = 0; ArgusHash.buf[0] = probe; if (RaMonitorTable != NULL) { if ((list = (struct ArgusListStruct *) RaFindHashObject(RaMonitorTable, &ArgusHash)) != NULL) { if ((addr = ArgusFrontList(list)) != NULL) { start = addr; do { if (RaCIDRAddrMatches (saddr, addr)) { retn++; break; } ArgusPopFrontList(list); ArgusPushBackList(list, addr); addr = ArgusFrontList(list); } while (addr != start); } } } return (retn); } void ArgusReverseDataRecord (struct ArgusRecord *argus) { struct ArgusRecord *tmp = RaCopyArgusRecord(argus); struct ArgusFarHeaderStruct *a1farhdr[32], *a2farhdr[32]; unsigned int a1DSRStatus = 0, a2DSRStatus = 0, status; int i; a1DSRStatus = ArgusIndexRecord (argus, a1farhdr); a2DSRStatus = ArgusIndexRecord (tmp, a2farhdr); status = a1DSRStatus; for (i = 0; i < 32; i++) { if (status & 0x01) { switch (i) { case ARGUS_FAR_DSR_INDEX: { struct ArgusFarStruct *far1 = (struct ArgusFarStruct *) a1farhdr[i]; struct ArgusFarStruct *far2 = (struct ArgusFarStruct *) a2farhdr[i]; bcopy ((char *)&far1->src, (char *)&far2->dst, sizeof(struct ArgusMeter)); bcopy ((char *)&far1->dst, (char *)&far2->src, sizeof(struct ArgusMeter)); break; } case ARGUS_MAC_DSR_INDEX: case ARGUS_VLAN_DSR_INDEX: case ARGUS_MPLS_DSR_INDEX: case ARGUS_AGR_DSR_INDEX: { break; } case ARGUS_TIME_DSR_INDEX: { struct ArgusTimeStruct *time1 = (struct ArgusTimeStruct *) a1farhdr[i]; struct ArgusTimeStruct *time2 = (struct ArgusTimeStruct *) a2farhdr[i]; bcopy ((char *)&time1->src, (char *)&time2->dst, sizeof(struct ArgusTimeEntity)); bcopy ((char *)&time1->dst, (char *)&time2->src, sizeof(struct ArgusTimeEntity)); break; } case ARGUS_SRCUSRDATA_DSR_INDEX: case ARGUS_DSTUSRDATA_DSR_INDEX: { struct ArgusUserStruct *user2 = (struct ArgusUserStruct *) a2farhdr[i]; if (user2->type == ARGUS_SRCUSRDATA_DSR) user2->type = ARGUS_DSTUSRDATA_DSR; else user2->type = ARGUS_SRCUSRDATA_DSR; break; } case ARGUS_TCP_DSR_INDEX: { struct ArgusTCPObject *tcp1 = (struct ArgusTCPObject *) a1farhdr[i]; struct ArgusTCPObject *tcp2 = (struct ArgusTCPObject *) a2farhdr[i]; bcopy ((char *)&tcp1->src, (char *)&tcp2->dst, sizeof(struct ArgusTCPObjectMetrics)); bcopy ((char *)&tcp1->dst, (char *)&tcp2->src, sizeof(struct ArgusTCPObjectMetrics)); break; } case ARGUS_ICMP_DSR_INDEX: { break; } case ARGUS_RTP_DSR_INDEX: { struct ArgusRTPObject *rtp1 = (struct ArgusRTPObject *) a1farhdr[i]; struct ArgusRTPObject *rtp2 = (struct ArgusRTPObject *) a2farhdr[i]; bcopy ((char *)&rtp1->src, (char *)&rtp2->dst, sizeof(struct rtphdr)); bcopy ((char *)&rtp1->dst, (char *)&rtp2->src, sizeof(struct rtphdr)); rtp2->sdrop = rtp2->ddrop; rtp2->ddrop = rtp2->sdrop; rtp2->ssdev = rtp2->dsdev; rtp2->dsdev = rtp2->ssdev; break; } case ARGUS_IGMP_DSR_INDEX: { break; } case ARGUS_ARP_DSR_INDEX: break; case ARGUS_FRG_DSR_INDEX: break; case ARGUS_ESP_DSR_INDEX: { break; } } } status >>= 1; } bcopy ((char *)tmp, (char *)argus, argus->ahdr.length); ArgusFree(tmp); } argus-clients-2.0.6.fixes.1/ragraph/rahistogram.h0000664000076600007660000000210407640610166015372 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (C) 2000-2001 QoSient, LLC. * All Rights Reserved * * THE ACCOMPANYING PROGRAM IS PROPRIETARY SOFTWARE OF QoSIENT, LLC, * AND CANNOT BE USED, DISTRIBUTED, COPIED OR MODIFIED WITHOUT * EXPRESS PERMISSION OF QoSIENT, LLC. * */ #ifndef RaHistogram_h #define RaHistogram_h #include #include #include #include #include #include #include #include void RaProcessQueue(struct RaQueueStruct *, unsigned char state); void *RaFindHashObject (struct RaHashTableStruct *, struct RaHashStruct *); struct RaHashTableHeader *RaFindHash (struct RaHashTableStruct *, struct RaHashStruct *); struct RaHashTableHeader *RaAddHashObject (struct RaHashTableStruct *, void *, struct RaHashStruct *); void ArgusReverseDataRecord (struct ArgusRecord *); int RaProbeMonitorsThisAddr (unsigned int, unsigned int); struct RaHashTableStruct RaProbeTable; struct RaHashTableStruct *RaMonitorTable = NULL; #endif argus-clients-2.0.6.fixes.1/ratop/0000775000076600007660000000000010047734056012465 5argus-clients-2.0.6.fixes.1/ratop/Makefile.in0000664000076600007660000000712507703321100014442 # # Argus Client Software. Tools to read, analyze and manage Argus data. # Copyright (c) 2000-2003 QoSient, LLC # All rights reserved. # # 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 # # Various configurable paths (remember to edit Makefile.in, not Makefile) # # Top level hierarchy prefix = $(DESTDIR)@prefix@ exec_prefix = @exec_prefix@ # Pathname of directory to install the system binaries SBINDIR = @sbindir@ # Pathname of directory to install the system binaries BINDIR = @bindir@ # Pathname of directory to install the include files INCLDEST = @includedir@ # Pathname of directory to install the library LIBDEST = @libdir@ # Pathname of directory to install the man page MANDEST = @mandir@ # VPATH srcdir = @srcdir@ VPATH = @srcdir@ # # You shouldn't need to edit anything below. # CC = @CC@ CCOPT = @V_CCOPT@ INCLS = -I. -I../include -I../common @V_INCLS@ DEFS = @DEFS@ COMPATLIB = @COMPATLIB@ @LIB_SASL@ # Standard CFLAGS CFLAGS = $(CCOPT) $(INCLS) $(DEFS) INSTALL = @INSTALL@ RANLIB = @V_RANLIB@ # # Flex and bison allow you to specify the prefixes of the global symbols # used by the generated parser. This allows programs to use lex/yacc # and link against libpcap. If you don't have flex or bison, get them. # LEX = @V_LEX@ YACC = @V_YACC@ # Explicitly define compilation rule since SunOS 4's make doesn't like gcc. # Also, gcc does not remove the .o before forking 'as', which can be a # problem if you don't own the file but can write to the directory. .c.o: @rm -f $@ $(CC) $(CFLAGS) -c $(srcdir)/$*.c LIB = @INSTALL_LIB@/argus_parse.a @INSTALL_LIB@/argus_common.a @INSTALL_LIB@/argus_client.a SRC = ratop.c PROGS = @INSTALL_BIN@/ratop all: $(PROGS) @INSTALL_BIN@/ratop: ratop.o $(LIB) $(CC) $(CCOPT) -o $@ ratop.o $(LIB) $(COMPATLIB) -lcurses -lm # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot # hack the extra indirection OBJ = $(SRC:.c=.o) CLEANFILES = $(OBJ) $(PROGS) install: force all [ -d $(DESTDIR) ] || \ (mkdir -p $(DESTDIR); chmod 755 $(DESTDIR)) [ -d $(prefix) ] || \ (mkdir -p $(prefix); chmod 755 $(prefix)) [ -d $(BINDIR) ] || \ (mkdir -p $(BINDIR); chmod 755 $(BINDIR)) $(INSTALL) @INSTALL_BIN@/ratop $(BINDIR) clean: rm -f $(CLEANFILES) distclean: rm -f $(CLEANFILES) Makefile config.cache config.log config.status \ gnuc.h os-proto.h bpf_filter.c net tags: $(TAGFILES) ctags -wtd $(TAGFILES) tar: force @cwd=`pwd` ; dir=`basename $$cwd` ; name=libpcap-`cat VERSION` ; \ list="" ; tar="tar chFFf" ; \ for i in `cat FILES` ; do list="$$list $$name/$$i" ; done; \ echo \ "rm -f ../$$name; ln -s $$dir ../$$name" ; \ rm -f ../$$name; ln -s $$dir ../$$name ; \ echo \ "(cd .. ; $$tar - [lots of files]) | compress > /tmp/$$name.tar.Z" ; \ (cd .. ; $$tar - $$list) | compress > /tmp/$$name.tar.Z ; \ echo \ "rm -f ../$$name" ; \ rm -f ../$$name force: /tmp depend: $(GENSRC) force ../bin/mkdep -c $(CC) $(DEFS) $(INCLS) $(SRC) argus-clients-2.0.6.fixes.1/ratop/ratop.c0000664000076600007660000025352207725257001013706 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 * */ /* * ratop - top() style application for argus data. * * written by Carter Bullard * QoSient, LLC * */ #define ARGUS_CURSES 1 #include #include #include #ifdef ARGUS_CURSES #include #if !defined(CYGWIN) && !defined(__NetBSD__) #include #else #include #endif #endif #include #include #include extern int ArgusSrcUserDataLen; extern int ArgusDstUserDataLen; struct ArgusServiceRecord ArgusThisSrv; void RaProcessSrvRecord (struct ArgusServiceRecord *); #ifdef ARGUS_CURSES WINDOW *RaWindow = NULL; WINDOW *RaHeaderWindow = NULL; WINDOW *RaAvailableWindow = NULL; WINDOW *RaFailedWindow = NULL; WINDOW *RaRecordWindow = NULL; #define FAILEDWINSIZE 15 #define HEADERWINSIZE 5 int RaRecordWindowNum = 0; int RaCursesInit = 0; int RaServerMode = 0; int RaWindowStatus = 1; int RaWindowModified = 1; int RaWindowImmediate = 1; int RaWindowLines = 0; int RaWindowStartLine = 0; extern struct timeval RaClientTimeout; struct timeval RaUpdateTime = {0, 0}; struct timeval RaUpdateTimeInterval = {0, 500000}; int RaInitCurses (void); #include #define MAXFLOWMODELS 31 int RaThisFlowModelIndex = MAXFLOWMODELS - 1; char *RaSrvStatsFlowModelDesc [MAXFLOWMODELS] = { "Total Aggregate Traffic", "Protocol Aggregate Traffic", "Services Aggregate Traffic", "Src Class A Aggregate Traffic", "Src Class A Protocol Aggregate Traffic", "Src Class A Service Aggregate Traffic", "Src Class Aggregate Traffic", "Src Class Protocol Aggregate Traffic", "Src Class Service Aggregate Traffic", "Source Aggregate Traffic", "Source Protocol Aggregate Traffic", "Source Service Aggregate Traffic", "Dest Class A Aggregate Traffic", "Dest Class A Protocol Aggregate Traffic", "Dest Class A Service Aggregate Traffic", "Dest Class Aggregate Traffic", "Dest Class Protocol Aggregate Traffic", "Dest Class Service Aggregate Traffic", "Destination Aggregate Traffic", "Destination Protocol Aggregate Traffic", "Destination Service Aggregate Traffic", "Class Matrix Aggregate Traffic", "Class Matrix Protocol Traffic", "Class Matrix Service Traffic", "Source Class Destination Aggregate Traffic", "Source Class Destination Protocol Aggregate Traffic", "Source Class Destination Services Aggregate Traffic", "Flow Aggregate Traffic", "Microflow Protocol Aggregate Traffic", "Microflow Services Aggregate Traffic", "Microflow Traffic", }; char *RaSrvStatsFlowModelFile [] = { "RAGATOR_PRESERVE_FIELDS=yes", "RAGATOR_REPORT_AGGREGATION=yes", "Flow 100 ip * * * * * 200 120 180", "Flow 101 ip * * * * * 201 120 180", "Flow 102 ip * * * * * 202 120 180", "Flow 103 ip * * * * * 203 120 180", "Flow 104 ip * * * * * 204 120 180", "Flow 105 ip * * * * * 205 120 180", "Flow 106 ip * * * * * 206 120 180", "Flow 107 ip * * * * * 207 120 180", "Flow 108 ip * * * * * 208 120 180", "Flow 109 ip * * * * * 209 120 180", "Flow 110 ip * * * * * 210 120 180", "Flow 111 ip * * * * * 211 120 180", "Flow 112 ip * * * * * 212 120 180", "Flow 113 ip * * * * * 213 120 180", "Flow 114 ip * * * * * 214 120 180", "Flow 115 ip * * * * * 215 120 180", "Flow 116 ip * * * * * 216 120 180", "Flow 117 ip * * * * * 217 120 180", "Flow 118 ip * * * * * 218 120 180", "Flow 119 ip * * * * * 219 120 180", "Flow 120 ip * * * * * 220 120 180", "Flow 121 ip * * * * * 221 120 180", "Flow 122 ip * * * * * 222 120 180", "Flow 123 ip * * * * * 223 120 180", "Flow 124 ip * * * * * 224 120 180", "Flow 125 ip * * * * * 225 120 180", "Flow 126 ip * * * * * 226 120 180", "Flow 127 ip * * * * * 227 120 180", "Flow 128 ip * * * * * 228 120 180", "Flow 129 ip * * * * * 229 120 180", "Flow 130 ip * * * * * 230 120 180", "Model 200 ip 0.0.0.0 0.0.0.0 no no no", "Model 201 ip 0.0.0.0 0.0.0.0 yes no no", "Model 202 ip 0.0.0.0 0.0.0.0 yes no yes", "Model 203 ip 255.0.0.0 0.0.0.0 no no no", "Model 204 ip 255.0.0.0 0.0.0.0 yes no no", "Model 205 ip 255.0.0.0 0.0.0.0 yes no yes", "Model 206 ip class 0.0.0.0 no no no", "Model 207 ip class 0.0.0.0 yes no no", "Model 208 ip class 0.0.0.0 yes no yes", "Model 209 ip 255.255.255.255 0.0.0.0 no no no", "Model 210 ip 255.255.255.255 0.0.0.0 yes no no", "Model 211 ip 255.255.255.255 0.0.0.0 yes no yes", "Model 212 ip 0.0.0.0 255.0.0.0 no no no", "Model 213 ip 0.0.0.0 255.0.0.0 yes no no", "Model 214 ip 0.0.0.0 255.0.0.0 yes no yes", "Model 215 ip 0.0.0.0 class no no no", "Model 216 ip 0.0.0.0 class yes no no", "Model 217 ip 0.0.0.0 class yes no yes", "Model 218 ip 0.0.0.0 255.255.255.255 no no no", "Model 219 ip 0.0.0.0 255.255.255.255 yes no no", "Model 220 ip 0.0.0.0 255.255.255.255 yes no yes", "Model 221 ip class class no no no", "Model 222 ip class class yes no no", "Model 223 ip class class yes no yes", "Model 224 ip class 255.255.255.255 no no no", "Model 225 ip class 255.255.255.255 yes no no", "Model 226 ip class 255.255.255.255 yes no yes", "Model 227 ip 255.255.255.255 255.255.255.255 no no no", "Model 228 ip 255.255.255.255 255.255.255.255 yes no no", "Model 229 ip 255.255.255.255 255.255.255.255 yes no yes", "Model 230 ip 255.255.255.255 255.255.255.255 yes yes yes", NULL, }; struct RaFlowModelStruct *RaFlowModel = NULL; int RaInitCurses () { struct termios newtty; RaCursesInit++; if (tcgetattr(0, &RaOrigTty) == -1) ArgusLog(LOG_ERR, "tcgetattr() failed %s\n", strerror(errno)); newtty = RaOrigTty; newtty.c_lflag &= ~ICANON; newtty.c_lflag &= ~ECHO; newtty.c_cc[VMIN] = 1; newtty.c_cc[VTIME] = 0; if (tcsetattr(0, TCSAFLUSH, &newtty) == -1) ArgusLog(LOG_ERR, "cannot put tty into raw mode\n"); RaWindow = initscr(); noraw(); cbreak(); nodelay(RaWindow, TRUE); noecho(); nonl(); intrflush(stdscr, FALSE); keypad(stdscr, TRUE); clearok(RaWindow, TRUE); werase(RaWindow); wrefresh(RaWindow); RaHeaderWindow = newwin (HEADERWINSIZE, COLS, 0, 0); RaWindowLines = LINES - (HEADERWINSIZE + 1); RaWindowStartLine = 0; Nflag = RaWindowLines - 3; RaAvailableWindow = newwin (RaWindowLines, COLS, HEADERWINSIZE, 0); RaFailedWindow = RaAvailableWindow; idlok (RaHeaderWindow, TRUE); idlok (RaAvailableWindow, TRUE); notimeout(RaHeaderWindow, TRUE); refresh(); return (1); } #endif void RaTopLoop(void); extern struct timeval ArgusGlobalTime; struct timeval RaTopStartTime = {0, 0}; int RaInitialized = 0; void ArgusClientInit () { struct ArgusModeStruct *mode = NULL; if (!(RaInitialized)) { RaWriteOut = 0; RaCumulativeMerge = 1; if ((mode = ArgusModeList) != NULL) while (mode) { if (isdigit((int)*mode->mode)) { RaThisFlowModelIndex = atoi (mode->mode); if (RaThisFlowModelIndex > (MAXFLOWMODELS - 1)) RaThisFlowModelIndex = MAXFLOWMODELS - 1; } mode = mode->nxt; } if ((RaFlowModel = RaReadFlowModelFile (RaSrvStatsFlowModelFile)) == NULL) ArgusLog (LOG_ERR, "ArgusClientInit RaReadFlowModelFile returned NULL %s\n", strerror(errno)); if ((RaAvailableQueue = RaNewQueue()) == NULL) ArgusLog (LOG_ERR, "ArgusClientInit RaNewQueue returned NULL %s\n", strerror(errno)); if ((RaFailedQueue = RaNewQueue()) == NULL) ArgusLog (LOG_ERR, "ArgusClientInit RaNewQueue returned NULL %s\n", strerror(errno)); if ((RaHashTable.array = (struct RaHashTableHeader **) ArgusCalloc (RA_HASHTABLESIZE, sizeof (struct RaHashTableHeader *))) != NULL) { RaHashTable.size = RA_HASHTABLESIZE; } bzero ((char *)RaSortAlgorithms, sizeof(RaSortAlgorithms)); RaSortAlgorithms[0] = RaSortPktsCount; RaSortAlgorithms[1] = RaSortByteCount; (void) signal (SIGHUP, (void (*)(int)) RaParseComplete); (void) signal (SIGTERM, (void (*)(int)) RaParseComplete); (void) signal (SIGQUIT, (void (*)(int)) RaParseComplete); (void) signal (SIGINT, (void (*)(int)) RaParseComplete); if (Sflag || Cflag) { RaClientTimeout.tv_sec = 0; RaClientTimeout.tv_usec = 10000; } else { RaClientTimeout.tv_sec = 0; RaClientTimeout.tv_usec = 10000; } RaInitialized++; if (nflag > 0) hfield = 15; if (nflag > 1) pfield = 5; RaCumulativeMerge = 0; RaInitCurses (); RaTopLoop(); } } #include #include #include int RaTopCompleted = 0; int RaTasksToDo = 1; struct ARGUS_INPUT *RaCurrentInput = NULL; void RaRefreshDisplay(void); void RaOutputHelpScreen(void); void RaOutputModifyScreen(void); void RaTopLoop() { int retn = 0, fd = -1; while (!(RaTopCompleted)) { if (RaTasksToDo) { if (Sflag || Cflag) { mvwprintw (RaHeaderWindow, 4, 1, "RaTopLoop() Processing Remote Server"); if ((RaCurrentInput = ArgusRemoteHostList) != NULL) { if ((RaCurrentInput->fd = ArgusGetServerSocket (RaCurrentInput)) >= 0) { if ((ArgusReadConnection (RaCurrentInput, NULL)) >= 0) { ArgusRemoteFDs[ArgusActiveServers++] = RaCurrentInput; ArgusReadStream(); } else mvwprintw (RaHeaderWindow, 4, 1, "%s", strerror(errno)); } RaTasksToDo = 0; ArgusDeleteHostList(); } } else { if ((RaCurrentInput = ArgusInputFileList) != NULL) { mvwprintw (RaHeaderWindow, 4, 1, "RaTopLoop() Processing Input File List"); while (RaCurrentInput) { if (strcmp (RaCurrentInput->filename, "-")) { if ((RaCurrentInput->fd = open(RaCurrentInput->filename, O_RDONLY)) >= 0) { if (((ArgusReadConnection (RaCurrentInput, RaCurrentInput->filename)) >= 0)) { ArgusRemoteFDs[0] = RaCurrentInput; ArgusReadStream(); if (RaCurrentInput) close(RaCurrentInput->fd); } } else { fprintf (stderr, "%s: open '%s': %s\n", ArgusProgramName, RaCurrentInput->filename, strerror(errno)); _exit(1); } } else { RaCurrentInput->fd = 0; if (((ArgusReadConnection (RaCurrentInput, NULL)) >= 0)) { ArgusRemoteFDs[0] = RaCurrentInput; ArgusReadStream(); if (RaCurrentInput) close(RaCurrentInput->fd); } } if (RaCurrentInput) RaCurrentInput = RaCurrentInput->nxt; } } else { mvwprintw (RaHeaderWindow, 4, 1, "RaTopLoop() Idle"); RaRefreshDisplay(); } ArgusClientTimeout (); RaTasksToDo = 0; RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); } } else { usleep(50000); ArgusClientTimeout (); } } if (fd >= 0) { ArgusShutDown (0); } else retn = 1; #ifdef ARGUSDEBUG ArgusDebug (1, "main () exiting with %d\n", retn); #endif exit (retn); } int RaParseCompleting = 0; void RaParseComplete (int sig) { int retn = 0; #ifdef ARGUS_CURSES if (RaCursesInit) { mvwprintw (RaWindow, LINES - 1, 0, "\n"); endwin(); refresh(); if ((retn = tcsetattr(0, TCSAFLUSH, &RaOrigTty)) == ERR) ArgusLog (LOG_ERR, "tcsetattr error %s\n", strerror(errno)); printf("\n"); } #endif switch (sig) { case SIGHUP: case SIGTERM: case SIGINT: RaTopCompleted = 1; _exit(0); break; } } extern char version[]; extern struct ARGUS_INPUT *ArgusInput; struct timeval RaProbeUptime = {0, 0}; int RaActiveCons = 0; int RaClosingCons = 0; int RaNoResponse = 0; void RaUpdateWindow (WINDOW *, struct RaQueueStruct *); char *RaModifyCommandArray[] = { "RA_CISCONETFLOW_SOURCE=", "RA_NO_OUTPUT=", "RA_USER_AUTH=", "RA_AUTH_PASS=", "RA_OUTPUT_FILE=", "RA_EXCEPTION_OUTPUT_FILE=", "RA_TIMERANGE=", "RA_RUN_TIME=", "RA_FIELD_DELIMITER=", "RA_TIME_FORMAT=", "RA_USEC_PRECISION=", "RAGATOR_TIME_SERIES=", "RAGATOR_VALIDATE=", "RAMON_NUMBER=", "RA_DEBUG_LEVEL=", "RA_USERDATA_ARG=", "RA_USERDATA_ENCODE=", "RA_HOST_FIELD_LENGTH=", "RA_PORT_FIELD_LENGTH=", }; char *RaGetCiscoServers(void); char *RaGetNoOutputStatus(void); char *RaGetUserAuth(void); char *RaGetUserPass(void); char *RaGetOutputFile(void); char *RaGetExceptionOutputFile(void); char *RaGetTimeRange(void); char *RaGetRunTime(void); char *RaGetFieldDelimiter(void); char *RaGetTimeFormat(void); char *RaGetPrecision(void); char *RaGetTimeSeries(void); char *RaGetValidateStatus(void); char *RaGetNumber(void); char *RaGetDebugLevel(void); char *RaGetUserDataArg(void); char *RaGetUserDataEncode(void); char *RaGetHostFieldLength(void); char *RaGetPortFieldLength(void); #define ARGUS_MAX_MODIFY_ELEMENTS 19 strproc RaModifyCommandValueArray[ARGUS_MAX_MODIFY_ELEMENTS] = { RaGetCiscoServers, RaGetNoOutputStatus, RaGetUserAuth, RaGetUserPass, RaGetOutputFile, RaGetExceptionOutputFile, RaGetTimeRange, RaGetRunTime, RaGetFieldDelimiter, RaGetTimeFormat, RaGetPrecision, RaGetTimeSeries, RaGetValidateStatus, RaGetNumber, RaGetDebugLevel, RaGetUserDataArg, RaGetUserDataEncode, RaGetHostFieldLength, RaGetPortFieldLength, }; #define RANEWCOMMAND 1 #define RAGETTINGc 2 #define RAGETTINGf 3 #define RAGETTINGF 4 #define RAGETTINGh 5 #define RAGETTINGm 6 #define RAGETTINGN 7 #define RAGETTINGo 8 #define RAGETTINGs 9 #define RAGETTINGt 10 #define RAREADINGSTR 11 #define RAGETTINGu 12 #define RAGETTINGcSTR "Connect to: " #define RAGETTINGfSTR "Specify filter: " #define RAGETTINGtSTR "Specify time range: " #define RAGETTINGFSTR "Specify fields: " #define RAGETTINGhSTR "Help menu (press any key to continue): " #define RAGETTINGmSTR "Use arrow keys to select variable (use d when done)." #define RAGETTINGNSTR "Connections to display: " #define RAGETTINGoSTR "Read file: " #define RAGETTINGSSTR "Switching to Server Mode: " #define RAGETTINGSORTSTR "Specify Sort fields: " #define RAGETTINGUPDATESTR "Specify Update value: " unsigned int RaUpdateCount = 0; int RaInputStatus = RANEWCOMMAND; char RaCommandInputStr[MAXSTRLEN]; int RaCommandIndex = 0; int RaCommandLines = 0; int RaMinCommandLines = 0; int RaMaxCommandLines = 0; WINDOW *RaCommandWindow = NULL; char **RaCommandArray = NULL; strproc *RaCommandValueArray = NULL; void RaOutputModifyScreen () { int i = 0; werase(RaAvailableWindow); for (i = RaMinCommandLines; i < (RaMaxCommandLines + 1); i++) { mvwprintw (RaAvailableWindow, i, 1, RaCommandArray[i - RaMinCommandLines]); if (i == RaMinCommandLines) wstandout(RaAvailableWindow); wprintw (RaAvailableWindow, "%s", RaCommandValueArray[i - RaMinCommandLines]()); if (i == RaMinCommandLines) wstandend(RaAvailableWindow); } } void RaOutputHelpScreen () { werase(RaAvailableWindow); mvwprintw (RaAvailableWindow, 1, 1, "RaTop Version %s\n", version); mvwprintw (RaAvailableWindow, 2, 1, "Key Commands: h,q,n,s"); mvwprintw (RaAvailableWindow, 3, 1, " h - Print help screen."); mvwprintw (RaAvailableWindow,27, 1, " c - connect to remote Argus"); mvwprintw (RaAvailableWindow,26, 1, " d - disconnect from remote Argus"); mvwprintw (RaAvailableWindow,29, 1, " f - specify filter expression"); mvwprintw (RaAvailableWindow,12, 1, " F - Specify fields to print."); mvwprintw (RaAvailableWindow,13, 1, " +[#]field - add field to optional column # or end of line"); mvwprintw (RaAvailableWindow,14, 1, " -field - remove field from display"); mvwprintw (RaAvailableWindow,15, 1, " field - reset fields and add to display"); mvwprintw (RaAvailableWindow,16, 1, " available fields are:"); mvwprintw (RaAvailableWindow,18, 1, " startime, lasttime, trans, dur, avgdur"); mvwprintw (RaAvailableWindow,19, 1, " saddr, daddr, proto, sport, dport"); mvwprintw (RaAvailableWindow,20, 1, " stos, dtos, sttl, dttl, bytes, sbytes"); mvwprintw (RaAvailableWindow,21, 1, " dbytes, pkts, spkts, dpkts"); mvwprintw (RaAvailableWindow,22, 1, " load, loss, rate, srcid, ind, mac, dir"); mvwprintw (RaAvailableWindow,23, 1, " jitter, status, user, tcpext, win"); mvwprintw (RaAvailableWindow, 5, 1, " n - Specify the number of entries to print."); mvwprintw (RaAvailableWindow,28, 1, " o - open Argus data file"); mvwprintw (RaAvailableWindow, 4, 1, " q - Quit the program."); mvwprintw (RaAvailableWindow, 6, 1, " s - Specify sort fields."); mvwprintw (RaAvailableWindow, 7, 1, " available fields are:"); mvwprintw (RaAvailableWindow, 8, 1, " time, startime, lasttime, trans, dur, avgdur"); mvwprintw (RaAvailableWindow, 9, 1, " saddr, daddr, proto, sport, dport"); mvwprintw (RaAvailableWindow,10, 1, " stos, dtos, sttl, dttl, bytes, sbytes, dbytes"); mvwprintw (RaAvailableWindow,11, 1, " pkts, spkts, dpkts, load, loss, rate, transref, seq"); mvwprintw (RaAvailableWindow,24, 1, " S - Toggle server display mode. When on displays entries that have multiple sources"); mvwprintw (RaAvailableWindow,25, 1, " t - Specify time range. same as -t command line option. "); mvwprintw (RaAvailableWindow,25, 1, " u - Specify the window update timer, in seconds (default 0.5s)"); wnoutrefresh(RaWindow); doupdate(); } void RaRefreshDisplay () { struct timeval tvp, *last, *start; int dsec, dusec, srcaddr; char timebuf[32], tbuf[MAXSTRLEN]; struct tm *tm; if (RaTopStartTime.tv_sec == 0) RaTopStartTime = ArgusGlobalTime; tvp = ArgusRealTime; if (RaUpdateTime.tv_sec == 0) RaUpdateTime = tvp; if ((RaWindowImmediate) || ((RaUpdateTime.tv_sec < tvp.tv_sec) || ((RaUpdateTime.tv_sec == tvp.tv_sec) && (RaUpdateTime.tv_usec <= tvp.tv_usec)))) { RaUpdateWindow(RaAvailableWindow, RaAvailableQueue); RaUpdateTime = tvp; RaUpdateTime.tv_sec += RaUpdateTimeInterval.tv_sec; RaUpdateTime.tv_usec += RaUpdateTimeInterval.tv_usec; if (RaUpdateTime.tv_usec >= 1000000) { RaUpdateTime.tv_sec += 1; RaUpdateTime.tv_usec -= 1000000; } RaWindowImmediate = 0; } if (ArgusInput && (RaProbeUptime.tv_sec == 0)) { start = &ArgusInput->ArgusInitCon.argus_mar.startime; last = &ArgusInput->ArgusInitCon.argus_mar.now; tvp.tv_sec = ntohl(last->tv_sec) - ntohl(start->tv_sec); tvp.tv_usec = ntohl(last->tv_usec) - ntohl(start->tv_usec); if (tvp.tv_usec < 0) { tvp.tv_sec--; tvp.tv_usec += 1000000; } if (tvp.tv_usec >= 1000000) { tvp.tv_sec++; tvp.tv_usec -= 1000000; } RaProbeUptime = tvp; } dsec = RaProbeUptime.tv_sec + (tvp.tv_sec - RaTopStartTime.tv_sec); dusec = RaProbeUptime.tv_usec + (tvp.tv_usec - RaTopStartTime.tv_usec); if (dusec < 0) { dsec--; dusec += 1000000; } if (dusec >= 1000000) { dsec++; dusec -= 1000000; } tm = localtime((time_t *) &tvp.tv_sec); strftime ((char *) timebuf, 32, "%d/%m/%Y %I:%M%P", tm); #ifdef ARGUS_CURSES mvwprintw (RaWindow, LINES - 1, 0, "\n"); if (strlen(ArgusProgramArgs) > 60) ArgusProgramArgs[60] = '\0'; mvwaddnstr (RaHeaderWindow, 0, 1, ArgusProgramArgs, COLS - 1); if (ArgusInput != NULL) { srcaddr = ntohl(ArgusInput->ArgusInitCon.argus_mar.argusid); if (RaTasksToDo) { bzero (tbuf, MAXSTRLEN); sprintf (tbuf, "Source %s Version %d.%d %s up %d days, %02d:%02d:%02d Far %d secs Mar %d secs", ipaddr_string(&srcaddr), ArgusInput->ArgusInitCon.argus_mar.major_version, ArgusInput->ArgusInitCon.argus_mar.minor_version, timebuf, dsec / 86400, (dsec % 86400)/3600, ((dsec % 86400) % 3600)/60, (((dsec % 86400) % 3600) % 60), ntohs(ArgusInput->ArgusInitCon.argus_mar.reportInterval), ntohs(ArgusInput->ArgusInitCon.argus_mar.argusMrInterval)); mvwaddnstr (RaHeaderWindow, 1, 1, tbuf, COLS - 1); wclrtoeol(RaHeaderWindow); bzero (tbuf, MAXSTRLEN); sprintf (tbuf, "%6d Flows %6d Active %6d Closing %12d Total Records", RaAvailableQueue->count + RaFailedQueue->count, RaActiveCons, RaClosingCons, totalrecords); mvwaddnstr (RaHeaderWindow, 2, 1, tbuf, COLS - 1); wclrtoeol(RaHeaderWindow); } } else { mvwaddnstr (RaHeaderWindow, 1, 1, "Source Not Connected", COLS - 3); } wnoutrefresh(RaHeaderWindow); #endif #ifdef ARGUS_CURSES if (RaWindowStatus && (RaLabel != NULL)) { if (RaServerMode) mvwaddnstr (RaAvailableWindow, 0, 1, "Services", COLS - 2); else mvwaddnstr (RaAvailableWindow, 0, 1, "Flows", COLS - 2); if (strlen(RaLabel) > (COLS - 6)) RaLabel[COLS - 6] = '\0'; sprintf (tbuf, "Rank %s", RaLabel); mvwaddnstr (RaAvailableWindow, 1, 1, tbuf, COLS - 2); wnoutrefresh(RaAvailableWindow); } wnoutrefresh(RaWindow); doupdate(); #endif } extern void ArgusCloseInput(struct ARGUS_INPUT *); #include #include extern unsigned char *ArgusRemoteFilter; int RaScreenLines = 0; int RaScreenColumns = 0; void ArgusClientTimeout () { #ifdef ARGUS_CURSES struct ArgusRecordStore *store = NULL; struct ARGUS_INPUT *addr, *tmp; struct timeval tv; fd_set in; int c; unsigned char *ptr = NULL; int i; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&in); FD_SET(0, &in); if (RaScreenLines == 0) RaScreenLines = LINES; if (RaScreenColumns == 0) RaScreenColumns = COLS; if ((RaScreenLines != LINES) || (RaScreenColumns != COLS)) { RaScreenLines = LINES; RaScreenColumns = COLS; RaWindowLines = LINES - (HEADERWINSIZE + 1); Nflag = RaWindowLines - 3; #if !defined(HAVE_SOLARIS) wresize(RaWindow, LINES, COLS); wresize(RaHeaderWindow, HEADERWINSIZE, COLS); wresize(RaAvailableWindow, RaWindowLines, COLS); #endif RaLabel = NULL; RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); } switch (RaInputStatus) { case RANEWCOMMAND: { if ((c = wgetch(RaWindow)) != ERR) { mvwaddnstr (RaHeaderWindow, 4, 1, " ", COLS - 2); wclrtoeol(RaHeaderWindow); if (RaCommandIndex != 0) { RaCommandIndex = 0; bzero (RaCommandInputStr, MAXSTRLEN); } switch (c) { case 0x1B: RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); break; case 'k': case 0x19: case KEY_UP: if (RaWindowStartLine > 0) { RaWindowStartLine--; RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; wscrl(RaAvailableWindow, -1); RaRefreshDisplay(); } break; case 'j': case 0x05: case KEY_DOWN: if ((RaAvailableQueue->count - RaWindowStartLine) > Nflag) { RaWindowStartLine++; RaWindowModified = RA_MODIFIED; wscrl(RaAvailableWindow, 1); RaWindowImmediate = TRUE; RaRefreshDisplay(); } break; case 'g': case KEY_HOME: if (RaWindowStartLine != 0) { werase(RaWindow); RaWindowModified = RA_MODIFIED; RaWindowStartLine = 0; RaWindowImmediate = TRUE; RaRefreshDisplay(); } break; case 'G': case KEY_END: if (RaWindowStartLine != (RaAvailableQueue->count - Nflag)) { RaWindowStartLine = RaAvailableQueue->count - Nflag; if (RaWindowStartLine < 0) RaWindowStartLine = 0; werase(RaWindow); RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); } break; case 0x06: case ' ': case KEY_NPAGE: if ((RaAvailableQueue->count - RaWindowStartLine) > Nflag) { RaWindowStartLine += Nflag; wscrl(RaWindow, Nflag); RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); } break; case 0x02: case KEY_PPAGE: if (RaWindowStartLine > 0) { wscrl(RaWindow, (Nflag > RaWindowStartLine) ? -RaWindowStartLine : -Nflag); RaWindowStartLine -= Nflag; if (RaWindowStartLine < 0) RaWindowStartLine = 0; RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); } break; case 'n': RaInputStatus = RAGETTINGN; mvwaddnstr (RaHeaderWindow, 4, 1, RAGETTINGNSTR, COLS - 2); break; case 'c': if ((ArgusRemoteHostList) == NULL) { RaInputStatus = RAGETTINGc; mvwaddnstr (RaHeaderWindow, 4, 1, RAGETTINGcSTR, COLS - 2); } else mvwaddnstr (RaHeaderWindow, 4, 1, "Connected", COLS - 2); RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); break; case 'd': if (RaCurrentInput != NULL) { for (i = 0; i < ARGUS_MAX_REMOTE_CONN; i++) { if (ArgusRemoteFDs[i] != NULL) { ArgusCloseInput(ArgusRemoteFDs[i]); ArgusRemoteFDs[i] = NULL; } } RaCurrentInput = NULL; Sflag = 0; Cflag = 0; if ((ArgusRemoteHostList) != NULL) { ArgusDeleteHostList(); ArgusActiveServers = 0; ArgusRemoteHostList = NULL; } if ((addr = ArgusInputFileList) != NULL) { while (addr) { tmp = addr->nxt; ArgusFree(addr); addr = tmp; } ArgusInputFileList = NULL; } RaWindowModified = RA_MODIFIED; werase(RaHeaderWindow); while ((store = (struct ArgusRecordStore *) RaPopQueue(RaAvailableQueue))) RaTimeoutArgusStore(store); while ((store = (struct ArgusRecordStore *) RaPopQueue(RaFailedQueue))) RaTimeoutArgusStore(store); mvwaddnstr (RaHeaderWindow, 4, 1, "Disonnecting", COLS - 2); RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); } else mvwaddnstr (RaHeaderWindow, 4, 1, "Not Connected", COLS - 2); RaWindowImmediate = TRUE; RaRefreshDisplay(); break; case 'f': { char tbuf[MAXSTRLEN]; bzero (tbuf, MAXSTRLEN); RaInputStatus = RAGETTINGf; if (*RaInputFilter != NULL) { sprintf (tbuf, "%s %s", RAGETTINGfSTR, *RaInputFilter); mvwaddnstr (RaHeaderWindow, 4, 1, tbuf, COLS - 2); } else { sprintf (tbuf, "%s %s", RAGETTINGfSTR, "(null)"); mvwaddnstr (RaHeaderWindow, 4, 1, tbuf, COLS - 2); } break; } case 't': RaInputStatus = RAGETTINGt; if (timearg != NULL) { char tbuf[MAXSTRLEN]; bzero (tbuf, MAXSTRLEN); sprintf (tbuf, "%s %s", RAGETTINGtSTR, timearg); mvwaddnstr (RaHeaderWindow, 4, 1, tbuf, COLS - 2); } else mvwaddnstr (RaHeaderWindow, 4, 1, RAGETTINGtSTR, COLS - 2); break; case 'o': if (RaCurrentInput == NULL) { RaInputStatus = RAGETTINGo; mvwaddnstr (RaHeaderWindow, 4, 1, RAGETTINGoSTR, COLS - 2); } else mvwaddnstr (RaHeaderWindow, 4, 1, "Connected", COLS - 2); break; case '+': { if (++RaThisFlowModelIndex > (MAXFLOWMODELS - 1)) RaThisFlowModelIndex = 0; while ((store = (struct ArgusRecordStore *) RaPopQueue(RaAvailableQueue))) RaTimeoutArgusStore(store); while ((store = (struct ArgusRecordStore *) RaPopQueue(RaFailedQueue))) RaTimeoutArgusStore(store); werase(RaAvailableWindow); mvwaddnstr (RaHeaderWindow, 4, 1, RaSrvStatsFlowModelDesc[RaThisFlowModelIndex], COLS - 2); RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } case '-': { struct ArgusRecordStore *store = NULL; if (--RaThisFlowModelIndex < 0) RaThisFlowModelIndex = MAXFLOWMODELS - 1; while ((store = (struct ArgusRecordStore *) RaPopQueue(RaAvailableQueue))) RaTimeoutArgusStore(store); while ((store = (struct ArgusRecordStore *) RaPopQueue(RaFailedQueue))) RaTimeoutArgusStore(store); werase(RaAvailableWindow); mvwaddnstr (RaHeaderWindow, 4, 1, RaSrvStatsFlowModelDesc[RaThisFlowModelIndex], COLS - 2); RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } case 'S': { char tbuf[MAXSTRLEN]; bzero (tbuf, MAXSTRLEN); if ((RaServerMode = (RaServerMode > 0) ? 0 : 1) > 0) ptr = (unsigned char *) "on"; else ptr = (unsigned char *) "off"; sprintf (tbuf, "%s %s", RAGETTINGSSTR, ptr); mvwaddnstr (RaHeaderWindow, 4, 1, tbuf, COLS - 2); break; } case 's': RaInputStatus = RAGETTINGs; mvwaddnstr (RaHeaderWindow, 4, 1, RAGETTINGSORTSTR, COLS - 2); break; case 'u': RaInputStatus = RAGETTINGu; mvwaddnstr (RaHeaderWindow, 4, 1, RAGETTINGUPDATESTR, COLS - 2); break; case 'F': RaInputStatus = RAGETTINGF; mvwaddnstr (RaHeaderWindow, 4, 1, RAGETTINGFSTR, COLS - 2); break; case 'q': RaParseComplete(SIGINT); break; case 'h': RaInputStatus = RAGETTINGh; mvwaddnstr (RaHeaderWindow, 4, 1, RAGETTINGhSTR, COLS - 2); RaWindowStatus = 0; werase(RaAvailableWindow); RaOutputHelpScreen(); RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); break; case 'm': RaInputStatus = RAGETTINGm; RaMinCommandLines = 2; RaMaxCommandLines = 20; RaCommandArray = RaModifyCommandArray; RaCommandValueArray = RaModifyCommandValueArray; RaCommandLines = RaMinCommandLines; mvwaddnstr (RaHeaderWindow, 4, 1, RAGETTINGmSTR, COLS - 2); RaWindowStatus = 0; werase(RaAvailableWindow); RaOutputModifyScreen(); RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); break; default: break; } } break; } case RAGETTINGc: { while (select(1, &in, 0, 0, &tv) > 0) { if (read (0, &RaCommandInputStr[RaCommandIndex], 1)) { if ((RaCommandInputStr[RaCommandIndex] == '\n') || (RaCommandInputStr[RaCommandIndex] == '\r')) { RaCommandInputStr[RaCommandIndex] = '\0'; if (!(ArgusAddHostList (RaCommandInputStr, ARGUS_DATA_SOURCE))) { mvwprintw (RaHeaderWindow, 4, 1, "%s %s host not found", RAGETTINGcSTR, RaCommandInputStr); } else { mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGcSTR, RaCommandInputStr); RaTasksToDo = 1; totalrecords = 0; Sflag = 1; RaClientTimeout.tv_sec = 0; RaClientTimeout.tv_usec = 10000; while ((store = (struct ArgusRecordStore *) RaPopQueue(RaAvailableQueue))) RaTimeoutArgusStore(store); while ((store = (struct ArgusRecordStore *) RaPopQueue(RaFailedQueue))) RaTimeoutArgusStore(store); } RaInputStatus = RANEWCOMMAND; werase(RaAvailableWindow); RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } else { if (iscntrl((int)RaCommandInputStr[RaCommandIndex])) { if ((RaCommandInputStr[RaCommandIndex] == '\b') || (RaCommandInputStr[RaCommandIndex] == 0x7F)) { RaCommandInputStr[RaCommandIndex--] = '\0'; RaCommandInputStr[RaCommandIndex] = ' '; if (RaCommandIndex < 0) RaCommandIndex = 0; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGcSTR, RaCommandInputStr); } else { RaInputStatus = RANEWCOMMAND; mvwaddnstr (RaHeaderWindow, 4, 1, " ", COLS - 2); wclrtoeol(RaHeaderWindow); RaWindowImmediate = TRUE; RaRefreshDisplay(); } } else { RaCommandIndex++; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGcSTR, RaCommandInputStr); } } } else break; } break; } case RAGETTINGf: { struct bpf_program localfilter; char *str = NULL; while (select(1, &in, 0, 0, &tv) > 0) { if (read (0, &RaCommandInputStr[RaCommandIndex], 1)) { if ((RaCommandInputStr[RaCommandIndex] == '\n') || (RaCommandInputStr[RaCommandIndex] == '\r')) { RaInputStatus = RANEWCOMMAND; werase(RaAvailableWindow); RaCommandInputStr[RaCommandIndex] = '\0'; if (*RaInputFilter != NULL) free(*RaInputFilter); str = strdup(RaCommandInputStr); bzero ((char *) &localfilter, sizeof (localfilter)); if (ArgusFilterCompile (&localfilter, str, 1, ArgusNetMask) < 0) { mvwprintw (RaHeaderWindow, 4, 1, "%-*s syntax error", strlen(RAGETTINGfSTR) + strlen(RaCommandInputStr), str); } else { mvwprintw (RaHeaderWindow, 4, 1, "%s %s %s", RAGETTINGfSTR, RaCommandInputStr, "Filter accepted"); *RaInputFilter = strdup(str); setArgusRemoteFilter((unsigned char *) str); if (ArgusFilterCode.bf_insns != NULL) free (ArgusFilterCode.bf_insns); bcopy((char *)&localfilter, (char *)&ArgusFilterCode, sizeof(localfilter)); while ((store = (struct ArgusRecordStore *) RaPopQueue(RaAvailableQueue))) RaTimeoutArgusStore(store); while ((store = (struct ArgusRecordStore *) RaPopQueue(RaFailedQueue))) RaTimeoutArgusStore(store); } RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } else { if (iscntrl((int)RaCommandInputStr[RaCommandIndex])) { if ((RaCommandInputStr[RaCommandIndex] == '\b') || (RaCommandInputStr[RaCommandIndex] == 0x7F)) { RaCommandInputStr[RaCommandIndex--] = '\0'; RaCommandInputStr[RaCommandIndex] = ' '; if (RaCommandIndex < 0) RaCommandIndex = 0; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGfSTR, RaCommandInputStr); } else { RaInputStatus = RANEWCOMMAND; mvwaddnstr (RaHeaderWindow, 4, 1, " ", COLS - 2); wclrtoeol(RaHeaderWindow); RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } } else { RaCommandIndex++; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGfSTR, RaCommandInputStr); } } } else break; } } case RAGETTINGt: { while (select(1, &in, 0, 0, &tv) > 0) { if (read (0, &RaCommandInputStr[RaCommandIndex], 1)) { if ((RaCommandInputStr[RaCommandIndex] == '\n') || (RaCommandInputStr[RaCommandIndex] == '\r')) { RaInputStatus = RANEWCOMMAND; werase(RaAvailableWindow); RaTmStruct = localtime((time_t *) &ArgusGlobalTime.tv_sec); RaCommandInputStr[strlen(RaCommandInputStr) - 1] = '\0'; if (check_time_format (RaTmStruct, RaCommandInputStr)) { mvwprintw (RaHeaderWindow, 4, 1, "%-*s", COLS, "Time format error"); } else { mvwprintw (RaHeaderWindow, 4, 1, "%-*s", COLS, "Time range accepted"); tflag++; if (timearg != NULL) free(timearg); timearg = strdup(RaCommandInputStr); } RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } else { if (iscntrl((int)RaCommandInputStr[RaCommandIndex])) { if ((RaCommandInputStr[RaCommandIndex] == '\b') || (RaCommandInputStr[RaCommandIndex] == 0x7F)) { RaCommandInputStr[RaCommandIndex--] = '\0'; RaCommandInputStr[RaCommandIndex] = ' '; if (RaCommandIndex < 0) RaCommandIndex = 0; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGtSTR, RaCommandInputStr); } else { RaInputStatus = RANEWCOMMAND; mvwaddnstr (RaHeaderWindow, 4, 1, " ", COLS - 2); wclrtoeol(RaHeaderWindow); RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } } else { RaCommandIndex++; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGtSTR, RaCommandInputStr); } } } else break; } } case RAGETTINGo: { while (select(1, &in, 0, 0, &tv) > 0) { if (read (0, &RaCommandInputStr[RaCommandIndex], 1)) { glob_t globbuf; if ((RaCommandInputStr[RaCommandIndex] == '\n') || (RaCommandInputStr[RaCommandIndex] == '\r')) { RaCommandInputStr[RaCommandIndex] = '\0'; glob(RaCommandInputStr, 0, NULL, &globbuf); ArgusDeleteFileList(); if (globbuf.gl_pathc > 0) { for (i = 0; i < globbuf.gl_pathc; i++) { if (!(ArgusAddFileList (globbuf.gl_pathv[i], (Cflag ? ARGUS_CISCO_DATA_SOURCE : ARGUS_DATA_SOURCE), -1, -1))) { mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGoSTR, RaCommandInputStr, strerror(errno)); } else { werase(RaHeaderWindow); mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGoSTR, RaCommandInputStr); RaTasksToDo = 1; totalrecords = 0; RaClientTimeout.tv_sec = 0; RaClientTimeout.tv_usec = 10000; if (ArgusProgramArgs != NULL) ArgusFree(ArgusProgramArgs); if ((ArgusProgramArgs = ArgusCalloc (1, MAXSTRLEN)) != NULL) { sprintf (ArgusProgramArgs, "%s -r %s", ArgusProgramName, RaCommandInputStr); if (tflag) { sprintf (&ArgusProgramArgs[strlen(ArgusProgramArgs)], " -t %s", timearg); } if (*RaInputFilter != NULL) { sprintf (&ArgusProgramArgs[strlen(ArgusProgramArgs)], " - %s", *RaInputFilter); } } while ((store = (struct ArgusRecordStore *) RaPopQueue(RaAvailableQueue))) RaTimeoutArgusStore(store); while ((store = (struct ArgusRecordStore *) RaPopQueue(RaFailedQueue))) RaTimeoutArgusStore(store); } } } else mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGoSTR, RaCommandInputStr, " no match"); RaInputStatus = RANEWCOMMAND; werase(RaAvailableWindow); RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } else { if (iscntrl((int)RaCommandInputStr[RaCommandIndex])) { if ((RaCommandInputStr[RaCommandIndex] == '\b') || (RaCommandInputStr[RaCommandIndex] == 0x7F)) { RaCommandInputStr[RaCommandIndex--] = '\0'; RaCommandInputStr[RaCommandIndex] = ' '; if (RaCommandIndex < 0) RaCommandIndex = 0; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGoSTR, RaCommandInputStr); } else { RaInputStatus = RANEWCOMMAND; mvwaddnstr (RaHeaderWindow, 4, 1, " ", COLS - 2); wclrtoeol(RaHeaderWindow); RaWindowImmediate = TRUE; RaRefreshDisplay(); } } else { RaCommandIndex++; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGoSTR, RaCommandInputStr); } } } else break; } break; } case RAGETTINGF: { while (select(1, &in, 0, 0, &tv) > 0) { if (read (0, &RaCommandInputStr[RaCommandIndex], 1)) { if ((RaCommandInputStr[RaCommandIndex] == '\n') || (RaCommandInputStr[RaCommandIndex] == '\r')) { char strbuf[1024], *ptr = strbuf, *tok; int ind = 0; RaInputStatus = RANEWCOMMAND; werase(RaAvailableWindow); RaCommandInputStr[RaCommandIndex] = '\0'; strcpy (ptr, RaCommandInputStr); bzero ((char *)RaSOptionStrings, sizeof(RaSOptionStrings)); while ((tok = strtok(ptr, " ")) != NULL) { RaSOptionStrings[ind++] = tok; ptr = NULL; } RaLabel = NULL; RaProcessSOptions(); werase(RaAvailableWindow); RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } else { if (iscntrl((int)RaCommandInputStr[RaCommandIndex])) { if ((RaCommandInputStr[RaCommandIndex] == '\b') || (RaCommandInputStr[RaCommandIndex] == 0x7F)) { RaCommandInputStr[RaCommandIndex--] = '\0'; RaCommandInputStr[RaCommandIndex] = ' '; if (RaCommandIndex < 0) RaCommandIndex = 0; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGFSTR, RaCommandInputStr); } else { RaInputStatus = RANEWCOMMAND; mvwaddnstr (RaHeaderWindow, 4, 1, " ", COLS - 2); wclrtoeol(RaHeaderWindow); RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } } else { RaCommandIndex++; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGFSTR, RaCommandInputStr); } } } else break; } } case RAGETTINGh: { if (select(1, &in, 0, 0, &tv) > 0 && read(0, &c, 1) == 1) { RaWindowStatus = 1; RaInputStatus = RANEWCOMMAND; mvwaddnstr (RaHeaderWindow, 4, 1, " ", COLS - 2); wclrtoeol(RaHeaderWindow); werase(RaAvailableWindow); RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); } break; } case RAGETTINGm: { if ((c = wgetch(RaWindow)) != ERR) { switch (c) { case KEY_UP: case 'k': mvwprintw (RaAvailableWindow, RaCommandLines, 1, RaCommandArray[RaCommandLines - RaMinCommandLines]); wprintw (RaAvailableWindow, "%s", RaCommandValueArray[RaCommandLines - RaMinCommandLines]()); RaCommandLines = (RaCommandLines > RaMinCommandLines) ? RaCommandLines - 1: RaMinCommandLines; mvwprintw (RaAvailableWindow, RaCommandLines, 1, RaCommandArray[RaCommandLines - RaMinCommandLines]); wstandout(RaAvailableWindow); wprintw (RaAvailableWindow, "%s", RaCommandValueArray[RaCommandLines - RaMinCommandLines]()); wstandend(RaAvailableWindow); break; case KEY_DOWN: case 'j': mvwprintw (RaAvailableWindow, RaCommandLines, 1, RaCommandArray[RaCommandLines - RaMinCommandLines]); wprintw (RaAvailableWindow, "%s", RaCommandValueArray[RaCommandLines - RaMinCommandLines]()); RaCommandLines = (RaCommandLines < RaMaxCommandLines) ? RaCommandLines + 1: RaMaxCommandLines; mvwprintw (RaAvailableWindow, RaCommandLines, 1, RaCommandArray[RaCommandLines - RaMinCommandLines]); wstandout(RaAvailableWindow); wprintw (RaAvailableWindow, "%s", RaCommandValueArray[RaCommandLines - RaMinCommandLines]()); wstandend(RaAvailableWindow); break; case 'D': case 'd': RaWindowStatus = 1; RaInputStatus = RANEWCOMMAND; mvwaddnstr (RaHeaderWindow, 4, 1, " ", COLS - 2); wclrtoeol(RaHeaderWindow); werase(RaAvailableWindow); break; default: break; } } RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); } break; case RAGETTINGu: { while (select(1, &in, 0, 0, &tv) > 0) { if (read (0, &RaCommandInputStr[RaCommandIndex], 1)) { if ((RaCommandInputStr[RaCommandIndex] == '\n') || (RaCommandInputStr[RaCommandIndex] == '\r')) { char strbuf[1024], *endptr = NULL; double value = 0.0, ivalue, fvalue; RaInputStatus = RANEWCOMMAND; RaCommandInputStr[RaCommandIndex] = '\0'; value = strtod(RaCommandInputStr, &endptr); if (RaCommandInputStr != endptr) { fvalue = modf(value, &ivalue); RaUpdateTimeInterval.tv_sec = (int) ivalue; RaUpdateTimeInterval.tv_usec = (int) (fvalue * 1000000.0); bzero (strbuf, 1024); sprintf (strbuf, "%s %6.6f %s", RAGETTINGUPDATESTR, value, " accepted"); mvwaddnstr (RaHeaderWindow, 4, 1, strbuf, COLS - 2); RaUpdateTime = ArgusRealTime; RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); } else { sprintf (strbuf, "%s %s %s", RAGETTINGUPDATESTR, RaCommandInputStr, " syntax error"); mvwaddnstr (RaHeaderWindow, 4, 1, strbuf, COLS - 2); RaRefreshDisplay(); } break; } else { if (iscntrl((int)RaCommandInputStr[RaCommandIndex])) { if ((RaCommandInputStr[RaCommandIndex] == '\b') || (RaCommandInputStr[RaCommandIndex] == 0x7F)) { RaCommandInputStr[RaCommandIndex--] = '\0'; RaCommandInputStr[RaCommandIndex] = ' '; if (RaCommandIndex < 0) RaCommandIndex = 0; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGUPDATESTR, RaCommandInputStr); } else { RaInputStatus = RANEWCOMMAND; mvwaddnstr (RaHeaderWindow, 4, 1, " ", COLS - 2); wclrtoeol(RaHeaderWindow); RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } } else { RaCommandIndex++; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGUPDATESTR, RaCommandInputStr); } } } else break; } } break; case RAGETTINGs: { while (select(1, &in, 0, 0, &tv) > 0) { if (read (0, &RaCommandInputStr[RaCommandIndex], 1)) { if ((RaCommandInputStr[RaCommandIndex] == '\n') || (RaCommandInputStr[RaCommandIndex] == '\r')) { char strbuf[1024], *ptr = strbuf, *tok; int x, ind = 0; RaInputStatus = RANEWCOMMAND; RaCommandInputStr[RaCommandIndex] = '\0'; strcpy (ptr, RaCommandInputStr); bzero ((char *)RaSortAlgorithms, sizeof(RaSortAlgorithms)); while ((tok = strtok(ptr, " ")) != NULL) { for (x = 0; x < MAX_SORT_ALG_TYPES; x++) { if (!strncmp (RaSortKeyWords[x], tok, strlen(RaSortKeyWords[x]))) { RaSortAlgorithms[ind++] = RaSortAlgorithmTable[x]; break; } } ptr = NULL; } RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } else { if (iscntrl((int)RaCommandInputStr[RaCommandIndex])) { if ((RaCommandInputStr[RaCommandIndex] == '\b') || (RaCommandInputStr[RaCommandIndex] == 0x7F)) { RaCommandInputStr[RaCommandIndex--] = '\0'; RaCommandInputStr[RaCommandIndex] = ' '; if (RaCommandIndex < 0) RaCommandIndex = 0; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGSORTSTR, RaCommandInputStr); } else { RaInputStatus = RANEWCOMMAND; mvwaddnstr (RaHeaderWindow, 4, 1, " ", COLS - 2); wclrtoeol(RaHeaderWindow); RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } } else { RaCommandIndex++; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGSORTSTR, RaCommandInputStr); } } } else break; } } break; case RAGETTINGN: { while (select(1, &in, 0, 0, &tv) > 0) { if (read (0, &RaCommandInputStr[RaCommandIndex], 1)) { if ((RaCommandInputStr[RaCommandIndex] == '\n') || (RaCommandInputStr[RaCommandIndex] == '\r')) { Nflag = ((atoi(RaCommandInputStr) < (LINES - (HEADERWINSIZE + 1)) - 3) ? atoi(RaCommandInputStr) : (LINES - (HEADERWINSIZE + 1)) - 3); RaInputStatus = RANEWCOMMAND; werase(RaAvailableWindow); RaWindowModified = RA_MODIFIED; RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } else { if (iscntrl((int)RaCommandInputStr[RaCommandIndex])) { if ((RaCommandInputStr[RaCommandIndex] == '\b') || (RaCommandInputStr[RaCommandIndex] == 0x7F)) { RaCommandInputStr[RaCommandIndex--] = '\0'; RaCommandInputStr[RaCommandIndex] = ' '; if (RaCommandIndex < 0) RaCommandIndex = 0; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGNSTR, RaCommandInputStr); } else { RaInputStatus = RANEWCOMMAND; mvwaddnstr (RaHeaderWindow, 4, 1, " ", COLS - 2); wclrtoeol(RaHeaderWindow); RaWindowImmediate = TRUE; RaRefreshDisplay(); break; } } else { RaCommandIndex++; mvwprintw (RaHeaderWindow, 4, 1, "%s %s", RAGETTINGNSTR, RaCommandInputStr); } } } else break; } } break; } wclrtoeol(RaHeaderWindow); #endif RaUpdateCount++; RaProcessQueue (RaAvailableQueue, ARGUS_STATUS); RaProcessQueue (RaFailedQueue, ARGUS_STATUS); #ifdef ARGUS_CURSES if (RaCursesInit) #endif RaRefreshDisplay(); #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusClientTimeout: current time %s.\n", print_time(&ArgusGlobalTime)); if (ArgusHourlyUpdate++ == 3600) { ArgusDebug (2, "ArgusClientTimeout: current time %s.\n", print_time(&ArgusGlobalTime)); ArgusHourlyUpdate = 1; } #endif } void parse_arg (argc, argv) int argc; char**argv; {} void usage () { fprintf (stderr, "RaTop Version %s\n", version); fprintf (stderr, "usage: %s \n", ArgusProgramName); fprintf (stderr, "usage: %s [options] -S remoteServer [- filter-expression]\n", ArgusProgramName); fprintf (stderr, "usage: %s [options] -r argusDataFile [- filter-expression]\n\n", ArgusProgramName); fprintf (stderr, "options: -a print record summaries on termination.\n"); fprintf (stderr, " -A print application bytes.\n"); fprintf (stderr, " -b dump packet-matching code.\n"); fprintf (stderr, " -c print packet and byte counts.\n"); fprintf (stderr, " -C treat the remote source as a Cisco Netflow source.\n"); fprintf (stderr, " -d print number of from user data capture buffer.\n"); fprintf (stderr, " format: num | s | d | s:d\n"); #if defined (ARGUSDEBUG) fprintf (stderr, " -D specify debug level\n"); #endif fprintf (stderr, " -e convert user data using method.\n"); fprintf (stderr, " Supported types are and .\n"); fprintf (stderr, " -E write records that are rejected by the filter into \n"); fprintf (stderr, " -F read configuration from .\n"); fprintf (stderr, " -g print record time duration.\n"); fprintf (stderr, " -G print both start and last time values.\n"); fprintf (stderr, " -h print help.\n"); fprintf (stderr, " -i print source probe id.\n"); fprintf (stderr, " -I print transaction state and option indicators.\n"); fprintf (stderr, " -l print last time values [default is start time].\n"); fprintf (stderr, " -m print MAC addresses.\n"); fprintf (stderr, " -n don't convert numbers to names.\n"); fprintf (stderr, " -p print fractional time with precision.\n"); fprintf (stderr, " -P specify remote argus (tcp/561).\n"); fprintf (stderr, " -q quiet mode. don't print record outputs.\n"); fprintf (stderr, " -r read argus data . '-' denotes stdin.\n"); fprintf (stderr, " -R print out response data when availabile.\n"); fprintf (stderr, " -S specify remote argus .\n"); fprintf (stderr, " -t specify for reading records.\n"); fprintf (stderr, " format: timeSpecification[-timeSpecification]\n"); fprintf (stderr, " timeSpecification: [[[yyyy/]mm/]dd.]hh[:mm[:ss]]\n"); fprintf (stderr, " [yyyy/]mm/dd\n"); fprintf (stderr, " -T attach to remote server for T seconds.\n"); fprintf (stderr, " -u print time in Unix time format.\n"); #ifdef ARGUS_SASL fprintf (stderr, " -U specify authentication information.\n"); #endif fprintf (stderr, " -w write output to . '-' denotes stdout.\n"); fprintf (stderr, " -z print Argus TCP state changes.\n"); fprintf (stderr, " -Z print actual TCP flag values.<'s'rc | 'd'st | 'b'oth>\n"); exit(1); } #ifdef ARGUS_CURSES int RaPrintCursesStr (char *); int RaPrintCursesStr (char *str) { if (!(RaCursesInit)) RaInitCurses (); return (1); } #endif void RaProcessRecord (struct ArgusRecord *argus) { if (argus->ahdr.type & ARGUS_MAR) RaProcessManRecord (argus); else { switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: RaProcessTCPRecord (argus); break; case IPPROTO_UDP: RaProcessUDPRecord (argus); break; case IPPROTO_ICMP: RaProcessICMPRecord (argus); break; default: RaProcessIPRecord (argus); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: RaProcessARPRecord (argus); break; default: RaProcessNonIPRecord (argus); break; } } } void RaProcessSrvRecord (struct ArgusServiceRecord *srv) { struct ArgusRecord *argus = srv->argus; struct ArgusRecordStore *store; struct ArgusRecordData *data = NULL; struct RaPolicyStruct *rap; struct ArgusFlow *flow = &argus->argus_far.flow; int RaTimeout = -1, RaIdleTimeout = 30; RaThisActiveIndex = 0; bcopy((char *) flow, (char *) RaArgusFlow, sizeof(struct ArgusFlow)); rap = RaFlowModel->policy[RaThisFlowModelIndex]; if (RaPolicyMatch (argus, rap)) { RaModifyFlow(rap, argus, RaFlowModel); if (Sflag || Cflag) { RaTimeout = rap->ArgusTimeout; RaIdleTimeout = rap->ArgusIdleTimeout; } else { RaTimeout = 1000000; RaIdleTimeout = 1000000; } } else { if (Sflag || Cflag) { RaTimeout = 60; RaIdleTimeout = 120; } else { RaTimeout = 60; RaIdleTimeout = 120; } RaModifyDefaultFlow(argus); } if ((store = RaFindArgusRecord(&RaHashTable, argus)) == NULL) if ((store = RaFindRevArgusRecord(&RaHashTable, argus)) != NULL) { } if (store) { RaThisArgusStore = store; if (RaCheckTimeout (store, argus)) RaSendArgusRecord(store); if ((data = store->data[0]) == NULL) { if ((data = RaNewArgusData(argus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; data->status |= srv->status & RA_SVCTEST; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *) &data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } store->data[0] = data; } else ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); } else RaMergeArgusRecord(argus, store, RaThisActiveIndex); RaUpdateArgusStore(argus, store); if (RaServerMode) { if ((data = store->data[0]) != NULL) { if ((data->status & ARGUS_FAR_SRCADDR_MODIFIED) && (store->status & RA_SVCPASSED)) { if (store->qhdr.queue == RaFailedQueue) { RaRemoveFromQueue(RaFailedQueue, &store->qhdr); RaAddToQueue(RaAvailableQueue, &store->qhdr); } } else { if (store->qhdr.queue == RaAvailableQueue) { RaRemoveFromQueue(RaAvailableQueue, &store->qhdr); RaAddToQueue(RaFailedQueue, &store->qhdr); } } } } } else { if ((store = RaNewArgusStore(argus)) != NULL) { struct ArgusRecordData *data = NULL; store->status |= RA_MODIFIED; store->status |= srv->status & RA_SVCTEST; store->ArgusTimeout = RaTimeout; store->ArgusIdleTimeout = RaIdleTimeout; RaThisArgusStore = store; if ((data = RaNewArgusData(argus)) != NULL) { data->farhdrstatus = ArgusIndexRecord (data->argus, data->farhdrs); data->status |= RA_MODIFIED; if (data->farhdrstatus & ARGUS_AGR_DSR_STATUS) { double sumtime; bcopy((char *)data->farhdrs[ARGUS_AGR_DSR_INDEX], (char *)&data->agr, sizeof(data->agr)); data->act.n = data->agr.act.n; sumtime = data->agr.act.meanval * data->agr.act.n; data->act.sumtime = sumtime; data->act.sumsqrd = (data->agr.act.n * pow(data->agr.act.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.act.n; data->idle.n = data->agr.idle.n; sumtime = data->agr.idle.meanval * data->agr.idle.n; data->idle.sumtime = sumtime; data->idle.sumsqrd = (data->agr.idle.n * pow(data->agr.idle.stdev, 2.0)) + pow(sumtime, 2.0)/data->agr.idle.n; } store->data[0] = data; if ((store->rahtblhdr = RaAddHashEntry (&RaHashTable, store)) != NULL) { if (!(RaServerMode) && (store->status & RA_SVCPASSED)) RaAddToQueue(RaAvailableQueue, &store->qhdr); else RaAddToQueue(RaFailedQueue, &store->qhdr); } } else ArgusLog (LOG_ERR, "RaNewArgusData failed %s\n", strerror(errno)); RaUpdateArgusStore(argus, store); } else ArgusLog (LOG_ERR, "RaNewArgusStore failed %s\n", strerror(errno)); } RaWindowModified = RA_MODIFIED; #ifdef ARGUSDEBUG ArgusDebug (6, "RaProcessSrvRecord: done\n"); #endif } void RaProcessManRecord (struct ArgusRecord *argus) { char *str = NULL; if (!(qflag || wfile)) { str = get_man_string (argus); #ifdef ARGUS_CURSES RaPrintCursesStr (str); #endif } } struct ArgusServiceRecord ArgusThisSrv; void RaProcessTCPRecord (struct ArgusRecord *argus) { char *str = NULL; if (!(qflag || wfile)) { str = get_tcp_string (argus); #ifdef ARGUS_CURSES RaPrintCursesStr (str); #endif } ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; RaProcessSrvRecord (&ArgusThisSrv); } void RaProcessICMPRecord (struct ArgusRecord *argus) { char *str = NULL; if (!(qflag || wfile)) { str = get_icmp_string (argus); #ifdef ARGUS_CURSES RaPrintCursesStr (str); #endif } ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; RaProcessSrvRecord (&ArgusThisSrv); } void RaProcessUDPRecord (struct ArgusRecord *argus) { char *str = NULL; if (!(qflag || wfile)) { str = get_udp_string (argus); #ifdef ARGUS_CURSES RaPrintCursesStr (str); #endif } ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (argus->argus_far.flow.ip_flow.tp_p == ARGUS_RTP_FLOWTAG) if (!((argus->argus_far.src.count > 3) || (argus->argus_far.dst.count > 3))) argus->argus_far.flow.ip_flow.tp_p = 0; if (Rflag) if (!((argus->argus_far.src.count == 1) && (argus->argus_far.dst.count == 1))) ArgusThisSrv.status = RA_SVCFAILED; RaProcessSrvRecord (&ArgusThisSrv); } void RaProcessIPRecord (struct ArgusRecord *argus) { ArgusThisSrv.argus = argus; ArgusThisSrv.status = RA_SVCPASSED; if (Rflag) if (!((argus->argus_far.src.count == 1) && (argus->argus_far.dst.count == 1))) ArgusThisSrv.status = RA_SVCFAILED; RaProcessSrvRecord (&ArgusThisSrv); } void RaProcessARPRecord (struct ArgusRecord *argus) { } void RaProcessNonIPRecord (struct ArgusRecord *argus) { } int RaSendArgusRecord(struct ArgusRecordStore *store) { unsigned char buf[4098]; struct ArgusRecordData *data; struct ArgusRecord *argus = NULL; struct ArgusAGRStruct *agr = NULL; int retn = 0, i; for (i = 0; i < RaHistoTimeSeries; i++) { if ((data = store->data[i]) != NULL) { argus = data->argus; if (argus && (data->status & RA_MODIFIED)) { if (data->act.n > 0) { data->agr.act.n = data->act.n; data->agr.act.meanval = data->act.sumtime/data->act.n; data->agr.act.stdev = (unsigned int) sqrt (data->act.sumsqrd/data->act.n - pow (data->act.sumtime/data->act.n, 2.0)); } if (data->idle.n > 0) { data->agr.idle.n = data->idle.n; data->agr.idle.meanval = data->idle.sumtime/data->idle.n; data->agr.idle.stdev = (unsigned int) sqrt (data->idle.sumsqrd/data->idle.n - pow (data->idle.sumtime/data->idle.n, 2.0)); } ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) != NULL) { bcopy ((char *)&data->agr, (char *)agr, data->agr.length); } else { if (ArgusFlowModelFile && (data->agr.count > 1)) { bzero (buf, sizeof(buf)); bcopy ((char *)argus, buf, argus->ahdr.length); argus = (struct ArgusRecord *) buf; bcopy ((char *)&data->agr, &buf[argus->ahdr.length], data->agr.length); argus->ahdr.length += data->agr.length; argus->ahdr.status |= ARGUS_MERGED; ArgusFree (data->argus); data->argus = RaCopyArgusRecord(argus); ArgusThisFarStatus = ArgusIndexRecord(data->argus, ArgusThisFarHdrs); } } } } } store->qhdr.logtime = ArgusGlobalTime; #ifdef ARGUSDEBUG ArgusDebug (4, "RaSendArgusRecord(0x%x) done.\n", store); #endif return (retn); } #include #include #define RA_MAXQSCAN 100000 void RaProcessQueue(struct RaQueueStruct *queue, unsigned char status) { struct ArgusRecordData *data = NULL; struct ArgusRecordStore *obj = NULL; int cnt = 0; switch (status) { case ARGUS_STOP: while ((obj = (struct ArgusRecordStore *) RaPopQueue(queue)) != NULL) RaTimeoutArgusStore(obj); break; default: if ((cnt = ((queue->count > RA_MAXQSCAN) ? RA_MAXQSCAN : queue->count)) != 0) { while (cnt--) { if ((obj = (struct ArgusRecordStore *) RaPopQueue(queue)) != NULL) { if (RaCheckTimeout(obj, NULL)) { RaTimeoutArgusStore(obj); } else { if ((RaServerMode) && (data = obj->data[0]) != NULL) { if ((data->status & ARGUS_FAR_SRCADDR_MODIFIED) && (obj->status & RA_SVCPASSED)) { RaAddToQueue(RaAvailableQueue, &obj->qhdr); } else { RaAddToQueue(RaFailedQueue, &obj->qhdr); } } else RaAddToQueue(queue, &obj->qhdr); } } else cnt++; } } break; } #ifdef ARGUSDEBUG ArgusDebug (4, "RaProcessQueue (0x%x, %d) returning\n", queue, status); #endif } void RaUpdateWindow (WINDOW *window, struct RaQueueStruct *queue) { struct ArgusAGRStruct *agr = NULL; struct ArgusRecord *argus = NULL; struct ArgusQueueHeader *qhdr; struct ArgusFlow *flow = NULL; int i, x, cnt, attr = A_NORMAL; short color = COLOR_WHITE; char *str = NULL; char buf[2048], tbuf[MAXSTRLEN]; if (RaWindowModified) { if (RaWindowStatus && ((qhdr = queue->start) != NULL)) { RaSortQueue (queue); RaActiveCons = 0; RaClosingCons = 0; RaNoResponse = 0; cnt = ((Nflag > 0) ? Nflag : RaWindowLines - 1); cnt = (cnt > (queue->count - RaWindowStartLine)) ? (queue->count - RaWindowStartLine) : cnt; if (cnt > 0) { mvwaddnstr (RaHeaderWindow, 4, 1, RaSrvStatsFlowModelDesc[RaThisFlowModelIndex], COLS - 2); wclrtoeol(RaHeaderWindow); } for (x = 0, i = RaWindowStartLine; x < cnt; x++, i++) { attr = A_NORMAL; color = COLOR_WHITE; if (queue->array[i] != NULL) { struct ArgusRecordStore *store = (struct ArgusRecordStore *) queue->array[i]; struct ArgusRecordData *data = store->data[0]; if (data && ((argus = data->argus) != NULL)) { if (RaLabel == NULL) RaLabel = RaGenerateLabel(argus); if (data->act.n > 0) { data->agr.act.n = data->act.n; data->agr.act.meanval = data->act.sumtime/data->act.n; data->agr.act.stdev = (unsigned int) sqrt (data->act.sumsqrd/data->act.n - pow (data->act.sumtime/data->act.n, 2.0)); } if (data->idle.n > 0) { data->agr.idle.n = data->idle.n; data->agr.idle.meanval = data->idle.sumtime/data->idle.n; data->agr.idle.stdev = (unsigned int) sqrt (data->idle.sumsqrd/data->idle.n - pow (data->idle.sumtime/data->idle.n, 2.0)); } ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); if ((agr = (struct ArgusAGRStruct *) ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX]) != NULL) bcopy ((char *)&data->agr, (char *)agr, agr->length); else { bcopy ((char *) argus, buf, argus->ahdr.length); argus = (struct ArgusRecord *) buf; if (ArgusFlowModelFile && (data->agr.count > 1)) { bcopy ((char *)&data->agr, &buf[argus->ahdr.length], data->agr.length); argus->ahdr.length += data->agr.length; argus->ahdr.status |= ARGUS_MERGED; ArgusThisFarStatus = ArgusIndexRecord(argus, ArgusThisFarHdrs); ArgusFree (data->argus); data->argus = RaCopyArgusRecord(argus); ArgusThisFarStatus = ArgusIndexRecord(data->argus, ArgusThisFarHdrs); argus = data->argus; } } flow = &argus->argus_far.flow; if (!(data->status & ARGUS_FAR_SRCADDR_MODIFIED)) flow->ip_flow.ip_src = data->flow.ip_flow.ip_src; if (!(data->status & ARGUS_FAR_DSTADDR_MODIFIED)) flow->ip_flow.ip_dst = data->flow.ip_flow.ip_dst; if (!(data->status & ARGUS_FAR_PROTO_MODIFIED)) flow->ip_flow.ip_p = data->flow.ip_flow.ip_p; if (!(data->status & ARGUS_FAR_SRCPORT_MODIFIED)) flow->ip_flow.sport = data->flow.ip_flow.sport; if (!(data->status & ARGUS_FAR_DSTPORT_MODIFIED)) flow->ip_flow.dport = data->flow.ip_flow.dport; if (!(data->status & ARGUS_FAR_TPVAL_MODIFIED)) flow->ip_flow.tp_p = data->flow.ip_flow.tp_p; switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: { int status; struct ArgusTCPObject *tcp = NULL; if (ArgusThisFarStatus & ARGUS_TCP_DSR_STATUS) tcp = (struct ArgusTCPObject *)ArgusThisFarHdrs[ARGUS_TCP_DSR_INDEX]; if ((tcp != NULL) && ((status = tcp->state) != 0)) { if ((status & ARGUS_NORMAL_CLOSE) || (status & ARGUS_RESET) || (status & ARGUS_FIN) || (status & ARGUS_FIN_ACK)) { RaClosingCons++; } else if (status & ARGUS_CON_ESTABLISHED) { RaActiveCons++; } } else { if (argus->argus_far.src.count && argus->argus_far.dst.count) { RaActiveCons++; } else { RaNoResponse++; } } break; } case IPPROTO_UDP: case IPPROTO_ICMP: if (argus->argus_far.src.count && argus->argus_far.dst.count) { RaActiveCons++; } else { RaNoResponse++; } break; default: if (argus->argus_far.src.count && argus->argus_far.dst.count) { RaActiveCons++; } else { RaNoResponse++; } break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: default: break; } str = get_argus_string (argus); attr = A_NORMAL; #ifdef ARGUS_CURSES bzero (tbuf, MAXSTRLEN); sprintf (tbuf, "%3d %s", i + 1, str); mvwaddnstr (window, x + 2, 2, tbuf, COLS - 3); wclrtoeol(window); #else fprintf (stdout, "%3d %s", i, str); #endif } } else break; } #ifdef ARGUS_CURSES if (i < queue->count) mvwaddnstr (window, x + 2, 0, "-more-\n", COLS - 3); wclrtobot(window); #endif } #ifdef ARGUS_CURSES wnoutrefresh(window); #endif } RaWindowModified = 0; } char RaGetStrBuf[MAXSTRLEN]; char * RaGetCiscoServers(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%s", (Cflag ? "yes" : "no")); return(retn); } char * RaGetNoOutputStatus(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%s", (qflag ? "yes" : "no")); return(retn); } char * RaGetUserAuth(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%s", ustr); return(retn); } char * RaGetUserPass(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%s", pstr); return(retn); } char * RaGetOutputFile(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%s", wfile); return(retn); } char * RaGetExceptionOutputFile(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%s", exceptfile); return(retn); } char * RaGetTimeRange(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%s", timearg); return(retn); } char * RaGetRunTime(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%d", Tflag); return(retn); } char * RaGetFieldDelimiter(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); if (RaFieldDelimiter == '\0') sprintf(RaGetStrBuf, "'\\0'"); else sprintf(RaGetStrBuf, "'%c'", RaFieldDelimiter); return(retn); } char * RaGetTimeFormat(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%s", RaTimeFormat); return(retn); } char * RaGetPrecision(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%d", pflag); return(retn); } char * RaGetTimeSeries(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%s", (Hflag ? "yes" : "no")); return(retn); } char * RaGetValidateStatus(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%s", (Vflag ? "yes" : "no")); return(retn); } char * RaGetNumber(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%d", Nflag); return(retn); } char * RaGetDebugLevel(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%d", Argusdflag); return(retn); } char * RaGetUserDataArg(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); if (ArgusSrcUserDataLen || ArgusDstUserDataLen) { if (ArgusSrcUserDataLen == ArgusDstUserDataLen) sprintf (RaGetStrBuf, "d%d", ArgusSrcUserDataLen); else { sprintf (RaGetStrBuf, "d"); if (ArgusSrcUserDataLen) sprintf (&RaGetStrBuf[strlen(RaGetStrBuf)], "s:%d", ArgusSrcUserDataLen); if (ArgusDstUserDataLen) sprintf (&RaGetStrBuf[strlen(RaGetStrBuf)], "d:%d", ArgusDstUserDataLen); } } else retn = NULL; return (retn); } char * RaGetUserDataEncode(void) { char *retn = RaGetStrBuf, *str = NULL; bzero(RaGetStrBuf, MAXSTRLEN); switch (eflag) { case ARGUS_ENCODE_ASCII: str = "ascii"; break; case ARGUS_ENCODE_32: str = "encode32"; break; case ARGUS_ENCODE_64: str = "encode64"; break; } sprintf(RaGetStrBuf, "%s", str); return(retn); } char * RaGetHostFieldLength(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%d", hfield); return(retn); } char * RaGetPortFieldLength(void) { char *retn = RaGetStrBuf; bzero(RaGetStrBuf, MAXSTRLEN); sprintf(RaGetStrBuf, "%d", pfield); return(retn); } argus-clients-2.0.6.fixes.1/ratop/ratop.h0000664000076600007660000000351607640610353013706 /* * Argus Client Software. Tools to read, analyze and manage Argus data. * Copyright (c) 2000-2003 QoSient, LLC * All rights reserved. * * 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 RaTop_h #define RaTop_h #include #include #include #include #include #include #include #include int RaCheckTimeout(struct ArgusRecordStore *obj, struct ArgusRecord *); void RaProcessQueue(struct RaQueueStruct *, unsigned char state); void error_end(int rno); void end(int signo); void stop(int signo); void window_size(int signo); void do_key(char c); /* configurable field display support */ int pflags[30]; int sflags[10]; int Numfields; #define MAXLINES 2048 #if !defined(MAXNAMELEN) #define MAXNAMELEN 1024 #endif /* this is what procps top does by default, so let's do this, if nothing is * specified */ #ifndef DEFAULT_SHOW /* 0 1 2 3 */ /* 0123456789012345678901234567890 */ #define DEFAULT_SHOW "AbcDgHIjklMnoTP|qrsuzyV{EFWX" #endif char Fields[256] = ""; struct termios RaOrigTty; #endif argus-clients-2.0.6.fixes.1/contrib/0000775000076600007660000000000007764241712013004 5argus-clients-2.0.6.fixes.1/contrib/Argus-perl-2.00/0000775000076600007660000000000007764241724015405 5argus-clients-2.0.6.fixes.1/contrib/Argus-perl-2.00/Argus.pm0000664000076600007660000000701207551075061016735 use Date::Manip; Date_Init("DateFormat = NONUS"); #change to US for mm/dd package Argus; use Argus::Support; use vars qw ($Client_bin $RA $Local_IP_re $LocalTimeZone_re $Local_domain $Local_domain_re $Def_Host $Def_Port $Archive_root $Error @Errors $Accuracy $Notify $Home $Client_path $NotConfigured $Archive_dir_template $Archive_file_template); # Installation specific vars if( defined $ENV{ARGUSHOME} ) { $Home = $ENV{ARGUSHOME}; } else { $Home = $ENV{HOME}; } $Client_path = "/usr/local/bin"; if( defined $ENV{ARGUSARCHIVE} ) { $Archive_root = $ENV{ARGUSARCHIVE}; } else { $Archive_root = "$Home/data"; } # Template for directory stucture where archived data is stored. # By default Argus::Archive assumes a directory stucture of the form # "$Archive_root/$Archive_dir_template/ where $Archive_dir_template # is and strftime format string. # $Archive_dir_template = "%Y/%m/%d"; # eg 2001/03/05 #$Archive_dir_template = "%Y.%m.%d"; # eg 2001.03.05 # an RE that will match all argus log files (you may have other file # stored in the directory -- I do) Argus::Archive assumes (by default) # that sorting the filenames lexically will yeild the files in time # order $Archive_file_template = "^argus*"; # If your archive tree does not conform to the above assumptions you # will need to modify the Argus/Archive.pm file to do 'the right thing' # with your archive structure. $Def_Host = 'localhost'; $Def_Port = '561'; # Logger of errors and warnings. This variable sets the default destination # for errors and warnings produced by the scripts. They may be overridden in the # config modules for the individual scripts # defaults to STDERR $LOG_TO = 'SYSLOG:Argus:deamon:warning:unix'; #$LOG_TO = 'Filename'; # site specific vars $Local_IP = '192.168'; $Local_IP_re = '^192\.168|202\.37\.88\.'; # domains with same timezone - useful in NZ ;-) less useful elsewhere # used to decide whether to report times in local time or UTC. $LocalTimeZone_re = '\.us$'; $Local_domain_re = 'qosient\.com\.us$'; $Local_domain = 'qosient.com'; # who gets reports ? $Notify = "carter\@$Local_domain"; # How accurate are log times ? $Accuracy = "GPS synchronized"; ######################################################################## # determine OS stuff Based on Date::Manip.pm # # Copyright (c) 1995-2000 Sullivan Beck. All rights reserved. # This program is free software; you can redistribute it and/or modify it # under the same terms as Perl itself. # ########################################################################### ########################################################################### use vars qw($OS %Lang %Curr %Cnf); # Determine the type of OS... $OS="Unix"; $OS="Windows" if ((defined $^O and $^O =~ /MSWin32/i || $^O =~ /Windows_95/i || $^O =~ /Windows_NT/i) || (defined $ENV{OS} and $ENV{OS} =~ /MSWin32/i || $ENV{OS} =~ /Windows_95/i || $ENV{OS} =~ /Windows_NT/i)); $OS="Mac" if ((defined $^O and $^O =~ /MacOS/i) || (defined $ENV{OS} and $ENV{OS} =~ /MacOS/i)); $OS="MPE" if (defined $^O and $^O =~ /MPE/i); $OS="OS2" if (defined $^O and $^O =~ /os2/i); $OS="VMS" if (defined $^O and $^O =~ /VMS/i); # Determine if we're doing taint checking $NoTaint = eval { local $^W; unlink "$^X$^T"; 1 }; 1; argus-clients-2.0.6.fixes.1/contrib/Argus-perl-2.00/HISTORY0000664000076600007660000000060307551075061016401 ####################################################################### # HISTORY ####################################################################### Important changes marked with *** (as of 5.20) Written by: Russell Fulton (r.fulton@auckland.ac.nz) Any suggestions, bug reports, or donations :-) should be sent to either one of us. Version 1.0 2001-01-17 Getting started argus-clients-2.0.6.fixes.1/contrib/Argus-perl-2.00/INSTALL0000664000076600007660000000206307551075061016350 Before you install perl support for argus, check out the variables at the top of Argus.pm and be sure to delete the $NotConfigured. You will almost certainly want to modify some of the configuration variables. You will also probably want to edit Watcher.pm and Slowscan.pm if you wish to use these scripts. These files are installed in the ../lib/Argus directory and you will probably need to fine tune the options as you gain experience with the sripts. AUTOMATIC INSTALLATION To install, just type perl Makefile.PL make make install This will install all the files under the either $ARGUSHOME or $HOME directories. Make sure that either of these enviroment variables are set appropriately Currently there is little in the way of testing. make leaves the files ready for installation under the blib directory so you may want to move them to their final destinations by hand. However be warned, make alters some paths in the scripts (look for the #^# marker in the scripts). It is vital that these paths reflect the real location of the library files etc. argus-clients-2.0.6.fixes.1/contrib/Argus-perl-2.00/MANIFEST0000664000076600007660000000036507551075061016453 HISTORY INSTALL MANIFEST Makefile.PL Argus.pm Argus/Archive.pm Argus/SlowScan.pm Argus/Support.pm Argus/Watcher.pm ra.conf README TODO watcher.pp slowscan.pp look_for.pp t/archive_get_archive_dir.t t/archive_get_files.t t/runtests fix-script.PL argus-clients-2.0.6.fixes.1/contrib/Argus-perl-2.00/Makefile.PL0000664000076600007660000000212007551075061017263 use ExtUtils::MakeMaker; if( defined $ENV{ARGUSHOME} ) { $Home = $ENV{ARGUSHOME}; } else { $Home = $ENV{HOME}; } WriteMakefile( NAME => "Argus", DISTNAME => "Argus-perl", VERSION => "2.00", PREREQ_PM => { Net::SMTP => 1.0, Date::Manip => 1.0 }, PL_FILES => { 'fix-script.PL' => ['watcher', 'slowscan','look_for'] }, PM => { 'ra.conf' => '$(INST_LIBDIR)/ra.conf', 'Argus.pm' => '$(INST_LIBDIR)/Argus.pm', 'Argus/Support.pm' => '$(INST_LIBDIR)/Argus/Support.pm', 'Argus/Archive.pm' => '$(INST_LIBDIR)/Argus/Archive.pm', 'Argus/SlowScan.pm' => '$(INST_LIBDIR)/Argus/SlowScan.pm', 'Argus/Watcher.pm' => '$(INST_LIBDIR)/Argus/Watcher.pm', }, EXE_FILES => ['slowscan', 'watcher', 'look_for'], PREFIX => $Home, INSTALLSITELIB => "$Home/lib", INSTALLARCHLIB => $Home, INSTALLMAN1DIR => $Home, INSTALLMAN3DIR => $Home, ABSTRACT => 'Scripts and modules to support Argus IP audit tool.', AUTHOR => 'Russell Fulton ', 'dist' => {COMPRESS=>'gzip',SUFFIX=>'gz'} ); argus-clients-2.0.6.fixes.1/contrib/Argus-perl-2.00/README0000664000076600007660000001025407551075061016200 For information on installing Argus::Archive, see the INSTALL file included in the distribution. For other documentation, see the Archive.pod file. Please send questions or bug reports to the argus mailing list. AUTHORS Russell Fulton (r.fulton@auckland.au.nz). Look_for script takes a supplied filter and runs ra with the filter over archived data, you can specify dates to start and finish or you can specify things like today, yesterday, thisweek, lastweek etc. the scan detection scripts. Why have two scripts for detecting scans? Well partly belts and braces but mostly because this is an ongoing research project and the two scripts use somewhat different strategies to detect scans. Watcher is a 'real time' script that watches output from a live server, scan_watch is an overnight job that processes a days logs in one go. It maintains records of activity for a long time (up to 7 days be default) and thus is capable of spotting very slow scans (I regularly find scans with below 10 probes per day -- there are currently about 80 probing udp-137). Over the last two weeks I have added udp scan detection. This is a mixed blessing because there are so many machines infected by worms that scan on port udp-137. These scans are typically about 10 probes per day but the sheer number of them tends to overwhelm everything else. You can stop it looking at udp by altering the ra filter to ignore udp. These scripts have been tuned over the last two years to our network traffic volumes, if you put them on a very busy network you will have to tweak the parameters to get the resource usage and sensitivity approriate. I suspect that scan-watch will not work for those of you who have OC3s, it will simply consume too much memory, but then you may have machines with much more memory than I have. The distribution has two directories: bin and lib, bin has the executable scripts and lib has the perl modules. I have tried to move all site specific configuration out into the module files: Argus.pm Argus/Watcher.pm and Argus/Slowscan.pm I hope that others will adopt this scheme and convert your perl scripts to use this scheme and, of course, add them to the contrib distribution. One thing that made me reluctant in the past to distribute my code was that a good deal of it is necessarily site specific, particularly anything that accesses archived data. I have attempted to deal with this problem (see Argus::Archive below). Argus.pm contains all the generic site specific information (what your local IP address are, where is your usual argus server, etc.) Argus/Watcher.pm has addition configuration information for watcher and Argus/Slowscan.pm has stuff for scan_watch (you have noticed I can't decide whether to call it slowscan or scanwatch ;-) Both scan_watch and look_for read archived argus data and they do this by calling module Argus/Archive.pm. The idea is that you will need to modify this module to match the layout of your own archive. There is also Argus/Support.pm which contains a lot of code that is common to the two major scripts. Much of this code is to do with formating long lists of IP addresses and port numbers. The scripts use a few CPAN modules: use Date::Manip; # handles dates and times use Net::SMTP; # so we can mail reports -- this is part of libnet # bundle which is installed by default on many systems use Data::Dumper; # store data structures to disk I am not aware of any perl version dependencies -- should run with any reasonably recent version of perl 5. I think that about wraps it up. There are bound to be details I have fogotten so if you have any problems drop me a line. I will be away from work for the rest of the week (on babysitting duty -- if you can describe keeping an bored 12 yearold out of mischief during school holidays babysitting ;-) I will be checking my mail at least once a day but don't expect lightning response. As always comments (positive and negative) welcome. I particularly want to know what needs to be better documented. I would also like suggestions on how to automatically set things like the bin dir for ra and lib directory. Could this be done via make install or configure? argus-clients-2.0.6.fixes.1/contrib/Argus-perl-2.00/TODO0000664000076600007660000000030507551075061016004 ######################################################################## # MISC ######################################################################## Add routines to create and manage Archive. argus-clients-2.0.6.fixes.1/contrib/Argus-perl-2.00/fix-script.PL0000775000076600007660000000070607551075061017651 use Argus; my $script = shift; if( defined $Argus::NotConfigured ) { die "You do not appear to have edited the Argus.pm file"; } open( SCRIPT, "$script.pp") or die "Can't open $script:$!"; open(NEW, ">$script") or die "Can't open $script for write:$!"; while(