ex_dscp.c revision 25cf1a301a396c38e8adf52c15f537b80d2483f7
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CDDL HEADER START
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The contents of this file are subject to the terms of the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Common Development and Distribution License (the "License").
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * You may not use this file except in compliance with the License.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * See the License for the specific language governing permissions
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * and limitations under the License.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * When distributing Covered Code, include this CDDL HEADER in each
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If applicable, add the following below this CDDL HEADER, with the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * fields enclosed by brackets "[]" replaced with your own identifying
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * information: Portions Copyright [yyyy] [name of copyright owner]
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CDDL HEADER END
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Use is subject to license terms.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#pragma ident "%Z%%M% %I% %E% SMI"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * FMA Event Transport Module Transport Layer API implementation.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Library for establishing connections and transporting FMA events between
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * ETMs (event-transport modules) in separate fault domains.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The transport for this library is internet socket based and uses the DSCP
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * client services library (libdscp).
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Transport Layer handle implementations
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* Connection handle */
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct etm_xport_sock_conn {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct sockaddr_in c_saddr; /* Sockaddr for DSCP connection */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* Transport instance handle */
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct etm_xport_sock_hdl {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*h_cb_func)(fmd_hdl_t *, etm_xport_conn_t, etm_cb_flag_t, void *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Callback function for ETM common */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *h_cb_func_arg; /* Arg to pass when calling h_cb_func */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* For the socket */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define EXS_SERVER_ADDR in6addr_any /* Address for server */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define EXS_SD_FREE -1 /* Socket descr value when unset */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define EXS_DOMAIN_PREFIX "dom" /* Domain auth prefix in FMRI string */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define EXS_DOMAIN_PREFIX_LEN 3 /* Length of domain prefix */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define EXS_SP_PREFIX "sp" /* SP auth prefix in FMRI string */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define EXS_IO_SLEEP_DIV 100 /* Divisor for I/O sleeptime */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Global variables
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Status of Server */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic pthread_t Server_tid = 0; /* Thread ID of Server */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic exs_conn_t Acceptor_conn; /* Connection handle for Acceptor */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic pthread_mutex_t Mod_lock = PTHREAD_MUTEX_INITIALIZER;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Protects globals (above) */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic exs_hdl_t *Exh_head = NULL; /* Head of ex_hdl_t list */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic pthread_mutex_t List_lock = PTHREAD_MUTEX_INITIALIZER;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Protects linked list of ex_hdl_t */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Mutex lock order
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * (1) List_lock
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * (2) hp->h_lock
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * (3) Mod_lock
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Module specific routines.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Allocate and initialize a transport instance handle.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return hdl pointer for success, NULL for failure.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*cb_func)(fmd_hdl_t *hdl, etm_xport_conn_t conn, etm_cb_flag_t flag,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hp->h_endpt_id = fmd_hdl_strdup(hdl, endpoint_id, FMD_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (hp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Prepare the client connection.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return 0 for success, nonzero for failure.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Find the DSCP address for the remote endpoint */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((hp->h_client.c_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fmd_hdl_debug(hdl, "xport - client socket failed for %s",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Bind the socket to the local IP address of the DSCP link */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fmd_hdl_debug(hdl, "xport - client bind for %s failed: %d",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Set IPsec security policy for this socket */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((rv = dscpSecure(hp->h_domain_id, hp->h_client.c_sd)) != DSCP_OK) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fmd_hdl_debug(hdl, "xport - dscpSecure for %s failed: %d",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Prepare to accept a connection.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Assume Mod_lock is held by caller.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return 0 for success, nonzero for failure.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((Acceptor_conn.c_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (setsockopt(Acceptor_conn.c_sd, SOL_SOCKET, SO_REUSEADDR,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Bind the socket to the local IP address of the DSCP link */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fmd_hdl_debug(hdl, "xport - acceptor bind failed: %d", rv);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Activate IPsec security policy for this socket */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((rv = dscpSecure(domain, Acceptor_conn.c_sd)) != DSCP_OK) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fmd_hdl_debug(hdl, "xport - dscpSecure for acceptor failed: %d",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) fcntl(Acceptor_conn.c_sd, F_SETFL, flags | O_NONBLOCK);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Translate endpoint_id str to int.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return the domain ID via "dom_id".
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return 0 for success, nonzero for failure
25cf1a301a396c38e8adf52c15f537b80d2483f7jlexs_get_id(fmd_hdl_t *hdl, char *endpoint_id, int *dom_id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Remote endpoint is the SP */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((ptr = strstr(endpoint_id, EXS_DOMAIN_PREFIX)) == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Build set of socket descriptors based on the current list of exs_hdl_t.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return the largest descriptor.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fmd_hdl_debug(hdl, "xport - building set of socket descr");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Use getsockname to test for valid socket descr */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Find the exs_hdl_t associated with the given sockaddr_in.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Assume caller holds lock on List_lock.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return the exs_hdl_t for success, NULL for failure.
25cf1a301a396c38e8adf52c15f537b80d2483f7jlexs_find_hdl(fmd_hdl_t *hdl, struct sockaddr_in *saddr, socklen_t salen)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Translate saddr to a domain id string */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((rv = dscpIdent((struct sockaddr *)saddr, (int)salen,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fmd_hdl_debug(hdl, "xport - dscpIdent failed for 0x%x : %d",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fmd_hdl_debug(hdl, "xport - dscpAuth failed for 0x%x : %d",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Lookup this domain id */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Main server function, runs on thread started at init.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Accepts incoming connections and notifies ETM of incoming data.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Thread/function runs until Server_status changes to S_DOEXIT.
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct sockaddr_in new_saddr; /* Sockaddr of remote endpt */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* First check if a new connection has arrived */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "connection for %s",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Set the socket to be non-blocking */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Add this socket descriptor to the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * fd_set and remove the old one.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "xport - no tlhdl for endpt 0x%x",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "xport - accept failed");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (--nready <= 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* No more sockets to check */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Check if any of the other sockets have data to recv */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Data is available on this socket
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * or the remote side has closed.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Remove the socket descriptor from
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the fd_set
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Close the server socket */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (--nready <= 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* No more sockets to check */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fmd_hdl_debug(hdl, "xport - exiting server thread %d", Server_tid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Thread dies */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * ETM-to-Transport API Connection Management routines
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Initialize and setup any transport infrastructure before any connections
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * are opened.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return etm_xport_hdl_t for success, NULL for failure.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*cb_func)(fmd_hdl_t *hdl, etm_xport_conn_t conn, etm_cb_flag_t flag,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* This is the first init */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Check for a duplicate endpoint_id on the list */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Alloc and init a transport instance handle */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hp = exs_hdl_alloc(hdl, endpoint_id, cb_func, cb_func_arg,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Prep the client-side connection */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Add this transport instance handle to the list */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Create the Server thread, if necessary */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Teardown any transport infrastructure after all connections are closed.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return 0 for success, or nonzero for failure.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Remove this handle from the list */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fmd_hdl_debug(hdl, "xport - fini failed, tlhdl %p not on list",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* If this is the last handle, cleanup and exit the Server thread */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Close the handle's client connection */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Close the handle's server connection and remove it from the fd_set
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * used in the Server thread.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Open a connection with the given endpoint,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return etm_xport_conn_t for success, NULL and set errno for failure.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fmd_hdl_error(hdl, "xport - failed connect to server for %s",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Set the socket to be non-blocking */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) fcntl(hp->h_client.c_sd, F_SETFL, flags | O_NONBLOCK);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fmd_hdl_debug(hdl, "xport - connected client socket for %s",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Close a connection from either endpoint.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return zero for success, nonzero for failure.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0); /* Connection already closed */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * ETM-to-Transport API I/O routines
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Try to read byte_cnt bytes from the connection into the given buffer.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return how many bytes actually read for success, negative value for failure.
25cf1a301a396c38e8adf52c15f537b80d2483f7jletm_xport_read(fmd_hdl_t *hdl, etm_xport_conn_t conn, hrtime_t timeout,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-EBADF);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0)) < 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else if (len == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Try to write byte_cnt bytes to the connection from the given buffer.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return how many bytes actually written for success, negative value
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * for failure.
25cf1a301a396c38e8adf52c15f537b80d2483f7jletm_xport_write(fmd_hdl_t *hdl, etm_xport_conn_t conn, hrtime_t timeout,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fmd_hdl_debug(hdl, "xport - write socket %d is closed\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-EBADF);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0)) < 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);