metal/mtce-common/src/common/pingUtil.cpp
Eric MacDonald 9bf231a286 Fix BMC access loss handling
Recent refactoring of the BMC handler FSM introduced a code change that
prevents the BMC Access alarm from being raised after initial BMC
accessibility was established and is then lost.

This update ensures BMC access alarm management is working properly.

This update also implements ping failure debounce so that a single ping
failure does not trigger full reconnection handling. Instead that now
requires 3 ping failures in a row. This has the effect of adding a minute
to ping failure action handling before the usual 2 minute BMC access failure
alarm is raised. ping failure logging is reduced/improved.

Test Plan: for both hwmond and mtcAgent

PASS: Verify BMC access alarm due to bad provisioning (un, pw, ip, type)
PASS: Verify BMC ping failure debounce handling, recovery and logging
PASS: Verify BMC ping persistent failure handling
PASS: Verify BMC ping periodic miss handling
PASS: Verify BMC ping and access failure recovery timing
PASS: Verify BMC ping failure and recovery handling over BMC link pull/plug
PASS: Verify BMC sensor monitoring stops/resumes over ping failure/recovery

Regression:

PASS: Verify IPv6 System Install using provisioned BMCs (wp8-12)
PASS: Verify BMC power-off request handling with BMC ping failing & recovering
PASS: Verify BMC power-on request handling with BMC ping failing & recovering
PASS: Verify BMC reset request handling with BMC ping failing & recovering
PASS: Verify BMC sensor group read failure handling & recovery
PASS: Verify sensor monitoring after ping failure handling & recovery

Change-Id: I74870816930ef6cdb11f987424ffed300ff8affe
Closes-Bug: 1858110
Signed-off-by: Eric MacDonald <eric.macdonald@windriver.com>
2020-01-03 09:34:37 -05:00

860 lines
29 KiB
C++

