17850SVuong.Nguyen@Sun.COM /*
27850SVuong.Nguyen@Sun.COM * CDDL HEADER START
37850SVuong.Nguyen@Sun.COM *
47850SVuong.Nguyen@Sun.COM * The contents of this file are subject to the terms of the
57850SVuong.Nguyen@Sun.COM * Common Development and Distribution License (the "License").
67850SVuong.Nguyen@Sun.COM * You may not use this file except in compliance with the License.
77850SVuong.Nguyen@Sun.COM *
87850SVuong.Nguyen@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97850SVuong.Nguyen@Sun.COM * or http://www.opensolaris.org/os/licensing.
107850SVuong.Nguyen@Sun.COM * See the License for the specific language governing permissions
117850SVuong.Nguyen@Sun.COM * and limitations under the License.
127850SVuong.Nguyen@Sun.COM *
137850SVuong.Nguyen@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147850SVuong.Nguyen@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157850SVuong.Nguyen@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167850SVuong.Nguyen@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177850SVuong.Nguyen@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187850SVuong.Nguyen@Sun.COM *
197850SVuong.Nguyen@Sun.COM * CDDL HEADER END
207850SVuong.Nguyen@Sun.COM */
217850SVuong.Nguyen@Sun.COM /*
22*12516SVuong.Nguyen@Sun.COM * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
237850SVuong.Nguyen@Sun.COM */
247850SVuong.Nguyen@Sun.COM
257850SVuong.Nguyen@Sun.COM /*
268357SVuong.Nguyen@Sun.COM * ldom_xmpp_client.c Extensible Messaging and Presence Protocol (XMPP)
277850SVuong.Nguyen@Sun.COM *
287850SVuong.Nguyen@Sun.COM * Implement an xmpp client to subscribe for domain events from the ldmd.
297850SVuong.Nguyen@Sun.COM * Notify fmd module clients upon receiving the events.
307850SVuong.Nguyen@Sun.COM *
317850SVuong.Nguyen@Sun.COM */
327850SVuong.Nguyen@Sun.COM
337850SVuong.Nguyen@Sun.COM #include "ldom_xmpp_client.h"
347850SVuong.Nguyen@Sun.COM #include "ldom_alloc.h"
3511831SVuong.Nguyen@Sun.COM #include "ldom_utils.h"
367850SVuong.Nguyen@Sun.COM
377850SVuong.Nguyen@Sun.COM #include <stdio.h>
387850SVuong.Nguyen@Sun.COM #include <signal.h>
397850SVuong.Nguyen@Sun.COM #include <strings.h>
407850SVuong.Nguyen@Sun.COM #include <unistd.h>
417850SVuong.Nguyen@Sun.COM #include <errno.h>
427850SVuong.Nguyen@Sun.COM
437850SVuong.Nguyen@Sun.COM #include <netdb.h>
447850SVuong.Nguyen@Sun.COM #include <dlfcn.h>
457850SVuong.Nguyen@Sun.COM #include <fcntl.h>
467850SVuong.Nguyen@Sun.COM #include <sys/socket.h>
477850SVuong.Nguyen@Sun.COM #include <sys/types.h>
487850SVuong.Nguyen@Sun.COM #include <sys/stat.h>
497850SVuong.Nguyen@Sun.COM #include <libxml/parser.h>
507850SVuong.Nguyen@Sun.COM #include <openssl/ssl.h>
517850SVuong.Nguyen@Sun.COM
527850SVuong.Nguyen@Sun.COM typedef enum conn_state {
537850SVuong.Nguyen@Sun.COM CONN_STATE_UNKNOWN,
547850SVuong.Nguyen@Sun.COM CONN_STATE_TLS,
557850SVuong.Nguyen@Sun.COM CONN_STATE_FEATURE,
567850SVuong.Nguyen@Sun.COM CONN_STATE_LDM_INTERFACE,
577850SVuong.Nguyen@Sun.COM CONN_STATE_LDM_EVENT,
587850SVuong.Nguyen@Sun.COM CONN_STATE_DONE,
597850SVuong.Nguyen@Sun.COM CONN_STATE_FAILURE,
607850SVuong.Nguyen@Sun.COM CONN_STATE_MAX
617850SVuong.Nguyen@Sun.COM } conn_state_t;
627850SVuong.Nguyen@Sun.COM
637850SVuong.Nguyen@Sun.COM typedef struct xmpp_conn {
647850SVuong.Nguyen@Sun.COM int fd;
657850SVuong.Nguyen@Sun.COM int state;
667850SVuong.Nguyen@Sun.COM boolean_t tls_started;
677850SVuong.Nguyen@Sun.COM SSL *ssl;
687850SVuong.Nguyen@Sun.COM xmlParserCtxtPtr parser;
697850SVuong.Nguyen@Sun.COM } xmpp_conn_t;
707850SVuong.Nguyen@Sun.COM
717850SVuong.Nguyen@Sun.COM /* Forward declaration */
727850SVuong.Nguyen@Sun.COM static int iowrite(xmpp_conn_t *conn, char *buf, int size);
737850SVuong.Nguyen@Sun.COM static void start_element(void *state, const xmlChar *name,
747850SVuong.Nguyen@Sun.COM const xmlChar **attrs);
757850SVuong.Nguyen@Sun.COM static void end_element(void *state, const xmlChar *name);
767850SVuong.Nguyen@Sun.COM static void error_func(void *state, const char *msg, ...);
777850SVuong.Nguyen@Sun.COM static void xmpp_close(xmpp_conn_t *conn);
787850SVuong.Nguyen@Sun.COM static int start_tls(xmpp_conn_t *conn);
797850SVuong.Nguyen@Sun.COM static void handle_ldm_resp(xmpp_conn_t *conn, char *buf, size_t buf_size);
807850SVuong.Nguyen@Sun.COM static void handle_ldm_event(xmpp_conn_t *conn, char *buf, size_t buf_size);
817850SVuong.Nguyen@Sun.COM
827850SVuong.Nguyen@Sun.COM static int xmpp_enable = 0;
83*12516SVuong.Nguyen@Sun.COM static int xmpp_notify_pipe[2];
847850SVuong.Nguyen@Sun.COM static pthread_t xmpp_tid = 0;
857850SVuong.Nguyen@Sun.COM static pthread_mutex_t xmpp_tid_lock = PTHREAD_MUTEX_INITIALIZER;
867850SVuong.Nguyen@Sun.COM
877850SVuong.Nguyen@Sun.COM static client_list_t clt_list = { NULL, NULL, PTHREAD_MUTEX_INITIALIZER };
887850SVuong.Nguyen@Sun.COM
897850SVuong.Nguyen@Sun.COM
907850SVuong.Nguyen@Sun.COM #define FUNCTION_ADD(_function, _pointer, _lib, _func_name, _ret) \
917850SVuong.Nguyen@Sun.COM _function = (_pointer)dlsym(_lib, _func_name); \
927850SVuong.Nguyen@Sun.COM if (_function == NULL) { \
937850SVuong.Nguyen@Sun.COM _ret += -1; \
947850SVuong.Nguyen@Sun.COM }
957850SVuong.Nguyen@Sun.COM
967850SVuong.Nguyen@Sun.COM /*
977850SVuong.Nguyen@Sun.COM * Prototypes and pointers to functions needed from libssl.
987850SVuong.Nguyen@Sun.COM */
997850SVuong.Nguyen@Sun.COM typedef void (*SSL_load_error_strings_pt)(void);
1007850SVuong.Nguyen@Sun.COM typedef int (*SSL_library_init_pt)(void);
1017850SVuong.Nguyen@Sun.COM typedef SSL_CTX *(*SSL_CTX_new_pt)(const SSL_METHOD *method);
1027850SVuong.Nguyen@Sun.COM typedef SSL_METHOD *(*SSLv23_client_method_pt)(void);
1037850SVuong.Nguyen@Sun.COM typedef int (*SSL_write_pt)(SSL *ssl, const void *buf, int num);
1047850SVuong.Nguyen@Sun.COM typedef int (*SSL_CTX_use_PrivateKey_file_pt)(SSL_CTX *ctx, const char *file,
1057850SVuong.Nguyen@Sun.COM int type);
1067850SVuong.Nguyen@Sun.COM typedef void (*RAND_seed_pt)(const void *buf, int num);
1077850SVuong.Nguyen@Sun.COM typedef int (*SSL_get_error_pt)(const SSL *ssl, int ret);
1087850SVuong.Nguyen@Sun.COM typedef long (*ERR_get_error_pt)(void);
1097850SVuong.Nguyen@Sun.COM typedef char *(*ERR_error_string_pt)(unsigned long e, char *buf);
1107850SVuong.Nguyen@Sun.COM typedef int (*SSL_connect_pt)(SSL *ssl);
1117850SVuong.Nguyen@Sun.COM typedef int (*SSL_CTX_use_certificate_chain_file_pt)(SSL_CTX *ctx,
1127850SVuong.Nguyen@Sun.COM const char *file);
1137850SVuong.Nguyen@Sun.COM typedef int (*SSL_set_fd_pt)(SSL *ssl, int fd);
1147850SVuong.Nguyen@Sun.COM typedef void (*SSL_free_pt)(SSL *ssl);
1157850SVuong.Nguyen@Sun.COM typedef int (*SSL_read_pt)(SSL *ssl, void *buf, int num);
1167850SVuong.Nguyen@Sun.COM typedef SSL *(*SSL_new_pt)(SSL_CTX *ctx);
1177850SVuong.Nguyen@Sun.COM typedef SSL_CTX *(*SSL_get_SSL_CTX_pt)(const SSL *ssl);
1187850SVuong.Nguyen@Sun.COM typedef void (*SSL_CTX_free_pt)(SSL_CTX *ctx);
1197850SVuong.Nguyen@Sun.COM
1207850SVuong.Nguyen@Sun.COM static SSL_load_error_strings_pt SSL_load_error_strings_f = NULL;
1217850SVuong.Nguyen@Sun.COM static SSL_library_init_pt SSL_library_init_f = NULL;
1227850SVuong.Nguyen@Sun.COM static SSL_CTX_new_pt SSL_CTX_new_f = NULL;
1237850SVuong.Nguyen@Sun.COM static SSLv23_client_method_pt SSLv23_client_method_f = NULL;
1247850SVuong.Nguyen@Sun.COM static SSL_write_pt SSL_write_f = NULL;
1257850SVuong.Nguyen@Sun.COM static SSL_CTX_use_PrivateKey_file_pt SSL_CTX_use_PrivateKey_file_f = NULL;
1267850SVuong.Nguyen@Sun.COM static RAND_seed_pt RAND_seed_f = NULL;
1277850SVuong.Nguyen@Sun.COM static SSL_get_error_pt SSL_get_error_f = NULL;
1287850SVuong.Nguyen@Sun.COM static ERR_get_error_pt ERR_get_error_f = NULL;
1297850SVuong.Nguyen@Sun.COM static ERR_error_string_pt ERR_error_string_f = NULL;
1307850SVuong.Nguyen@Sun.COM static SSL_connect_pt SSL_connect_f = NULL;
1317850SVuong.Nguyen@Sun.COM static SSL_CTX_use_certificate_chain_file_pt
1327850SVuong.Nguyen@Sun.COM SSL_CTX_use_certificate_chain_file_f = NULL;
1337850SVuong.Nguyen@Sun.COM static SSL_set_fd_pt SSL_set_fd_f = NULL;
1347850SVuong.Nguyen@Sun.COM static SSL_free_pt SSL_free_f = NULL;
1357850SVuong.Nguyen@Sun.COM static SSL_read_pt SSL_read_f = NULL;
1367850SVuong.Nguyen@Sun.COM static SSL_new_pt SSL_new_f = NULL;
1377850SVuong.Nguyen@Sun.COM static SSL_get_SSL_CTX_pt SSL_get_SSL_CTX_f = NULL;
1387850SVuong.Nguyen@Sun.COM static SSL_CTX_free_pt SSL_CTX_free_f = NULL;
1397850SVuong.Nguyen@Sun.COM
1407850SVuong.Nguyen@Sun.COM static void *xmpp_dl = NULL;
1417850SVuong.Nguyen@Sun.COM
1427850SVuong.Nguyen@Sun.COM static ldom_event_info_t event_table[] = {
1437850SVuong.Nguyen@Sun.COM { LDOM_EVENT_UNKNOWN, "unknown" },
1447850SVuong.Nguyen@Sun.COM { LDOM_EVENT_ADD, "add-domain" },
1457850SVuong.Nguyen@Sun.COM { LDOM_EVENT_REMOVE, "remove-domain" },
1467850SVuong.Nguyen@Sun.COM { LDOM_EVENT_BIND, "bind-domain" },
1477850SVuong.Nguyen@Sun.COM { LDOM_EVENT_UNBIND, "unbind-domain" },
1487850SVuong.Nguyen@Sun.COM { LDOM_EVENT_START, "start-domain" },
1497850SVuong.Nguyen@Sun.COM { LDOM_EVENT_STOP, "stop-domain" },
1507850SVuong.Nguyen@Sun.COM { LDOM_EVENT_RESET, "domain-reset" },
1517850SVuong.Nguyen@Sun.COM { LDOM_EVENT_PANIC, "panic-domain" },
1527850SVuong.Nguyen@Sun.COM { LDOM_EVENT_MAX, NULL }
1537850SVuong.Nguyen@Sun.COM };
1547850SVuong.Nguyen@Sun.COM static int event_table_size = \
1557850SVuong.Nguyen@Sun.COM sizeof (event_table) / sizeof (ldom_event_info_t);
1567850SVuong.Nguyen@Sun.COM
1577850SVuong.Nguyen@Sun.COM static xmlSAXHandler xml_handler = {
1587850SVuong.Nguyen@Sun.COM NULL, /* internalSubsetSAXFunc */
1597850SVuong.Nguyen@Sun.COM NULL, /* isStandaloneSAXFunc */
1607850SVuong.Nguyen@Sun.COM NULL, /* hasInternalSubsetSAXFunc */
1617850SVuong.Nguyen@Sun.COM NULL, /* hasExternalSubsetSAXFunc */
1627850SVuong.Nguyen@Sun.COM NULL, /* resolveEntitySAXFunc */
1637850SVuong.Nguyen@Sun.COM NULL, /* getEntitySAXFunc */
1647850SVuong.Nguyen@Sun.COM NULL, /* entityDeclSAXFunc */
1657850SVuong.Nguyen@Sun.COM NULL, /* notationDeclSAXFunc */
1667850SVuong.Nguyen@Sun.COM NULL, /* attributeDeclSAXFunc */
1677850SVuong.Nguyen@Sun.COM NULL, /* elementDeclSAXFunc */
1687850SVuong.Nguyen@Sun.COM NULL, /* unparsedEntityDeclSAXFunc */
1697850SVuong.Nguyen@Sun.COM NULL, /* setDocumentLocatorSAXFunc */
1707850SVuong.Nguyen@Sun.COM NULL, /* startDocumentSAXFunc */
1717850SVuong.Nguyen@Sun.COM NULL, /* endDocumentSAXFunc */
1727850SVuong.Nguyen@Sun.COM start_element, /* startElementSAXFunc */
1737850SVuong.Nguyen@Sun.COM end_element, /* endElementSAXFunc */
1747850SVuong.Nguyen@Sun.COM NULL, /* referenceSAXFunc */
1757850SVuong.Nguyen@Sun.COM NULL, /* charactersSAXFunc */
1767850SVuong.Nguyen@Sun.COM NULL, /* ignorableWhitespaceSAXFunc */
1777850SVuong.Nguyen@Sun.COM NULL, /* processingInstructionSAXFunc */
1787850SVuong.Nguyen@Sun.COM NULL, /* commentSAXFunc */
1797850SVuong.Nguyen@Sun.COM NULL, /* warningSAXFunc */
1807850SVuong.Nguyen@Sun.COM error_func, /* errorSAXFunc */
1817850SVuong.Nguyen@Sun.COM NULL, /* fatalErrorSAXFunc */
1827850SVuong.Nguyen@Sun.COM NULL, /* getParameterEntitySAXFunc */
1837850SVuong.Nguyen@Sun.COM NULL, /* cdataBlockSAXFunc */
1847850SVuong.Nguyen@Sun.COM NULL, /* externalSubsetSAXFunc */
1857850SVuong.Nguyen@Sun.COM 0, /* unsigned int */
1867850SVuong.Nguyen@Sun.COM NULL, /* void * _private */
1877850SVuong.Nguyen@Sun.COM NULL, /* startElementNsSAX2Func */
1887850SVuong.Nguyen@Sun.COM NULL, /* endElementNsSAX2Func */
1897850SVuong.Nguyen@Sun.COM NULL /* xmlStructuredErrorFunc */
1907850SVuong.Nguyen@Sun.COM };
1917850SVuong.Nguyen@Sun.COM
1927850SVuong.Nguyen@Sun.COM static void
end_element(void * state,const xmlChar * name)1937850SVuong.Nguyen@Sun.COM end_element(void *state, const xmlChar *name)
1947850SVuong.Nguyen@Sun.COM {
1957850SVuong.Nguyen@Sun.COM xmpp_conn_t *conn = (xmpp_conn_t *)state;
1967850SVuong.Nguyen@Sun.COM
1977850SVuong.Nguyen@Sun.COM if (xmlStrcmp(name, STREAM_NODE) == 0) {
1987850SVuong.Nguyen@Sun.COM conn->state = CONN_STATE_DONE;
1997850SVuong.Nguyen@Sun.COM } else if (xmlStrcmp(name, STARTTLS_NODE) == 0) {
2007850SVuong.Nguyen@Sun.COM (void) iowrite(conn, START_TLS, strlen(START_TLS));
2017850SVuong.Nguyen@Sun.COM } else if (xmlStrcmp(name, PROCEED_NODE) == 0) {
2027850SVuong.Nguyen@Sun.COM if (start_tls(conn)) {
2037850SVuong.Nguyen@Sun.COM conn->state = CONN_STATE_FAILURE;
2047850SVuong.Nguyen@Sun.COM }
2057850SVuong.Nguyen@Sun.COM } else if (xmlStrcmp(name, FEATURE_NODE) == 0) {
2067850SVuong.Nguyen@Sun.COM if (conn->state == CONN_STATE_TLS) {
2077850SVuong.Nguyen@Sun.COM conn->state = CONN_STATE_FEATURE;
2087850SVuong.Nguyen@Sun.COM (void) iowrite(conn, (char *)LDM_REG_DOMAIN_EVENTS,
2097850SVuong.Nguyen@Sun.COM strlen((char *)LDM_REG_DOMAIN_EVENTS));
2107850SVuong.Nguyen@Sun.COM }
2117850SVuong.Nguyen@Sun.COM } else if (xmlStrcmp(name, XML_LDM_INTERFACE) == 0) {
2127850SVuong.Nguyen@Sun.COM conn->state = CONN_STATE_LDM_INTERFACE;
2137850SVuong.Nguyen@Sun.COM } else if (xmlStrcmp(name, XML_LDM_EVENT) == 0) {
2147850SVuong.Nguyen@Sun.COM conn->state = CONN_STATE_LDM_EVENT;
2157850SVuong.Nguyen@Sun.COM } else if (xmlStrcmp(name, XML_FAILURE) == 0) {
2167850SVuong.Nguyen@Sun.COM conn->state = CONN_STATE_FAILURE;
2177850SVuong.Nguyen@Sun.COM }
2187850SVuong.Nguyen@Sun.COM }
2197850SVuong.Nguyen@Sun.COM
2207850SVuong.Nguyen@Sun.COM /*ARGSUSED*/
2217850SVuong.Nguyen@Sun.COM static void
start_element(void * state,const xmlChar * name,const xmlChar ** attrs)2227850SVuong.Nguyen@Sun.COM start_element(void *state, const xmlChar *name, const xmlChar **attrs)
2237850SVuong.Nguyen@Sun.COM {
2247850SVuong.Nguyen@Sun.COM }
2257850SVuong.Nguyen@Sun.COM
2267850SVuong.Nguyen@Sun.COM /*ARGSUSED*/
2277850SVuong.Nguyen@Sun.COM static void
error_func(void * state,const char * msg,...)2287850SVuong.Nguyen@Sun.COM error_func(void *state, const char *msg, ...)
2297850SVuong.Nguyen@Sun.COM {
2307850SVuong.Nguyen@Sun.COM }
2317850SVuong.Nguyen@Sun.COM
2327850SVuong.Nguyen@Sun.COM static int
xmpp_connect(xmpp_conn_t * conn)2337850SVuong.Nguyen@Sun.COM xmpp_connect(xmpp_conn_t *conn)
2347850SVuong.Nguyen@Sun.COM {
2357850SVuong.Nguyen@Sun.COM int sock;
2367850SVuong.Nguyen@Sun.COM struct sockaddr_in serveraddr;
2377850SVuong.Nguyen@Sun.COM
2387850SVuong.Nguyen@Sun.COM if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
2397850SVuong.Nguyen@Sun.COM return (-1);
2407850SVuong.Nguyen@Sun.COM }
2417850SVuong.Nguyen@Sun.COM
2427850SVuong.Nguyen@Sun.COM serveraddr.sin_family = AF_INET;
2437850SVuong.Nguyen@Sun.COM serveraddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2447850SVuong.Nguyen@Sun.COM serveraddr.sin_port = htons(XMPP_DEFAULT_PORT);
2457850SVuong.Nguyen@Sun.COM if (connect(sock, (struct sockaddr *)(&serveraddr),
2467850SVuong.Nguyen@Sun.COM sizeof (struct sockaddr_in)) < 0) {
2477850SVuong.Nguyen@Sun.COM return (-1);
2487850SVuong.Nguyen@Sun.COM }
2497850SVuong.Nguyen@Sun.COM
2507850SVuong.Nguyen@Sun.COM (void) bzero(conn, sizeof (xmpp_conn_t));
2517850SVuong.Nguyen@Sun.COM conn->fd = sock;
2527850SVuong.Nguyen@Sun.COM conn->tls_started = B_FALSE;
2537850SVuong.Nguyen@Sun.COM
2547850SVuong.Nguyen@Sun.COM conn->parser = xmlCreatePushParserCtxt(&xml_handler, (void *) conn,
2557850SVuong.Nguyen@Sun.COM NULL, NULL, NULL);
2567850SVuong.Nguyen@Sun.COM if (conn->parser == NULL) {
2577850SVuong.Nguyen@Sun.COM return (-1);
2587850SVuong.Nguyen@Sun.COM }
2597850SVuong.Nguyen@Sun.COM
2607850SVuong.Nguyen@Sun.COM return (0);
2617850SVuong.Nguyen@Sun.COM }
2627850SVuong.Nguyen@Sun.COM
2637850SVuong.Nguyen@Sun.COM static void
xmpp_close(xmpp_conn_t * conn)2647850SVuong.Nguyen@Sun.COM xmpp_close(xmpp_conn_t *conn)
2657850SVuong.Nguyen@Sun.COM {
2667850SVuong.Nguyen@Sun.COM (void) close(conn->fd);
2677850SVuong.Nguyen@Sun.COM conn->fd = -1;
2687850SVuong.Nguyen@Sun.COM conn->state = CONN_STATE_UNKNOWN;
2697850SVuong.Nguyen@Sun.COM if (conn->parser != NULL) {
2707850SVuong.Nguyen@Sun.COM xmlFreeParserCtxt(conn->parser);
2717850SVuong.Nguyen@Sun.COM conn->parser = NULL;
2727850SVuong.Nguyen@Sun.COM }
2737850SVuong.Nguyen@Sun.COM if (conn->tls_started) {
2747850SVuong.Nguyen@Sun.COM SSL_free_f(conn->ssl);
2757850SVuong.Nguyen@Sun.COM conn->ssl = NULL;
2767850SVuong.Nguyen@Sun.COM }
2777850SVuong.Nguyen@Sun.COM conn->tls_started = B_FALSE;
2787850SVuong.Nguyen@Sun.COM }
2797850SVuong.Nguyen@Sun.COM
2807850SVuong.Nguyen@Sun.COM static int
ioread(xmpp_conn_t * conn,char * buf,int size)2817850SVuong.Nguyen@Sun.COM ioread(xmpp_conn_t *conn, char *buf, int size)
2827850SVuong.Nguyen@Sun.COM {
2837850SVuong.Nguyen@Sun.COM int count;
2847850SVuong.Nguyen@Sun.COM if (conn->tls_started) {
2857850SVuong.Nguyen@Sun.COM count = SSL_read_f(conn->ssl, buf, size);
2867850SVuong.Nguyen@Sun.COM } else {
2877850SVuong.Nguyen@Sun.COM count = read(conn->fd, buf, size);
2887850SVuong.Nguyen@Sun.COM }
2897850SVuong.Nguyen@Sun.COM if (count <= 0) {
2907850SVuong.Nguyen@Sun.COM conn->state = CONN_STATE_FAILURE;
2917850SVuong.Nguyen@Sun.COM }
2927850SVuong.Nguyen@Sun.COM
2937850SVuong.Nguyen@Sun.COM return (count);
2947850SVuong.Nguyen@Sun.COM }
2957850SVuong.Nguyen@Sun.COM
2967850SVuong.Nguyen@Sun.COM static int
iowrite(xmpp_conn_t * conn,char * buf,int size)2977850SVuong.Nguyen@Sun.COM iowrite(xmpp_conn_t *conn, char *buf, int size)
2987850SVuong.Nguyen@Sun.COM {
2997850SVuong.Nguyen@Sun.COM int count;
3007850SVuong.Nguyen@Sun.COM
3017850SVuong.Nguyen@Sun.COM if (conn->tls_started) {
3027850SVuong.Nguyen@Sun.COM count = SSL_write_f(conn->ssl, buf, size);
3037850SVuong.Nguyen@Sun.COM } else {
3047850SVuong.Nguyen@Sun.COM count = send(conn->fd, buf, size, 0);
3057850SVuong.Nguyen@Sun.COM }
3067850SVuong.Nguyen@Sun.COM if (count <= 0) {
3077850SVuong.Nguyen@Sun.COM conn->state = CONN_STATE_FAILURE;
3087850SVuong.Nguyen@Sun.COM }
3097850SVuong.Nguyen@Sun.COM
3107850SVuong.Nguyen@Sun.COM return (count);
3117850SVuong.Nguyen@Sun.COM }
3127850SVuong.Nguyen@Sun.COM
3137850SVuong.Nguyen@Sun.COM /*
3147850SVuong.Nguyen@Sun.COM * notify_event()
3157850SVuong.Nguyen@Sun.COM * Description:
3167850SVuong.Nguyen@Sun.COM * Notify all clients an event by going through the client list and invoke
3177850SVuong.Nguyen@Sun.COM * the callback functions.
3187850SVuong.Nguyen@Sun.COM */
3197850SVuong.Nguyen@Sun.COM static void
notify_event(ldom_event_t event,char * ldom_name)3207850SVuong.Nguyen@Sun.COM notify_event(ldom_event_t event, char *ldom_name)
3217850SVuong.Nguyen@Sun.COM {
3227850SVuong.Nguyen@Sun.COM client_info_t *p;
3237850SVuong.Nguyen@Sun.COM
3247850SVuong.Nguyen@Sun.COM (void) pthread_mutex_lock(&clt_list.lock);
3257850SVuong.Nguyen@Sun.COM
3267850SVuong.Nguyen@Sun.COM for (p = clt_list.head; p != NULL; p = p->next) {
3277850SVuong.Nguyen@Sun.COM p->cb(ldom_name, event, p->data);
3287850SVuong.Nguyen@Sun.COM }
3297850SVuong.Nguyen@Sun.COM
3307850SVuong.Nguyen@Sun.COM (void) pthread_mutex_unlock(&clt_list.lock);
3317850SVuong.Nguyen@Sun.COM }
3327850SVuong.Nguyen@Sun.COM
3337850SVuong.Nguyen@Sun.COM /*
3347850SVuong.Nguyen@Sun.COM * xmpp_client_thr()
3357850SVuong.Nguyen@Sun.COM * Description:
3367850SVuong.Nguyen@Sun.COM * The main entry fo the xmpp client thread.
3377850SVuong.Nguyen@Sun.COM */
3387850SVuong.Nguyen@Sun.COM /*ARGSUSED*/
3397850SVuong.Nguyen@Sun.COM static void *
xmpp_client_thr(void * data)3407850SVuong.Nguyen@Sun.COM xmpp_client_thr(void *data)
3417850SVuong.Nguyen@Sun.COM {
3427850SVuong.Nguyen@Sun.COM int rc = 0;
3437850SVuong.Nguyen@Sun.COM int cnt;
3447850SVuong.Nguyen@Sun.COM char buf[XMPP_BUF_SIZE];
3457850SVuong.Nguyen@Sun.COM xmpp_conn_t conn;
346*12516SVuong.Nguyen@Sun.COM pollfd_t pollfd[2];
347*12516SVuong.Nguyen@Sun.COM struct pollfd *pipe_fd = &pollfd[0];
348*12516SVuong.Nguyen@Sun.COM struct pollfd *recv_fd = &pollfd[1];
3497850SVuong.Nguyen@Sun.COM
3507850SVuong.Nguyen@Sun.COM while (xmpp_enable) {
35111831SVuong.Nguyen@Sun.COM /* clear the conn struct */
35211831SVuong.Nguyen@Sun.COM bzero(&conn, sizeof (xmpp_conn_t));
3537850SVuong.Nguyen@Sun.COM
3547850SVuong.Nguyen@Sun.COM /* keep making a connection until successfully */
3557850SVuong.Nguyen@Sun.COM do {
3567850SVuong.Nguyen@Sun.COM if (rc = xmpp_connect(&conn))
3577850SVuong.Nguyen@Sun.COM (void) sleep(XMPP_SLEEP);
3587850SVuong.Nguyen@Sun.COM } while (rc != 0 && xmpp_enable);
3597850SVuong.Nguyen@Sun.COM
3607850SVuong.Nguyen@Sun.COM /* write the stream node */
3617850SVuong.Nguyen@Sun.COM cnt = iowrite(&conn, (char *)STREAM_START,
3627850SVuong.Nguyen@Sun.COM strlen((char *)STREAM_START));
36311831SVuong.Nguyen@Sun.COM if (cnt != strlen((char *)STREAM_START)) {
36411831SVuong.Nguyen@Sun.COM xmpp_close(&conn);
36511831SVuong.Nguyen@Sun.COM (void) sleep(XMPP_SLEEP);
36611831SVuong.Nguyen@Sun.COM continue;
36711831SVuong.Nguyen@Sun.COM }
3687850SVuong.Nguyen@Sun.COM
369*12516SVuong.Nguyen@Sun.COM pipe_fd->fd = xmpp_notify_pipe[1]; /* notification pipe */
370*12516SVuong.Nguyen@Sun.COM pipe_fd->events = POLLIN;
371*12516SVuong.Nguyen@Sun.COM recv_fd->fd = conn.fd; /* XMPP connection */
372*12516SVuong.Nguyen@Sun.COM recv_fd->events = POLLIN;
373*12516SVuong.Nguyen@Sun.COM
3747850SVuong.Nguyen@Sun.COM /* process input */
3757850SVuong.Nguyen@Sun.COM while ((conn.state != CONN_STATE_FAILURE) &&
3767850SVuong.Nguyen@Sun.COM (conn.state != CONN_STATE_DONE) && xmpp_enable) {
3777850SVuong.Nguyen@Sun.COM
378*12516SVuong.Nguyen@Sun.COM /* Wait for xmpp input or the notification */
379*12516SVuong.Nguyen@Sun.COM pipe_fd->revents = 0;
380*12516SVuong.Nguyen@Sun.COM recv_fd->revents = 0;
381*12516SVuong.Nguyen@Sun.COM if (poll(pollfd, 2, -1) <= 0) {
382*12516SVuong.Nguyen@Sun.COM break;
383*12516SVuong.Nguyen@Sun.COM } else if (pipe_fd->revents & POLLIN) {
384*12516SVuong.Nguyen@Sun.COM /* Receive a notification to exit */
385*12516SVuong.Nguyen@Sun.COM xmpp_close(&conn);
386*12516SVuong.Nguyen@Sun.COM pthread_exit((void *)NULL);
387*12516SVuong.Nguyen@Sun.COM }
388*12516SVuong.Nguyen@Sun.COM
3897850SVuong.Nguyen@Sun.COM /*
3907850SVuong.Nguyen@Sun.COM * Assume the document size of a ldmd response is
3917850SVuong.Nguyen@Sun.COM * less than 1KB. This assumption is valid with the
3927850SVuong.Nguyen@Sun.COM * current ldmd implementation.
3937850SVuong.Nguyen@Sun.COM * Should the document size exceeds 1KB, the buffer
3947850SVuong.Nguyen@Sun.COM * size should be revisited accordingly.
3957850SVuong.Nguyen@Sun.COM */
3967850SVuong.Nguyen@Sun.COM (void) memset(buf, 0, XMPP_BUF_SIZE);
3977850SVuong.Nguyen@Sun.COM cnt = ioread(&conn, buf, XMPP_BUF_SIZE);
3987850SVuong.Nguyen@Sun.COM if (cnt <= 0)
3997850SVuong.Nguyen@Sun.COM break;
4007850SVuong.Nguyen@Sun.COM if (rc = xmlParseChunk(conn.parser, buf, cnt, 0)) {
4017850SVuong.Nguyen@Sun.COM conn.state = CONN_STATE_FAILURE;
4027850SVuong.Nguyen@Sun.COM }
4037850SVuong.Nguyen@Sun.COM
4047850SVuong.Nguyen@Sun.COM switch (conn.state) {
4057850SVuong.Nguyen@Sun.COM case CONN_STATE_LDM_INTERFACE:
4067850SVuong.Nguyen@Sun.COM handle_ldm_resp(&conn, buf, cnt);
4077850SVuong.Nguyen@Sun.COM break;
4087850SVuong.Nguyen@Sun.COM case CONN_STATE_LDM_EVENT:
4097850SVuong.Nguyen@Sun.COM handle_ldm_event(&conn, buf, cnt);
4107850SVuong.Nguyen@Sun.COM break;
4117850SVuong.Nguyen@Sun.COM default:
4127850SVuong.Nguyen@Sun.COM break;
4137850SVuong.Nguyen@Sun.COM }
4147850SVuong.Nguyen@Sun.COM
4157850SVuong.Nguyen@Sun.COM /*
4167850SVuong.Nguyen@Sun.COM * For now, the parser is reset after every read.
4177850SVuong.Nguyen@Sun.COM * It should only be reset once after the ssl is opened
4187850SVuong.Nguyen@Sun.COM * in the start_tls().
4197850SVuong.Nguyen@Sun.COM */
4207850SVuong.Nguyen@Sun.COM (void) xmlCtxtResetPush(conn.parser, NULL, NULL, NULL,
4217850SVuong.Nguyen@Sun.COM NULL);
4227850SVuong.Nguyen@Sun.COM }
4237850SVuong.Nguyen@Sun.COM xmpp_close(&conn);
4247850SVuong.Nguyen@Sun.COM (void) sleep(XMPP_SLEEP);
4257850SVuong.Nguyen@Sun.COM }
4267850SVuong.Nguyen@Sun.COM return (NULL);
4277850SVuong.Nguyen@Sun.COM }
4287850SVuong.Nguyen@Sun.COM
4297850SVuong.Nguyen@Sun.COM /*
4307850SVuong.Nguyen@Sun.COM * find_client()
4317850SVuong.Nguyen@Sun.COM * Description:
4327850SVuong.Nguyen@Sun.COM * Walk to the list to find a libldom client
4337850SVuong.Nguyen@Sun.COM */
4347850SVuong.Nguyen@Sun.COM static client_info_t *
find_client(ldom_hdl_t * lhp)4357850SVuong.Nguyen@Sun.COM find_client(ldom_hdl_t *lhp)
4367850SVuong.Nguyen@Sun.COM {
4377850SVuong.Nguyen@Sun.COM client_info_t *p;
4387850SVuong.Nguyen@Sun.COM
4397850SVuong.Nguyen@Sun.COM for (p = clt_list.head; p != NULL; p = p->next) {
4407850SVuong.Nguyen@Sun.COM if (p->lhp == lhp)
4417850SVuong.Nguyen@Sun.COM return (p);
4427850SVuong.Nguyen@Sun.COM }
4437850SVuong.Nguyen@Sun.COM
4447850SVuong.Nguyen@Sun.COM return (NULL);
4457850SVuong.Nguyen@Sun.COM }
4467850SVuong.Nguyen@Sun.COM
4477850SVuong.Nguyen@Sun.COM /*
4487850SVuong.Nguyen@Sun.COM * xmpp_add_client()
4497850SVuong.Nguyen@Sun.COM * Description:
4507850SVuong.Nguyen@Sun.COM * Add a libldom client from the client list.
4517850SVuong.Nguyen@Sun.COM */
4527850SVuong.Nguyen@Sun.COM int
xmpp_add_client(ldom_hdl_t * lhp,ldom_reg_cb_t cb,ldom_cb_arg_t data)4537850SVuong.Nguyen@Sun.COM xmpp_add_client(ldom_hdl_t *lhp, ldom_reg_cb_t cb, ldom_cb_arg_t data)
4547850SVuong.Nguyen@Sun.COM {
4557850SVuong.Nguyen@Sun.COM client_info_t *clt;
4567850SVuong.Nguyen@Sun.COM
4577850SVuong.Nguyen@Sun.COM (void) pthread_mutex_lock(&clt_list.lock);
4587850SVuong.Nguyen@Sun.COM if (find_client(lhp)) {
4597850SVuong.Nguyen@Sun.COM /* already exists */
4607850SVuong.Nguyen@Sun.COM (void) pthread_mutex_unlock(&clt_list.lock);
4617850SVuong.Nguyen@Sun.COM return (-1);
4627850SVuong.Nguyen@Sun.COM }
4637850SVuong.Nguyen@Sun.COM
4647850SVuong.Nguyen@Sun.COM /* new client */
4657850SVuong.Nguyen@Sun.COM clt = (client_info_t *)ldom_alloc(sizeof (client_info_t));
4667850SVuong.Nguyen@Sun.COM clt->lhp = lhp;
4677850SVuong.Nguyen@Sun.COM clt->cb = cb;
4687850SVuong.Nguyen@Sun.COM clt->data = data;
4697850SVuong.Nguyen@Sun.COM clt->next = NULL;
4707850SVuong.Nguyen@Sun.COM clt->prev = NULL;
4717850SVuong.Nguyen@Sun.COM
4727850SVuong.Nguyen@Sun.COM if (clt_list.head == NULL && clt_list.tail == NULL) {
4737850SVuong.Nguyen@Sun.COM clt_list.head = clt;
4747850SVuong.Nguyen@Sun.COM clt_list.tail = clt;
4757850SVuong.Nguyen@Sun.COM } else {
4767850SVuong.Nguyen@Sun.COM /* append to the list */
4777850SVuong.Nguyen@Sun.COM clt->prev = clt_list.tail;
4787850SVuong.Nguyen@Sun.COM clt_list.tail->next = clt;
4797850SVuong.Nguyen@Sun.COM clt_list.tail = clt;
4807850SVuong.Nguyen@Sun.COM }
4817850SVuong.Nguyen@Sun.COM
4827850SVuong.Nguyen@Sun.COM (void) pthread_mutex_unlock(&clt_list.lock);
4837850SVuong.Nguyen@Sun.COM return (0);
4847850SVuong.Nguyen@Sun.COM }
4857850SVuong.Nguyen@Sun.COM
4867850SVuong.Nguyen@Sun.COM /*
4877850SVuong.Nguyen@Sun.COM * xmpp_remove_client()
4887850SVuong.Nguyen@Sun.COM * Description:
4897850SVuong.Nguyen@Sun.COM * Remove a libldom client from the client list.
4907850SVuong.Nguyen@Sun.COM */
4917850SVuong.Nguyen@Sun.COM int
xmpp_remove_client(ldom_hdl_t * lhp)4927850SVuong.Nguyen@Sun.COM xmpp_remove_client(ldom_hdl_t *lhp)
4937850SVuong.Nguyen@Sun.COM {
4947850SVuong.Nguyen@Sun.COM client_info_t *p;
4957850SVuong.Nguyen@Sun.COM
4967850SVuong.Nguyen@Sun.COM (void) pthread_mutex_lock(&clt_list.lock);
4977850SVuong.Nguyen@Sun.COM if ((p = find_client(lhp)) == NULL) {
4987850SVuong.Nguyen@Sun.COM /* not present */
4997850SVuong.Nguyen@Sun.COM (void) pthread_mutex_unlock(&clt_list.lock);
5007850SVuong.Nguyen@Sun.COM return (-1);
5017850SVuong.Nguyen@Sun.COM }
5027850SVuong.Nguyen@Sun.COM
5037850SVuong.Nguyen@Sun.COM if (clt_list.head == p && clt_list.tail == p) {
5047850SVuong.Nguyen@Sun.COM /* single item list */
5057850SVuong.Nguyen@Sun.COM clt_list.head = NULL;
5067850SVuong.Nguyen@Sun.COM clt_list.tail = NULL;
5077850SVuong.Nguyen@Sun.COM } else if (clt_list.head == p) {
5087850SVuong.Nguyen@Sun.COM /* delete the head */
5097850SVuong.Nguyen@Sun.COM clt_list.head = p->next;
5107850SVuong.Nguyen@Sun.COM clt_list.head->prev = NULL;
5117850SVuong.Nguyen@Sun.COM } else if (clt_list.tail == p) {
5127850SVuong.Nguyen@Sun.COM /* delete the tail */
5137850SVuong.Nguyen@Sun.COM clt_list.tail = p->prev;
5147850SVuong.Nguyen@Sun.COM clt_list.tail->next = NULL;
5157850SVuong.Nguyen@Sun.COM } else {
5167850SVuong.Nguyen@Sun.COM /* delete a middle node */
5177850SVuong.Nguyen@Sun.COM p->next->prev = p->prev;
5187850SVuong.Nguyen@Sun.COM p->prev->next = p->next;
5197850SVuong.Nguyen@Sun.COM }
5207850SVuong.Nguyen@Sun.COM ldom_free(p, sizeof (client_info_t));
5217850SVuong.Nguyen@Sun.COM
5227850SVuong.Nguyen@Sun.COM (void) pthread_mutex_unlock(&clt_list.lock);
5237850SVuong.Nguyen@Sun.COM return (0);
5247850SVuong.Nguyen@Sun.COM }
5257850SVuong.Nguyen@Sun.COM
5267850SVuong.Nguyen@Sun.COM /*
5277850SVuong.Nguyen@Sun.COM * xmpp_stop()
5287850SVuong.Nguyen@Sun.COM * Description:
5297850SVuong.Nguyen@Sun.COM * Stop the xmpp client thread
5307850SVuong.Nguyen@Sun.COM */
5317850SVuong.Nguyen@Sun.COM /*ARGSUSED*/
5327850SVuong.Nguyen@Sun.COM void
xmpp_stop(void)5337850SVuong.Nguyen@Sun.COM xmpp_stop(void)
5347850SVuong.Nguyen@Sun.COM {
5357850SVuong.Nguyen@Sun.COM (void) pthread_mutex_lock(&xmpp_tid_lock);
5367850SVuong.Nguyen@Sun.COM xmpp_enable = 0;
5377850SVuong.Nguyen@Sun.COM if (xmpp_tid) {
538*12516SVuong.Nguyen@Sun.COM /*
539*12516SVuong.Nguyen@Sun.COM * Write a byte to the pipe to notify the xmpp thread to exit.
540*12516SVuong.Nguyen@Sun.COM * Then wait for it to exit.
541*12516SVuong.Nguyen@Sun.COM */
542*12516SVuong.Nguyen@Sun.COM (void) write(xmpp_notify_pipe[0], "1", 1);
5437850SVuong.Nguyen@Sun.COM (void) pthread_join(xmpp_tid, NULL);
5447850SVuong.Nguyen@Sun.COM xmpp_tid = 0;
5457850SVuong.Nguyen@Sun.COM }
5467850SVuong.Nguyen@Sun.COM (void) pthread_mutex_unlock(&xmpp_tid_lock);
5477850SVuong.Nguyen@Sun.COM }
5487850SVuong.Nguyen@Sun.COM
5497850SVuong.Nguyen@Sun.COM /*
5507850SVuong.Nguyen@Sun.COM * xmpp_start()
5517850SVuong.Nguyen@Sun.COM * Description:
5527850SVuong.Nguyen@Sun.COM * Start the xmpp client thread if have not done so.
5537850SVuong.Nguyen@Sun.COM */
5547850SVuong.Nguyen@Sun.COM void
xmpp_start(void)5557850SVuong.Nguyen@Sun.COM xmpp_start(void)
5567850SVuong.Nguyen@Sun.COM {
5577850SVuong.Nguyen@Sun.COM xmpp_conn_t conn;
5587850SVuong.Nguyen@Sun.COM
5597850SVuong.Nguyen@Sun.COM /* Check if the xmmp thread has already started */
5607850SVuong.Nguyen@Sun.COM (void) pthread_mutex_lock(&xmpp_tid_lock);
5617850SVuong.Nguyen@Sun.COM if (xmpp_tid != 0) {
5627850SVuong.Nguyen@Sun.COM (void) pthread_mutex_unlock(&xmpp_tid_lock);
5637850SVuong.Nguyen@Sun.COM return;
5647850SVuong.Nguyen@Sun.COM }
5657850SVuong.Nguyen@Sun.COM
5667850SVuong.Nguyen@Sun.COM /* Check if the ldmd supports xmpp by opening a connection */
5677850SVuong.Nguyen@Sun.COM if (xmpp_connect(&conn)) {
5687850SVuong.Nguyen@Sun.COM (void) pthread_mutex_unlock(&xmpp_tid_lock);
5697850SVuong.Nguyen@Sun.COM return;
5707850SVuong.Nguyen@Sun.COM }
5717850SVuong.Nguyen@Sun.COM xmpp_close(&conn);
5727850SVuong.Nguyen@Sun.COM xmpp_enable = 1;
5737850SVuong.Nguyen@Sun.COM
5747850SVuong.Nguyen@Sun.COM /*
575*12516SVuong.Nguyen@Sun.COM * create xmpp client thread for receiving domain events.
576*12516SVuong.Nguyen@Sun.COM * The notification pipe is for stopping the thread.
5777850SVuong.Nguyen@Sun.COM */
578*12516SVuong.Nguyen@Sun.COM (void) notify_setup(xmpp_notify_pipe);
5797850SVuong.Nguyen@Sun.COM (void) pthread_create(&xmpp_tid, NULL, xmpp_client_thr, NULL);
5807850SVuong.Nguyen@Sun.COM
5817850SVuong.Nguyen@Sun.COM (void) pthread_mutex_unlock(&xmpp_tid_lock);
5827850SVuong.Nguyen@Sun.COM
5837850SVuong.Nguyen@Sun.COM /*
5847850SVuong.Nguyen@Sun.COM * Register a function to stop the above thread upon a termination
5857850SVuong.Nguyen@Sun.COM */
5867850SVuong.Nguyen@Sun.COM (void) atexit(xmpp_stop);
5877850SVuong.Nguyen@Sun.COM }
5887850SVuong.Nguyen@Sun.COM
5897850SVuong.Nguyen@Sun.COM /*
5907850SVuong.Nguyen@Sun.COM * This routine will run through the first time we get a remote XMPP
5917850SVuong.Nguyen@Sun.COM * connection. After that we will not need to do this again. It cannot be run
5927850SVuong.Nguyen@Sun.COM * from main thread at start as we need to alert remote users if the TLS
5937850SVuong.Nguyen@Sun.COM * handshake failed.
5947850SVuong.Nguyen@Sun.COM */
5957850SVuong.Nguyen@Sun.COM static int
load_SSL_lib()5967850SVuong.Nguyen@Sun.COM load_SSL_lib()
5977850SVuong.Nguyen@Sun.COM {
5987850SVuong.Nguyen@Sun.COM int ret = 0;
5997850SVuong.Nguyen@Sun.COM
6007850SVuong.Nguyen@Sun.COM /* If we have already opened the library no need to do it again. */
6017850SVuong.Nguyen@Sun.COM if (xmpp_dl != NULL)
6027850SVuong.Nguyen@Sun.COM return (0);
6037850SVuong.Nguyen@Sun.COM
6048357SVuong.Nguyen@Sun.COM /*
6058357SVuong.Nguyen@Sun.COM * If the libssl.so in not in the default path, attempt to open it
6068357SVuong.Nguyen@Sun.COM * under /usr/sfw/lib.
6078357SVuong.Nguyen@Sun.COM */
6088357SVuong.Nguyen@Sun.COM xmpp_dl = dlopen("libssl.so", RTLD_NOW);
6098357SVuong.Nguyen@Sun.COM if (xmpp_dl == NULL) {
6108357SVuong.Nguyen@Sun.COM xmpp_dl = dlopen("/usr/sfw/lib/libssl.so", RTLD_NOW);
6118357SVuong.Nguyen@Sun.COM if (xmpp_dl == NULL)
6128357SVuong.Nguyen@Sun.COM return (-1);
6138357SVuong.Nguyen@Sun.COM }
6147850SVuong.Nguyen@Sun.COM
6157850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSL_load_error_strings_f, SSL_load_error_strings_pt,
6167850SVuong.Nguyen@Sun.COM xmpp_dl, "SSL_load_error_strings", ret);
6177850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSL_library_init_f, SSL_library_init_pt, xmpp_dl,
6187850SVuong.Nguyen@Sun.COM "SSL_library_init", ret);
6197850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSL_CTX_new_f, SSL_CTX_new_pt, xmpp_dl,
6207850SVuong.Nguyen@Sun.COM "SSL_CTX_new", ret);
6217850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSLv23_client_method_f, SSLv23_client_method_pt, xmpp_dl,
6227850SVuong.Nguyen@Sun.COM "SSLv23_client_method", ret);
6237850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSL_write_f, SSL_write_pt, xmpp_dl, "SSL_write", ret);
6247850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSL_CTX_use_PrivateKey_file_f,
6257850SVuong.Nguyen@Sun.COM SSL_CTX_use_PrivateKey_file_pt, xmpp_dl,
6267850SVuong.Nguyen@Sun.COM "SSL_CTX_use_PrivateKey_file", ret);
6277850SVuong.Nguyen@Sun.COM FUNCTION_ADD(RAND_seed_f, RAND_seed_pt, xmpp_dl, "RAND_seed", ret);
6287850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSL_get_error_f, SSL_get_error_pt, xmpp_dl,
6297850SVuong.Nguyen@Sun.COM "SSL_get_error", ret);
6307850SVuong.Nguyen@Sun.COM FUNCTION_ADD(ERR_get_error_f, ERR_get_error_pt, xmpp_dl,
6317850SVuong.Nguyen@Sun.COM "ERR_get_error", ret);
6327850SVuong.Nguyen@Sun.COM FUNCTION_ADD(ERR_error_string_f, ERR_error_string_pt, xmpp_dl,
6337850SVuong.Nguyen@Sun.COM "ERR_error_string", ret);
6347850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSL_connect_f, SSL_connect_pt, xmpp_dl, "SSL_connect",
6357850SVuong.Nguyen@Sun.COM ret);
6367850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSL_CTX_use_certificate_chain_file_f,
6377850SVuong.Nguyen@Sun.COM SSL_CTX_use_certificate_chain_file_pt, xmpp_dl,
6387850SVuong.Nguyen@Sun.COM "SSL_CTX_use_certificate_chain_file", ret);
6397850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSL_set_fd_f, SSL_set_fd_pt, xmpp_dl, "SSL_set_fd", ret);
6407850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSL_free_f, SSL_free_pt, xmpp_dl, "SSL_free", ret);
6417850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSL_read_f, SSL_read_pt, xmpp_dl, "SSL_read", ret);
6427850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSL_new_f, SSL_new_pt, xmpp_dl, "SSL_new", ret);
6437850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSL_get_SSL_CTX_f, SSL_get_SSL_CTX_pt, xmpp_dl,
6447850SVuong.Nguyen@Sun.COM "SSL_get_SSL_CTX", ret);
6457850SVuong.Nguyen@Sun.COM FUNCTION_ADD(SSL_CTX_free_f, SSL_CTX_free_pt, xmpp_dl,
6467850SVuong.Nguyen@Sun.COM "SSL_CTX_free", ret);
6477850SVuong.Nguyen@Sun.COM
6487850SVuong.Nguyen@Sun.COM if (ret < 0)
6497850SVuong.Nguyen@Sun.COM return (-1);
6507850SVuong.Nguyen@Sun.COM else
6517850SVuong.Nguyen@Sun.COM return (0);
6527850SVuong.Nguyen@Sun.COM }
6537850SVuong.Nguyen@Sun.COM
6547850SVuong.Nguyen@Sun.COM /*
6557850SVuong.Nguyen@Sun.COM * start_tls()
6567850SVuong.Nguyen@Sun.COM * Description:
6577850SVuong.Nguyen@Sun.COM * Load the libssl.so if has not done so and open a ssl connection.
6587850SVuong.Nguyen@Sun.COM * It is assumed that there is one xmpp thread to use the ssl connection.
6597850SVuong.Nguyen@Sun.COM * If multi-thread xmpp clients use the ssl connection, addtional work is
6607850SVuong.Nguyen@Sun.COM * needed to ensure the usage of the ssl be thread-safe.
6617850SVuong.Nguyen@Sun.COM */
6627850SVuong.Nguyen@Sun.COM static int
start_tls(xmpp_conn_t * conn)6637850SVuong.Nguyen@Sun.COM start_tls(xmpp_conn_t *conn)
6647850SVuong.Nguyen@Sun.COM {
6657850SVuong.Nguyen@Sun.COM int rv, urand_fd;
6667850SVuong.Nguyen@Sun.COM SSL_CTX *ssl_ctx;
6677850SVuong.Nguyen@Sun.COM char rand_buf[RAND_BUF_SIZE];
6687850SVuong.Nguyen@Sun.COM
6697850SVuong.Nguyen@Sun.COM rv = load_SSL_lib();
6707850SVuong.Nguyen@Sun.COM if (rv == -1) {
6717850SVuong.Nguyen@Sun.COM return (rv);
6727850SVuong.Nguyen@Sun.COM }
6737850SVuong.Nguyen@Sun.COM
6747850SVuong.Nguyen@Sun.COM urand_fd = open("/dev/random", O_RDONLY);
6757850SVuong.Nguyen@Sun.COM if (urand_fd == -1) {
6767850SVuong.Nguyen@Sun.COM return (-1);
6777850SVuong.Nguyen@Sun.COM }
6787850SVuong.Nguyen@Sun.COM (void) read(urand_fd, rand_buf, RAND_BUF_SIZE);
6797850SVuong.Nguyen@Sun.COM
6807850SVuong.Nguyen@Sun.COM SSL_library_init_f();
6817850SVuong.Nguyen@Sun.COM RAND_seed_f(rand_buf, RAND_BUF_SIZE);
6827850SVuong.Nguyen@Sun.COM
6837850SVuong.Nguyen@Sun.COM ssl_ctx = SSL_CTX_new_f(SSLv23_client_method_f());
6847850SVuong.Nguyen@Sun.COM if (ssl_ctx == NULL) {
6857850SVuong.Nguyen@Sun.COM return (-1);
6867850SVuong.Nguyen@Sun.COM }
6877850SVuong.Nguyen@Sun.COM conn->ssl = SSL_new_f(ssl_ctx);
6887850SVuong.Nguyen@Sun.COM rv = SSL_set_fd_f(conn->ssl, conn->fd);
6897850SVuong.Nguyen@Sun.COM if (rv == 0) {
6907850SVuong.Nguyen@Sun.COM return (-1);
6917850SVuong.Nguyen@Sun.COM }
6927850SVuong.Nguyen@Sun.COM rv = SSL_connect_f(conn->ssl);
6937850SVuong.Nguyen@Sun.COM if (rv != 1) {
6947850SVuong.Nguyen@Sun.COM return (-1);
6957850SVuong.Nguyen@Sun.COM }
6967850SVuong.Nguyen@Sun.COM conn->tls_started = B_TRUE;
6977850SVuong.Nguyen@Sun.COM conn->state = CONN_STATE_TLS;
6987850SVuong.Nguyen@Sun.COM
6997850SVuong.Nguyen@Sun.COM (void) iowrite(conn, STREAM_START, strlen(STREAM_START));
7007850SVuong.Nguyen@Sun.COM
7017850SVuong.Nguyen@Sun.COM return (0);
7027850SVuong.Nguyen@Sun.COM }
7037850SVuong.Nguyen@Sun.COM
7047850SVuong.Nguyen@Sun.COM /*
7057850SVuong.Nguyen@Sun.COM * Find and return the first-level subnode (if any) of 'node' which has name
7067850SVuong.Nguyen@Sun.COM * 'name'.
7077850SVuong.Nguyen@Sun.COM */
7087850SVuong.Nguyen@Sun.COM xmlNodePtr
xml_find_subnode(xmlNodePtr node,const xmlChar * name)7097850SVuong.Nguyen@Sun.COM xml_find_subnode(xmlNodePtr node, const xmlChar *name)
7107850SVuong.Nguyen@Sun.COM {
7117850SVuong.Nguyen@Sun.COM xmlNodePtr subnode;
7127850SVuong.Nguyen@Sun.COM
7137850SVuong.Nguyen@Sun.COM if (node == NULL)
7147850SVuong.Nguyen@Sun.COM return (NULL);
7157850SVuong.Nguyen@Sun.COM
7167850SVuong.Nguyen@Sun.COM subnode = node->xmlChildrenNode;
7177850SVuong.Nguyen@Sun.COM while (subnode != NULL) {
7187850SVuong.Nguyen@Sun.COM if (((char *)subnode->name != NULL) &&
7197850SVuong.Nguyen@Sun.COM (xmlStrcmp(subnode->name, name) == 0))
7207850SVuong.Nguyen@Sun.COM break;
7217850SVuong.Nguyen@Sun.COM subnode = subnode->next;
7227850SVuong.Nguyen@Sun.COM }
7237850SVuong.Nguyen@Sun.COM
7247850SVuong.Nguyen@Sun.COM return (subnode);
7257850SVuong.Nguyen@Sun.COM }
7267850SVuong.Nguyen@Sun.COM
7277850SVuong.Nguyen@Sun.COM /*
7287850SVuong.Nguyen@Sun.COM * handle_ldm_resp()
7297850SVuong.Nguyen@Sun.COM * Description:
7307850SVuong.Nguyen@Sun.COM * Parse the ldmd response of the domain event registration for the failure
7317850SVuong.Nguyen@Sun.COM * status. If found, set the connection to failure so that it will be
7327850SVuong.Nguyen@Sun.COM * closed and a new xmpp connection is established.
7337850SVuong.Nguyen@Sun.COM */
7347850SVuong.Nguyen@Sun.COM void
handle_ldm_resp(xmpp_conn_t * conn,char * buf,size_t buf_size)7357850SVuong.Nguyen@Sun.COM handle_ldm_resp(xmpp_conn_t *conn, char *buf, size_t buf_size)
7367850SVuong.Nguyen@Sun.COM {
7377850SVuong.Nguyen@Sun.COM xmlDocPtr xml_output;
7387850SVuong.Nguyen@Sun.COM xmlNodePtr root, resp, status, cmd, action;
7397850SVuong.Nguyen@Sun.COM char *status_str, *action_str;
7407850SVuong.Nguyen@Sun.COM
7417850SVuong.Nguyen@Sun.COM if ((xml_output = xmlParseMemory((const char *)buf, buf_size)) == NULL)
7427850SVuong.Nguyen@Sun.COM return;
7437850SVuong.Nguyen@Sun.COM if ((root = xmlDocGetRootElement(xml_output)) == NULL)
7447850SVuong.Nguyen@Sun.COM return;
7457850SVuong.Nguyen@Sun.COM
7467850SVuong.Nguyen@Sun.COM /* get the cmd node */
7477850SVuong.Nguyen@Sun.COM if ((cmd = xml_find_subnode(root, XML_CMD)) == NULL)
7487850SVuong.Nguyen@Sun.COM return;
7497850SVuong.Nguyen@Sun.COM if (strcmp((char *)cmd->name, (char *)XML_CMD) != 0)
7507850SVuong.Nguyen@Sun.COM return;
7517850SVuong.Nguyen@Sun.COM
7527850SVuong.Nguyen@Sun.COM /* get the action node and make sure it is the reg-domain-events */
7537850SVuong.Nguyen@Sun.COM if ((action = xml_find_subnode(cmd, XML_ACTION)) == NULL) {
7547850SVuong.Nguyen@Sun.COM return;
7557850SVuong.Nguyen@Sun.COM }
7567850SVuong.Nguyen@Sun.COM if ((action_str = (char *)xmlNodeGetContent(action)) == NULL)
7577850SVuong.Nguyen@Sun.COM return;
7587850SVuong.Nguyen@Sun.COM if (strcmp(action_str, XML_REGISTER_ACTION) != 0) {
7597850SVuong.Nguyen@Sun.COM xmlFree(action_str);
7607850SVuong.Nguyen@Sun.COM return;
7617850SVuong.Nguyen@Sun.COM }
7627850SVuong.Nguyen@Sun.COM xmlFree(action_str);
7637850SVuong.Nguyen@Sun.COM
7647850SVuong.Nguyen@Sun.COM /* check the status of the response */
7657850SVuong.Nguyen@Sun.COM if ((resp = xml_find_subnode(cmd, XML_RESPONSE)) == NULL)
7667850SVuong.Nguyen@Sun.COM return;
7677850SVuong.Nguyen@Sun.COM if ((status = xml_find_subnode(resp, XML_STATUS)) == NULL)
7687850SVuong.Nguyen@Sun.COM return;
7697850SVuong.Nguyen@Sun.COM if ((status_str = (char *)xmlNodeGetContent(status)) == NULL)
7707850SVuong.Nguyen@Sun.COM return;
7717850SVuong.Nguyen@Sun.COM if (strcmp(status_str, (char *)XML_FAILURE) == 0) {
7727850SVuong.Nguyen@Sun.COM conn->state = CONN_STATE_FAILURE;
7737850SVuong.Nguyen@Sun.COM }
7747850SVuong.Nguyen@Sun.COM xmlFree(status_str);
7757850SVuong.Nguyen@Sun.COM }
7767850SVuong.Nguyen@Sun.COM
7777850SVuong.Nguyen@Sun.COM /*
7787850SVuong.Nguyen@Sun.COM * handle_ldm_event()
7797850SVuong.Nguyen@Sun.COM * Description:
7807850SVuong.Nguyen@Sun.COM * Parse the LDM_event for the ldom name and domain action. Then invokes
7817850SVuong.Nguyen@Sun.COM * the clients's callback to notify them the event.
7827850SVuong.Nguyen@Sun.COM */
7837850SVuong.Nguyen@Sun.COM /*ARGSUSED*/
7847850SVuong.Nguyen@Sun.COM void
handle_ldm_event(xmpp_conn_t * conn,char * buf,size_t buf_size)7857850SVuong.Nguyen@Sun.COM handle_ldm_event(xmpp_conn_t *conn, char *buf, size_t buf_size)
7867850SVuong.Nguyen@Sun.COM {
7877850SVuong.Nguyen@Sun.COM int i;
7887850SVuong.Nguyen@Sun.COM xmlDocPtr xml_output;
7897850SVuong.Nguyen@Sun.COM xmlNodePtr root, cmd, action, data, envelope, content;
7907850SVuong.Nguyen@Sun.COM char *action_str, *ldom_name;
7917850SVuong.Nguyen@Sun.COM ldom_event_t event = LDOM_EVENT_UNKNOWN;
7927850SVuong.Nguyen@Sun.COM
7937850SVuong.Nguyen@Sun.COM if ((xml_output = xmlParseMemory((const char *)buf, buf_size)) == NULL)
7947850SVuong.Nguyen@Sun.COM return;
7957850SVuong.Nguyen@Sun.COM if ((root = xmlDocGetRootElement(xml_output)) == NULL)
7967850SVuong.Nguyen@Sun.COM return;
7977850SVuong.Nguyen@Sun.COM
7987850SVuong.Nguyen@Sun.COM /* get the action such as bind-domain, unbind-domain, etc. */
7997850SVuong.Nguyen@Sun.COM if ((cmd = xml_find_subnode(root, XML_CMD)) == NULL)
8007850SVuong.Nguyen@Sun.COM return;
8017850SVuong.Nguyen@Sun.COM if ((action = xml_find_subnode(cmd, XML_ACTION)) == NULL) {
8027850SVuong.Nguyen@Sun.COM return;
8037850SVuong.Nguyen@Sun.COM }
8047850SVuong.Nguyen@Sun.COM if ((action_str = (char *)xmlNodeGetContent(action)) == NULL)
8057850SVuong.Nguyen@Sun.COM return;
8067850SVuong.Nguyen@Sun.COM for (i = 0; i < event_table_size; i++) {
8077850SVuong.Nguyen@Sun.COM if (event_table[i].name != NULL &&
8087850SVuong.Nguyen@Sun.COM strcasecmp(event_table[i].name, action_str) == 0) {
8097850SVuong.Nguyen@Sun.COM event = event_table[i].id;
8107850SVuong.Nguyen@Sun.COM break;
8117850SVuong.Nguyen@Sun.COM }
8127850SVuong.Nguyen@Sun.COM }
8137850SVuong.Nguyen@Sun.COM xmlFree(action_str);
8147850SVuong.Nguyen@Sun.COM
8157850SVuong.Nguyen@Sun.COM /* get the ldom name */
8167850SVuong.Nguyen@Sun.COM data = xml_find_subnode(cmd, XML_DATA);
8177850SVuong.Nguyen@Sun.COM envelope = xml_find_subnode(data, XML_ENVELOPE);
8187850SVuong.Nguyen@Sun.COM content = xml_find_subnode(envelope, XML_CONTENT);
8197850SVuong.Nguyen@Sun.COM if ((ldom_name = (char *)xmlGetProp(content, XML_ATTR_ID)) == NULL)
8207850SVuong.Nguyen@Sun.COM return;
8217850SVuong.Nguyen@Sun.COM
8227850SVuong.Nguyen@Sun.COM /* Notifies all the clients the event */
8237850SVuong.Nguyen@Sun.COM if (VALID_LDOM_EVENT(event)) {
8247850SVuong.Nguyen@Sun.COM notify_event(event, ldom_name);
8257850SVuong.Nguyen@Sun.COM }
8267850SVuong.Nguyen@Sun.COM
8277850SVuong.Nguyen@Sun.COM xmlFree(ldom_name);
8287850SVuong.Nguyen@Sun.COM }
829