Files
metal/mtce/src/public/amon.c
haochuan 85cd4ebf2e Fix out of band issue. In some case array or string is possible to be
illegal accessed. Fix with add boundry checking.

Verified with deployed system, check with system host-list command to
ensure get_adminAction_str/get_adminState_str/get_operState_str in
nodeClass correct,daemon_init in rmon with no error message, active
monitor is corect for hbsClient and pmon is correct in hbsClient.log
and pmon.log

Closes-Bug: 1795110

Change-Id: Iff81d93702cfa5636c3d8c9567363ff9601be5f6
Signed-off-by: Martin, Chen <haochuan.z.chen@intel.com>
2018-11-02 09:36:13 +08:00

304 lines
9.5 KiB
C

/*
* Copyright (c) 2013, 2016 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
/**
* @file
* Wind River Active (Process) Monitoring Implementation.
* See amon.h for API.
*
**/
#include "amon.h"
#include <stdarg.h>
/* Pass code */
#ifndef PASS
#define PASS (0)
#endif
/* Fail Code */
#ifndef FAIL
#define FAIL (1)
#endif
/* Retry Code */
#ifndef RETRY
#define RETRY (2)
#endif
/* maximum string and socket endpoint path length */
#define AMON_MAX_LEN (100)
/* initialization signature to gate functional
* api calls made prior to initialization */
#define INIT_SIG (0xdeafdead)
#define TXPORT 2200
/** Control Structure */
typedef struct
{
unsigned int init ; /**< Init signature */
int rx_sock ; /**< inet pulse request rx socket */
int rx_port ; /**< inet pulse request rx port number */
struct sockaddr_in rx_addr ; /**< inet pulse request rx attributes */
char rx_buf[AMON_MAX_LEN] ; /**< pulse request message */
int tx_sock ; /**< inet pulse response tx socket */
int tx_port ; /**< inet pulse response tx port number */
struct sockaddr_in tx_addr ; /**< inet pulse response tx attributes */
char tx_buf[AMON_MAX_LEN] ; /**< pulse response message */
char name[AMON_MAX_LEN] ; /**< name of process using this instance */
bool debug_mode ; /**< debug mode if true */
int fit_code ; /**< fit code MAGIC, SEQ, PROCESS */
} active_mon_socket_type ;
/* Instance Control Structure - Per Process Private Data */
static active_mon_socket_type amon ;
/* open unix domain socket */
int active_monitor_initialize ( const char * process_name_ptr, int port )
{
struct stat p ;
int val = 1 ;
memset ( &amon, 0, sizeof(amon));
memset ( &p, 0 , sizeof(struct stat));
syslog ( LOG_INFO , "%s is actively Monitored over lo:%d:%x\n", process_name_ptr, port, port );
sprintf ( amon.name, "/var/run/%s.debug", process_name_ptr );
stat ( amon.name, &p ) ;
if ((p.st_ino != 0 ) && (p.st_dev != 0))
{
amon.debug_mode = true ;
syslog ( LOG_INFO, "Enabling Active Monitor Debug Mode\n");
if ( p.st_size )
{
FILE * filename = fopen ( amon.name, "rb" ) ;
if ( filename != NULL )
{
memset ( &amon.name, 0, AMON_MAX_LEN);
if ( fgets ( amon.name, 20, filename ) != NULL )
{
if ( !strncmp ( amon.name, FIT_MAGIC_STRING, strlen (FIT_MAGIC_STRING)))
{
amon.fit_code = FIT_MAGIC ;
syslog ( LOG_INFO, "Enabling FIT on 'magic calculation'\n");
}
else if ( !strncmp ( amon.name, FIT_SEQUENCE_STRING, strlen(FIT_SEQUENCE_STRING)))
{
amon.fit_code = FIT_SEQ ;
syslog ( LOG_INFO, "Enabling FIT on 'sequence number'\n");
}
else if ( !strncmp ( amon.name, FIT_PROCESS_STRING, strlen(FIT_PROCESS_STRING)))
{
amon.fit_code = FIT_PROCESS ;
syslog ( LOG_INFO, "Enabling FIT on 'process name'\n");
}
else
{
syslog ( LOG_INFO, "Unsupported FIT string (%s)\n", amon.name );
}
}
fclose (filename);
}
else
{
syslog ( LOG_INFO, "Failed to open %s\n", amon.name);
}
}
}
/* Init the control struct - includes all members */
memset ( amon.name, 0, AMON_MAX_LEN);
if ( process_name_ptr )
{
memcpy ( amon.name, process_name_ptr, strlen (process_name_ptr)) ;
}
else
{
syslog ( LOG_INFO, "active_monitor_initialize called with null process name");
return (-ESRCH);
}
/*******************************************************/
/* Create and Setup Inet Receive Socket */
/*******************************************************/
amon.rx_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if ( 0 >= amon.rx_sock )
return (-errno);
if ( setsockopt ( amon.rx_sock , SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int)) == -1 )
{
syslog ( LOG_INFO, "%s failed to set socket as re-useable (%d:%s)\n",
process_name_ptr, errno, strerror(errno));
}
/* Setup with localhost ip */
memset(&amon.rx_addr, 0, sizeof(struct sockaddr_in));
amon.rx_addr.sin_family = AF_INET ;
amon.rx_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
amon.rx_addr.sin_port = htons(port) ;
amon.rx_port = port ;
/* bind socket to the receive addr */
if ( bind ( amon.rx_sock, (const struct sockaddr *)&amon.rx_addr, sizeof(struct sockaddr_in)) == -1 )
{
syslog ( LOG_ERR, "failed to bind to rx socket with port %d\n", port );
close (amon.rx_sock);
amon.rx_sock = 0 ;
return (-errno);
}
/*******************************************************/
/* Create and Setup Inet Transmit Socket */
/*******************************************************/
amon.tx_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if ( 0 >= amon.tx_sock )
return (-errno);
/* Setup with localhost ip */
memset(&amon.tx_addr, 0, sizeof(struct sockaddr_in));
amon.tx_addr.sin_family = AF_INET ;
amon.tx_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
amon.tx_addr.sin_port = htons(TXPORT) ;
amon.tx_port = TXPORT ;
/*******************************************************************/
/* Set init sig */
amon.init = INIT_SIG ;
/* Return the socket descriptor */
return (amon.rx_sock);
}
/* */
int active_monitor_get_sel_obj ( void )
{
if (( amon.init != INIT_SIG ) || ( amon.rx_sock <= 0 ))
{
syslog (LOG_WARNING , "'%s' called with invalid init (sock:%d)\n",
__FUNCTION__, amon.rx_sock);
}
return (amon.rx_sock);
}
/* Receive pulse request */
int active_monitor_dispatch ( void )
{
int msg_cnt = 0 ;
int rc = RETRY ;
socklen_t len = sizeof(struct sockaddr_un);
if ( amon.init != INIT_SIG )
{
syslog (LOG_WARNING , "'%s' called with invalid init\n", __FUNCTION__ );
return (-EPERM);
}
do
{
memset ( amon.rx_buf, 0 , AMON_MAX_LEN );
rc = recvfrom ( amon.rx_sock, amon.rx_buf, AMON_MAX_LEN-1, 0,
(struct sockaddr *)&amon.rx_addr, &len);
if ( rc == -1 )
{
if (( errno != EINTR ) && ( errno != EAGAIN ))
{
syslog ( LOG_WARNING, "amon:%s 'recvfrom' %s.%d failed (%d:%s)\n",
__FUNCTION__, inet_ntoa(amon.tx_addr.sin_addr), amon.rx_port,
errno, strerror(errno));
rc = -errno ;
}
else
{
rc = -EAGAIN ;
}
}
/* Otherwise we got a message */
else
{
/* Small Song and Dance
*
* Invert magic number and maintain the sequence number
*
**/
char str[AMON_MAX_LEN] ;
unsigned int magic = 0 ;
int seq ;
memset (str, 0, AMON_MAX_LEN );
sscanf ( amon.rx_buf, "%s %8x %d", str, &magic, &seq );
/* Fault Insertion Controls */
if ( amon.fit_code == FIT_PROCESS )
{
str[0] = 'x' ;
str[1] = 'x' ;
}
if ( amon.fit_code == FIT_SEQ )
{
seq-- ;
}
if ( amon.fit_code != FIT_MAGIC )
{
magic = magic ^ -1 ;
}
memset ( amon.tx_buf, 0 , AMON_MAX_LEN );
sprintf( amon.tx_buf, "%s %8x %d%c", str, magic, seq, '\0' );
if ( strcmp ( str, amon.name ) )
{
syslog ( LOG_ERR, "recv message for wrong process: %s:%s (%d)\n", str, amon.name, seq );
}
else
{
if ( amon.debug_mode )
{
syslog ( LOG_INFO, "recv: %s (%d)\n", amon.rx_buf, seq );
syslog ( LOG_INFO, "send: %s (%d)\n", amon.tx_buf, seq );
}
rc = sendto ( amon.tx_sock, &amon.tx_buf[0], strlen(amon.tx_buf), 0,
(struct sockaddr *) &amon.tx_addr, sizeof(struct sockaddr_in));
if ( rc == -1 )
{
syslog ( LOG_WARNING, "amon:%s 'sendto' %s.%d failed (%d:%s)\n",
__FUNCTION__, inet_ntoa(amon.tx_addr.sin_addr), TXPORT, errno, strerror(errno));
syslog ( LOG_WARNING, "amon:%s:%s -> %s\n",
__FUNCTION__, amon.rx_buf, amon.tx_buf );
rc = -errno ;
}
else
{
rc = PASS ;
}
}
}
} while (( rc == RETRY ) && ( msg_cnt < 5 )) ;
return (rc);
}
void active_monitor_finalize ( void )
{
if ( amon.tx_sock )
{
close (amon.tx_sock);
}
if ( amon.rx_sock )
{
close (amon.rx_sock);
}
}