3376 lines
122 KiB
C
3376 lines
122 KiB
C
//
|
|
// Copyright (c) 2014-2018 Wind River Systems, Inc.
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
#include "sm_msg.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet/ip.h>
|
|
#include <net/if.h>
|
|
#include <arpa/inet.h>
|
|
|
|
#include "sm_types.h"
|
|
#include "sm_debug.h"
|
|
#include "sm_list.h"
|
|
#include "sm_selobj.h"
|
|
#include "sm_uuid.h"
|
|
#include "sm_sha512.h"
|
|
#include "sm_hw.h"
|
|
#include "sm_node_utils.h"
|
|
#include "sm_db.h"
|
|
#include "sm_db_service_domain_interfaces.h"
|
|
|
|
#define SM_MSG_VERSION 1
|
|
#define SM_MSG_REVISION 1
|
|
#define SM_MSG_FLAG_ACK 0x1
|
|
#define SM_MSG_MAX_SIZE 1024
|
|
#define SM_MSG_BUFFER_MAX_SIZE 4096
|
|
#define SM_MSG_MAX_SEQ_DELTA 1000
|
|
|
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
#define ntohll(x) (x)
|
|
#define htonll(x) (x)
|
|
#else
|
|
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
# define ntohll(x) sm_msg_little_endian_ntohll(x)
|
|
# define htonll(x) sm_msg_little_endian_htonll(x)
|
|
# endif
|
|
#endif
|
|
|
|
#define _MSG_NOT_SENT_TO_TARGET -128
|
|
typedef enum
|
|
{
|
|
SM_MSG_TYPE_UNKNOWN = 0x0,
|
|
SM_MSG_TYPE_NODE_HELLO = 0x1,
|
|
SM_MSG_TYPE_NODE_UPDATE = 0x2,
|
|
SM_MSG_TYPE_NODE_SWACT = 0x3,
|
|
SM_MSG_TYPE_NODE_SWACT_ACK = 0x4,
|
|
SM_MSG_TYPE_SERVICE_DOMAIN_HELLO = 0x5,
|
|
SM_MSG_TYPE_SERVICE_DOMAIN_PAUSE = 0x6,
|
|
SM_MSG_TYPE_SERVICE_DOMAIN_EXCHANGE_START = 0x7,
|
|
SM_MSG_TYPE_SERVICE_DOMAIN_EXCHANGE = 0x8,
|
|
SM_MSG_TYPE_SERVICE_DOMAIN_MEMBER_REQUEST = 0x9,
|
|
SM_MSG_TYPE_SERVICE_DOMAIN_MEMBER_UPDATE = 0xa,
|
|
SM_MSG_MAX,
|
|
} SmMsgTypeT;
|
|
|
|
typedef struct
|
|
{
|
|
uint16_t version;
|
|
uint16_t revision;
|
|
uint16_t max_supported_version;
|
|
uint16_t max_supported_revision;
|
|
uint16_t msg_len;
|
|
uint16_t msg_type;
|
|
uint64_t msg_flags;
|
|
SmUuidT msg_instance;
|
|
uint64_t msg_seq_num;
|
|
char node_name[SM_NODE_NAME_MAX_CHAR];
|
|
uint32_t auth_type;
|
|
uint8_t auth_vector[SM_AUTHENTICATION_VECTOR_MAX_CHAR];
|
|
} __attribute__ ((packed)) SmMsgHeaderT;
|
|
|
|
typedef struct
|
|
{
|
|
char node_name[SM_NODE_NAME_MAX_CHAR];
|
|
char admin_state[SM_NODE_ADMIN_STATE_MAX_CHAR];
|
|
char oper_state[SM_NODE_OPERATIONAL_STATE_MAX_CHAR];
|
|
char avail_status[SM_NODE_AVAIL_STATUS_MAX_CHAR];
|
|
char ready_state[SM_NODE_READY_STATE_MAX_CHAR];
|
|
SmUuidT state_uuid;
|
|
uint32_t uptime;
|
|
} __attribute__ ((packed)) SmMsgNodeHelloT;
|
|
|
|
typedef struct
|
|
{
|
|
char node_name[SM_NODE_NAME_MAX_CHAR];
|
|
char admin_state[SM_NODE_ADMIN_STATE_MAX_CHAR];
|
|
char oper_state[SM_NODE_OPERATIONAL_STATE_MAX_CHAR];
|
|
char avail_status[SM_NODE_AVAIL_STATUS_MAX_CHAR];
|
|
char ready_state[SM_NODE_READY_STATE_MAX_CHAR];
|
|
SmUuidT old_state_uuid;
|
|
SmUuidT state_uuid;
|
|
uint32_t uptime;
|
|
uint32_t force;
|
|
} __attribute__ ((packed)) SmMsgNodeUpdateT;
|
|
|
|
typedef struct
|
|
{
|
|
SmUuidT request_uuid;
|
|
char node_name[SM_NODE_NAME_MAX_CHAR];
|
|
uint32_t force;
|
|
} __attribute__ ((packed)) SmMsgNodeSwactT;
|
|
|
|
typedef struct
|
|
{
|
|
SmUuidT request_uuid;
|
|
char node_name[SM_NODE_NAME_MAX_CHAR];
|
|
uint32_t force;
|
|
} __attribute__ ((packed)) SmMsgNodeSwactAckT;
|
|
|
|
typedef struct
|
|
{
|
|
char service_domain[SM_SERVICE_DOMAIN_NAME_MAX_CHAR];
|
|
char node_name[SM_NODE_NAME_MAX_CHAR];
|
|
char orchestration[SM_ORCHESTRATION_MAX_CHAR];
|
|
char designation[SM_DESIGNATION_MAX_CHAR];
|
|
uint32_t generation;
|
|
uint32_t priority;
|
|
uint32_t hello_interval;
|
|
uint32_t dead_interval;
|
|
uint32_t wait_interval;
|
|
uint32_t exchange_interval;
|
|
char leader[SM_NODE_NAME_MAX_CHAR];
|
|
} __attribute__ ((packed)) SmMsgServiceDomainHelloT;
|
|
|
|
typedef struct
|
|
{
|
|
char service_domain[SM_SERVICE_DOMAIN_NAME_MAX_CHAR];
|
|
char node_name[SM_NODE_NAME_MAX_CHAR];
|
|
uint32_t pause_interval;
|
|
} __attribute__ ((packed)) SmMsgServiceDomainPauseT;
|
|
|
|
typedef struct
|
|
{
|
|
char service_domain[SM_SERVICE_DOMAIN_NAME_MAX_CHAR];
|
|
char node_name[SM_NODE_NAME_MAX_CHAR];
|
|
char exchange_node_name[SM_NODE_NAME_MAX_CHAR];
|
|
uint32_t exchange_seq;
|
|
} __attribute__ ((packed)) SmMsgServiceDomainExchangeStartT;
|
|
|
|
typedef struct
|
|
{
|
|
char service_domain[SM_SERVICE_DOMAIN_NAME_MAX_CHAR];
|
|
char node_name[SM_NODE_NAME_MAX_CHAR];
|
|
char exchange_node_name[SM_NODE_NAME_MAX_CHAR];
|
|
uint32_t exchange_seq;
|
|
int64_t member_id;
|
|
char member_name[SM_SERVICE_GROUP_NAME_MAX_CHAR];
|
|
char member_desired_state[SM_SERVICE_GROUP_STATE_MAX_CHAR];
|
|
char member_state[SM_SERVICE_GROUP_STATE_MAX_CHAR];
|
|
char member_status[SM_SERVICE_GROUP_STATUS_MAX_CHAR];
|
|
char member_condition[SM_SERVICE_GROUP_CONDITION_MAX_CHAR];
|
|
int64_t member_health;
|
|
char reason_text[SM_SERVICE_GROUP_REASON_TEXT_MAX_CHAR];
|
|
uint32_t more_members;
|
|
int64_t last_received_member_id;
|
|
} __attribute__ ((packed)) SmMsgServiceDomainExchangeT;
|
|
|
|
typedef struct
|
|
{
|
|
char service_domain[SM_SERVICE_DOMAIN_NAME_MAX_CHAR];
|
|
char node_name[SM_NODE_NAME_MAX_CHAR];
|
|
char member_node_name[SM_NODE_NAME_MAX_CHAR];
|
|
int64_t member_id;
|
|
char member_name[SM_SERVICE_GROUP_NAME_MAX_CHAR];
|
|
char member_action[SM_SERVICE_GROUP_ACTION_MAX_CHAR];
|
|
uint64_t member_action_flags;
|
|
} __attribute__ ((packed)) SmMsgServiceDomainMemberRequestT;
|
|
|
|
typedef struct
|
|
{
|
|
char service_domain[SM_SERVICE_DOMAIN_NAME_MAX_CHAR];
|
|
char node_name[SM_NODE_NAME_MAX_CHAR];
|
|
char member_node_name[SM_NODE_NAME_MAX_CHAR];
|
|
int64_t member_id;
|
|
char member_name[SM_SERVICE_GROUP_NAME_MAX_CHAR];
|
|
char member_desired_state[SM_SERVICE_GROUP_STATE_MAX_CHAR];
|
|
char member_state[SM_SERVICE_GROUP_STATE_MAX_CHAR];
|
|
char member_status[SM_SERVICE_GROUP_STATUS_MAX_CHAR];
|
|
char member_condition[SM_SERVICE_GROUP_CONDITION_MAX_CHAR];
|
|
int64_t member_health;
|
|
char reason_text[SM_SERVICE_GROUP_REASON_TEXT_MAX_CHAR];
|
|
} __attribute__ ((packed)) SmMsgServiceDomainMemberUpdateT;
|
|
|
|
typedef struct
|
|
{
|
|
SmMsgHeaderT header;
|
|
|
|
union
|
|
{ // Node Messages.
|
|
SmMsgNodeHelloT node_hello;
|
|
SmMsgNodeUpdateT node_update;
|
|
SmMsgNodeSwactT node_swact;
|
|
SmMsgNodeSwactAckT node_swact_ack;
|
|
|
|
// Service Domain Messages.
|
|
SmMsgServiceDomainHelloT hello;
|
|
SmMsgServiceDomainPauseT pause;
|
|
SmMsgServiceDomainExchangeStartT exchange_start;
|
|
SmMsgServiceDomainExchangeT exchange;
|
|
SmMsgServiceDomainMemberRequestT request;
|
|
SmMsgServiceDomainMemberUpdateT update;
|
|
char raw_msg[SM_MSG_MAX_SIZE-sizeof(SmMsgHeaderT)];
|
|
} u;
|
|
} __attribute__ ((packed)) SmMsgT;
|
|
|
|
typedef struct
|
|
{
|
|
bool inuse;
|
|
char node_name[SM_NODE_NAME_MAX_CHAR];
|
|
SmUuidT msg_instance;
|
|
uint64_t msg_last_seq_num;
|
|
} SmMsgPeerNodeInfoT;
|
|
|
|
typedef struct
|
|
{
|
|
bool inuse;
|
|
char interface_name[SM_INTERFACE_NAME_MAX_CHAR];
|
|
SmNetworkAddressT network_address;
|
|
int network_port;
|
|
SmAuthTypeT auth_type;
|
|
char auth_key[SM_AUTHENTICATION_KEY_MAX_CHAR];
|
|
} SmMsgPeerInterfaceInfoT;
|
|
|
|
static bool _messaging_enabled = false;
|
|
static char _hostname[SM_NODE_NAME_MAX_CHAR];
|
|
static SmUuidT _msg_instance = {0};
|
|
static uint64_t _msg_seq_num = 0;
|
|
static char _tx_control_buffer[SM_MSG_BUFFER_MAX_SIZE] __attribute__((aligned));
|
|
static char _tx_buffer[SM_MSG_BUFFER_MAX_SIZE] __attribute__((aligned));
|
|
static char _rx_control_buffer[SM_MSG_BUFFER_MAX_SIZE] __attribute__((aligned));
|
|
static char _rx_buffer[SM_MSG_BUFFER_MAX_SIZE] __attribute__((aligned));
|
|
static SmListT* _callbacks = NULL;
|
|
static unsigned int _next_free_peer_entry = 0;
|
|
static SmMsgPeerNodeInfoT _peers[SM_NODE_MAX];
|
|
static SmMsgPeerInterfaceInfoT _peer_interfaces[SM_INTERFACE_PEER_MAX];
|
|
|
|
// Transmit and Receive Statistics
|
|
static uint64_t _rcvd_total_msgs = 0;
|
|
static uint64_t _rcvd_msgs_while_disabled = 0;
|
|
static uint64_t _rcvd_bad_msg_auth = 0;
|
|
static uint64_t _rcvd_bad_msg_version = 0;
|
|
static uint64_t _send_node_hello_cnt = 0;
|
|
static uint64_t _rcvd_node_hello_cnt = 0;
|
|
static uint64_t _send_node_update_cnt = 0;
|
|
static uint64_t _rcvd_node_update_cnt = 0;
|
|
static uint64_t _send_node_swact_cnt = 0;
|
|
static uint64_t _rcvd_node_swact_cnt = 0;
|
|
static uint64_t _send_node_swact_ack_cnt = 0;
|
|
static uint64_t _rcvd_node_swact_ack_cnt = 0;
|
|
static uint64_t _send_service_domain_hello_cnt = 0;
|
|
static uint64_t _rcvd_service_domain_hello_cnt = 0;
|
|
static uint64_t _send_service_domain_pause_cnt = 0;
|
|
static uint64_t _rcvd_service_domain_pause_cnt = 0;
|
|
static uint64_t _send_service_domain_exchange_start_cnt = 0;
|
|
static uint64_t _rcvd_service_domain_exchange_start_cnt = 0;
|
|
static uint64_t _send_service_domain_exchange_cnt = 0;
|
|
static uint64_t _rcvd_service_domain_exchange_cnt = 0;
|
|
static uint64_t _send_service_domain_member_request_cnt = 0;
|
|
static uint64_t _rcvd_service_domain_member_request_cnt = 0;
|
|
static uint64_t _send_service_domain_member_update_cnt = 0;
|
|
static uint64_t _rcvd_service_domain_member_update_cnt = 0;
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Find Peer Node Info
|
|
// ===============================
|
|
static SmMsgPeerNodeInfoT* sm_msg_find_peer_node_info( char node_name[] )
|
|
{
|
|
SmMsgPeerNodeInfoT* entry;
|
|
|
|
unsigned int entry_i;
|
|
for( entry_i=0; SM_NODE_MAX > entry_i; ++entry_i )
|
|
{
|
|
entry = &(_peers[entry_i]);
|
|
|
|
if( entry->inuse )
|
|
{
|
|
if( 0 == strcmp( node_name, entry->node_name ) )
|
|
{
|
|
return( entry );
|
|
}
|
|
}
|
|
}
|
|
|
|
return( NULL );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - In Sequence
|
|
// =======================
|
|
static bool sm_msg_in_sequence( char node_name[],
|
|
SmUuidT msg_instance, uint64_t msg_seq_num )
|
|
{
|
|
bool in_sequence = false;
|
|
SmMsgPeerNodeInfoT* entry;
|
|
|
|
entry = sm_msg_find_peer_node_info( node_name );
|
|
if( NULL == entry )
|
|
{
|
|
// Cheap way of aging out entries when the maximum node limit is
|
|
// reached.
|
|
entry = &(_peers[_next_free_peer_entry++]);
|
|
if( _next_free_peer_entry >= SM_NODE_MAX )
|
|
{
|
|
_next_free_peer_entry = 0;
|
|
}
|
|
|
|
entry->inuse = true;
|
|
snprintf( entry->node_name, sizeof(entry->node_name), "%s",
|
|
node_name );
|
|
snprintf( entry->msg_instance, sizeof(entry->msg_instance),
|
|
"%s", msg_instance );
|
|
entry->msg_last_seq_num = msg_seq_num;
|
|
in_sequence = true;
|
|
|
|
DPRINTFI( "Message instance (%s) for node (%s) set.", msg_instance,
|
|
node_name );
|
|
} else {
|
|
if( 0 == strcmp( msg_instance, entry->msg_instance ) )
|
|
{
|
|
uint64_t delta;
|
|
|
|
if( msg_seq_num > entry->msg_last_seq_num )
|
|
{
|
|
delta = msg_seq_num- entry->msg_last_seq_num;
|
|
if( SM_MSG_MAX_SEQ_DELTA < delta )
|
|
{
|
|
DPRINTFI( "Message sequence delta (%" PRIu64 ") too large "
|
|
"for message instance (%s) from node (%s), "
|
|
"rcvd_seq=%" PRIu64 ", last_recvd_seq=%" PRIu64 ".",
|
|
delta, entry->msg_instance, node_name,
|
|
msg_seq_num, entry->msg_last_seq_num );
|
|
}
|
|
|
|
entry->msg_last_seq_num = msg_seq_num;
|
|
in_sequence = true;
|
|
|
|
} else {
|
|
delta = entry->msg_last_seq_num - msg_seq_num;
|
|
|
|
if( SM_MSG_MAX_SEQ_DELTA < delta )
|
|
{
|
|
DPRINTFI( "Message sequence delta (%" PRIu64 ") too large "
|
|
"for message instance (%s) from node (%s), "
|
|
"rcvd_seq=%" PRIu64 ", last_recvd_seq=%" PRIu64 ".",
|
|
delta, entry->msg_instance, node_name,
|
|
msg_seq_num, entry->msg_last_seq_num );
|
|
|
|
entry->msg_last_seq_num = msg_seq_num;
|
|
in_sequence = true;
|
|
}
|
|
}
|
|
} else {
|
|
DPRINTFI( "Message instance (%s) changed for node (%s), now=%s.",
|
|
entry->msg_instance, node_name, msg_instance );
|
|
|
|
snprintf( entry->msg_instance, sizeof(entry->msg_instance),
|
|
"%s", msg_instance );
|
|
entry->msg_last_seq_num = msg_seq_num;
|
|
in_sequence = true;
|
|
}
|
|
}
|
|
|
|
return( in_sequence );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Add Peer Interface
|
|
// ==============================
|
|
SmErrorT sm_msg_add_peer_interface( char interface_name[],
|
|
SmNetworkAddressT* network_address, int network_port,
|
|
SmAuthTypeT auth_type, char auth_key[] )
|
|
{
|
|
bool found = false;
|
|
SmMsgPeerInterfaceInfoT* entry;
|
|
|
|
unsigned int entry_i;
|
|
for( entry_i=0; SM_INTERFACE_PEER_MAX > entry_i; ++entry_i )
|
|
{
|
|
entry = &(_peer_interfaces[entry_i]);
|
|
|
|
if( !(entry->inuse) )
|
|
continue;
|
|
|
|
if( 0 != strcmp( interface_name, entry->interface_name ) )
|
|
continue;
|
|
|
|
if( network_address->type != entry->network_address.type )
|
|
continue;
|
|
|
|
if( SM_NETWORK_TYPE_IPV4 == network_address->type )
|
|
{
|
|
if( network_address->u.ipv4.sin.s_addr
|
|
== entry->network_address.u.ipv4.sin.s_addr )
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
} else if( SM_NETWORK_TYPE_IPV4_UDP == network_address->type ) {
|
|
if(( network_address->u.ipv4.sin.s_addr
|
|
== entry->network_address.u.ipv4.sin.s_addr )&&
|
|
( network_port == entry->network_port ))
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
} else if( SM_NETWORK_TYPE_IPV6 == network_address->type ) {
|
|
if( 0 != memcmp( &( network_address->u.ipv6.sin6 ),
|
|
&( entry->network_address.u.ipv6.sin6 ),
|
|
sizeof(struct in6_addr) ))
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
} else if( SM_NETWORK_TYPE_IPV6_UDP == network_address->type ) {
|
|
if(( 0 != memcmp( &( network_address->u.ipv6.sin6 ),
|
|
&( entry->network_address.u.ipv6.sin6 ),
|
|
sizeof(struct in6_addr) ))&&
|
|
( network_port == entry->network_port ))
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !found )
|
|
{
|
|
for( entry_i=0; SM_INTERFACE_PEER_MAX > entry_i; ++entry_i )
|
|
{
|
|
entry = &(_peer_interfaces[entry_i]);
|
|
|
|
if( !(entry->inuse) )
|
|
{
|
|
entry->inuse = true;
|
|
snprintf( entry->interface_name, sizeof(entry->interface_name),
|
|
"%s", interface_name );
|
|
memcpy( &(entry->network_address), network_address,
|
|
sizeof(SmNetworkAddressT) );
|
|
entry->network_port = network_port;
|
|
entry->auth_type = auth_type;
|
|
memcpy( entry->auth_key, auth_key,
|
|
SM_AUTHENTICATION_KEY_MAX_CHAR );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Delete Peer Interface
|
|
// =================================
|
|
SmErrorT sm_msg_delete_peer_interface( char interface_name[],
|
|
SmNetworkAddressT* network_address, int network_port )
|
|
{
|
|
SmMsgPeerInterfaceInfoT* entry;
|
|
|
|
unsigned int entry_i;
|
|
for( entry_i=0; SM_INTERFACE_PEER_MAX > entry_i; ++entry_i )
|
|
{
|
|
entry = &(_peer_interfaces[entry_i]);
|
|
|
|
if( !(entry->inuse) )
|
|
continue;
|
|
|
|
if( 0 != strcmp( interface_name, entry->interface_name ) )
|
|
continue;
|
|
|
|
if( network_address->type != entry->network_address.type )
|
|
continue;
|
|
|
|
if( SM_NETWORK_TYPE_IPV4 == network_address->type )
|
|
{
|
|
if( network_address->u.ipv4.sin.s_addr
|
|
== entry->network_address.u.ipv4.sin.s_addr )
|
|
{
|
|
memset( entry, 0, sizeof(SmMsgPeerInterfaceInfoT) );
|
|
break;
|
|
}
|
|
} else if( SM_NETWORK_TYPE_IPV4_UDP == network_address->type ) {
|
|
if(( network_address->u.ipv4.sin.s_addr
|
|
== entry->network_address.u.ipv4.sin.s_addr )&&
|
|
( network_port == entry->network_port ))
|
|
{
|
|
memset( entry, 0, sizeof(SmMsgPeerInterfaceInfoT) );
|
|
break;
|
|
}
|
|
} else if( SM_NETWORK_TYPE_IPV6 == network_address->type ) {
|
|
if( 0 != memcmp( &(network_address->u.ipv6.sin6),
|
|
&(entry->network_address.u.ipv6.sin6),
|
|
sizeof(in6_addr) ))
|
|
{
|
|
memset( entry, 0, sizeof(SmMsgPeerInterfaceInfoT) );
|
|
break;
|
|
}
|
|
} else if( SM_NETWORK_TYPE_IPV6_UDP == network_address->type ) {
|
|
if(( 0 != memcmp( &(network_address->u.ipv6.sin6),
|
|
&(entry->network_address.u.ipv6.sin6),
|
|
sizeof(in6_addr) ))&&
|
|
( network_port == entry->network_port ))
|
|
{
|
|
memset( entry, 0, sizeof(SmMsgPeerInterfaceInfoT) );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Get Peer Interface
|
|
// ==============================
|
|
static SmMsgPeerInterfaceInfoT* sm_msg_get_peer_interface(
|
|
char interface_name[], SmNetworkAddressT* network_address,
|
|
int network_port )
|
|
{
|
|
SmMsgPeerInterfaceInfoT* entry;
|
|
in6_addr empty_ipv6_address;
|
|
|
|
unsigned int entry_i;
|
|
for( entry_i=0; SM_INTERFACE_PEER_MAX > entry_i; ++entry_i )
|
|
{
|
|
entry = &(_peer_interfaces[entry_i]);
|
|
|
|
if( !(entry->inuse) )
|
|
continue;
|
|
|
|
if( 0 != strcmp( interface_name, entry->interface_name ) )
|
|
continue;
|
|
|
|
if( SM_NETWORK_TYPE_IPV4 == entry->network_address.type )
|
|
{
|
|
if( 0 == entry->network_address.u.ipv4.sin.s_addr )
|
|
{
|
|
return( entry );
|
|
|
|
} else if( network_address->u.ipv4.sin.s_addr
|
|
== entry->network_address.u.ipv4.sin.s_addr )
|
|
{
|
|
return( entry );
|
|
}
|
|
} else if( SM_NETWORK_TYPE_IPV4_UDP == entry->network_address.type ) {
|
|
if( 0 == entry->network_address.u.ipv4.sin.s_addr )
|
|
{
|
|
return( entry );
|
|
|
|
} else if( -1 == entry->network_port )
|
|
{
|
|
return( entry );
|
|
|
|
} else if(( network_address->u.ipv4.sin.s_addr
|
|
== entry->network_address.u.ipv4.sin.s_addr )&&
|
|
( network_port == entry->network_port ))
|
|
{
|
|
return( entry );
|
|
}
|
|
} else if( SM_NETWORK_TYPE_IPV6 == entry->network_address.type ) {
|
|
memset( &empty_ipv6_address, 0, sizeof(in6_addr) );
|
|
if( 0 == memcmp( &(entry->network_address.u.ipv6.sin6),
|
|
&(empty_ipv6_address),
|
|
sizeof(in6_addr) ))
|
|
{
|
|
return( entry );
|
|
|
|
} else if( 0 == memcmp( &(network_address->u.ipv6.sin6),
|
|
&(entry->network_address.u.ipv6.sin6),
|
|
sizeof(in6_addr) ))
|
|
{
|
|
return( entry );
|
|
}
|
|
} else if( SM_NETWORK_TYPE_IPV6_UDP == entry->network_address.type ) {
|
|
memset( &empty_ipv6_address, 0, sizeof(in6_addr) );
|
|
if( 0 == memcmp( &(entry->network_address.u.ipv6.sin6),
|
|
&(empty_ipv6_address),
|
|
sizeof(in6_addr) ))
|
|
{
|
|
return( entry );
|
|
|
|
} else if( -1 == entry->network_port )
|
|
{
|
|
return( entry );
|
|
|
|
} else if(( 0 == memcmp( &(network_address->u.ipv6.sin6),
|
|
&(entry->network_address.u.ipv6.sin6),
|
|
sizeof(in6_addr) ))&&
|
|
( network_port == entry->network_port ))
|
|
{
|
|
return( entry );
|
|
}
|
|
}
|
|
}
|
|
|
|
return( NULL );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Little Endian Network To Host Byte Order For Uint64
|
|
// ===============================================================
|
|
uint64_t sm_msg_little_endian_ntohll( uint64_t i )
|
|
{
|
|
uint32_t tmp;
|
|
|
|
union
|
|
{
|
|
uint64_t uint64;
|
|
struct
|
|
{
|
|
uint32_t word0;
|
|
uint32_t word1;
|
|
} uint32;
|
|
} u;
|
|
|
|
u.uint64 = i;
|
|
|
|
u.uint32.word0 = ntohl( u.uint32.word0 );
|
|
u.uint32.word1 = ntohl( u.uint32.word1 );
|
|
|
|
tmp = u.uint32.word0;
|
|
u.uint32.word0 = u.uint32.word1;
|
|
u.uint32.word1 = tmp;
|
|
|
|
return( u.uint64 );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Little Endian Host To Network Byte Order For Uint64
|
|
// ===============================================================
|
|
uint64_t sm_msg_little_endian_htonll( uint64_t i )
|
|
{
|
|
uint32_t tmp;
|
|
|
|
union
|
|
{
|
|
uint64_t uint64;
|
|
struct
|
|
{
|
|
uint32_t word0;
|
|
uint32_t word1;
|
|
} uint32;
|
|
} u;
|
|
|
|
u.uint64 = i;
|
|
|
|
u.uint32.word0 = htonl( u.uint32.word0 );
|
|
u.uint32.word1 = htonl( u.uint32.word1 );
|
|
|
|
tmp = u.uint32.word0;
|
|
u.uint32.word0 = u.uint32.word1;
|
|
u.uint32.word1 = tmp;
|
|
|
|
return( u.uint64 );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Enable
|
|
// ==================
|
|
void sm_msg_enable( void )
|
|
{
|
|
_messaging_enabled = true;
|
|
|
|
DPRINTFI( "Messaging is now enabled." );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Disable
|
|
// ===================
|
|
void sm_msg_disable( void )
|
|
{
|
|
_messaging_enabled = false;
|
|
|
|
DPRINTFI( "Messaging is now disabled." );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Register Callbacks
|
|
// ==============================
|
|
SmErrorT sm_msg_register_callbacks( SmMsgCallbacksT* callbacks )
|
|
{
|
|
SM_LIST_PREPEND( _callbacks, (SmListEntryDataPtrT) callbacks );
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Deregister Callbacks
|
|
// ================================
|
|
SmErrorT sm_msg_deregister_callbacks( SmMsgCallbacksT* callbacks )
|
|
{
|
|
SM_LIST_REMOVE( _callbacks, (SmListEntryDataPtrT) callbacks );
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Increment Sequence Number
|
|
// =====================================
|
|
void sm_msg_increment_seq_num( void )
|
|
{
|
|
++_msg_seq_num;
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Send message from IPv6 source
|
|
// ==========================================
|
|
static int sm_msg_sendmsg_src_ipv6( int socket, void* msg, size_t msg_len,
|
|
int flags, struct sockaddr_in6* dst_addr, struct in6_addr* src_Addr )
|
|
{
|
|
struct msghdr msg_hdr = {};
|
|
struct cmsghdr *cmsg;
|
|
struct in6_pktinfo *pktinfo;
|
|
struct iovec iov = {msg, msg_len};
|
|
|
|
memset( &_tx_control_buffer, 0, sizeof(_tx_control_buffer) );
|
|
msg_hdr.msg_iov = &iov;
|
|
msg_hdr.msg_iovlen = 1;
|
|
msg_hdr.msg_name = dst_addr;
|
|
msg_hdr.msg_namelen = sizeof(struct sockaddr_in6);
|
|
msg_hdr.msg_control = _tx_control_buffer;
|
|
msg_hdr.msg_controllen = CMSG_LEN( sizeof(struct in6_pktinfo) );
|
|
cmsg = CMSG_FIRSTHDR( &msg_hdr );
|
|
cmsg->cmsg_level = IPPROTO_IPV6;
|
|
cmsg->cmsg_type = IPV6_PKTINFO;
|
|
cmsg->cmsg_len = CMSG_LEN( sizeof(struct in6_pktinfo) );
|
|
pktinfo = (struct in6_pktinfo*) CMSG_DATA( cmsg );
|
|
pktinfo->ipi6_ifindex = 0;
|
|
pktinfo->ipi6_addr = *src_Addr;
|
|
|
|
return sendmsg( socket, &msg_hdr, flags );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
static int sm_send_msg(SmServiceDomainInterfaceT* interface, SmMsgT* msg )
|
|
{
|
|
struct sockaddr_in dst_addr4;
|
|
int result = -1;
|
|
SmIpv4AddressT* ipv4_dst;
|
|
|
|
memset( &dst_addr4, 0, sizeof(dst_addr4) );
|
|
dst_addr4.sin_family = AF_INET;
|
|
dst_addr4.sin_port = htons(interface->network_port);
|
|
|
|
if ( SM_INTERFACE_OAM != interface->interface_type )
|
|
{
|
|
ipv4_dst = &(interface->network_multicast.u.ipv4);
|
|
}
|
|
else
|
|
{
|
|
ipv4_dst = &(interface->network_peer_address.u.ipv4);
|
|
}
|
|
|
|
if( 0 == ipv4_dst->sin.s_addr )
|
|
{
|
|
//don't send to 0.0.0.0
|
|
return _MSG_NOT_SENT_TO_TARGET;
|
|
}
|
|
dst_addr4.sin_addr.s_addr = ipv4_dst->sin.s_addr;
|
|
|
|
result = sendto( interface->unicast_socket, msg, sizeof(SmMsgT),
|
|
0, (struct sockaddr *) &dst_addr4, sizeof(dst_addr4) );
|
|
|
|
return result;
|
|
}
|
|
|
|
static int sm_send_ipv6_msg(SmServiceDomainInterfaceT* interface, SmMsgT* msg )
|
|
{
|
|
struct sockaddr_in6 dst_addr6;
|
|
int result = -1;
|
|
SmIpv6AddressT* ipv6_dst;
|
|
|
|
memset( &dst_addr6, 0, sizeof(dst_addr6) );
|
|
dst_addr6.sin6_family = AF_INET6;
|
|
dst_addr6.sin6_port = htons(interface->network_port);
|
|
|
|
if ( SM_INTERFACE_OAM != interface->interface_type )
|
|
{
|
|
ipv6_dst = &(interface->network_multicast.u.ipv6);
|
|
}else
|
|
{
|
|
ipv6_dst = &(interface->network_peer_address.u.ipv6);
|
|
}
|
|
dst_addr6.sin6_addr = ipv6_dst->sin6;
|
|
result = sm_msg_sendmsg_src_ipv6( interface->unicast_socket, msg, sizeof(SmMsgT),
|
|
0, &dst_addr6, &interface->network_address.u.ipv6.sin6 );
|
|
|
|
return result;
|
|
}
|
|
// ****************************************************************************
|
|
// Messaging - Send Node Hello
|
|
// ===========================
|
|
SmErrorT sm_msg_send_node_hello( char node_name[],
|
|
SmNodeAdminStateT admin_state, SmNodeOperationalStateT oper_state,
|
|
SmNodeAvailStatusT avail_status, SmNodeReadyStateT ready_state,
|
|
SmUuidT state_uuid, long uptime, SmServiceDomainInterfaceT* interface )
|
|
{
|
|
SmMsgT* msg = (SmMsgT*) _tx_buffer;
|
|
SmMsgNodeHelloT* hello_msg = &(msg->u.node_hello);
|
|
int result = -1;
|
|
|
|
memset( _tx_buffer, 0, sizeof(_tx_buffer) );
|
|
|
|
msg->header.version = htons(SM_VERSION);
|
|
msg->header.revision = htons(SM_REVISION);
|
|
msg->header.max_supported_version = htons(SM_VERSION);
|
|
msg->header.max_supported_revision = htons(SM_REVISION);
|
|
msg->header.msg_len = htons(sizeof(SmMsgT));
|
|
msg->header.msg_type = htons(SM_MSG_TYPE_NODE_HELLO);
|
|
msg->header.msg_flags = htonll(0);
|
|
snprintf( msg->header.msg_instance, sizeof(msg->header.msg_instance),
|
|
"%s", _msg_instance );
|
|
msg->header.msg_seq_num = htonll(_msg_seq_num);
|
|
snprintf( msg->header.node_name, sizeof(msg->header.node_name),
|
|
"%s", _hostname );
|
|
|
|
snprintf( hello_msg->node_name, sizeof(hello_msg->node_name),
|
|
"%s", node_name );
|
|
snprintf( hello_msg->admin_state, sizeof(hello_msg->admin_state),
|
|
"%s", sm_node_admin_state_str(admin_state) );
|
|
snprintf( hello_msg->oper_state, sizeof(hello_msg->oper_state),
|
|
"%s", sm_node_oper_state_str(oper_state) );
|
|
snprintf( hello_msg->avail_status, sizeof(hello_msg->avail_status),
|
|
"%s", sm_node_avail_status_str(avail_status) );
|
|
snprintf( hello_msg->ready_state, sizeof(hello_msg->ready_state),
|
|
"%s", sm_node_ready_state_str(ready_state) );
|
|
snprintf( hello_msg->state_uuid, sizeof(hello_msg->state_uuid),
|
|
"%s", state_uuid );
|
|
hello_msg->uptime = htonl(uptime);
|
|
|
|
if( SM_AUTH_TYPE_HMAC_SHA512 == interface->auth_type )
|
|
{
|
|
SmSha512HashT hash;
|
|
|
|
msg->header.auth_type = htonl(interface->auth_type);
|
|
sm_sha512_hmac( msg, sizeof(SmMsgT), interface->auth_key,
|
|
strlen(interface->auth_key), &hash );
|
|
memcpy( &(msg->header.auth_vector[0]), &(hash.bytes[0]),
|
|
SM_SHA512_HASH_SIZE );
|
|
} else {
|
|
msg->header.auth_type = htonl(SM_AUTH_TYPE_NONE);
|
|
}
|
|
|
|
if(( SM_NETWORK_TYPE_IPV4_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV4 == interface->network_type ))
|
|
{
|
|
result = sm_send_msg(interface, msg);
|
|
} else if(( SM_NETWORK_TYPE_IPV6_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV6 == interface->network_type ))
|
|
{
|
|
result = sm_send_ipv6_msg(interface, msg);
|
|
}
|
|
|
|
if( 0 > result )
|
|
{
|
|
if ( _MSG_NOT_SENT_TO_TARGET != result )
|
|
{
|
|
DPRINTFE( "Failed to send message on socket for interface (%s), "
|
|
"error=%s.", interface->interface_name, strerror( errno ) );
|
|
return( SM_FAILED );
|
|
}
|
|
return( SM_OKAY );
|
|
}
|
|
|
|
++_send_node_hello_cnt;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Send Node Update
|
|
// ============================
|
|
SmErrorT sm_msg_send_node_update( char node_name[],
|
|
SmNodeAdminStateT admin_state, SmNodeOperationalStateT oper_state,
|
|
SmNodeAvailStatusT avail_status, SmNodeReadyStateT ready_state,
|
|
SmUuidT old_state_uuid, SmUuidT state_uuid, long uptime, bool force,
|
|
SmServiceDomainInterfaceT* interface )
|
|
{
|
|
SmMsgT* msg = (SmMsgT*) _tx_buffer;
|
|
SmMsgNodeUpdateT* update_msg = &(msg->u.node_update);
|
|
int result = -1;
|
|
|
|
memset( _tx_buffer, 0, sizeof(_tx_buffer) );
|
|
|
|
msg->header.version = htons(SM_VERSION);
|
|
msg->header.revision = htons(SM_REVISION);
|
|
msg->header.max_supported_version = htons(SM_VERSION);
|
|
msg->header.max_supported_revision = htons(SM_REVISION);
|
|
msg->header.msg_len = htons(sizeof(SmMsgT));
|
|
msg->header.msg_type = htons(SM_MSG_TYPE_NODE_UPDATE);
|
|
msg->header.msg_flags = htonll(0);
|
|
snprintf( msg->header.msg_instance, sizeof(msg->header.msg_instance),
|
|
"%s", _msg_instance );
|
|
msg->header.msg_seq_num = htonll(_msg_seq_num);
|
|
snprintf( msg->header.node_name, sizeof(msg->header.node_name),
|
|
"%s", _hostname );
|
|
|
|
snprintf( update_msg->node_name, sizeof(update_msg->node_name),
|
|
"%s", node_name );
|
|
snprintf( update_msg->admin_state, sizeof(update_msg->admin_state),
|
|
"%s", sm_node_admin_state_str(admin_state) );
|
|
snprintf( update_msg->oper_state, sizeof(update_msg->oper_state),
|
|
"%s", sm_node_oper_state_str(oper_state) );
|
|
snprintf( update_msg->avail_status, sizeof(update_msg->avail_status),
|
|
"%s", sm_node_avail_status_str(avail_status) );
|
|
snprintf( update_msg->ready_state, sizeof(update_msg->ready_state),
|
|
"%s", sm_node_ready_state_str(ready_state) );
|
|
snprintf( update_msg->old_state_uuid,
|
|
sizeof(update_msg->old_state_uuid), "%s", old_state_uuid );
|
|
snprintf( update_msg->state_uuid, sizeof(update_msg->state_uuid),
|
|
"%s", state_uuid );
|
|
update_msg->uptime = htonl(uptime);
|
|
update_msg->force = htonl(force);
|
|
|
|
if( SM_AUTH_TYPE_HMAC_SHA512 == interface->auth_type )
|
|
{
|
|
SmSha512HashT hash;
|
|
|
|
msg->header.auth_type = htonl(interface->auth_type);
|
|
sm_sha512_hmac( msg, sizeof(SmMsgT), interface->auth_key,
|
|
strlen(interface->auth_key), &hash );
|
|
memcpy( &(msg->header.auth_vector[0]), &(hash.bytes[0]),
|
|
SM_SHA512_HASH_SIZE );
|
|
} else {
|
|
msg->header.auth_type = htonl(SM_AUTH_TYPE_NONE);
|
|
}
|
|
|
|
if(( SM_NETWORK_TYPE_IPV4_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV4 == interface->network_type ))
|
|
{
|
|
result = sm_send_msg(interface, msg);
|
|
} else if(( SM_NETWORK_TYPE_IPV6_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV6 == interface->network_type ))
|
|
{
|
|
result = sm_send_ipv6_msg(interface, msg);
|
|
}
|
|
if( 0 > result )
|
|
{
|
|
if ( _MSG_NOT_SENT_TO_TARGET != result )
|
|
{
|
|
DPRINTFE( "Failed to send message on socket for interface (%s), "
|
|
"error=%s.", interface->interface_name, strerror( errno ) );
|
|
return( SM_FAILED );
|
|
}
|
|
return( SM_OKAY );
|
|
}
|
|
|
|
++_send_node_update_cnt;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Send Node Swact
|
|
// ===========================
|
|
SmErrorT sm_msg_send_node_swact( char node_name[], bool force,
|
|
SmUuidT request_uuid, SmServiceDomainInterfaceT* interface )
|
|
{
|
|
SmMsgT* msg = (SmMsgT*) _tx_buffer;
|
|
SmMsgNodeSwactT* swact_msg = &(msg->u.node_swact);
|
|
int result = -1;
|
|
|
|
memset( _tx_buffer, 0, sizeof(_tx_buffer) );
|
|
|
|
msg->header.version = htons(SM_VERSION);
|
|
msg->header.revision = htons(SM_REVISION);
|
|
msg->header.max_supported_version = htons(SM_VERSION);
|
|
msg->header.max_supported_revision = htons(SM_REVISION);
|
|
msg->header.msg_len = htons(sizeof(SmMsgT));
|
|
msg->header.msg_type = htons(SM_MSG_TYPE_NODE_SWACT);
|
|
msg->header.msg_flags = htonll(0);
|
|
snprintf( msg->header.msg_instance, sizeof(msg->header.msg_instance),
|
|
"%s", _msg_instance );
|
|
msg->header.msg_seq_num = htonll(_msg_seq_num);
|
|
snprintf( msg->header.node_name, sizeof(msg->header.node_name),
|
|
"%s", _hostname );
|
|
|
|
snprintf( swact_msg->node_name, sizeof(swact_msg->node_name),
|
|
"%s", node_name );
|
|
snprintf( swact_msg->request_uuid, sizeof(swact_msg->request_uuid),
|
|
"%s", request_uuid );
|
|
swact_msg->force = htonl(force);
|
|
|
|
if( SM_AUTH_TYPE_HMAC_SHA512 == interface->auth_type )
|
|
{
|
|
SmSha512HashT hash;
|
|
|
|
msg->header.auth_type = htonl(interface->auth_type);
|
|
sm_sha512_hmac( msg, sizeof(SmMsgT), interface->auth_key,
|
|
strlen(interface->auth_key), &hash );
|
|
memcpy( &(msg->header.auth_vector[0]), &(hash.bytes[0]),
|
|
SM_SHA512_HASH_SIZE );
|
|
} else {
|
|
msg->header.auth_type = htonl(SM_AUTH_TYPE_NONE);
|
|
}
|
|
|
|
if(( SM_NETWORK_TYPE_IPV4_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV4 == interface->network_type ))
|
|
{
|
|
result = sm_send_msg(interface, msg);
|
|
} else if(( SM_NETWORK_TYPE_IPV6_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV6 == interface->network_type ))
|
|
{
|
|
result = sm_send_ipv6_msg(interface, msg);
|
|
}
|
|
|
|
if( 0 > result )
|
|
{
|
|
if ( _MSG_NOT_SENT_TO_TARGET != result )
|
|
{
|
|
DPRINTFE( "Failed to send message on socket for interface (%s), "
|
|
"error=%s.", interface->interface_name, strerror( errno ) );
|
|
return( SM_FAILED );
|
|
}
|
|
return( SM_OKAY );
|
|
}
|
|
|
|
++_send_node_swact_cnt;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Send Node Swact Ack
|
|
// ===============================
|
|
SmErrorT sm_msg_send_node_swact_ack( char node_name[], bool force,
|
|
SmUuidT request_uuid, SmServiceDomainInterfaceT* interface )
|
|
{
|
|
SmMsgT* msg = (SmMsgT*) _tx_buffer;
|
|
SmMsgNodeSwactAckT* swact_ack_msg = NULL;
|
|
int result = -1;
|
|
|
|
swact_ack_msg = &(msg->u.node_swact_ack);
|
|
|
|
memset( _tx_buffer, 0, sizeof(_tx_buffer) );
|
|
|
|
msg->header.version = htons(SM_VERSION);
|
|
msg->header.revision = htons(SM_REVISION);
|
|
msg->header.max_supported_version = htons(SM_VERSION);
|
|
msg->header.max_supported_revision = htons(SM_REVISION);
|
|
msg->header.msg_len = htons(sizeof(SmMsgT));
|
|
msg->header.msg_type = htons(SM_MSG_TYPE_NODE_SWACT_ACK);
|
|
msg->header.msg_flags = htonll(0);
|
|
snprintf( msg->header.msg_instance, sizeof(msg->header.msg_instance),
|
|
"%s", _msg_instance );
|
|
msg->header.msg_seq_num = htonll(_msg_seq_num);
|
|
snprintf( msg->header.node_name, sizeof(msg->header.node_name),
|
|
"%s", _hostname );
|
|
|
|
snprintf( swact_ack_msg->node_name,
|
|
sizeof(swact_ack_msg->node_name), "%s", node_name );
|
|
snprintf( swact_ack_msg->request_uuid,
|
|
sizeof(swact_ack_msg->request_uuid), "%s", request_uuid );
|
|
swact_ack_msg->force = htonl(force);
|
|
|
|
if( SM_AUTH_TYPE_HMAC_SHA512 == interface->auth_type )
|
|
{
|
|
SmSha512HashT hash;
|
|
|
|
msg->header.auth_type = htonl(interface->auth_type);
|
|
sm_sha512_hmac( msg, sizeof(SmMsgT), interface->auth_key,
|
|
strlen(interface->auth_key), &hash );
|
|
memcpy( &(msg->header.auth_vector[0]), &(hash.bytes[0]),
|
|
SM_SHA512_HASH_SIZE );
|
|
} else {
|
|
msg->header.auth_type = htonl(SM_AUTH_TYPE_NONE);
|
|
}
|
|
|
|
if(( SM_NETWORK_TYPE_IPV4_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV4 == interface->network_type ))
|
|
{
|
|
result = sm_send_msg(interface, msg);
|
|
} else if(( SM_NETWORK_TYPE_IPV6_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV6 == interface->network_type ))
|
|
{
|
|
result = sm_send_ipv6_msg(interface, msg);
|
|
}
|
|
|
|
if( 0 > result )
|
|
{
|
|
if ( _MSG_NOT_SENT_TO_TARGET != result )
|
|
{
|
|
DPRINTFE( "Failed to send message on socket for interface (%s), "
|
|
"error=%s.", interface->interface_name, strerror( errno ) );
|
|
return( SM_FAILED );
|
|
}
|
|
return( SM_OKAY );
|
|
}
|
|
|
|
++_send_node_swact_ack_cnt;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Send Service Domain Hello
|
|
// =====================================
|
|
SmErrorT sm_msg_send_service_domain_hello( char node_name[],
|
|
SmOrchestrationTypeT orchestration, SmDesignationTypeT designation,
|
|
int generation, int priority, int hello_interval, int dead_interval,
|
|
int wait_interval, int exchange_interval, char leader[],
|
|
SmServiceDomainInterfaceT* interface )
|
|
{
|
|
SmMsgT* msg = (SmMsgT*) _tx_buffer;
|
|
SmMsgServiceDomainHelloT* hello_msg = &(msg->u.hello);
|
|
int result = -1;
|
|
|
|
memset( _tx_buffer, 0, sizeof(_tx_buffer) );
|
|
|
|
msg->header.version = htons(SM_VERSION);
|
|
msg->header.revision = htons(SM_REVISION);
|
|
msg->header.max_supported_version = htons(SM_VERSION);
|
|
msg->header.max_supported_revision = htons(SM_REVISION);
|
|
msg->header.msg_len = htons(sizeof(SmMsgT));
|
|
msg->header.msg_type = htons(SM_MSG_TYPE_SERVICE_DOMAIN_HELLO);
|
|
msg->header.msg_flags = htonll(0);
|
|
snprintf( msg->header.msg_instance, sizeof(msg->header.msg_instance),
|
|
"%s", _msg_instance );
|
|
msg->header.msg_seq_num = htonll(_msg_seq_num);
|
|
snprintf( msg->header.node_name, sizeof(msg->header.node_name),
|
|
"%s", _hostname );
|
|
|
|
snprintf( hello_msg->service_domain, sizeof(hello_msg->service_domain),
|
|
"%s", interface->service_domain );
|
|
snprintf( hello_msg->node_name, sizeof(hello_msg->node_name),
|
|
"%s", node_name );
|
|
snprintf( hello_msg->orchestration, sizeof(hello_msg->orchestration),
|
|
"%s", sm_orchestration_type_str(orchestration) );
|
|
snprintf( hello_msg->designation, sizeof(hello_msg->designation),
|
|
"%s", sm_designation_type_str(designation) );
|
|
hello_msg->generation = htonl(generation);
|
|
hello_msg->priority = htonl(priority);
|
|
hello_msg->hello_interval = htonl(hello_interval);
|
|
hello_msg->dead_interval = htonl(dead_interval);
|
|
hello_msg->wait_interval = htonl(wait_interval);
|
|
hello_msg->exchange_interval = htonl(exchange_interval);
|
|
snprintf( hello_msg->leader, sizeof(hello_msg->leader), "%s", leader );
|
|
|
|
if( SM_AUTH_TYPE_HMAC_SHA512 == interface->auth_type )
|
|
{
|
|
SmSha512HashT hash;
|
|
|
|
msg->header.auth_type = htonl(interface->auth_type);
|
|
sm_sha512_hmac( msg, sizeof(SmMsgT), interface->auth_key,
|
|
strlen(interface->auth_key), &hash );
|
|
memcpy( &(msg->header.auth_vector[0]), &(hash.bytes[0]),
|
|
SM_SHA512_HASH_SIZE );
|
|
} else {
|
|
msg->header.auth_type = htonl(SM_AUTH_TYPE_NONE);
|
|
}
|
|
|
|
if(( SM_NETWORK_TYPE_IPV4_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV4 == interface->network_type ))
|
|
{
|
|
result = sm_send_msg(interface, msg);
|
|
} else if(( SM_NETWORK_TYPE_IPV6_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV6 == interface->network_type ))
|
|
{
|
|
result = sm_send_ipv6_msg(interface, msg);
|
|
}
|
|
|
|
if( 0 > result )
|
|
{
|
|
if ( _MSG_NOT_SENT_TO_TARGET != result )
|
|
{
|
|
DPRINTFE( "Failed to send message on socket for interface (%s), "
|
|
"error=%s.", interface->interface_name, strerror( errno ) );
|
|
return( SM_FAILED );
|
|
}
|
|
return( SM_OKAY );
|
|
}
|
|
|
|
++_send_service_domain_hello_cnt;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Send Service Domain Pause
|
|
// =====================================
|
|
SmErrorT sm_msg_send_service_domain_pause( char node_name[],
|
|
int pause_interval, SmServiceDomainInterfaceT* interface )
|
|
{
|
|
SmMsgT* msg = (SmMsgT*) _tx_buffer;
|
|
SmMsgServiceDomainPauseT* pause_msg = &(msg->u.pause);
|
|
int result = -1;
|
|
|
|
memset( _tx_buffer, 0, sizeof(_tx_buffer) );
|
|
|
|
msg->header.version = htons(SM_VERSION);
|
|
msg->header.revision = htons(SM_REVISION);
|
|
msg->header.max_supported_version = htons(SM_VERSION);
|
|
msg->header.max_supported_revision = htons(SM_REVISION);
|
|
msg->header.msg_len = htons(sizeof(SmMsgT));
|
|
msg->header.msg_type = htons(SM_MSG_TYPE_SERVICE_DOMAIN_PAUSE);
|
|
msg->header.msg_flags = htonll(0);
|
|
snprintf( msg->header.msg_instance, sizeof(msg->header.msg_instance),
|
|
"%s", _msg_instance );
|
|
msg->header.msg_seq_num = htonll(_msg_seq_num);
|
|
snprintf( msg->header.node_name, sizeof(msg->header.node_name),
|
|
"%s", _hostname );
|
|
|
|
snprintf( pause_msg->service_domain, sizeof(pause_msg->service_domain),
|
|
"%s", interface->service_domain );
|
|
snprintf( pause_msg->node_name, sizeof(pause_msg->node_name),
|
|
"%s", node_name );
|
|
pause_msg->pause_interval = htonl(pause_interval);
|
|
|
|
if( SM_AUTH_TYPE_HMAC_SHA512 == interface->auth_type )
|
|
{
|
|
SmSha512HashT hash;
|
|
|
|
msg->header.auth_type = htonl(interface->auth_type);
|
|
sm_sha512_hmac( msg, sizeof(SmMsgT), interface->auth_key,
|
|
strlen(interface->auth_key), &hash );
|
|
memcpy( &(msg->header.auth_vector[0]), &(hash.bytes[0]),
|
|
SM_SHA512_HASH_SIZE );
|
|
} else {
|
|
msg->header.auth_type = htonl(SM_AUTH_TYPE_NONE);
|
|
}
|
|
|
|
if(( SM_NETWORK_TYPE_IPV4_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV4 == interface->network_type ))
|
|
{
|
|
result = sm_send_msg(interface, msg);
|
|
} else if(( SM_NETWORK_TYPE_IPV6_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV6 == interface->network_type ))
|
|
{
|
|
result = sm_send_ipv6_msg(interface, msg);
|
|
}
|
|
|
|
if( 0 > result )
|
|
{
|
|
if ( _MSG_NOT_SENT_TO_TARGET != result )
|
|
{
|
|
DPRINTFE( "Failed to send message on socket for interface (%s), "
|
|
"error=%s.", interface->interface_name, strerror( errno ) );
|
|
return( SM_FAILED );
|
|
}
|
|
return( SM_OKAY );
|
|
}
|
|
|
|
++_send_service_domain_pause_cnt;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Send Service Domain Exchange Start
|
|
// ==============================================
|
|
SmErrorT sm_msg_send_service_domain_exchange_start( char node_name[],
|
|
char exchange_node_name[], int exchange_seq,
|
|
SmServiceDomainInterfaceT* interface )
|
|
{
|
|
SmMsgT* msg = (SmMsgT*) _tx_buffer;
|
|
SmMsgServiceDomainExchangeStartT* exchange_start_msg;
|
|
int result = -1;
|
|
|
|
exchange_start_msg = &(msg->u.exchange_start);
|
|
|
|
memset( _tx_buffer, 0, sizeof(_tx_buffer) );
|
|
|
|
msg->header.version = htons(SM_VERSION);
|
|
msg->header.revision = htons(SM_REVISION);
|
|
msg->header.max_supported_version = htons(SM_VERSION);
|
|
msg->header.max_supported_revision = htons(SM_REVISION);
|
|
msg->header.msg_len = htons(sizeof(SmMsgT));
|
|
msg->header.msg_type = htons(SM_MSG_TYPE_SERVICE_DOMAIN_EXCHANGE_START);
|
|
msg->header.msg_flags = htonll(0);
|
|
snprintf( msg->header.msg_instance, sizeof(msg->header.msg_instance),
|
|
"%s", _msg_instance );
|
|
msg->header.msg_seq_num = htonll(_msg_seq_num);
|
|
snprintf( msg->header.node_name, sizeof(msg->header.node_name),
|
|
"%s", _hostname );
|
|
|
|
snprintf( exchange_start_msg->service_domain,
|
|
sizeof(exchange_start_msg->service_domain),
|
|
"%s", interface->service_domain );
|
|
snprintf( exchange_start_msg->node_name,
|
|
sizeof(exchange_start_msg->node_name),
|
|
"%s", node_name );
|
|
snprintf( exchange_start_msg->exchange_node_name,
|
|
sizeof(exchange_start_msg->exchange_node_name),
|
|
"%s", exchange_node_name );
|
|
exchange_start_msg->exchange_seq = htonl(exchange_seq);
|
|
|
|
if( SM_AUTH_TYPE_HMAC_SHA512 == interface->auth_type )
|
|
{
|
|
SmSha512HashT hash;
|
|
|
|
msg->header.auth_type = htonl(interface->auth_type);
|
|
sm_sha512_hmac( msg, sizeof(SmMsgT), interface->auth_key,
|
|
strlen(interface->auth_key), &hash );
|
|
memcpy( &(msg->header.auth_vector[0]), &(hash.bytes[0]),
|
|
SM_SHA512_HASH_SIZE );
|
|
} else {
|
|
msg->header.auth_type = htonl(SM_AUTH_TYPE_NONE);
|
|
}
|
|
|
|
if(( SM_NETWORK_TYPE_IPV4_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV4 == interface->network_type ))
|
|
{
|
|
result = sm_send_msg(interface, msg);
|
|
} else if(( SM_NETWORK_TYPE_IPV6_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV6 == interface->network_type ))
|
|
{
|
|
result = sm_send_ipv6_msg(interface, msg);
|
|
}
|
|
|
|
if( 0 > result )
|
|
{
|
|
if ( _MSG_NOT_SENT_TO_TARGET != result )
|
|
{
|
|
DPRINTFE( "Failed to send message on socket for interface (%s), "
|
|
"error=%s.", interface->interface_name, strerror( errno ) );
|
|
return( SM_FAILED );
|
|
}
|
|
return( SM_OKAY );
|
|
}
|
|
|
|
++_send_service_domain_exchange_start_cnt;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Send Service Domain Exchange
|
|
// ========================================
|
|
SmErrorT sm_msg_send_service_domain_exchange( char node_name[],
|
|
char exchange_node_name[], int exchange_seq, int64_t member_id,
|
|
char member_name[], SmServiceGroupStateT member_desired_state,
|
|
SmServiceGroupStateT member_state, SmServiceGroupStatusT member_status,
|
|
SmServiceGroupConditionT member_condition, int64_t member_health,
|
|
char reason_text[], bool more_members, int64_t last_received_member_id,
|
|
SmServiceDomainInterfaceT* interface )
|
|
{
|
|
SmMsgT* msg = (SmMsgT*) _tx_buffer;
|
|
SmMsgServiceDomainExchangeT* exchange_msg = &(msg->u.exchange);
|
|
int result = -1;
|
|
|
|
memset( _tx_buffer, 0, sizeof(_tx_buffer) );
|
|
|
|
msg->header.version = htons(SM_VERSION);
|
|
msg->header.revision = htons(SM_REVISION);
|
|
msg->header.max_supported_version = htons(SM_VERSION);
|
|
msg->header.max_supported_revision = htons(SM_REVISION);
|
|
msg->header.msg_len = htons(sizeof(SmMsgT));
|
|
msg->header.msg_type = htons(SM_MSG_TYPE_SERVICE_DOMAIN_EXCHANGE);
|
|
msg->header.msg_flags = htonll(0);
|
|
snprintf( msg->header.msg_instance, sizeof(msg->header.msg_instance),
|
|
"%s", _msg_instance );
|
|
msg->header.msg_seq_num = htonll(_msg_seq_num);
|
|
snprintf( msg->header.node_name, sizeof(msg->header.node_name),
|
|
"%s", _hostname );
|
|
|
|
snprintf( exchange_msg->service_domain, sizeof(exchange_msg->service_domain),
|
|
"%s", interface->service_domain );
|
|
snprintf( exchange_msg->node_name, sizeof(exchange_msg->node_name),
|
|
"%s", node_name );
|
|
snprintf( exchange_msg->exchange_node_name,
|
|
sizeof(exchange_msg->exchange_node_name),
|
|
"%s", exchange_node_name );
|
|
exchange_msg->exchange_seq = htonl(exchange_seq);
|
|
exchange_msg->member_id = htonll(member_id);
|
|
snprintf( exchange_msg->member_name, sizeof(exchange_msg->member_name),
|
|
"%s", member_name );
|
|
snprintf( exchange_msg->member_desired_state,
|
|
sizeof(exchange_msg->member_desired_state),
|
|
"%s", sm_service_group_state_str(member_desired_state) );
|
|
snprintf( exchange_msg->member_state, sizeof(exchange_msg->member_state),
|
|
"%s", sm_service_group_state_str(member_state) );
|
|
snprintf( exchange_msg->member_status, sizeof(exchange_msg->member_status),
|
|
"%s", sm_service_group_status_str(member_status) );
|
|
snprintf( exchange_msg->member_condition,
|
|
sizeof( exchange_msg->member_condition),
|
|
"%s", sm_service_group_condition_str(member_condition) );
|
|
exchange_msg->member_health = htonll(member_health);
|
|
snprintf( exchange_msg->reason_text, sizeof(exchange_msg->reason_text),
|
|
"%s", reason_text );
|
|
exchange_msg->more_members = htonl(more_members ? 1 : 0);
|
|
exchange_msg->last_received_member_id = htonll(last_received_member_id);
|
|
|
|
if( SM_AUTH_TYPE_HMAC_SHA512 == interface->auth_type )
|
|
{
|
|
SmSha512HashT hash;
|
|
|
|
msg->header.auth_type = htonl(interface->auth_type);
|
|
sm_sha512_hmac( msg, sizeof(SmMsgT), interface->auth_key,
|
|
strlen(interface->auth_key), &hash );
|
|
memcpy( &(msg->header.auth_vector[0]), &(hash.bytes[0]),
|
|
SM_SHA512_HASH_SIZE );
|
|
} else {
|
|
msg->header.auth_type = htonl(SM_AUTH_TYPE_NONE);
|
|
}
|
|
|
|
if(( SM_NETWORK_TYPE_IPV4_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV4 == interface->network_type ))
|
|
{
|
|
result = sm_send_msg(interface, msg);
|
|
} else if(( SM_NETWORK_TYPE_IPV6_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV6 == interface->network_type ))
|
|
{
|
|
result = sm_send_ipv6_msg(interface, msg);
|
|
}
|
|
|
|
if( 0 > result )
|
|
{
|
|
if ( _MSG_NOT_SENT_TO_TARGET != result )
|
|
{
|
|
DPRINTFE( "Failed to send message on socket for interface (%s), "
|
|
"error=%s.", interface->interface_name, strerror( errno ) );
|
|
return( SM_FAILED );
|
|
}
|
|
return( SM_OKAY );
|
|
}
|
|
|
|
++_send_service_domain_exchange_cnt;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Send Service Domain Member Request
|
|
// ==============================================
|
|
SmErrorT sm_msg_send_service_domain_member_request( char node_name[],
|
|
char member_node_name[], int64_t member_id, char member_name[],
|
|
SmServiceGroupActionT member_action,
|
|
SmServiceGroupActionFlagsT member_action_flags,
|
|
SmServiceDomainInterfaceT* interface )
|
|
{
|
|
SmMsgT* msg = (SmMsgT*) _tx_buffer;
|
|
SmMsgServiceDomainMemberRequestT* request_msg = &(msg->u.request);
|
|
int result = -1;
|
|
|
|
memset( _tx_buffer, 0, sizeof(_tx_buffer) );
|
|
|
|
msg->header.version = htons(SM_VERSION);
|
|
msg->header.revision = htons(SM_REVISION);
|
|
msg->header.max_supported_version = htons(SM_VERSION);
|
|
msg->header.max_supported_revision = htons(SM_REVISION);
|
|
msg->header.msg_len = htons(sizeof(SmMsgT));
|
|
msg->header.msg_type = htons(SM_MSG_TYPE_SERVICE_DOMAIN_MEMBER_REQUEST);
|
|
msg->header.msg_flags = htonll(0);
|
|
snprintf( msg->header.msg_instance, sizeof(msg->header.msg_instance),
|
|
"%s", _msg_instance );
|
|
msg->header.msg_seq_num = htonll(_msg_seq_num);
|
|
snprintf( msg->header.node_name, sizeof(msg->header.node_name),
|
|
"%s", _hostname );
|
|
|
|
snprintf( request_msg->service_domain, sizeof(request_msg->service_domain),
|
|
"%s", interface->service_domain );
|
|
snprintf( request_msg->node_name, sizeof(request_msg->node_name),
|
|
"%s", node_name );
|
|
snprintf( request_msg->member_node_name, sizeof(request_msg->member_node_name),
|
|
"%s", member_node_name );
|
|
request_msg->member_id = htonll(member_id);
|
|
snprintf( request_msg->member_name, sizeof(request_msg->member_name),
|
|
"%s", member_name );
|
|
snprintf( request_msg->member_action, sizeof(request_msg->member_action),
|
|
"%s", sm_service_group_action_str(member_action) );
|
|
request_msg->member_action_flags = htonll(member_action_flags);
|
|
|
|
if( SM_AUTH_TYPE_HMAC_SHA512 == interface->auth_type )
|
|
{
|
|
SmSha512HashT hash;
|
|
|
|
msg->header.auth_type = htonl(interface->auth_type);
|
|
sm_sha512_hmac( msg, sizeof(SmMsgT), interface->auth_key,
|
|
strlen(interface->auth_key), &hash );
|
|
memcpy( &(msg->header.auth_vector[0]), &(hash.bytes[0]),
|
|
SM_SHA512_HASH_SIZE );
|
|
} else {
|
|
msg->header.auth_type = htonl(SM_AUTH_TYPE_NONE);
|
|
}
|
|
|
|
if(( SM_NETWORK_TYPE_IPV4_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV4 == interface->network_type ))
|
|
{
|
|
result = sm_send_msg(interface, msg);
|
|
} else if(( SM_NETWORK_TYPE_IPV6_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV6 == interface->network_type ))
|
|
{
|
|
result = sm_send_ipv6_msg(interface, msg);
|
|
}
|
|
|
|
if( 0 > result )
|
|
{
|
|
if ( _MSG_NOT_SENT_TO_TARGET != result )
|
|
{
|
|
DPRINTFE( "Failed to send message on socket for interface (%s), "
|
|
"error=%s.", interface->interface_name, strerror( errno ) );
|
|
return( SM_FAILED );
|
|
}
|
|
return( SM_OKAY );
|
|
}
|
|
|
|
++_send_service_domain_member_request_cnt;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Send Service Domain Member Update
|
|
// =============================================
|
|
SmErrorT sm_msg_send_service_domain_member_update( char node_name[],
|
|
char member_node_name[], int64_t member_id, char member_name[],
|
|
SmServiceGroupStateT member_desired_state,
|
|
SmServiceGroupStateT member_state, SmServiceGroupStatusT member_status,
|
|
SmServiceGroupConditionT member_condition, int64_t member_health,
|
|
const char reason_text[], SmServiceDomainInterfaceT* interface )
|
|
{
|
|
SmMsgT* msg = (SmMsgT*) _tx_buffer;
|
|
SmMsgServiceDomainMemberUpdateT* update_msg = &(msg->u.update);
|
|
int result = -1;
|
|
|
|
memset( _tx_buffer, 0, sizeof(_tx_buffer) );
|
|
|
|
msg->header.version = htons(SM_VERSION);
|
|
msg->header.revision = htons(SM_REVISION);
|
|
msg->header.max_supported_version = htons(SM_VERSION);
|
|
msg->header.max_supported_revision = htons(SM_REVISION);
|
|
msg->header.msg_len = htons(sizeof(SmMsgT));
|
|
msg->header.msg_type = htons(SM_MSG_TYPE_SERVICE_DOMAIN_MEMBER_UPDATE);
|
|
msg->header.msg_flags = htonll(0);
|
|
snprintf( msg->header.msg_instance, sizeof(msg->header.msg_instance),
|
|
"%s", _msg_instance );
|
|
msg->header.msg_seq_num = htonll(_msg_seq_num);
|
|
snprintf( msg->header.node_name, sizeof(msg->header.node_name),
|
|
"%s", _hostname );
|
|
|
|
snprintf( update_msg->service_domain, sizeof(update_msg->service_domain),
|
|
"%s", interface->service_domain );
|
|
snprintf( update_msg->node_name, sizeof(update_msg->node_name),
|
|
"%s", node_name );
|
|
snprintf( update_msg->member_node_name, sizeof(update_msg->member_node_name),
|
|
"%s", member_node_name );
|
|
update_msg->member_id = htonll(member_id);
|
|
snprintf( update_msg->member_name, sizeof(update_msg->member_name),
|
|
"%s", member_name );
|
|
snprintf( update_msg->member_desired_state,
|
|
sizeof(update_msg->member_desired_state),
|
|
"%s", sm_service_group_state_str(member_desired_state) );
|
|
snprintf( update_msg->member_state, sizeof(update_msg->member_state),
|
|
"%s", sm_service_group_state_str(member_state) );
|
|
snprintf( update_msg->member_status, sizeof(update_msg->member_status),
|
|
"%s", sm_service_group_status_str(member_status) );
|
|
snprintf( update_msg->member_condition, sizeof(update_msg->member_condition),
|
|
"%s", sm_service_group_condition_str(member_condition) );
|
|
update_msg->member_health = htonll(member_health);
|
|
snprintf( update_msg->reason_text, sizeof(update_msg->reason_text),
|
|
"%s", reason_text );
|
|
|
|
if( SM_AUTH_TYPE_HMAC_SHA512 == interface->auth_type )
|
|
{
|
|
SmSha512HashT hash;
|
|
|
|
msg->header.auth_type = htonl(interface->auth_type);
|
|
sm_sha512_hmac( msg, sizeof(SmMsgT), interface->auth_key,
|
|
strlen(interface->auth_key), &hash );
|
|
memcpy( &(msg->header.auth_vector[0]), &(hash.bytes[0]),
|
|
SM_SHA512_HASH_SIZE );
|
|
} else {
|
|
msg->header.auth_type = htonl(SM_AUTH_TYPE_NONE);
|
|
}
|
|
|
|
if(( SM_NETWORK_TYPE_IPV4_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV4 == interface->network_type ))
|
|
{
|
|
result = sm_send_msg(interface, msg);
|
|
} else if(( SM_NETWORK_TYPE_IPV6_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV6 == interface->network_type ))
|
|
{
|
|
result = sm_send_ipv6_msg(interface, msg);
|
|
}
|
|
|
|
if( 0 > result )
|
|
{
|
|
if ( _MSG_NOT_SENT_TO_TARGET != result )
|
|
{
|
|
DPRINTFE( "Failed to send message on socket for interface (%s), "
|
|
"error=%s.", interface->interface_name, strerror( errno ) );
|
|
return( SM_FAILED );
|
|
}
|
|
return( SM_OKAY );
|
|
}
|
|
|
|
++_send_service_domain_member_update_cnt;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Get Ancillary Data
|
|
// ==============================
|
|
static void* sm_msg_get_ancillary_data( struct msghdr* msg_hdr, int cmsg_level,
|
|
int cmsg_type )
|
|
{
|
|
struct cmsghdr* cmsg;
|
|
|
|
for( cmsg = CMSG_FIRSTHDR(msg_hdr); NULL != cmsg;
|
|
cmsg = CMSG_NXTHDR( msg_hdr, cmsg) )
|
|
{
|
|
if(( cmsg_level == cmsg->cmsg_level )&&
|
|
( cmsg_type == cmsg->cmsg_type ))
|
|
{
|
|
return( CMSG_DATA(cmsg) );
|
|
}
|
|
}
|
|
|
|
return( NULL );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Dispatch Message
|
|
// ============================
|
|
static void sm_msg_dispatch_msg( bool is_multicast_msg, SmMsgT* msg,
|
|
SmNetworkAddressT* network_address, int network_port,
|
|
SmMsgPeerInterfaceInfoT* peer_interface )
|
|
{
|
|
SmListT* entry = NULL;
|
|
SmListEntryDataPtrT entry_data;
|
|
SmMsgCallbacksT* callbacks;
|
|
SmMsgNodeHelloT* node_hello_msg = &(msg->u.node_hello);
|
|
SmMsgNodeUpdateT* node_update_msg = &(msg->u.node_update);
|
|
SmMsgNodeSwactT* node_swact_msg;
|
|
SmMsgNodeSwactAckT* node_swact_ack_msg;
|
|
SmNodeAdminStateT node_admin_state;
|
|
SmNodeOperationalStateT node_oper_state;
|
|
SmNodeAvailStatusT node_avail_status;
|
|
SmNodeReadyStateT node_ready_state;
|
|
SmMsgServiceDomainHelloT* hello_msg = &(msg->u.hello);
|
|
SmMsgServiceDomainPauseT* pause_msg = &(msg->u.pause);
|
|
SmMsgServiceDomainExchangeStartT* exchange_start_msg;
|
|
SmMsgServiceDomainExchangeT* exchange_msg = &(msg->u.exchange);
|
|
SmMsgServiceDomainMemberRequestT* request_msg = &(msg->u.request);
|
|
SmMsgServiceDomainMemberUpdateT* update_msg = &(msg->u.update);
|
|
SmServiceGroupStateT member_desired_state;
|
|
SmServiceGroupStateT member_state;
|
|
SmServiceGroupStatusT member_status;
|
|
SmServiceGroupConditionT member_condition;
|
|
SmServiceGroupActionT member_action;
|
|
|
|
|
|
node_swact_msg = &(msg->u.node_swact);
|
|
node_swact_ack_msg = &(msg->u.node_swact_ack);
|
|
exchange_start_msg = &(msg->u.exchange_start);
|
|
|
|
if( SM_VERSION != ntohs(msg->header.version) )
|
|
{
|
|
++_rcvd_bad_msg_version;
|
|
DPRINTFD( "Received unsupported version (%i).",
|
|
ntohs(msg->header.version) );
|
|
return;
|
|
}
|
|
|
|
if( 0 == strcmp( _hostname, msg->header.node_name ) )
|
|
{
|
|
DPRINTFD( "Received own message (%i),",
|
|
ntohs(msg->header.msg_type) );
|
|
return;
|
|
}
|
|
|
|
if( !(sm_msg_in_sequence( msg->header.node_name, msg->header.msg_instance,
|
|
ntohll(msg->header.msg_seq_num) )) )
|
|
{
|
|
DPRINTFD( "Duplicate message received from node (%s), "
|
|
"msg_seq=%" PRIi64 ".", msg->header.node_name,
|
|
ntohll(msg->header.msg_seq_num) );
|
|
return;
|
|
} else {
|
|
DPRINTFD( "Message received from node (%s), "
|
|
"msg_seq=%" PRIi64 ".", msg->header.node_name,
|
|
ntohll(msg->header.msg_seq_num) );
|
|
}
|
|
|
|
if( SM_AUTH_TYPE_HMAC_SHA512 == ntohl(msg->header.auth_type) )
|
|
{
|
|
uint8_t auth_vector[SM_AUTHENTICATION_VECTOR_MAX_CHAR];
|
|
SmSha512HashT hash;
|
|
|
|
memcpy( auth_vector, &(msg->header.auth_vector[0]),
|
|
SM_AUTHENTICATION_VECTOR_MAX_CHAR );
|
|
memset( &(msg->header.auth_vector[0]), 0,
|
|
SM_AUTHENTICATION_VECTOR_MAX_CHAR );
|
|
|
|
sm_sha512_hmac( msg, sizeof(SmMsgT), peer_interface->auth_key,
|
|
strlen(peer_interface->auth_key), &hash );
|
|
|
|
if( 0 != memcmp( &(hash.bytes[0]), auth_vector, SM_SHA512_HASH_SIZE ) )
|
|
{
|
|
++_rcvd_bad_msg_auth;
|
|
DPRINTFD( "Authentication check failed on message (%i) from "
|
|
"node (%s).", ntohs(msg->header.msg_type),
|
|
msg->header.node_name );
|
|
return;
|
|
} else {
|
|
DPRINTFD( "Authentication check passed on message (%i) from "
|
|
"node (%s).", ntohs(msg->header.msg_type),
|
|
msg->header.node_name );
|
|
}
|
|
}
|
|
|
|
uint16_t msg_type = ntohs(msg->header.msg_type) ;
|
|
|
|
switch( msg_type )
|
|
{
|
|
case SM_MSG_TYPE_NODE_HELLO:
|
|
++_rcvd_node_hello_cnt;
|
|
|
|
node_admin_state
|
|
= sm_node_admin_state_value(node_hello_msg->admin_state);
|
|
node_oper_state
|
|
= sm_node_oper_state_value(node_hello_msg->oper_state);
|
|
node_avail_status
|
|
= sm_node_avail_status_value(node_hello_msg->avail_status);
|
|
node_ready_state
|
|
= sm_node_ready_state_value(node_hello_msg->ready_state);
|
|
|
|
SM_LIST_FOREACH( _callbacks, entry, entry_data )
|
|
{
|
|
callbacks = (SmMsgCallbacksT*) entry_data;
|
|
|
|
if( NULL == callbacks->node_hello )
|
|
continue;
|
|
|
|
callbacks->node_hello( network_address, network_port,
|
|
ntohs(msg->header.version),
|
|
ntohs(msg->header.revision),
|
|
node_hello_msg->node_name,
|
|
node_admin_state, node_oper_state,
|
|
node_avail_status, node_ready_state,
|
|
node_hello_msg->state_uuid,
|
|
ntohl(node_hello_msg->uptime) );
|
|
}
|
|
break;
|
|
|
|
case SM_MSG_TYPE_NODE_UPDATE:
|
|
++_rcvd_node_update_cnt;
|
|
|
|
node_admin_state
|
|
= sm_node_admin_state_value(node_update_msg->admin_state);
|
|
node_oper_state
|
|
= sm_node_oper_state_value(node_update_msg->oper_state);
|
|
node_avail_status
|
|
= sm_node_avail_status_value(node_update_msg->avail_status);
|
|
node_ready_state
|
|
= sm_node_ready_state_value(node_update_msg->ready_state);
|
|
|
|
SM_LIST_FOREACH( _callbacks, entry, entry_data )
|
|
{
|
|
callbacks = (SmMsgCallbacksT*) entry_data;
|
|
|
|
if( NULL == callbacks->node_update )
|
|
continue;
|
|
|
|
callbacks->node_update( network_address, network_port,
|
|
ntohs(msg->header.version),
|
|
ntohs(msg->header.revision),
|
|
node_update_msg->node_name,
|
|
node_admin_state, node_oper_state,
|
|
node_avail_status, node_ready_state,
|
|
node_update_msg->old_state_uuid,
|
|
node_update_msg->state_uuid,
|
|
ntohl(node_update_msg->uptime),
|
|
ntohl(node_update_msg->force) );
|
|
}
|
|
break;
|
|
|
|
case SM_MSG_TYPE_NODE_SWACT:
|
|
++_rcvd_node_swact_cnt;
|
|
|
|
SM_LIST_FOREACH( _callbacks, entry, entry_data )
|
|
{
|
|
callbacks = (SmMsgCallbacksT*) entry_data;
|
|
|
|
if( NULL == callbacks->node_swact )
|
|
continue;
|
|
|
|
callbacks->node_swact( network_address, network_port,
|
|
ntohs(msg->header.version),
|
|
ntohs(msg->header.revision),
|
|
node_swact_msg->node_name,
|
|
ntohl(node_swact_msg->force),
|
|
node_swact_msg->request_uuid );
|
|
}
|
|
break;
|
|
|
|
case SM_MSG_TYPE_NODE_SWACT_ACK:
|
|
++_rcvd_node_swact_ack_cnt;
|
|
|
|
SM_LIST_FOREACH( _callbacks, entry, entry_data )
|
|
{
|
|
callbacks = (SmMsgCallbacksT*) entry_data;
|
|
|
|
if( NULL == callbacks->node_swact_ack )
|
|
continue;
|
|
|
|
callbacks->node_swact_ack( network_address, network_port,
|
|
ntohs(msg->header.version),
|
|
ntohs(msg->header.revision),
|
|
node_swact_ack_msg->node_name,
|
|
ntohl(node_swact_ack_msg->force),
|
|
node_swact_ack_msg->request_uuid );
|
|
}
|
|
break;
|
|
|
|
|
|
case SM_MSG_TYPE_SERVICE_DOMAIN_HELLO:
|
|
++_rcvd_service_domain_hello_cnt;
|
|
|
|
SM_LIST_FOREACH( _callbacks, entry, entry_data )
|
|
{
|
|
callbacks = (SmMsgCallbacksT*) entry_data;
|
|
|
|
if( NULL == callbacks->hello )
|
|
continue;
|
|
|
|
callbacks->hello( network_address, network_port,
|
|
ntohs(msg->header.version),
|
|
ntohs(msg->header.revision),
|
|
hello_msg->service_domain,
|
|
hello_msg->node_name,
|
|
hello_msg->orchestration,
|
|
hello_msg->designation,
|
|
ntohl(hello_msg->generation),
|
|
ntohl(hello_msg->priority),
|
|
ntohl(hello_msg->hello_interval),
|
|
ntohl(hello_msg->dead_interval),
|
|
ntohl(hello_msg->wait_interval),
|
|
ntohl(hello_msg->exchange_interval),
|
|
hello_msg->leader );
|
|
}
|
|
break;
|
|
|
|
case SM_MSG_TYPE_SERVICE_DOMAIN_PAUSE:
|
|
++_send_service_domain_pause_cnt;
|
|
|
|
SM_LIST_FOREACH( _callbacks, entry, entry_data )
|
|
{
|
|
callbacks = (SmMsgCallbacksT*) entry_data;
|
|
|
|
if( NULL == callbacks->pause )
|
|
continue;
|
|
|
|
callbacks->pause( network_address, network_port,
|
|
ntohs(msg->header.version),
|
|
ntohs(msg->header.revision),
|
|
pause_msg->service_domain,
|
|
pause_msg->node_name,
|
|
ntohl(pause_msg->pause_interval) );
|
|
}
|
|
break;
|
|
|
|
case SM_MSG_TYPE_SERVICE_DOMAIN_EXCHANGE_START:
|
|
if( 0 != strcmp( exchange_start_msg->exchange_node_name,
|
|
_hostname ) )
|
|
{
|
|
DPRINTFD( "Exchange start message not for us." );
|
|
return;
|
|
}
|
|
|
|
++_rcvd_service_domain_exchange_start_cnt;
|
|
|
|
SM_LIST_FOREACH( _callbacks, entry, entry_data )
|
|
{
|
|
callbacks = (SmMsgCallbacksT*) entry_data;
|
|
|
|
if( NULL == callbacks->exchange_start )
|
|
continue;
|
|
|
|
callbacks->exchange_start( network_address, network_port,
|
|
ntohs(msg->header.version),
|
|
ntohs(msg->header.revision),
|
|
exchange_start_msg->service_domain,
|
|
exchange_start_msg->node_name,
|
|
ntohl(exchange_start_msg->exchange_seq) );
|
|
}
|
|
break;
|
|
|
|
case SM_MSG_TYPE_SERVICE_DOMAIN_EXCHANGE:
|
|
if( 0 != strcmp( exchange_msg->exchange_node_name, _hostname ) )
|
|
{
|
|
DPRINTFD( "Exchange message not for us." );
|
|
return;
|
|
}
|
|
|
|
++_rcvd_service_domain_exchange_cnt;
|
|
|
|
member_desired_state = sm_service_group_state_value(
|
|
exchange_msg->member_desired_state );
|
|
member_state = sm_service_group_state_value(
|
|
exchange_msg->member_state );
|
|
member_status = sm_service_group_status_value(
|
|
exchange_msg->member_status );
|
|
|
|
member_condition = sm_service_group_condition_value(
|
|
exchange_msg->member_condition );
|
|
|
|
SM_LIST_FOREACH( _callbacks, entry, entry_data )
|
|
{
|
|
callbacks = (SmMsgCallbacksT*) entry_data;
|
|
|
|
if( NULL == callbacks->exchange )
|
|
continue;
|
|
|
|
callbacks->exchange( network_address, network_port,
|
|
ntohs(msg->header.version),
|
|
ntohs(msg->header.revision),
|
|
exchange_msg->service_domain,
|
|
exchange_msg->node_name,
|
|
ntohl(exchange_msg->exchange_seq),
|
|
ntohll(exchange_msg->member_id),
|
|
exchange_msg->member_name,
|
|
member_desired_state,
|
|
member_state, member_status,
|
|
member_condition,
|
|
ntohll(exchange_msg->member_health),
|
|
exchange_msg->reason_text,
|
|
ntohl(exchange_msg->more_members) ? true : false,
|
|
ntohll(exchange_msg->last_received_member_id) );
|
|
}
|
|
break;
|
|
|
|
case SM_MSG_TYPE_SERVICE_DOMAIN_MEMBER_REQUEST:
|
|
if( 0 != strcmp( request_msg->member_node_name, _hostname ) )
|
|
{
|
|
DPRINTFD( "Member request message not for us." );
|
|
return;
|
|
}
|
|
|
|
++_rcvd_service_domain_member_request_cnt;
|
|
|
|
member_action = sm_service_group_action_value(
|
|
request_msg->member_action );
|
|
|
|
SM_LIST_FOREACH( _callbacks, entry, entry_data )
|
|
{
|
|
callbacks = (SmMsgCallbacksT*) entry_data;
|
|
|
|
if( NULL == callbacks->member_request )
|
|
continue;
|
|
|
|
callbacks->member_request( network_address, network_port,
|
|
ntohs(msg->header.version),
|
|
ntohs(msg->header.revision),
|
|
request_msg->service_domain,
|
|
request_msg->node_name,
|
|
request_msg->member_node_name,
|
|
ntohll(request_msg->member_id),
|
|
request_msg->member_name,
|
|
member_action,
|
|
ntohll(request_msg->member_action_flags) );
|
|
}
|
|
break;
|
|
|
|
case SM_MSG_TYPE_SERVICE_DOMAIN_MEMBER_UPDATE:
|
|
++_rcvd_service_domain_member_update_cnt;
|
|
|
|
member_desired_state = sm_service_group_state_value(
|
|
update_msg->member_desired_state );
|
|
member_state = sm_service_group_state_value(
|
|
update_msg->member_state );
|
|
member_status = sm_service_group_status_value(
|
|
update_msg->member_status );
|
|
member_condition = sm_service_group_condition_value(
|
|
update_msg->member_condition );
|
|
|
|
SM_LIST_FOREACH( _callbacks, entry, entry_data )
|
|
{
|
|
callbacks = (SmMsgCallbacksT*) entry_data;
|
|
|
|
if( NULL == callbacks->member_update )
|
|
continue;
|
|
|
|
callbacks->member_update( network_address, network_port,
|
|
ntohs(msg->header.version),
|
|
ntohs(msg->header.revision),
|
|
update_msg->service_domain,
|
|
update_msg->node_name,
|
|
update_msg->member_node_name,
|
|
ntohll(update_msg->member_id),
|
|
update_msg->member_name,
|
|
member_desired_state,
|
|
member_state, member_status,
|
|
member_condition,
|
|
ntohll(update_msg->member_health),
|
|
update_msg->reason_text );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DPRINTFI( "Unsupported message type (%i) received.",
|
|
ntohs(msg->header.msg_type) );
|
|
break;
|
|
}
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Dispatch Ipv4 Udp
|
|
// =============================
|
|
static void sm_msg_dispatch_ipv4_udp( int selobj, int64_t msg_method )
|
|
{
|
|
SmMsgT* msg = (SmMsgT*) _rx_buffer;
|
|
SmNetworkAddressT network_address;
|
|
SmMsgPeerInterfaceInfoT* peer_interface = NULL;
|
|
SmErrorT error;
|
|
int network_port;
|
|
struct sockaddr_in src_addr;
|
|
struct iovec iovec = {(void*)_rx_buffer, sizeof(_rx_buffer)};
|
|
struct msghdr msg_hdr;
|
|
int bytes_read;
|
|
|
|
memset( &network_address, 0, sizeof(network_address) );
|
|
memset( _rx_control_buffer, 0, sizeof(_rx_control_buffer) );
|
|
memset( _rx_buffer, 0, sizeof(_rx_buffer) );
|
|
memset( &msg_hdr, 0, sizeof(msg_hdr) );
|
|
|
|
msg_hdr.msg_name = &src_addr;
|
|
msg_hdr.msg_namelen= sizeof(src_addr);
|
|
msg_hdr.msg_iov = &iovec;
|
|
msg_hdr.msg_iovlen = 1;
|
|
msg_hdr.msg_control = _rx_control_buffer;
|
|
msg_hdr.msg_controllen = sizeof(_rx_control_buffer);
|
|
|
|
int retry_i;
|
|
for( retry_i = 5; retry_i != 0; --retry_i )
|
|
{
|
|
bytes_read = recvmsg( selobj, &msg_hdr, MSG_NOSIGNAL | MSG_DONTWAIT );
|
|
if( 0 < bytes_read )
|
|
{
|
|
break;
|
|
|
|
} else if( 0 == bytes_read ) {
|
|
// For connection oriented sockets, this indicates that the peer
|
|
// has performed an orderly shutdown.
|
|
return;
|
|
|
|
} else if(( 0 > bytes_read )&&( EINTR != errno )) {
|
|
DPRINTFE( "Failed to receive message, errno=%s.",
|
|
strerror( errno ) );
|
|
return;
|
|
}
|
|
|
|
DPRINTFD( "Interrupted while receiving message, retry=%d, errno=%s.",
|
|
retry_i, strerror( errno ) );
|
|
}
|
|
|
|
++_rcvd_total_msgs;
|
|
|
|
if( !_messaging_enabled )
|
|
{
|
|
++_rcvd_msgs_while_disabled;
|
|
DPRINTFD( "Messaging is disabled." );
|
|
return;
|
|
}
|
|
|
|
if( AF_INET == src_addr.sin_family )
|
|
{
|
|
char if_name[SM_INTERFACE_NAME_MAX_CHAR] = {0};
|
|
struct in_pktinfo* pkt_info;
|
|
char network_address_str[SM_NETWORK_ADDRESS_MAX_CHAR];
|
|
|
|
pkt_info = (struct in_pktinfo*) sm_msg_get_ancillary_data( &msg_hdr,
|
|
SOL_IP, IP_PKTINFO );
|
|
if( NULL == pkt_info )
|
|
{
|
|
DPRINTFD( "No packet information available." );
|
|
return;
|
|
}
|
|
|
|
error = sm_hw_get_if_name( pkt_info->ipi_ifindex, if_name );
|
|
if( SM_OKAY != error )
|
|
{
|
|
if( SM_NOT_FOUND == error )
|
|
{
|
|
DPRINTFD( "Failed to get interface name for interface index "
|
|
"(%i), error=%s.", pkt_info->ipi_ifindex,
|
|
sm_error_str(error) );
|
|
} else {
|
|
DPRINTFE( "Failed to get interface name for interface index "
|
|
"(%i), error=%s.", pkt_info->ipi_ifindex,
|
|
sm_error_str(error) );
|
|
}
|
|
return;
|
|
}
|
|
|
|
network_address.type = SM_NETWORK_TYPE_IPV4_UDP;
|
|
network_address.u.ipv4.sin.s_addr = src_addr.sin_addr.s_addr;
|
|
network_port = ntohs(src_addr.sin_port);
|
|
|
|
sm_network_address_str( &network_address, network_address_str );
|
|
|
|
DPRINTFD( "Received message from ip (%s), port (%i) on "
|
|
"interface (%s).", network_address_str, network_port,
|
|
if_name );
|
|
|
|
peer_interface = sm_msg_get_peer_interface( if_name, &network_address,
|
|
network_port );
|
|
if( NULL == peer_interface )
|
|
{
|
|
DPRINTFD( "Message received not for us, if=%s, ip=%s, port=%i.",
|
|
if_name, network_address_str, network_port );
|
|
return;
|
|
}
|
|
} else {
|
|
DPRINTFE( "Received unsupported network address type (%i).",
|
|
src_addr.sin_family );
|
|
return;
|
|
}
|
|
|
|
// Once the message is received, pass it to protocol-independent handler
|
|
sm_msg_dispatch_msg( msg_method, msg, &network_address, network_port,
|
|
peer_interface );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Dispatch Ipv6 Udp
|
|
// =============================
|
|
static void sm_msg_dispatch_ipv6_udp( int selobj, int64_t msg_method )
|
|
{
|
|
SmMsgT* msg = (SmMsgT*) _rx_buffer;
|
|
SmNetworkAddressT network_address;
|
|
SmMsgPeerInterfaceInfoT* peer_interface = NULL;
|
|
SmErrorT error;
|
|
int network_port;
|
|
struct sockaddr_in6 src_addr;
|
|
struct iovec iovec = {(void*)_rx_buffer, sizeof(_rx_buffer)};
|
|
struct msghdr msg_hdr;
|
|
int bytes_read;
|
|
|
|
memset( &network_address, 0, sizeof(network_address) );
|
|
memset( _rx_control_buffer, 0, sizeof(_rx_control_buffer) );
|
|
memset( _rx_buffer, 0, sizeof(_rx_buffer) );
|
|
memset( &msg_hdr, 0, sizeof(msg_hdr) );
|
|
|
|
msg_hdr.msg_name = &src_addr;
|
|
msg_hdr.msg_namelen= sizeof(src_addr);
|
|
msg_hdr.msg_iov = &iovec;
|
|
msg_hdr.msg_iovlen = 1;
|
|
msg_hdr.msg_control = _rx_control_buffer;
|
|
msg_hdr.msg_controllen = sizeof(_rx_control_buffer);
|
|
|
|
int retry_i;
|
|
for( retry_i = 5; retry_i != 0; --retry_i )
|
|
{
|
|
bytes_read = recvmsg( selobj, &msg_hdr, MSG_NOSIGNAL | MSG_DONTWAIT );
|
|
if( 0 < bytes_read )
|
|
{
|
|
break;
|
|
|
|
} else if( 0 == bytes_read ) {
|
|
// For connection oriented sockets, this indicates that the peer
|
|
// has performed an orderly shutdown.
|
|
return;
|
|
|
|
} else if(( 0 > bytes_read )&&( EINTR != errno )) {
|
|
DPRINTFE( "Failed to receive message, errno=%s.",
|
|
strerror( errno ) );
|
|
return;
|
|
}
|
|
|
|
DPRINTFD( "Interrupted while receiving message, retry=%d, errno=%s.",
|
|
retry_i, strerror( errno ) );
|
|
}
|
|
|
|
++_rcvd_total_msgs;
|
|
|
|
if( !_messaging_enabled )
|
|
{
|
|
++_rcvd_msgs_while_disabled;
|
|
DPRINTFD( "Messaging is disabled." );
|
|
return;
|
|
}
|
|
|
|
if( AF_INET6 == src_addr.sin6_family )
|
|
{
|
|
char if_name[SM_INTERFACE_NAME_MAX_CHAR] = {0};
|
|
struct in6_pktinfo* pkt_info;
|
|
char network_address_str[SM_NETWORK_ADDRESS_MAX_CHAR];
|
|
|
|
pkt_info = (struct in6_pktinfo*) sm_msg_get_ancillary_data( &msg_hdr,
|
|
SOL_IPV6, IPV6_PKTINFO );
|
|
if( NULL == pkt_info )
|
|
{
|
|
DPRINTFD( "No packet information available." );
|
|
return;
|
|
}
|
|
|
|
error = sm_hw_get_if_name( pkt_info->ipi6_ifindex, if_name );
|
|
if( SM_OKAY != error )
|
|
{
|
|
if( SM_NOT_FOUND == error )
|
|
{
|
|
DPRINTFD( "Failed to get interface name for interface index "
|
|
"(%i), error=%s.", pkt_info->ipi6_ifindex,
|
|
sm_error_str(error) );
|
|
} else {
|
|
DPRINTFE( "Failed to get interface name for interface index "
|
|
"(%i), error=%s.", pkt_info->ipi6_ifindex,
|
|
sm_error_str(error) );
|
|
}
|
|
return;
|
|
}
|
|
|
|
network_address.type = SM_NETWORK_TYPE_IPV6_UDP;
|
|
network_address.u.ipv6.sin6 = src_addr.sin6_addr;
|
|
network_port = ntohs(src_addr.sin6_port);
|
|
|
|
sm_network_address_str( &network_address, network_address_str );
|
|
|
|
DPRINTFD( "Received message from ip (%s), port (%i) on "
|
|
"interface (%s).", network_address_str, network_port,
|
|
if_name );
|
|
|
|
peer_interface = sm_msg_get_peer_interface( if_name, &network_address,
|
|
network_port );
|
|
if( NULL == peer_interface )
|
|
{
|
|
DPRINTFD( "Message received not for us, if=%s, ip=%s, port=%i.",
|
|
if_name, network_address_str, network_port );
|
|
return;
|
|
}
|
|
} else {
|
|
DPRINTFE( "Received unsupported network address type (%i).",
|
|
src_addr.sin6_family );
|
|
return;
|
|
}
|
|
|
|
// Once the message is received, pass it to protocol-independent handler
|
|
sm_msg_dispatch_msg( msg_method, msg, &network_address, network_port,
|
|
peer_interface );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Register Ipv4 Multicast Address
|
|
// ===========================================
|
|
static SmErrorT sm_msg_register_ipv4_multicast(
|
|
SmServiceDomainInterfaceT* interface )
|
|
{
|
|
int if_index;
|
|
struct ip_mreqn mreq;
|
|
int result = 0;
|
|
SmIpv4AddressT* ipv4_multicast = &(interface->network_multicast.u.ipv4);
|
|
SmErrorT error;
|
|
|
|
error = sm_hw_get_if_index( interface->interface_name, &if_index );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to convert interface name (%s) to interface index, "
|
|
"error=%s.", interface->interface_name,
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
memset( &mreq, 0, sizeof(mreq) );
|
|
|
|
mreq.imr_multiaddr.s_addr = ipv4_multicast->sin.s_addr;
|
|
mreq.imr_ifindex = if_index;
|
|
|
|
result = setsockopt( interface->multicast_socket, IPPROTO_IP,
|
|
IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to add multicast membership to interface (%s), "
|
|
"errno=%s.", interface->interface_name, strerror(errno) );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Register Ipv6 Multicast Address
|
|
// ===========================================
|
|
static SmErrorT sm_msg_register_ipv6_multicast(
|
|
SmServiceDomainInterfaceT* interface )
|
|
{
|
|
int if_index;
|
|
struct ipv6_mreq mreq;
|
|
int result = 0;
|
|
SmIpv6AddressT* ipv6_multicast = &(interface->network_multicast.u.ipv6);
|
|
SmErrorT error;
|
|
|
|
error = sm_hw_get_if_index( interface->interface_name, &if_index );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to convert interface name (%s) to interface index, "
|
|
"error=%s.", interface->interface_name,
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
memset( &mreq, 0, sizeof(mreq) );
|
|
|
|
mreq.ipv6mr_multiaddr = ipv6_multicast->sin6;
|
|
mreq.ipv6mr_interface = if_index;
|
|
|
|
result = setsockopt( interface->multicast_socket, IPPROTO_IPV6,
|
|
IPV6_JOIN_GROUP, &mreq, sizeof(mreq) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to add multicast membership to interface (%s), "
|
|
"errno=%s.", interface->interface_name, strerror(errno) );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Deregister Ipv4 Multicast Address
|
|
// =============================================
|
|
static SmErrorT sm_msg_deregister_ipv4_multicast(
|
|
SmServiceDomainInterfaceT* interface )
|
|
{
|
|
int if_index;
|
|
struct ip_mreqn mreq;
|
|
int result = 0;
|
|
SmIpv4AddressT* ipv4_multicast = &(interface->network_multicast.u.ipv4);
|
|
SmErrorT error;
|
|
|
|
error = sm_hw_get_if_index( interface->interface_name, &if_index );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to convert interface name (%s) to interface index, "
|
|
"error=%s.", interface->interface_name,
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
memset( &mreq, 0, sizeof(mreq) );
|
|
|
|
mreq.imr_multiaddr.s_addr = ipv4_multicast->sin.s_addr;
|
|
mreq.imr_ifindex = if_index;
|
|
|
|
result = setsockopt( interface->multicast_socket, IPPROTO_IP,
|
|
IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to drop multicast membership from interface (%s), "
|
|
"errno=%s.", interface->interface_name, strerror(errno) );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Deregister Ipv6 Multicast Address
|
|
// =============================================
|
|
static SmErrorT sm_msg_deregister_ipv6_multicast(
|
|
SmServiceDomainInterfaceT* interface )
|
|
{
|
|
int if_index;
|
|
struct ipv6_mreq mreq;
|
|
int result = 0;
|
|
SmIpv6AddressT* ipv6_multicast = &(interface->network_multicast.u.ipv6);
|
|
SmErrorT error;
|
|
|
|
error = sm_hw_get_if_index( interface->interface_name, &if_index );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to convert interface name (%s) to interface index, "
|
|
"error=%s.", interface->interface_name,
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
memset( &mreq, 0, sizeof(mreq) );
|
|
|
|
mreq.ipv6mr_multiaddr = ipv6_multicast->sin6;
|
|
mreq.ipv6mr_interface = if_index;
|
|
|
|
result = setsockopt( interface->multicast_socket, IPPROTO_IPV6,
|
|
IPV6_LEAVE_GROUP, &mreq, sizeof(mreq) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to drop multicast membership from interface (%s), "
|
|
"errno=%s.", interface->interface_name, strerror(errno) );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Open Ipv4 UDP Multicast Socket
|
|
// ==========================================
|
|
static SmErrorT sm_msg_open_ipv4_udp_multicast_socket(
|
|
SmServiceDomainInterfaceT* interface, int* socket_fd )
|
|
{
|
|
int flags;
|
|
int sock;
|
|
int result;
|
|
struct ifreq ifr;
|
|
struct sockaddr_in addr;
|
|
SmIpv4AddressT* ipv4_address = &(interface->network_address.u.ipv4);
|
|
SmIpv4AddressT* ipv4_multicast = &(interface->network_multicast.u.ipv4);
|
|
|
|
*socket_fd = -1;
|
|
|
|
// Create socket.
|
|
sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
|
|
if( 0 > sock )
|
|
{
|
|
DPRINTFE( "Failed to open socket for interface (%s), errno=%s.",
|
|
interface->interface_name, strerror(errno) );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set socket to non-blocking.
|
|
flags = fcntl( sock, F_GETFL, 0 );
|
|
if( 0 > flags )
|
|
{
|
|
DPRINTFE( "Failed to get flags, error=%s.", strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
if( 0 > fcntl( sock, F_SETFL, flags | O_NONBLOCK ) )
|
|
{
|
|
DPRINTFE( "Failed to set flags, error=%s.", strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Close on exec.
|
|
flags = fcntl( sock, F_GETFD, 0 );
|
|
if( 0 > flags )
|
|
{
|
|
DPRINTFE( "Failed to get flags, error=%s.", strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
if( 0 > fcntl( sock, F_SETFD, flags | FD_CLOEXEC ) )
|
|
{
|
|
DPRINTFE( "Failed to set flags, error=%s.", strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Allow address reuse on socket.
|
|
flags = 1;
|
|
result = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR,
|
|
(void*) &flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set reuseaddr socket option on interface (%s), "
|
|
"errno=%s.", interface->interface_name, strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Bind address to socket.
|
|
memset( &addr, 0, sizeof(addr) );
|
|
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons(interface->network_port);
|
|
addr.sin_addr.s_addr = ipv4_multicast->sin.s_addr;
|
|
|
|
result = bind( sock, (struct sockaddr *) &addr, sizeof(addr) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to bind multicast address to socket for "
|
|
"interface (%s), error=%s.", interface->interface_name,
|
|
strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set multicast interface on socket.
|
|
result = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_IF,
|
|
(struct in_addr*) &(ipv4_address->sin.s_addr),
|
|
sizeof(struct in_addr) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set unicast address on socket for "
|
|
"interface (%s), error=%s.", interface->interface_name,
|
|
strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Bind socket to interface.
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
snprintf( ifr.ifr_name, sizeof(ifr.ifr_name), "%s",
|
|
interface->interface_name );
|
|
|
|
result = setsockopt( sock, SOL_SOCKET, SO_BINDTODEVICE,
|
|
(void *)&ifr, sizeof(ifr) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to bind socket to interface (%s), errno=%s.",
|
|
interface->interface_name, strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set multicast TTL.
|
|
flags = 1;
|
|
result = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_TTL,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set multicast ttl for interface (%s), errno=%s.",
|
|
interface->interface_name, strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Disable looping of sent multicast packets on socket.
|
|
flags = 0;
|
|
result = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_LOOP,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to stop looping of multicast messages for "
|
|
"interface (%s), errno=%s.", interface->interface_name,
|
|
strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set socket send priority on interface.
|
|
flags = IPTOS_CLASS_CS6;
|
|
result = setsockopt( sock, IPPROTO_IP, IP_TOS,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set socket send priority for interface (%s) "
|
|
"multicast messages, errno=%s.", interface->interface_name,
|
|
strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
flags = 6;
|
|
result = setsockopt( sock, SOL_SOCKET, SO_PRIORITY,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set socket send priority for interface (%s) "
|
|
"multicast messages, errno=%s.", interface->interface_name,
|
|
strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set socket receive packet information.
|
|
flags = 1;
|
|
result = setsockopt( sock, SOL_IP, IP_PKTINFO,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set socket receive packet information for "
|
|
"interface (%s) multicast messages, errno=%s.",
|
|
interface->interface_name, strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
*socket_fd = sock;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Open IPv6 UDP Multicast Socket
|
|
// ==========================================
|
|
static SmErrorT sm_msg_open_ipv6_udp_multicast_socket(
|
|
SmServiceDomainInterfaceT* interface, int* socket_fd )
|
|
{
|
|
int flags;
|
|
int sock;
|
|
int result;
|
|
struct ifreq ifr;
|
|
struct sockaddr_in6 addr;
|
|
SmIpv6AddressT* ipv6_multicast = &(interface->network_multicast.u.ipv6);
|
|
|
|
*socket_fd = -1;
|
|
|
|
// Create socket.
|
|
sock = socket( AF_INET6, SOCK_DGRAM, IPPROTO_UDP );
|
|
if( 0 > sock )
|
|
{
|
|
DPRINTFE( "Failed to open socket for interface (%s), errno=%s.",
|
|
interface->interface_name, strerror(errno) );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set socket to non-blocking.
|
|
flags = fcntl( sock, F_GETFL, 0 );
|
|
if( 0 > flags )
|
|
{
|
|
DPRINTFE( "Failed to get flags, error=%s.", strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
if( 0 > fcntl( sock, F_SETFL, flags | O_NONBLOCK ) )
|
|
{
|
|
DPRINTFE( "Failed to set flags, error=%s.", strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Close on exec.
|
|
flags = fcntl( sock, F_GETFD, 0 );
|
|
if( 0 > flags )
|
|
{
|
|
DPRINTFE( "Failed to get flags, error=%s.", strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
if( 0 > fcntl( sock, F_SETFD, flags | FD_CLOEXEC ) )
|
|
{
|
|
DPRINTFE( "Failed to set flags, error=%s.", strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Allow address reuse on socket.
|
|
flags = 1;
|
|
result = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR,
|
|
(void*) &flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set reuseaddr socket option on interface (%s), "
|
|
"errno=%s.", interface->interface_name, strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Bind address to socket.
|
|
memset( &addr, 0, sizeof(addr) );
|
|
|
|
addr.sin6_family = AF_INET6;
|
|
addr.sin6_port = htons(interface->network_port);
|
|
addr.sin6_addr = ipv6_multicast->sin6;
|
|
|
|
result = bind( sock, (struct sockaddr *) &addr, sizeof(addr) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to bind multicast address to socket for "
|
|
"interface (%s), error=%s.", interface->interface_name,
|
|
strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Bind socket to interface.
|
|
memset( &ifr, 0, sizeof(ifr) );
|
|
snprintf( ifr.ifr_name, sizeof(ifr.ifr_name), "%s",
|
|
interface->interface_name );
|
|
|
|
result = setsockopt( sock, SOL_SOCKET, SO_BINDTODEVICE,
|
|
(void* )&ifr, sizeof(ifr) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to bind socket to interface (%s), errno=%s.",
|
|
interface->interface_name, strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set multicast TTL.
|
|
flags = 1;
|
|
result = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set multicast ttl for interface (%s), errno=%s.",
|
|
interface->interface_name, strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Disable looping of sent multicast packets on socket.
|
|
flags = 0;
|
|
result = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to stop looping of multicast messages for "
|
|
"interface (%s), errno=%s.", interface->interface_name,
|
|
strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set socket send priority on interface.
|
|
flags = IPTOS_CLASS_CS6;
|
|
result = setsockopt( sock, IPPROTO_IPV6, IPV6_TCLASS,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set socket send priority for interface (%s) "
|
|
"multicast messages, errno=%s.", interface->interface_name,
|
|
strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
flags = 6;
|
|
result = setsockopt( sock, SOL_SOCKET, SO_PRIORITY,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set socket send priority for interface (%s) "
|
|
"multicast messages, errno=%s.", interface->interface_name,
|
|
strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set socket receive packet information.
|
|
flags = 1;
|
|
result = setsockopt( sock, SOL_IPV6, IPV6_RECVPKTINFO,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set socket receive packet information for "
|
|
"interface (%s) multicast messages, errno=%s.",
|
|
interface->interface_name, strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
*socket_fd = sock;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Open Ipv4 UDP Unicast Socket
|
|
// ========================================
|
|
static SmErrorT sm_msg_open_ipv4_udp_unicast_socket(
|
|
SmServiceDomainInterfaceT* interface, int* socket_fd )
|
|
{
|
|
int flags;
|
|
int sock;
|
|
int result;
|
|
struct sockaddr_in src_addr;
|
|
SmIpv4AddressT* ipv4_address = &(interface->network_address.u.ipv4);
|
|
|
|
*socket_fd = -1;
|
|
|
|
// Create socket.
|
|
sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
|
|
if( 0 > sock )
|
|
{
|
|
DPRINTFE( "Failed to open socket for interface (%s), errno=%s.",
|
|
interface->interface_name, strerror(errno) );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set socket to non-blocking.
|
|
flags = fcntl( sock, F_GETFL, 0 );
|
|
if( 0 > flags )
|
|
{
|
|
DPRINTFE( "Failed to get flags, error=%s.", strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
if( 0 > fcntl( sock, F_SETFL, flags | O_NONBLOCK ) )
|
|
{
|
|
DPRINTFE( "Failed to set flags, error=%s.", strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Close on exec.
|
|
if( 0 > fcntl( sock, F_SETFD, FD_CLOEXEC ) )
|
|
{
|
|
DPRINTFE( "Failed to set fd, error=%s.", strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Allow address reuse on socket.
|
|
flags = 1;
|
|
result = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR,
|
|
(void*) &flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set reuseaddr socket option on interface (%s), "
|
|
"errno=%s.", interface->interface_name,
|
|
strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Bind address to socket.
|
|
memset( &src_addr, 0, sizeof(src_addr) );
|
|
|
|
src_addr.sin_family = AF_INET;
|
|
src_addr.sin_port = htons(interface->network_port);
|
|
src_addr.sin_addr.s_addr = ipv4_address->sin.s_addr;
|
|
|
|
result = bind( sock, (struct sockaddr *) &src_addr, sizeof(src_addr) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to bind unicast address to socket for "
|
|
"interface (%s), error=%s.", interface->interface_name,
|
|
strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Bind socket to interface.
|
|
result = setsockopt( sock, SOL_SOCKET, SO_BINDTODEVICE,
|
|
interface->interface_name,
|
|
strlen(interface->interface_name)+1 );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to bind socket to interface (%s), "
|
|
"errno=%s.", interface->interface_name, strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Disable looping of sent multicast packets on socket.
|
|
flags = 0;
|
|
result = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_LOOP,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to stop looping of unicast messages for "
|
|
"interface (%s), errno=%s.", interface->interface_name,
|
|
strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set socket send priority on interface.
|
|
flags = IPTOS_CLASS_CS6;
|
|
result = setsockopt( sock, IPPROTO_IP, IP_TOS,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set socket send priority for interface (%s) "
|
|
"unicast messages, errno=%s.", interface->interface_name,
|
|
strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
flags = 6;
|
|
result = setsockopt( sock, SOL_SOCKET, SO_PRIORITY,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set socket send priority for interface (%s) "
|
|
"unicast messages, errno=%s.", interface->interface_name,
|
|
strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set socket receive packet information.
|
|
flags = 1;
|
|
result = setsockopt( sock, SOL_IP, IP_PKTINFO,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set socket receive packet information for "
|
|
"interface (%s) unicast messages, errno=%s.",
|
|
interface->interface_name, strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
*socket_fd = sock;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Open IPv6 UDP Unicast Socket
|
|
// ========================================
|
|
static SmErrorT sm_msg_open_ipv6_udp_unicast_socket(
|
|
SmServiceDomainInterfaceT* interface, int* socket_fd )
|
|
{
|
|
int flags;
|
|
int sock;
|
|
int result;
|
|
struct sockaddr_in6 src_addr;
|
|
SmIpv6AddressT* ipv6_address = &(interface->network_address.u.ipv6);
|
|
|
|
*socket_fd = -1;
|
|
|
|
// Create socket.
|
|
sock = socket( AF_INET6, SOCK_DGRAM, IPPROTO_UDP );
|
|
if( 0 > sock )
|
|
{
|
|
DPRINTFE( "Failed to open socket for interface (%s), errno=%s.",
|
|
interface->interface_name, strerror(errno) );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set socket to non-blocking.
|
|
flags = fcntl( sock, F_GETFL, 0 );
|
|
if( 0 > flags )
|
|
{
|
|
DPRINTFE( "Failed to get flags, error=%s.", strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
if( 0 > fcntl( sock, F_SETFL, flags | O_NONBLOCK ) )
|
|
{
|
|
DPRINTFE( "Failed to set flags, error=%s.", strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Close on exec.
|
|
if( 0 > fcntl( sock, F_SETFD, FD_CLOEXEC ) )
|
|
{
|
|
DPRINTFE( "Failed to set fd, error=%s.", strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Allow address reuse on socket.
|
|
flags = 1;
|
|
result = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR,
|
|
(void*) &flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set reuseaddr socket option on interface (%s), "
|
|
"errno=%s.", interface->interface_name,
|
|
strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Bind address to socket.
|
|
memset( &src_addr, 0, sizeof(src_addr) );
|
|
|
|
src_addr.sin6_family = AF_INET6;
|
|
src_addr.sin6_port = htons(interface->network_port);
|
|
src_addr.sin6_addr = ipv6_address->sin6;
|
|
|
|
result = bind( sock, (struct sockaddr *) &src_addr, sizeof(src_addr) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to bind unicast address to socket for "
|
|
"interface (%s), error=%s.", interface->interface_name,
|
|
strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Bind socket to interface.
|
|
result = setsockopt( sock, SOL_SOCKET, SO_BINDTODEVICE,
|
|
interface->interface_name,
|
|
strlen(interface->interface_name)+1 );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to bind socket to interface (%s), "
|
|
"errno=%s.", interface->interface_name, strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Disable looping of sent multicast packets on socket.
|
|
flags = 0;
|
|
result = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to stop looping of unicast messages for "
|
|
"interface (%s), errno=%s.", interface->interface_name,
|
|
strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set socket send priority on interface.
|
|
flags = IPTOS_CLASS_CS6;
|
|
result = setsockopt( sock, IPPROTO_IPV6, IPV6_TCLASS,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set socket send priority for interface (%s) "
|
|
"unicast messages, errno=%s.", interface->interface_name,
|
|
strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
flags = 6;
|
|
result = setsockopt( sock, SOL_SOCKET, SO_PRIORITY,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set socket send priority for interface (%s) "
|
|
"unicast messages, errno=%s.", interface->interface_name,
|
|
strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
// Set socket receive packet information.
|
|
flags = 1;
|
|
result = setsockopt( sock, SOL_IPV6, IPV6_RECVPKTINFO,
|
|
&flags, sizeof(flags) );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to set socket receive packet information for "
|
|
"interface (%s) unicast messages, errno=%s.",
|
|
interface->interface_name, strerror(errno) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
*socket_fd = sock;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Open Sockets
|
|
// ========================
|
|
SmErrorT sm_msg_open_sockets( SmServiceDomainInterfaceT* interface )
|
|
{
|
|
SmErrorT error;
|
|
|
|
if( SM_NETWORK_TYPE_IPV4_UDP == interface->network_type )
|
|
{
|
|
int unicast_socket, multicast_socket;
|
|
|
|
error = sm_msg_open_ipv4_udp_unicast_socket( interface,
|
|
&unicast_socket );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to open unicast socket for interface (%s), "
|
|
"error=%s.", interface->interface_name,
|
|
sm_error_str(error) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_selobj_register( unicast_socket, sm_msg_dispatch_ipv4_udp,
|
|
(int64_t) false );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to register selection object for "
|
|
"interface (%s), error=%s.", interface->interface_name,
|
|
sm_error_str(error) );
|
|
close( unicast_socket );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
if( interface->network_multicast.type != SM_NETWORK_TYPE_NIL )
|
|
{
|
|
error = sm_msg_open_ipv4_udp_multicast_socket( interface,
|
|
&multicast_socket );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to open multicast socket for interface (%s), "
|
|
"error=%s.", interface->interface_name,
|
|
sm_error_str(error) );
|
|
close( unicast_socket );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_selobj_register( multicast_socket, sm_msg_dispatch_ipv4_udp,
|
|
(int64_t) false );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to register selection object for "
|
|
"interface (%s), error=%s.", interface->interface_name,
|
|
sm_error_str(error) );
|
|
close( unicast_socket );
|
|
close( multicast_socket );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
interface->unicast_socket = unicast_socket;
|
|
interface->multicast_socket = multicast_socket;
|
|
|
|
error = sm_msg_register_ipv4_multicast( interface );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to register multicast address for "
|
|
"interface (%s), error=%s.", interface->interface_name,
|
|
sm_error_str(error) );
|
|
close( unicast_socket );
|
|
interface->unicast_socket = -1;
|
|
close( multicast_socket );
|
|
interface->multicast_socket = -1;
|
|
return( SM_FAILED );
|
|
}
|
|
} else
|
|
{
|
|
DPRINTFD( "Multicast not configured in the interface %s", interface->interface_name );
|
|
interface->unicast_socket = unicast_socket;
|
|
interface->multicast_socket = -1;
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
|
|
} else if( SM_NETWORK_TYPE_IPV6_UDP == interface->network_type ) {
|
|
int unicast_socket, multicast_socket;
|
|
|
|
error = sm_msg_open_ipv6_udp_unicast_socket( interface,
|
|
&unicast_socket );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to open unicast socket for interface (%s), "
|
|
"error=%s.", interface->interface_name,
|
|
sm_error_str(error) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_selobj_register( unicast_socket, sm_msg_dispatch_ipv6_udp,
|
|
(int64_t) false);
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to register selection object for "
|
|
"interface (%s), error=%s.", interface->interface_name,
|
|
sm_error_str(error) );
|
|
close( unicast_socket );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
if( interface->network_multicast.type != SM_NETWORK_TYPE_NIL )
|
|
{
|
|
error = sm_msg_open_ipv6_udp_multicast_socket( interface,
|
|
&multicast_socket );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to open multicast socket for interface (%s), "
|
|
"error=%s.", interface->interface_name,
|
|
sm_error_str(error) );
|
|
close( unicast_socket );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_selobj_register( multicast_socket, sm_msg_dispatch_ipv6_udp,
|
|
(int64_t) false );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to register selection object for "
|
|
"interface (%s), error=%s.", interface->interface_name,
|
|
sm_error_str(error) );
|
|
close( unicast_socket );
|
|
close( multicast_socket );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
interface->unicast_socket = unicast_socket;
|
|
interface->multicast_socket = multicast_socket;
|
|
|
|
error = sm_msg_register_ipv6_multicast( interface );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to register multicast address for "
|
|
"interface (%s), error=%s.", interface->interface_name,
|
|
sm_error_str(error) );
|
|
close( unicast_socket );
|
|
interface->unicast_socket = -1;
|
|
close( multicast_socket );
|
|
interface->multicast_socket = -1;
|
|
return( SM_FAILED );
|
|
}
|
|
} else
|
|
{
|
|
interface->unicast_socket = unicast_socket;
|
|
interface->multicast_socket = -1;
|
|
}
|
|
return( SM_OKAY );
|
|
|
|
} else {
|
|
DPRINTFE( "Unsupported network type (%s).",
|
|
sm_network_type_str( interface->network_type ) );
|
|
return( SM_FAILED );
|
|
}
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Close Sockets
|
|
// =========================
|
|
SmErrorT sm_msg_close_sockets( SmServiceDomainInterfaceT* interface )
|
|
{
|
|
SmErrorT error;
|
|
|
|
if( -1 < interface->unicast_socket )
|
|
{
|
|
error = sm_selobj_deregister( interface->unicast_socket );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to deregister selection object for "
|
|
"interface (%s), error=%s.", interface->interface_name,
|
|
sm_error_str(error) );
|
|
}
|
|
|
|
close( interface->unicast_socket );
|
|
interface->unicast_socket = -1;
|
|
}
|
|
|
|
if( -1 < interface->multicast_socket )
|
|
{
|
|
error = sm_selobj_deregister( interface->multicast_socket );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to deregister selection object for "
|
|
"interface (%s), error=%s.", interface->interface_name,
|
|
sm_error_str(error) );
|
|
}
|
|
|
|
if(( SM_NETWORK_TYPE_IPV4_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV4 == interface->network_type ))
|
|
{
|
|
error = sm_msg_deregister_ipv4_multicast( interface );
|
|
|
|
} else if(( SM_NETWORK_TYPE_IPV6_UDP == interface->network_type )||
|
|
( SM_NETWORK_TYPE_IPV6 == interface->network_type ))
|
|
{
|
|
error = sm_msg_deregister_ipv6_multicast( interface );
|
|
}
|
|
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to deregister multicast address for "
|
|
"interface (%s), error=%s.", interface->interface_name,
|
|
sm_error_str(error) );
|
|
}
|
|
|
|
close( interface->multicast_socket );
|
|
interface->multicast_socket = -1;
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Dump Data
|
|
// =====================
|
|
void sm_msg_dump_data( FILE* log )
|
|
{
|
|
fprintf( log, "--------------------------------------------------------------------\n" );
|
|
fprintf( log, "MESSAGING DATA\n" );
|
|
fprintf( log, " rcvd_total_msgs..............................%" PRIu64 "\n", _rcvd_total_msgs );
|
|
fprintf( log, " rcvd_msgs_while_disabled.....................%" PRIu64 "\n", _rcvd_msgs_while_disabled );
|
|
fprintf( log, " rcvd_bad_msg_auth............................%" PRIu64 "\n", _rcvd_bad_msg_auth );
|
|
fprintf( log, " rcvd_bad_msg_version.........................%" PRIu64 "\n", _rcvd_bad_msg_version );
|
|
fprintf( log, " send_node_hello_count........................%" PRIu64 "\n", _send_node_hello_cnt );
|
|
fprintf( log, " rcvd_node_hello_count........................%" PRIu64 "\n", _rcvd_node_hello_cnt );
|
|
fprintf( log, " send_node_update_count.......................%" PRIu64 "\n", _send_node_update_cnt );
|
|
fprintf( log, " rcvd_node_update_count.......................%" PRIu64 "\n", _rcvd_node_update_cnt );
|
|
fprintf( log, " send_node_swact_count........................%" PRIu64 "\n", _send_node_swact_cnt );
|
|
fprintf( log, " rcvd_node_swact_count........................%" PRIu64 "\n", _rcvd_node_swact_cnt );
|
|
fprintf( log, " send_node_swact_ack_count....................%" PRIu64 "\n", _send_node_swact_ack_cnt );
|
|
fprintf( log, " rcvd_node_swact_ack_count....................%" PRIu64 "\n", _rcvd_node_swact_ack_cnt );
|
|
fprintf( log, " send_service_domain_hello_count..............%" PRIu64 "\n", _send_service_domain_hello_cnt );
|
|
fprintf( log, " rcvd_service_domain_hello_count..............%" PRIu64 "\n", _rcvd_service_domain_hello_cnt );
|
|
fprintf( log, " send_service_domain_pause_count..............%" PRIu64 "\n", _send_service_domain_pause_cnt );
|
|
fprintf( log, " rcvd_service_domain_pause_count..............%" PRIu64 "\n", _rcvd_service_domain_pause_cnt );
|
|
fprintf( log, " send_service_domain_exchange_start_count.....%" PRIu64 "\n", _send_service_domain_exchange_start_cnt );
|
|
fprintf( log, " rcvd_service_domain_exchange_start_count.....%" PRIu64 "\n", _rcvd_service_domain_exchange_start_cnt );
|
|
fprintf( log, " send_service_domain_exchange_count...........%" PRIu64 "\n", _send_service_domain_exchange_cnt );
|
|
fprintf( log, " rcvd_service_domain_exchange_count...........%" PRIu64 "\n", _rcvd_service_domain_exchange_cnt );
|
|
fprintf( log, " send_service_domain_member_request_count.....%" PRIu64 "\n", _send_service_domain_member_request_cnt );
|
|
fprintf( log, " rcvd_service_domain_member_request_count.....%" PRIu64 "\n", _rcvd_service_domain_member_request_cnt );
|
|
fprintf( log, " send_service_domain_member_update_count......%" PRIu64 "\n", _send_service_domain_member_update_cnt );
|
|
fprintf( log, " rcvd_service_domain_member_update_count......%" PRIu64 "\n", _rcvd_service_domain_member_update_cnt );
|
|
fprintf( log, "--------------------------------------------------------------------\n" );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Initialize
|
|
// ======================
|
|
SmErrorT sm_msg_initialize( void )
|
|
{
|
|
SmErrorT error;
|
|
|
|
_hostname[0] = '\0';
|
|
|
|
error = sm_node_utils_get_hostname( _hostname );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to get local hostname." );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
_messaging_enabled = false;
|
|
sm_uuid_create( _msg_instance );
|
|
DPRINTFI( "Message instance (%s) created.", _msg_instance );
|
|
|
|
|
|
DPRINTFV( "Hello message size is %i.", sizeof(SmMsgNodeHelloT) );
|
|
DPRINTFV( "Node update message size is %i.", sizeof(SmMsgNodeUpdateT) );
|
|
DPRINTFV( "Swact message size is %i.", sizeof(SmMsgNodeSwactT) );
|
|
DPRINTFV( "Swact ack message size is %i.", sizeof(SmMsgNodeSwactAckT) );
|
|
DPRINTFV( "Service Domain Hello message size is %i.",
|
|
sizeof(SmMsgServiceDomainHelloT) );
|
|
DPRINTFV( "Service Domain Pause message size is %i.",
|
|
sizeof(SmMsgServiceDomainPauseT) );
|
|
DPRINTFV( "Service Domain Exchange Start message size is %i.",
|
|
sizeof(SmMsgServiceDomainExchangeStartT) );
|
|
DPRINTFV( "Service Domain Exchange message size is %i.",
|
|
sizeof(SmMsgServiceDomainExchangeT) );
|
|
DPRINTFV( "Service Domain Member Request message size is %i.",
|
|
sizeof(SmMsgServiceDomainMemberRequestT) );
|
|
DPRINTFV( "Service Domain Member Update message size is %i.",
|
|
sizeof(SmMsgServiceDomainMemberUpdateT) );
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Messaging - Finalize
|
|
// ====================
|
|
SmErrorT sm_msg_finalize( void )
|
|
{
|
|
_hostname[0] = '\0';
|
|
_messaging_enabled = false;
|
|
memset( _msg_instance, 0, sizeof(_msg_instance) );
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|