/*
* Copyright (c) 2015-2017,2020 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
/**
* @file
* Wind River Titanium Cloud Maintenance Ping Utility Implementation
*/
#include "daemon_common.h" /* for ... MEMSET_ZERO */
#include "nodeBase.h"
#include "nodeUtil.h"
#include "hostUtil.h" /* for ... hostUtil_is_valid_ip_addr */
#include "pingUtil.h" /* for ... this module header */
#ifdef __AREA__
#undef __AREA__
#endif
#define __AREA__ "acc"
typedef struct
{
struct icmphdr hdr;
char msg[PING_MESSAGE_LEN];
} ping4_tx_message_type ;
typedef struct
{
struct iphdr ip_hdr ;
struct icmphdr hdr ;
char msg[PING_MESSAGE_LEN];
} ping4_rx_message_type ;
typedef struct
{
// struct ip6_hdr iphdr;
struct icmp6_hdr icmphdr;
char msg[PING_MESSAGE_LEN] ; // MSG_HEADER_SIZE];
} ping6_tx_message_type ;
typedef struct
{
// struct ip6_hdr ip_hdr;
struct icmp6_hdr hdr;
char msg[PING_MESSAGE_LEN];
} ping6_rx_message_type ;
/*******************************************************************************
*
* Name : pingUtil_init
*
* Purpose : Setup a ping socket
*
* Assumptions: caller initializes and installs timer handler outside of init
* before the monitor is called.
*
* Returns : PASS : non-blocking ping socket towards specified ip address setup ok
* FAIL__xxx : init failed
*
******************************************************************************/
int pingUtil_init ( string hostname, ping_info_type & ping_info, const char * ip_address )
{
int rc = PASS ;
if ( hostUtil_is_valid_ip_addr ( ip_address ) == false )
{
wlog ("%s refusing to setup ping socket for invalid IP address\n", hostname.c_str());
return (FAIL_NULL_POINTER);
}
string identity_string = program_invocation_short_name ;
identity_string.append ("_");
identity_string.append(ip_address) ;
ping_info.identity =
checksum ((void*)identity_string.data(), identity_string.length());
dlog1 ("%s ping identity string: %s (0x%04x)\n",
hostname.c_str(),
identity_string.c_str(),
ping_info.identity);
/* init the ping_info struct */
ping_info.hostname = hostname ;
ping_info.ip = ip_address ;
ping_info.sequence = getpid() ;
ping_info.recv_retries = 0 ;
ping_info.send_retries = 0 ;
ping_info.fail_debounce = 0 ;
ping_info.requested= false ;
ping_info.received = false ;
ping_info.recv_flush_highwater=2;
/* added for ping monitor */
ping_info.ok = false ;
ping_info.monitoring = false ;
ping_info.stage = PINGUTIL_MONITOR_STAGE__OPEN ;
ping_info.sock = new msgClassTx(ip_address, 0, IPPROTO_RAW, NULL, true);
/* Validate the socket setup */
if ( ping_info.sock == NULL )
{
rc = FAIL_SOCKET_CREATE ;
elog ("%s failed to create ping socket ; null socket\n",
ping_info.hostname.c_str());
}
else
{
rc = ping_info.sock->return_status;
if ( rc != PASS )
{
elog ("%s failed to create ping socket ; error status:%d\n",
ping_info.hostname.c_str(), rc );
rc = FAIL_SOCKET_CREATE ;
delete (ping_info.sock );
return rc;
}
else
{
if ( ( rc = ping_info.sock->setSocketNonBlocking () ) == PASS )
{
MEMSET_ZERO(ping_info.message);
switch ( ping_info.sock->get_dst_addr()->getIPVersion() )
{
case AF_INET:
{
ping_info.ipv6_mode = false ;
snprintf (&ping_info.message[0], PING_MESSAGE_LEN,
"%s ipv4 ping message from %s daemon",
ping_info.hostname.data(),
program_invocation_short_name);
break ;
}
case AF_INET6:
{
ping_info.ipv6_mode = true ;
snprintf (&ping_info.message[0], PING_MESSAGE_LEN,
"%s ipv6 ping message from %s daemon",
ping_info.hostname.data(),
program_invocation_short_name);
break ;
}
default:
{
elog ("Unsupported IP protocol version\n");
return (FAIL);
}
}
dlog3 ("%s (fd:%d)\n",
ping_info.message,
ping_info.sock->getFD());
}
else
{
elog ("%s failed to set ping socket to non-blocking:%d\n",
ping_info.hostname.c_str(), rc );
}
}
}
return rc ;
}
int pingUtil_recv_flush ( ping_info_type & ping_info, bool loud );
/*******************************************************************************
*
* Name : pingUtil_send
*
* Purpose : Send an ICMP ECHO ping request to the specified socket
*
* Returns : PASS : send was ok
* FAIL : send failed
*
******************************************************************************/
int pingUtil_send ( ping_info_type & ping_info )
{
ping4_tx_message_type ping4_tx;
ping6_tx_message_type ping6_tx;
int bytes = 0 ;
pingUtil_recv_flush ( ping_info, false );
if (( ping_info.sock == NULL ) || ( ping_info.sock->return_status != PASS ))
{
wlog ("%s refusing to send ping on %s socket\n",
ping_info.hostname.c_str(),
ping_info.sock ? "faulty" : "null" );
return (FAIL_NULL_POINTER);
}
ping_info.sequence++ ;
if ( ping_info.ipv6_mode == false )
{
MEMSET_ZERO (ping4_tx);
ping4_tx.hdr.type = ICMP_ECHO;
ping4_tx.hdr.un.echo.id = htons(ping_info.identity) ;
ping4_tx.hdr.un.echo.sequence = htons(ping_info.sequence) ;
snprintf ( &ping4_tx.msg[0], PING_MESSAGE_LEN, "%s", ping_info.message );
/* checksum should not be converted to htons
* - will get (wrong icmp cksum ) */
ping4_tx.hdr.checksum = checksum(&ping4_tx, sizeof(ping4_tx));
dlog3 ("%s ping4 checksum: %04x\n",
ping_info.hostname.c_str(),
ping4_tx.hdr.checksum );
bytes = ping_info.sock->write((const char*)&ping4_tx, sizeof(ping4_tx));
}
else
{
MEMSET_ZERO (ping6_tx);
ping6_tx.icmphdr.icmp6_type = ICMP6_ECHO_REQUEST;
ping6_tx.icmphdr.icmp6_code = 0;
ping6_tx.icmphdr.icmp6_id = htons(ping_info.identity) ;
ping6_tx.icmphdr.icmp6_seq = htons(ping_info.sequence) ;
snprintf ( &ping6_tx.msg[0], PING_MESSAGE_LEN, "%s", ping_info.message );
ping6_tx.icmphdr.icmp6_cksum = htons(checksum(&ping6_tx, sizeof(ping6_tx)));
dlog3 ("%s ping6 checksum: %04x\n",
ping_info.hostname.c_str(),
ping6_tx.icmphdr.icmp6_cksum );
bytes = ping_info.sock->write( (const char*)&ping6_tx, sizeof(ping6_tx_message_type));
}
if ( bytes <= 0 )
{
wlog ("%s ping %s send failed (rc:%d) (%d:%m)\n", ping_info.hostname.c_str(), ping_info.ip.c_str(), bytes, errno );
return FAIL ;
}
if (( ping_info.monitoring == false ) &&
( ping_info.send_retries >= PING_MAX_SEND_RETRIES ))
{
ilog ("%s ping send %s ok ; identity:%04x sequence:%04x (try %d of %d)\n",
ping_info.hostname.c_str(),
ping_info.ip.c_str(),
ping_info.identity,
ping_info.sequence,
ping_info.send_retries,
PING_MAX_SEND_RETRIES);
}
else
{
mlog ("%s ping send %s ok ; identity:%04x sequence:%04x (try %d)\n",
ping_info.hostname.c_str(),
ping_info.ip.c_str(),
ping_info.identity,
ping_info.sequence,
ping_info.send_retries);
}
ping_info.received = false ;
ping_info.requested = true ;
return PASS ;
}
/*******************************************************************************
*
* Name : pingUtil_recv_flush
*
* Purpose : Empty the ping receiver in preparation for a fresh ping request.
*
* Returns : PASS : empty
* RETRY: not empty
*
******************************************************************************/
int pingUtil_recv_flush ( ping_info_type & ping_info, bool loud )
{
int empty_count = 0 ;
int flush_count = 0 ;
bool exit_pass = false ;
if ( ping_info.sock == NULL )
return (FAIL_NULL_POINTER);
for ( int i = 0 , bytes = 0 ; i < PING_MAX_FLUSH_RETRIES ; i++ )
{
if ( ping_info.ipv6_mode == true )
{
ping6_rx_message_type ping6_rx ;
MEMSET_ZERO(ping6_rx);
bytes = ping_info.sock->readReply( (char *)&ping6_rx, sizeof(ping6_rx_message_type));
if ( bytes > 0 )
{
unsigned short id = htons(ping6_rx.hdr.icmp6_id) ;
unsigned short seq = htons(ping6_rx.hdr.icmp6_seq) ;
flush_count++ ;
empty_count = 0 ;
if ( id == ping_info.identity )
{
wlog ("%s flushed out-of-sequence ping response for my identity:%04x ; sequence:%04x (%d)\n",
ping_info.hostname.c_str(), ping_info.identity, seq, flush_count );
}
else if ( loud == true )
{
wlog ("%s flushed %d byte message identity:%04x sequence:%04x\n",
ping_info.hostname.c_str(), bytes, id , seq );
}
}
}
else
{
ping4_rx_message_type ping4_rx ;
MEMSET_ZERO(ping4_rx);
bytes = ping_info.sock->readReply( (char *)&ping4_rx, sizeof(ping4_rx_message_type));
if (( bytes > 0 ) && ( ping4_rx.hdr.un.echo.id != 0 ))
{
flush_count++ ;
empty_count = 0 ;
unsigned short id = htons(ping4_rx.hdr.un.echo.id);
unsigned short seq = htons(ping4_rx.hdr.un.echo.sequence);
if ( id == ping_info.identity )
{
wlog ("%s flushed out-of-sequence ping response for my identity:%04x ; sequence:%04x (%d)\n",
ping_info.hostname.c_str(),
ping_info.identity,
seq,
flush_count );
}
else if ( loud == true )
{
wlog ("%s flushed %d byte message identity:%04x sequence:%04x\n",
ping_info.hostname.c_str(), bytes, id, seq );
}
}
}
if ( bytes <= 0 )
{
if ( empty_count++ == 3 )
{
exit_pass = true ;
break ;
}
}
}
if ( flush_count > ping_info.recv_flush_highwater )
{
ping_info.recv_flush_highwater = flush_count ;
dlog ("%s ping flush peak at %d\n",
ping_info.hostname.c_str(),
ping_info.recv_flush_highwater );
}
else if ( flush_count )
{
dlog2 ("%s ping flushed %d messages\n",
ping_info.hostname.c_str(), flush_count );
}
if ( exit_pass == true )
return (PASS);
return (RETRY);
}
/*******************************************************************************
*
* Name : pingUtil_recv
*
* Purpose : Receive an ICMP ping response and compare the suggested sequence
* and identifier numbers.
*
* Returns : PASS : got the response with the correct id and seq codes
* RETRY: got response but with one or mode bad codes
* FAIL : got no ping reply
*
******************************************************************************/
/* handle a reasonable ping flood without failing local pings */
#define MAX_PING_FLUSH (512)
int pingUtil_recv ( ping_info_type & ping_info,
bool loud ) /* print log if no data received */
{
int rc = FAIL ;
int bytes = 0 ;
if (( ping_info.requested == true ) && ( ping_info.received == true ))
{
ping_info.requested = false ;
return (PASS);
}
if ( ping_info.sock == NULL )
return (FAIL_NULL_POINTER);
for ( int i = 0 ; i < MAX_PING_FLUSH ; i++ )
{
if ( ping_info.ipv6_mode == true )
{
ping6_rx_message_type ping6_rx ;
MEMSET_ZERO(ping6_rx);
bytes = ping_info.sock->readReply( (char *)&ping6_rx, sizeof(ping6_rx_message_type));
if ( bytes > 0 )
{
unsigned short id = htons(ping6_rx.hdr.icmp6_id);
unsigned short seq = htons(ping6_rx.hdr.icmp6_seq);
if ( loud == true )
{
ilog ("%s %s search ; bytes:%d ; identity:%04x (got %04x) sequence:%04x (got %04x)\n",
ping_info.hostname.c_str(),
ping_info.ip.c_str(), bytes,
ping_info.identity, ping6_rx.hdr.icmp6_id,
ping_info.sequence, ping6_rx.hdr.icmp6_seq );
}
if (( ping6_rx.hdr.icmp6_type == ICMP6_ECHO_REPLY ) &&
( id == ping_info.identity ) &&
( seq == ping_info.sequence ))
{
/* Don't print this log once we have established ping and
* are in monitoring mode. */
if ( ping_info.monitoring == false )
{
/* ... only want the log when we ar first connecting */
ilog ("%s ping recv %s ok ; identity:%04x sequence:%04x (try %d) (%d)\n",
ping_info.hostname.c_str(),
ping_info.ip.c_str(),
ping_info.identity,
ping_info.sequence,
ping_info.recv_retries+1,
i);
}
else
{
/* ... only want the log when we ar first connecting */
mlog ("%s ping recv %s ok ; identity:%04x sequence:%04x (try %d) (%d)\n",
ping_info.hostname.c_str(),
ping_info.ip.c_str(),
ping_info.identity,
ping_info.sequence,
ping_info.recv_retries+1,
i);
}
ping_info.requested = false ;
ping_info.received = true ;
rc = PASS ;
break ;
}
else if ( ping6_rx.hdr.icmp6_id == ping_info.identity )
{
ilog ("%s received-out-of-sequence ping response for this identity:%04x ; sequence:%04x\n",
ping_info.hostname.c_str(), id, seq);
rc = RETRY ;
}
else
{
; /* identity is 0 or does not match this host */
}
}
else
{
/* no data */
rc = RETRY ;
break ;
}
}
else
{
ping4_rx_message_type ping4_rx ;
MEMSET_ZERO(ping4_rx);
bytes = ping_info.sock->readReply ( (char*)&ping4_rx, sizeof(ping4_rx)) ;
if ( bytes > 0 )
{
unsigned short id = htons(ping4_rx.hdr.un.echo.id);
unsigned short seq = htons(ping4_rx.hdr.un.echo.sequence);
// dump_memory ( &ping4_rx, 16, sizeof(ping4_rx_message_type));
if ( loud == true )
{
ilog ("%s %s search ; bytes:%d ; identity:%04x (got %04x) sequence:%04x (got %04x)\n",
ping_info.hostname.c_str(),
ping_info.ip.c_str(), bytes,
ping_info.identity, id,
ping_info.sequence, seq );
}
if (( ping4_rx.hdr.type == ICMP_ECHOREPLY ) &&
( id == ping_info.identity ) &&
( seq == ping_info.sequence ))
{
/* Don't print this log once we have established ping and
* are in monitoring mode. */
if ( ping_info.monitoring == false )
{
/* ... only want the log when we are first connecting */
if ( ping_info.recv_retries )
{
ilog ("%s ping %s ok ; (try %d)",
ping_info.hostname.c_str(),
ping_info.ip.c_str(),
ping_info.recv_retries+1);
}
else
{
ilog ("%s ping %s ok",
ping_info.hostname.c_str(),
ping_info.ip.c_str());
}
}
else
{
/* ... only want the log when we ar first connecting */
mlog ("%s ping recv %s ok ; identity:%04x sequence:%04x (try %d) (%d)\n",
ping_info.hostname.c_str(),
ping_info.ip.c_str(),
ping_info.identity,
ping_info.sequence,
ping_info.recv_retries+1,
i);
}
ping_info.requested = false ;
ping_info.received = true ;
rc = PASS ;
break ;
}
else if ( id == ping_info.identity )
{
ilog ("%s received-out-of-sequence ping response for this identity:%04x ; sequence:%04x\n",
ping_info.hostname.c_str(), id, seq );
rc = RETRY ;
}
else
{
; /* identity is 0 or does not match this host */
}
}
else
{
/* no data */
rc = RETRY ;
break ;
}
}
}
return rc ;
}
/*******************************************************************************
*
* Name : pingUtil_fini
*
* Purpose : Close an ping socket
*
*******************************************************************************/
void pingUtil_fini ( ping_info_type & ping_info )
{
if ( ping_info.sock )
{
dlog1 ("%s ping socket close ok (fd:%d)\n",
ping_info.hostname.c_str(),
ping_info.sock->getFD());
delete ( ping_info.sock );
ping_info.sock = NULL ;
}
ping_info.recv_retries = 0;
ping_info.send_retries = 0;
ping_info.fail_debounce = 0;
ping_info.sequence = 0;
ping_info.identity = 0;
/* Support for ping monitor */
mtcTimer_reset ( ping_info.timer );
ping_info.stage = PINGUTIL_MONITOR_STAGE__IDLE ;
}
void pingUtil_restart ( ping_info_type & ping_info )
{
dlog ("%s ping monitor restart", ping_info.hostname.c_str());
pingUtil_fini (ping_info);
pingUtil_init (ping_info.hostname, ping_info, ping_info.ip.data());
mtcTimer_reset ( ping_info.timer );
mtcTimer_start ( ping_info.timer, ping_info.timer_handler, 1 );
ping_info.stage = PINGUTIL_MONITOR_STAGE__WAIT;
}
/********************************************************************************
*
* Name : pingUtil_acc_monitor
*
* Purpose : FSM used to monitor ping access to specific ip address
*
*******************************************************************************/
int pingUtil_acc_monitor ( ping_info_type & ping_info )
{
switch ( ping_info.stage )
{
/* do nothing stage */
case PINGUTIL_MONITOR_STAGE__IDLE:
{
break ;
}
case PINGUTIL_MONITOR_STAGE__WAIT:
{
if ( mtcTimer_expired ( ping_info.timer ) )
{
ping_info.stage = PINGUTIL_MONITOR_STAGE__SEND ;
}
/* Don't let the buffer fill up with pings ;
* keep the socket empty till we want to ping */
pingUtil_recv_flush ( ping_info , false );
break ;
}
case PINGUTIL_MONITOR_STAGE__OPEN:
{
if ( pingUtil_init ( ping_info.hostname,
ping_info,
ping_info.ip.data()) != PASS )
{
ping_info.stage = PINGUTIL_MONITOR_STAGE__FAIL ;
}
else
{
ping_info.stage = PINGUTIL_MONITOR_STAGE__SEND ;
}
break ;
}
case PINGUTIL_MONITOR_STAGE__SEND:
{
if ( ping_info.sock == NULL )
{
if (( ping_info.ip.empty()) || !ping_info.ip.compare(NONE))
{
elog ("%s no address to ping\n", ping_info.hostname.c_str());
ping_info.stage = PINGUTIL_MONITOR_STAGE__FAIL ;
break ;
}
int rc = pingUtil_init ( ping_info.hostname,
ping_info,
ping_info.ip.data());
if ( rc )
{
elog ("%s failed to setup bmc ping socket to '%s'\n",
ping_info.hostname.c_str(),
ping_info.ip.c_str());
ping_info.stage = PINGUTIL_MONITOR_STAGE__FAIL ;
break ;
}
}
if ( ++ping_info.send_retries > PING_MAX_SEND_RETRIES )
{
dlog ("%s ping %s failed ; max send retries\n",
ping_info.hostname.c_str(),
ping_info.ip.c_str());
ping_info.stage = PINGUTIL_MONITOR_STAGE__FAIL ;
}
else if ( pingUtil_send ( ping_info ) )
{
wlog ("%s ping %s send failed\n",
ping_info.hostname.c_str(),
ping_info.ip.c_str());
ping_info.stage = PINGUTIL_MONITOR_STAGE__FAIL ;
}
else
{
if ( ping_info.timer_handler == NULL )
{
elog ("%s no timer handler installed\n", ping_info.hostname.c_str());
ping_info.stage = PINGUTIL_MONITOR_STAGE__FAIL ;
}
else
{
if ( ping_info.timer.tid )
{
ilog ("%s unexpected active timer\n", ping_info.hostname.c_str());
mtcTimer_reset ( ping_info.timer );
}
mtcTimer_start_msec ( ping_info.timer, ping_info.timer_handler, PING_WAIT_TIMER_MSEC );
/* send was ok so clear its retry counter */
ping_info.send_retries = 0 ;
ping_info.stage = PINGUTIL_MONITOR_STAGE__RECV ;
}
}
break ;
}
case PINGUTIL_MONITOR_STAGE__RECV:
{
if ( mtcTimer_expired ( ping_info.timer ))
{
bool loud = false ;
if ( daemon_get_cfg_ptr()->debug_bmgmt )
loud = true ;
if ( pingUtil_recv ( ping_info , loud ) )
{
if ( ++ping_info.recv_retries > (PING_MAX_RECV_RETRIES) )
{
ping_info.recv_retries = 0;
dlog ("%s ping %s failed ; max recv retries\n",
ping_info.hostname.c_str(),
ping_info.ip.c_str());
ping_info.stage = PINGUTIL_MONITOR_STAGE__FAIL ;
}
else
{
blog1 ("%s retrying ping\n", ping_info.hostname.c_str());
mtcTimer_start_msec ( ping_info.timer, ping_info.timer_handler, PING_RETRY_DELAY_MSECS );
}
}
else
{
int interval = PING_MONITOR_INTERVAL ;
ping_info.ok = true ;
ping_info.monitoring = true ;
dlog ("%s ping %s ok (send:%d:recv:%d) (%d)\n",
ping_info.hostname.c_str(),
ping_info.ip.c_str(),
ping_info.send_retries,
ping_info.recv_retries+1,
ping_info.ok );
ping_info.send_retries = 0 ;
ping_info.recv_retries = 0 ;
ping_info.fail_debounce = 0 ;
mtcTimer_start ( ping_info.timer, ping_info.timer_handler, interval );
ping_info.stage = PINGUTIL_MONITOR_STAGE__WAIT ;
}
}
break ;
}
case PINGUTIL_MONITOR_STAGE__CLOSE:
{
pingUtil_fini (ping_info);
break ;
}
case PINGUTIL_MONITOR_STAGE__FAIL:
{
// Assume socket reinit unless thresholding */
bool reinit = true ;
if ( ping_info.ok == true )
{
if ( ++ping_info.fail_debounce < PING_FAIL_DEBOUNCE_THLD )
{
reinit = false ;
wlog("%s ping %s miss (%d of %d)",
ping_info.hostname.c_str(),
ping_info.ip.c_str(),
ping_info.fail_debounce,
PING_FAIL_DEBOUNCE_THLD );
}
}
if ( reinit == true )
{
elog("%s ping %s fail", ping_info.hostname.c_str(),
ping_info.ip.c_str());
pingUtil_fini (ping_info);
pingUtil_init (ping_info.hostname, ping_info, ping_info.ip.data());
}
mtcTimer_reset ( ping_info.timer );
mtcTimer_start ( ping_info.timer, ping_info.timer_handler, PING_FAIL_RETRY_DELAY );
ping_info.stage = PINGUTIL_MONITOR_STAGE__WAIT;
break ;
}
default:
{
slog ("%s default case (%d)\n", ping_info.hostname.c_str(), ping_info.stage );
/* Default to check the connection.
* Failure case is handled there */
mtcTimer_reset ( ping_info.timer );
ping_info.stage = PINGUTIL_MONITOR_STAGE__FAIL ;
}
}
return(PASS);
}
#ifdef WANT_MAIN
/*--------------------------------------------------------------------*/
/*--- main - look up host and start ping processes. ---*/
/*--------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
int rc ;
int ping_socket = 0;
int sequence = 1 ;
struct sockaddr_in addr_ping ;
if ( argc > 1 )
{
int identity = getpid() ;
printf ( "\npinging %s\n", argv[1]);
if ( ( rc = pingUtil_init ( argv[1], ping_socket , addr_ping )) == 0 )
{
pingUtil_recv ( ping_socket, identity, sequence, false );
if ( ( rc = pingUtil_send ( ping_socket, &addr_ping, identity, sequence )) == 0 )
{
for ( int loop=0;loop < 10; loop++)
{
usleep(300000);
if ( ( rc = pingUtil_recv ( ping_socket, identity, sequence, true ) ) == 0 )
{
printf("Ping OK.\n");
return 0;
}
else
{
printf ("receive failed (%d)\n", rc );
}
}
printf("Ping FAILED !!\n");
}
else
{
printf ("ping send Failed (%d)\n", rc );
}
}
else
{
printf ("ping init failed (%d)\n", rc );
}
}
pingUtil_close ( ping_socket );
return 0;
}
#endif