110480SAlexandre.Chartre@Sun.COM /*
210480SAlexandre.Chartre@Sun.COM * CDDL HEADER START
310480SAlexandre.Chartre@Sun.COM *
410480SAlexandre.Chartre@Sun.COM * The contents of this file are subject to the terms of the
510480SAlexandre.Chartre@Sun.COM * Common Development and Distribution License (the "License").
610480SAlexandre.Chartre@Sun.COM * You may not use this file except in compliance with the License.
710480SAlexandre.Chartre@Sun.COM *
810480SAlexandre.Chartre@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910480SAlexandre.Chartre@Sun.COM * or http://www.opensolaris.org/os/licensing.
1010480SAlexandre.Chartre@Sun.COM * See the License for the specific language governing permissions
1110480SAlexandre.Chartre@Sun.COM * and limitations under the License.
1210480SAlexandre.Chartre@Sun.COM *
1310480SAlexandre.Chartre@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1410480SAlexandre.Chartre@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510480SAlexandre.Chartre@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1610480SAlexandre.Chartre@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1710480SAlexandre.Chartre@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1810480SAlexandre.Chartre@Sun.COM *
1910480SAlexandre.Chartre@Sun.COM * CDDL HEADER END
2010480SAlexandre.Chartre@Sun.COM */
2110480SAlexandre.Chartre@Sun.COM
2210480SAlexandre.Chartre@Sun.COM /*
23*12051SAlexandre.Chartre@oracle.com * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2410480SAlexandre.Chartre@Sun.COM */
2510480SAlexandre.Chartre@Sun.COM
2610480SAlexandre.Chartre@Sun.COM /*
2710480SAlexandre.Chartre@Sun.COM * Logical Domains (LDoms) Agents Daemon
2810480SAlexandre.Chartre@Sun.COM *
2910480SAlexandre.Chartre@Sun.COM * The LDoms agents daemon (ldmad) runs on LDoms domains and provides
3010480SAlexandre.Chartre@Sun.COM * information to the control domain. It is composed of a set of agents
3110480SAlexandre.Chartre@Sun.COM * which can send and receive messages to and from the control domain.
3210480SAlexandre.Chartre@Sun.COM * Each agent is registered as a domain service using the libds library,
3310480SAlexandre.Chartre@Sun.COM * and is able to handle requests coming from the control domain.
3410480SAlexandre.Chartre@Sun.COM *
3510480SAlexandre.Chartre@Sun.COM * The control domain sends requests to an agent as messages on the
3610480SAlexandre.Chartre@Sun.COM * corresponding domain service (identified by the agent name). All requests
3710480SAlexandre.Chartre@Sun.COM * are received by the ldmad daemon which dispatches them to the appropriate
3810480SAlexandre.Chartre@Sun.COM * handler function of the agent depending on the type of the message.
3910480SAlexandre.Chartre@Sun.COM *
4010480SAlexandre.Chartre@Sun.COM * After the request has been processed by the handler, the ldmad daemon sent
4110480SAlexandre.Chartre@Sun.COM * a reply message back to the control domain. The reply is either a result
4210480SAlexandre.Chartre@Sun.COM * message if the request was successfully completed, or an error message
4310480SAlexandre.Chartre@Sun.COM * describing the failure.
4410480SAlexandre.Chartre@Sun.COM */
4510480SAlexandre.Chartre@Sun.COM
4610480SAlexandre.Chartre@Sun.COM #include <dirent.h>
4710480SAlexandre.Chartre@Sun.COM #include <errno.h>
4810480SAlexandre.Chartre@Sun.COM #include <fcntl.h>
4910480SAlexandre.Chartre@Sun.COM #include <libds.h>
5010480SAlexandre.Chartre@Sun.COM #include <libgen.h>
5110480SAlexandre.Chartre@Sun.COM #include <signal.h>
5210480SAlexandre.Chartre@Sun.COM #include <stdio.h>
5310480SAlexandre.Chartre@Sun.COM #include <stdlib.h>
5410480SAlexandre.Chartre@Sun.COM #include <strings.h>
5511833SMichael.Christensen@Sun.COM #include <synch.h>
5610480SAlexandre.Chartre@Sun.COM #include <syslog.h>
5711833SMichael.Christensen@Sun.COM #include <thread.h>
5810480SAlexandre.Chartre@Sun.COM #include <unistd.h>
5911833SMichael.Christensen@Sun.COM #include <sys/debug.h>
6011833SMichael.Christensen@Sun.COM #include <sys/ldoms.h>
6110480SAlexandre.Chartre@Sun.COM #include <sys/types.h>
6210480SAlexandre.Chartre@Sun.COM #include <sys/stat.h>
6310480SAlexandre.Chartre@Sun.COM #include <sys/wait.h>
6410480SAlexandre.Chartre@Sun.COM
6510480SAlexandre.Chartre@Sun.COM #include "ldma.h"
6610480SAlexandre.Chartre@Sun.COM
6710480SAlexandre.Chartre@Sun.COM #define LDMA_MODULE "ldm-agent-daemon"
6810480SAlexandre.Chartre@Sun.COM
6910480SAlexandre.Chartre@Sun.COM #define LDMA_CONTROL_DOMAIN_DHDL 0 /* id of the control domain */
7011833SMichael.Christensen@Sun.COM
7111833SMichael.Christensen@Sun.COM typedef struct ldma_connexion_t {
7211833SMichael.Christensen@Sun.COM ds_hdl_t hdl; /* connexion handle */
7311833SMichael.Christensen@Sun.COM ds_domain_hdl_t dhdl; /* connexion domain handle */
7411833SMichael.Christensen@Sun.COM ds_ver_t ver; /* connexion version */
7511833SMichael.Christensen@Sun.COM } ldma_connexion_t;
7610480SAlexandre.Chartre@Sun.COM
7710480SAlexandre.Chartre@Sun.COM typedef struct ldma_agent {
7810480SAlexandre.Chartre@Sun.COM ldma_agent_info_t *info; /* agent information */
7911833SMichael.Christensen@Sun.COM mutex_t conn_lock; /* connexion table lock */
8011833SMichael.Christensen@Sun.COM ldma_connexion_t conn[LDOMS_MAX_DOMAINS]; /* connexions */
8110480SAlexandre.Chartre@Sun.COM } ldma_agent_t;
8210480SAlexandre.Chartre@Sun.COM
8310480SAlexandre.Chartre@Sun.COM /* information about existing agents */
8410480SAlexandre.Chartre@Sun.COM extern ldma_agent_info_t ldma_device_info;
8510480SAlexandre.Chartre@Sun.COM extern ldma_agent_info_t ldma_system_info;
8611596SJason.Beloro@Sun.COM extern ldma_agent_info_t ldma_dio_info;
8710480SAlexandre.Chartre@Sun.COM
8810480SAlexandre.Chartre@Sun.COM boolean_t ldma_debug = B_FALSE;
8910480SAlexandre.Chartre@Sun.COM boolean_t ldma_daemon = B_FALSE;
9010480SAlexandre.Chartre@Sun.COM
9110480SAlexandre.Chartre@Sun.COM static ldma_agent_info_t *ldma_agent_infos[] = {
9210480SAlexandre.Chartre@Sun.COM &ldma_device_info,
9310480SAlexandre.Chartre@Sun.COM &ldma_system_info,
9411596SJason.Beloro@Sun.COM &ldma_dio_info,
9510480SAlexandre.Chartre@Sun.COM NULL
9610480SAlexandre.Chartre@Sun.COM };
9710480SAlexandre.Chartre@Sun.COM
9810480SAlexandre.Chartre@Sun.COM static char *cmdname;
9911029SAlexandre.Chartre@Sun.COM static pid_t daemon_pid = 0;
10010480SAlexandre.Chartre@Sun.COM
10110480SAlexandre.Chartre@Sun.COM /*
10211833SMichael.Christensen@Sun.COM * Lookup connexion in agent connexion table.
10311833SMichael.Christensen@Sun.COM */
10411833SMichael.Christensen@Sun.COM static ldma_connexion_t *
ldma_connexion_lookup(ldma_agent_t * agent,ds_hdl_t hdl)10511833SMichael.Christensen@Sun.COM ldma_connexion_lookup(ldma_agent_t *agent, ds_hdl_t hdl)
10611833SMichael.Christensen@Sun.COM {
10711833SMichael.Christensen@Sun.COM ldma_connexion_t *connp;
10811833SMichael.Christensen@Sun.COM int i;
10911833SMichael.Christensen@Sun.COM
11011833SMichael.Christensen@Sun.COM ASSERT(MUTEX_HELD(&agent->conn_lock));
11111833SMichael.Christensen@Sun.COM for (connp = agent->conn, i = 0; i < LDOMS_MAX_DOMAINS; i++, connp++) {
11211833SMichael.Christensen@Sun.COM if (connp->hdl == hdl)
11311833SMichael.Christensen@Sun.COM return (connp);
11411833SMichael.Christensen@Sun.COM }
11511833SMichael.Christensen@Sun.COM return (NULL);
11611833SMichael.Christensen@Sun.COM }
11711833SMichael.Christensen@Sun.COM
11811833SMichael.Christensen@Sun.COM /*
11911833SMichael.Christensen@Sun.COM * Add connextion to agent connexion table.
12011833SMichael.Christensen@Sun.COM */
12111833SMichael.Christensen@Sun.COM static int
ldma_connexion_add(ldma_agent_t * agent,ds_hdl_t hdl,ds_domain_hdl_t dhdl,ds_ver_t * verp)12211833SMichael.Christensen@Sun.COM ldma_connexion_add(ldma_agent_t *agent, ds_hdl_t hdl, ds_domain_hdl_t dhdl,
12311833SMichael.Christensen@Sun.COM ds_ver_t *verp)
12411833SMichael.Christensen@Sun.COM {
12511833SMichael.Christensen@Sun.COM ldma_connexion_t *connp;
12611833SMichael.Christensen@Sun.COM ldma_connexion_t *availp = NULL;
12711833SMichael.Christensen@Sun.COM int i;
12811833SMichael.Christensen@Sun.COM
12911833SMichael.Christensen@Sun.COM (void) mutex_lock(&agent->conn_lock);
13011833SMichael.Christensen@Sun.COM for (connp = agent->conn, i = 0; i < LDOMS_MAX_DOMAINS; i++, connp++) {
13111833SMichael.Christensen@Sun.COM if (connp->hdl == hdl)
13211833SMichael.Christensen@Sun.COM break;
13311833SMichael.Christensen@Sun.COM if (availp == NULL && connp->hdl == DS_INVALID_HDL)
13411833SMichael.Christensen@Sun.COM availp = connp;
13511833SMichael.Christensen@Sun.COM }
13611833SMichael.Christensen@Sun.COM
13711833SMichael.Christensen@Sun.COM if (i < LDOMS_MAX_DOMAINS) {
13811833SMichael.Christensen@Sun.COM (void) mutex_unlock(&agent->conn_lock);
13911833SMichael.Christensen@Sun.COM LDMA_INFO("agent %s hdl %llx already exists", agent->info->name,
14011833SMichael.Christensen@Sun.COM hdl);
14111833SMichael.Christensen@Sun.COM return (0);
14211833SMichael.Christensen@Sun.COM }
14311833SMichael.Christensen@Sun.COM
14411833SMichael.Christensen@Sun.COM if (!availp) {
14511833SMichael.Christensen@Sun.COM (void) mutex_unlock(&agent->conn_lock);
14611833SMichael.Christensen@Sun.COM LDMA_INFO("agent %s too many connections", agent->info->name);
14711833SMichael.Christensen@Sun.COM return (0);
14811833SMichael.Christensen@Sun.COM }
14911833SMichael.Christensen@Sun.COM
15011833SMichael.Christensen@Sun.COM LDMA_DBG("agent %s adding connection (%x) %llx, %llx, %d.%d",
15111833SMichael.Christensen@Sun.COM agent->info->name, availp, hdl, dhdl, verp->major, verp->minor);
15211833SMichael.Christensen@Sun.COM
15311833SMichael.Christensen@Sun.COM availp->hdl = hdl;
15411833SMichael.Christensen@Sun.COM availp->dhdl = dhdl;
15511833SMichael.Christensen@Sun.COM availp->ver = *verp;
15611833SMichael.Christensen@Sun.COM (void) mutex_unlock(&agent->conn_lock);
15711833SMichael.Christensen@Sun.COM return (1);
15811833SMichael.Christensen@Sun.COM }
15911833SMichael.Christensen@Sun.COM
16011833SMichael.Christensen@Sun.COM /*
16111833SMichael.Christensen@Sun.COM * Delete connexion from agent connexion table.
16211833SMichael.Christensen@Sun.COM */
16311833SMichael.Christensen@Sun.COM static int
ldma_connexion_delete(ldma_agent_t * agent,ds_hdl_t hdl)16411833SMichael.Christensen@Sun.COM ldma_connexion_delete(ldma_agent_t *agent, ds_hdl_t hdl)
16511833SMichael.Christensen@Sun.COM {
16611833SMichael.Christensen@Sun.COM ldma_connexion_t *connp;
16711833SMichael.Christensen@Sun.COM
16811833SMichael.Christensen@Sun.COM (void) mutex_lock(&agent->conn_lock);
16911833SMichael.Christensen@Sun.COM if ((connp = ldma_connexion_lookup(agent, hdl)) == NULL) {
17011833SMichael.Christensen@Sun.COM (void) mutex_unlock(&agent->conn_lock);
17111833SMichael.Christensen@Sun.COM LDMA_INFO("agent %s connection delete failed to find %llx",
17211833SMichael.Christensen@Sun.COM agent->info->name, hdl);
17311833SMichael.Christensen@Sun.COM return (0);
17411833SMichael.Christensen@Sun.COM }
17511833SMichael.Christensen@Sun.COM
17611833SMichael.Christensen@Sun.COM LDMA_DBG("agent %s deleting connection (%x) %llx", agent->info->name,
17711833SMichael.Christensen@Sun.COM connp, hdl);
17811833SMichael.Christensen@Sun.COM
17911833SMichael.Christensen@Sun.COM connp->hdl = DS_INVALID_HDL;
18011833SMichael.Christensen@Sun.COM connp->dhdl = 0;
18111833SMichael.Christensen@Sun.COM connp->ver.major = 0;
18211833SMichael.Christensen@Sun.COM connp->ver.minor = 0;
18311833SMichael.Christensen@Sun.COM (void) mutex_unlock(&agent->conn_lock);
18411833SMichael.Christensen@Sun.COM return (1);
18511833SMichael.Christensen@Sun.COM }
18611833SMichael.Christensen@Sun.COM
18711833SMichael.Christensen@Sun.COM /*
18811833SMichael.Christensen@Sun.COM * Initialize connexion table.
18911833SMichael.Christensen@Sun.COM */
19011833SMichael.Christensen@Sun.COM static void
ldma_connexion_init(ldma_agent_t * agent)19111833SMichael.Christensen@Sun.COM ldma_connexion_init(ldma_agent_t *agent)
19211833SMichael.Christensen@Sun.COM {
19311833SMichael.Christensen@Sun.COM ldma_connexion_t *connp;
19411833SMichael.Christensen@Sun.COM int i;
19511833SMichael.Christensen@Sun.COM
19611833SMichael.Christensen@Sun.COM for (connp = agent->conn, i = 0; i < LDOMS_MAX_DOMAINS; i++, connp++) {
19711833SMichael.Christensen@Sun.COM connp->hdl = DS_INVALID_HDL;
19811833SMichael.Christensen@Sun.COM }
19911833SMichael.Christensen@Sun.COM }
20011833SMichael.Christensen@Sun.COM
20111833SMichael.Christensen@Sun.COM /*
20210480SAlexandre.Chartre@Sun.COM * Allocate a new message with the specified message number (msg_num),
20310480SAlexandre.Chartre@Sun.COM * message type (msg_type) and message data length (msg_dlen). Return
20410480SAlexandre.Chartre@Sun.COM * NULL if the allocation has failed.
20510480SAlexandre.Chartre@Sun.COM */
20610480SAlexandre.Chartre@Sun.COM static ldma_message_header_t *
ldma_alloc_msg(uint64_t msg_num,uint32_t msg_type,size_t msg_dlen)20710480SAlexandre.Chartre@Sun.COM ldma_alloc_msg(uint64_t msg_num, uint32_t msg_type, size_t msg_dlen)
20810480SAlexandre.Chartre@Sun.COM {
20910480SAlexandre.Chartre@Sun.COM ldma_message_header_t *msg;
21010480SAlexandre.Chartre@Sun.COM size_t msg_len;
21110480SAlexandre.Chartre@Sun.COM
21210480SAlexandre.Chartre@Sun.COM msg_len = LDMA_MESSAGE_SIZE(msg_dlen);
21310480SAlexandre.Chartre@Sun.COM msg = malloc(msg_len);
21410480SAlexandre.Chartre@Sun.COM if (msg == NULL)
21510480SAlexandre.Chartre@Sun.COM return (NULL);
21610480SAlexandre.Chartre@Sun.COM
21710480SAlexandre.Chartre@Sun.COM msg->msg_num = msg_num;
21810480SAlexandre.Chartre@Sun.COM msg->msg_type = msg_type;
21910480SAlexandre.Chartre@Sun.COM msg->msg_info = 0;
22010480SAlexandre.Chartre@Sun.COM
22110480SAlexandre.Chartre@Sun.COM return (msg);
22210480SAlexandre.Chartre@Sun.COM }
22310480SAlexandre.Chartre@Sun.COM
22410480SAlexandre.Chartre@Sun.COM /*
22510480SAlexandre.Chartre@Sun.COM * Allocate a result message (LDMA_MSG_REQ_RESULT) with the specified message
22610480SAlexandre.Chartre@Sun.COM * data length (msg_dlen). If the request argument is not NULL then the message
22710480SAlexandre.Chartre@Sun.COM * is created with the same message number as the request, otherwise the message
22810480SAlexandre.Chartre@Sun.COM * number is set to 0. Return NULL if the allocation has failed.
22910480SAlexandre.Chartre@Sun.COM */
23010480SAlexandre.Chartre@Sun.COM ldma_message_header_t *
ldma_alloc_result_msg(ldma_message_header_t * request,size_t msg_dlen)23110480SAlexandre.Chartre@Sun.COM ldma_alloc_result_msg(ldma_message_header_t *request, size_t msg_dlen)
23210480SAlexandre.Chartre@Sun.COM {
23310480SAlexandre.Chartre@Sun.COM uint64_t msg_num;
23410480SAlexandre.Chartre@Sun.COM
23510480SAlexandre.Chartre@Sun.COM msg_num = (request == NULL)? 0 : request->msg_num;
23610480SAlexandre.Chartre@Sun.COM
23710480SAlexandre.Chartre@Sun.COM return (ldma_alloc_msg(msg_num, LDMA_MSG_RESULT, msg_dlen));
23810480SAlexandre.Chartre@Sun.COM }
23910480SAlexandre.Chartre@Sun.COM
24010480SAlexandre.Chartre@Sun.COM /*
24110480SAlexandre.Chartre@Sun.COM * Agent register callback. This callback is invoked when a client is registered
24210480SAlexandre.Chartre@Sun.COM * for using the service provided by an agent. An agent will only have one
24310480SAlexandre.Chartre@Sun.COM * consumer which is coming from the control domain.
24410480SAlexandre.Chartre@Sun.COM */
24510480SAlexandre.Chartre@Sun.COM static void
ldma_reg_cb(ds_hdl_t hdl,ds_cb_arg_t arg,ds_ver_t * ver,ds_domain_hdl_t dhdl)24610480SAlexandre.Chartre@Sun.COM ldma_reg_cb(ds_hdl_t hdl, ds_cb_arg_t arg, ds_ver_t *ver,
24710480SAlexandre.Chartre@Sun.COM ds_domain_hdl_t dhdl)
24810480SAlexandre.Chartre@Sun.COM {
24910480SAlexandre.Chartre@Sun.COM ldma_agent_t *agent = (ldma_agent_t *)arg;
25011833SMichael.Christensen@Sun.COM char dname[LDOMS_MAX_NAME_LEN];
25110480SAlexandre.Chartre@Sun.COM
25211833SMichael.Christensen@Sun.COM if (ds_dom_hdl_to_name(dhdl, dname, LDOMS_MAX_NAME_LEN) != 0) {
25310480SAlexandre.Chartre@Sun.COM (void) strcpy(dname, "<unknown>");
25410480SAlexandre.Chartre@Sun.COM }
25510480SAlexandre.Chartre@Sun.COM
25610480SAlexandre.Chartre@Sun.COM LDMA_DBG("%s: REGISTER hdl=%llx, dhdl=%llx (%s) ver=%hd.%hd",
25710480SAlexandre.Chartre@Sun.COM agent->info->name, hdl, dhdl, dname, ver->major, ver->minor);
25810480SAlexandre.Chartre@Sun.COM
25910480SAlexandre.Chartre@Sun.COM /*
26011833SMichael.Christensen@Sun.COM * Record client information. Access control is done on a
26111833SMichael.Christensen@Sun.COM * message-by-message basis upon receipt of the message.
26210480SAlexandre.Chartre@Sun.COM */
26311833SMichael.Christensen@Sun.COM if (!ldma_connexion_add(agent, hdl, dhdl, ver)) {
26411833SMichael.Christensen@Sun.COM LDMA_INFO("agent %s failed to add connection from "
26510480SAlexandre.Chartre@Sun.COM "domain %s", agent->info->name, dname);
26610480SAlexandre.Chartre@Sun.COM }
26710480SAlexandre.Chartre@Sun.COM }
26810480SAlexandre.Chartre@Sun.COM
26910480SAlexandre.Chartre@Sun.COM /*
27010480SAlexandre.Chartre@Sun.COM * Agent unregister callback. This callback is invoked when a client is
27110480SAlexandre.Chartre@Sun.COM * unregistered and stops using the service provided by an agent.
27210480SAlexandre.Chartre@Sun.COM */
27310480SAlexandre.Chartre@Sun.COM static void
ldma_unreg_cb(ds_hdl_t hdl,ds_cb_arg_t arg)27410480SAlexandre.Chartre@Sun.COM ldma_unreg_cb(ds_hdl_t hdl, ds_cb_arg_t arg)
27510480SAlexandre.Chartre@Sun.COM {
27610480SAlexandre.Chartre@Sun.COM ldma_agent_t *agent = (ldma_agent_t *)arg;
27710480SAlexandre.Chartre@Sun.COM
27810480SAlexandre.Chartre@Sun.COM LDMA_DBG("%s: UNREGISTER hdl=%llx", agent->info->name, hdl);
27910480SAlexandre.Chartre@Sun.COM
28011833SMichael.Christensen@Sun.COM if (!ldma_connexion_delete(agent, hdl)) {
28111833SMichael.Christensen@Sun.COM LDMA_INFO("agent %s failed to unregister handle %llx",
28211833SMichael.Christensen@Sun.COM agent->info->name, hdl);
28310480SAlexandre.Chartre@Sun.COM }
28410480SAlexandre.Chartre@Sun.COM }
28510480SAlexandre.Chartre@Sun.COM
28610480SAlexandre.Chartre@Sun.COM /*
28710480SAlexandre.Chartre@Sun.COM * Agent data callback. This callback is invoked when an agent receives a new
28810480SAlexandre.Chartre@Sun.COM * message from a client. Any request from a client which is not the control
28910480SAlexandre.Chartre@Sun.COM * domain is immediatly rejected. Otherwise the message is forwarded to the
29010480SAlexandre.Chartre@Sun.COM * appropriate handler function provided by the agent, depending on the message
29110480SAlexandre.Chartre@Sun.COM * type.
29210480SAlexandre.Chartre@Sun.COM */
29310480SAlexandre.Chartre@Sun.COM static void
ldma_data_cb(ds_hdl_t hdl,ds_cb_arg_t arg,void * buf,size_t len)29410480SAlexandre.Chartre@Sun.COM ldma_data_cb(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf, size_t len)
29510480SAlexandre.Chartre@Sun.COM {
29610480SAlexandre.Chartre@Sun.COM ldma_agent_t *agent = (ldma_agent_t *)arg;
29710480SAlexandre.Chartre@Sun.COM ldma_msg_handler_t *handler;
29810480SAlexandre.Chartre@Sun.COM ldma_message_header_t *request = buf;
29910480SAlexandre.Chartre@Sun.COM ldma_message_header_t *reply = NULL;
30011833SMichael.Christensen@Sun.COM ldma_connexion_t *connp;
30111833SMichael.Christensen@Sun.COM ds_ver_t conn_ver;
30211833SMichael.Christensen@Sun.COM ds_domain_hdl_t conn_dhdl;
30310480SAlexandre.Chartre@Sun.COM ldma_request_status_t status;
30410480SAlexandre.Chartre@Sun.COM size_t request_dlen, reply_len, reply_dlen = 0;
30510480SAlexandre.Chartre@Sun.COM int i;
30610480SAlexandre.Chartre@Sun.COM
30710480SAlexandre.Chartre@Sun.COM /* check the message size */
30810480SAlexandre.Chartre@Sun.COM if (len < LDMA_MESSAGE_HEADER_SIZE) {
30910480SAlexandre.Chartre@Sun.COM LDMA_INFO("agent %s has ignored message with an invalid "
31010480SAlexandre.Chartre@Sun.COM "size of %d bytes", agent->info->name, len);
31110480SAlexandre.Chartre@Sun.COM return;
31210480SAlexandre.Chartre@Sun.COM }
31310480SAlexandre.Chartre@Sun.COM
31410480SAlexandre.Chartre@Sun.COM request_dlen = LDMA_MESSAGE_DLEN(len);
31510480SAlexandre.Chartre@Sun.COM
31610480SAlexandre.Chartre@Sun.COM LDMA_DBG("%s: DATA hdl=%llx, request num=%llu type=0x%x info=0x%x "
31710480SAlexandre.Chartre@Sun.COM "dlen=%d", agent->info->name, hdl, request->msg_num,
31810480SAlexandre.Chartre@Sun.COM request->msg_type, request->msg_info, request_dlen);
31910480SAlexandre.Chartre@Sun.COM
32011833SMichael.Christensen@Sun.COM (void) mutex_lock(&agent->conn_lock);
32111833SMichael.Christensen@Sun.COM connp = ldma_connexion_lookup(agent, hdl);
32211833SMichael.Christensen@Sun.COM if (connp != NULL) {
32311833SMichael.Christensen@Sun.COM conn_dhdl = connp->dhdl;
32411833SMichael.Christensen@Sun.COM conn_ver = connp->ver;
32511833SMichael.Christensen@Sun.COM }
32611833SMichael.Christensen@Sun.COM (void) mutex_unlock(&agent->conn_lock);
32711833SMichael.Christensen@Sun.COM
32811833SMichael.Christensen@Sun.COM /* reject any request which is not in the connexion table */
32911833SMichael.Christensen@Sun.COM if (connp == NULL) {
33010480SAlexandre.Chartre@Sun.COM LDMA_DBG("%s: DATA hdl=%llx, rejecting request from a "
33110480SAlexandre.Chartre@Sun.COM "distrusted domain", agent->info->name, hdl);
33210480SAlexandre.Chartre@Sun.COM status = LDMA_REQ_DENIED;
33310480SAlexandre.Chartre@Sun.COM goto do_reply;
33410480SAlexandre.Chartre@Sun.COM }
33510480SAlexandre.Chartre@Sun.COM
33610480SAlexandre.Chartre@Sun.COM handler = NULL;
33710480SAlexandre.Chartre@Sun.COM
33810480SAlexandre.Chartre@Sun.COM for (i = 0; i < agent->info->nhandlers; i++) {
33910480SAlexandre.Chartre@Sun.COM if (agent->info->handlers[i].msg_type == request->msg_type) {
34010480SAlexandre.Chartre@Sun.COM handler = &agent->info->handlers[i];
34110480SAlexandre.Chartre@Sun.COM break;
34210480SAlexandre.Chartre@Sun.COM }
34310480SAlexandre.Chartre@Sun.COM }
34410480SAlexandre.Chartre@Sun.COM
34510480SAlexandre.Chartre@Sun.COM if (handler == NULL) {
34610480SAlexandre.Chartre@Sun.COM /* this type of message is not defined by the agent */
34710480SAlexandre.Chartre@Sun.COM LDMA_DBG("%s: DATA hdl=%llx, unknown message type %x",
34810480SAlexandre.Chartre@Sun.COM agent->info->name, hdl, request->msg_type);
34910480SAlexandre.Chartre@Sun.COM status = LDMA_REQ_NOTSUP;
35010480SAlexandre.Chartre@Sun.COM goto do_reply;
35110480SAlexandre.Chartre@Sun.COM }
35210480SAlexandre.Chartre@Sun.COM
35311833SMichael.Christensen@Sun.COM /* reject any request from a guest which is not allowed */
35411833SMichael.Christensen@Sun.COM if ((conn_dhdl != LDMA_CONTROL_DOMAIN_DHDL) &&
35511833SMichael.Christensen@Sun.COM (handler->msg_flags & LDMA_MSGFLG_ACCESS_ANY) == 0) {
35611833SMichael.Christensen@Sun.COM LDMA_DBG("%s: DATA hdl=%llx, rejecting request from a "
35711833SMichael.Christensen@Sun.COM "distrusted domain", agent->info->name, hdl);
35811833SMichael.Christensen@Sun.COM status = LDMA_REQ_DENIED;
35911833SMichael.Christensen@Sun.COM goto do_reply;
36011833SMichael.Christensen@Sun.COM }
36111833SMichael.Christensen@Sun.COM
36210480SAlexandre.Chartre@Sun.COM if (handler->msg_handler == NULL) {
36310480SAlexandre.Chartre@Sun.COM /*
36410480SAlexandre.Chartre@Sun.COM * This type of message is defined by the agent but it
36510480SAlexandre.Chartre@Sun.COM * has no handler. That means there is no processing to
36610480SAlexandre.Chartre@Sun.COM * do, the message is just ignored, but the request is
36710480SAlexandre.Chartre@Sun.COM * successfully completed.
36810480SAlexandre.Chartre@Sun.COM */
36910480SAlexandre.Chartre@Sun.COM LDMA_DBG("%s: DATA hdl=%llx, no handler",
37010480SAlexandre.Chartre@Sun.COM agent->info->name, hdl);
37110480SAlexandre.Chartre@Sun.COM status = LDMA_REQ_COMPLETED;
37210480SAlexandre.Chartre@Sun.COM goto do_reply;
37310480SAlexandre.Chartre@Sun.COM }
37410480SAlexandre.Chartre@Sun.COM
37510480SAlexandre.Chartre@Sun.COM /* invoke the message handler of the agent */
37611833SMichael.Christensen@Sun.COM status = (*handler->msg_handler)(&conn_ver, request, request_dlen,
37711833SMichael.Christensen@Sun.COM &reply, &reply_dlen);
37810480SAlexandre.Chartre@Sun.COM
37910480SAlexandre.Chartre@Sun.COM LDMA_DBG("%s: DATA hdl=%llx, handler stat=%d reply=%p rlen=%d",
38010480SAlexandre.Chartre@Sun.COM agent->info->name, hdl, status, (void *)reply, reply_dlen);
38110480SAlexandre.Chartre@Sun.COM
38210480SAlexandre.Chartre@Sun.COM do_reply:
38310480SAlexandre.Chartre@Sun.COM /*
38410480SAlexandre.Chartre@Sun.COM * If the handler has provided a reply message, we use it directly.
38510480SAlexandre.Chartre@Sun.COM * Otherwise, we build a reply depending on the status of the request.
38610480SAlexandre.Chartre@Sun.COM * In that case, we re-use the request buffer to build the reply
38710480SAlexandre.Chartre@Sun.COM * message.
38810480SAlexandre.Chartre@Sun.COM */
38910480SAlexandre.Chartre@Sun.COM if (reply == NULL) {
39010480SAlexandre.Chartre@Sun.COM
39110480SAlexandre.Chartre@Sun.COM reply = request;
39210480SAlexandre.Chartre@Sun.COM reply_dlen = 0;
39310480SAlexandre.Chartre@Sun.COM
39410480SAlexandre.Chartre@Sun.COM if (status == LDMA_REQ_COMPLETED) {
39510480SAlexandre.Chartre@Sun.COM /*
39610480SAlexandre.Chartre@Sun.COM * The request was successful but no result message was
39710480SAlexandre.Chartre@Sun.COM * provided so we send an empty result message.
39810480SAlexandre.Chartre@Sun.COM */
39910480SAlexandre.Chartre@Sun.COM reply->msg_type = LDMA_MSG_RESULT;
40010480SAlexandre.Chartre@Sun.COM reply->msg_info = 0;
40110480SAlexandre.Chartre@Sun.COM
40210480SAlexandre.Chartre@Sun.COM } else {
40310480SAlexandre.Chartre@Sun.COM /*
40410480SAlexandre.Chartre@Sun.COM * The request has failed but no error message was
40510480SAlexandre.Chartre@Sun.COM * provided so we send an error message based on the
40610480SAlexandre.Chartre@Sun.COM * request status.
40710480SAlexandre.Chartre@Sun.COM */
40810480SAlexandre.Chartre@Sun.COM reply->msg_type = LDMA_MSG_ERROR;
40910480SAlexandre.Chartre@Sun.COM reply->msg_info =
41010480SAlexandre.Chartre@Sun.COM (status == LDMA_REQ_NOTSUP)? LDMA_MSGERR_NOTSUP :
41110480SAlexandre.Chartre@Sun.COM (status == LDMA_REQ_INVALID)? LDMA_MSGERR_INVALID :
41210480SAlexandre.Chartre@Sun.COM (status == LDMA_REQ_DENIED)? LDMA_MSGERR_DENY :
41310480SAlexandre.Chartre@Sun.COM LDMA_MSGERR_FAIL;
41410480SAlexandre.Chartre@Sun.COM }
41510480SAlexandre.Chartre@Sun.COM }
41610480SAlexandre.Chartre@Sun.COM
41710480SAlexandre.Chartre@Sun.COM reply_len = LDMA_MESSAGE_SIZE(reply_dlen);
41810480SAlexandre.Chartre@Sun.COM
41910480SAlexandre.Chartre@Sun.COM LDMA_DBG("%s: DATA hdl=%llx, reply num=%llu type=0x%x info=0x%x "
42010480SAlexandre.Chartre@Sun.COM "dlen=%d", agent->info->name, hdl, reply->msg_num,
42110480SAlexandre.Chartre@Sun.COM reply->msg_type, reply->msg_info, reply_dlen);
42210480SAlexandre.Chartre@Sun.COM
42310480SAlexandre.Chartre@Sun.COM if (ds_send_msg(hdl, reply, reply_len) != 0) {
42410480SAlexandre.Chartre@Sun.COM LDMA_ERR("agent %s has failed to send reply for request %llu",
42510480SAlexandre.Chartre@Sun.COM agent->info->name, request->msg_num);
42610480SAlexandre.Chartre@Sun.COM }
42710480SAlexandre.Chartre@Sun.COM
42810480SAlexandre.Chartre@Sun.COM if (reply != request)
42910480SAlexandre.Chartre@Sun.COM free(reply);
43010480SAlexandre.Chartre@Sun.COM }
43110480SAlexandre.Chartre@Sun.COM
43210480SAlexandre.Chartre@Sun.COM /*
43310480SAlexandre.Chartre@Sun.COM * Register an agent. Return 0 if the agent was successfully registered.
43410480SAlexandre.Chartre@Sun.COM */
43510480SAlexandre.Chartre@Sun.COM static int
ldma_register(ldma_agent_info_t * agent_info)43610480SAlexandre.Chartre@Sun.COM ldma_register(ldma_agent_info_t *agent_info)
43710480SAlexandre.Chartre@Sun.COM {
43810480SAlexandre.Chartre@Sun.COM ldma_agent_t *agent;
43910480SAlexandre.Chartre@Sun.COM ds_capability_t ds_cap;
44010480SAlexandre.Chartre@Sun.COM ds_ops_t ds_ops;
44110480SAlexandre.Chartre@Sun.COM
44210480SAlexandre.Chartre@Sun.COM agent = malloc(sizeof (ldma_agent_t));
44310480SAlexandre.Chartre@Sun.COM if (agent == NULL)
44410480SAlexandre.Chartre@Sun.COM goto register_fail;
44510480SAlexandre.Chartre@Sun.COM
44610480SAlexandre.Chartre@Sun.COM agent->info = agent_info;
44711833SMichael.Christensen@Sun.COM (void) mutex_init(&agent->conn_lock, USYNC_THREAD, NULL);
44811833SMichael.Christensen@Sun.COM ldma_connexion_init(agent);
44910480SAlexandre.Chartre@Sun.COM
45010480SAlexandre.Chartre@Sun.COM ds_cap.svc_id = agent_info->name;
45110480SAlexandre.Chartre@Sun.COM ds_cap.vers = agent_info->vers;
45210480SAlexandre.Chartre@Sun.COM ds_cap.nvers = agent_info->nvers;
45310480SAlexandre.Chartre@Sun.COM
45410480SAlexandre.Chartre@Sun.COM ds_ops.ds_reg_cb = ldma_reg_cb;
45510480SAlexandre.Chartre@Sun.COM ds_ops.ds_unreg_cb = ldma_unreg_cb;
45610480SAlexandre.Chartre@Sun.COM ds_ops.ds_data_cb = ldma_data_cb;
45710480SAlexandre.Chartre@Sun.COM ds_ops.cb_arg = agent;
45810480SAlexandre.Chartre@Sun.COM
45910480SAlexandre.Chartre@Sun.COM if (ds_svc_reg(&ds_cap, &ds_ops) == 0) {
46010480SAlexandre.Chartre@Sun.COM LDMA_INFO("agent %s registered", agent_info->name);
46110480SAlexandre.Chartre@Sun.COM return (0);
46210480SAlexandre.Chartre@Sun.COM }
46310480SAlexandre.Chartre@Sun.COM
46410480SAlexandre.Chartre@Sun.COM register_fail:
46510480SAlexandre.Chartre@Sun.COM
46610480SAlexandre.Chartre@Sun.COM LDMA_ERR("agent %s has failed to register", agent_info->name);
46710480SAlexandre.Chartre@Sun.COM free(agent);
46810480SAlexandre.Chartre@Sun.COM return (-1);
46910480SAlexandre.Chartre@Sun.COM }
47010480SAlexandre.Chartre@Sun.COM
47110480SAlexandre.Chartre@Sun.COM /*
47210480SAlexandre.Chartre@Sun.COM * Register all known agents. Return the number of agents successfully
47310480SAlexandre.Chartre@Sun.COM * registered.
47410480SAlexandre.Chartre@Sun.COM */
47510480SAlexandre.Chartre@Sun.COM static int
ldma_register_agents()47610480SAlexandre.Chartre@Sun.COM ldma_register_agents()
47710480SAlexandre.Chartre@Sun.COM {
47810480SAlexandre.Chartre@Sun.COM int count = 0;
47910480SAlexandre.Chartre@Sun.COM ldma_agent_info_t **agent_infop;
48010480SAlexandre.Chartre@Sun.COM
48110480SAlexandre.Chartre@Sun.COM for (agent_infop = ldma_agent_infos;
48210480SAlexandre.Chartre@Sun.COM *agent_infop != NULL; agent_infop++) {
48310480SAlexandre.Chartre@Sun.COM
48410480SAlexandre.Chartre@Sun.COM if (ldma_register(*agent_infop) == 0)
48510480SAlexandre.Chartre@Sun.COM count++;
48610480SAlexandre.Chartre@Sun.COM }
48710480SAlexandre.Chartre@Sun.COM
48810480SAlexandre.Chartre@Sun.COM return (count);
48910480SAlexandre.Chartre@Sun.COM }
49010480SAlexandre.Chartre@Sun.COM
49110480SAlexandre.Chartre@Sun.COM /*ARGSUSED*/
49210480SAlexandre.Chartre@Sun.COM static void
ldma_sigusr_handler(int sig,siginfo_t * sinfo,void * ucontext)49310480SAlexandre.Chartre@Sun.COM ldma_sigusr_handler(int sig, siginfo_t *sinfo, void *ucontext)
49410480SAlexandre.Chartre@Sun.COM {
49511029SAlexandre.Chartre@Sun.COM /*
49611029SAlexandre.Chartre@Sun.COM * The child process can send the signal before the fork()
49711029SAlexandre.Chartre@Sun.COM * call has returned in the parent process. So daemon_pid
49811029SAlexandre.Chartre@Sun.COM * may not be set yet, and we don't check the pid in that
49911029SAlexandre.Chartre@Sun.COM * case.
50011029SAlexandre.Chartre@Sun.COM */
50111029SAlexandre.Chartre@Sun.COM if (sig != SIGUSR1 || sinfo->si_code != SI_USER ||
50211029SAlexandre.Chartre@Sun.COM (daemon_pid > 0 && sinfo->si_pid != daemon_pid))
50310480SAlexandre.Chartre@Sun.COM return;
50410480SAlexandre.Chartre@Sun.COM
50510480SAlexandre.Chartre@Sun.COM /*
50610480SAlexandre.Chartre@Sun.COM * The parent process has received a USR1 signal from the child.
50710480SAlexandre.Chartre@Sun.COM * This means that the daemon has correctly started and the parent
50810480SAlexandre.Chartre@Sun.COM * can exit.
50910480SAlexandre.Chartre@Sun.COM */
51010480SAlexandre.Chartre@Sun.COM exit(0);
51110480SAlexandre.Chartre@Sun.COM }
51210480SAlexandre.Chartre@Sun.COM
51310480SAlexandre.Chartre@Sun.COM static void
ldma_start(boolean_t standalone)51410480SAlexandre.Chartre@Sun.COM ldma_start(boolean_t standalone)
51510480SAlexandre.Chartre@Sun.COM {
51610480SAlexandre.Chartre@Sun.COM int stat, rv;
51710480SAlexandre.Chartre@Sun.COM struct sigaction action;
51810480SAlexandre.Chartre@Sun.COM
51910480SAlexandre.Chartre@Sun.COM if (!standalone) {
52010480SAlexandre.Chartre@Sun.COM /*
52110480SAlexandre.Chartre@Sun.COM * Some configuration of the daemon has to be done in the
52210480SAlexandre.Chartre@Sun.COM * child, but we want the parent to report if the daemon
52310480SAlexandre.Chartre@Sun.COM * has successfully started or not. So we setup a signal
52410480SAlexandre.Chartre@Sun.COM * handler, and the child will notify the parent using the
52510480SAlexandre.Chartre@Sun.COM * USR1 signal if the setup was successful. Otherwise the
52610480SAlexandre.Chartre@Sun.COM * child will exit.
52710480SAlexandre.Chartre@Sun.COM */
52810480SAlexandre.Chartre@Sun.COM action.sa_sigaction = ldma_sigusr_handler;
52910480SAlexandre.Chartre@Sun.COM action.sa_flags = SA_SIGINFO;
53010480SAlexandre.Chartre@Sun.COM
53110480SAlexandre.Chartre@Sun.COM if (sigemptyset(&action.sa_mask) == -1) {
53210480SAlexandre.Chartre@Sun.COM LDMA_ERR("sigemptyset error (%d)", errno);
53310480SAlexandre.Chartre@Sun.COM exit(1);
53410480SAlexandre.Chartre@Sun.COM }
53510480SAlexandre.Chartre@Sun.COM
53610480SAlexandre.Chartre@Sun.COM if (sigaction(SIGUSR1, &action, NULL) == -1) {
53710480SAlexandre.Chartre@Sun.COM LDMA_ERR("sigaction() error (%d)", errno);
53810480SAlexandre.Chartre@Sun.COM exit(1);
53910480SAlexandre.Chartre@Sun.COM }
54010480SAlexandre.Chartre@Sun.COM
54110480SAlexandre.Chartre@Sun.COM if (sigrelse(SIGUSR1) == -1) {
54210480SAlexandre.Chartre@Sun.COM LDMA_ERR("sigrelse() error (%d)", errno);
54310480SAlexandre.Chartre@Sun.COM exit(1);
54410480SAlexandre.Chartre@Sun.COM }
54510480SAlexandre.Chartre@Sun.COM
54610480SAlexandre.Chartre@Sun.COM if ((daemon_pid = fork()) == -1) {
54710480SAlexandre.Chartre@Sun.COM LDMA_ERR("fork() error (%d)", errno);
54810480SAlexandre.Chartre@Sun.COM exit(1);
54910480SAlexandre.Chartre@Sun.COM }
55010480SAlexandre.Chartre@Sun.COM
55110480SAlexandre.Chartre@Sun.COM if (daemon_pid != 0) {
55210480SAlexandre.Chartre@Sun.COM /*
55310480SAlexandre.Chartre@Sun.COM * The parent process waits until the child exits (in
55410480SAlexandre.Chartre@Sun.COM * case of an error) or sends a USR1 signal (if the
55510480SAlexandre.Chartre@Sun.COM * daemon has correctly started).
55610480SAlexandre.Chartre@Sun.COM */
55710480SAlexandre.Chartre@Sun.COM for (;;) {
55810480SAlexandre.Chartre@Sun.COM rv = waitpid(daemon_pid, &stat, 0);
55910480SAlexandre.Chartre@Sun.COM if ((rv == daemon_pid && WIFEXITED(stat)) ||
56010480SAlexandre.Chartre@Sun.COM (rv == -1 && errno != EINTR)) {
56110480SAlexandre.Chartre@Sun.COM /* child has exited or error */
56210480SAlexandre.Chartre@Sun.COM exit(1);
56310480SAlexandre.Chartre@Sun.COM }
56410480SAlexandre.Chartre@Sun.COM }
56510480SAlexandre.Chartre@Sun.COM }
56610480SAlexandre.Chartre@Sun.COM
56710480SAlexandre.Chartre@Sun.COM /*
56810480SAlexandre.Chartre@Sun.COM * Initialize child process
56910480SAlexandre.Chartre@Sun.COM */
57010480SAlexandre.Chartre@Sun.COM if (sighold(SIGUSR1) == -1) {
57110480SAlexandre.Chartre@Sun.COM LDMA_ERR("sighold error (%d)", errno);
57210480SAlexandre.Chartre@Sun.COM exit(1);
57310480SAlexandre.Chartre@Sun.COM }
57410480SAlexandre.Chartre@Sun.COM
57510480SAlexandre.Chartre@Sun.COM if (sigignore(SIGUSR1) == -1) {
57610480SAlexandre.Chartre@Sun.COM LDMA_ERR("sigignore error (%d)", errno);
57710480SAlexandre.Chartre@Sun.COM exit(1);
57810480SAlexandre.Chartre@Sun.COM }
57910480SAlexandre.Chartre@Sun.COM
58010480SAlexandre.Chartre@Sun.COM if (setsid() == -1) {
58110480SAlexandre.Chartre@Sun.COM LDMA_ERR("setsid error (%d)", errno);
58210480SAlexandre.Chartre@Sun.COM exit(1);
58310480SAlexandre.Chartre@Sun.COM }
58410480SAlexandre.Chartre@Sun.COM
58510480SAlexandre.Chartre@Sun.COM if (chdir("/") == -1) {
58610480SAlexandre.Chartre@Sun.COM LDMA_ERR("chdir error (%d)", errno);
58710480SAlexandre.Chartre@Sun.COM exit(1);
58810480SAlexandre.Chartre@Sun.COM }
58910480SAlexandre.Chartre@Sun.COM (void) umask(0);
59010480SAlexandre.Chartre@Sun.COM
59110480SAlexandre.Chartre@Sun.COM /*
59210480SAlexandre.Chartre@Sun.COM * Initialize file descriptors. Do not touch stderr
59310480SAlexandre.Chartre@Sun.COM * which is initialized by SMF to point to the daemon
59410480SAlexandre.Chartre@Sun.COM * specific log file.
59510480SAlexandre.Chartre@Sun.COM */
59610480SAlexandre.Chartre@Sun.COM (void) close(STDIN_FILENO);
59710480SAlexandre.Chartre@Sun.COM if (open("/dev/null", O_RDWR) == -1) {
59810480SAlexandre.Chartre@Sun.COM LDMA_ERR("open /dev/null error (%d)", errno);
59910480SAlexandre.Chartre@Sun.COM exit(1);
60010480SAlexandre.Chartre@Sun.COM }
60110480SAlexandre.Chartre@Sun.COM if (dup2(STDIN_FILENO, STDOUT_FILENO) == -1) {
60210480SAlexandre.Chartre@Sun.COM LDMA_ERR("dup2 error (%d)", errno);
60310480SAlexandre.Chartre@Sun.COM exit(1);
60410480SAlexandre.Chartre@Sun.COM }
60510480SAlexandre.Chartre@Sun.COM closefrom(STDERR_FILENO + 1);
60610480SAlexandre.Chartre@Sun.COM
60710480SAlexandre.Chartre@Sun.COM /* initialize logging */
60810480SAlexandre.Chartre@Sun.COM openlog(cmdname, LOG_CONS | LOG_NDELAY, LOG_DAEMON);
60910480SAlexandre.Chartre@Sun.COM
61010480SAlexandre.Chartre@Sun.COM ldma_daemon = B_TRUE;
61110480SAlexandre.Chartre@Sun.COM }
61210480SAlexandre.Chartre@Sun.COM
61310480SAlexandre.Chartre@Sun.COM /*
61410480SAlexandre.Chartre@Sun.COM * Register the agents. It would be easier to do this before
61510480SAlexandre.Chartre@Sun.COM * daemonizing so that any start error is directly reported. But
61610480SAlexandre.Chartre@Sun.COM * this can not be done because agents are registered using libds
61710480SAlexandre.Chartre@Sun.COM * and this will subscribe the daemon to some sysevents which is
61810480SAlexandre.Chartre@Sun.COM * a process based subscription. Instead we notify the parent process
61910480SAlexandre.Chartre@Sun.COM * either by exiting, or by sending a SIGUSR1 signal.
62010480SAlexandre.Chartre@Sun.COM */
62110480SAlexandre.Chartre@Sun.COM if (ldma_register_agents() == 0) {
62210480SAlexandre.Chartre@Sun.COM /* no agent registered */
62311029SAlexandre.Chartre@Sun.COM LDMA_ERR("Unable to register any agent");
62410480SAlexandre.Chartre@Sun.COM exit(1);
62510480SAlexandre.Chartre@Sun.COM }
62610480SAlexandre.Chartre@Sun.COM
62710480SAlexandre.Chartre@Sun.COM if (!standalone) {
62810480SAlexandre.Chartre@Sun.COM /* signal parent that startup was successful */
62910480SAlexandre.Chartre@Sun.COM if (kill(getppid(), SIGUSR1) == -1)
63010480SAlexandre.Chartre@Sun.COM exit(1);
63110480SAlexandre.Chartre@Sun.COM }
63210480SAlexandre.Chartre@Sun.COM }
63310480SAlexandre.Chartre@Sun.COM
63410480SAlexandre.Chartre@Sun.COM static void
ldma_usage()63510480SAlexandre.Chartre@Sun.COM ldma_usage()
63610480SAlexandre.Chartre@Sun.COM {
63710480SAlexandre.Chartre@Sun.COM (void) fprintf(stderr, "usage: %s\n", cmdname);
63810480SAlexandre.Chartre@Sun.COM }
63910480SAlexandre.Chartre@Sun.COM
64010480SAlexandre.Chartre@Sun.COM int
main(int argc,char * argv[])64110480SAlexandre.Chartre@Sun.COM main(int argc, char *argv[])
64210480SAlexandre.Chartre@Sun.COM {
64310480SAlexandre.Chartre@Sun.COM int opt;
64410480SAlexandre.Chartre@Sun.COM boolean_t standalone = B_FALSE;
64510480SAlexandre.Chartre@Sun.COM
64610480SAlexandre.Chartre@Sun.COM cmdname = basename(argv[0]);
64710480SAlexandre.Chartre@Sun.COM
64810480SAlexandre.Chartre@Sun.COM /* disable getopt error messages */
64910480SAlexandre.Chartre@Sun.COM opterr = 0;
65010480SAlexandre.Chartre@Sun.COM
65110480SAlexandre.Chartre@Sun.COM while ((opt = getopt(argc, argv, "ds")) != EOF) {
65210480SAlexandre.Chartre@Sun.COM
65310480SAlexandre.Chartre@Sun.COM switch (opt) {
65410480SAlexandre.Chartre@Sun.COM case 'd':
65510480SAlexandre.Chartre@Sun.COM ldma_debug = B_TRUE;
65610480SAlexandre.Chartre@Sun.COM break;
65710480SAlexandre.Chartre@Sun.COM case 's':
65810480SAlexandre.Chartre@Sun.COM standalone = B_TRUE;
65910480SAlexandre.Chartre@Sun.COM break;
66010480SAlexandre.Chartre@Sun.COM default:
66110480SAlexandre.Chartre@Sun.COM ldma_usage();
66210480SAlexandre.Chartre@Sun.COM exit(1);
66310480SAlexandre.Chartre@Sun.COM }
66410480SAlexandre.Chartre@Sun.COM }
66510480SAlexandre.Chartre@Sun.COM
66610480SAlexandre.Chartre@Sun.COM ldma_start(standalone);
66710480SAlexandre.Chartre@Sun.COM
66810480SAlexandre.Chartre@Sun.COM /*
66910480SAlexandre.Chartre@Sun.COM * Loop forever. Any incoming message will be received by libds and
67010480SAlexandre.Chartre@Sun.COM * forwarded to the agent data callback (ldma_data_cb()) where it
67110480SAlexandre.Chartre@Sun.COM * will be processed.
67210480SAlexandre.Chartre@Sun.COM */
67310480SAlexandre.Chartre@Sun.COM for (;;) {
67410480SAlexandre.Chartre@Sun.COM (void) pause();
67510480SAlexandre.Chartre@Sun.COM }
67610480SAlexandre.Chartre@Sun.COM
67710480SAlexandre.Chartre@Sun.COM /*NOTREACHED*/
67810480SAlexandre.Chartre@Sun.COM return (0);
67910480SAlexandre.Chartre@Sun.COM }
680