Преглед на файлове

Add ./tarball_archive/symon-2.55.tar.gz

Wictor Lund преди 3 години
родител
ревизия
7e804206ab
променени са 65 файла, в които са добавени 2120 реда и са изтрити 1144 реда
  1. 23 1
      symon/CHANGELOG
  2. 23 1
      symon/INSTALL
  3. 3 3
      symon/Makefile
  4. 12 3
      symon/Makefile.inc
  5. 14 0
      symon/client/Makefile
  6. 288 0
      symon/client/SymuxClient.pm
  7. 16 0
      symon/client/getsymonitem.pl
  8. 218 182
      symon/lib/data.c
  9. 86 62
      symon/lib/data.h
  10. 32 29
      symon/lib/error.c
  11. 6 6
      symon/lib/error.h
  12. 60 54
      symon/lib/lex.c
  13. 27 26
      symon/lib/lex.h
  14. 169 61
      symon/lib/net.c
  15. 15 7
      symon/lib/net.h
  16. 7 7
      symon/lib/xmalloc.c
  17. 6 6
      symon/lib/xmalloc.h
  18. 4 2
      symon/ports/symon/Makefile
  19. 25 0
      symon/ports/symon/pkg/DEINSTALL
  20. 2 2
      symon/ports/symon/pkg/DEINSTALL-mon
  21. 67 0
      symon/ports/symon/pkg/INSTALL
  22. 5 1
      symon/ports/symon/pkg/PLIST
  23. 4 1
      symon/ports/symon/pkg/PLIST-mux
  24. 1 0
      symon/ports/symon/pkg/PLIST-web
  25. 3 3
      symon/symon/Makefile
  26. 2 2
      symon/symon/c_config.sh
  27. 51 55
      symon/symon/readconf.c
  28. 2 14
      symon/symon/readconf.h
  29. 15 15
      symon/symon/sm_cpu.c
  30. 80 0
      symon/symon/sm_debug.c
  31. 18 20
      symon/symon/sm_if.c
  32. 14 14
      symon/symon/sm_io.c
  33. 16 17
      symon/symon/sm_mem.c
  34. 10 10
      symon/symon/sm_pf.c
  35. 8 7
      symon/symon/symon.8
  36. 48 40
      symon/symon/symon.c
  37. 19 16
      symon/symon/symon.h
  38. 38 41
      symon/symon/symonnet.c
  39. 2 2
      symon/symon/symonnet.h
  40. 1 0
      symon/symon2web/Makefile
  41. 1 0
      symon/symon2web/class_cpu.inc
  42. 1 2
      symon/symon2web/class_graph.inc
  43. 1 0
      symon/symon2web/class_if.inc
  44. 1 0
      symon/symon2web/class_io.inc
  45. 1 0
      symon/symon2web/class_mem.inc
  46. 1 0
      symon/symon2web/class_pf.inc
  47. 1 0
      symon/symon2web/graph_cpu.php
  48. 1 0
      symon/symon2web/graph_if.php
  49. 1 0
      symon/symon2web/graph_io.php
  50. 1 0
      symon/symon2web/graph_mem.php
  51. 1 0
      symon/symon2web/graph_pf.php
  52. 2 0
      symon/symon2web/index.php
  53. 78 0
      symon/symon2web/test_config.php
  54. 0 4
      symon/symux/.gdbinit
  55. 21 4
      symon/symux/c_smrrds.sh
  56. 138 109
      symon/symux/readconf.c
  57. 3 5
      symon/symux/readconf.h
  58. 142 96
      symon/symux/share.c
  59. 15 14
      symon/symux/share.h
  60. 20 15
      symon/symux/symux.8
  61. 80 71
      symon/symux/symux.c
  62. 2 2
      symon/symux/symux.conf
  63. 3 3
      symon/symux/symux.h
  64. 158 98
      symon/symux/symuxnet.c
  65. 7 11
      symon/symux/symuxnet.h

+ 23 - 1
symon/CHANGELOG

@@ -1,3 +1,25 @@
+29/11/2002 - 2.55
+
+   Markus Friedl reported that unresolvable ip addresses cannot be used in the
+   configuration file - fixed.
+
+   Overhauled the networking code. Everything is now ip6 aware. This does mean
+   that the ':' is no longer a keyword in the lexer; i.e. '<host>:<port>'
+   statements should now be written as '<host> <port>' or '<host> port <port>'.
+
+   Added the debug module. This can be used to retrieve debug0 ... debug19
+   variables from the kernel.
+
+08/11/2002 - 2.54
+
+   Added a perl module that allows ppl to connect to symux and do something
+   with the measurements as they come in. (I plan to drive an LCD using this,
+   but it could also be used to get, say, daily bandwidth usage)
+ 
+   Clients of symux would not sleep after they had read and relayed data symux
+   gave to them. This could lead to one child eating up multiple 'semaphore
+   slots' and starvation in other clients - fixed.
+
 25/10/2002 - 2.53
 
    Henning Brauer suggested a datadir statement for symux configuration -
@@ -196,4 +218,4 @@
 29/09/2001 - Lexer had trouble dealing with ip-addresses. Cleaned up the number	
              parsing code and removed a second comment reader.
 
-$Id: CHANGELOG,v 1.8 2002/10/18 12:29:09 dijkstra Exp $
+$Id: CHANGELOG,v 1.10 2002/11/29 10:50:28 dijkstra Exp $

+ 23 - 1
symon/INSTALL

@@ -77,6 +77,11 @@ Less quick, but more verbose
   the symon2web/datasources.inc to reflect your filelocations. datasources.inc
   also contains some settings on how the data is displayed.
 
+  symon2web runs 'rrdtool' to generate graphs as requests for pictures come
+  in. As of OpenBSD 3.2 apache is chrooted at /var/www. Make sure a statically
+  linked rrdtool is available, or break the chroot. You were not planning of
+  running this software on a machine tied to the internet anyway.
+
      + $symon2web["view"] = show all graphs for all machines ('all') or show
        only graphs for a single selected machine ('one').
 
@@ -89,6 +94,23 @@ Less quick, but more verbose
           'big'    =  600 x 450, 
           'huge'   = 1024 x 640.
 
+     + test your setup with test_config.php - this will try to run rrdtool and
+       see if your rrd files are accessable by symon2web.
+
+Getting measurements without the web
+====================================
+
+The client directory contains a perl module 'SymuxClient.pm' that can be used
+to read measurements as they come in at the symux host. A sample Perl program
+called 'getsymonitem.pl' shows how to use the module. 
+
+Example:
+
+hoard$ getsymonitem.pl 127.0.0.1 2100 127.0.0.1 "cpu(0)" "idle"
+93.40
+
+Historical data can be gathered using rrdfetch(1) from symux's rrd files.
+
 Portability
 ===========
 
@@ -98,5 +120,5 @@ symon2web run on POSIX compliant unixes, but the monitoring application itself
 
 Willem Dijkstra <wpd@xs4all.nl>
 
-$Id: INSTALL,v 1.7 2002/10/18 12:29:09 dijkstra Exp $
+$Id: INSTALL,v 1.9 2002/11/29 10:50:28 dijkstra Exp $
 

+ 3 - 3
symon/Makefile

@@ -1,6 +1,6 @@
-# $Id: Makefile,v 1.9 2002/09/14 15:58:45 dijkstra Exp $
+# $Id: Makefile,v 1.10 2002/11/08 15:40:11 dijkstra Exp $
 
-SUBDIR=	lib symon symux symon2web
+SUBDIR=	lib symon symux symon2web client
 
 .if make(clean)
 SUBDIR+= ports/symon
@@ -20,7 +20,7 @@ dist: clean
 	${MAKE} clean; \
 	cd ../../..; \
 	echo Exporting symon-${V}.tar.gz; \
-	find $${workdir} -type f -print | egrep -v 'CVS|doc|clients|README|regress|#'| \
+	find $${workdir} -type f -print | egrep -v 'CVS|doc|README|regress|#'| \
 		tar -czvf /tmp/symon-${V}.tar.gz -I -; \
 	cp /tmp/symon-${V}.tar.gz /usr/ports/distfiles/; \
 	cd $${workdir}/ports/symon; \

+ 12 - 3
symon/Makefile.inc

@@ -1,6 +1,6 @@
-# $Id: Makefile.inc,v 1.10 2002/10/18 12:29:09 dijkstra Exp $
+# $Id: Makefile.inc,v 1.12 2002/11/29 10:50:28 dijkstra Exp $
 
-V=2.53
+V=2.55
 
 AR=	ar
 CC=	cc
@@ -14,11 +14,13 @@ LORDER=	lorder
 NROFF=	nroff
 RANLIB= ranlib
 STRIP=  strip
+POD2MAN= pod2man
 
 BINDIR= libexec
 MANDIR=	man
 SHRDIR= share/symon
 WEBDIR= ${SHRDIR}/web
+CLIENTDIR= ${SHRDIR}/client
 
 .ifndef PREFIX
 PREFIX=/usr/local
@@ -28,10 +30,17 @@ PREFIX=/usr/local
 SYSCONFDIR=/etc
 .endif
 
-.SUFFIXES: .c .o .8 .cat8
+.SUFFIXES: .c .o .8 .cat8 .pm .cat3p
 
 .c.o:
 	${CC} ${CFLAGS} -c $<
 
 .8.cat8:
 	${NROFF} -mandoc $< > $@ || (rm -f $@; false)
+		
+.pm.cat3p:
+	${POD2MAN} $< > $@.tmp || (rm -f $@; false)
+	${NROFF} -mandoc $@.tmp > $@ || (rm -f $@; false)
+	rm -f $@.tmp
+
+

+ 14 - 0
symon/client/Makefile

@@ -0,0 +1,14 @@
+# $Id: Makefile,v 1.1 2002/11/08 15:40:25 dijkstra Exp $
+.include "../Makefile.inc"
+
+all: SymuxClient.cat3p
+
+clean:
+	rm -f SymuxClient.cat3p
+
+install: SymuxClient.pm SymuxClient.cat3p getsymonitem.pl
+	${INSTALL} -d -m 555 -g www -o www ${PREFIX}/${CLIENTDIR}
+	${INSTALL} -c -m 555 -g bin   -o root getsymonitem.pl      ${PREFIX}/${CLIENTDIR}
+	${INSTALL} -c -m 444 -g wheel -o root SymuxClient.pm       ${PREFIX}/${CLIENTDIR}
+	${INSTALL} -c -m 444 -g wheel -o root SymuxClient.cat3p    ${PREFIX}/${CLIENTDIR}/SymuxClient.0
+

+ 288 - 0
symon/client/SymuxClient.pm

