Adding support IPv6 to the fm-trap-subagent
Now the server that runs in the fm-trap-subagent is able to recieve messages when it runs in a StarlingX with IPv6 environment. This server is responsible to receive the alarm metada and generate the traps accordingly to the configuration in the master agent. Story: 2008132 Task: 41774 Signed-off-by: Pablo Bovina <pablo.bovina@windriver.com> Change-Id: I89b1d8e7c97d315637b12bcfea0269f2fcf8d452
This commit is contained in:
parent
f15426c720
commit
5aca0dd166
@ -16,7 +16,8 @@ STRICT_FLAGS = -Wall -Wstrict-prototypes
|
|||||||
CFLAGS=-I. $(NETSNMPCFLAGS) $(STRICT_FLAGS) -fPIC
|
CFLAGS=-I. $(NETSNMPCFLAGS) $(STRICT_FLAGS) -fPIC
|
||||||
|
|
||||||
SRCS = $(SOURCE)/$(PREFIX)Trap.c \
|
SRCS = $(SOURCE)/$(PREFIX)Trap.c \
|
||||||
$(SOURCE)/$(PREFIX)Subagent.c
|
$(SOURCE)/$(PREFIX)Subagent.c \
|
||||||
|
$(SOURCE)/$(PREFIX)Server.c
|
||||||
|
|
||||||
OBJS = $(SRCS:.c=.o)
|
OBJS = $(SRCS:.c=.o)
|
||||||
|
|
||||||
|
@ -0,0 +1,444 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Wind River Systems, Inc.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <json-c/json.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <net-snmp/net-snmp-config.h>
|
||||||
|
#include <net-snmp/net-snmp-includes.h>
|
||||||
|
#include "wrsAlarmMIBServer.h"
|
||||||
|
#include "wrsAlarmMIBTrap.h"
|
||||||
|
|
||||||
|
#define HOST_NAME "localhost"
|
||||||
|
#define MSG_SIZE 4
|
||||||
|
#define BACKLOG 1
|
||||||
|
#define ENABLE 1
|
||||||
|
#define RETRIES 5
|
||||||
|
#define RETRIES_MESSAGE_SIZE 20
|
||||||
|
#define DEFAULT_ERROR -1
|
||||||
|
#define DEFAULT_SUCCESS 0
|
||||||
|
|
||||||
|
struct sServerInfo {
|
||||||
|
char address[INET6_ADDRSTRLEN];
|
||||||
|
int address_family;
|
||||||
|
int port;
|
||||||
|
int fd;
|
||||||
|
int retries;
|
||||||
|
int error;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns a ServerInfo error attribute.
|
||||||
|
*/
|
||||||
|
int get_error(ServerInfo server_info){
|
||||||
|
assert(server_info != NULL);
|
||||||
|
return server_info->error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This procedure attempts to start to listen a Server.
|
||||||
|
In case of success returns DEFAULT_SUCCESS.
|
||||||
|
*/
|
||||||
|
int init_server(ServerInfo server_info){
|
||||||
|
assert(server_info != NULL);
|
||||||
|
int optval = ENABLE;
|
||||||
|
int error = DEFAULT_ERROR;
|
||||||
|
int fd = DEFAULT_ERROR;
|
||||||
|
|
||||||
|
snmp_log(LOG_INFO, "server init_server init on address: %s family: %d port:"
|
||||||
|
" %d\n", server_info->address, server_info->address_family,
|
||||||
|
server_info->port);
|
||||||
|
|
||||||
|
fd = socket(server_info->address_family, SOCK_STREAM, 0);
|
||||||
|
if( fd == DEFAULT_ERROR){
|
||||||
|
snmp_log(LOG_ERR, "server init_server socket errno: (%d) (%s)\n", errno,
|
||||||
|
strerror(errno));
|
||||||
|
return DEFAULT_ERROR;
|
||||||
|
}
|
||||||
|
server_info->fd = fd;
|
||||||
|
|
||||||
|
error = setsockopt(server_info->fd, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
&optval, sizeof optval);
|
||||||
|
if( error != DEFAULT_SUCCESS){
|
||||||
|
snmp_log(LOG_ERR, "server init_server setsockopt errno: (%d) (%s)\n",
|
||||||
|
errno, strerror(errno));
|
||||||
|
close(server_info->fd);
|
||||||
|
snmp_log(LOG_ERR, "server init_server setsockopt errno: (%d) (%s)\n",
|
||||||
|
errno, strerror(errno));
|
||||||
|
return DEFAULT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (server_info -> address_family) {
|
||||||
|
//When address is IPv4
|
||||||
|
case AF_INET:
|
||||||
|
{
|
||||||
|
struct sockaddr_in addr_4;
|
||||||
|
addr_4.sin_family = AF_INET;
|
||||||
|
addr_4.sin_port = htons(server_info -> port);
|
||||||
|
error = inet_pton(AF_INET, server_info->address,
|
||||||
|
&(addr_4.sin_addr.s_addr));
|
||||||
|
if(error <= DEFAULT_SUCCESS){
|
||||||
|
snmp_log(LOG_ERR,
|
||||||
|
"server init_server inet_pton error ip address %s with "
|
||||||
|
"error: %d errno: (%d) (%s)\n",
|
||||||
|
server_info->address, error, errno, strerror(errno));
|
||||||
|
close(server_info->fd);
|
||||||
|
snmp_log(LOG_ERR,
|
||||||
|
"server init_server closing socket errno: (%d) (%s)\n",
|
||||||
|
errno, strerror(errno));
|
||||||
|
return DEFAULT_ERROR;
|
||||||
|
}
|
||||||
|
error = bind(server_info->fd, (const struct sockaddr *)&addr_4,
|
||||||
|
sizeof(addr_4));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//When address is IPv6
|
||||||
|
case AF_INET6:
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 addr_6;
|
||||||
|
addr_6.sin6_family = AF_INET6;
|
||||||
|
addr_6.sin6_port = htons(server_info->port);
|
||||||
|
error = inet_pton(AF_INET6, server_info->address,
|
||||||
|
&(addr_6.sin6_addr));
|
||||||
|
if(error <= DEFAULT_SUCCESS){
|
||||||
|
snmp_log(LOG_ERR, "server init_server inet_pton error ip"
|
||||||
|
"address %s with error: %d errno: (%d) (%s)\n",
|
||||||
|
server_info->address, error, errno, strerror(errno));
|
||||||
|
close(server_info->fd);
|
||||||
|
snmp_log(LOG_ERR, "server init_server closing socket errno:"
|
||||||
|
"(%d) (%s)\n", errno, strerror(errno));
|
||||||
|
return DEFAULT_ERROR;
|
||||||
|
}
|
||||||
|
error = bind(server_info->fd, (const struct sockaddr *)&addr_6,
|
||||||
|
sizeof(addr_6));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//Should never get here, needed for completeness
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
snmp_log(LOG_ERR, "server init_server run default state %d\n",
|
||||||
|
server_info -> address_family);
|
||||||
|
close(server_info->fd);
|
||||||
|
snmp_log(LOG_ERR, "server init_server closing socket errno:"
|
||||||
|
"(%d) (%s)\n", errno, strerror(errno));
|
||||||
|
return DEFAULT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error != DEFAULT_SUCCESS) {
|
||||||
|
snmp_log(LOG_ERR, "server init_server binding errno: (%d) (%s)\n",
|
||||||
|
errno, strerror(errno));
|
||||||
|
close(server_info->fd);
|
||||||
|
snmp_log(LOG_ERR, "server init_server closing socket errno:"
|
||||||
|
"(%d) (%s)\n", errno, strerror(errno));
|
||||||
|
return DEFAULT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
snmp_log(LOG_INFO, "server init_server bind success address: %s with "
|
||||||
|
"port: %d\n", server_info->address, server_info->port);
|
||||||
|
error = listen(server_info->fd, BACKLOG);
|
||||||
|
if (error != DEFAULT_SUCCESS) {
|
||||||
|
snmp_log(LOG_ERR, "server init_server listen fd:(%d) error, errno:"
|
||||||
|
" (%d) (%s)\n", server_info->fd, errno, strerror(errno));
|
||||||
|
close(server_info->fd);
|
||||||
|
snmp_log(LOG_ERR, "server init_server closing socket errno: "
|
||||||
|
"(%d) (%s)\n", errno, strerror(errno));
|
||||||
|
return DEFAULT_ERROR;
|
||||||
|
}
|
||||||
|
snmp_log(LOG_INFO, "server listening fd: %d \n", server_info->fd);
|
||||||
|
snmp_log(LOG_INFO, "server init_server success\n");
|
||||||
|
return DEFAULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This procedure returns a ServerInfo with host_name and port. Also with all
|
||||||
|
metadata needed to start listening. In case of error returns NULL.
|
||||||
|
*/
|
||||||
|
ServerInfo get_server_info(const char * host_name, int port){
|
||||||
|
|
||||||
|
struct addrinfo hints;
|
||||||
|
struct addrinfo *result, *rp;
|
||||||
|
struct in_addr in4addr_any;
|
||||||
|
int error = -1;
|
||||||
|
ServerInfo server_info;
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = AI_PASSIVE;
|
||||||
|
hints.ai_protocol = 0;
|
||||||
|
hints.ai_canonname = NULL;
|
||||||
|
hints.ai_addr = NULL;
|
||||||
|
hints.ai_next = NULL;
|
||||||
|
|
||||||
|
snmp_log(LOG_INFO, "server get_server_info for hostname: %s\n", host_name);
|
||||||
|
error = getaddrinfo(host_name, NULL, &hints, &result);
|
||||||
|
if (error != 0) {
|
||||||
|
snmp_log(LOG_ERR, "server get_server_info getaddrinfo: %s\n",
|
||||||
|
gai_strerror(error));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
server_info = malloc(sizeof(struct sServerInfo));
|
||||||
|
if(server_info == NULL){
|
||||||
|
snmp_log(LOG_ERR, "server get_server_info error allocation ServerInfo \n");
|
||||||
|
freeaddrinfo(result);
|
||||||
|
result = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
server_info -> port = port;
|
||||||
|
server_info -> error = DEFAULT_SUCCESS;
|
||||||
|
server_info -> retries = RETRIES;
|
||||||
|
|
||||||
|
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||||
|
if(rp->ai_family == AF_INET) {
|
||||||
|
in4addr_any.s_addr = INADDR_ANY;
|
||||||
|
inet_ntop(AF_INET, &in4addr_any,
|
||||||
|
server_info->address, sizeof(server_info->address));
|
||||||
|
server_info->address_family = AF_INET;
|
||||||
|
snmp_log(LOG_INFO, "server get_server_info found IPv4: %s\n",
|
||||||
|
server_info->address);
|
||||||
|
break;
|
||||||
|
} else if (rp->ai_family == AF_INET6) {
|
||||||
|
inet_ntop(AF_INET6, &in6addr_any,
|
||||||
|
server_info->address, sizeof(server_info->address));
|
||||||
|
server_info->address_family = AF_INET6;
|
||||||
|
snmp_log(LOG_INFO, "server get_server_info found IPv6: %s \n",
|
||||||
|
server_info->address);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rp == NULL){
|
||||||
|
snmp_log(LOG_ERR, "server get_server_info ip not found at %s\n",
|
||||||
|
host_name);
|
||||||
|
free(server_info);
|
||||||
|
server_info = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(result);
|
||||||
|
result = NULL;
|
||||||
|
return server_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This procedure intents to close the listener socket of the server and free the
|
||||||
|
memory of ServerInfo. In case of error returns an non-zero value.
|
||||||
|
*/
|
||||||
|
int stop_alarm_server(ServerInfo server_info){
|
||||||
|
assert(server_info!=NULL);
|
||||||
|
int error = close(server_info->fd);
|
||||||
|
snmp_log(LOG_ERR, "server stop_alarm_server close errno: (%d) (%s)\n",
|
||||||
|
errno, strerror(errno));
|
||||||
|
free(server_info);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This procedures is responsible to listen for new connections.
|
||||||
|
On error stops listening and return a non-zero value.
|
||||||
|
*/
|
||||||
|
int handle_server_messages(ServerInfo server_info){
|
||||||
|
|
||||||
|
int socket_keep_running = 1;
|
||||||
|
struct sockaddr cli;
|
||||||
|
int connfd = 0;
|
||||||
|
int read = 0;
|
||||||
|
int bytes_read = 0;
|
||||||
|
socklen_t cli_len= sizeof(cli);
|
||||||
|
int length_bytes = 0;
|
||||||
|
uint32_t length = 0;
|
||||||
|
uint32_t nlength = 0;
|
||||||
|
int error_msg_len = DEFAULT_SUCCESS;
|
||||||
|
int error_processing = DEFAULT_ERROR;
|
||||||
|
int partial_retries = 0;
|
||||||
|
int terminate = 0;
|
||||||
|
|
||||||
|
// reduce recall tries and check if max retries reached
|
||||||
|
server_info->retries = server_info->retries -1;
|
||||||
|
if(server_info->retries < 0 ){
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages handling messages MAX"
|
||||||
|
"retries reach\n");
|
||||||
|
return DEFAULT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start handling messages
|
||||||
|
snmp_log(LOG_INFO,"server handle_server_messages start handling messages\n");
|
||||||
|
snmp_log(LOG_INFO,"server handle_server_messages retries counter: %d\n",
|
||||||
|
server_info->retries);
|
||||||
|
|
||||||
|
while (socket_keep_running) {
|
||||||
|
// accepts connections
|
||||||
|
connfd = accept(server_info->fd, (struct sockaddr*) &cli, &cli_len);
|
||||||
|
if (connfd < DEFAULT_SUCCESS) {
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages acccept error, errno:"
|
||||||
|
"(%d) (%s)\n", errno, strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
snmp_log(LOG_INFO,"server handle_server_messages client socket"
|
||||||
|
" accepted %d\n", connfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// message length read
|
||||||
|
length_bytes = 0;
|
||||||
|
nlength = 0;
|
||||||
|
error_msg_len = DEFAULT_SUCCESS;
|
||||||
|
partial_retries = 0;
|
||||||
|
while (length_bytes < MSG_SIZE) {
|
||||||
|
read = recv(connfd, ((char *)&nlength) + length_bytes, MSG_SIZE - length_bytes, 0);
|
||||||
|
if (read < DEFAULT_SUCCESS) {
|
||||||
|
snmp_log(LOG_ERR,
|
||||||
|
"\nserver handle_server_messages failed to receive message "
|
||||||
|
"length errno: (%d) (%s)\n",
|
||||||
|
errno, strerror(errno));
|
||||||
|
error_msg_len = DEFAULT_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (partial_retries > RETRIES_MESSAGE_SIZE) {
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages message length "
|
||||||
|
"max retries: (%d)\n", partial_retries);
|
||||||
|
error_msg_len = DEFAULT_ERROR;
|
||||||
|
break;
|
||||||
|
}else{
|
||||||
|
partial_retries ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
length_bytes += read;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if error in message len read then recall
|
||||||
|
if(error_msg_len != DEFAULT_SUCCESS) {
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages recall because handle"
|
||||||
|
" message len failed\n");
|
||||||
|
close(connfd);
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages port close errno: "
|
||||||
|
"(%d) (%s)\n", errno, strerror(errno));
|
||||||
|
terminate = handle_server_messages(server_info);
|
||||||
|
if(terminate == DEFAULT_ERROR){
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages recall failed"
|
||||||
|
" with state %d \n", terminate);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// message allocation memory
|
||||||
|
length = ntohl(nlength);
|
||||||
|
char *msg = malloc(length);
|
||||||
|
|
||||||
|
// memory allocation error
|
||||||
|
if(msg == NULL) {
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages recall because "
|
||||||
|
"message malloc failed\n");
|
||||||
|
close(connfd);
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages port close errno:"
|
||||||
|
" (%d) (%s)\n",
|
||||||
|
errno, strerror(errno));
|
||||||
|
terminate = handle_server_messages(server_info);
|
||||||
|
if(terminate == DEFAULT_ERROR){
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages recall failed"
|
||||||
|
" with state %d \n", terminate);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// message read
|
||||||
|
bytes_read = recv(connfd, msg, length, 0);
|
||||||
|
|
||||||
|
// no message arrived
|
||||||
|
if (bytes_read < DEFAULT_SUCCESS) {
|
||||||
|
free(msg);
|
||||||
|
msg = NULL;
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages recall because"
|
||||||
|
" message receive failed\n");
|
||||||
|
close(connfd);
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages port close errno:"
|
||||||
|
" (%d) (%s)\n", errno, strerror(errno));
|
||||||
|
terminate = handle_server_messages(server_info);
|
||||||
|
if(terminate == DEFAULT_ERROR){
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages recall failed"
|
||||||
|
" with state %d \n", terminate);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// error message incomplete
|
||||||
|
if (bytes_read != length) {
|
||||||
|
free(msg);
|
||||||
|
msg = NULL;
|
||||||
|
snmp_log(LOG_ERR,
|
||||||
|
"server handle_server_messages recall because message bytes_read"
|
||||||
|
" != length failed\n");
|
||||||
|
close(connfd);
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages port close errno: "
|
||||||
|
"(%d) (%s)\n", errno, strerror(errno));
|
||||||
|
terminate = handle_server_messages(server_info);
|
||||||
|
if(terminate == DEFAULT_ERROR){
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages recall failed "
|
||||||
|
"with state %d \n", terminate);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// process the message
|
||||||
|
error_processing = process_json_alarm(msg);
|
||||||
|
if(error_processing != DEFAULT_SUCCESS){
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages bad message "
|
||||||
|
"processing.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// free resources
|
||||||
|
free(msg);
|
||||||
|
msg = NULL;
|
||||||
|
close(connfd);
|
||||||
|
snmp_log(LOG_INFO,"server handle_server_messages port close fd: (%d),"
|
||||||
|
" errno: (%d) (%s)\n", connfd, errno, strerror(errno));
|
||||||
|
snmp_log(LOG_INFO,"server handle_server_messages message received ok.\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// if breaks return error
|
||||||
|
snmp_log(LOG_ERR,"server handle_server_messages unespected error\n");
|
||||||
|
return DEFAULT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This procedure starts the server workflow.
|
||||||
|
In case of memory allocation failure returns NULL.
|
||||||
|
In case of communication errors returns a ServerInfo with an error
|
||||||
|
that can be retrieved by get_error() method.
|
||||||
|
*/
|
||||||
|
ServerInfo start_alarm_server (int port){
|
||||||
|
ServerInfo server_info = get_server_info(HOST_NAME, port);
|
||||||
|
int error = DEFAULT_ERROR;
|
||||||
|
if( server_info != NULL){
|
||||||
|
error = init_server(server_info);
|
||||||
|
if(error == DEFAULT_SUCCESS){
|
||||||
|
error = handle_server_messages(server_info);
|
||||||
|
if (error != DEFAULT_SUCCESS){
|
||||||
|
// unespected server error
|
||||||
|
// retry until MAX tries
|
||||||
|
server_info -> error = DEFAULT_ERROR;
|
||||||
|
snmp_log(LOG_ERR,
|
||||||
|
"server start_alarm_server stopped by error in "
|
||||||
|
"handle_server_messages\n");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
// an error during starting up
|
||||||
|
server_info -> error = DEFAULT_ERROR;
|
||||||
|
snmp_log(LOG_ERR, "server start_alarm_server stopped by error "
|
||||||
|
"in init_server\n");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
// cannot get host address info
|
||||||
|
snmp_log(LOG_ERR, "server start_alarm_server stopped by error in "
|
||||||
|
"get_server_info\n");
|
||||||
|
}
|
||||||
|
return server_info;
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Wind River Systems, Inc.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WRSALARMMIBSERVER_H
|
||||||
|
#define WRSALARMMIBSERVER_H
|
||||||
|
|
||||||
|
typedef struct sServerInfo * ServerInfo;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Description: start listening in an specified port.
|
||||||
|
Parameters: an integer port to start listening
|
||||||
|
Return value: On error a NULL value if a memory allocation error occurs.
|
||||||
|
On success a ServerInfo with the runtime information.
|
||||||
|
*/
|
||||||
|
ServerInfo start_alarm_server (int port);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Description: stop listening for connections and free memory structures.
|
||||||
|
Parameters: a ServerInfo not null value.
|
||||||
|
Return value: a non-zero value on close port error.
|
||||||
|
*/
|
||||||
|
int stop_alarm_server(ServerInfo server_info);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Description: retrieve the ServerInfo status.
|
||||||
|
Parameters: a ServerInfo not null value .
|
||||||
|
Return value: retrieves non-zero value indicating error status.
|
||||||
|
*/
|
||||||
|
int get_error(ServerInfo server_info);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* WRSALARMMIBSERVER_H */
|
@ -1,44 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 Wind River Systems, Inc.
|
* Copyright (c) 2020-2021 Wind River Systems, Inc.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <json-c/json.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <net-snmp/net-snmp-config.h>
|
#include <net-snmp/net-snmp-config.h>
|
||||||
#include <net-snmp/net-snmp-features.h>
|
#include <net-snmp/net-snmp-features.h>
|
||||||
#include <net-snmp/net-snmp-includes.h>
|
#include <net-snmp/net-snmp-includes.h>
|
||||||
|
|
||||||
#include <net-snmp/agent/net-snmp-agent-includes.h>
|
#include <net-snmp/agent/net-snmp-agent-includes.h>
|
||||||
|
#include "wrsAlarmMIBServer.h"
|
||||||
|
|
||||||
#include "wrsAlarmMIBTrap.h"
|
|
||||||
|
|
||||||
#define MSG_SIZE 4
|
|
||||||
#define TCP_SOCKET_PORT 162
|
#define TCP_SOCKET_PORT 162
|
||||||
#define ALARM_CRITICAL "wrsAlarmCritical"
|
|
||||||
#define ALARM_MAJOR "wrsAlarmMajor"
|
|
||||||
#define ALARM_MINOR "wrsAlarmMinor"
|
|
||||||
#define ALARM_WARNING "wrsAlarmWarning"
|
|
||||||
#define ALARM_MSG "wrsAlarmMessage"
|
|
||||||
#define ALARM_CLEAR "wrsAlarmClear"
|
|
||||||
#define ALARM_HIERARCHICAL_CLEAR "wrsAlarmHierarchicalClear"
|
|
||||||
#define WARM_START "warmStart"
|
|
||||||
|
|
||||||
#define SA struct sockaddr
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If compiling within the net-snmp source code, this will trigger the feature
|
* If compiling within the net-snmp source code, this will trigger the feature
|
||||||
@ -77,131 +51,6 @@ static void usage(void)
|
|||||||
"\t-L\tDo not open a log file; print all messages to stderr.\n");
|
"\t-L\tDo not open a log file; print all messages to stderr.\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
void initSocketServer(void)
|
|
||||||
{
|
|
||||||
int sockfd, connfd, read, bytes_read;
|
|
||||||
int enable = 1;
|
|
||||||
int socket_keep_running = 1;
|
|
||||||
socklen_t len;
|
|
||||||
struct sockaddr_in servaddr, cli;
|
|
||||||
const int backlog = 1;
|
|
||||||
|
|
||||||
// socket create and verification
|
|
||||||
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
||||||
if (sockfd == -1) {
|
|
||||||
snmp_log(LOG_ERR,"Socket creation failed\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
snmp_log(LOG_INFO,"Socket successfully created\n");
|
|
||||||
|
|
||||||
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
|
|
||||||
|
|
||||||
bzero(&servaddr, sizeof(servaddr));
|
|
||||||
|
|
||||||
// assign IP, PORT
|
|
||||||
servaddr.sin_family = AF_INET;
|
|
||||||
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
servaddr.sin_port = htons(TCP_SOCKET_PORT);
|
|
||||||
|
|
||||||
// Binding newly created socket to given IP and verification
|
|
||||||
if ((bind(sockfd, (SA *)&servaddr, sizeof(servaddr))) != 0) {
|
|
||||||
close(sockfd);
|
|
||||||
snmp_log(LOG_ERR,"Socket bind failed\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
snmp_log(LOG_INFO,"Socket successfully binded\n");
|
|
||||||
|
|
||||||
if ((listen(sockfd, backlog)) != 0) {
|
|
||||||
snmp_log(LOG_ERR,"Failed to start server socket listen.\n");
|
|
||||||
close(sockfd);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
snmp_log(LOG_INFO,"Server listening\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
len = sizeof(cli);
|
|
||||||
|
|
||||||
while (socket_keep_running) {
|
|
||||||
connfd = accept(sockfd, (SA *)&cli, &len);
|
|
||||||
if (connfd < 0) {
|
|
||||||
snmp_log(LOG_ERR,"Server acccept failed\n");
|
|
||||||
close(sockfd);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
snmp_log(LOG_INFO,"Client socket accepted\n");
|
|
||||||
|
|
||||||
int length_bytes = 0;
|
|
||||||
uint32_t length, nlength;
|
|
||||||
|
|
||||||
while (length_bytes < MSG_SIZE) {
|
|
||||||
read = recv(connfd, ((char *)&nlength) + length_bytes, MSG_SIZE - length_bytes, 0);
|
|
||||||
if (read == -1) {
|
|
||||||
snmp_log(LOG_ERR,"Failed to receive message.\n");
|
|
||||||
}
|
|
||||||
length_bytes += read;
|
|
||||||
}
|
|
||||||
|
|
||||||
length = ntohl(nlength);
|
|
||||||
char *msg = malloc(length);
|
|
||||||
bytes_read = recv(connfd, msg, length, 0);
|
|
||||||
|
|
||||||
if (bytes_read == -1) {
|
|
||||||
snmp_log(LOG_ERR,"Failed to receive message.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytes_read != length) {
|
|
||||||
snmp_log(LOG_ERR,"recv: Premature EOF.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct json_object *parsed_json = json_tokener_parse(msg);
|
|
||||||
struct json_object *operation_type;
|
|
||||||
json_object_object_get_ex(parsed_json, "operation_type", &operation_type);
|
|
||||||
const char *opt_type = json_object_get_string(operation_type);
|
|
||||||
|
|
||||||
if (strcmp(ALARM_CLEAR, opt_type) == 0) {
|
|
||||||
|
|
||||||
send_wrsAlarmClear_trap(parsed_json);
|
|
||||||
}
|
|
||||||
else if (strcmp(ALARM_HIERARCHICAL_CLEAR, opt_type) == 0) {
|
|
||||||
|
|
||||||
send_wrsAlarmHierarchicalClear_trap(parsed_json);
|
|
||||||
}
|
|
||||||
else if (strcmp(ALARM_MSG, opt_type) == 0) {
|
|
||||||
|
|
||||||
send_wrsEventMessage_trap(parsed_json);
|
|
||||||
}
|
|
||||||
else if (strcmp(ALARM_WARNING, opt_type) == 0) {
|
|
||||||
|
|
||||||
send_wrsAlarmWarning_trap(parsed_json);
|
|
||||||
}
|
|
||||||
else if (strcmp(ALARM_MINOR, opt_type) == 0) {
|
|
||||||
|
|
||||||
send_wrsAlarmMinor_trap(parsed_json);
|
|
||||||
}
|
|
||||||
else if (strcmp(ALARM_MAJOR, opt_type) == 0) {
|
|
||||||
|
|
||||||
send_wrsAlarmMajor_trap(parsed_json);
|
|
||||||
}
|
|
||||||
else if (strcmp(ALARM_CRITICAL, opt_type) == 0) {
|
|
||||||
|
|
||||||
send_wrsAlarmCritical_trap(parsed_json);
|
|
||||||
}
|
|
||||||
else if (strcmp(WARM_START, opt_type) == 0) {
|
|
||||||
|
|
||||||
send_wrsWarmStart_trap();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
send_wrsAlarmMessage_trap(parsed_json);
|
|
||||||
}
|
|
||||||
json_object_put(parsed_json);
|
|
||||||
free(msg);
|
|
||||||
}
|
|
||||||
close(sockfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -211,6 +60,8 @@ int main(int argc, char **argv)
|
|||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
int dont_fork = 0, use_syslog = 0;
|
int dont_fork = 0, use_syslog = 0;
|
||||||
char *agentx_socket = NULL;
|
char *agentx_socket = NULL;
|
||||||
|
ServerInfo server_info = NULL;
|
||||||
|
int server_info_error = -1;
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "D:fHLM-:x:")) != EOF)
|
while ((ch = getopt(argc, argv, "D:fHLM-:x:")) != EOF)
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
@ -318,7 +169,31 @@ int main(int argc, char **argv)
|
|||||||
keep_running = 1;
|
keep_running = 1;
|
||||||
signal(SIGTERM, stop_server);
|
signal(SIGTERM, stop_server);
|
||||||
signal(SIGINT, stop_server);
|
signal(SIGINT, stop_server);
|
||||||
initSocketServer();
|
|
||||||
|
// server start listening
|
||||||
|
server_info = start_alarm_server(TCP_SOCKET_PORT);
|
||||||
|
|
||||||
|
// if server stops
|
||||||
|
if(server_info == NULL){
|
||||||
|
// server memmory allocation errors
|
||||||
|
snmp_log(LOG_ERR, "trap-subagent: stopping server, server_info NULL calling stop_server()\n");
|
||||||
|
stop_server(SIGABRT);
|
||||||
|
}else{
|
||||||
|
// other server errors
|
||||||
|
server_info_error = get_error(server_info);
|
||||||
|
snmp_log(LOG_ERR, "trap-subagent: stopping server, server_info -> error: "
|
||||||
|
"%d \n", server_info_error);
|
||||||
|
// if error after closing
|
||||||
|
if(stop_alarm_server(server_info) < 0){
|
||||||
|
snmp_log(LOG_INFO, "trap-subagent: stop server failed %d\n", server_info_error);
|
||||||
|
}else{
|
||||||
|
snmp_log(LOG_INFO, "trap-subagent: stop server success\n");
|
||||||
|
}
|
||||||
|
// server_info to NULL
|
||||||
|
server_info = NULL;
|
||||||
|
stop_server(SIGABRT);
|
||||||
|
}
|
||||||
|
|
||||||
while (keep_running) {
|
while (keep_running) {
|
||||||
/* if you use select(), see snmp_select_info() in snmp_api(3) */
|
/* if you use select(), see snmp_select_info() in snmp_api(3) */
|
||||||
/* --- OR --- */
|
/* --- OR --- */
|
||||||
@ -326,7 +201,21 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* at shutdown time */
|
/* at shutdown time */
|
||||||
|
|
||||||
snmp_shutdown("wrsAlarmMIB");
|
snmp_shutdown("wrsAlarmMIB");
|
||||||
|
|
||||||
|
if(server_info != NULL){
|
||||||
|
// stop from SIGTERM or SIGINT
|
||||||
|
snmp_log(LOG_INFO, "trap-subagent: signal received, calling stop_alarm_sever()\n");
|
||||||
|
server_info_error = get_error(server_info);
|
||||||
|
if( stop_alarm_server(server_info) < 0 ){
|
||||||
|
snmp_log(LOG_INFO, "trap-subagent: stop server error: %d\n", server_info_error);
|
||||||
|
}else{
|
||||||
|
snmp_log(LOG_INFO, "trap-subagent: stop server success\n");
|
||||||
|
}
|
||||||
|
server_info = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
SOCK_CLEANUP;
|
SOCK_CLEANUP;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 Wind River Systems, Inc.
|
* Copyright (c) 2020-2021 Wind River Systems, Inc.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <net-snmp/net-snmp-config.h>
|
#include <net-snmp/net-snmp-config.h>
|
||||||
|
#include <net-snmp/net-snmp-features.h>
|
||||||
#include <net-snmp/net-snmp-includes.h>
|
#include <net-snmp/net-snmp-includes.h>
|
||||||
#include <net-snmp/agent/net-snmp-agent-includes.h>
|
#include <net-snmp/agent/net-snmp-agent-includes.h>
|
||||||
|
|
||||||
@ -31,6 +32,15 @@
|
|||||||
#define EVENT_CAUSE "wrsEventProbableCause"
|
#define EVENT_CAUSE "wrsEventProbableCause"
|
||||||
#define EVENT_SERVICE_AFFECTING "wrsEventServiceAffecting"
|
#define EVENT_SERVICE_AFFECTING "wrsEventServiceAffecting"
|
||||||
|
|
||||||
|
#define ALARM_CRITICAL "wrsAlarmCritical"
|
||||||
|
#define ALARM_MAJOR "wrsAlarmMajor"
|
||||||
|
#define ALARM_MINOR "wrsAlarmMinor"
|
||||||
|
#define ALARM_WARNING "wrsAlarmWarning"
|
||||||
|
#define ALARM_MSG "wrsAlarmMessage"
|
||||||
|
#define ALARM_CLEAR "wrsAlarmClear"
|
||||||
|
#define ALARM_HIERARCHICAL_CLEAR "wrsAlarmHierarchicalClear"
|
||||||
|
#define WARM_START "warmStart"
|
||||||
|
|
||||||
extern const oid snmptrap_oid[];
|
extern const oid snmptrap_oid[];
|
||||||
extern const size_t snmptrap_oid_len;
|
extern const size_t snmptrap_oid_len;
|
||||||
|
|
||||||
@ -894,4 +904,51 @@ send_wrsWarmStart_trap()
|
|||||||
snmp_free_varbind( var_list );
|
snmp_free_varbind( var_list );
|
||||||
|
|
||||||
return SNMP_ERR_NOERROR;
|
return SNMP_ERR_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
process_json_alarm(const char* msg )
|
||||||
|
{
|
||||||
|
|
||||||
|
if(msg == NULL) {
|
||||||
|
snmp_log(LOG_ERR,"JSON message alarm to processs is null\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct json_object *parsed_json = json_tokener_parse(msg);
|
||||||
|
struct json_object *operation_type;
|
||||||
|
json_object_object_get_ex(parsed_json, "operation_type", &operation_type);
|
||||||
|
const char *opt_type = json_object_get_string(operation_type);
|
||||||
|
|
||||||
|
if (strcmp(ALARM_CLEAR, opt_type) == 0) {
|
||||||
|
send_wrsAlarmClear_trap(parsed_json);
|
||||||
|
}
|
||||||
|
else if (strcmp(ALARM_HIERARCHICAL_CLEAR, opt_type) == 0) {
|
||||||
|
send_wrsAlarmHierarchicalClear_trap(parsed_json);
|
||||||
|
}
|
||||||
|
else if (strcmp(ALARM_MSG, opt_type) == 0) {
|
||||||
|
send_wrsEventMessage_trap(parsed_json);
|
||||||
|
}
|
||||||
|
else if (strcmp(ALARM_WARNING, opt_type) == 0) {
|
||||||
|
send_wrsAlarmWarning_trap(parsed_json);
|
||||||
|
}
|
||||||
|
else if (strcmp(ALARM_MINOR, opt_type) == 0) {
|
||||||
|
send_wrsAlarmMinor_trap(parsed_json);
|
||||||
|
}
|
||||||
|
else if (strcmp(ALARM_MAJOR, opt_type) == 0) {
|
||||||
|
send_wrsAlarmMajor_trap(parsed_json);
|
||||||
|
}
|
||||||
|
else if (strcmp(ALARM_CRITICAL, opt_type) == 0) {
|
||||||
|
send_wrsAlarmCritical_trap(parsed_json);
|
||||||
|
}
|
||||||
|
else if (strcmp(WARM_START, opt_type) == 0) {
|
||||||
|
send_wrsWarmStart_trap();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
send_wrsAlarmMessage_trap(parsed_json);
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object_put(parsed_json);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 Wind River Systems, Inc.
|
* Copyright (c) 2020-2021 Wind River Systems, Inc.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
@ -19,5 +19,6 @@ int send_wrsEventMessage_trap(struct json_object *);
|
|||||||
int send_wrsAlarmClear_trap(struct json_object *);
|
int send_wrsAlarmClear_trap(struct json_object *);
|
||||||
int send_wrsAlarmHierarchicalClear_trap(struct json_object *);
|
int send_wrsAlarmHierarchicalClear_trap(struct json_object *);
|
||||||
int send_wrsWarmStart_trap(void);
|
int send_wrsWarmStart_trap(void);
|
||||||
|
int process_json_alarm(const char* msg);
|
||||||
|
|
||||||
#endif /* WRSALARMMIBTRAP_H */
|
#endif /* WRSALARMMIBTRAP_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user