eibstatus.c

eibnetmux - eibnet/ip multiplexer Copyright (C) 2006-2009 Urs Zurbuchen <going_nuts@users.sourceforge.net>

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Demonstrates usage of the EIBnetmux server status function.

It produces a status summary for an EIBnetmux server.

/*
 * eibstatus - eibnetmux server status
 * 
 * eibnetmux - eibnet/ip multiplexer
 * Copyright (C) 2006-2009 Urs Zurbuchen <going_nuts@users.sourceforge.net>
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
 
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <libgen.h>
#include <getopt.h>
#include <errno.h>

#include <eibnetmux/enmx_lib.h>
#include <mylib.h>

/*
 * Global variables
 */
ENMX_HANDLE     sock_con = 0;
unsigned char   conn_state = 0;


/*
 * local function declarations
 */
// static void Shutdown( int arg );
static void Usage( char *progname );

static char *_authlevels[] = {
        "<not supported by this version of eibnetmux>",
        "Deny all",
        "Allow Read",
        "Allow Write",
        "Allow all"
};

static void Usage( char *progname )
{
    fprintf( stderr, "Usage: %s [options] hostname[:port]\n"
                     "where:\n"
                     "  hostname[:port]     defines eibnetmux server with default port of 4390\n"
                     "options:\n"
                     "  -u user             name of user (default: -)\n"
                     "\n", basename( progname ));
}


