
1.Remove 'const' in DELIMITER to fix "Werror=ignored-qualifiers" 2.Replace sprintf with snprintf, and add return value check for snprintf to fix "Werror=format-overflow" 3.Replace strncpy with snprintf to fix "Werror=stringop-truncation" Change-Id: Iecca021fc02df35a472a3f8aa04c9501998e2dba Story: 2007506 Task: 39279 Signed-off-by: Shuicheng Lin <shuicheng.lin@intel.com> Signed-off-by: Dongqi Chen <chen.dq@neusoft.com>
309 lines
9.7 KiB
C
309 lines
9.7 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 ;
|
|
int ret ;
|
|
|
|
memset ( str, 0, sizeof(str) );
|
|
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, sizeof(amon.tx_buf) );
|
|
ret = snprintf( amon.tx_buf, sizeof(amon.tx_buf), "%s %8x %d", str, magic, seq );
|
|
if ( ret >= (int)sizeof(amon.tx_buf) )
|
|
{
|
|
syslog ( LOG_ERR, "amon.tx_buf is truncated\n");
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|