ldom_xmpp_client.c revision f044df33d9fe9e8e3ed7344a8b548b17f20709f2
/*
* 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
*/
/*
*/
/*
* ldom_xmpp_client.c Extensible Messaging and Presence Protocol (XMPP)
*
* Implement an xmpp client to subscribe for domain events from the ldmd.
* Notify fmd module clients upon receiving the events.
*
*/
#include "ldom_xmpp_client.h"
#include "ldom_alloc.h"
#include "ldom_utils.h"
#include <stdio.h>
#include <signal.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <dlfcn.h>
#include <fcntl.h>
typedef enum conn_state {
} conn_state_t;
typedef struct xmpp_conn {
int fd;
int state;
} xmpp_conn_t;
/* Forward declaration */
static int xmpp_enable = 0;
static int xmpp_notify_pipe[2];
_ret += -1; \
}
/*
* Prototypes and pointers to functions needed from libssl.
*/
typedef void (*SSL_load_error_strings_pt)(void);
typedef int (*SSL_library_init_pt)(void);
typedef SSL_METHOD *(*SSLv23_client_method_pt)(void);
int type);
typedef long (*ERR_get_error_pt)(void);
typedef char *(*ERR_error_string_pt)(unsigned long e, char *buf);
const char *file);
static ldom_event_info_t event_table[] = {
{ LDOM_EVENT_UNKNOWN, "unknown" },
{ LDOM_EVENT_ADD, "add-domain" },
{ LDOM_EVENT_REMOVE, "remove-domain" },
{ LDOM_EVENT_BIND, "bind-domain" },
{ LDOM_EVENT_UNBIND, "unbind-domain" },
{ LDOM_EVENT_START, "start-domain" },
{ LDOM_EVENT_STOP, "stop-domain" },
{ LDOM_EVENT_RESET, "domain-reset" },
{ LDOM_EVENT_PANIC, "panic-domain" },
{ LDOM_EVENT_MAX, NULL }
};
static int event_table_size = \
sizeof (event_table) / sizeof (ldom_event_info_t);
static xmlSAXHandler xml_handler = {
NULL, /* internalSubsetSAXFunc */
NULL, /* isStandaloneSAXFunc */
NULL, /* hasInternalSubsetSAXFunc */
NULL, /* hasExternalSubsetSAXFunc */
NULL, /* resolveEntitySAXFunc */
NULL, /* getEntitySAXFunc */
NULL, /* entityDeclSAXFunc */
NULL, /* notationDeclSAXFunc */
NULL, /* attributeDeclSAXFunc */
NULL, /* elementDeclSAXFunc */
NULL, /* unparsedEntityDeclSAXFunc */
NULL, /* setDocumentLocatorSAXFunc */
NULL, /* startDocumentSAXFunc */
NULL, /* endDocumentSAXFunc */
start_element, /* startElementSAXFunc */
end_element, /* endElementSAXFunc */
NULL, /* referenceSAXFunc */
NULL, /* charactersSAXFunc */
NULL, /* ignorableWhitespaceSAXFunc */
NULL, /* processingInstructionSAXFunc */
NULL, /* commentSAXFunc */
NULL, /* warningSAXFunc */
error_func, /* errorSAXFunc */
NULL, /* fatalErrorSAXFunc */
NULL, /* getParameterEntitySAXFunc */
NULL, /* cdataBlockSAXFunc */
NULL, /* externalSubsetSAXFunc */
0, /* unsigned int */
NULL, /* void * _private */
NULL, /* startElementNsSAX2Func */
NULL, /* endElementNsSAX2Func */
NULL /* xmlStructuredErrorFunc */
};
static void
{
}
strlen((char *)LDM_REG_DOMAIN_EVENTS));
}
}
}
/*ARGSUSED*/
static void
{
}
/*ARGSUSED*/
static void
{
}
static int
{
int sock;
struct sockaddr_in serveraddr;
return (-1);
}
sizeof (struct sockaddr_in)) < 0) {
return (-1);
}
return (-1);
}
return (0);
}
static void
{
}
if (conn->tls_started) {
}
}
static int
{
int count;
if (conn->tls_started) {
} else {
}
if (count <= 0) {
}
return (count);
}
static int
{
int count;
if (conn->tls_started) {
} else {
}
if (count <= 0) {
}
return (count);
}
/*
* notify_event()
* Description:
* Notify all clients an event by going through the client list and invoke
* the callback functions.
*/
static void
{
client_info_t *p;
}
}
/*
* xmpp_client_thr()
* Description:
* The main entry fo the xmpp client thread.
*/
/*ARGSUSED*/
static void *
xmpp_client_thr(void *data)
{
int rc = 0;
int cnt;
char buf[XMPP_BUF_SIZE];
while (xmpp_enable) {
/* clear the conn struct */
/* keep making a connection until successfully */
do {
(void) sleep(XMPP_SLEEP);
} while (rc != 0 && xmpp_enable);
/* write the stream node */
strlen((char *)STREAM_START));
xmpp_close(&conn);
(void) sleep(XMPP_SLEEP);
continue;
}
/* process input */
/* Wait for xmpp input or the notification */
break;
/* Receive a notification to exit */
xmpp_close(&conn);
pthread_exit((void *)NULL);
}
/*
* Assume the document size of a ldmd response is
* less than 1KB. This assumption is valid with the
* current ldmd implementation.
* Should the document size exceeds 1KB, the buffer
* size should be revisited accordingly.
*/
if (cnt <= 0)
break;
}
case CONN_STATE_LDM_INTERFACE:
break;
case CONN_STATE_LDM_EVENT:
break;
default:
break;
}
/*
* For now, the parser is reset after every read.
* It should only be reset once after the ssl is opened
* in the start_tls().
*/
NULL);
}
xmpp_close(&conn);
(void) sleep(XMPP_SLEEP);
}
return (NULL);
}
/*
* find_client()
* Description:
* Walk to the list to find a libldom client
*/
static client_info_t *
{
client_info_t *p;
return (p);
}
return (NULL);
}
/*
* xmpp_add_client()
* Description:
* Add a libldom client from the client list.
*/
int
{
if (find_client(lhp)) {
/* already exists */
return (-1);
}
/* new client */
} else {
/* append to the list */
}
return (0);
}
/*
* xmpp_remove_client()
* Description:
* Remove a libldom client from the client list.
*/
int
{
client_info_t *p;
/* not present */
return (-1);
}
/* single item list */
/* delete the head */
/* delete the tail */
} else {
/* delete a middle node */
}
ldom_free(p, sizeof (client_info_t));
return (0);
}
/*
* xmpp_stop()
* Description:
* Stop the xmpp client thread
*/
/*ARGSUSED*/
void
xmpp_stop(void)
{
(void) pthread_mutex_lock(&xmpp_tid_lock);
xmpp_enable = 0;
if (xmpp_tid) {
/*
* Write a byte to the pipe to notify the xmpp thread to exit.
* Then wait for it to exit.
*/
xmpp_tid = 0;
}
(void) pthread_mutex_unlock(&xmpp_tid_lock);
}
/*
* xmpp_start()
* Description:
* Start the xmpp client thread if have not done so.
*/
void
xmpp_start(void)
{
/* Check if the xmmp thread has already started */
(void) pthread_mutex_lock(&xmpp_tid_lock);
if (xmpp_tid != 0) {
(void) pthread_mutex_unlock(&xmpp_tid_lock);
return;
}
/* Check if the ldmd supports xmpp by opening a connection */
if (xmpp_connect(&conn)) {
(void) pthread_mutex_unlock(&xmpp_tid_lock);
return;
}
xmpp_close(&conn);
xmpp_enable = 1;
/*
* create xmpp client thread for receiving domain events.
* The notification pipe is for stopping the thread.
*/
(void) notify_setup(xmpp_notify_pipe);
(void) pthread_mutex_unlock(&xmpp_tid_lock);
/*
* Register a function to stop the above thread upon a termination
*/
}
/*
* This routine will run through the first time we get a remote XMPP
* connection. After that we will not need to do this again. It cannot be run
* from main thread at start as we need to alert remote users if the TLS
* handshake failed.
*/
static int
{
int ret = 0;
/* If we have already opened the library no need to do it again. */
return (0);
/*
* If the libssl.so in not in the default path, attempt to open it
*/
return (-1);
}
"SSL_library_init", ret);
"SSL_CTX_new", ret);
"SSLv23_client_method", ret);
"SSL_CTX_use_PrivateKey_file", ret);
"SSL_get_error", ret);
"ERR_get_error", ret);
"ERR_error_string", ret);
ret);
"SSL_CTX_use_certificate_chain_file", ret);
"SSL_get_SSL_CTX", ret);
"SSL_CTX_free", ret);
if (ret < 0)
return (-1);
else
return (0);
}
/*
* start_tls()
* Description:
* Load the libssl.so if has not done so and open a ssl connection.
* It is assumed that there is one xmpp thread to use the ssl connection.
* If multi-thread xmpp clients use the ssl connection, addtional work is
* needed to ensure the usage of the ssl be thread-safe.
*/
static int
{
char rand_buf[RAND_BUF_SIZE];
rv = load_SSL_lib();
if (rv == -1) {
return (rv);
}
if (urand_fd == -1) {
return (-1);
}
return (-1);
}
if (rv == 0) {
return (-1);
}
if (rv != 1) {
return (-1);
}
return (0);
}
/*
* Find and return the first-level subnode (if any) of 'node' which has name
* 'name'.
*/
{
return (NULL);
break;
}
return (subnode);
}
/*
* handle_ldm_resp()
* Description:
* Parse the ldmd response of the domain event registration for the failure
* status. If found, set the connection to failure so that it will be
* closed and a new xmpp connection is established.
*/
void
{
char *status_str, *action_str;
return;
return;
/* get the cmd node */
return;
return;
/* get the action node and make sure it is the reg-domain-events */
return;
}
return;
return;
}
/* check the status of the response */
return;
return;
return;
}
}
/*
* handle_ldm_event()
* Description:
* Parse the LDM_event for the ldom name and domain action. Then invokes
* the clients's callback to notify them the event.
*/
/*ARGSUSED*/
void
{
int i;
char *action_str, *ldom_name;
return;
return;
/* get the action such as bind-domain, unbind-domain, etc. */
return;
return;
}
return;
for (i = 0; i < event_table_size; i++) {
break;
}
}
/* get the ldom name */
return;
/* Notifies all the clients the event */
if (VALID_LDOM_EVENT(event)) {
}
}