int main( int argc, char **argv )
{
    sENMX_Status            *state;
    sENMX_StatusEIB         *p_eib;
    sENMX_StatusSocket      *p_client;
    sENMX_StatusEIBD        *p_eibd;
    int                     enmx_version;
    int                     c;
    char                    *user = NULL;
    char                    pwd[255];
    int                     loop;
    char                    *target;

    opterr = 0;
    while( ( c = getopt( argc, argv, "u:" )) != -1 ) {
        switch( c ) {
            case 'u':
                user = strdup( optarg );
                break;
            default:
                fprintf( stderr, "Invalid option: %c\n", c );
                Usage( argv[0] );
                exit( -1 );
        }
    }
    if( optind == argc ) {
        target = NULL;
    } else if( optind + 1 == argc ) {
        target = argv[optind];
    } else {
        Usage( argv[0] );
        exit( -1 );
    }
    
    // catch signals for shutdown
    signal( SIGINT, Shutdown );
    signal( SIGTERM, Shutdown );
    
    // request monitoring connection
    enmx_version = enmx_init();
    sock_con = enmx_open( target, "eibstatus" );
    if( sock_con < 0 ) {
        fprintf( stderr, "Connect to eibnetmux failed: %s\n", enmx_errormessage( sock_con ));
        exit( -2 );
    }
    
    // authenticate
    if( user != NULL ) {
        if( getpassword( pwd ) != 0 ) {
            fprintf( stderr, "Error reading password - cannot continue\n" );
            exit( -6 );
        }
        if( enmx_auth( sock_con, user, pwd ) != 0 ) {
            fprintf( stderr, "Authentication failure\n" );
            exit( -3 );
        }
    }
    fprintf( stderr, "Connection to eibnetmux established\n" );
    
    state = enmx_mgmt_getstatus( sock_con );
    if( state == NULL ) {
        fprintf( stderr, "getstatus returned with error\n" );
        fprintf( stderr, "error code = %d\n", enmx_geterror( sock_con ));
        switch( enmx_geterror( sock_con )) {
            case ENMX_E_COMMUNICATION:
            case ENMX_E_NO_CONNECTION:
            case ENMX_E_WRONG_USAGE:
            case ENMX_E_NO_MEMORY:
                fprintf( stderr, "Error on write: %s\n", enmx_errormessage( sock_con ));
                enmx_close( sock_con );
                exit( -4 );
                break;
            case ENMX_E_INTERNAL:
                fprintf( stderr, "Bad status returned\n" );
                break;
            case ENMX_E_SERVER_ABORTED:
                fprintf( stderr, "EOF reached: %s\n", enmx_errormessage( sock_con ));
                enmx_close( sock_con );
                exit( -4 );
                break;
            case ENMX_E_TIMEOUT:
                fprintf( stderr, "No value received\n" );
                break;
            default:
                fprintf( stderr, enmx_errormessage( enmx_geterror( sock_con )));
                enmx_close( sock_con );
                exit( -4 );
                break;
        }
    } else {
        printf( "eibnetmux server @ %s (v%d)\n", enmx_gethost( sock_con ), state->status_version );
        printf( "Common information (v%d):\n", state->common.status_version );
        printf( "  version............: %s\n", state->common.version );
        printf( "  loglevel...........: %d\n", state->common.loglevel );
        printf( "  uptime.............: %s\n", deltatime( state->common.uptime ));
        printf( "  user/group.........: %d/%d\n", state->common.uid, state->common.gid );
        printf( "  daemon.............: %s\n", (state->common.daemon == 0) ? "no" : "yes" );
        
        printf( "Client information (v%d):\n", state->client.status_version );
        printf( "  %s", state->client.connected == 0 ? "disconnected" : "connected" );
        if( state->client.target_name != NULL ) {
            printf( " to %s (%s:%d)", state->client.target_name, ip_addr( state->client.target_ip ), state->client.target_port );
        }
        if( state->client.source_ip != 0 ) {
            printf( " via %s", ip_addr( state->client.source_ip ));
        }
        if( state->client.loopback == 2 ) {
            printf( " in loopback mode" );
        }
        printf( "\n" );
        printf( "  uptime.............: %s\n", deltatime( state->client.uptime ));
        printf( "  queue length.......: %d\n", state->client.queue_len );
        printf( "  missed heartbeats..: %d\n", state->client.missed_heartbeat );
        printf( "  session in/out.....: %d/%d\n", state->client.session_received, state->client.session_sent );
        printf( "  overall in/out.....: %d/%d\n", state->client.total_received, state->client.total_sent );
        
        printf( "EIBnet/IP server information (v%d):\n", state->server.status_version );
        printf( "  %s on port....: %d\n", state->server.active == 0 ? "stopped" : "running", state->server.port );
        printf( "  in/out.............: %d/%d\n", state->server.received, state->server.sent );
        printf( "  queue length.......: %d\n", state->server.queue_len );
        printf( "  default auth level.: %s\n", _authlevels[ (uint16_t)(state->server.default_level +1)] );
        printf( "  access block level.: %s\n", _authlevels[ (uint16_t)(state->server.access_block +1)] );
        printf( "  clients............: %d / %d\n", state->server.nr_clients, state->server.max_connections );
        loop = 0;
        for( p_eib = state->server.clients; p_eib != NULL; p_eib = p_eib->next ) {
            printf( "    % d: %s:%d via %s\n", (p_eib->conn_id == 0) ? ++loop : p_eib->conn_id, ip_addr( p_eib->ip ), p_eib->port, ip_addr( p_eib->source_ip ));
            printf( "        in/out......: %d/%d\n", p_eib->received, p_eib->sent );
            printf( "        queue length: %d\n", p_eib->queue_len );
        }
        
        printf( "Socketserver information (v%d):\n", state->socketserver.status_version );
        printf( "  TCP services %s on port %d\n", (state->socketserver.active_tcp == 0) ? "stopped" : "running", state->socketserver.port );
        printf( "  Named pipe   %s on %s\n", (state->socketserver.active_unix == 0) ? "stopped" : "running", (state->socketserver.path != NULL) ? state->socketserver.path : "<undefined>" );
        printf( "  in/out.............: %d/%d\n", state->socketserver.received, state->socketserver.sent );
        printf( "  queue length.......: %d\n", state->socketserver.queue_len );
        printf( "  authentication.....: %s\n", (state->socketserver.authentication == 0) ? "not supported" : "supported" );
        printf( "  clients............: %d / %d\n", state->socketserver.nr_clients, state->socketserver.max_connections );
        loop = 0;
        for( p_client = state->socketserver.clients; p_client != NULL; p_client = p_client->next ) {
            if( p_client->name != NULL ) {
                printf( "    % d: %s %s:%d", (p_client->conn_id == 0) ? ++loop : p_client->conn_id, p_client->name, ip_addr( p_client->ip ), p_client->port );
            } else {
                printf( "    % d: %s:%d", (p_client->conn_id == 0) ? ++loop : p_client->conn_id, ip_addr( p_client->ip ), p_client->port );
            }
            if( p_client->user != NULL ) {
                printf( " as %s", p_client->user );
            }
            printf( "\n" );
            printf( "        in/out......: %d/%d\n", p_client->received, p_client->sent );
        }
        
        printf( "EIBD server information (v%d):\n", state->eibd.status_version );
        printf( "  %s on port %d\n", (state->eibd.active == 0) ? "stopped" : "running", state->eibd.port );
        printf( "  in/out.............: %d/%d\n", state->eibd.received, state->eibd.sent );
        printf( "  queue length.......: %d\n", state->eibd.queue_len );
        printf( "  clients............: %d / %d\n", state->eibd.nr_clients, state->eibd.max_connections );
        loop = 0;
        for( p_eibd = state->eibd.clients; p_eibd != NULL; p_eibd = p_eibd->next ) {
            printf( "    % d: %s:%d", (p_eibd->conn_id == 0) ? ++loop : p_eibd->conn_id, ip_addr( p_eibd->ip ), p_eibd->port );
            printf( "\n" );
            printf( "        in/out......: %d/%d\n", p_eibd->received, p_eibd->sent );
        }
    }
    enmx_mgmt_releasestatus( state );
    enmx_close( sock_con );
    
    return( 0 );
}


/*
 * Shutdown
 * 
 * catches SIGINT and SIGTERM and shuts down
 */
/*
RETSIGTYPE Shutdown( int arg )
{
    fprintf( stderr, "Signal received - shutting down\n" );

    // close monitoring connection
    if( conn_state != 0 ) {
        fprintf( stderr, "Disconnecting from eibnetmux\n" );
        enmx_close( sock_con );
    }

    exit( 0 );
}
*/