49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre/*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * CDDL HEADER START
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre *
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * The contents of this file are subject to the terms of the
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Common Development and Distribution License (the "License").
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * You may not use this file except in compliance with the License.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre *
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * or http://www.opensolaris.org/os/licensing.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * See the License for the specific language governing permissions
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * and limitations under the License.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre *
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * When distributing Covered Code, include this CDDL HEADER in each
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * If applicable, add the following below this CDDL HEADER, with the
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * fields enclosed by brackets "[]" replaced with your own identifying
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * information: Portions Copyright [yyyy] [name of copyright owner]
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre *
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * CDDL HEADER END
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre/*
b63861bbdaea40d18f3f62a70cc3978d21a14013Alexandre Chartre * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre/*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Logical Domains (LDoms) Agents Daemon
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre *
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * The LDoms agents daemon (ldmad) runs on LDoms domains and provides
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * information to the control domain. It is composed of a set of agents
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * which can send and receive messages to and from the control domain.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Each agent is registered as a domain service using the libds library,
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * and is able to handle requests coming from the control domain.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre *
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * The control domain sends requests to an agent as messages on the
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * corresponding domain service (identified by the agent name). All requests
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * are received by the ldmad daemon which dispatches them to the appropriate
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * handler function of the agent depending on the type of the message.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre *
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * After the request has been processed by the handler, the ldmad daemon sent
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * a reply message back to the control domain. The reply is either a result
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * message if the request was successfully completed, or an error message
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * describing the failure.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include <dirent.h>
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include <errno.h>
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include <fcntl.h>
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include <libds.h>
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include <libgen.h>
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include <signal.h>
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include <stdio.h>
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include <stdlib.h>
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include <strings.h>
82629e3015252bf18319ba3815c773df23e21436Mike Christensen#include <synch.h>
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include <syslog.h>
82629e3015252bf18319ba3815c773df23e21436Mike Christensen#include <thread.h>
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include <unistd.h>
82629e3015252bf18319ba3815c773df23e21436Mike Christensen#include <sys/debug.h>
82629e3015252bf18319ba3815c773df23e21436Mike Christensen#include <sys/ldoms.h>
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include <sys/types.h>
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include <sys/stat.h>
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include <sys/wait.h>
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#include "ldma.h"
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#define LDMA_MODULE "ldm-agent-daemon"
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre#define LDMA_CONTROL_DOMAIN_DHDL 0 /* id of the control domain */
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensentypedef struct ldma_connexion_t {
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ds_hdl_t hdl; /* connexion handle */
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ds_domain_hdl_t dhdl; /* connexion domain handle */
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ds_ver_t ver; /* connexion version */
82629e3015252bf18319ba3815c773df23e21436Mike Christensen} ldma_connexion_t;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartretypedef struct ldma_agent {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_agent_info_t *info; /* agent information */
82629e3015252bf18319ba3815c773df23e21436Mike Christensen mutex_t conn_lock; /* connexion table lock */
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ldma_connexion_t conn[LDOMS_MAX_DOMAINS]; /* connexions */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre} ldma_agent_t;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre/* information about existing agents */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreextern ldma_agent_info_t ldma_device_info;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreextern ldma_agent_info_t ldma_system_info;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloroextern ldma_agent_info_t ldma_dio_info;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreboolean_t ldma_debug = B_FALSE;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreboolean_t ldma_daemon = B_FALSE;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartrestatic ldma_agent_info_t *ldma_agent_infos[] = {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre &ldma_device_info,
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre &ldma_system_info,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro &ldma_dio_info,
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre NULL
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre};
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartrestatic char *cmdname;
6b8303caf3c5c70ae1c1d362bf6de0c55eb622bbAlexandre Chartrestatic pid_t daemon_pid = 0;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
82629e3015252bf18319ba3815c773df23e21436Mike Christensen/*
82629e3015252bf18319ba3815c773df23e21436Mike Christensen * Lookup connexion in agent connexion table.
82629e3015252bf18319ba3815c773df23e21436Mike Christensen */
82629e3015252bf18319ba3815c773df23e21436Mike Christensenstatic ldma_connexion_t *
82629e3015252bf18319ba3815c773df23e21436Mike Christensenldma_connexion_lookup(ldma_agent_t *agent, ds_hdl_t hdl)
82629e3015252bf18319ba3815c773df23e21436Mike Christensen{
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ldma_connexion_t *connp;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen int i;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ASSERT(MUTEX_HELD(&agent->conn_lock));
82629e3015252bf18319ba3815c773df23e21436Mike Christensen for (connp = agent->conn, i = 0; i < LDOMS_MAX_DOMAINS; i++, connp++) {
82629e3015252bf18319ba3815c773df23e21436Mike Christensen if (connp->hdl == hdl)
82629e3015252bf18319ba3815c773df23e21436Mike Christensen return (connp);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen }
82629e3015252bf18319ba3815c773df23e21436Mike Christensen return (NULL);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen}
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensen/*
82629e3015252bf18319ba3815c773df23e21436Mike Christensen * Add connextion to agent connexion table.
82629e3015252bf18319ba3815c773df23e21436Mike Christensen */
82629e3015252bf18319ba3815c773df23e21436Mike Christensenstatic int
82629e3015252bf18319ba3815c773df23e21436Mike Christensenldma_connexion_add(ldma_agent_t *agent, ds_hdl_t hdl, ds_domain_hdl_t dhdl,
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ds_ver_t *verp)
82629e3015252bf18319ba3815c773df23e21436Mike Christensen{
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ldma_connexion_t *connp;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ldma_connexion_t *availp = NULL;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen int i;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensen (void) mutex_lock(&agent->conn_lock);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen for (connp = agent->conn, i = 0; i < LDOMS_MAX_DOMAINS; i++, connp++) {
82629e3015252bf18319ba3815c773df23e21436Mike Christensen if (connp->hdl == hdl)
82629e3015252bf18319ba3815c773df23e21436Mike Christensen break;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen if (availp == NULL && connp->hdl == DS_INVALID_HDL)
82629e3015252bf18319ba3815c773df23e21436Mike Christensen availp = connp;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen }
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensen if (i < LDOMS_MAX_DOMAINS) {
82629e3015252bf18319ba3815c773df23e21436Mike Christensen (void) mutex_unlock(&agent->conn_lock);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen LDMA_INFO("agent %s hdl %llx already exists", agent->info->name,
82629e3015252bf18319ba3815c773df23e21436Mike Christensen hdl);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen return (0);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen }
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensen if (!availp) {
82629e3015252bf18319ba3815c773df23e21436Mike Christensen (void) mutex_unlock(&agent->conn_lock);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen LDMA_INFO("agent %s too many connections", agent->info->name);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen return (0);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen }
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensen LDMA_DBG("agent %s adding connection (%x) %llx, %llx, %d.%d",
82629e3015252bf18319ba3815c773df23e21436Mike Christensen agent->info->name, availp, hdl, dhdl, verp->major, verp->minor);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensen availp->hdl = hdl;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen availp->dhdl = dhdl;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen availp->ver = *verp;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen (void) mutex_unlock(&agent->conn_lock);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen return (1);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen}
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensen/*
82629e3015252bf18319ba3815c773df23e21436Mike Christensen * Delete connexion from agent connexion table.
82629e3015252bf18319ba3815c773df23e21436Mike Christensen */
82629e3015252bf18319ba3815c773df23e21436Mike Christensenstatic int
82629e3015252bf18319ba3815c773df23e21436Mike Christensenldma_connexion_delete(ldma_agent_t *agent, ds_hdl_t hdl)
82629e3015252bf18319ba3815c773df23e21436Mike Christensen{
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ldma_connexion_t *connp;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensen (void) mutex_lock(&agent->conn_lock);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen if ((connp = ldma_connexion_lookup(agent, hdl)) == NULL) {
82629e3015252bf18319ba3815c773df23e21436Mike Christensen (void) mutex_unlock(&agent->conn_lock);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen LDMA_INFO("agent %s connection delete failed to find %llx",
82629e3015252bf18319ba3815c773df23e21436Mike Christensen agent->info->name, hdl);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen return (0);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen }
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensen LDMA_DBG("agent %s deleting connection (%x) %llx", agent->info->name,
82629e3015252bf18319ba3815c773df23e21436Mike Christensen connp, hdl);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensen connp->hdl = DS_INVALID_HDL;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen connp->dhdl = 0;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen connp->ver.major = 0;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen connp->ver.minor = 0;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen (void) mutex_unlock(&agent->conn_lock);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen return (1);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen}
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensen/*
82629e3015252bf18319ba3815c773df23e21436Mike Christensen * Initialize connexion table.
82629e3015252bf18319ba3815c773df23e21436Mike Christensen */
82629e3015252bf18319ba3815c773df23e21436Mike Christensenstatic void
82629e3015252bf18319ba3815c773df23e21436Mike Christensenldma_connexion_init(ldma_agent_t *agent)
82629e3015252bf18319ba3815c773df23e21436Mike Christensen{
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ldma_connexion_t *connp;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen int i;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensen for (connp = agent->conn, i = 0; i < LDOMS_MAX_DOMAINS; i++, connp++) {
82629e3015252bf18319ba3815c773df23e21436Mike Christensen connp->hdl = DS_INVALID_HDL;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen }
82629e3015252bf18319ba3815c773df23e21436Mike Christensen}
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre/*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Allocate a new message with the specified message number (msg_num),
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * message type (msg_type) and message data length (msg_dlen). Return
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * NULL if the allocation has failed.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartrestatic ldma_message_header_t *
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreldma_alloc_msg(uint64_t msg_num, uint32_t msg_type, size_t msg_dlen)
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre{
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_message_header_t *msg;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre size_t msg_len;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre msg_len = LDMA_MESSAGE_SIZE(msg_dlen);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre msg = malloc(msg_len);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (msg == NULL)
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre return (NULL);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre msg->msg_num = msg_num;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre msg->msg_type = msg_type;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre msg->msg_info = 0;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre return (msg);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre}
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre/*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Allocate a result message (LDMA_MSG_REQ_RESULT) with the specified message
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * data length (msg_dlen). If the request argument is not NULL then the message
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * is created with the same message number as the request, otherwise the message
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * number is set to 0. Return NULL if the allocation has failed.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreldma_message_header_t *
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreldma_alloc_result_msg(ldma_message_header_t *request, size_t msg_dlen)
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre{
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre uint64_t msg_num;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre msg_num = (request == NULL)? 0 : request->msg_num;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre return (ldma_alloc_msg(msg_num, LDMA_MSG_RESULT, msg_dlen));
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre}
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre/*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Agent register callback. This callback is invoked when a client is registered
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * for using the service provided by an agent. An agent will only have one
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * consumer which is coming from the control domain.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartrestatic void
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreldma_reg_cb(ds_hdl_t hdl, ds_cb_arg_t arg, ds_ver_t *ver,
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ds_domain_hdl_t dhdl)
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre{
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_agent_t *agent = (ldma_agent_t *)arg;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen char dname[LDOMS_MAX_NAME_LEN];
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
82629e3015252bf18319ba3815c773df23e21436Mike Christensen if (ds_dom_hdl_to_name(dhdl, dname, LDOMS_MAX_NAME_LEN) != 0) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre (void) strcpy(dname, "<unknown>");
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_DBG("%s: REGISTER hdl=%llx, dhdl=%llx (%s) ver=%hd.%hd",
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre agent->info->name, hdl, dhdl, dname, ver->major, ver->minor);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /*
82629e3015252bf18319ba3815c773df23e21436Mike Christensen * Record client information. Access control is done on a
82629e3015252bf18319ba3815c773df23e21436Mike Christensen * message-by-message basis upon receipt of the message.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
82629e3015252bf18319ba3815c773df23e21436Mike Christensen if (!ldma_connexion_add(agent, hdl, dhdl, ver)) {
82629e3015252bf18319ba3815c773df23e21436Mike Christensen LDMA_INFO("agent %s failed to add connection from "
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre "domain %s", agent->info->name, dname);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre}
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre/*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Agent unregister callback. This callback is invoked when a client is
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * unregistered and stops using the service provided by an agent.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartrestatic void
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreldma_unreg_cb(ds_hdl_t hdl, ds_cb_arg_t arg)
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre{
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_agent_t *agent = (ldma_agent_t *)arg;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_DBG("%s: UNREGISTER hdl=%llx", agent->info->name, hdl);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
82629e3015252bf18319ba3815c773df23e21436Mike Christensen if (!ldma_connexion_delete(agent, hdl)) {
82629e3015252bf18319ba3815c773df23e21436Mike Christensen LDMA_INFO("agent %s failed to unregister handle %llx",
82629e3015252bf18319ba3815c773df23e21436Mike Christensen agent->info->name, hdl);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre}
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre/*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Agent data callback. This callback is invoked when an agent receives a new
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * message from a client. Any request from a client which is not the control
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * domain is immediatly rejected. Otherwise the message is forwarded to the
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * appropriate handler function provided by the agent, depending on the message
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * type.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartrestatic void
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreldma_data_cb(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf, size_t len)
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre{
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_agent_t *agent = (ldma_agent_t *)arg;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_msg_handler_t *handler;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_message_header_t *request = buf;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_message_header_t *reply = NULL;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ldma_connexion_t *connp;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ds_ver_t conn_ver;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ds_domain_hdl_t conn_dhdl;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_request_status_t status;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre size_t request_dlen, reply_len, reply_dlen = 0;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre int i;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /* check the message size */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (len < LDMA_MESSAGE_HEADER_SIZE) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_INFO("agent %s has ignored message with an invalid "
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre "size of %d bytes", agent->info->name, len);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre return;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre request_dlen = LDMA_MESSAGE_DLEN(len);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_DBG("%s: DATA hdl=%llx, request num=%llu type=0x%x info=0x%x "
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre "dlen=%d", agent->info->name, hdl, request->msg_num,
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre request->msg_type, request->msg_info, request_dlen);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
82629e3015252bf18319ba3815c773df23e21436Mike Christensen (void) mutex_lock(&agent->conn_lock);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen connp = ldma_connexion_lookup(agent, hdl);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen if (connp != NULL) {
82629e3015252bf18319ba3815c773df23e21436Mike Christensen conn_dhdl = connp->dhdl;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen conn_ver = connp->ver;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen }
82629e3015252bf18319ba3815c773df23e21436Mike Christensen (void) mutex_unlock(&agent->conn_lock);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
82629e3015252bf18319ba3815c773df23e21436Mike Christensen /* reject any request which is not in the connexion table */
82629e3015252bf18319ba3815c773df23e21436Mike Christensen if (connp == NULL) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_DBG("%s: DATA hdl=%llx, rejecting request from a "
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre "distrusted domain", agent->info->name, hdl);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre status = LDMA_REQ_DENIED;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre goto do_reply;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre handler = NULL;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre for (i = 0; i < agent->info->nhandlers; i++) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (agent->info->handlers[i].msg_type == request->msg_type) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre handler = &agent->info->handlers[i];
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre break;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (handler == NULL) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /* this type of message is not defined by the agent */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_DBG("%s: DATA hdl=%llx, unknown message type %x",
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre agent->info->name, hdl, request->msg_type);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre status = LDMA_REQ_NOTSUP;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre goto do_reply;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
82629e3015252bf18319ba3815c773df23e21436Mike Christensen /* reject any request from a guest which is not allowed */
82629e3015252bf18319ba3815c773df23e21436Mike Christensen if ((conn_dhdl != LDMA_CONTROL_DOMAIN_DHDL) &&
82629e3015252bf18319ba3815c773df23e21436Mike Christensen (handler->msg_flags & LDMA_MSGFLG_ACCESS_ANY) == 0) {
82629e3015252bf18319ba3815c773df23e21436Mike Christensen LDMA_DBG("%s: DATA hdl=%llx, rejecting request from a "
82629e3015252bf18319ba3815c773df23e21436Mike Christensen "distrusted domain", agent->info->name, hdl);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen status = LDMA_REQ_DENIED;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen goto do_reply;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen }
82629e3015252bf18319ba3815c773df23e21436Mike Christensen
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (handler->msg_handler == NULL) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * This type of message is defined by the agent but it
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * has no handler. That means there is no processing to
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * do, the message is just ignored, but the request is
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * successfully completed.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_DBG("%s: DATA hdl=%llx, no handler",
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre agent->info->name, hdl);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre status = LDMA_REQ_COMPLETED;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre goto do_reply;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /* invoke the message handler of the agent */
82629e3015252bf18319ba3815c773df23e21436Mike Christensen status = (*handler->msg_handler)(&conn_ver, request, request_dlen,
82629e3015252bf18319ba3815c773df23e21436Mike Christensen &reply, &reply_dlen);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_DBG("%s: DATA hdl=%llx, handler stat=%d reply=%p rlen=%d",
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre agent->info->name, hdl, status, (void *)reply, reply_dlen);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartredo_reply:
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * If the handler has provided a reply message, we use it directly.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Otherwise, we build a reply depending on the status of the request.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * In that case, we re-use the request buffer to build the reply
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * message.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (reply == NULL) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre reply = request;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre reply_dlen = 0;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (status == LDMA_REQ_COMPLETED) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * The request was successful but no result message was
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * provided so we send an empty result message.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre reply->msg_type = LDMA_MSG_RESULT;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre reply->msg_info = 0;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre } else {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * The request has failed but no error message was
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * provided so we send an error message based on the
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * request status.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre reply->msg_type = LDMA_MSG_ERROR;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre reply->msg_info =
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre (status == LDMA_REQ_NOTSUP)? LDMA_MSGERR_NOTSUP :
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre (status == LDMA_REQ_INVALID)? LDMA_MSGERR_INVALID :
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre (status == LDMA_REQ_DENIED)? LDMA_MSGERR_DENY :
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_MSGERR_FAIL;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre reply_len = LDMA_MESSAGE_SIZE(reply_dlen);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_DBG("%s: DATA hdl=%llx, reply num=%llu type=0x%x info=0x%x "
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre "dlen=%d", agent->info->name, hdl, reply->msg_num,
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre reply->msg_type, reply->msg_info, reply_dlen);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (ds_send_msg(hdl, reply, reply_len) != 0) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_ERR("agent %s has failed to send reply for request %llu",
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre agent->info->name, request->msg_num);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (reply != request)
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre free(reply);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre}
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre/*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Register an agent. Return 0 if the agent was successfully registered.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartrestatic int
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreldma_register(ldma_agent_info_t *agent_info)
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre{
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_agent_t *agent;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ds_capability_t ds_cap;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ds_ops_t ds_ops;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre agent = malloc(sizeof (ldma_agent_t));
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (agent == NULL)
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre goto register_fail;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre agent->info = agent_info;
82629e3015252bf18319ba3815c773df23e21436Mike Christensen (void) mutex_init(&agent->conn_lock, USYNC_THREAD, NULL);
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ldma_connexion_init(agent);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ds_cap.svc_id = agent_info->name;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ds_cap.vers = agent_info->vers;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ds_cap.nvers = agent_info->nvers;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ds_ops.ds_reg_cb = ldma_reg_cb;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ds_ops.ds_unreg_cb = ldma_unreg_cb;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ds_ops.ds_data_cb = ldma_data_cb;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ds_ops.cb_arg = agent;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (ds_svc_reg(&ds_cap, &ds_ops) == 0) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_INFO("agent %s registered", agent_info->name);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre return (0);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreregister_fail:
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_ERR("agent %s has failed to register", agent_info->name);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre free(agent);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre return (-1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre}
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre/*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Register all known agents. Return the number of agents successfully
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * registered.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartrestatic int
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreldma_register_agents()
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre{
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre int count = 0;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_agent_info_t **agent_infop;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre for (agent_infop = ldma_agent_infos;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre *agent_infop != NULL; agent_infop++) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (ldma_register(*agent_infop) == 0)
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre count++;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre return (count);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre}
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre/*ARGSUSED*/
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartrestatic void
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreldma_sigusr_handler(int sig, siginfo_t *sinfo, void *ucontext)
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre{
6b8303caf3c5c70ae1c1d362bf6de0c55eb622bbAlexandre Chartre /*
6b8303caf3c5c70ae1c1d362bf6de0c55eb622bbAlexandre Chartre * The child process can send the signal before the fork()
6b8303caf3c5c70ae1c1d362bf6de0c55eb622bbAlexandre Chartre * call has returned in the parent process. So daemon_pid
6b8303caf3c5c70ae1c1d362bf6de0c55eb622bbAlexandre Chartre * may not be set yet, and we don't check the pid in that
6b8303caf3c5c70ae1c1d362bf6de0c55eb622bbAlexandre Chartre * case.
6b8303caf3c5c70ae1c1d362bf6de0c55eb622bbAlexandre Chartre */
6b8303caf3c5c70ae1c1d362bf6de0c55eb622bbAlexandre Chartre if (sig != SIGUSR1 || sinfo->si_code != SI_USER ||
6b8303caf3c5c70ae1c1d362bf6de0c55eb622bbAlexandre Chartre (daemon_pid > 0 && sinfo->si_pid != daemon_pid))
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre return;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * The parent process has received a USR1 signal from the child.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * This means that the daemon has correctly started and the parent
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * can exit.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(0);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre}
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartrestatic void
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreldma_start(boolean_t standalone)
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre{
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre int stat, rv;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre struct sigaction action;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (!standalone) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Some configuration of the daemon has to be done in the
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * child, but we want the parent to report if the daemon
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * has successfully started or not. So we setup a signal
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * handler, and the child will notify the parent using the
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * USR1 signal if the setup was successful. Otherwise the
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * child will exit.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre action.sa_sigaction = ldma_sigusr_handler;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre action.sa_flags = SA_SIGINFO;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (sigemptyset(&action.sa_mask) == -1) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_ERR("sigemptyset error (%d)", errno);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (sigaction(SIGUSR1, &action, NULL) == -1) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_ERR("sigaction() error (%d)", errno);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (sigrelse(SIGUSR1) == -1) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_ERR("sigrelse() error (%d)", errno);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if ((daemon_pid = fork()) == -1) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_ERR("fork() error (%d)", errno);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (daemon_pid != 0) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * The parent process waits until the child exits (in
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * case of an error) or sends a USR1 signal (if the
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * daemon has correctly started).
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre for (;;) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre rv = waitpid(daemon_pid, &stat, 0);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if ((rv == daemon_pid && WIFEXITED(stat)) ||
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre (rv == -1 && errno != EINTR)) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /* child has exited or error */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Initialize child process
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (sighold(SIGUSR1) == -1) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_ERR("sighold error (%d)", errno);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (sigignore(SIGUSR1) == -1) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_ERR("sigignore error (%d)", errno);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (setsid() == -1) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_ERR("setsid error (%d)", errno);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (chdir("/") == -1) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_ERR("chdir error (%d)", errno);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre (void) umask(0);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Initialize file descriptors. Do not touch stderr
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * which is initialized by SMF to point to the daemon
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * specific log file.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre (void) close(STDIN_FILENO);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (open("/dev/null", O_RDWR) == -1) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_ERR("open /dev/null error (%d)", errno);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (dup2(STDIN_FILENO, STDOUT_FILENO) == -1) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre LDMA_ERR("dup2 error (%d)", errno);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre closefrom(STDERR_FILENO + 1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /* initialize logging */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre openlog(cmdname, LOG_CONS | LOG_NDELAY, LOG_DAEMON);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_daemon = B_TRUE;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Register the agents. It would be easier to do this before
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * daemonizing so that any start error is directly reported. But
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * this can not be done because agents are registered using libds
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * and this will subscribe the daemon to some sysevents which is
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * a process based subscription. Instead we notify the parent process
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * either by exiting, or by sending a SIGUSR1 signal.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (ldma_register_agents() == 0) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /* no agent registered */
6b8303caf3c5c70ae1c1d362bf6de0c55eb622bbAlexandre Chartre LDMA_ERR("Unable to register any agent");
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (!standalone) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /* signal parent that startup was successful */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre if (kill(getppid(), SIGUSR1) == -1)
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre}
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartrestatic void
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreldma_usage()
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre{
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre (void) fprintf(stderr, "usage: %s\n", cmdname);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre}
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartreint
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartremain(int argc, char *argv[])
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre{
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre int opt;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre boolean_t standalone = B_FALSE;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre cmdname = basename(argv[0]);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /* disable getopt error messages */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre opterr = 0;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre while ((opt = getopt(argc, argv, "ds")) != EOF) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre switch (opt) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre case 'd':
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_debug = B_TRUE;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre break;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre case 's':
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre standalone = B_TRUE;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre break;
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre default:
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_usage();
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre exit(1);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre ldma_start(standalone);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /*
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * Loop forever. Any incoming message will be received by libds and
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * forwarded to the agent data callback (ldma_data_cb()) where it
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre * will be processed.
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre */
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre for (;;) {
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre (void) pause();
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre }
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre /*NOTREACHED*/
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre return (0);
49bfb42b00abac0958a1308f4233e366fd083366Alexandre Chartre}