@@ -0,0 +1,288 @@
+# $Id: SymuxClient.pm,v 1.2 2002/11/29 10:47:35 dijkstra Exp $
+#
+# Copyright (c) 2001-2002 Willem Dijkstra
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#    - Redistributions of source code must retain the above copyright
+#      notice, this list of conditions and the following disclaimer.
+#    - 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+# COPYRIGHT HOLDERS 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.
+#
+
+package SymuxClient;
+
+use Carp;
+use IO::Socket;
+
+my $streamitem = 
+    {cpu   => {user => 1, nice => 2, system => 3, interrupt => 4, idle => 5},
+     mem   => {real_active => 1, real_total => 2, free => 3, swap_used => 4, 
+	       swap_total =>5},
+     if    => {packets_in => 1, packets_out => 2, bytes_in => 3, bytes_out => 4, 
+	       multicasts_in => 5, multicasts_out => 6, errors_in => 7, 
+	       errors_out => 8, collisions => 9, drops => 10},
+     io    => {total_transfers => 1, total_seeks => 2, total_bytes => 3},
+     pf    => {bytes_v4_in => 1, bytes_v4_out => 2, bytes_v6_in => 3,
+	       bytes_v6_out => 4, packets_v4_in_pass => 5, 
+	       packets_v4_in_drop => 6, packets_v4_out_pass => 7,
+	       packets_v4_out_drop => 8, packets_v6_in_pass => 9, 
+	       packets_v6_in_drop => 10, packets_v6_out_pass => 11,
+	       packets_v6_out_drop => 12, states_entries => 13, 
+	       states_searches => 14, states_inserts => 15, 
+	       states_removals => 16, counters_match => 17, 
+	       counters_badoffset => 18, counters_fragment => 19,
+	       counters_short => 20, counters_normalize => 21, 
+	       counters_memory => 22},
+     debug => {debug0 => 1, debug1 => 2, debug3 => 3, debug4 => 4, debug5 = 5,
+	       debug6 => 6, debug7 => 7, debug8 => 8, debug9 => 9, 
+	       debug10 => 10, debug11 => 11, debug12 => 12, debug13 => 13,
+	       debug14 => 14, debug15 => 15, debug16 => 16, debug17 => 17,
+	       debug18 => 18, debug19 => 19}};
+
+sub new {
+    my ($class, %arg) = @_;
+    my $self;
+    
+    (defined $arg{host} && defined $arg{port}) or 
+        croak "error: need a host and a port to connect to.";
+
+    ($self->{host}, $self->{port}) = ($arg{host}, $arg{port});
+
+    $self->{retry} = (defined $arg{retry}? $arg{retry} : 10);
+
+    bless($self, $class);
+
+    $self->connect();
+
+    return $self;
+}
+
+sub DESTROY {
+    my $self = shift;
+
+    if (defined $self->{sock}) {
+        close($self->{sock});
+    }
+}
+    
+sub connect {
+    my $self = shift;
+
+    if (defined $self->{sock} && $self->{sock}->connected() ne '') {
+        return;
+    } else { 
+        close($self->{sock});
+    }
+    
+    $self->{sock} = new 
+      IO::Socket::INET(PeerAddr => $self->{host},
+                       PeerPort => $self->{port},
+                       Proto => "tcp",
+                       Type => SOCK_STREAM)
+          or croak "error: could not connect to $self->{host}:$self->{port}";
+}
+
+sub getdata {
+    my $self = shift;
+    my $sock;
+    my $data;
+    my $tries;
+
+    $tries = 0;
+
+    while (1) {
+        $self->connect();
+        $sock = $self->{sock};
+        $data = <$sock>;
+        if ((index($data, "\012") != -1) && (index($data, ';') != -1)) {
+            $self->{rawdata} = $data;
+            return $data;
+        } else {
+            croak "error: tried to get data $tries times and failed"  
+                if (++$tries == $self->{retry});
+        }
+    }
+}
+
+sub parse {
+    my $self = shift;
+    my ($stream, @streams, $name, $arg, @data, $number);
+
+    $self->getdata() if ! defined $self->{rawdata};
+
+    $number = 0;
+    undef $self->{data};
+    undef $self->{datasource};
+    chop $self->{rawdata}; # remove ';\n'
+    chop $self->{rawdata};
+
+    @streams = split(/;/, $self->{rawdata});
+    croak "error: expected a symux dataline with ';' delimited streams" 
+        if ($#streams < 2);
+    
+    $self->{datasource} = shift @streams;
+    
+    foreach $stream (@streams) {
+        ($name, $arg, @data) = split(':', $stream);
+        
+        croak "error: expected a symux stream with ':' delimited values"
+            if ($#data < 2);
+
+        $name .= '('.$arg.')' if ($arg ne '');
+
+        @{$self->{data}{$name}} = @data;
+        $number++;
+    }
+
+    $self->{rawdata} = '';
+    return $number;
+}
+
+sub getcacheditem {
+    my ($self, $host, $streamname, $item) = @_;
+    my ($streamtype, @addr, $element);
+
+    return undef if not defined $self->{datasource};
+    return undef if (($host ne $self->{datasource})  && 
+		     ($host ne "*"));
+
+    croak "error: source $host does not contain stream $streamname" 
+        if not defined $self->{data}{$streamname};
+
+    ($streamtype = $streamname) =~ s/^([a-z]+).*/\1/;
+
+    if ($item eq 'timestamp') {
+        $element = 0;
+    } elsif (not defined $$streamitem{$streamtype}{$item}) {
+        croak "error: unknown stream item '$item' - check symux(8) for names";
+    } else {
+        $element = $$streamitem{$streamtype}{$item};
+    }
+        
+    return $self->{data}{$streamname}[$element];
+}
+
+sub getitem {
+    my ($self, $host, $streamname, $item) = @_;
+    my $data;
+    my %hosts = ();
+    
+    undef $data;
+    while (! defined $data) {
+        $self->getdata();
+        $self->parse();
+        $hosts{$self->{datasource}} += 1;
+        if ($hosts{$self->{datasource}} > $self->{retry}) {
+            croak "error: seen a lot of data ($tries strings), but none that matches $host";
+        }
+        $data = $self->getcacheditem($host, $streamname, $item);
+        return $data if defined $data;
+        $tries++;
+    }
+}
+
+sub source {
+    my $self = shift;
+
+    return $self->{datasource};
+}
+1;
+
+__END__
+
+=head1 NAME
+
+SymuxClient - Object client interface for symux
+
+=head1 SYNOPSIS
+
+use SymuxClient;
+
+=head1 DESCRIPTION
+
+C<SymuxClient> provides an object client interface for listening to, and
+parsing of, symux data.
+
+=head1 CONSTRUCTOR
+
+=over 4
+
+=item new ( ARGS )
+
+Creates a new C<SymuxClient> object that holds both the connection to a symux
+and data it receives from that connection. Arguments are:
+
+    host           dotted quad ipv4 hostaddress
+    port           tcp port that symux is on
+    retry*         maximum number of retries; used to limit number 
+                   of connection attempts and number of successive 
+                   read attempts
+
+Arguments marked with * are optional.
+
+Example:
+    $sc = new SymuxClient(host => 127.0.0.1,
+                          port => 2100);
+
+=back 
+
+=head2 METHODS
+
+=item getitem (host, stream, item)
+
+Refresh the measured data and get an item from a stream for a particular
+host. Note that successive calls for this function deal with successive
+measurements of B<symon>. Set C<host> to '*' if data about any host is of
+interest. Any errors are sent out on STDOUT prepended with 'error: '.
+
+=item getcacheditem (host, stream, item)
+
+Get an item from a stream for a particular host. Returns C<undef> if no data is
+cached, or if the data cached does not match the B<host>. Can be called
+multiple times to obtain items from the same measurement. Set C<host> to '*' if
+data about any host is of interest. Any errors are sent out on STDOUT prepended
+with 'error: '.
+
+=item getsource ()
+
+Get the symon source host of the currently cached information. Usefull to see
+what host's data getcacheditem is working on.
+
+Example: 
+    $sc = new SymuxClient(host => 127.0.0.1,
+                          port => 2100);
+
+    print $sc->getitem("127.0.0.1", "if(de0)", 
+                       "packets_out");
+
+    # get more data from that measurement
+    print $sc->getcacheditem("127.0.0.1","if(de0)", 
+                             "packets_in"); 
+
+    # start a new measurement
+    print $sc->getitem("*", "if(de0)", 
+                       "packets_out");
+    # which hosts packets_out was that?
+    print $sc->getsource();
+
+=cut
+

+ 16 - 0
symon/client/getsymonitem.pl

@@ -0,0 +1,16 @@
+#!/usr/bin/perl
+#
+# $Id: getsymonitem.pl,v 1.1 2002/11/08 15:40:25 dijkstra Exp $
+# 
+# Example program of how to use SymuxClient
+
+use SymuxClient;
+
+die "Usage: $0 <symux host> <symux port> <measured host> <stream> <item>
+Example: $0 127.0.0.1 2100 127.0.0.1 'cpu(0)' user\n" if ($#ARGV < 4);
+
+my $sc = new SymuxClient( host => $ARGV[0],
+			  port => $ARGV[1]);
+
+print $sc->getitem( $ARGV[2], $ARGV[3], $ARGV[4] );
+			  

+ 218 - 182
symon/lib/data.c

@@ -1,4 +1,4 @@
-/* $Id: data.c,v 1.16 2002/09/14 15:56:18 dijkstra Exp $ */
+/* $Id: data.c,v 1.17 2002/11/29 10:44:21 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -6,7 +6,7 @@
  *
  * The crc routine is from Rob Warnock <rpw3@sgi.com>, from the
  * comp.compression FAQ.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -32,8 +32,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  * */
 
-/* Terminology: 
- * 
+/* Terminology:
+ *
  * A host carrying a 'symon' is considered a 'source' of information. A single
  * data 'stream' of information has a particular type: <cpu|mem|if|io>. A
  * source can provide multiple 'streams' simultaniously. A source spools
@@ -51,22 +51,23 @@
 #include "data.h"
 #include "error.h"
 #include "lex.h"
+#include "net.h"
 #include "xmalloc.h"
 
 __BEGIN_DECLS
-int            bytelenvar(char);
-int            checklen(int, int, int);
+int bytelenvar(char);
+int checklen(int, int, int);
 struct stream *create_stream(int, char *);
-char          *formatstrvar(char);
-char          *rrdstrvar(char);
-int            strlenvar(char);
+char *formatstrvar(char);
+char *rrdstrvar(char);
+int strlenvar(char);
 __END_DECLS
 
 /* Stream formats
- * 
+ *
  * Format specifications are strings of characters:
  *
- * L = u_int64 
+ * L = u_int64
  * l = u_int32
  * s = u_int16
  * c = 3.2f <= u_int14 <= u_int16  (used in percentages)
@@ -76,57 +77,58 @@ struct {
     char type;
     char *rrdformat;
     char *strformat;
-    int  strlen;
-    int  bytelen;
+    int strlen;
+    int bytelen;
     u_int64_t max;
-} streamvar[] = {
-    {'L', ":%llu",  " %20llu",   22, sizeof(u_int64_t), (u_int64_t) 0xffffffffffffffff},
-    {'l', ":%lu",    " %10lu",   12, sizeof(u_int32_t), (u_int64_t) 0xffffffff},
-    {'s', ":%u",       " %5u",    7, sizeof(u_int16_t), (u_int64_t) 0xffff},
-    {'c', ":%3.2f",  " %3.2f",    8, sizeof(u_int16_t), (u_int64_t) 100},
-    {'b', ":%3u",      " %3u",    5, sizeof(u_int8_t),  (u_int64_t) 255},
-    {'\0', NULL,         NULL,    0,                 0,             0}
+}      streamvar[] = {
+    { 'L', ":%llu", " %20llu", 22, sizeof(u_int64_t), (u_int64_t) 0xffffffffffffffff },
+    { 'l', ":%lu", " %10lu", 12, sizeof(u_int32_t), (u_int64_t) 0xffffffff },
+    { 's', ":%u", " %5u", 7, sizeof(u_int16_t), (u_int64_t) 0xffff },
+    { 'c', ":%3.2f", " %3.2f", 8, sizeof(u_int16_t), (u_int64_t) 100 },
+    { 'b', ":%3u", " %3u", 5, sizeof(u_int8_t), (u_int64_t) 255 },
+    { '\0', NULL, NULL, 0, 0, 0 }
 };
 /* streams of <type> have the packedstream <form> */
 struct {
     int type;
     char *form;
-} streamform[] = {
-    {MT_IO,  "LLL"},
-    {MT_CPU, "ccccc"},
-    {MT_MEM, "lllll"},
-    {MT_IF,  "llllllllll"},
-    {MT_PF,  "LLLLLLLLLLLLLLLLLLLLLL"},
-    {MT_EOT, ""}
+}      streamform[] = {
+    { MT_IO, "LLL" },
+    { MT_CPU, "ccccc" },
+    { MT_MEM, "lllll" },
+    { MT_IF, "llllllllll" },
+    { MT_PF, "LLLLLLLLLLLLLLLLLLLLLL" },
+    { MT_DEBUG, "llllllllllllllllllll" },
+    { MT_EOT, "" }
 };
 
 struct {
     int type;
     int token;
-} streamtoken[] = {
-    {MT_IO,  LXT_IO},
-    {MT_CPU, LXT_CPU},
-    {MT_MEM, LXT_MEM},
-    {MT_IF,  LXT_IF},
-    {MT_PF,  LXT_PF},
-    {MT_EOT, LXT_BADTOKEN}
+}      streamtoken[] = {
+    { MT_IO, LXT_IO },
+    { MT_CPU, LXT_CPU },
+    { MT_MEM, LXT_MEM },
+    { MT_IF, LXT_IF },
+    { MT_PF, LXT_PF },
+    { MT_DEBUG, LXT_DEBUG },
+    { MT_EOT, LXT_BADTOKEN }
 };
 /* parallel crc32 table */
-u_int32_t 
+u_int32_t
 crc32_table[256];
 
-
 /* Convert lexical entities to stream entities */
 const int 
 token2type(const int token)
 {
     int i;
 
-    for (i=0; streamtoken[i].type < MT_EOT; i++) 
-	if (streamtoken[i].token == token) 
+    for (i = 0; streamtoken[i].type < MT_EOT; i++)
+	if (streamtoken[i].token == token)
 	    return streamtoken[i].type;
 
-    fatal("%s:%d: internal error: token (%d) could not be translated into a stream type", 
+    fatal("%s:%d: internal error: token (%d) could not be translated into a stream type",
 	  __FILE__, __LINE__, token);
 
     /* NOT REACHED */
@@ -138,11 +140,11 @@ type2str(const int streamtype)
 {
     int i;
 
-    for (i=0; streamtoken[i].type < MT_EOT; i++) 
-	if (streamtoken[i].type == streamtype) 
+    for (i = 0; streamtoken[i].type < MT_EOT; i++)
+	if (streamtoken[i].type == streamtype)
 	    return parse_opcode(streamtoken[i].token);
 
-    fatal("%s:%d: internal error: type (%d) could not be translated into ascii representation", 
+    fatal("%s:%d: internal error: type (%d) could not be translated into ascii representation",
 	  __FILE__, __LINE__, streamtype);
 
     /* NOT REACHED */
@@ -150,7 +152,7 @@ type2str(const int streamtype)
 }
 /* Return the maximum lenght of the ascii representation of type <type> */
 int 
-strlentype(int type) 
+strlentype(int type)
 {
     int i = 0;
     int sum = 0;
@@ -166,13 +168,13 @@ strlenvar(char var)
 {
     int i;
 
-    for (i=0; streamvar[i].type > '\0'; i++)
+    for (i = 0; streamvar[i].type > '\0'; i++)
 	if (streamvar[i].type == var)
 	    return streamvar[i].strlen;
-    
-    fatal("%s:%d: internal error: type spefication for stream var '%c' not found", 
+
+    fatal("%s:%d: internal error: type spefication for stream var '%c' not found",
 	  __FILE__, __LINE__, var);
-    
+
     /* NOT REACHED */
     return 0;
 }
@@ -182,13 +184,13 @@ bytelenvar(char var)
 {
     int i;
 
-    for (i=0; streamvar[i].type > '\0'; i++)
+    for (i = 0; streamvar[i].type > '\0'; i++)
 	if (streamvar[i].type == var)
 	    return streamvar[i].bytelen;
-    
-    fatal("%s:%d: internal error: type spefication for stream var '%c' not found", 
+
+    fatal("%s:%d: internal error: type spefication for stream var '%c' not found",
 	  __FILE__, __LINE__, var);
-    
+
     /* NOT REACHED */
     return 0;
 }
@@ -198,13 +200,13 @@ formatstrvar(char var)
 {
     int i;
 
-    for (i=0; streamvar[i].type > '\0'; i++)
+    for (i = 0; streamvar[i].type > '\0'; i++)
 	if (streamvar[i].type == var)
 	    return streamvar[i].strformat;
-    
-    fatal("%s:%d: internal error: type spefication for stream var '%c' not found", 
+
+    fatal("%s:%d: internal error: type spefication for stream var '%c' not found",
 	  __FILE__, __LINE__, var);
-    
+
     /* NOT REACHED */
     return "";
 }
@@ -214,29 +216,30 @@ rrdstrvar(char var)
 {
     int i;
 
-    for (i=0; streamvar[i].type > '\0'; i++)
+    for (i = 0; streamvar[i].type > '\0'; i++)
 	if (streamvar[i].type == var)
 	    return streamvar[i].rrdformat;
-    
+
     fatal("internal error: type spefication for stream var '%c' not found", var);
-    
+
     /* NOT REACHED */
     return "";
 }
 /* Check whether <extra> more bytes fit in <maxlen> when we are already at <start> */
 int 
-checklen(int maxlen, int current, int extra) 
+checklen(int maxlen, int current, int extra)
 {
     if ((current + extra) < maxlen) {
 	return 0;
-    } else {
+    }
+    else {
 	warning("buffer overflow: max=%d, current=%d, extra=%d",
 		maxlen, current, extra);
 	return 1;
     }
 }
 int 
-setheader(char *buf, struct symonpacketheader *hph) 
+setheader(char *buf, struct symonpacketheader *hph)
 {
     struct symonpacketheader nph;
     char *p;
@@ -248,37 +251,45 @@ setheader(char *buf, struct symonpacketheader *hph)
 
     p = buf;
 
-    bcopy(&nph.crc, p, sizeof(u_int32_t)); p += sizeof(u_int32_t);
-    bcopy(&nph.timestamp, p, sizeof(u_int64_t)); p += sizeof(u_int64_t);
-    bcopy(&nph.length, p, sizeof(u_int16_t)); p += sizeof(u_int16_t);
-    bcopy(&nph.symon_version, p, sizeof(u_int8_t)); p += sizeof(u_int8_t);
+    bcopy(&nph.crc, p, sizeof(u_int32_t));
+    p += sizeof(u_int32_t);
+    bcopy(&nph.timestamp, p, sizeof(u_int64_t));
+    p += sizeof(u_int64_t);
+    bcopy(&nph.length, p, sizeof(u_int16_t));
+    p += sizeof(u_int16_t);
+    bcopy(&nph.symon_version, p, sizeof(u_int8_t));
+    p += sizeof(u_int8_t);
 
     return (p - buf);
 }
-int
+int 
 getheader(char *buf, struct symonpacketheader *hph)
 {
     char *p;
 
     p = buf;
 
-    bcopy(p, &hph->crc, sizeof(u_int32_t)); p += sizeof(u_int32_t);
-    bcopy(p, &hph->timestamp, sizeof(u_int64_t)); p += sizeof(u_int64_t);
-    bcopy(p, &hph->length, sizeof(u_int16_t)); p += sizeof(u_int16_t);
-    bcopy(p, &hph->symon_version, sizeof(u_int8_t)); p += sizeof(u_int8_t);
+    bcopy(p, &hph->crc, sizeof(u_int32_t));
+    p += sizeof(u_int32_t);
+    bcopy(p, &hph->timestamp, sizeof(u_int64_t));
+    p += sizeof(u_int64_t);
+    bcopy(p, &hph->length, sizeof(u_int16_t));
+    p += sizeof(u_int16_t);
+    bcopy(p, &hph->symon_version, sizeof(u_int8_t));
+    p += sizeof(u_int8_t);
 
     hph->timestamp = ntohq(hph->timestamp);
     hph->crc = ntohl(hph->crc);
     hph->length = ntohs(hph->length);
-    
+
     return (p - buf);
 }
-/* 
+/*
  * Pack multiple arguments of a MT_TYPE into a network order bytestream.
- * snpack returns the number of bytes actually stored.  
+ * snpack returns the number of bytes actually stored.
  */
 int 
-snpack(char *buf, int maxlen, char *id, int type, ...)
+snpack(char *buf, int maxlen, char *id, int type,...)
 {
     va_list ap;
     u_int16_t b;
@@ -294,32 +305,36 @@ snpack(char *buf, int maxlen, char *id, int type, ...)
 	return 0;
     }
 
-    if ( maxlen < 2 ) {
+    if (maxlen < 2) {
 	fatal("%s:%d: maxlen too small", __FILE__, __LINE__);
-    } else {
+    }
+    else {
 	buf[offset++] = type & 0xff;
     }
 
     if (id) {
 	if ((strlen(id) + 1) >= maxlen) {
 	    return 0;
-	} else {
-	    strncpy(&buf[offset], id, maxlen-1);
+	}
+	else {
+	    strncpy(&buf[offset], id, maxlen - 1);
 	    offset += strlen(id);
 	}
     }
     buf[offset++] = '\0';
-	        	    
+
     va_start(ap, type);
-    while (streamform[type].form[i] != '\0'){
+    while (streamform[type].form[i] != '\0') {
 	/* check for buffer overflow */
 	if (checklen(maxlen, offset, bytelenvar(streamform[type].form[i])))
 	    return offset;
-	
-	/* all values smaller than 32 bytes are transferred using ints on the
-           stack. This is to ensure that we get the correct value, if the
-           compiler decided to upgrade our short to a 32bit int. -- cheers
-           dhartmei@ */
+
+	/*
+	 * all values smaller than 32 bytes are transferred using ints on the
+	 * stack. This is to ensure that we get the correct value, if the
+	 * compiler decided to upgrade our short to a 32bit int. -- cheers
+	 * dhartmei@
+	 */
 	switch (streamform[type].form[i]) {
 	case 'b':
 	    b = va_arg(ap, int);
@@ -340,14 +355,14 @@ snpack(char *buf, int maxlen, char *id, int type, ...)
 	    offset += sizeof(u_int16_t);
 	    break;
 
-	case 'l': 
+	case 'l':
 	    l = va_arg(ap, u_int32_t);
 	    l = htonl(l);
 	    bcopy(&l, buf + offset, sizeof(u_int32_t));
 	    offset += sizeof(u_int32_t);
 	    break;
 
-	case 'L': 
+	case 'L':
 	    q = va_arg(ap, u_int64_t);
 	    q = htonq(q);
 	    bcopy(&q, buf + offset, sizeof(u_int64_t));
@@ -364,25 +379,25 @@ snpack(char *buf, int maxlen, char *id, int type, ...)
 
     return offset;
 }
-/* 
+/*
  * Unpack a packedstream in buf into a struct packetstream. Returns the number
- * of bytes actually read.  
- * 
+ * of bytes actually read.
+ *
  * Note that this function does "automatic" bounds checking; it uses a
  * description of the packedstream (streamform) to parse the actual bytes. This
  * description corresponds to the amount of bytes that will fit inside the
  * packedstream structure.  */
 int 
-sunpack(char *buf, struct packedstream *ps)
+sunpack(char *buf, struct packedstream * ps)
 {
     char *in, *out;
-    int i=0;
+    int i = 0;
     int type;
     u_int16_t s;
     u_int16_t c;
     u_int32_t l;
     u_int64_t q;
-    
+
     bzero(ps, sizeof(struct packedstream));
 
     in = buf;
@@ -396,53 +411,54 @@ sunpack(char *buf, struct packedstream *ps)
     in++;
     if ((*in) != '\0') {
 	strncpy(ps->args, in, sizeof(ps->args));
-	ps->args[sizeof(ps->args)-1]='\0';
+	ps->args[sizeof(ps->args) - 1] = '\0';
 	in += strlen(ps->args);
-    } else {
+    }
+    else {
 	ps->args[0] = '\0';
     }
 
     in++;
 
-    out = (char *)(&ps->data);
+    out = (char *) (&ps->data);
 
     while (streamform[type].form[i] != '\0') {
 	switch (streamform[type].form[i]) {
 	case 'b':
-	    bcopy((void *)in, (void *)out, sizeof(u_int8_t));
+	    bcopy((void *) in, (void *) out, sizeof(u_int8_t));
 	    in++;
 	    out++;
 	    break;
 
 	case 'c':
-	    bcopy((void *)in, &c, sizeof(u_int16_t));
+	    bcopy((void *) in, &c, sizeof(u_int16_t));
 	    c = ntohs(c);
-	    bcopy(&c, (void *)out, sizeof(u_int16_t));
-	    in  += sizeof(u_int16_t);
+	    bcopy(&c, (void *) out, sizeof(u_int16_t));
+	    in += sizeof(u_int16_t);
 	    out += sizeof(u_int16_t);
 	    break;
 
 	case 's':
-	    bcopy((void *)in, &s, sizeof(u_int16_t));
+	    bcopy((void *) in, &s, sizeof(u_int16_t));
 	    s = ntohs(s);
-	    bcopy(&s, (void *)out, sizeof(u_int16_t));
-	    in  += sizeof(u_int16_t);
+	    bcopy(&s, (void *) out, sizeof(u_int16_t));
+	    in += sizeof(u_int16_t);
 	    out += sizeof(u_int16_t);
 	    break;
 
-	case 'l': 
-	    bcopy((void *)in, &l, sizeof(u_int32_t));
+	case 'l':
+	    bcopy((void *) in, &l, sizeof(u_int32_t));
 	    l = ntohl(l);
-	    bcopy(&l, (void *)out, sizeof(u_int32_t));
-	    in  += sizeof(u_int32_t);
+	    bcopy(&l, (void *) out, sizeof(u_int32_t));
+	    in += sizeof(u_int32_t);
 	    out += sizeof(u_int32_t);
 	    break;
 
-	case 'L': 
-	    bcopy((void *)in, &q, sizeof(u_int64_t));
+	case 'L':
+	    bcopy((void *) in, &q, sizeof(u_int64_t));
 	    q = ntohq(q);
-	    bcopy(&q, (void *)out, sizeof(u_int64_t));
-	    in  += sizeof(u_int64_t);
+	    bcopy(&q, (void *) out, sizeof(u_int64_t));
+	    in += sizeof(u_int64_t);
 	    out += sizeof(u_int64_t);
 	    break;
 
@@ -456,7 +472,7 @@ sunpack(char *buf, struct packedstream *ps)
 }
 /* Get the RRD or 'pretty' ascii representation of packedstream */
 int 
-ps2strn(struct packedstream *ps, char *buf, const int maxlen, int pretty)
+ps2strn(struct packedstream * ps, char *buf, const int maxlen, int pretty)
 {
     float f;
     u_int16_t b;
@@ -464,19 +480,19 @@ ps2strn(struct packedstream *ps, char *buf, const int maxlen, int pretty)
     u_int16_t c;
     u_int64_t q;
     u_int32_t l;
-    int i=0;
+    int i = 0;
     char *formatstr;
     char *in, *out;
     char vartype;
-    
-    in = (char *)(&ps->data);
-    out = (char *)buf;
+
+    in = (char *) (&ps->data);
+    out = (char *) buf;
 
     while ((vartype = streamform[ps->type].form[i]) != '\0') {
 	/* check buffer overflow */
-	if (checklen(maxlen, (out-buf), strlenvar(vartype)))
+	if (checklen(maxlen, (out - buf), strlenvar(vartype)))
 	    return 0;
-	
+
 	switch (pretty) {
 	case PS2STR_PRETTY:
 	    formatstr = formatstrvar(vartype);
@@ -492,33 +508,33 @@ ps2strn(struct packedstream *ps, char *buf, const int maxlen, int pretty)
 	switch (vartype) {
 	case 'b':
 	    bcopy(in, &b, sizeof(u_int8_t));
-	    snprintf(out, strlenvar(vartype), formatstr, b); 
+	    snprintf(out, strlenvar(vartype), formatstr, b);
 	    in++;
-	    break; 
+	    break;
 
 	case 'c':
 	    bcopy(in, &c, sizeof(u_int16_t));
-	    f = (float)c / 10.0;
-	    snprintf(out, strlenvar(vartype), formatstr, f); 
-	    in  += sizeof(u_int16_t);
+	    f = (float) c / 10.0;
+	    snprintf(out, strlenvar(vartype), formatstr, f);
+	    in += sizeof(u_int16_t);
 	    break;
 
 	case 's':
 	    bcopy(in, &s, sizeof(u_int16_t));
-	    snprintf(out, strlenvar(vartype), formatstr, s); 
-	    in  += sizeof(u_int16_t);
+	    snprintf(out, strlenvar(vartype), formatstr, s);
+	    in += sizeof(u_int16_t);
 	    break;
 
-	case 'l': 
+	case 'l':
 	    bcopy(in, &l, sizeof(u_int32_t));
-	    snprintf(out, strlenvar(vartype), formatstr, l); 
-	    in  += sizeof(u_int32_t);
+	    snprintf(out, strlenvar(vartype), formatstr, l);
+	    in += sizeof(u_int32_t);
 	    break;
 
-	case 'L': 
+	case 'L':
 	    bcopy(in, &q, sizeof(u_int64_t));
-	    snprintf(out, strlenvar(vartype), formatstr, q); 
-	    in  += sizeof(u_int64_t);
+	    snprintf(out, strlenvar(vartype), formatstr, q);
+	    in += sizeof(u_int64_t);
 	    break;
 
 	default:
@@ -538,18 +554,18 @@ create_stream(int type, char *args)
     if (type < 0 || type >= MT_EOT)
 	fatal("%s:%d: internal error: stream type unknown", __FILE__, __LINE__);
 
-    p = (struct stream *)xmalloc(sizeof(struct stream));
+    p = (struct stream *) xmalloc(sizeof(struct stream));
     bzero(p, sizeof(struct stream));
     p->type = type;
 
     if (args != NULL)
 	p->args = xstrdup(args);
-    
+
     return p;
 }
 /* Find the stream handle in a source */
 struct stream *
-find_source_stream(struct source *source, int type, char *args) 
+find_source_stream(struct source * source, int type, char *args)
 {
     struct stream *p;
 
@@ -557,8 +573,8 @@ find_source_stream(struct source *source, int type, char *args)
 	return NULL;
 
     SLIST_FOREACH(p, &source->sl, streams) {
-	if ((p->type == type) 
-	    && (((void *)args != (void *)p != NULL) 
+	if ((p->type == type)
+	    && (((void *) args != (void *) p != NULL)
 		&& strncmp(args, p->args, _POSIX2_LINE_MAX) == 0))
 	    return p;
     }
@@ -567,7 +583,7 @@ find_source_stream(struct source *source, int type, char *args)
 }
 /* Add a stream to a source */
 struct stream *
-add_source_stream(struct source *source, int type, char *args) 
+add_source_stream(struct source * source, int type, char *args)
 {
     struct stream *p;
 
@@ -585,7 +601,7 @@ add_source_stream(struct source *source, int type, char *args)
 }
 /* Find a stream in a mux */
 struct stream *
-find_mux_stream(struct mux *mux, int type, char *args) 
+find_mux_stream(struct mux * mux, int type, char *args)
 {
     struct stream *p;
 
@@ -593,8 +609,8 @@ find_mux_stream(struct mux *mux, int type, char *args)
 	return NULL;
 
     SLIST_FOREACH(p, &mux->sl, streams) {
-	if ((p->type == type) 
-	    && (((void *)args != (void *)p != NULL) 
+	if ((p->type == type)
+	    && (((void *) args != (void *) p != NULL)
 		&& strncmp(args, p->args, _POSIX2_LINE_MAX) == 0))
 	    return p;
     }
@@ -603,7 +619,7 @@ find_mux_stream(struct mux *mux, int type, char *args)
 }
 /* Add a stream to a mux */
 struct stream *
-add_mux_stream(struct mux *mux, int type, char *args) 
+add_mux_stream(struct mux * mux, int type, char *args)
 {
     struct stream *p;
 
@@ -621,7 +637,7 @@ add_mux_stream(struct mux *mux, int type, char *args)
 }
 /* Find a source by name in a sourcelist */
 struct source *
-find_source(struct sourcelist *sol, char *name) 
+find_source(struct sourcelist * sol, char *name)
 {
     struct source *p;
 
@@ -629,8 +645,8 @@ find_source(struct sourcelist *sol, char *name)
 	return NULL;
 
     SLIST_FOREACH(p, sol, sources) {
-	if (((void *)name != (void *)p != NULL) 
-	    && strncmp(name, p->name, _POSIX2_LINE_MAX) == 0)
+	if (((void *) name != (void *) p != NULL)
+	    && strncmp(name, p->addr, _POSIX2_LINE_MAX) == 0)
 	    return p;
     }
 
@@ -638,7 +654,7 @@ find_source(struct sourcelist *sol, char *name)
 }
 /* Find a source by ip in a sourcelist */
 struct source *
-find_source_ip(struct sourcelist *sol, u_int32_t ip) 
+find_source_sockaddr(struct sourcelist * sol, struct sockaddr * addr)
 {
     struct source *p;
 
@@ -646,7 +662,7 @@ find_source_ip(struct sourcelist *sol, u_int32_t ip)
 	return NULL;
 
     SLIST_FOREACH(p, sol, sources) {
-	if (p->ip == ip)
+	if (cmpsock_addr((struct sockaddr *) & p->sockaddr, addr))
 	    return p;
     }
 
@@ -654,9 +670,9 @@ find_source_ip(struct sourcelist *sol, u_int32_t ip)
 }
 /* Add a source with to a sourcelist */
 struct source *
-add_source(struct sourcelist *sol, char *name)
+add_source(struct sourcelist * sol, char *name)
 {
-    struct source* p;
+    struct source *p;
 
     if (sol == NULL)
 	return NULL;
@@ -664,16 +680,17 @@ add_source(struct sourcelist *sol, char *name)
     if (find_source(sol, name) != NULL)
 	return NULL;
 
-    p = (struct source *)xmalloc(sizeof(struct source));
+    p = (struct source *) xmalloc(sizeof(struct source));
     bzero(p, sizeof(struct source));
-    p->name = xstrdup(name);
+    p->addr = xstrdup(name);
+
     SLIST_INSERT_HEAD(sol, p, sources);
 
     return p;
 }
 /* Find a mux by name in a muxlist */
 struct mux *
-find_mux(struct muxlist *mul, char *name) 
+find_mux(struct muxlist * mul, char *name)
 {
     struct mux *p;
 
@@ -681,7 +698,7 @@ find_mux(struct muxlist *mul, char *name)
 	return NULL;
 
     SLIST_FOREACH(p, mul, muxes) {
-	if (((void *)name != (void *)p != NULL) 
+	if (((void *) name != (void *) p != NULL)
 	    && strncmp(name, p->name, _POSIX2_LINE_MAX) == 0)
 	    return p;
     }
@@ -690,9 +707,9 @@ find_mux(struct muxlist *mul, char *name)
 }
 /* Add a mux to a muxlist */
 struct mux *
-add_mux(struct muxlist *mul, char *name)
+add_mux(struct muxlist * mul, char *name)
 {
-    struct mux* p;
+    struct mux *p;
 
     if (mul == NULL)
 	return NULL;
@@ -700,16 +717,17 @@ add_mux(struct muxlist *mul, char *name)
     if (find_mux(mul, name) != NULL)
 	return NULL;
 
-    p = (struct mux *)xmalloc(sizeof(struct mux));
+    p = (struct mux *) xmalloc(sizeof(struct mux));
     bzero(p, sizeof(struct mux));
     p->name = xstrdup(name);
     SLIST_INSERT_HEAD(mul, p, muxes);
+    SLIST_INIT(&p->sol);
 
     return p;
 }
 /* Rename a mux */
 struct mux *
-rename_mux(struct muxlist *mul, struct mux *mux, char *name)
+rename_mux(struct muxlist * mul, struct mux * mux, char *name)
 {
     if (mul == NULL || mux == NULL)
 	return NULL;
@@ -725,61 +743,77 @@ rename_mux(struct muxlist *mul, struct mux *mux, char *name)
     return mux;
 }
 void 
-free_muxlist(struct muxlist *mul) 
+free_muxlist(struct muxlist * mul)
 {
     struct mux *p, *np;
+    int i;
 
     if (mul == NULL || SLIST_EMPTY(mul))
 	return;
 
     p = SLIST_FIRST(mul);
 
-    while ( p ) {
+    while (p) {
 	np = SLIST_NEXT(p, muxes);
 
-	if (p->name != NULL) xfree(p->name);
+	if (p->name != NULL)
+	    xfree(p->name);
+	if (p->addr != NULL)
+	    xfree(p->addr);
+	if (p->port != NULL)
+	    xfree(p->port);
+
 	close(p->clientsocket);
-	close(p->symonsocket);
+	close(p->symuxsocket);
+	for (i = 0; i < AF_MAX; i++)
+	    if (p->symonsocket[i])
+		close(p->symonsocket[i]);
+
 	free_streamlist(&p->sl);
+	free_sourcelist(&p->sol);
 	xfree(p);
 
 	p = np;
     }
 }
 void 
-free_streamlist(struct streamlist *sl) 
+free_streamlist(struct streamlist * sl)
 {
     struct stream *p, *np;
 
     if (sl == NULL || SLIST_EMPTY(sl))
 	return;
-    
+
     p = SLIST_FIRST(sl);
 
-    while ( p ) {
+    while (p) {
 	np = SLIST_NEXT(p, streams);
 
-	if (p->args != NULL) xfree(p->args);
-	if (p->file != NULL) xfree(p->file);
+	if (p->args != NULL)
+	    xfree(p->args);
+	if (p->file != NULL)
+	    xfree(p->file);
 	xfree(p);
 
 	p = np;
     }
 }
 void 
-free_sourcelist(struct sourcelist *sol) 
+free_sourcelist(struct sourcelist * sol)
 {
     struct source *p, *np;
 
     if (sol == NULL || SLIST_EMPTY(sol))
 	return;
-    
+
     p = SLIST_FIRST(sol);
 
-    while ( p ) {
+    while (p) {
 	np = SLIST_NEXT(p, sources);
 
-	if (p->name != NULL) xfree(p->name);
+	if (p->addr != NULL)
+	    xfree(p->addr);
+
 	free_streamlist(&p->sl);
 	xfree(p);
 
@@ -788,19 +822,20 @@ free_sourcelist(struct sourcelist *sol)
 }
 /* Calculate maximum buffer space needed for a single symon hit */
 int 
-calculate_churnbuffer(struct sourcelist *sol) { 
-    struct source *source; 
-    struct stream *stream; 
+calculate_churnbuffer(struct sourcelist * sol)
+{
+    struct source *source;
+    struct stream *stream;
     int prefixlen;
     int maxlen;
-    int len; 
+    int len;
     int n;
-    
+
     /* determine length of a timestamp + ip as strings */
-    prefixlen = (sizeof(time_t)*3) + strlen(":") + 15 + strlen(":");
-    
-    len = n = 0; 
-    source = NULL; 
+    prefixlen = (sizeof(time_t) * 3) + strlen(":") + 15 + strlen(":");
+
+    len = n = 0;
+    source = NULL;
     stream = NULL;
     maxlen = 0;
     /* determine maximum string size for a single source */
@@ -812,7 +847,8 @@ calculate_churnbuffer(struct sourcelist *sol) {
 	    len += strlentype(stream->type);
 	    n++;
 	}
-	if (len > maxlen) maxlen = len;
+	if (len > maxlen)
+	    maxlen = len;
     }
     return maxlen;
 }
@@ -820,9 +856,9 @@ calculate_churnbuffer(struct sourcelist *sol) {
 u_int32_t
 crc32(const void *buf, unsigned int len)
 {
-    u_int8_t  *p;
+    u_int8_t *p;
     u_int32_t crc;
-    
+
     crc = 0xffffffff;
     for (p = (u_int8_t *) buf; len > 0; ++p, --len)
 	crc = (crc << 8) ^ crc32_table[(crc >> 24) ^ *p];
@@ -830,7 +866,7 @@ crc32(const void *buf, unsigned int len)
     return ~crc;
 }
 /* Init table for CRC32 */
-void
+void 
 init_crc32()
 {
     unsigned int i, j;

+ 86 - 62
symon/lib/data.h

@@ -1,4 +1,4 @@
-/* $Id: data.h,v 1.16 2002/09/14 15:56:18 dijkstra Exp $ */
+/* $Id: data.h,v 1.17 2002/11/29 10:46:59 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -56,48 +56,48 @@
 #define ntohq(n) (n)
 #else
 static inline u_int64_t
-htonq (u_int64_t v)
+       htonq(u_int64_t v)
 {
-    return (u_int64_t)htonl(v) << 32 | htonl(v >> 32);
+    return (u_int64_t) htonl(v) << 32 | htonl(v >> 32);
 }
 static inline u_int64_t
-ntohq (u_int64_t v) 
+       ntohq(u_int64_t v)
 {
-    return (u_int64_t)ntohl(v) << 32 | ntohl(v >> 32);
+    return (u_int64_t) ntohl(v) << 32 | ntohl(v >> 32);
 }
 #endif
 
-/* Symon packet version 
+/* Symon packet version
  * version 1:
  * symon_version:timestamp:length:crc:n*packedstream
- * 
+ *
  * Note that the data portion is limited. The current (31/03/2002) largest
  * streamtype (if) needs 42 bytes without arguments. My _POSIX2_LINE_MAX is 2k,
- * so that works out to about 38 packedstreams in a single symon packet.  
+ * so that works out to about 38 packedstreams in a single symon packet.
  */
 #define SYMON_PACKET_VER  1
 
 /* Sending structures over the network is dangerous as the compiler might have
  * added extra padding between items. symonpacketheader below is therefore also
  * marshalled and demarshalled via snpack and sunpack. The actual values are
- * copied out of memory into this structure one by one. 
+ * copied out of memory into this structure one by one.
  */
 struct symonpacketheader {
-	u_int64_t timestamp;
-	u_int32_t crc;
-	u_int16_t length;
-	u_int8_t symon_version;
-	u_int8_t reserved;
+    u_int64_t timestamp;
+    u_int32_t crc;
+    u_int16_t length;
+    u_int8_t symon_version;
+    u_int8_t reserved;
 };
 
 struct symonpacket {
     struct symonpacketheader header;
     char data[_POSIX2_LINE_MAX];
-};  
-  
+};
+
 /* The difference between a stream and a packed stream:
- * - A stream ties stream information to a file. 
- * - A packed stream is the measured data itself 
+ * - A stream ties stream information to a file.
+ * - A packed stream is the measured data itself
  *
  * A stream is meta data describing properties, a packed stream is the data itself.
  */
@@ -110,9 +110,8 @@ struct stream {
 SLIST_HEAD(streamlist, stream);
 
 struct source {
-    char *name;
-    u_int32_t ip;
-    u_int16_t port;
+    char *addr;
+    struct sockaddr_storage sockaddr;
     struct streamlist sl;
     SLIST_ENTRY(source) sources;
 };
@@ -120,15 +119,17 @@ SLIST_HEAD(sourcelist, source);
 
 struct mux {
     char *name;
+    char *addr;
+    char *port;
+    struct sourcelist sol;
     int offset;
-    int clientsocket;
-    int symonsocket;
+    int clientsocket;		/* symux; incoming tcp connections */
+    int symonsocket[AF_MAX];	/* symux; incoming symon data */
+    int symuxsocket;		/* symon; outgoing data to mux */
     struct symonpacket packet;
-    struct sockaddr_in sockaddr;
+    struct sockaddr_storage sockaddr;
     struct streamlist sl;
     u_int32_t senderr;
-    u_int32_t ip;
-    u_int16_t port;
     SLIST_ENTRY(mux) muxes;
 };
 SLIST_HEAD(muxlist, mux);
@@ -143,54 +144,55 @@ SLIST_HEAD(muxlist, mux);
 #define MT_MEM    2
 #define MT_IF     3
 #define MT_PF     4
-#define MT_EOT    5
+#define MT_DEBUG  5
+#define MT_EOT    6
 
-/* NOTE: struct packetstream
- *
+/*
  * Unpacking of incoming packets is done via a packedstream structure. This
  * structure defines the maximum amount of data that can be contained in a
  * single network representation of a stream. It is used internally for sizing
  * only. Although the union members are here, they could also read u_int64_t[4]
  * with io, for instance.
  */
-#define SYMON_PS_ARGLEN    16
+#define SYMON_UNKMUX   "<unknown mux>"	/* mux nodes without host addr */
+#define SYMON_PS_ARGLEN    16	/* maximum argument length */
 struct packedstream {
     int type;
     int padding;
     char args[SYMON_PS_ARGLEN];
     union {
 	struct symonpacketheader header;
-	struct { 
+	struct {
 	    u_int64_t mtotal_transfers;
 	    u_int64_t mtotal_seeks;
 	    u_int64_t mtotal_bytes;
-	} ps_io;
+	}      ps_io;
 	struct {
 	    u_int16_t muser;
 	    u_int16_t mnice;
 	    u_int16_t msystem;
 	    u_int16_t minterrupt;
 	    u_int16_t midle;
-	} ps_cpu;
+	}      ps_cpu;
 	struct {
-	    u_int32_t mreal_active; 
+	    u_int32_t mreal_active;
 	    u_int32_t mreal_total;
 	    u_int32_t mfree;
 	    u_int32_t mswap_used;
 	    u_int32_t mswap_total;
-	} ps_mem;
+	}      ps_mem;
 	struct {
 	    u_int32_t mipackets;
 	    u_int32_t mopackets;
-	    u_int32_t mibytes; 
+	    u_int32_t mibytes;
 	    u_int32_t mobytes;
-	    u_int32_t mimcasts; 
+	    u_int32_t mimcasts;
 	    u_int32_t momcasts;
-	    u_int32_t mierrors; 
+	    u_int32_t mierrors;
 	    u_int32_t moerrors;
 	    u_int32_t mcolls;
 	    u_int32_t mdrops;
-	} ps_if;
+	}      ps_if;
 	struct {
 	    u_int64_t bytes_v4_in;
 	    u_int64_t bytes_v4_out;
@@ -214,35 +216,57 @@ struct packedstream {
 	    u_int64_t counters_short;
 	    u_int64_t counters_normalize;
 	    u_int64_t counters_memory;
-	} ps_pf;
-    } data;
+	}      ps_pf;
+	struct {
+	    u_int32_t debug0;
+	    u_int32_t debug1;
+	    u_int32_t debug2;
+	    u_int32_t debug3;
+	    u_int32_t debug4;
+	    u_int32_t debug5;
+	    u_int32_t debug6;
+	    u_int32_t debug7;
+	    u_int32_t debug8;
+	    u_int32_t debug9;
+	    u_int32_t debug10;
+	    u_int32_t debug11;
+	    u_int32_t debug12;
+	    u_int32_t debug13;
+	    u_int32_t debug14;
+	    u_int32_t debug15;
+	    u_int32_t debug16;
+	    u_int32_t debug17;
+	    u_int32_t debug18;
+	    u_int32_t debug19;
+	}      ps_debug;
+    }     data;
 };
 
 /* prototypes */
 __BEGIN_DECLS
-const char    *type2str(const int);
-const int      token2type(const int);
-int            calculate_churnbuffer(struct sourcelist *);
-int            getheader(char *, struct symonpacketheader *);
-int            ps2strn(struct packedstream *, char *, int, int);
-int            setheader(char *, struct symonpacketheader *);
-int            snpack(char *, int, char*, int, ...);
-int            strlentype(int);
-int            sunpack(char *, struct packedstream *);
-struct mux    *add_mux(struct muxlist *, char *);
-struct mux    *find_mux(struct muxlist *, char *);
-struct mux *   rename_mux(struct muxlist *, struct mux *, char *);
+const char *type2str(const int);
+const int token2type(const int);
+int calculate_churnbuffer(struct sourcelist *);
+int getheader(char *, struct symonpacketheader *);
+int ps2strn(struct packedstream *, char *, int, int);
+int setheader(char *, struct symonpacketheader *);
+int snpack(char *, int, char *, int,...);
+int strlentype(int);
+int sunpack(char *, struct packedstream *);
+struct mux *add_mux(struct muxlist *, char *);
+struct mux *find_mux(struct muxlist *, char *);
+struct mux *rename_mux(struct muxlist *, struct mux *, char *);
 struct source *add_source(struct sourcelist *, char *);
 struct source *find_source(struct sourcelist *, char *);
-struct source *find_source_ip(struct sourcelist *, u_int32_t);
+struct source *find_source_sockaddr(struct sourcelist *, struct sockaddr *);
 struct stream *add_mux_stream(struct mux *, int, char *);
-struct stream *add_source_stream(struct source *, int, char *); 
-struct stream *find_mux_stream(struct mux *,  int, char *);
+struct stream *add_source_stream(struct source *, int, char *);
+struct stream *find_mux_stream(struct mux *, int, char *);
 struct stream *find_source_stream(struct source *, int, char *);
-u_int32_t      crc32(const void*, unsigned int);
-void           free_muxlist(struct muxlist *);
-void           free_sourcelist(struct sourcelist *);
-void           free_streamlist(struct streamlist *);
-void           init_crc32();
+u_int32_t crc32(const void *, unsigned int);
+void free_muxlist(struct muxlist *);
+void free_sourcelist(struct sourcelist *);
+void free_streamlist(struct streamlist *);
+void init_crc32();
 __END_DECLS
-#endif /*_SYMON_LIB_DATA_H*/
+#endif				/* _SYMON_LIB_DATA_H */

+ 32 - 29
symon/lib/error.c

@@ -1,4 +1,4 @@
-/* $Id: error.c,v 1.9 2002/09/14 15:56:18 dijkstra Exp $ */
+/* $Id: error.c,v 1.10 2002/11/29 10:50:29 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -40,35 +40,37 @@
 #include "error.h"
 
 __BEGIN_DECLS
-void output_message(int, char *, va_list); 
+void output_message(int, char *, va_list);
 __END_DECLS
 
 int flag_daemon = 0;
 int flag_debug = 0;
 
-enum { SYMON_LOG_FATAL, 
-       SYMON_LOG_WARNING,
-       SYMON_LOG_INFO,
-       SYMON_LOG_DEBUG } loglevels;
+enum {
+    SYMON_LOG_FATAL,
+    SYMON_LOG_WARNING,
+    SYMON_LOG_INFO,
+    SYMON_LOG_DEBUG
+}    loglevels;
 
 struct {
     int type;
     int priority;
     char *errtxt;
     FILE *stream;
-} logmapping[] = {
-    {SYMON_LOG_FATAL,   LOG_ERR,     "fatal",   stderr},
-    {SYMON_LOG_WARNING, LOG_WARNING, "warning", stderr},
-    {SYMON_LOG_INFO,    LOG_INFO,    "",        stdout},
-    {SYMON_LOG_DEBUG,   LOG_DEBUG,   "debug",   stdout},
-    {-1,              0,           "",        NULL}
+}      logmapping[] = {
+    { SYMON_LOG_FATAL, LOG_ERR, "fatal", stderr },
+    { SYMON_LOG_WARNING, LOG_WARNING, "warning", stderr },
+    { SYMON_LOG_INFO, LOG_INFO, "", stdout },
+    { SYMON_LOG_DEBUG, LOG_DEBUG, "debug", stdout },
+    { -1, 0, "", NULL }
 };
-/* 
- * Internal helper that actually outputs every 
- * (fatal|warning|info|debug) message 
+/*
+ * Internal helper that actually outputs every
+ * (fatal|warning|info|debug) message
  */
-void
-output_message(int level, char *fmt, va_list args) 
+void 
+output_message(int level, char *fmt, va_list args)
 {
     char msgbuf[_POSIX2_LINE_MAX];
     int loglevel;
@@ -77,7 +79,7 @@ output_message(int level, char *fmt, va_list args)
 	return;
 
     vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
-    
+
     for (loglevel = 0; logmapping[loglevel].type != -1; loglevel++) {
 	if (logmapping[loglevel].type == level)
 	    break;
@@ -89,11 +91,13 @@ output_message(int level, char *fmt, va_list args)
 
     if (flag_daemon) {
 	syslog(logmapping[loglevel].priority, msgbuf);
-    } else {
+    }
+    else {
 	if (strlen(logmapping[loglevel].errtxt) > 0) {
-	    fprintf(logmapping[loglevel].stream, "%s: %s\n", 
+	    fprintf(logmapping[loglevel].stream, "%s: %s\n",
 		    logmapping[loglevel].errtxt, msgbuf);
-	} else 
+	}
+	else
 	    fprintf(logmapping[loglevel].stream, "%s\n", msgbuf);
 
 	fflush(logmapping[loglevel].stream);
@@ -101,18 +105,18 @@ output_message(int level, char *fmt, va_list args)
 }
 /* Output error and exit */
 __dead void 
-fatal(char *fmt, ...)
+fatal(char *fmt,...)
 {
     va_list ap;
     va_start(ap, fmt);
     output_message(SYMON_LOG_FATAL, fmt, ap);
     va_end(ap);
-        
-    exit( 1 );
+
+    exit(1);
 }
 /* Warn and continue */
 void 
-warning(char *fmt, ...)
+warning(char *fmt,...)
 {
     va_list ap;
     va_start(ap, fmt);
@@ -121,7 +125,7 @@ warning(char *fmt, ...)
 }
 /* Inform and continue */
 void 
-info(char *fmt, ...)
+info(char *fmt,...)
 {
     va_list ap;
     va_start(ap, fmt);
@@ -129,12 +133,11 @@ info(char *fmt, ...)
     va_end(ap);
 }
 /* Debug statements only */
-void
-debug(char *fmt, ...)
+void 
+debug(char *fmt,...)
 {
     va_list ap;
     va_start(ap, fmt);
     output_message(SYMON_LOG_DEBUG, fmt, ap);
     va_end(ap);
 }
-

+ 6 - 6
symon/lib/error.h

@@ -1,4 +1,4 @@
-/* $Id: error.h,v 1.6 2002/09/14 15:56:18 dijkstra Exp $ */
+/* $Id: error.h,v 1.7 2002/11/29 10:50:29 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -40,10 +40,10 @@ extern int flag_debug;
 extern int flag_daemon;
 
 __BEGIN_DECLS
-__dead void fatal(char *, ...);
-void        warning(char *, ...);
-void        info(char *, ...);
-void        debug(char *, ...);
+__dead void fatal(char *,...);
+void warning(char *,...);
+void info(char *,...);
+void debug(char *,...);
 __END_DECLS
 
-#endif /*_SYMON_LIB_ERROR_H*/
+#endif				/* _SYMON_LIB_ERROR_H */

+ 60 - 54
symon/lib/lex.c

@@ -1,4 +1,4 @@
-/* $Id: lex.c,v 1.13 2002/10/25 15:24:31 dijkstra Exp $ */
+/* $Id: lex.c,v 1.14 2002/11/29 10:44:21 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -39,11 +39,11 @@
  *
  * Usage:
  *
- *    l = open_lex(filename); 
+ *    l = open_lex(filename);
  *    while (lex_nexttoken(l)) {
  *       use l->token, l->op, l->value
  *    }
- *    close_lex(l); 
+ *    close_lex(l);
  */
 
 #include <sys/types.h>
@@ -61,16 +61,16 @@
 static struct {
     const char *name;
     int opcode;
-} keywords[] = {
+}      keywords[] = {
     { "{", LXT_BEGIN },
     { "}", LXT_END },
     { "(", LXT_OPEN },
     { ")", LXT_CLOSE },
     { ",", LXT_COMMA },
-    { ":", LXT_COLON },
     { "accept", LXT_ACCEPT },
     { "cpu", LXT_CPU },
     { "datadir", LXT_DATADIR },
+    { "debug", LXT_DEBUG },
     { "if", LXT_IF },
     { "in", LXT_IN },
     { "io", LXT_IO },
@@ -85,7 +85,7 @@ static struct {
     { "write", LXT_WRITE },
     { NULL, 0 }
 };
-#define KW_OPS "{},():"
+#define KW_OPS "{},()"
 
 /* Return the number of the token pointed to by cp or LXT_BADTOKEN */
 int 
@@ -96,16 +96,16 @@ parse_token(const char *cp)
     for (i = 0; keywords[i].name; i++)
 	if (strcasecmp(cp, keywords[i].name) == 0)
 	    return keywords[i].opcode;
-        
+
     return LXT_BADTOKEN;
 }
 /* Return the ascii representation of an opcode */
-const char* 
+const char *
 parse_opcode(const int op)
 {
     u_int i;
-    
-    for (i=0; keywords[i].name; i++)
+
+    for (i = 0; keywords[i].name; i++)
 	if (keywords[i].opcode == op)
 	    return keywords[i].name;
 
@@ -113,30 +113,32 @@ parse_opcode(const int op)
 }
 /* Read a line and increase buffer if needed */
 int 
-lex_readline(struct lex *l)
+lex_readline(struct lex * l)
 {
     char *bp;
 
     bp = l->buffer;
 
     if (l->buffer) {
-	if ((l->curpos < l->endpos) && 
+	if ((l->curpos < l->endpos) &&
 	    ((l->bsize - l->endpos) < _POSIX2_LINE_MAX)) {
 	    l->bsize += _POSIX2_LINE_MAX;
 	    l->buffer = xrealloc(l->buffer, l->bsize);
 	    bp = l->buffer;
 	    bp += l->endpos;
-	} else {
+	}
+	else {
 	    l->curpos = 0;
 	    l->endpos = 0;
 	}
-    } else {
+    }
+    else {
 	l->bsize = _POSIX2_LINE_MAX;
 	l->buffer = xmalloc(l->bsize);
 	bp = l->buffer;
     }
-    
-    if (!fgets(bp, (l->buffer+l->bsize)-bp, l->fh))
+
+    if (!fgets(bp, (l->buffer + l->bsize) - bp, l->fh))
 	return 0;
     else {
 	l->endpos += strlen(bp) - 1;
@@ -145,19 +147,19 @@ lex_readline(struct lex *l)
 }
 /* Copy char out of input stream */
 void 
-lex_copychar(struct lex *l) 
+lex_copychar(struct lex * l)
 {
-    l->token[l->tokpos]=l->buffer[l->curpos];
-    
+    l->token[l->tokpos] = l->buffer[l->curpos];
+
     if (++l->tokpos >= _POSIX2_LINE_MAX) {
-	l->token[_POSIX2_LINE_MAX-1] = '\0';
+	l->token[_POSIX2_LINE_MAX - 1] = '\0';
 	fatal("%s:%d: parse error at '%s'", l->filename, l->cline, l->token);
 	/* NOT REACHED */
     }
 }
 /* Get next char, read next line if needed */
 int 
-lex_nextchar(struct lex *l)
+lex_nextchar(struct lex * l)
 {
     l->curpos++;
 
@@ -165,54 +167,55 @@ lex_nextchar(struct lex *l)
 	if (!lex_readline(l))
 	    return 0;
 
-    if (l->buffer[l->curpos] == '\n') l->cline++;
-    
+    if (l->buffer[l->curpos] == '\n')
+	l->cline++;
+
     return 1;
 }
 /* Close of current token with a '\0' */
 void 
-lex_termtoken(struct lex *l)
+lex_termtoken(struct lex * l)
 {
-    l->token[l->tokpos] = l->token[_POSIX2_LINE_MAX-1] = '\0';
-    l->tokpos=0;
+    l->token[l->tokpos] = l->token[_POSIX2_LINE_MAX - 1] = '\0';
+    l->tokpos = 0;
 }
 /* Unget token; the lexer allows 1 look a head. */
 void 
-lex_ungettoken(struct lex *l) 
+lex_ungettoken(struct lex * l)
 {
     l->unget = 1;
 }
 /* Get the next token in lex->token. return 0 if no more tokens found. */
-int
-lex_nexttoken(struct lex *l)
+int 
+lex_nexttoken(struct lex * l)
 {
     /* return same token as last time if it has been pushed back */
     if (l->unget) {
 	l->unget = 0;
 	return 1;
     }
-	
+
     l->op = LXT_BADTOKEN;
     l->value = 0;
     l->type = LXY_UNKNOWN;
 
     /* find first non whitespace */
-    while (l->buffer[l->curpos] == ' ' || 
-	   l->buffer[l->curpos] == '\t' || 
+    while (l->buffer[l->curpos] == ' ' ||
+	   l->buffer[l->curpos] == '\t' ||
 	   l->buffer[l->curpos] == '\r' ||
 	   l->buffer[l->curpos] == '\n' ||
 	   l->buffer[l->curpos] == '\0' ||
 	   l->buffer[l->curpos] == '#') {
 	/* flush rest of line if comment */
 	if (l->buffer[l->curpos] == '#') {
-	    while (l->buffer[l->curpos] != '\n') 
+	    while (l->buffer[l->curpos] != '\n')
 		if (!lex_nextchar(l))
 		    return 0;
-	} else
-	    if (!lex_nextchar(l))
-		return 0;
+	}
+	else if (!lex_nextchar(l))
+	    return 0;
     }
-    
+
     l->type = LXY_STRING;
 
     /* "delimited string" */
@@ -232,7 +235,7 @@ lex_nexttoken(struct lex *l)
 	lex_nextchar(l);
 	return 1;
     }
-    
+
     /* 'delimited string' */
     if (l->buffer[l->curpos] == '\'') {
 	if (!lex_nextchar(l)) {
@@ -250,7 +253,7 @@ lex_nexttoken(struct lex *l)
 	lex_nextchar(l);
 	return 1;
     }
-    
+
     /* one char keyword */
     if (strchr(KW_OPS, l->buffer[l->curpos])) {
 	lex_copychar(l);
@@ -262,7 +265,7 @@ lex_nexttoken(struct lex *l)
 
     /* single keyword */
     while (l->buffer[l->curpos] != ' ' &&
-	   l->buffer[l->curpos] != '\t' && 
+	   l->buffer[l->curpos] != '\t' &&
 	   l->buffer[l->curpos] != '\r' &&
 	   l->buffer[l->curpos] != '\n' &&
 	   l->buffer[l->curpos] != '\0' &&
@@ -276,20 +279,20 @@ lex_nexttoken(struct lex *l)
     l->op = parse_token(l->token);
 
     /* number */
-    if (l->token[0] >= '0' && l->token[0] <= '9' ) {
+    if (l->token[0] >= '0' && l->token[0] <= '9') {
 	if (strlen(l->token) == strspn(l->token, "0123456789")) {
 	    l->type = LXY_NUMBER;
-	    l->value = strtol(l->token, NULL , 10);
+	    l->value = strtol(l->token, NULL, 10);
 	}
     }
     return 1;
-}    
+}
 /* Create and initialize a lexical analyser */
 struct lex *
 open_lex(const char *filename)
 {
     struct lex *l;
-    
+
     l = xmalloc(sizeof(struct lex));
     l->buffer = NULL;
     l->cline = 1;
@@ -304,7 +307,7 @@ open_lex(const char *filename)
     l->value = 0;
 
     if ((l->fh = fopen(l->filename, "r")) == NULL) {
-	warning("could not open file '%s':%s", 
+	warning("could not open file '%s':%s",
 		l->filename, strerror(errno));
 	xfree(l);
 	return NULL;
@@ -315,19 +318,22 @@ open_lex(const char *filename)
 }
 /* Destroy a lexical analyser */
 void 
-close_lex(struct lex *l)
+close_lex(struct lex * l)
 {
-    if (l == NULL) return;
-    if (l->fh) fclose(l->fh);
-    if (l->buffer) xfree(l->buffer);
-    if (l->token) xfree(l->token);
+    if (l == NULL)
+	return;
+    if (l->fh)
+	fclose(l->fh);
+    if (l->buffer)
+	xfree(l->buffer);
+    if (l->token)
+	xfree(l->token);
     xfree(l);
 }
 /* Signal a parse error */
-void
-parse_error(struct lex *l, const char *s)
+void 
+parse_error(struct lex * l, const char *s)
 {
-    warning("%s:%d: expected %s (found '%.8s')", 
+    warning("%s:%d: expected %s (found '%.8s')",
 	    l->filename, l->cline, s, l->token);
 }
-

+ 27 - 26
symon/lib/lex.h

@@ -1,4 +1,4 @@
-/* $Id: lex.h,v 1.13 2002/10/25 15:24:31 dijkstra Exp $ */
+/* $Id: lex.h,v 1.14 2002/11/29 10:50:29 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -32,7 +32,7 @@
 
 /*
  * This file defines the keyword tokens and lexer structure for the simple
- * lexical analyser. 
+ * lexical analyser.
  */
 
 #ifndef _SYMON_LIB_LEX_H
@@ -47,10 +47,10 @@
 #define LXT_ACCEPT     1
 #define LXT_BEGIN      2
 #define LXT_CLOSE      3
-#define LXT_COLON      4
-#define LXT_COMMA      5
-#define LXT_CPU        6
-#define LXT_DATADIR    7
+#define LXT_COMMA      4
+#define LXT_CPU        5
+#define LXT_DATADIR    6
+#define LXT_DEBUG      7
 #define LXT_END        8
 #define LXT_IF         9
 #define LXT_IN        10
@@ -67,30 +67,32 @@
 #define LXT_WRITE     21
 
 struct lex {
-    char *buffer;          /* current line(s) */
+    char *buffer;		/* current line(s) */
     const char *filename;
     FILE *fh;
-    char *token;           /* last token seen */
-    long value;            /* value of last token seen, if num */
-    int bsize;             /* size of buffer  */
-    int cline;             /* current lineno */
-    int curpos;            /* current position in buffer */
-    int endpos;            /* current maxpos in buffer */
-    int op;                /* opcode of token, if string */
-    int unget;             /* bool; token pushed back */
-    int tokpos;            /* current position in token buffer */
-    enum { LXY_STRING, LXY_NUMBER, LXY_UNKNOWN } 
-        type;              /* type of token in buffer */
+    char *token;		/* last token seen */
+    long value;			/* value of last token seen, if num */
+    int bsize;			/* size of buffer  */
+    int cline;			/* current lineno */
+    int curpos;			/* current position in buffer */
+    int endpos;			/* current maxpos in buffer */
+    int op;			/* opcode of token, if string */
+    int unget;			/* bool; token pushed back */
+    int tokpos;			/* current position in token buffer */
+    enum {
+	LXY_STRING, LXY_NUMBER, LXY_UNKNOWN
+    }
+         type;			/* type of token in buffer */
 };
 
 __BEGIN_DECLS
 struct lex *open_lex(const char *);
-void        close_lex(struct lex *);
-int         lex_nexttoken(struct lex *);
-void        lex_ungettoken(struct lex *);
-const char* parse_opcode(int);
-int         parse_token(const char *);
-void        parse_error(struct lex *, const char *);
+void close_lex(struct lex *);
+int lex_nexttoken(struct lex *);
+void lex_ungettoken(struct lex *);
+const char *parse_opcode(int);
+int parse_token(const char *);
+void parse_error(struct lex *, const char *);
 __END_DECLS
 
 /* EXPECT(l,x) = next token in l must be opcode x or error.  */
@@ -102,5 +104,4 @@ __END_DECLS
 	}                                         \
     } while (0);
 
-#endif /*_SYMON_LIB_LEX_H*/
-
+#endif				/* _SYMON_LIB_LEX_H */

+ 169 - 61
symon/lib/net.c

@@ -1,4 +1,4 @@
-/* $Id: net.c,v 1.6 2002/08/29 19:38:52 dijkstra Exp $ */
+/* $Id: net.c,v 1.7 2002/11/29 10:45:20 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -30,81 +30,189 @@
  *
  */
 
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
 #include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
 
-#include <limits.h>
-#include <stdio.h>
+#include <netdb.h>
 #include <string.h>
 
+#include "data.h"
+#include "error.h"
+#include "net.h"
+
 /*
- * lookup( hostname ) - hostname resolver
+ * getip( address | fqdn ) - get ip address
  *
- * Lookup returns 1 if hostname could be resolved. Resolved data is
- * stored in the globals lookup_hostname, lookup_address and lookup_ip below.  
+ * getip returns 1 if address could be reworked into an ip address. Resolved
+ * data is stored in the globals res_host. The address structure res_addr is
+ * aslo filled with sockaddr information that was obtained.
  */
-char lookup_hostname[_POSIX2_LINE_MAX];
-char lookup_address[_POSIX2_LINE_MAX];
-u_int32_t lookup_ip;
-
+char res_host[NI_MAXHOST];
+struct sockaddr_storage res_addr;
 int 
-lookup(char *name)
+getip(char *name)
 {
-    struct in_addr addr;
-    struct hostent *host;
-    extern int h_errno;
-    char *chostname, *sptr;
-    int i, bestl, newl;
-	
-    strcpy(lookup_hostname, "unresolved.");
-    strcpy(lookup_address, "unresolved.");
-    strncat(lookup_hostname, name, (_POSIX2_LINE_MAX - 1 - sizeof("unresolved")));
-    strncat(lookup_address, name, (_POSIX2_LINE_MAX - 1 - sizeof("unresolved")));
-
-    if (4 == sscanf(name, "%4d.%4d.%4d.%4d", &i, &i, &i, &i)) {
-	addr.s_addr = inet_addr(name);
-	if (addr.s_addr == 0xffffffff) 
+    struct addrinfo hints, *res;
+    int error;
+
+    res = NULL;
+    bzero((void *) &hints, sizeof(struct addrinfo));
+
+    /* don't lookup if we have a numeric address already */
+    hints.ai_flags = AI_NUMERICHOST;
+    if (getaddrinfo(name, NULL, &hints, &res) != 0) {
+	hints.ai_flags = 0;
+	if ((error = getaddrinfo(name, NULL, &hints, &res)) < 0) {
+	    warning("getaddrinfo(%.200s): %.200s", name, gai_strerror(error));
 	    return 0;
-	    
-	host = gethostbyaddr((char *)&addr.s_addr, 4, AF_INET);
-    } else {
-	host = gethostbyname(name);
+	}
     }
-    
-    if (host == NULL) {
-	return 0;
-    } else {
-	i = 0;
-	newl = 0;
-	bestl = 0;
-	sptr = (char *)(host->h_name ? host->h_name : host->h_aliases[0]);
-	chostname = NULL;
-
-	while (sptr) {
-	    newl = strlen(sptr);
-	    if (newl > bestl) {
-		bestl = newl;
-		chostname = sptr;
-	    }
 
-	    sptr = host->h_aliases[i++];
+    if (res && hints.ai_flags & AI_NUMERICHOST) {
+	strncpy(res_host, name, NI_MAXHOST);
+	res_host[NI_MAXHOST - 1] = 0;
+
+	cpysock(res->ai_addr, &res_addr);
+
+	freeaddrinfo(res);
+	return 1;
+    }
+    else {
+	if (res->ai_addr) {
+	    if ((error = getnameinfo(res->ai_addr, res->ai_addrlen,
+				     res_host, NI_MAXHOST,
+				     NULL, 0, NI_NUMERICHOST)) == 0) {
+		res_host[NI_MAXHOST - 1] = 0;
+
+		cpysock(res->ai_addr, &res_addr);
+
+		freeaddrinfo(res);
+		return 1;
+	    }
+	    else
+		warning("getnameinfo(%.200s): %.200s", name, gai_strerror(error));
 	}
-	
-	if (chostname)
-	    snprintf(lookup_hostname, (_POSIX2_LINE_MAX - 1), "%s", chostname);
-	
-	if (*host->h_addr_list) {
-	    lookup_ip = ntohl(*(u_int32_t *) *(char **) host->h_addr_list);
-
-	    snprintf(lookup_address, (_POSIX2_LINE_MAX - 1),"%u.%u.%u.%u", 
-		    (lookup_ip >> 24), (lookup_ip >> 16) & 0xff,
-		    (lookup_ip >> 8) & 0xff, lookup_ip & 0xff);
+	else
+	    warning("getip(%s): could not get numeric host via getaddrinfo nor getnameinfo", name);
+    }
+
+    return 0;
+}
+/*
+ * getaddr( address | fqdn, service ) - get the addrinfo structure
+ *
+ * getaddr returns a sockaddr structure in res_addr. it will only resolve
+ * the address if that is necessary.
+ */
+int 
+getaddr(char *name, char *service, int socktype, int flags)
+{
+    struct addrinfo hints, *res;
+    int error;
+
+    res = NULL;
+    bzero((void *) &hints, sizeof(hints));
+
+    hints.ai_flags = flags;
+    hints.ai_socktype = socktype;
+
+    /* don't lookup if not necessary */
+    hints.ai_flags |= AI_NUMERICHOST;
+    if (getaddrinfo(name, service, &hints, &res) != 0) {
+	hints.ai_flags = flags;
+	if ((error = getaddrinfo(name, service, &hints, &res)) < 0) {
+	    warning("getaddrinfo(%.200s): %.200s", name, gai_strerror(error));
+	    return 0;
 	}
     }
 
+    if (res->ai_addrlen > sizeof(res_addr))
+	fatal("%s:%d: internal error: getaddr returned bigger sockaddr than expected (%d>%d)",
+	      __FILE__, __LINE__, res->ai_addrlen, sizeof(res_addr));
+
+    cpysock(res->ai_addr, &res_addr);
+
     return 1;
 }
+void 
+cpysock(struct sockaddr * source, struct sockaddr_storage * dest)
+{
+    bzero(dest, sizeof(struct sockaddr_storage));
+    bcopy(source, dest, source->sa_len);
+}
+/*
+ * cmpsock_addr(sockaddr, sockaddr)
+ *
+ * compare if two sockaddr are talking about the same host
+ */
+int 
+cmpsock_addr(struct sockaddr * first, struct sockaddr * second)
+{
+
+    if (first == NULL || second == NULL)
+	return 0;
+
+    if ((first->sa_len != second->sa_len) ||
+	(first->sa_family != second->sa_family))
+	return 0;
+
+    if (first->sa_family == PF_INET) {
+	if (bcmp((void *) &((struct sockaddr_in *) first)->sin_addr,
+		 (void *) &((struct sockaddr_in *) second)->sin_addr,
+		 sizeof(struct in_addr)) == 0)
+	    return 1;
+
+	else
+	    return 0;
+    }
+
+    if (first->sa_family == PF_INET6) {
+	if (bcmp((void *) &((struct sockaddr_in6 *) first)->sin6_addr,
+		 (void *) &((struct sockaddr_in6 *) second)->sin6_addr,
+		 sizeof(struct in6_addr)) == 0)
+	    return 1;
+	else
+	    return 0;
+    }
+
+    /* don't know what to compare for this family */
+    return 0;
+}
+/* generate INADDR_ANY info */
+void 
+get_inaddrany_sockaddr(struct sockaddr_storage * sockaddr, int family, int socktype, char *port)
+{
+    struct addrinfo hints, *res;
+
+    bzero((void *) &hints, sizeof(struct addrinfo));
+    hints.ai_family = family;
+    hints.ai_socktype = socktype;
+    hints.ai_flags = AI_PASSIVE;
+    if (getaddrinfo(NULL, port, &hints, &res) != 0)
+	fatal("could not get inaddr address");
+    else {
+	cpysock((struct sockaddr *) res->ai_addr, sockaddr);
+	freeaddrinfo(res);
+    }
+}
+/* fill a source->sockaddr with a sockaddr for use in address compares */
+void 
+get_source_sockaddr(struct source * source)
+{
+    if (!getip(source->addr))
+	fatal("could not get address information for %s",
+	      source->addr);
+
+    cpysock((struct sockaddr *) & res_addr, &source->sockaddr);
+}
+/* fill mux->sockaddr with a udp listen sockaddr */
+void 
+get_mux_sockaddr(struct mux * mux, int socktype)
+{
+    if (getaddr(mux->addr, mux->port, socktype, AI_PASSIVE) == 0)
+	fatal("could not get address information for %s %s",
+	      mux->addr, mux->port);
+
+    cpysock((struct sockaddr *) & res_addr, &mux->sockaddr);
+}

+ 15 - 7
symon/lib/net.h

@@ -1,4 +1,4 @@
-/* $Id: net.h,v 1.7 2002/09/14 15:56:18 dijkstra Exp $ */
+/* $Id: net.h,v 1.9 2002/11/29 10:45:20 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -33,20 +33,28 @@
 #ifndef _SYMON_LIB_NET_H
 #define _SYMON_LIB_NET_H
 
+#include <sys/queue.h>
+#include <sys/socket.h>
 #include <sys/types.h>
 
-#define SYMUX_PORT  2100                     /* default symux port */
-
-/* Rewrite an ipadress uint32_t as 4 comma seperated bytes */
-#define IPAS4BYTES(x) \
-        ((x) >> 24), ((x) >> 16) & 0xff, ((x) >> 8) & 0xff, (x) & 0xff
+#define SYMUX_PORT  "2100"	/* default symux port */
 
 extern char lookup_hostname[];
 extern char lookup_address[];
 extern u_int32_t lookup_ip;
+extern char res_host[];
+extern struct sockaddr_storage res_addr;
 
 __BEGIN_DECLS
+int cmpsock_addr(struct sockaddr *, struct sockaddr *);
+int getaddr(char *, char *, int, int);
+int getip(char *);
 int lookup(char *);
+void cpysock(struct sockaddr *, struct sockaddr_storage *);
+void get_inaddrany_sockaddr(struct sockaddr_storage *, int, int, char *);
+void get_mux_sockaddr(struct mux *, int);
+void get_source_sockaddr(struct source *);
 __END_DECLS
 
-#endif /* _SYMON_LIB_NET_H */
+#endif				/* _SYMON_LIB_NET_H */
+

+ 7 - 7
symon/lib/xmalloc.c

@@ -1,4 +1,4 @@
-/* $Id: xmalloc.c,v 1.4 2002/03/31 14:27:46 dijkstra Exp $ */
+/* $Id: xmalloc.c,v 1.5 2002/11/29 10:50:29 dijkstra Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -24,15 +24,15 @@ void *
 xmalloc(size_t size)
 {
     void *ptr;
-    
+
     if (size == 0)
 	fatal("xmalloc: zero size");
-    
+
     ptr = malloc(size);
-    
+
     if (ptr == NULL)
 	fatal("xmalloc: out of memory (allocating %lu bytes)", (u_long) size);
-    
+
     return ptr;
 }
 
@@ -40,7 +40,7 @@ void *
 xrealloc(void *ptr, size_t new_size)
 {
     void *new_ptr;
-    
+
     if (new_size == 0)
 	fatal("xrealloc: zero size");
 
@@ -64,7 +64,7 @@ xfree(void *ptr)
     free(ptr);
 }
 
-char 
+char
 *xstrdup(const char *str)
 {
     size_t len = strlen(str) + 1;

+ 6 - 6
symon/lib/xmalloc.h

@@ -1,4 +1,4 @@
-/* $Id: xmalloc.h,v 1.5 2002/09/14 15:56:18 dijkstra Exp $ */
+/* $Id: xmalloc.h,v 1.6 2002/11/29 10:50:29 dijkstra Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -21,9 +21,9 @@
 
 /* Like malloc and friends, but these call fatal if something breaks */
 __BEGIN_DECLS
-void   *xmalloc(size_t);
-void   *xrealloc(void *, size_t);
-void    xfree(void *);
-char   *xstrdup(const char *);
+void *xmalloc(size_t);
+void *xrealloc(void *, size_t);
+void xfree(void *);
+char *xstrdup(const char *);
 __END_DECLS
-#endif /*_SYMON_LIB_XMALLOC_H*/
+#endif				/* _SYMON_LIB_XMALLOC_H */

+ 4 - 2
symon/ports/symon/Makefile

@@ -1,10 +1,10 @@
 # $OpenBSD: Makefile,v 1.1 2002/10/08 07:56:42 dhartmei Exp $
 
 COMMENT=		"active monitoring tool"
-V=			2.53
+V=			2.55
 DISTNAME=		symon-${V}
 CATEGORIES=		net sysutils
-NEED_VERSION=		1.502
+
 MASTER_SITES=		http://www.xs4all.nl/~wpd/symon/
 
 HOMEPAGE=		http://www.xs4all.nl/~wpd/symon/
@@ -52,4 +52,6 @@ LIB_DEPENDS=		rrd:rrdtool-*:net/rrdtool
 WRKDIST=		${WRKDIR}/symon
 SUBST_VARS=		V
 
+NO_REGRESS=		Yes
+
 .include <bsd.port.mk>

+ 25 - 0
symon/ports/symon/pkg/DEINSTALL

@@ -0,0 +1,25 @@
+#!/bin/sh
+# $Id: DEINSTALL,v 1.1 2002/11/29 10:59:56 dijkstra Exp $
+#
+# symon de-installation
+
+set -e
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+PREFIX=${PKG_PREFIX:-/usr/local}
+CONFIG_FILE=${SYSCONFDIR}/symon.conf
+
+if [ -e $CONFIG_FILE ]; then
+    echo
+    echo "+---------------"
+    echo "| To completely deinstall the $1 package you need to perform"
+    echo "| this step as root:"
+    echo "|"
+    echo "|           rm -f $CONFIG_FILE"
+    echo "|"
+    echo "| Do not do this if you plan on re-installing $1"
+    echo "| at some future time."
+    echo "+---------------"
+    echo
+fi
+
+exit 0

+ 2 - 2
symon/ports/symon/pkg/DEINSTALL-mon

@@ -1,12 +1,12 @@
 #!/bin/sh
-# $Id: DEINSTALL-mon,v 1.1 2002/10/18 12:26:28 dijkstra Exp $
+# $Id: DEINSTALL-mon,v 1.2 2002/11/29 10:50:32 dijkstra Exp $
 #
 # symon de-installation
 
 set -e
 PATH=/bin:/usr/bin:/sbin:/usr/sbin
 PREFIX=${PKG_PREFIX:-/usr/local}
-CONFIG_FILE=${SYSCONFDIR}/lftp.conf
+CONFIG_FILE=${SYSCONFDIR}/symon.conf
 
 if [ -e $CONFIG_FILE ]; then
     echo

+ 67 - 0
symon/ports/symon/pkg/INSTALL

@@ -0,0 +1,67 @@
+#!/bin/sh
+# $Id: INSTALL,v 1.1 2002/11/29 10:59:56 dijkstra Exp $
+#
+# Pre/post-installation setup of symon monitor
+
+# exit on errors, use a sane path and install prefix
+#
+set -e
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+PREFIX=${PKG_PREFIX:-/usr/local}
+CONFIG_FILE=${SYSCONFDIR}/symon.conf
+SAMPLE_CONFIG_FILE=$PREFIX/share/symon/symon.conf
+
+do_notice()
+{
+    echo
+    echo "+---------------"
+    echo "| The existing $1 configuration file, $CONFIG_FILE,"
+    echo "| has NOT been changed. You may want to compare it to the"
+    echo "| current sample file, $SAMPLE_CONFIG_FILE,"
+    echo "| and update your configuration as needed."
+    echo "+---------------"
+    echo
+}
+
+do_install()
+{
+    $PREFIX/share/symon/c_config.sh 127.0.0.1 2100 > $CONFIG_FILE
+
+    echo
+    echo "+---------------"
+    echo "| The $1 configuration file, $CONFIG_FILE, has been generated by"
+    echo "| $PREFIX/share/symon/c_config.sh.  It has been filled with cpu, memory,"
+    echo "| pf, default disks and interfaces. Please review this file and change"
+    echo "| the configuration to suit your needs."
+    echo "+---------------"
+    echo 
+}
+
+# verify proper execution
+#
+if [ $# -ne 2 ]; then
+    echo "usage: $0 distname { PRE-INSTALL | POST-INSTALL }" >&2
+    exit 1
+fi
+
+# Verify/process the command
+#
+case $2 in
+    PRE-INSTALL)
+        : nothing to pre-install for this port
+        ;;
+    POST-INSTALL)
+	if [ -f $CONFIG_FILE ]; then
+	    do_notice $1
+	else
+	    do_install $1
+	fi
+        ;;
+    *)
+        echo "usage: $0 distname { PRE-INSTALL | POST-INSTALL }" >&2
+        exit 1
+        ;;
+esac
+
+exit 0
+

+ 5 - 1
symon/ports/symon/pkg/PLIST

@@ -1,4 +1,4 @@
-@comment $Id: PLIST,v 1.2 2002/10/18 12:26:28 dijkstra Exp $
+@comment $Id: PLIST,v 1.3 2002/11/08 15:39:40 dijkstra Exp $
 @comment $OpenBSD: PLIST,v 1.1 2002/10/08 07:56:42 dhartmei Exp $
 libexec/symon
 libexec/symux
@@ -23,5 +23,9 @@ share/symon/web/index.php
 share/symon/web/symon.css              
 share/symon/web/symon.png              
 share/symon/web/spacer.png           
+share/symon/web/test_config.php
+share/symon/client/getsymonitem.pl
+share/symon/client/SymuxClient.pm
+share/symon/client/SymuxClient.0
 @dirrm share/symon/web
 @dirrm share/symon

+ 4 - 1
symon/ports/symon/pkg/PLIST-mux

@@ -1,7 +1,10 @@
-@comment $Id: PLIST-mux,v 1.2 2002/10/18 12:26:28 dijkstra Exp $
+@comment $Id: PLIST-mux,v 1.3 2002/11/08 15:39:40 dijkstra Exp $
 @comment $OpenBSD: PLIST-mux,v 1.1 2002/10/08 07:56:42 dhartmei Exp $
 libexec/symux
 man/cat8/symux.0
 share/symon/c_smrrds.sh
 share/symon/symux.conf
+share/symon/client/getsymonitem.pl
+share/symon/client/SymuxClient.pm
+share/symon/client/SymuxClient.0
 @dirrm share/symon

+ 1 - 0
symon/ports/symon/pkg/PLIST-web

@@ -16,5 +16,6 @@ share/symon/web/index.php
 share/symon/web/symon.css              
 share/symon/web/symon.png              
 share/symon/web/spacer.png           
+share/symon/web/test_config.php
 @dirrm share/symon/web
 @dirrm share/symon

+ 3 - 3
symon/symon/Makefile

@@ -1,10 +1,10 @@
-# $Id: Makefile,v 1.27 2002/10/18 12:29:48 dijkstra Exp $
+# $Id: Makefile,v 1.28 2002/11/29 10:48:53 dijkstra Exp $
 .include "../Makefile.inc"
 
 LIBS=	-L../lib -lsymon
-SRCS=	symon.c sm_cpu.c sm_mem.c sm_if.c sm_io.c sm_pf.c readconf.c symonnet.c 
+SRCS=	symon.c sm_cpu.c sm_debug.c sm_mem.c sm_if.c sm_io.c sm_pf.c readconf.c symonnet.c 
 OBJS+=	${SRCS:R:S/$/.o/g}
-CFLAGS+=-DNET_INET6 -I../lib
+CFLAGS+=-I../lib
 
 all: symon symon.cat8
 

+ 2 - 2
symon/symon/c_config.sh

@@ -1,5 +1,5 @@
 #!/bin/sh
-# $Id: c_config.sh,v 1.1 2002/10/18 12:29:48 dijkstra Exp $
+# $Id: c_config.sh,v 1.2 2002/11/29 10:48:53 dijkstra Exp $
 #
 # Create an example configuration file for symon on a host and print to stdout
 
@@ -36,6 +36,6 @@ cat <<EOF
 #
 monitor { $if 
           $io 
-          cpu(0), mem } stream to $host:$port
+          cpu(0), mem } stream to $host $port
 EOF
 

+ 51 - 55
symon/symon/readconf.c

@@ -1,4 +1,4 @@
-/* $Id: readconf.c,v 1.11 2002/10/18 12:29:48 dijkstra Exp $ */
+/* $Id: readconf.c,v 1.12 2002/11/29 10:48:53 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -32,20 +32,13 @@
 
 #include <sys/queue.h>
 
-#include <stdarg.h>
-#include <stdio.h>
 #include <string.h>
-#include <assert.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <unistd.h>
 
 #include "data.h"
 #include "error.h"
 #include "lex.h"
-#include "symon.h"
 #include "net.h"
-#include "readconf.h"
+#include "symon.h"
 #include "xmalloc.h"
 
 __BEGIN_DECLS
@@ -54,63 +47,65 @@ int read_symon_args(struct mux *, struct lex *);
 int read_monitor(struct muxlist *, struct lex *);
 __END_DECLS
 
+const char *default_symux_port = SYMUX_PORT;
+
 /* <hostname> (port|:|,| ) <number> */
-int
-read_host_port(struct muxlist *mul, struct mux *mux, struct lex *l)
+int 
+read_host_port(struct muxlist * mul, struct mux * mux, struct lex * l)
 {
+    char muxname[_POSIX2_LINE_MAX];
+
     lex_nexttoken(l);
-    if (!lookup(l->token)) {
+    if (!getip(l->token)) {
 	warning("%s:%d: could not resolve '%s'",
 		l->filename, l->cline, l->token);
 	return 0;
     }
 
-    if (rename_mux(mul, mux, lookup_address) == NULL) {
-	warning("%s:%d: monitored data for host '%s' has already been specified",
-		l->filename, l->cline, lookup_address);
-	return 0;
-    }
-	
-    mux->ip = lookup_ip;
+    mux->addr = xstrdup((const char *) &res_host);
 
     /* check for port statement */
     if (!lex_nexttoken(l))
 	return 1;
 
-    if (l->op == LXT_PORT || l->op == LXT_COLON || l->op == LXT_COMMA)
+    if (l->op == LXT_PORT || l->op == LXT_COMMA)
 	lex_nexttoken(l);
+
+    if (l->type != LXY_NUMBER) {
+	lex_ungettoken(l);
+	mux->port = xstrdup(default_symux_port);
+    }
     else {
-	if (l->type != LXY_NUMBER) {
-	    lex_ungettoken(l);
-	    mux->port = SYMUX_PORT;
-	    return 1;
-	}
+	mux->port = xstrdup((const char *) l->token);
     }
 
-    if (l->type != LXY_NUMBER) {
-	parse_error(l, "<number>");
+    bzero(&muxname, sizeof(muxname));
+    snprintf(&muxname[0], sizeof(muxname), "%s %s", mux->addr, mux->port);
+    if (rename_mux(mul, mux, muxname) == NULL) {
+	warning("%s:%d: monitored data for host '%s' has already been specified",
+		l->filename, l->cline, muxname);
 	return 0;
     }
 
-    mux->port = l->value;
     return 1;
 }
-/* parse "<cpu(arg)|mem|if(arg)|io(arg)>", end condition == "}" */
+/* parse "<cpu(arg)|mem|if(arg)|io(arg)|debug|pf>", end condition == "}" */
 int 
-read_symon_args(struct mux *mux, struct lex *l) 
+read_symon_args(struct mux * mux, struct lex * l)
 {
     char sn[_POSIX2_LINE_MAX];
     char sa[_POSIX2_LINE_MAX];
-    int  st;
+    int st;
 
     EXPECT(l, LXT_BEGIN)
-    while (lex_nexttoken(l) && l->op != LXT_END) {
+	while (lex_nexttoken(l) && l->op != LXT_END) {
 	switch (l->op) {
 	case LXT_CPU:
 	case LXT_IF:
 	case LXT_IO:
 	case LXT_MEM:
 	case LXT_PF:
+	case LXT_DEBUG:
 	    st = token2type(l->op);
 	    strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
 
@@ -118,19 +113,20 @@ read_symon_args(struct mux *mux, struct lex *l)
 	    lex_nexttoken(l);
 	    if (l->op == LXT_OPEN) {
 		lex_nexttoken(l);
-		if (l->op == LXT_CLOSE){
+		if (l->op == LXT_CLOSE) {
 		    parse_error(l, "<stream argument>");
 		    return 0;
 		}
 		strncpy(&sa[0], l->token, _POSIX2_LINE_MAX);
 		lex_nexttoken(l);
-		if (l->op != LXT_CLOSE){
+		if (l->op != LXT_CLOSE) {
 		    parse_error(l, ")");
 		    return 0;
 		}
-	    } else {
+	    }
+	    else {
 		lex_ungettoken(l);
-		sa[0]='\0';
+		sa[0] = '\0';
 	    }
 
 	    if ((add_mux_stream(mux, st, sa)) == NULL) {
@@ -138,27 +134,27 @@ read_symon_args(struct mux *mux, struct lex *l)
 			l->filename, l->cline, sn, sa);
 		return 0;
 	    }
-	    
-	    break; /* LXT_CPU/IF/IO/MEM/PF */
+
+	    break;		/* LXT_CPU/IF/IO/MEM/PF/DEBUG */
 	case LXT_COMMA:
 	    break;
 	default:
-	    parse_error(l, "{cpu|mem|if|io|pf}");
+	    parse_error(l, "{cpu|mem|if|io|pf|debug}");
 	    return 0;
 	    break;
 	}
     }
-    
+
     return 1;
 }
 
 /* parse monitor <args> stream [to] <host>:<port> */
-int
-read_monitor(struct muxlist *mul, struct lex *l)
+int 
+read_monitor(struct muxlist * mul, struct lex * l)
 {
     struct mux *mux;
 
-    mux = add_mux(mul, "<unnamed host>");
+    mux = add_mux(mul, SYMON_UNKMUX);
 
     /* parse cpu|mem|if|io */
     if (!read_symon_args(mux, l))
@@ -167,20 +163,16 @@ read_monitor(struct muxlist *mul, struct lex *l)
     /* parse stream to */
     EXPECT(l, LXT_STREAM);
     lex_nexttoken(l);
-    if (l->op != LXT_TO) 
+    if (l->op != LXT_TO)
 	lex_ungettoken(l);
 
     /* parse host */
-    if (!read_host_port(mul, mux, l))
-	return 0;
-    
-    return 1;
+    return read_host_port(mul, mux, l);
 }
 
 /* Read symon.conf */
-int
-read_config_file(struct muxlist *muxlist, 
-		 const char *filename)
+int 
+read_config_file(struct muxlist * muxlist, const char *filename)
 {
     struct lex *l;
     struct mux *mux;
@@ -189,16 +181,16 @@ read_config_file(struct muxlist *muxlist,
 
     if ((l = open_lex(filename)) == NULL)
 	return 0;
-    
+
     while (lex_nexttoken(l)) {
-    /* expecting keyword now */
+	/* expecting keyword now */
 	switch (l->op) {
 	case LXT_MONITOR:
-	    if (!read_monitor(muxlist, l)) 
+	    if (!read_monitor(muxlist, l))
 		return 0;
 	    break;
 	default:
-	    parse_error(l, "monitor" );
+	    parse_error(l, "monitor");
 	    return 0;
 	    break;
 	}
@@ -206,6 +198,10 @@ read_config_file(struct muxlist *muxlist,
 
     /* sanity checks */
     SLIST_FOREACH(mux, muxlist, muxes) {
+	if (strncmp(SYMON_UNKMUX, mux->name, sizeof(SYMON_UNKMUX)) == 0) {
+	    /* mux was not initialised for some reason */
+	    return 0;
+	}
 	if (SLIST_EMPTY(&mux->sl)) {
 	    warning("%s: no monitors selected for mux '%s'",
 		    l->filename, mux->name);

+ 2 - 14
symon/symon/readconf.h

@@ -1,4 +1,4 @@
-/* $Id: readconf.h,v 1.4 2002/09/14 15:49:39 dijkstra Exp $ */
+/* $Id: readconf.h,v 1.5 2002/11/29 10:48:53 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -33,21 +33,9 @@
 #ifndef _SYMON_READCONF_H
 #define _SYMON_READCONF_H
 
-#include <sys/cdefs.h>
-
 #include "data.h"
-#include "lex.h"
-
-/* Monitor subsystem structure */
-struct symonm {
-    int type;
-    void  (*init)(char *);
-    char* (*get)(char *);
-};
 
 __BEGIN_DECLS
 int read_config_file(struct muxlist *, const char *);
 __END_DECLS
-#endif /*_SYMON_READCONF_H*/
-
-
+#endif				/* _SYMON_READCONF_H */

+ 15 - 15
symon/symon/sm_cpu.c

@@ -1,7 +1,7 @@
-/* $Id: sm_cpu.c,v 1.13 2002/09/14 15:49:39 dijkstra Exp $ */
+/* $Id: sm_cpu.c,v 1.14 2002/11/29 10:48:53 dijkstra Exp $ */
 
 /* The author of this code is Willem Dijkstra (wpd@xs4all.nl).
- * 
+ *
  * The percentages function was written by William LeFebvre and is part of the
  * 'top' utility. His copyright statement is below.
  *
@@ -66,7 +66,7 @@ int percentages(int, int *, long *, long *, long *);
 __END_DECLS
 
 /* Globals for this module all start with cp_ */
-static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
+static int cp_time_mib[] = {CTL_KERN, KERN_CPTIME};
 static size_t cp_size;
 static long cp_time[CPUSTATES];
 static long cp_old[CPUSTATES];
@@ -97,27 +97,27 @@ percentages(int cnt, int *out, register long *new, register long *old, long *dif
     for (i = 0; i < cnt; i++) {
 	if ((change = *new - *old) < 0) {
 	    /* this only happens when the counter wraps */
-	    change = ((unsigned int)*new-(unsigned int)*old);
-        }
+	    change = ((unsigned int) *new - (unsigned int) *old);
+	}
 	total_change += (*dp++ = change);
 	*old++ = *new++;
     }
-  
+
     /* avoid divide by zero potential */
     if (total_change == 0)
 	total_change = 1;
-  
+
     /* calculate percentages based on overall change, rounding up */
     half_total = total_change / 2l;
     for (i = 0; i < cnt; i++)
 	*out++ = ((*diffs++ * 1000 + half_total) / total_change);
-  
+
     /* return the total in case the caller wants to use it */
     return total_change;
 }
 /* Prepare cpu module for use */
 void 
-init_cpu(char *s) 
+init_cpu(char *s)
 {
     char buf[_POSIX2_LINE_MAX];
 
@@ -129,7 +129,7 @@ init_cpu(char *s)
 }
 /* Get new cpu measurements */
 int 
-get_cpu(char *symon_buf, int maxlen, char *s) 
+get_cpu(char *symon_buf, int maxlen, char *s)
 {
     int total;
 
@@ -140,11 +140,11 @@ get_cpu(char *symon_buf, int maxlen, char *s)
 
     /* convert cp_time counts to percentages */
     total = percentages(CPUSTATES, cp_states, cp_time, cp_old, cp_diff);
-    
+
     return snpack(symon_buf, maxlen, s, MT_CPU,
-		  cp_states[CP_USER], 
-		  cp_states[CP_NICE], 
-		  cp_states[CP_SYS], 
-		  cp_states[CP_INTR], 
+		  cp_states[CP_USER],
+		  cp_states[CP_NICE],
+		  cp_states[CP_SYS],
+		  cp_states[CP_INTR],
 		  cp_states[CP_IDLE]);
 }

+ 80 - 0
symon/symon/sm_debug.c

@@ -0,0 +1,80 @@
+/* $Id: sm_debug.c,v 1.1 2002/11/29 10:44:18 dijkstra Exp $ */
+
+/*
+ * Copyright (c) 2001-2002 Willem Dijkstra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *    - Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    - 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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.
+ *
+ */
+
+/*
+ * Get current debug statistics from kernel and return them in symon_buf as
+ *
+ * debug0 : debug1 : ... : debug19
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <string.h>
+
+#include "error.h"
+#include "symon.h"
+
+#define SYMON_MAXDEBUGID      20/* = CTL_DEBUG_MAXID; depends lib/data.h */
+
+/* Globals for this module start with db_ */
+int db_mib[] = {CTL_DEBUG, 0, CTL_DEBUG_VALUE};
+int db_v[SYMON_MAXDEBUGID];
+/* Prepare if module for first use */
+void 
+init_debug(char *s)
+{
+    info("started module debug(%s)", s);
+}
+/* Get debug statistics */
+int 
+get_debug(char *symon_buf, int maxlen, char *s)
+{
+    size_t len;
+    int i;
+
+    bzero((void *) db_v, sizeof(db_v));
+    len = sizeof(int);
+
+    for (i = 0; i < SYMON_MAXDEBUGID; i++) {
+	db_mib[1] = i;
+
+	sysctl(db_mib, 3, &db_v[i], &len, NULL, 0);
+    }
+
+    return snpack(symon_buf, maxlen, s, MT_DEBUG,
+		  db_v[0], db_v[1], db_v[2], db_v[3], db_v[4], db_v[5], db_v[6],
+		  db_v[7], db_v[8], db_v[9], db_v[10], db_v[11], db_v[12], db_v[13],
+		  db_v[14], db_v[15], db_v[16], db_v[17], db_v[18], db_v[19]);
+
+}

+ 18 - 20
symon/symon/sm_if.c

@@ -1,4 +1,4 @@
-/* $Id: sm_if.c,v 1.6 2002/09/14 15:49:39 dijkstra Exp $ */
+/* $Id: sm_if.c,v 1.7 2002/11/29 10:48:53 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -35,7 +35,7 @@
  *
  * ipackets : opackets : ibytes : obytes : imcasts : omcasts : ierrors :
  * oerrors : colls : drops
- * 
+ *
  */
 
 #include <sys/types.h>
@@ -66,42 +66,40 @@
 int if_s = -1;
 /* Prepare if module for first use */
 void 
-init_if(char *s) 
+init_if(char *s)
 {
     if (if_s == -1)
 	if ((if_s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
-	    fatal("%s:%d: socket failed, %.200", 
+	    fatal("%s:%d: socket failed, %.200",
 		  __FILE__, __LINE__, strerror(errno));
 
     info("started module if(%s)", s);
 }
 /* Get interface statistics */
 int 
-get_if(char *symon_buf, int maxlen, char *interface) 
+get_if(char *symon_buf, int maxlen, char *interface)
 {
     struct ifreq ifr;
     struct if_data ifdata;
 
-    strncpy(ifr.ifr_name, interface, IFNAMSIZ-1);
+    strncpy(ifr.ifr_name, interface, IFNAMSIZ - 1);
     ifr.ifr_name[IFNAMSIZ - 1] = '\0';
-    ifr.ifr_data = (caddr_t)&ifdata;
-    
+    ifr.ifr_data = (caddr_t) & ifdata;
+
     if (ioctl(if_s, SIOCGIFDATA, &ifr)) {
 	warning("if(%s) failed (ioctl error)", interface);
 	return 0;
     }
-    
+
     return snpack(symon_buf, maxlen, interface, MT_IF,
-		  ifdata.ifi_ipackets, 
-		  ifdata.ifi_opackets, 
-		  ifdata.ifi_ibytes, 
-		  ifdata.ifi_obytes, 
-		  ifdata.ifi_imcasts, 
-		  ifdata.ifi_omcasts, 
-		  ifdata.ifi_ierrors, 
-		  ifdata.ifi_oerrors, 
-		  ifdata.ifi_collisions, 
+		  ifdata.ifi_ipackets,
+		  ifdata.ifi_opackets,
+		  ifdata.ifi_ibytes,
+		  ifdata.ifi_obytes,
+		  ifdata.ifi_imcasts,
+		  ifdata.ifi_omcasts,
+		  ifdata.ifi_ierrors,
+		  ifdata.ifi_oerrors,
+		  ifdata.ifi_collisions,
 		  ifdata.ifi_iqdrops);
 }
-
-

+ 14 - 14
symon/symon/sm_io.c

@@ -1,4 +1,4 @@
-/* $Id: sm_io.c,v 1.8 2002/09/14 15:49:39 dijkstra Exp $ */
+/* $Id: sm_io.c,v 1.9 2002/11/29 10:48:53 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -32,11 +32,11 @@
 
 /*
  * Get current disk transfer statistics from kernel and return them in symon_buf as
- * 
+ *
  * total nr of transfers : total seeks : total bytes transferred
  *
  * Non re-entrant code: gets_io messes with globals r/w without a semaphore.
- * 
+ *
  */
 #include <sys/param.h>
 #include <sys/sysctl.h>
@@ -58,14 +58,14 @@ int io_maxdks = 0;
 int io_maxstr = 0;
 
 void 
-gets_io() 
+gets_io()
 {
     int mib[3];
     char *p;
     int dks;
     size_t size;
     size_t strsize;
-    
+
     /* how much memory is needed */
     mib[0] = CTL_HW;
     mib[1] = HW_DISKCOUNT;
@@ -79,7 +79,7 @@ gets_io()
     mib[1] = HW_DISKNAMES;
     strsize = 0;
     if (sysctl(mib, 2, NULL, &strsize, NULL, 0) < 0) {
-	fatal("%s:%d: sysctl failed: can't get hw.disknames", 
+	fatal("%s:%d: sysctl failed: can't get hw.disknames",
 	      __FILE__, __LINE__);
     }
 
@@ -92,7 +92,7 @@ gets_io()
 	    fatal("%s:%d: dynamic object limit (%d) exceeded for diskstat structures",
 		  __FILE__, __LINE__, SYMON_MAX_DOBJECTS);
 	}
-	
+
 	if (io_maxstr > SYMON_MAX_OBJSIZE) {
 	    fatal("%s:%d: string size exceeded (%d)",
 		  __FILE__, __LINE__, SYMON_MAX_OBJSIZE);
@@ -124,28 +124,28 @@ gets_io()
     io_dks = 0;
     while ((io_dknames[io_dks] = strsep(&p, ",")) != NULL)
 	io_dks++;
-}    
+}
 /* Prepare io module for first use */
 void 
-init_io(char *s) 
+init_io(char *s)
 {
     info("started module io(%s)", s);
 }
 /* Get new io statistics */
 int 
-get_io(char *symon_buf, int maxlen, char *disk) 
+get_io(char *symon_buf, int maxlen, char *disk)
 {
     int i;
 
     /* look for disk */
-    for (i=0; i<io_dks; i++) {
-	if (strncmp(io_dknames[i], disk, 
+    for (i = 0; i < io_dks; i++) {
+	if (strncmp(io_dknames[i], disk,
 		    (io_dkstr + io_maxstr - io_dknames[i])) == 0)
 	    return snpack(symon_buf, maxlen, disk, MT_IO,
-			  io_dkstats[i].ds_xfer, 
+			  io_dkstats[i].ds_xfer,
 			  io_dkstats[i].ds_seek,
 			  io_dkstats[i].ds_bytes);
-    } 
+    }
 
     return 0;
 }

+ 16 - 17
symon/symon/sm_mem.c

@@ -1,4 +1,4 @@
-/* $Id: sm_mem.c,v 1.12 2002/09/14 15:49:39 dijkstra Exp $ */
+/* $Id: sm_mem.c,v 1.13 2002/11/29 10:48:53 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -64,10 +64,10 @@ static int me_pagesize;
 static int me_nswap;
 struct swapent *me_swdev = NULL;
 /* Prepare mem module for first use */
-void
-init_mem(char *s) 
+void 
+init_mem(char *s)
 {
-    me_pagesize = sysconf( _SC_PAGESIZE );
+    me_pagesize = sysconf(_SC_PAGESIZE);
     me_pageshift = 0;
     while (me_pagesize > 1) {
 	me_pageshift++;
@@ -79,17 +79,17 @@ init_mem(char *s)
 
     /* determine number of swap entries */
     me_nswap = swapctl(SWAP_NSWAP, 0, 0);
-  
-    if (me_swdev) 
+
+    if (me_swdev)
 	xfree(me_swdev);
 
     if (me_nswap != 0)
-      me_swdev = xmalloc(me_nswap * sizeof(*me_swdev));
+	me_swdev = xmalloc(me_nswap * sizeof(*me_swdev));
     else
-      me_swdev = NULL;
+	me_swdev = NULL;
 
-    if (me_swdev == NULL && me_nswap != 0) 
-	me_nswap=0; 
+    if (me_swdev == NULL && me_nswap != 0)
+	me_nswap = 0;
 
     info("started module mem(%s)", s);
 }
@@ -97,7 +97,7 @@ init_mem(char *s)
 int 
 get_mem(char *symon_buf, int maxlen, char *s)
 {
-    int i,rnswap;
+    int i, rnswap;
 
     if (sysctl(me_vm_mib, 2, &me_vmtotal, &me_vmsize, NULL, 0) < 0) {
 	warning("%s:%d: sysctl failed", __FILE__, __LINE__);
@@ -110,14 +110,14 @@ get_mem(char *symon_buf, int maxlen, char *s)
     me_stats[2] = pagetob(me_vmtotal.t_free);
 
     rnswap = swapctl(SWAP_STATS, me_swdev, me_nswap);
-    if (rnswap == -1) { 
+    if (rnswap == -1) {
 	/* A swap device may have been added; increase and retry */
-	init_mem(NULL); 
+	init_mem(NULL);
 	rnswap = swapctl(SWAP_STATS, me_swdev, me_nswap);
     }
 
     me_stats[3] = me_stats[4] = 0;
-    if (rnswap == me_nswap) { /* Read swap succesfully */
+    if (rnswap == me_nswap) {	/* Read swap succesfully */
 	/* Total things up */
 	for (i = 0; i < me_nswap; i++) {
 	    if (me_swdev[i].se_flags & SWF_ENABLE) {
@@ -127,8 +127,7 @@ get_mem(char *symon_buf, int maxlen, char *s)
 	}
     }
 
-    return snpack(symon_buf, maxlen, s, MT_MEM, 
-		  me_stats[0], me_stats[1], me_stats[2], 
+    return snpack(symon_buf, maxlen, s, MT_MEM,
+		  me_stats[0], me_stats[1], me_stats[2],
 		  me_stats[3], me_stats[4]);
 }
-

+ 10 - 10
symon/symon/sm_pf.c

@@ -1,4 +1,4 @@
-/* $Id: sm_pf.c,v 1.3 2002/09/14 15:49:39 dijkstra Exp $ */
+/* $Id: sm_pf.c,v 1.4 2002/11/29 10:48:53 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2002 Daniel Hartmeier
@@ -31,7 +31,7 @@
  */
 
 /*
- * Get current pf statistics and return them in symon_buf as 
+ * Get current pf statistics and return them in symon_buf as
  *
  *   bytes_v4_in : bytes_v4_out : bytes_v6_in : bytes_v6_out :
  *   packets_v4_in_pass : * packets_v4_in_drop : packets_v4_out_pass :
@@ -39,7 +39,7 @@
  *   packets_v6_out_pass : * packets_v6_out_drop : states_entries :
  *   states_searches : states_inserts : * states_removals : counters_match :
  *   counters_badoffset : counters_fragment : * counters_short :
- *   counters_normalize : counters_memory 
+ *   counters_normalize : counters_memory
  *
  */
 #include <sys/types.h>
@@ -60,36 +60,36 @@
 static int pf_dev = -1;
 
 /* Prepare if module for first use */
-void
+void 
 init_pf(char *s)
 {
     if (pf_dev == -1)
 	if ((pf_dev = open("/dev/pf", O_RDWR)) == -1)
-	    fatal("%s:%d: open(\"/dev/pf\") failed, %.200s", 
+	    fatal("%s:%d: open(\"/dev/pf\") failed, %.200s",
 		  __FILE__, __LINE__, strerror(errno));
 
     info("started module pf(%s)", s);
 }
 /* Get pf statistics */
-int
+int 
 get_pf(char *symon_buf, int maxlen, char *arg)
 {
     struct pf_status s;
     u_int64_t n;
-    
+
     if (pf_dev == -1) {
 	warning("pf(%s) failed (dev == -1)", arg);
 	return 0;
     }
-    
+
     if (ioctl(pf_dev, DIOCGETSTATUS, &s)) {
 	warning("pf(%s) failed (ioctl error)", arg);
 	return 0;
     }
-    
+
     if (!s.running)
 	return 0;
-    
+
     n = s.states;
     return snpack(symon_buf, maxlen, arg, MT_PF,
 		  s.bcounters[0][PF_IN],

+ 8 - 7
symon/symon/symon.8

@@ -55,7 +55,7 @@ should live on a different system and collect data from several
 instances in a LAN. 
 .Lp
 .Nm
-priviledge needs depend on the probes used. The cpu, mem, disk and interface probes will work even when symon runs as 
+priviledge needs depend on the probes used. The cpu, mem, disk, debug and interface probes will work even when symon runs as 
 .Ar "nobody" . 
 For pf, read and write access to 
 .Pa /dev/pf
@@ -91,22 +91,23 @@ Multiple monitor statements to different muxes are allowed. Whitespace, newlines
 .nf
 monitor-rule = "monitor" "{" resources "}" "stream" ["to"] host [ port ]
 resources    = resource ["(" argument ")"] [ ","|" " resources ]
-resource     = "cpu" | "mem" | "if" | "io" | "pf"
-host         = ip4addr | hostname
-port         = [ "port" | ":" | "," ] portnumber
+resource     = "cpu" | "mem" | "if" | "io" | "pf" | "debug"
+host         = ip4addr | ip6addr | hostname
+port         = [ "port" | "," ] portnumber
 argument     = number | interfacename | diskname
 .fi
 .Sh EXAMPLE
 Here is an example 
 .Ar symon.conf
-that monitors cpu, memory, pf, interfaces xl0/de0/lo0/wi0, disks wd[0-3]/cd[0-1]
-and streams that information to localhost on port 2100.
+that monitors cpu, memory, pf, interfaces xl0/de0/lo0/wi0, disks
+wd[0-3]/cd[0-1], debug variables debug0 to debug19 and streams that information
+to localhost on port 2100.
 .Pp
 .nf
 monitor { cpu(0),  mem, pf, if(xl0), if(de0),
           if(lo0), if(wi0), io(wd0), io(wd1), 
           io(wd2), io(wd3), io(cd0), io(cd1), 
-          io(ccd0)} stream to 127.0.0.1 2100
+          io(ccd0), debug } stream to 127.0.0.1 2100
 .fi
 .Sh SIGNALS
 .Bl -tag -width Ds

+ 48 - 40
symon/symon/symon.c

@@ -1,4 +1,4 @@
-/* $Id: symon.c,v 1.26 2002/10/18 12:29:48 dijkstra Exp $ */
+/* $Id: symon.c,v 1.27 2002/11/29 10:45:21 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -60,42 +60,47 @@ int flag_hup = 0;
 
 /* map stream types to inits and getters */
 struct funcmap streamfunc[] = {
-    {MT_IO,  init_io,  gets_io, get_io},  /* gets_io obtains entire io state, get_io = just a copy */
-    {MT_CPU, init_cpu, NULL,    get_cpu},
-    {MT_MEM, init_mem, NULL,    get_mem},
-    {MT_IF,  init_if,  NULL,    get_if},
-    {MT_PF,  init_pf,  NULL,    get_pf},
+    {MT_IO, init_io, gets_io, get_io},	/* gets_io obtains entire io state,
+					 * get_io = just a copy */
+    {MT_CPU, init_cpu, NULL, get_cpu},
+    {MT_MEM, init_mem, NULL, get_mem},
+    {MT_IF, init_if, NULL, get_if},
+    {MT_PF, init_pf, NULL, get_pf},
+    {MT_DEBUG, init_debug, NULL, get_debug},
     {MT_EOT, NULL, NULL}
 };
 
 /* alarmhandler that gets called every SYMON_INTERVAL */
 void 
-alarmhandler(int s) {
+alarmhandler(int s)
+{
     /* EMPTY */
 }
-void
-exithandler(int s) {
+void 
+exithandler(int s)
+{
     info("received signal %d - quitting", s);
     exit(1);
 }
-void
-huphandler(int s) {
+void 
+huphandler(int s)
+{
     info("hup received");
     flag_hup = 1;
 }
-/* 
- * Symon is a system measurement utility. 
+/*
+ * Symon is a system measurement utility.
  *
  * The main goals symon hopes to accomplish is:
- * - to take fine grained measurements of system parameters 
- * - with minimal performance impact 
+ * - to take fine grained measurements of system parameters
+ * - with minimal performance impact
  * - in a secure way.
- * 
+ *
  * Measuring system parameters (e.g. interfaces) sometimes means traversing
  * lists in kernel memory. Because of this the measurement of data has been
  * decoupled from the processing and storage of data. Storing the measured
  * information that symon provides is done by a second program, called symux.
- * 
+ *
  * Symon can keep track of cpu, memory, disk and network interface
  * interactions. Symon was built specifically for OpenBSD.
  */
@@ -131,7 +136,7 @@ main(int argc, char *argv[])
 		/* cfg path needs to be absolute, we will be a daemon soon */
 		if ((cfgpath = getwd(NULL)) == NULL)
 		    fatal("could not get working directory");
-		
+
 		maxstringlen = strlen(cfgpath) + strlen(optarg) + 1;
 		cfgfile = xmalloc(maxstringlen);
 		strncpy(cfgfile, cfgpath, maxstringlen);
@@ -142,7 +147,8 @@ main(int argc, char *argv[])
 		cfgfile[maxstringlen] = '\0';
 
 		free(cfgpath);
-	    } else 
+	    }
+	    else
 		cfgfile = xstrdup(optarg);
 
 	    break;
@@ -162,9 +168,9 @@ main(int argc, char *argv[])
     setgid(getgid());
 
     if (flag_debug != 1) {
-	if (daemon(0,0) != 0)
+	if (daemon(0, 0) != 0)
 	    fatal("daemonize failed");
-	
+
 	flag_daemon = 1;
 
 	/* record pid */
@@ -173,7 +179,7 @@ main(int argc, char *argv[])
 	    fprintf(f, "%u\n", (u_int) getpid());
 	    fclose(f);
 	}
-    } 
+    }
 
     info("symon version %s", SYMON_VERSION);
 
@@ -183,9 +189,9 @@ main(int argc, char *argv[])
     /* setup signal handlers */
     signal(SIGALRM, alarmhandler);
     signal(SIGHUP, huphandler);
-    signal(SIGINT, exithandler); 
-    signal(SIGQUIT, exithandler); 
-    signal(SIGTERM, exithandler); 
+    signal(SIGINT, exithandler);
+    signal(SIGQUIT, exithandler);
+    signal(SIGTERM, exithandler);
 
     /* prepare crc32 */
     init_crc32();
@@ -194,22 +200,22 @@ main(int argc, char *argv[])
     SLIST_FOREACH(mux, &mul, muxes) {
 	connect2mux(mux);
 	SLIST_FOREACH(stream, &mux->sl, streams) {
-	    (streamfunc[stream->type].init)(stream->args);
+	    (streamfunc[stream->type].init) (stream->args);
 	}
     }
 
     /* setup alarm */
     timerclear(&alarminterval.it_interval);
     timerclear(&alarminterval.it_value);
-    alarminterval.it_interval.tv_sec=
-	alarminterval.it_value.tv_sec=SYMON_INTERVAL;
+    alarminterval.it_interval.tv_sec =
+	alarminterval.it_value.tv_sec = SYMON_INTERVAL;
 
     if (setitimer(ITIMER_REAL, &alarminterval, NULL) != 0) {
 	fatal("alarm setup failed -- %s", strerror(errno));
     }
 
-    for (;;) {  /* FOREVER */
-	sleep(SYMON_INTERVAL*2);    /* alarm will always interrupt sleep */
+    for (;;) {			/* FOREVER */
+	sleep(SYMON_INTERVAL * 2);	/* alarm will always interrupt sleep */
 
 	if (flag_hup == 1) {
 	    flag_hup = 0;
@@ -219,7 +225,8 @@ main(int argc, char *argv[])
 	    if (!read_config_file(&newmul, cfgfile)) {
 		info("new configuration contains errors; keeping old configuration");
 		free_muxlist(&newmul);
-	    } else {
+	    }
+	    else {
 		free_muxlist(&mul);
 		mul = newmul;
 		info("read configuration file '%.100s' succesfully", cfgfile);
@@ -228,25 +235,26 @@ main(int argc, char *argv[])
 		SLIST_FOREACH(mux, &mul, muxes) {
 		    connect2mux(mux);
 		    SLIST_FOREACH(stream, &mux->sl, streams) {
-			(streamfunc[stream->type].init)(stream->args);
+			(streamfunc[stream->type].init) (stream->args);
 		    }
 		}
 	    }
-	} else {
-	    
+	}
+	else {
+
 	    /* populate for modules that get all their measurements in one go */
-	    for (i=0; i<MT_EOT; i++)
+	    for (i = 0; i < MT_EOT; i++)
 		if (streamfunc[i].gets != NULL)
-		    (streamfunc[i].gets)();
-	    
+		    (streamfunc[i].gets) ();
+
 	    SLIST_FOREACH(mux, &mul, muxes) {
 		prepare_packet(mux);
-		
+
 		SLIST_FOREACH(stream, &mux->sl, streams)
 		    stream_in_packet(stream, mux);
-		
+
 		finish_packet(mux);
-		
+
 		send_packet(mux);
 	    }
 	}

+ 19 - 16
symon/symon/symon.h

@@ -1,4 +1,4 @@
-/* $Id: symon.h,v 1.21 2002/10/18 12:29:48 dijkstra Exp $ */
+/* $Id: symon.h,v 1.22 2002/11/29 10:45:21 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -40,17 +40,16 @@
 #include "conf.h"
 
 #define SYMON_PID_FILE    "/var/run/symon.pid"
-#define SYMON_INTERVAL 5                           /* measurement interval */
-#define SYMON_WARN_SENDERR 50                      /* warn every x errors */
-#define SYMON_MAX_DOBJECTS  100                    /* max dynamic alloction
-                                                     = 100 objects */
-#define SYMON_MAX_OBJSIZE  (_POSIX2_LINE_MAX)      /* max allocation unit 
-						     = _POSIX2_LINE_MAX */
+#define SYMON_INTERVAL 5	/* measurement interval */
+#define SYMON_WARN_SENDERR 50	/* warn every x errors */
+#define SYMON_MAX_DOBJECTS  100	/* max dynamic alloction = 100 objects */
+#define SYMON_MAX_OBJSIZE  (_POSIX2_LINE_MAX)	/* max allocation unit =
+						 * _POSIX2_LINE_MAX */
 struct funcmap {
     int type;
-    void (*init)(char *);
-    void (*gets)();
-    int (*get)(char*, int, char *);
+    void (*init) (char *);
+    void (*gets) ();
+    int (*get) (char *, int, char *);
 };
 extern struct funcmap streamfunc[];
 
@@ -58,24 +57,28 @@ extern struct funcmap streamfunc[];
 __BEGIN_DECLS
 /* cpu.c */
 extern void init_cpu(char *);
-extern int  get_cpu(char *, int, char *);
+extern int get_cpu(char *, int, char *);
 
 /* mem.c */
 extern void init_mem(char *);
-extern int  get_mem(char *, int, char *);
+extern int get_mem(char *, int, char *);
 
 /* if.c */
 extern void init_if(char *);
-extern int  get_if(char *, int, char *);
+extern int get_if(char *, int, char *);
 
 /* io.c */
 extern void init_io(char *);
 extern void gets_io();
-extern int  get_io(char *, int, char *);
+extern int get_io(char *, int, char *);
 
 /* pf.c */
 extern void init_pf(char *);
-extern int  get_pf(char *, int, char *);
+extern int get_pf(char *, int, char *);
+
+/* debug.c */
+extern void init_debug(char *);
+extern int get_debug(char *, int, char *);
 __END_DECLS
 
-#endif /*_SYMON_SYMON_H*/
+#endif				/* _SYMON_SYMON_H */

+ 38 - 41
symon/symon/symonnet.c

@@ -1,4 +1,4 @@
-/* $Id: symonnet.c,v 1.10 2002/09/14 15:49:39 dijkstra Exp $ */
+/* $Id: symonnet.c,v 1.11 2002/11/29 10:45:21 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -33,7 +33,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 
-#include <netinet/in.h>
+#include <netdb.h>
 
 #include <string.h>
 #include <errno.h>
@@ -46,49 +46,46 @@
 
 /* Fill a mux structure with inet details */
 void 
-connect2mux(struct mux *mux)
+connect2mux(struct mux * mux)
 {
-    struct sockaddr_in sockaddr;
+    struct sockaddr_storage sockaddr;
+    int family;
 
-    if ((mux->symonsocket = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
-	fatal("could not obtain socket: %.200s", strerror(errno));
+    bzero((void *) &sockaddr, sizeof(sockaddr));
 
-    sockaddr.sin_family = AF_INET;
-    sockaddr.sin_port = 0;
-    sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
-    bzero(&sockaddr.sin_zero, 8);
+    get_mux_sockaddr(mux, SOCK_DGRAM);
+    family = mux->sockaddr.ss_family;
 
-    if (bind(mux->symonsocket, (struct sockaddr *) &sockaddr, 
-	     sizeof(struct sockaddr)) == -1)
-	fatal("could not bind socket: %.200s", strerror(errno));
+    get_inaddrany_sockaddr(&sockaddr, family, SOCK_DGRAM, "0");
 
-    mux->sockaddr.sin_family = AF_INET;
-    mux->sockaddr.sin_port = htons(mux->port);
-    mux->sockaddr.sin_addr.s_addr = htonl(mux->ip);
-    bzero(&mux->sockaddr.sin_zero, 8);
+    if ((mux->symuxsocket = socket(family, SOCK_DGRAM, 0)) == -1)
+	fatal("could not obtain socket: %.200s", strerror(errno));
+
+    if (bind(mux->symuxsocket, (struct sockaddr *) & sockaddr, sockaddr.ss_len) == -1)
+	fatal("could not bind socket: %.200s", strerror(errno));
 
-    info("sending packets to udp:%s:%d", 
-	 mux->name, mux->port);
+    info("sending packets to udp %s", mux->name);
 }
 /* Send data stored in the mux structure to a mux */
 void 
-send_packet(struct mux *mux)
-{   
-    if (sendto(mux->symonsocket, (void *)&mux->packet.data, 
-	       mux->offset, 0, (struct sockaddr *)&mux->sockaddr, 
-	       sizeof(mux->sockaddr))
+send_packet(struct mux * mux)
+{
+    if (sendto(mux->symuxsocket, (void *) &mux->packet.data,
+	       mux->offset, 0, (struct sockaddr *) & mux->sockaddr,
+	       mux->sockaddr.ss_len)
 	!= mux->offset) {
 	mux->senderr++;
     }
 
-    if (mux->senderr >= SYMON_WARN_SENDERR)
-	warning("%d updates to mux(%u.%u.%u.%u) lost due to send errors",
-		mux->senderr, 
-		IPAS4BYTES(mux->ip)), mux->senderr = 0;
+    if (mux->senderr >= SYMON_WARN_SENDERR) {
+	warning("%d updates to mux(%s) lost due to send errors",
+		mux->senderr, mux->name);
+	mux->senderr = 0;
+    }
 }
 /* Prepare a packet for data */
 void 
-prepare_packet(struct mux *mux) 
+prepare_packet(struct mux * mux)
 {
     time_t t = time(NULL);
 
@@ -97,31 +94,31 @@ prepare_packet(struct mux *mux)
     mux->packet.header.timestamp = t;
 
     /* symonpacketheader is always first stream */
-    mux->offset = 
-	setheader((char *)&mux->packet.data, 
+    mux->offset =
+	setheader((char *) &mux->packet.data,
 		  &mux->packet.header);
 }
 /* Put a stream into the packet for a mux */
 void 
-stream_in_packet(struct stream *stream, struct mux *mux) 
+stream_in_packet(struct stream * stream, struct mux * mux)
 {
-    mux->offset += 
-	(streamfunc[stream->type].get)      /* call getter of stream */
-	(&mux->packet.data[mux->offset],    /* packet buffer */
-	 sizeof(mux->packet.data) - mux->offset,    /* maxlen */
-	 stream->args);
+    mux->offset +=
+    (streamfunc[stream->type].get)	/* call getter of stream */
+    (&mux->packet.data[mux->offset],	/* packet buffer */
+     sizeof(mux->packet.data) - mux->offset,	/* maxlen */
+     stream->args);
 }
 /* Ready a packet for transmission, set length and crc */
-void finish_packet(struct mux *mux) 
+void 
+finish_packet(struct mux * mux)
 {
     mux->packet.header.length = mux->offset;
     mux->packet.header.crc = 0;
 
     /* fill in correct header with crc = 0 */
-    setheader((char *)&mux->packet.data, &mux->packet.header);
+    setheader((char *) &mux->packet.data, &mux->packet.header);
 
     /* fill in correct header with crc */
     mux->packet.header.crc = crc32(&mux->packet.data, mux->offset);
-    setheader((char *)&mux->packet.data, &mux->packet.header);
+    setheader((char *) &mux->packet.data, &mux->packet.header);
 }
-

+ 2 - 2
symon/symon/symonnet.h

@@ -1,4 +1,4 @@
-/* $Id: symonnet.h,v 1.4 2002/09/14 15:49:39 dijkstra Exp $ */
+/* $Id: symonnet.h,v 1.5 2002/11/29 10:45:21 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -43,4 +43,4 @@ void prepare_packet(struct mux *);
 void stream_in_packet(struct stream *, struct mux *);
 void finish_packet(struct mux *);
 __END_DECLS
-#endif /* _SYMON_SYMONNET_H */
+#endif				/* _SYMON_SYMONNET_H */

+ 1 - 0
symon/symon2web/Makefile

@@ -23,4 +23,5 @@ install:
 	${INSTALL} -c -m 444 -g www -o www symon.css		${PREFIX}/${WEBDIR}
 	${INSTALL} -c -m 444 -g www -o www symon.png		${PREFIX}/${WEBDIR}
 	${INSTALL} -c -m 444 -g www -o www spacer.png		${PREFIX}/${WEBDIR}
+	${INSTALL} -c -m 444 -g www -o www test_config.php	${PREFIX}/${WEBDIR
 

+ 1 - 0
symon/symon2web/class_cpu.inc

@@ -1,4 +1,5 @@
 <?php
+// $Id: class_cpu.inc,v 1.4 2002/11/29 10:45:46 dijkstra Exp $
 require_once("class_graph.inc");
 
 class CPU_Graph extends Graph {

+ 1 - 2
symon/symon2web/class_graph.inc

@@ -1,9 +1,8 @@
 <?php
-// $Id: class_graph.inc,v 1.6 2002/10/18 12:30:20 dijkstra Exp $
+// $Id: class_graph.inc,v 1.7 2002/11/29 10:45:46 dijkstra Exp $
 //
 // Base class for all graph classes. 
 
-// 
 class Graph {
     var $debug;
     var $graphdefaults;

+ 1 - 0
symon/symon2web/class_if.inc

@@ -1,4 +1,5 @@
 <?php
+// $Id: class_if.inc,v 1.9 2002/11/29 10:45:46 dijkstra Exp $
 require_once("class_graph.inc");
 
 class IF_Graph extends Graph {

+ 1 - 0
symon/symon2web/class_io.inc

@@ -1,4 +1,5 @@
 <?php
+// $Id: class_io.inc,v 1.4 2002/11/29 10:45:46 dijkstra Exp $
 require_once("class_graph.inc");
 
 class IO_Graph extends Graph {

+ 1 - 0
symon/symon2web/class_mem.inc

@@ -1,4 +1,5 @@
 <?php
+// $Id: class_mem.inc,v 1.4 2002/11/29 10:45:46 dijkstra Exp $
 require_once("class_graph.inc");
 
 class MEM_Graph extends Graph {

+ 1 - 0
symon/symon2web/class_pf.inc

@@ -1,4 +1,5 @@
 <?php
+// $Id: class_pf.inc,v 1.4 2002/11/29 10:45:46 dijkstra Exp $
 require_once("class_graph.inc");
 
 class PF_Graph extends Graph {

+ 1 - 0
symon/symon2web/graph_cpu.php

@@ -1,4 +1,5 @@
 <?php
+// $Id: graph_cpu.php,v 1.8 2002/11/29 10:45:46 dijkstra Exp $
 require_once("datasources.inc");
 require_once("class_cpu.inc");
 $g = new CPU_Graph();

+ 1 - 0
symon/symon2web/graph_if.php

@@ -1,4 +1,5 @@
 <?php
+// $Id: graph_if.php,v 1.9 2002/11/29 10:45:46 dijkstra Exp $
 require_once("datasources.inc");
 require_once("class_if.inc");
 $g = new IF_Graph();

+ 1 - 0
symon/symon2web/graph_io.php

@@ -1,4 +1,5 @@
 <?php
+// $Id: graph_io.php,v 1.5 2002/11/29 10:45:46 dijkstra Exp $
 require_once("datasources.inc");
 require_once("class_io.inc");
 $g = new IO_Graph();

+ 1 - 0
symon/symon2web/graph_mem.php

@@ -1,4 +1,5 @@
 <?php
+// $Id: graph_mem.php,v 1.8 2002/11/29 10:45:46 dijkstra Exp $
 require_once("datasources.inc");
 require_once("class_mem.inc");
 $g = new MEM_Graph();

+ 1 - 0
symon/symon2web/graph_pf.php

@@ -1,4 +1,5 @@
 <?php
+// $Id: graph_pf.php,v 1.3 2002/11/29 10:45:46 dijkstra Exp $
 require_once("datasources.inc");
 require_once("class_pf.inc");
 $g = new PF_Graph();

+ 2 - 0
symon/symon2web/index.php

@@ -1,4 +1,5 @@
 <?php
+// $Id: index.php,v 1.14 2002/11/29 10:45:46 dijkstra Exp $
 require_once('datasources.inc');
 require_once('class_cpu.inc');
 require_once('class_if.inc');
@@ -9,6 +10,7 @@ require_once('class_pf.inc');
 if (!empty($HTTP_SERVER_VARS["QUERY_STRING"])) {
     $args = $HTTP_SERVER_VARS["QUERY_STRING"];
     // rework args to contain ony last set 'command' 
+    $selected_machine = "";
     $options = array();
     $allargs = explode('&', $args);
     $i = 0;

+ 78 - 0
symon/symon2web/test_config.php

@@ -0,0 +1,78 @@
+<html>
+ <head>
+  <title>Symon2Web configuration test</title>
+ </head>
+ <body>
+<?php
+// $Id: test_config.php,v 1.1 2002/11/29 10:45:46 dijkstra Exp $
+//
+// Test configuration variables
+require_once('datasources.inc');
+require_once('class_cpu.inc');
+require_once('class_if.inc');
+require_once('class_io.inc');
+require_once('class_mem.inc');
+require_once('class_pf.inc');
+
+// Test to see if we can find rrdtool
+// Test to see if we can run rrdtool
+print "Trying to find rrdtool:<b>";
+$g = new CPU_Graph();
+$g->init(); $g->parseoptions();
+$rrdtool = substr($g->get("rrdtool"), 0, strpos($g->get("rrdtool"), " "));
+print $rrdtool;
+if (!is_string($rrdtool)) {
+    exit("Internal error, class_graph does not set a default rrdtool location!");
+} else {
+    if (!is_file($rrdtool)) {
+	exit("'$rrdtool' does not point to a file");
+    }
+
+    if (!is_executable($rrdtool)) {
+	exit("'$rrdtool' is not executable");
+    }
+}
+print "</b><br>rrdtool -v outputs:<hr><pre>";
+passthru($rrdtool.' -v');
+print "</pre><hr>";
+// Test to see if we can find rrd files
+print "Trying to find symon rrd files:<br>";
+$root_dir = dir($symon2web["tree"]);
+while ($machine = $root_dir->read()) {
+    if ($machine != '.' && 
+	$machine != '..' && 
+	is_dir($symon2web["tree"]."/".$machine)) {
+	$symon2web["machine"][$machine] = $symon2web["tree"]."/".$machine;
+    }
+}
+reset($symon2web["machine"]);
+while (list($machine, $dir) = each($symon2web["machine"])) {
+    $readable = TRUE;
+    print '<b>machine('.$machine.')=</b><br>';
+    $machine_dir = dir($dir);
+    while ($filename = $machine_dir->read()) {
+	$file = $dir."/".$filename;
+	if (is_file($file) && 
+	    preg_match("/^(cpu|if|io|mem|pf)(_([a-z]+))?([0-9]?).rrd$/", 
+		       $filename, $match)) {
+	    print "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$file";
+	    if (!is_readable($file)) {
+		$readable = FALSE;
+		print "!";
+	    }
+	    print "<br>";
+	}
+    }
+    print "}<br>";
+    if ($readable == FALSE) {
+	print "Note that files tagged with an exclamation mark could not be read.<br><br>";
+    } else {
+	print "And all files accessable.<br><br>";
+    }
+}
+// Test to see if we can load rrd files
+// Tie it all together
+?>
+</body>
+</html>
+

+ 0 - 4
symon/symux/.gdbinit

@@ -1,4 +0,0 @@
-file symux
-set args -d -f t
-b readconf.c:217
-r

+ 21 - 4
symon/symux/c_smrrds.sh

@@ -1,5 +1,5 @@
 #!/bin/sh
-# $Id: c_smrrds.sh,v 1.13 2002/10/25 15:24:55 dijkstra Exp $
+# $Id: c_smrrds.sh,v 1.14 2002/11/29 10:49:20 dijkstra Exp $
 
 #
 # Copyright (c) 2001-2002 Willem Dijkstra
@@ -91,8 +91,8 @@ if [ `echo $i | egrep -e "^($INTERFACES)$"` ]; then i=if_$i.rrd; fi
 if [ `echo $i | egrep -e "^($VIRTUALINTERFACES)$"` ]; then i=if_$i.rrd; fi
 # add io_*.rrd if it is a disk
 if [ `echo $i | egrep -e "^($DISKS)$"` ]; then i=io_$i.rrd; fi
-# add .rrd if it is a cpu, mem, or pf
-if [ `echo $i | egrep -e "^(cpu[0-9]|mem|pf)$"` ]; then i=$i.rrd; fi
+# add .rrd if it is a cpu, etc.
+if [ `echo $i | egrep -e "^(cpu[0-9]|mem|pf|debug)$"` ]; then i=$i.rrd; fi
 
 if [ -f $i ]; then
     echo "$i exists - ignoring"
@@ -155,6 +155,23 @@ if_*.rrd)
     echo "$i created"
     ;;
 
+debug.rrd)
+    # Build debug file
+    rrdtool create $i $RRD_ARGS \
+	DS:debug0:COUNTER:5:U:U DS:debug1:COUNTER:5:U:U \
+	DS:debug2:COUNTER:5:U:U DS:debug3:COUNTER:5:U:U \
+	DS:debug4:COUNTER:5:U:U DS:debug5:COUNTER:5:U:U \
+	DS:debug6:COUNTER:5:U:U DS:debug7:COUNTER:5:U:U \
+	DS:debug8:COUNTER:5:U:U DS:debug9:COUNTER:5:U:U \
+	DS:debug10:COUNTER:5:U:U DS:debug11:COUNTER:5:U:U \
+	DS:debug12:COUNTER:5:U:U DS:debug13:COUNTER:5:U:U \
+	DS:debug14:COUNTER:5:U:U DS:debug15:COUNTER:5:U:U \
+	DS:debug16:COUNTER:5:U:U DS:debug17:COUNTER:5:U:U \
+	DS:debug18:COUNTER:5:U:U DS:debug19:COUNTER:5:U:U \
+	$RRA_SETUP
+    echo "$i created"
+    ;;
+    
 pf.rrd)
     # Build pf file
     rrdtool create $i $RRD_ARGS \
@@ -195,7 +212,7 @@ io_*.rrd)
     # Default match
     cat <<EOF
 Usage: $0 all
-       $0 cpu0|mem|pf|<if>|<io>
+       $0 cpu0|mem|pf|debug|<if>|<io>
 
 Where:
 if=	`echo $INTERFACES|

+ 138 - 109
symon/symux/readconf.c

@@ -1,4 +1,4 @@
-/* $Id: readconf.c,v 1.15 2002/10/25 15:25:07 dijkstra Exp $ */
+/* $Id: readconf.c,v 1.16 2002/11/29 10:49:35 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -32,37 +32,35 @@
 
 #include <sys/queue.h>
 #include <sys/stat.h>
-#include <sys/types.h>
 
-#include <stdarg.h>
-#include <stdio.h>
 #include <string.h>
-#include <assert.h>
-#include <limits.h>
 #include <fcntl.h>
 #include <unistd.h>
 
-#include "xmalloc.h"
-#include "lex.h"
+#include "data.h"
 #include "error.h"
+#include "lex.h"
 #include "net.h"
-#include "data.h"
+#include "readconf.h"
+#include "xmalloc.h"
 
 __BEGIN_DECLS
-int read_mux(struct muxlist *mul, struct lex *);
-int read_source(struct sourcelist *sol, struct lex *);
+int read_mux(struct muxlist * mul, struct lex *);
+int read_source(struct sourcelist * sol, struct lex *);
 int insert_filename(char *, int, int, char *);
 __END_DECLS
 
+const char *default_symux_port = SYMUX_PORT;
+
 int 
-insert_filename(char *path, int maxlen, int type, char *args) 
+insert_filename(char *path, int maxlen, int type, char *args)
 {
     char *ts;
     char *ta;
 
     ts = ta = NULL;
 
-    switch(type) {
+    switch (type) {
     case MT_CPU:
 	ts = "cpu";
 	ta = args;
@@ -83,63 +81,70 @@ insert_filename(char *path, int maxlen, int type, char *args)
 	ts = "pf";
 	ta = "";
 	break;
+    case MT_DEBUG:
+	ts = "debug";
+	ta = "";
+	break;
     default:
 	warning("%s:%d: internal error: type (%d) unknown",
 		__FILE__, __LINE__, type);
 	return 0;
     }
-    
-    if ((snprintf(path, maxlen, "/%s%s.rrd", ts, ta)) >= maxlen) 
+
+    if ((snprintf(path, maxlen, "/%s%s.rrd", ts, ta)) >= maxlen)
 	return 0;
     else
 	return 1;
 }
-/* mux <host> (port|:|,| ) <number> */
+/* mux <host> (port|,| ) <number> */
 int 
-read_mux(struct muxlist *mul, struct lex *l)
+read_mux(struct muxlist * mul, struct lex * l)
 {
-    struct mux *m;
+    char muxname[_POSIX2_LINE_MAX];
+    struct mux *mux;
 
-    if (! SLIST_EMPTY(mul)) {
-	warning("%s:%d: only one mux statement allowed", 
+    if (!SLIST_EMPTY(mul)) {
+	warning("%s:%d: only one mux statement allowed",
 		l->filename, l->cline);
 	return 0;
     }
-    
+
     lex_nexttoken(l);
-    if (!lookup(l->token)) {
+    if (!getip(l->token)) {
 	warning("%s:%d: could not resolve '%s'",
-		l->filename, l->cline, l->token );
+		l->filename, l->cline, l->token);
 	return 0;
     }
 
-    m = add_mux(mul, lookup_address);
-    m->ip = lookup_ip;
+    mux = add_mux(mul, SYMON_UNKMUX);
+    mux->addr = xstrdup((const char *) &res_host);
 
     /* check for port statement */
     lex_nexttoken(l);
-    if (l->op == LXT_PORT || l->op == LXT_COLON || l->op == LXT_COMMA)
+
+    if (l->op == LXT_PORT || l->op == LXT_COMMA)
 	lex_nexttoken(l);
-    else {
-	if (l->type != LXY_NUMBER) {
-	    lex_ungettoken(l);
-	    m->port = SYMUX_PORT;
-	    return 1;
-	}
-    }
 
     if (l->type != LXY_NUMBER) {
-	parse_error(l, "<number>");
-	return 0;
+	lex_ungettoken(l);
+	mux->port = xstrdup(default_symux_port);
     }
+    else {
+	mux->port = xstrdup((const char *) l->token);
+    }
+
+    bzero(&muxname, sizeof(muxname));
+    snprintf(&muxname[0], sizeof(muxname), "%s %s", mux->addr, mux->port);
+
+    if (rename_mux(mul, mux, muxname) == NULL)
+	fatal("%s:%d: internal error: dual mux", __FILE__, __LINE__);
 
-    m->port = l->value;
 
     return 1;
 }
 /* source <host> { accept ... | write ... | datadir ... } */
 int 
-read_source(struct sourcelist *sol, struct lex *l)
+read_source(struct sourcelist * sol, struct lex * l)
 {
     struct source *source;
     struct stream *stream;
@@ -153,15 +158,14 @@ read_source(struct sourcelist *sol, struct lex *l)
 
     /* get hostname */
     lex_nexttoken(l);
-    if (!lookup(l->token)) {
+    if (!getip(l->token)) {
 	warning("%s:%d: could not resolve '%s'",
-		l->filename, l->cline, l->token );
-	return 0; 
+		l->filename, l->cline, l->token);
+	return 0;
     }
 
-    source = add_source(sol, lookup_address);
-    source->ip = lookup_ip;
-    
+    source = add_source(sol, res_host);
+
     EXPECT(l, LXT_BEGIN);
     while (lex_nexttoken(l)) {
 	switch (l->op) {
@@ -175,6 +179,7 @@ read_source(struct sourcelist *sol, struct lex *l)
 		case LXT_IO:
 		case LXT_MEM:
 		case LXT_PF:
+		case LXT_DEBUG:
 		    st = token2type(l->op);
 		    strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
 
@@ -194,28 +199,29 @@ read_source(struct sourcelist *sol, struct lex *l)
 			    parse_error(l, ")");
 			    return 0;
 			}
-		    } else {
+		    }
+		    else {
 			lex_ungettoken(l);
-			sa[0]='\0';
+			sa[0] = '\0';
 		    }
 
 		    if ((stream = add_source_stream(source, st, sa)) == NULL) {
-			warning("%s:%d: stream %s(%s) redefined", 
+			warning("%s:%d: stream %s(%s) redefined",
 				l->filename, l->cline, sn, sa);
 			return 0;
 		    }
 
-		    break; /* LXT_CPU/LXT_IF/LXT_IO/LXT_MEM/LXT_PF */
+		    break;	/* LXT_CPU/IF/IO/MEM/PF/DEBUG */
 		case LXT_COMMA:
 		    break;
 		default:
-		    parse_error(l, "{cpu|mem|if|io|pf}");
+		    parse_error(l, "{cpu|mem|if|io|pf|debug}");
 		    return 0;
 
 		    break;
 		}
 	    }
-	    break; /* LXT_ACCEPT */
+	    break;		/* LXT_ACCEPT */
 	    /* datadir "path" */
 	case LXT_DATADIR:
 	    lex_nexttoken(l);
@@ -230,62 +236,65 @@ read_source(struct sourcelist *sol, struct lex *l)
 	    bzero(&sb, sizeof(struct stat));
 
 	    if (stat(l->token, &sb) == 0) {
-		if (! (sb.st_mode & S_IFDIR)) {
+		if (!(sb.st_mode & S_IFDIR)) {
 		    warning("%s:%d: datadir path '%s' is not a directory",
 			    l->filename, l->cline, l->token);
 		    return 0;
 		}
-	    } else {
+	    }
+	    else {
 		warning("%s:%d: could not stat datadir path '%s'",
 			l->filename, l->cline, l->token);
 		return 0;
 	    }
 
 	    strncpy(&path[0], l->token, _POSIX2_LINE_MAX);
-	    path[_POSIX2_LINE_MAX-1] = '\0';
-	    
+	    path[_POSIX2_LINE_MAX - 1] = '\0';
+
 	    pc = strlen(path);
-	    
-	    if (path[pc-1] == '/') {
-		path[pc-1] = '\0';
+
+	    if (path[pc - 1] == '/') {
+		path[pc - 1] = '\0';
 		pc--;
 	    }
-	    
+
 	    /* add path to empty streams */
 	    SLIST_FOREACH(stream, &source->sl, streams) {
 		if (stream->file == NULL) {
-		    if (!(insert_filename(&path[pc], 
-					  _POSIX2_LINE_MAX - pc, 
-					  stream->type, 
+		    if (!(insert_filename(&path[pc],
+					  _POSIX2_LINE_MAX - pc,
+					  stream->type,
 					  stream->args))) {
 			if (stream->args && strlen(stream->args)) {
 			    warning("%s:%d: failed to construct stream "
 				    "%s(%s) filename using datadir '%s'",
-				    l->filename, l->cline, 
-				    type2str(stream->type), 
+				    l->filename, l->cline,
+				    type2str(stream->type),
 				    stream->args, l->token);
-			} else {
+			}
+			else {
 			    warning("%s:%d: failed to construct stream "
 				    "%s) filename using datadir '%s'",
-				    l->filename, l->cline, 
-				    type2str(stream->type), 
+				    l->filename, l->cline,
+				    type2str(stream->type),
 				    l->token);
 			}
 			return 0;
 		    }
-		    
+
 		    /* try filename */
 		    if ((fd = open(path, O_RDWR | O_NONBLOCK, 0)) == -1) {
-			warning("%s:%d: file '%s', guessed by datadir,  cannot be opened", 
+			warning("%s:%d: file '%s', guessed by datadir,  cannot be opened",
 				l->filename, l->cline, path);
 			return 0;
-		    } else {
+		    }
+		    else {
 			close(fd);
 			stream->file = xstrdup(path);
 		    }
 		}
 	    }
-	    break; /* LXT_DATADIR */
+	    break;		/* LXT_DATADIR */
 	    /* write cpu(0) in "filename" */
 	case LXT_WRITE:
 	    lex_nexttoken(l);
@@ -295,9 +304,10 @@ read_source(struct sourcelist *sol, struct lex *l)
 	    case LXT_IO:
 	    case LXT_MEM:
 	    case LXT_PF:
+	    case LXT_DEBUG:
 		st = token2type(l->op);
 		strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
-		
+
 		/* parse arg */
 		lex_nexttoken(l);
 		if (l->op == LXT_OPEN) {
@@ -313,50 +323,54 @@ read_source(struct sourcelist *sol, struct lex *l)
 			parse_error(l, ")");
 			return 0;
 		    }
-		} else {
+		}
+		else {
 		    lex_ungettoken(l);
-		    sa[0]='\0';
+		    sa[0] = '\0';
 		}
-		
+
 		EXPECT(l, LXT_IN);
 
 		lex_nexttoken(l);
-		
+
 		if ((stream = find_source_stream(source, st, sa)) == NULL) {
 		    if (strlen(sa)) {
-			warning("%s:%d: stream %s(%s) is not accepted for %s", 
-				l->filename, l->cline, sn, sa, source->name);
+			warning("%s:%d: stream %s(%s) is not accepted for %s",
+				l->filename, l->cline, sn, sa, source->addr);
 			return 0;
-		    } else {
-			warning("%s:%d: stream %s is not accepted for %s", 
-				l->filename, l->cline, sn, source->name);
+		    }
+		    else {
+			warning("%s:%d: stream %s is not accepted for %s",
+				l->filename, l->cline, sn, source->addr);
 			return 0;
 		    }
-		} else {
+		}
+		else {
 		    /* try filename */
 		    if ((fd = open(l->token, O_RDWR | O_NONBLOCK, 0)) == -1) {
-			warning("%s:%d: file '%s' cannot be opened", 
+			warning("%s:%d: file '%s' cannot be opened",
 				l->filename, l->cline, l->token);
 			return 0;
-		    } else {
+		    }
+		    else {
 			close(fd);
 
 			if (stream->file != NULL) {
 			    warning("%s:%d: file '%s' overwrites previous definition '%s'",
-				    l->filename, l->cline, l->token, stream->file);
+			     l->filename, l->cline, l->token, stream->file);
 			    xfree(stream->file);
 			}
 
 			stream->file = xstrdup(l->token);
 		    }
 		}
-		break; /* LXT_CPU/LXT_IF/LXT_IO/LXT_MEM/LXT_PF */
+		break;		/* LXT_CPU/IF/IO/MEM/PF/DEBUG */
 	    default:
-		parse_error(l, "{cpu|mem|if|io}");
+		parse_error(l, "{cpu|mem|if|io|debug}");
 		return 0;
 		break;
 	    }
-	    break; /* LXT_WRITE */
+	    break;		/* LXT_WRITE */
 	case LXT_END:
 	    return 1;
 	default:
@@ -365,75 +379,90 @@ read_source(struct sourcelist *sol, struct lex *l)
 	}
     }
 
-    warning("%s:%d: missing close brace on source statement", 
+    warning("%s:%d: missing close brace on source statement",
 	    l->filename, l->cline);
 
     return 0;
 }
 /* Read symux.conf */
-int  
-read_config_file(struct muxlist *mul, 
-		 struct sourcelist *sol, 
-		 const char *filename)
+int 
+read_config_file(struct muxlist * mul, const char *filename)
 {
     struct lex *l;
     struct source *source;
     struct stream *stream;
-
+    struct mux *mux;
+    struct sourcelist sol;
     SLIST_INIT(mul);
-    SLIST_INIT(sol);
+    SLIST_INIT(&sol);
 
     if ((l = open_lex(filename)) == NULL)
 	return 0;
-    
+
     while (lex_nexttoken(l)) {
-    /* expecting keyword now */
+	/* expecting keyword now */
 	switch (l->op) {
 	case LXT_MUX:
-	    if (!read_mux(mul, l))
+	    if (!read_mux(mul, l)) {
+		free_sourcelist(&sol);
 		return 0;
+	    }
 	    break;
 	case LXT_SOURCE:
-	    if (!read_source(sol, l))
+	    if (!read_source(&sol, l)) {
+		free_sourcelist(&sol);
 		return 0;
+	    }
 	    break;
 	default:
-	    parse_error(l, "mux|source" );
+	    parse_error(l, "mux|source");
+	    free_sourcelist(&sol);
 	    return 0;
 	    break;
 	}
     }
-    
+
     /* sanity checks */
     if (SLIST_EMPTY(mul)) {
+	free_sourcelist(&sol);
 	warning("%s: no mux statement seen",
 		l->filename);
 	return 0;
     }
+    else {
+	mux = SLIST_FIRST(mul);
+	mux->sol = sol;
+	if (strncmp(SYMON_UNKMUX, mux->name, sizeof(SYMON_UNKMUX)) == 0) {
+	    /* mux was not initialised for some reason */
+	    return 0;
+	}
+    }
 
-    if (SLIST_EMPTY(sol)) {
-	warning("%s: no source section seen", 
+    if (SLIST_EMPTY(&sol)) {
+	warning("%s: no source section seen",
 		l->filename);
 	return 0;
-    } else {
-	SLIST_FOREACH(source, sol, sources) {
+    }
+    else {
+	SLIST_FOREACH(source, &sol, sources) {
 	    if (SLIST_EMPTY(&source->sl)) {
-		warning("%s: no streams accepted for source '%s'", 
-			l->filename, source->name);
+		warning("%s: no streams accepted for source '%s'",
+			l->filename, source->addr);
 		return 0;
-	    } else {
+	    }
+	    else {
 		SLIST_FOREACH(stream, &source->sl, streams) {
 		    if (stream->file == NULL) {
 			warning("%s: no filename specified for stream '%s(%s)' in source '%s'",
-				l->filename, type2str(stream->type), stream->args, source->name);
+				l->filename, type2str(stream->type), stream->args, source->addr);
 			return 0;
 		    }
 		}
 	    }
 	}
     }
-    
+
     close_lex(l);
-    
+
     return 1;
 }

+ 3 - 5
symon/symux/readconf.h

@@ -1,4 +1,4 @@
-/* $Id: readconf.h,v 1.5 2002/09/14 15:54:55 dijkstra Exp $ */
+/* $Id: readconf.h,v 1.6 2002/11/29 10:49:35 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -37,9 +37,7 @@
 #include "data.h"
 
 __BEGIN_DECLS
-int read_config_file(struct muxlist *, struct sourcelist *, const char *);
+int read_config_file(struct muxlist *, const char *);
 __END_DECLS
 
-#endif /*_SYMUX_READCONF_H*/
-
-
+#endif				/* _SYMUX_READCONF_H */

+ 142 - 96
symon/symux/share.c

@@ -1,4 +1,4 @@
-/* $Id: share.c,v 1.9 2002/09/14 15:54:55 dijkstra Exp $ */
+/* $Id: share.c,v 1.11 2002/11/29 10:49:41 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -31,7 +31,7 @@
  */
 
 /* TODO:
- * Dynamically allocate buffer size 
+ * Dynamically allocate buffer size
  * Check wether one buffer suffices, do some performance tests
  */
 
@@ -43,16 +43,20 @@
 #include <sys/wait.h>
 
 #include <errno.h>
+#include <netdb.h>
+#include <signal.h>
 #include <string.h>
 #include <stdlib.h>
+#include <sysexits.h>
 #include <unistd.h>
 
 #include "data.h"
 #include "error.h"
 #include "symuxnet.h"
 #include "share.h"
+#include "net.h"
 
-/* Shared operation: 
+/* Shared operation:
  *
  * The moment the master symux receives a new packet:
  *
@@ -81,34 +85,38 @@
  */
 
 __BEGIN_DECLS
+int recvfd(int);
+int sendfd(int, int);
 void check_master();
 void check_sem();
 void client_doneread();
 void client_loop();
+void client_signalhandler();
 void client_waitread();
 void exitmaster();
 void master_resetsem();
 void reap_clients();
-int  recvfd(int);
-int  sendfd(int, int);
 __END_DECLS
 
-#define SEM_WAIT     0              /* wait semaphore */
-#define SEM_READ     1              /* have read semaphore */
+#define SEM_WAIT     0		/* wait semaphore */
+#define SEM_READ     1		/* have read semaphore */
 #define SEM_TOTAL    2
 
-int   realclients;               /* number of clients active */
-int   newclients;
-int   master;                    /* is current process master or child */
-int   clientsock;                /* connected client */
+int realclients;		/* number of clients active */
+int newclients;
+int master;			/* is current process master or child */
+int clientsock;			/* connected client */
+pid_t clientpid;
 
-enum  ipcstat { SIPC_FREE, SIPC_KEYED, SIPC_ATTACHED };
+enum ipcstat {
+    SIPC_FREE, SIPC_KEYED, SIPC_ATTACHED
+};
 key_t shmid;
 struct sharedregion *shm;
 enum ipcstat shmstat;
 key_t semid;
 enum ipcstat semstat;
-int   seqnr;
+int seqnr;
 /* Get start of data in shared region */
 long *
 shared_getmem()
@@ -116,42 +124,43 @@ shared_getmem()
     return &shm->data;
 }
 /* Get max length of data stored in shared region */
-long
+long 
 shared_getmaxlen()
 {
     return shm->reglen - sizeof(struct sharedregion);
 }
 /* Set length of data stored in shared region */
-void
+void 
 shared_setlen(long length)
 {
-    if (length > (shm->reglen - (long)sizeof(struct sharedregion)))
-	fatal("%s:%d: Internal error:"
+    if (length > (shm->reglen - (long) sizeof(struct sharedregion)))
+	fatal("%s:%d: internal error:"
 	      "set_length of shared region called with value larger than actual size",
 	      __FILE__, __LINE__);
+
     shm->ctlen = length;
 }
 /* Get length of data stored in shared region */
-long
+long 
 shared_getlen()
 {
     return shm->ctlen;
 }
 /* Check whether semaphore is available */
-void
+void 
 check_sem()
 {
     if (semstat != SIPC_KEYED)
-	fatal("%s:%d: Internal error: Semaphore not available",
+	fatal("%s:%d: internal error: semaphore not available",
 	      __FILE__, __LINE__);
 }
 
 /* Check whether process is the master process */
-void
+void 
 check_master()
 {
     if (master == 0)
-	fatal("%s:%d: Internal error: Child process tried to access master routines",
+	fatal("%s:%d: internal error: child process tried to access master routines",
 	      __FILE__, __LINE__);
 }
 
@@ -168,11 +177,11 @@ master_resetsem()
 
     if ((semctl(semid, SEM_WAIT, SETVAL, semarg) != 0) ||
 	(semctl(semid, SEM_READ, SETVAL, semarg) != 0))
-	fatal("%s:%d: Internal error: Cannot reset semaphores",
+	fatal("%s:%d: internal error: cannot reset semaphores",
 	      __FILE__, __LINE__);
 }
 /* Prepare for writing to shm */
-void
+void 
 master_forbidread()
 {
     int clientsread;
@@ -180,23 +189,25 @@ master_forbidread()
 
     check_sem();
     check_master();
-    
+
     /* prepare for a new read */
     semarg.val = 0;
     if ((clientsread = semctl(semid, SEM_READ, GETVAL, semarg)) < 0)
-	fatal("%s:%d: Internal error: Cannot read semaphore",
+	fatal("%s:%d: internal error: cannot read semaphore",
 	      __FILE__, __LINE__);
 
-    if (clientsread != realclients)
+    if (clientsread != realclients) {
 	reap_clients();
-    
+	debug("realclients = %d; clientsread = %d", realclients, clientsread);
+    }
+
     /* add new clients */
     realclients += newclients;
-    newclients = 0;    
+    newclients = 0;
     master_resetsem();
 }
 /* Signal 'permit read' to all clients */
-void
+void 
 master_permitread()
 {
     union semun semarg;
@@ -206,12 +217,11 @@ master_permitread()
     semarg.val = realclients;
 
     if (semctl(semid, SEM_WAIT, SETVAL, semarg) != 0)
-	fatal("%s:%d: Internal error: Cannot reset semaphores",
+	fatal("%s:%d: internal error: cannot reset semaphores",
 	      __FILE__, __LINE__);
 }
-
 /* Make clients wait until master signals */
-void
+void 
 client_waitread()
 {
     struct sembuf sops;
@@ -219,37 +229,47 @@ client_waitread()
     check_sem();
 
     sops.sem_num = SEM_WAIT;
-    sops.sem_op  = -1;
+    sops.sem_op = -1;
     sops.sem_flg = 0;
 
-    if (semop(semid, &sops, 1) != 0 )
-	fatal("%s:%d: Internal error: Cannot obtain semaphore (%.200s)",
-	      __FILE__, __LINE__, strerror(errno));
+    if (semop(semid, &sops, 1) != 0)
+	fatal("%s:%d: internal error: client(%d): cannot obtain semaphore (%.200s)",
+	      __FILE__, __LINE__, clientpid, strerror(errno));
 
     seqnr = shm->seqnr;
 }
-
 /* Client signal 'done reading' to master */
-void
+void 
 client_doneread()
 {
     struct sembuf sops;
 
     check_sem();
 
-    if (seqnr != shm->seqnr)
-	fatal("%s:%d: Internal error: Client lagging behind (%d, %d)",
-	      __FILE__, __LINE__, seqnr, shm->seqnr);
+    if (seqnr != shm->seqnr) {
+	close(clientsock);
+	fatal("%s:%d: client(%d) lagging behind (%d, %d) = high load?",
+	      __FILE__, __LINE__, clientpid, seqnr, shm->seqnr);
+    }
 
     sops.sem_num = SEM_READ;
-    sops.sem_op  = 1;
+    sops.sem_op = 1;
     sops.sem_flg = IPC_NOWAIT;
 
-    if (semop(semid, &sops, 1) != 0 )
-	fatal("%s:%d: Internal error: Cannot release semaphore (%.200s)",
+    if (semop(semid, &sops, 1) != 0)
+	fatal("%s:%d: internal error: cannot release semaphore (%.200s)",
 	      __FILE__, __LINE__, strerror(errno));
-}
 
+    /* force scheduling by sleeping a single second */
+    sleep(1);
+}
+/* Client signal handler => always exit */
+void 
+client_signalhandler(int s)
+{
+    debug("client(%d) received signal %d - quitting", clientpid, s);
+    exit(EX_TEMPFAIL);
+}
 /* Prepare sharing structures for use */
 void 
 initshare(int bufsize)
@@ -257,7 +277,7 @@ initshare(int bufsize)
     newclients = 0;
     realclients = 0;
     master = 1;
-    
+
     /* need some extra space for housekeeping */
     bufsize += sizeof(struct sharedregion);
 
@@ -267,113 +287,139 @@ initshare(int bufsize)
     atexit(exitmaster);
 
     if ((shmid = shmget(IPC_PRIVATE, bufsize, SHM_R | SHM_W)) < 0)
-	fatal("Could not get a shared memory identifier");
-    
+	fatal("could not get a shared memory identifier");
+
     shmstat = SIPC_KEYED;
 
-    if ((shm = (struct sharedregion *)shmat(shmid, 0, 0)) == (void *)(-1))
-	fatal("Could not attach shared memory");
+    if ((shm = (struct sharedregion *) shmat(shmid, 0, 0)) == (void *) (-1))
+	fatal("could not attach shared memory");
 
     shmstat = SIPC_ATTACHED;
     bzero(shm, bufsize);
     shm->reglen = bufsize;
-    
+
     /* allocate semaphores */
     if ((semid = semget(IPC_PRIVATE, SEM_TOTAL, SEM_A | SEM_R)) < 0)
-	fatal("Could not get a semaphore");
-    
+	fatal("could not get a semaphore");
+
     semstat = SIPC_KEYED;
 
     master_resetsem();
 }
-
 /* Spawn off a new client */
-void
-spawn_client(int sock) 
+pid_t
+spawn_client(int sock)
 {
-    pid_t client_pid;
+    pid_t pid;
+    char peername[NI_MAXHOST];
+
     check_master();
 
-    clientsock = acceptconnection(sock);
-    
-    if ((client_pid = fork())) {
+    bzero(peername, sizeof(peername));
+    clientsock = accept_connection(sock, (char *) &peername, sizeof(peername));
+
+    if ((pid = fork())) {
 	/* server */
-	newclients++;
+	if (pid == -1) {
+	    info("could not fork client process");
+	}
+	else {
+	    newclients++;
+	    info("forked client(%d) for incoming connection from %.17s",
+		 pid, peername);
+	}
+
 	close(clientsock);
-    } else {
+
+	return pid;
+    }
+    else {
 	/* client */
 	master = 0;
+
+	/* catch signals */
+	signal(SIGHUP, client_signalhandler);
+	signal(SIGINT, client_signalhandler);
+	signal(SIGQUIT, client_signalhandler);
+	signal(SIGTERM, client_signalhandler);
+	signal(SIGTERM, client_signalhandler);
+	signal(SIGPIPE, client_signalhandler);
+
+	clientpid = getpid();
 	client_loop();
+
+	/* NOT REACHED */
+	return 0;
     }
 }
-
 /* Reap exit/stopped clients */
-void
+void 
 reap_clients()
 {
-    pid_t clientpid;
-    int   status;
-    
+    pid_t pid;
+    int status;
+
     status = 0;
 
     /* Reap all children that died */
-    while (((int)(clientpid = wait4(-1, &status, WNOHANG, NULL)) > 0) && realclients >= 0) {
+    while (((int) (pid = wait4(-1, &status, WNOHANG, NULL)) > 0) && realclients >= 0) {
 
-      /* wait4 is supposed to return 0 if there is no status to report, but
-	 it also reports -1 on OpenBSD 2.9 */
+	/*
+	 * wait4 is supposed to return 0 if there is no status to report, but
+	 * it also reports -1 on OpenBSD 2.9
+	 */
 
 	if (WIFEXITED(status))
-	    info("client process %d exited", clientpid, status);
+	    info("client process %d exited", pid, status);
 	if (WIFSIGNALED(status))
-	    info("client process %d killed with signal %d", clientpid, WTERMSIG(status));
+	    info("client process %d killed with signal %d", pid, WTERMSIG(status));
 	if (WIFSTOPPED(status))
-	    info("client process %d stopped with signal %d", clientpid, WSTOPSIG(status));
+	    info("client process %d stopped with signal %d", pid, WSTOPSIG(status));
 
 	realclients--;
     }
 }
-
 /* Remove shared memory and semaphores at exit */
 void 
-exitmaster() 
+exitmaster()
 {
     union semun semarg;
 
     if (master == 0)
 	return;
-	
+
     switch (shmstat) {
     case SIPC_ATTACHED:
 	if (shmdt(shm))
-	    warning("%s:%d: Internal error: control region could not be detached",
+	    warning("%s:%d: internal error: control region could not be detached",
 		    __FILE__, __LINE__);
 
 	/* no break */
     case SIPC_KEYED:
 	if (shmctl(shmid, IPC_RMID, NULL))
-	    warning("%s:%d: Internal error: could remove control region %d",
+	    warning("%s:%d: internal error: could remove control region %d",
 		    __FILE__, __LINE__, shmid);
 	/* no break */
     case SIPC_FREE:
 	break;
 
     default:
-	warning("%s:%d: Internal error: control region is in an unknown state",
+	warning("%s:%d: internal error: control region is in an unknown state",
 		__FILE__, __LINE__);
     }
 
     switch (semstat) {
     case SIPC_KEYED:
 	semarg.val = 0;
-	if (semctl(semid, 0, IPC_RMID, semarg) != 0) 
-	    warning("%s:%d: Internal error: could not remove semaphore %d",
+	if (semctl(semid, 0, IPC_RMID, semarg) != 0)
+	    warning("%s:%d: internal error: could not remove semaphore %d",
 		    __FILE__, __LINE__, semid);
 	/* no break */
     case SIPC_FREE:
 	break;
 
     default:
-	warning("%s:%d: Internal error: semaphore is in an unknown state",
+	warning("%s:%d: internal error: semaphore is in an unknown state",
 		__FILE__, __LINE__);
     }
 }
@@ -384,25 +430,25 @@ client_loop()
     int sent;
     int written;
 
-    for (;;) { /* FOREVER */
-	
+    for (;;) {			/* FOREVER */
+
 	client_waitread();
-	
+
 	total = shared_getlen();
 	sent = 0;
 
 	while (sent < total) {
-	  
-	  if ((written = write(clientsock, (char *)(shared_getmem() + sent), total - sent)) == -1) {
-	    info("Write error. Client will quit.");
-	    exit(1);
-	  }
-	  
-	  sent += written;
-	  
-	  debug("client written %d bytes of %d total", sent, total);
+
+	    if ((written = write(clientsock, (char *) (shared_getmem() + sent), total - sent)) == -1) {
+		info("client(%d): write error. Client will quit.", clientpid);
+		exit(1);
+	    }
+
+	    sent += written;
+
+	    debug("client(%d): written %d bytes of %d total", clientpid, sent, total);
 	}
-	
+
 	client_doneread();
     }
 }

+ 15 - 14
symon/symux/share.h

@@ -1,4 +1,4 @@
-/* $Id: share.h,v 1.4 2002/09/14 15:54:55 dijkstra Exp $ */
+/* $Id: share.h,v 1.6 2002/11/29 10:49:41 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -31,7 +31,7 @@
  */
 
 /* TODO:
- * Dynamically allocate buffer size 
+ * Dynamically allocate buffer size
  * Check wether one buffer suffices, do some performance tests
  */
 
@@ -41,27 +41,28 @@
 #include "data.h"
 
 /* Share contains all routines needed for the ipc between symuxes */
-#define SEM_WAIT     0              /* wait semaphore */
-#define SEM_READ     1              /* have read semaphore */
+#define SEM_WAIT     0		/* wait semaphore */
+#define SEM_READ     1		/* have read semaphore */
 #define SEM_TOTAL    2
 
 struct sharedregion {
     long seqnr;
-    long reglen;                   /* size of buffer */
-    long ctlen;                    /* amount of content in buffer, assert(< size) */
+    long reglen;		/* size of buffer */
+    long ctlen;			/* amount of content in buffer, assert(<
+				 * size) */
     long data;
 };
 
 /* prototypes */
 __BEGIN_DECLS
-void  master_forbidread();
-void  master_permitread();
-long  shared_getlen();
-long  shared_getmaxlen();
+void master_forbidread();
+void master_permitread();
+long shared_getlen();
+long shared_getmaxlen();
 long *shared_getmem();
-void  initshare();
-void  shared_setlen(long);
-void  spawn_client(int);
+void initshare();
+void shared_setlen(long);
+pid_t spawn_client(int);
 __END_DECLS
 
-#endif /*_SYMUX_SHARE_H*/
+#endif				/* _SYMUX_SHARE_H */

+ 20 - 15
symon/symux/symux.8

@@ -84,23 +84,26 @@ instead of
 .Nm
 obtains configuration data from 
 .Pa /etc/symux.conf .
-The configuration file contains one mux stanza that defines on what interface and port
+The configuration file contains one mux stanza that defines on what host address and port
 .Nm 
 should listen to for incoming monitored data. There is a source section for
 every host that is to be monitored. The source section defines what data to
-accept and where to write that data to. Whitespace, newlines and text behind
-'#' are ignored. The format in BNF:
+accept and where to write that data to. In the case that a source is of another
+address family than the mux stanza, i.e. source = ipv6 with mux = ipv4, a
+listen port of the sources' family is opened using the unspecified
+address. Whitespace, newlines and text behind '#' are ignored. The format in
+BNF:
 .Pp
 .nf
 stmt         = mux-stmt | source-stmt
 mux-stmt     = "mux" host [ port ]
-host         = ip4addr | hostname
-port         = [ "port" | ":" | "," ] portnumber
+host         = ip4addr | ip6addr | hostname
+port         = [ "port" | "," ] portnumber
 source-stmt  = "source" host "{" accept-stmts write-stmts [ datadir-stmt ] "}"
 accept-stmts = accept-stmt [accept-stmts]
 accept-stmt  = "accept" "{" resources "}"
 resources    = resource ["(" argument ")"] [ ","|" " resources ]
-resource     = "cpu" | "mem" | "if" | "io" | "pf"
+resource     = "cpu" | "mem" | "if" | "io" | "pf" | "debug"
 argument     = number | interfacename | diskname
 datadir-stmt = "datadir" dirname
 write-stmts  = write-stmt [write-stmts]
@@ -133,7 +136,7 @@ on localhost.
 will also listen on tcp port 2100 for incoming listeners.
 .Pp
 .nf
-mux 127.0.0.1:2100
+mux 127.0.0.1 2100
 source 127.0.0.1 {
     accept { cpu(0), mem, pf,
              if(xl0), if(de0),
@@ -188,19 +191,19 @@ The format is
 Data formats:
 .Bl -tag -width Ds
 .It cpu
-Time spent in (user, nice, system, interrupt, idle). Total time is 100, data is
-offered with precision 2.
+Time spent in ( user, nice, system, interrupt, idle ). Total time is 100, data
+is offered with precision 2.
 .It mem
-Memory in (real active, real total, free, swap used, swap total). All values
+Memory in ( real_active, real_total, free, swap_used, swap_total ). All values
 are in bytes rounded of to page boundaries. Values are 32 bit unsigned integers
 internally.
 .It if
-Interface counters (packets in, packets out, bytes in, bytes out, multicasts
-in, multicasts out, errors in, errors out, collisions, drops). Values are 32
-bit unsigned integers internally.
+Interface counters ( packets_in, packets_out, bytes_in, bytes_out,
+multicasts_in, multicasts_out, errors_in, errors_out, collisions, drops
+). Values are 32 bit unsigned integers internally.
 .It io
-Io/disk counters (total transfers, total seeks, total bytes). Values are 64 bit
-unsigned integers internally.
+Io/disk counters ( total_transfers, total_seeks, total_bytes ). Values are 64
+bit unsigned integers internally.
 .It pf
 Packet filter statistics ( bytes_v4_in : bytes_v4_out : bytes_v6_in :
 bytes_v6_out : packets_v4_in_pass : packets_v4_in_drop : packets_v4_out_pass :
@@ -209,6 +212,8 @@ packets_v6_out_pass : packets_v6_out_drop : states_entries : states_searches :
 states_inserts : states_removals : counters_match : counters_badoffset :
 counters_fragment : counters_short : counters_normalize : counters_memory
 ). Values are 64 bit unsigned integers internally.
+.It debug
+Kernel variables debug0 to debug19. ( debug0 : ... : debug19 ). Values are 32 bit unsigned integers. 
 .El
 .Sh SIGNALS
 .Bl -tag -width Ds

+ 80 - 71
symon/symux/symux.c

@@ -1,4 +1,4 @@
-/* $Id: symux.c,v 1.24 2002/10/18 12:30:48 dijkstra Exp $ */
+/* $Id: symux.c,v 1.26 2002/11/29 10:45:22 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -7,7 +7,7 @@
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- 
+ *
  *    - Redistributions of source code must retain the above copyright
  *      notice, this list of conditions and the following disclaimer.
  *    - Redistributions in binary form must reproduce the above
@@ -64,29 +64,31 @@ int flag_hup = 0;
 fd_set fdset;
 int maxfd;
 
-void
-exithandler(int s) {
+void 
+exithandler(int s)
+{
     info("received signal %d - quitting", s);
     exit(EX_TEMPFAIL);
 }
-void
-huphandler(int s) {
+void 
+huphandler(int s)
+{
     info("hup received");
     flag_hup = 1;
 }
-/* 
+/*
  * symux is the receiver of symon performance measurements.
  *
  * The main goals symon hopes to accomplish is:
- * - to take fine grained measurements of system parameters 
- * - with minimal performance impact 
+ * - to take fine grained measurements of system parameters
+ * - with minimal performance impact
  * - in a secure way.
- * 
+ *
  * Measuring system parameters (e.g. interfaces) sometimes means traversing
  * lists in kernel memory. Because of this the measurement of data has been
  * decoupled from the processing and storage of data. Storing the measured
  * information that symon provides is done by a second program, called symux.
- * 
+ *
  * Symon can keep track of cpu, memory, disk and network interface
  * interactions. Symon was built specifically for OpenBSD.
  */
@@ -101,7 +103,6 @@ main(int argc, char *argv[])
     char *stringptr;
     int maxstringlen;
     struct muxlist mul, newmul;
-    struct sourcelist sol, newsol;
     char *arg_ra[4];
     struct stream *stream;
     struct source *source;
@@ -113,11 +114,10 @@ main(int argc, char *argv[])
     int churnbuflen;
 
     SLIST_INIT(&mul);
-    SLIST_INIT(&sol);
-	
+
     /* reset flags */
     flag_debug = 0;
-    flag_daemon = 0;    
+    flag_daemon = 0;
     cfgfile = SYMUX_CONFIG_FILE;
 
     while ((ch = getopt(argc, argv, "dvf:")) != -1) {
@@ -130,7 +130,7 @@ main(int argc, char *argv[])
 		/* cfg path needs to be absolute, we will be a daemon soon */
 		if ((cfgpath = getwd(NULL)) == NULL)
 		    fatal("could not get working directory");
-		
+
 		maxstringlen = strlen(cfgpath) + strlen(optarg) + 1;
 		cfgfile = xmalloc(maxstringlen);
 		strncpy(cfgfile, cfgpath, maxstringlen);
@@ -141,7 +141,8 @@ main(int argc, char *argv[])
 		cfgfile[maxstringlen] = '\0';
 
 		free(cfgpath);
-	    } else 
+	    }
+	    else
 		cfgfile = xstrdup(optarg);
 
 	    break;
@@ -154,16 +155,16 @@ main(int argc, char *argv[])
     }
 
     /* parse configuration file */
-    if (!read_config_file(&mul, &sol, cfgfile))
+    if (!read_config_file(&mul, cfgfile))
 	fatal("configuration contained errors; quitting");
 
     setegid(getgid());
     setgid(getgid());
 
     if (flag_debug != 1) {
-	if (daemon(0,0) != 0)
+	if (daemon(0, 0) != 0)
 	    fatal("daemonize failed");
-	
+
 	flag_daemon = 1;
 
 	/* record pid */
@@ -172,8 +173,8 @@ main(int argc, char *argv[])
 	    fprintf(f, "%u\n", (u_int) getpid());
 	    fclose(f);
 	}
-    } 
-    
+    }
+
     info("symux version %s", SYMUX_VERSION);
 
     if (flag_debug == 1)
@@ -181,81 +182,84 @@ main(int argc, char *argv[])
 
     mux = SLIST_FIRST(&mul);
 
-    churnbuflen = calculate_churnbuffer(&sol);
+    churnbuflen = calculate_churnbuffer(&mux->sol);
     debug("size of churnbuffer = %d", churnbuflen);
     initshare(churnbuflen);
 
     /* catch signals */
     signal(SIGHUP, huphandler);
-    signal(SIGINT, exithandler); 
-    signal(SIGQUIT, exithandler); 
+    signal(SIGINT, exithandler);
+    signal(SIGQUIT, exithandler);
+    signal(SIGTERM, exithandler);
     signal(SIGTERM, exithandler);
-    signal(SIGTERM, exithandler); 
 
     /* prepare crc32 */
     init_crc32();
 
-    getsymonsocket(mux);
-    getclientsocket(mux);
+    /* prepare sockets */
+    if (get_symon_sockets(mux) == 0)
+	fatal("no sockets could be opened for incoming symon traffic");
+    if (get_client_socket(mux) == 0)
+	fatal("socket for client connections could not be opened");
 
-    for (;;) {
-	waitfortraffic(mux, &sol, &source, &packet);
+    /* main loop */
+    for (;;) {			/* FOREVER */
+	wait_for_traffic(mux, &source, &packet);
 
 	if (flag_hup == 1) {
 	    flag_hup = 0;
 
 	    SLIST_INIT(&newmul);
-	    SLIST_INIT(&newsol);
 
-	    if (!read_config_file(&newmul, &newsol, cfgfile)) {
+	    if (!read_config_file(&newmul, cfgfile)) {
 		info("new configuration contains errors; keeping old configuration");
 		free_muxlist(&newmul);
-		free_sourcelist(&newsol);
-	    } else {
+	    }
+	    else {
 		info("read configuration file '%.100s' succesfully", cfgfile);
 		free_muxlist(&mul);
-		free_sourcelist(&sol);
 		mul = newmul;
-		sol = newsol;
 		mux = SLIST_FIRST(&mul);
-		getsymonsocket(mux);
-		getclientsocket(mux);
+		get_symon_sockets(mux);
+		get_client_socket(mux);
 	    }
-	} else {
+	}
+	else {
 
-	    /* Put information from packet into stringbuf (shared region). Note
-	     * that the stringbuf is used twice: 1) to update the rrdfile and 2) to
-	     * collect all the data from a single packet that needs to shared to
-	     * the clients. This is the reason for the hasseling with stringptr.
+	    /*
+	     * Put information from packet into stringbuf (shared region).
+	     * Note that the stringbuf is used twice: 1) to update the
+	     * rrdfile and 2) to collect all the data from a single packet
+	     * that needs to shared to the clients. This is the reason for
+	     * the hasseling with stringptr.
 	     */
-	    
+
 	    offset = mux->offset;
 	    maxstringlen = shared_getmaxlen();
 	    /* put time:ip: into shared region */
 	    master_forbidread();
 	    timestamp = (time_t) packet.header.timestamp;
-	    stringbuf = (char *)shared_getmem();
-	    snprintf(stringbuf, maxstringlen, "%u.%u.%u.%u;",
-		     IPAS4BYTES(source->ip));
-	    
+	    stringbuf = (char *) shared_getmem();
+	    snprintf(stringbuf, maxstringlen, "%s;", source->addr);
+
 	    /* hide this string region from rrd update */
 	    maxstringlen -= strlen(stringbuf);
 	    stringptr = stringbuf + strlen(stringbuf);
-	    
+
 	    while (offset < packet.header.length) {
 		bzero(&ps, sizeof(struct packedstream));
 		offset += sunpack(packet.data + offset, &ps);
-		
+
 		/* find stream in source */
 		stream = find_source_stream(source, ps.type, ps.args);
-		
+
 		if (stream != NULL) {
 		    /* put type in and hide from rrd */
 		    snprintf(stringptr, maxstringlen, "%s:", type2str(ps.type));
 		    maxstringlen -= strlen(stringptr);
 		    stringptr += strlen(stringptr);
 		    /* put arguments in and hide from rrd */
-		    snprintf(stringptr, maxstringlen, "%s:", 
+		    snprintf(stringptr, maxstringlen, "%s:",
 			     ((ps.args == NULL) ? "0" : ps.args));
 		    maxstringlen -= strlen(stringptr);
 		    stringptr += strlen(stringptr);
@@ -264,10 +268,10 @@ main(int argc, char *argv[])
 		    arg_ra[3] = stringptr;
 		    maxstringlen -= strlen(stringptr);
 		    stringptr += strlen(stringptr);
-		    
+
 		    /* put measurements in */
 		    ps2strn(&ps, stringptr, maxstringlen, PS2STR_RRD);
-		    
+
 		    if (stream->file != NULL) {
 			/* clear optind for getopt call by rrdupdate */
 			optind = 0;
@@ -275,41 +279,46 @@ main(int argc, char *argv[])
 			arg_ra[0] = "rrdupdate";
 			arg_ra[1] = "--";
 			arg_ra[2] = stream->file;
-			
-			/* This call will cost a lot (symux will become
+
+			/*
+			 * This call will cost a lot (symux will become
 			 * unresponsive and eat up massive amounts of cpu) if
-			 * the rrdfile is out of sync. While I could update the
-			 * rrd in a separate process, I choose not to at this
-			 * time.  
+			 * the rrdfile is out of sync. While I could update
+			 * the rrd in a separate process, I choose not to at
+			 * this time.
 			 */
 			rrd_update(4, arg_ra);
-			
+
 			if (rrd_test_error()) {
 			    warning("rrd_update:%s", rrd_get_error());
-			    warning("%s %s %s %s", arg_ra[0], arg_ra[1], 
+			    warning("%s %s %s %s", arg_ra[0], arg_ra[1],
 				    arg_ra[2], arg_ra[3]);
-			    rrd_clear_error();                                                            
-			} else {
-			    if (flag_debug == 1) 
-				debug("%s %s %s %s", arg_ra[0], arg_ra[1], 
+			    rrd_clear_error();
+			}
+			else {
+			    if (flag_debug == 1)
+				debug("%s %s %s %s", arg_ra[0], arg_ra[1],
 				      arg_ra[2], arg_ra[3]);
 			}
 		    }
 		    maxstringlen -= strlen(stringptr);
 		    stringptr += strlen(stringptr);
 		    snprintf(stringptr, maxstringlen, ";");
-		maxstringlen -= strlen(stringptr);
-		stringptr += strlen(stringptr);
+		    maxstringlen -= strlen(stringptr);
+		    stringptr += strlen(stringptr);
 		}
 	    }
-	    /* packet = parsed and in ascii in shared region -> copy to clients */
+	    /*
+	     * packet = parsed and in ascii in shared region -> copy to
+	     * clients
+	     */
 	    snprintf(stringptr, maxstringlen, "\n");
 	    stringptr += strlen(stringptr);
 	    shared_setlen((stringptr - stringbuf));
-	    debug("Churnbuffer used: %d", (stringptr - stringbuf));
+	    debug("churnbuffer used: %d", (stringptr - stringbuf));
 	    master_permitread();
-	} /* flag_hup == 0 */
-    } /* forever */
+	}			/* flag_hup == 0 */
+    }				/* forever */
 
     /* NOT REACHED */
     return (EX_SOFTWARE);

+ 2 - 2
symon/symux/symux.conf

@@ -1,9 +1,9 @@
 #
-# $Id: symux.conf,v 1.19 2002/10/25 15:25:08 dijkstra Exp $
+# $Id: symux.conf,v 1.20 2002/11/29 10:49:41 dijkstra Exp $
 #
 # Demo symux configuration. See symux(8) for BNF.
 
-mux 10.0.0.1:2100
+mux 10.0.0.1 2100
 
 source 10.0.0.1 {
 	accept { cpu(0), mem, if(xl0), if(de0),

+ 3 - 3
symon/symux/symux.h

@@ -1,4 +1,4 @@
-/* $Id: symux.h,v 1.15 2002/10/18 12:30:48 dijkstra Exp $ */
+/* $Id: symux.h,v 1.16 2002/11/29 10:45:22 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -37,7 +37,7 @@
 
 #define SYMUX_PID_FILE "/var/run/symux.pid"
 
-/* Amount of connections allowed in listen backlog 
+/* Amount of connections allowed in listen backlog
  * - note that more than 128 makes no sense in OpenBSD
  */
 #define SYMUX_TCPBACKLOG 5
@@ -45,4 +45,4 @@
 /* Number of retries allowed in recvfrom */
 #define SYMUX_MAXREADTRIES 5
 
-#endif /*_SYMUX_SYMUX_H*/
+#endif				/* _SYMUX_SYMUX_H */

+ 158 - 98
symon/symux/symuxnet.c

@@ -1,4 +1,4 @@
-/* $Id: symuxnet.c,v 1.10 2002/09/14 15:54:56 dijkstra Exp $ */
+/* $Id: symuxnet.c,v 1.12 2002/11/29 10:45:22 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -32,10 +32,10 @@
 
 #include <sys/types.h>
 #include <sys/socket.h>
-#include <netinet/in.h>
 
 #include <errno.h>
 #include <fcntl.h>
+#include <netdb.h>
 #include <string.h>
 #include <unistd.h>
 
@@ -47,59 +47,95 @@
 #include "xmalloc.h"
 #include "share.h"
 
-/* Obtain a udp socket for incoming symon traffic */
+__BEGIN_DECLS
+int check_crc_packet(struct symonpacket *);
+__END_DECLS
+
+/* Obtain sockets for incoming symon traffic */
 int 
-getsymonsocket(struct mux *mux) 
+get_symon_sockets(struct mux * mux)
 {
-    struct sockaddr_in sockaddr;
-    int sock;
-    
-    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 
-	fatal("could not obtain socket: %.200s", strerror(errno));
+    struct source *source;
+    struct sockaddr_storage sockaddr;
+    int family, nsocks;
+    char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
+    nsocks = 0;
 
-    sockaddr.sin_family = AF_INET;
-    sockaddr.sin_port = htons(mux->port);
-    sockaddr.sin_addr.s_addr = htonl(mux->ip);
-    bzero(&sockaddr.sin_zero, sizeof(sockaddr.sin_zero));
+    /* generate the udp listen socket specified in the mux statement */
+    get_mux_sockaddr(mux, SOCK_DGRAM);
 
-    if (bind(sock, (struct sockaddr *) &sockaddr, 
-	     sizeof(struct sockaddr)) == -1)
-	fatal("could not bind socket: %.200s", strerror(errno));
+    /* iterate over our sources to determine what types of sockets we need */
+    SLIST_FOREACH(source, &mux->sol, sources) {
+	get_source_sockaddr(source);
 
-    mux->symonsocket = sock;
+	family = source->sockaddr.ss_family;
+	/* do we have a socket for this type of family */
+	if (mux->symonsocket[family] <= 0) {
+	    if ((mux->symonsocket[family] = socket(family, SOCK_DGRAM, 0)) != -1) {
+		/*
+		 * does the mux statement specify a specific destination
+		 * address
+		 */
+		if (mux->sockaddr.ss_family == family) {
+		    cpysock((struct sockaddr *) & mux->sockaddr, &sockaddr);
+		}
+		else {
+		    get_inaddrany_sockaddr(&sockaddr, family, SOCK_DGRAM, mux->port);
+		}
 
-    info("listening for incoming symon traffic on udp:%s:%d", 
-	 mux->name, mux->port);
+		if (bind(mux->symonsocket[family], (struct sockaddr *) & sockaddr,
+			 sockaddr.ss_len) == -1)
+		    close(mux->symonsocket[family]);
+		else {
+		    if (getnameinfo((struct sockaddr *) & sockaddr, sockaddr.ss_len,
+				    hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
+				    NI_NUMERICHOST | NI_NUMERICSERV)) {
+			info("getnameinfo error - cannot determine numeric hostname and service");
+			info("listening for incoming symon traffic for family %d", family);
+		    }
+		    else
+			info("listening for incoming symon traffic on udp %s %s", hbuf, sbuf);
 
-    return sock;
+		    nsocks++;
+		}
+	    }
+	}
+    }
+    return nsocks;
 }
 /* Obtain a listen socket for new clients */
-int
-getclientsocket(struct mux *mux)
+int 
+get_client_socket(struct mux * mux)
 {
-  struct sockaddr_in sockaddr;
-  int sock;
-  
-  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+    struct addrinfo hints, *res;
+    int error, sock;
+
+    if ((sock = socket(mux->sockaddr.ss_family, SOCK_STREAM, 0)) == -1)
 	fatal("could not obtain socket: %.200s", strerror(errno));
 
-    sockaddr.sin_family = AF_INET;
-    sockaddr.sin_port = htons(mux->port);
-    sockaddr.sin_addr.s_addr = htonl(mux->ip);
-    bzero(&sockaddr.sin_zero, sizeof(sockaddr.sin_zero));
+    bzero((void *) &hints, sizeof(struct addrinfo));
 
-    if (bind(sock, (struct sockaddr *) &sockaddr, 
-	     sizeof(struct sockaddr)) == -1)
+    hints.ai_family = mux->sockaddr.ss_family;
+    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+    hints.ai_socktype = SOCK_STREAM;
+
+    if ((error = getaddrinfo(mux->addr, mux->port, &hints, &res)) != 0)
+	fatal("could not get address information for %s:%s - %s",
+	      mux->addr, mux->port, gai_strerror(error));
+
+    if (bind(sock, (struct sockaddr *) res->ai_addr, res->ai_addrlen) == -1)
 	fatal("could not bind socket: %.200s", strerror(errno));
 
+    freeaddrinfo(res);
+
     if (listen(sock, SYMUX_TCPBACKLOG) == -1)
-      fatal("could not listen to socket: %.200s", strerror(errno));
+	fatal("could not listen to socket: %.200s", strerror(errno));
 
     fcntl(sock, O_NONBLOCK);
     mux->clientsocket = sock;
 
-    info("listening for incoming connections on tcp:%s:%d", 
-	 mux->name, mux->port);
+    info("listening for incoming connections on tcp %s %s",
+	 mux->addr, mux->port);
 
     return sock;
 }
@@ -108,86 +144,97 @@ getclientsocket(struct mux *mux)
  * Returns the <source> and <packet>
  * Silently forks off clienthandlers
  */
-void
-waitfortraffic(struct mux *mux, struct sourcelist *sourcelist, 
-	       struct source **source, struct symonpacket *packet) 
+void 
+wait_for_traffic(struct mux * mux, struct source ** source,
+		 struct symonpacket * packet)
 {
     fd_set readset;
+    int i;
     int socksactive;
     int maxsock;
 
-    maxsock = ((mux->clientsocket > mux->symonsocket) ?
-	       mux->clientsocket :
-	       mux->symonsocket);
-    maxsock++;
-
-    for (;;) { /* FOREVER - until a valid symon packet is received */
+    for (;;) {			/* FOREVER - until a valid symon packet is
+				 * received */
 	FD_ZERO(&readset);
 	FD_SET(mux->clientsocket, &readset);
-	FD_SET(mux->symonsocket, &readset);
-	
+
+	maxsock = mux->clientsocket;
+
+	for (i = 0; i < AF_MAX; i++) {
+	    if (mux->symonsocket[i] > 0) {
+		FD_SET(mux->symonsocket[i], &readset);
+		maxsock = ((maxsock < mux->symonsocket[i]) ? mux->symonsocket[i] :
+			   maxsock);
+	    }
+	}
+
+	maxsock++;
 	socksactive = select(maxsock, &readset, NULL, NULL, NULL);
-	
+
 	if (socksactive != -1) {
 	    if (FD_ISSET(mux->clientsocket, &readset)) {
 		spawn_client(mux->clientsocket);
 	    }
 
-	    if (FD_ISSET(mux->symonsocket, &readset)) {
-		if (recvsymonpacket(mux, sourcelist, source, packet))
-		    return;
-	    }
-	} else {
+	    for (i = 0; i < AF_MAX; i++)
+		if (FD_ISSET(mux->symonsocket[i], &readset)) {
+		    if (recv_symon_packet(mux, i, source, packet))
+			return;
+		}
+	}
+	else {
 	    if (errno == EINTR)
-		return;  /* signal received while waiting, bail out */
+		return;		/* signal received while waiting, bail out */
 	}
     }
 }
 /* Receive a symon packet for mux. Checks if the source is allowed and returns the source found.
- * return 0 if no valid packet found 
+ * return 0 if no valid packet found
  */
-int
-recvsymonpacket(struct mux *mux, struct sourcelist *sourcelist, 
-	      struct source **source, struct symonpacket *packet) 
-
+int 
+recv_symon_packet(struct mux * mux, int socknr, struct source ** source,
+		  struct symonpacket * packet)
 {
-    struct sockaddr_in sind;
-    u_int32_t sourceaddr;
-    int size;
-    unsigned int received;
+    char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
+    struct sockaddr_storage sind;
     socklen_t sl;
-    int tries;
+    int size, tries;
+    unsigned int received;
     u_int32_t crc;
 
     received = 0;
     tries = 0;
+    bzero((void *) hbuf, sizeof(hbuf));
+    bzero((void *) sbuf, sizeof(sbuf));
+
     do {
 	sl = sizeof(sind);
 
-	size = recvfrom(mux->symonsocket, (void *)packet->data + received, 
-			sizeof(struct symonpacket) - received, 
-			0, (struct sockaddr *)&sind, &sl);
+	size = recvfrom(mux->symonsocket[socknr], (void *) packet->data + received,
+			sizeof(struct symonpacket) - received,
+			0, (struct sockaddr *) & sind, &sl);
 	if (size > 0)
-	  received += size;
+	    received += size;
 
 	tries++;
-    } while ((size == -1) && 
-	     (errno == EAGAIN || errno == EINTR) && 
+    } while ((size == -1) &&
+	     (errno == EAGAIN || errno == EINTR) &&
 	     (tries < SYMUX_MAXREADTRIES) &&
 	     (received < sizeof(packet->data)));
 
-    if ((size == -1) && 
-	errno) 
-      warning("recvfrom failed: %.200s", strerror(errno));
+    if ((size == -1) &&
+	errno)
+	warning("recvfrom failed: %.200s", strerror(errno));
+
+    *source = find_source_sockaddr(&mux->sol, (struct sockaddr *) & sind);
 
-    sourceaddr = ntohl((u_int32_t)sind.sin_addr.s_addr);
-    *source = find_source_ip(sourcelist, sourceaddr);
-	    
     if (*source == NULL) {
-	debug("ignored data from %u.%u.%u.%u",
-	      IPAS4BYTES(sourceaddr));
+	getnameinfo((struct sockaddr *) & sind, sind.ss_len, hbuf, sizeof(hbuf),
+		    sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
+	debug("ignored data from %s:%s", hbuf, sbuf);
 	return 0;
-    } else {
+    }
+    else {
 	/* get header stream */
 	mux->offset = getheader(packet->data, &packet->header);
 	/* check crc */
@@ -195,39 +242,52 @@ recvsymonpacket(struct mux *mux, struct sourcelist *sourcelist,
 	packet->header.crc = 0;
 	setheader(packet->data, &packet->header);
 	crc ^= crc32(packet->data, received);
-	if ( crc != 0 ) {
-	    warning("ignored packet with bad crc from %u.%u.%u.%u",
-		    IPAS4BYTES(sourceaddr));
+	if (crc != 0) {
+	    getnameinfo((struct sockaddr *) & sind, sind.ss_len, hbuf, sizeof(hbuf),
+			sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
+	    warning("ignored packet with bad crc from %s:%s",
+		    hbuf, sbuf);
 	    return 0;
 	}
 	/* check packet version */
 	if (packet->header.symon_version != SYMON_PACKET_VER) {
-	    warning("ignored packet with wrong version %d", 
-		    packet->header.symon_version);
+	    getnameinfo((struct sockaddr *) & sind, sind.ss_len, hbuf, sizeof(hbuf),
+			sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
+	    warning("ignored packet with wrong version %d from %s:%s",
+		    packet->header.symon_version, hbuf, sbuf);
 	    return 0;
-	} else {
-	    if (flag_debug) 
-		debug("good data received from %u.%u.%u.%u",
-		      IPAS4BYTES(sourceaddr));
-	    return 1;  /* good packet received */
-	} 
+	}
+	else {
+	    if (flag_debug) {
+		getnameinfo((struct sockaddr *) & sind, sind.ss_len, hbuf, sizeof(hbuf),
+		       sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
+		debug("good data received from %s:%s", hbuf, sbuf);
+	    }
+	    return 1;		/* good packet received */
+	}
     }
 }
 int 
-acceptconnection(int sock)
+accept_connection(int sock, char *peername, int peernamesize)
 {
-    struct sockaddr_in sind;
+    char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
+    struct sockaddr_storage sind;
     socklen_t len;
-    u_int32_t clientaddr;
     int clientsock;
 
-    if ((clientsock = accept(sock, (struct sockaddr *)&sind, &len)) < 0)
-	fatal("Failed to accept an incoming connection. (.200%s)",
+    bzero((void *) hbuf, sizeof(hbuf));
+    bzero((void *) sbuf, sizeof(sbuf));
+
+    if ((clientsock = accept(sock, (struct sockaddr *) & sind, &len)) < 0)
+	fatal("failed to accept an incoming connection. (.200%s)",
 	      strerror(errno));
 
-    clientaddr = ntohl((u_int32_t)sind.sin_addr.s_addr);
-    info("Accepted incoming client connection from %u.%u.%u.%u",
-	 IPAS4BYTES(clientaddr));
+
+    if (getnameinfo((struct sockaddr *) & sind, sind.ss_len, hbuf, sizeof(hbuf),
+		    sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV))
+	snprintf(peername, peernamesize, "<unknown>");
+    else
+	snprintf(peername, peernamesize, "%s:%s", hbuf, sbuf);
 
     return clientsock;
-}   
+}

+ 7 - 11
symon/symux/symuxnet.h

@@ -1,4 +1,4 @@
-/* $Id: symuxnet.h,v 1.6 2002/09/14 15:54:56 dijkstra Exp $ */
+/* $Id: symuxnet.h,v 1.8 2002/11/29 10:45:22 dijkstra Exp $ */
 
 /*
  * Copyright (c) 2001-2002 Willem Dijkstra
@@ -37,14 +37,10 @@
 
 /* prototypes */
 __BEGIN_DECLS
-int  acceptconnection(int);
-int  getsymonsocket(struct mux *);
-int  getclientsocket(struct mux *);
-void waitfortraffic(struct mux *, struct sourcelist *, 
-		    struct source **, struct symonpacket *);
-int  recvsymonpacket(struct mux *, struct sourcelist *, 
-		   struct source **, struct symonpacket *);
-int  check_crc_packet(struct symonpacket *);
+int get_client_socket(struct mux *);
+int get_symon_sockets(struct mux *);
+int accept_connection(int, char *, int);
+int recv_symon_packet(struct mux *, int, struct source **, struct symonpacket *);
+void wait_for_traffic(struct mux *, struct source **, struct symonpacket *);
 __END_DECLS
-#endif /*_SYMUX_SYMUXNET_H*/
-
+#endif				/* _SYMUX_SYMUXNET_H */