ex_dscp.c revision 25cf1a301a396c38e8adf52c15f537b80d2483f7
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* FMA Event Transport Module Transport Layer API implementation.
*
* Library for establishing connections and transporting FMA events between
* ETMs (event-transport modules) in separate fault domains.
*
* The transport for this library is internet socket based and uses the DSCP
* client services library (libdscp).
*/
#include <unistd.h>
#include <strings.h>
#include <fcntl.h>
#include <netdb.h>
#include <pthread.h>
#include <errno.h>
#include <time.h>
#include <libdscp.h>
#include "etm_xport_api.h"
/*
* Transport Layer handle implementations
*/
/* Connection handle */
typedef struct etm_xport_sock_conn {
int c_len; /* Length of saddr */
int c_sd; /* Socket descriptor */
} exs_conn_t;
typedef enum etm_xport_sock_status {
S_WAITING, /* Server thread is waiting to start */
S_RUNNING, /* Server thread is running */
S_DOEXIT /* Server thread needs to exit */
} exs_status_t;
/* Transport instance handle */
typedef struct etm_xport_sock_hdl {
char *h_endpt_id; /* Endpoint id from ETM common */
int h_domain_id; /* Domain ID from platform (libdscp) */
/* Callback function for ETM common */
void *h_cb_func_arg; /* Arg to pass when calling h_cb_func */
struct etm_xport_sock_hdl *h_next;
} exs_hdl_t;
/* For the socket */
#define EXS_CLIENT_PORT 0 /* Port number for client */
/*
* Global variables
*/
/* Status of Server */
/* Protects globals (above) */
/* Protects linked list of ex_hdl_t */
/*
* Mutex lock order
* (1) List_lock
* (2) hp->h_lock
* (3) Mod_lock
*/
/*
* Module specific routines.
*/
/*
* Allocate and initialize a transport instance handle.
* Return hdl pointer for success, NULL for failure.
*/
static exs_hdl_t *
{
return (hp);
}
/*
* Prepare the client connection.
* Return 0 for success, nonzero for failure.
*/
static int
{
int rv;
/* Find the DSCP address for the remote endpoint */
return (1);
}
hp->h_endpt_id);
return (1);
}
/* Bind the socket to the local IP address of the DSCP link */
EXS_CLIENT_PORT)) != DSCP_OK) {
return (1);
}
/* Set IPsec security policy for this socket */
return (1);
}
return (0);
}
/*
* Prepare to accept a connection.
* Assume Mod_lock is held by caller.
* Return 0 for success, nonzero for failure.
*/
static int
{
int rv;
return (1);
}
return (1);
}
/* Bind the socket to the local IP address of the DSCP link */
EXS_SERVER_PORT)) != DSCP_OK) {
return (1);
}
/* Activate IPsec security policy for this socket */
rv);
return (1);
}
return (1);
}
return (0);
}
/*
* Translate endpoint_id str to int.
* Return the domain ID via "dom_id".
* Return 0 for success, nonzero for failure
*/
static int
{
char *ptr;
/* Remote endpoint is the SP */
*dom_id = DSCP_IDENT_SP;
return (0);
} else {
return (1);
}
return (1);
}
}
return (0);
}
/*
* Build set of socket descriptors based on the current list of exs_hdl_t.
* Return the largest descriptor.
*/
static int
{
int max_sd = 0;
(void) pthread_mutex_lock(&List_lock);
/* Use getsockname to test for valid socket descr */
else
}
}
(void) pthread_mutex_unlock(&List_lock);
(void) pthread_mutex_lock(&Mod_lock);
(void) pthread_mutex_unlock(&Mod_lock);
if (max_sd > FD_SETSIZE)
return (max_sd);
}
/*
* Find the exs_hdl_t associated with the given sockaddr_in.
* Assume caller holds lock on List_lock.
* Return the exs_hdl_t for success, NULL for failure.
*/
static exs_hdl_t *
{
/* Translate saddr to a domain id string */
return (NULL);
}
return (NULL);
}
/* Lookup this domain id */
break;
}
return (curr);
}
/*
* Main server function, runs on thread started at init.
* Accepts incoming connections and notifies ETM of incoming data.
*/
static void
exs_server(void *arg)
{
int new_sd; /* Socket desc of new conn */
int nready; /* Num readable sockets from select */
int max_sd; /* Max socket desc : for select */
(void) pthread_mutex_lock(&Mod_lock);
while (Server_status != S_DOEXIT) {
(void) pthread_mutex_unlock(&Mod_lock);
NULL)) == -1) {
else
(void) pthread_mutex_lock(&Mod_lock);
continue;
}
/* First check if a new connection has arrived */
(void) pthread_mutex_lock(&List_lock);
"connection for %s",
hp->h_endpt_id);
}
/* Set the socket to be non-blocking */
F_GETFL, 0);
(void) pthread_mutex_unlock(
(void) pthread_mutex_unlock(&List_lock);
/*
* Add this socket descriptor to the
* fd_set and remove the old one.
*/
(void) pthread_mutex_lock(&Mod_lock);
if (old_sd) {
old_sd = 0;
}
(void) pthread_mutex_unlock(&Mod_lock);
} else {
(void) pthread_mutex_unlock(&List_lock);
"xport - no tlhdl for endpt 0x%x",
}
} else {
"xport - accept failed");
}
if (--nready <= 0) {
/* No more sockets to check */
(void) pthread_mutex_lock(&Mod_lock);
continue;
}
}
/* Check if any of the other sockets have data to recv */
(void) pthread_mutex_lock(&List_lock);
continue;
}
/*
* Data is available on this socket
* or the remote side has closed.
*/
hp->h_cb_func_arg)) != 0) {
/*
* Remove the socket descriptor from
* the fd_set
*/
(void) pthread_mutex_lock(&Mod_lock);
(void) pthread_mutex_unlock(&Mod_lock);
/* Close the server socket */
}
if (--nready <= 0) {
/* No more sockets to check */
(void) pthread_mutex_unlock(
break;
}
}
}
(void) pthread_mutex_unlock(&List_lock);
(void) pthread_mutex_lock(&Mod_lock);
}
Server_tid = 0;
(void) pthread_mutex_unlock(&Mod_lock);
/* Thread dies */
}
/*
* ETM-to-Transport API Connection Management routines
*/
/*
* Initialize and setup any transport infrastructure before any connections
* are opened.
* Return etm_xport_hdl_t for success, NULL for failure.
*/
void *arg), void *cb_func_arg)
{
int domain_id;
return (NULL);
(void) pthread_mutex_lock(&List_lock);
/* This is the first init */
(void) pthread_mutex_lock(&Mod_lock);
if (exs_prep_accept(hdl)) {
(void) pthread_mutex_unlock(&Mod_lock);
(void) pthread_mutex_unlock(&List_lock);
return (NULL);
}
(void) pthread_mutex_unlock(&Mod_lock);
} else {
/* Check for a duplicate endpoint_id on the list */
"duplicate domain_id : %d\n", domain_id);
(void) pthread_mutex_unlock(&List_lock);
return (NULL);
}
}
}
/* Alloc and init a transport instance handle */
/* Prep the client-side connection */
(void) pthread_mutex_lock(&Mod_lock);
}
(void) pthread_mutex_unlock(&Mod_lock);
}
(void) pthread_mutex_unlock(&List_lock);
return (NULL);
}
/* Add this transport instance handle to the list */
(void) pthread_mutex_unlock(&List_lock);
/* Create the Server thread, if necessary */
(void) pthread_mutex_lock(&Mod_lock);
if (Server_tid == 0)
(void) pthread_mutex_unlock(&Mod_lock);
return ((etm_xport_hdl_t)hp);
}
/*
* Teardown any transport infrastructure after all connections are closed.
* Return 0 for success, or nonzero for failure.
*/
int
{
/* Remove this handle from the list */
(void) pthread_mutex_lock(&List_lock);
break;
}
(void) pthread_mutex_unlock(&List_lock);
curr);
return (1);
}
else
/* If this is the last handle, cleanup and exit the Server thread */
(void) pthread_mutex_lock(&Mod_lock);
(void) pthread_mutex_unlock(&Mod_lock);
}
(void) pthread_mutex_unlock(&List_lock);
/* Close the handle's client connection */
/*
* Close the handle's server connection and remove it from the fd_set
* used in the Server thread.
*/
(void) pthread_mutex_lock(&Mod_lock);
(void) pthread_mutex_unlock(&Mod_lock);
}
return (0);
}
/*
* Open a connection with the given endpoint,
* Return etm_xport_conn_t for success, NULL and set errno for failure.
*/
{
int flags;
return (NULL);
}
hp->h_endpt_id);
return (NULL);
}
/* Set the socket to be non-blocking */
hp->h_endpt_id);
}
/*
* Close a connection from either endpoint.
* Return zero for success, nonzero for failure.
*/
/*ARGSUSED*/
int
{
return (0); /* Connection already closed */
return (0);
}
/*
* ETM-to-Transport API I/O routines
*/
/*
* Try to read byte_cnt bytes from the connection into the given buffer.
* Return how many bytes actually read for success, negative value for failure.
*/
{
return (-EBADF);
}
0)) < 0) {
}
continue;
} else if (len == 0) {
return (0);
}
} else {
break;
}
}
if (nbytes)
return (nbytes);
else
return (-1);
}
/*
* Try to write byte_cnt bytes to the connection from the given buffer.
* Return how many bytes actually written for success, negative value
* for failure.
*/
{
return (-EBADF);
}
0)) < 0) {
}
continue;
}
} else {
break;
}
}
if (nbytes)
return (nbytes);
else
return (-1);
}