diff options
| author | Mike Christensen <Michael.Christensen@Sun.COM> | 2010-03-01 18:02:46 -0800 |
|---|---|---|
| committer | Mike Christensen <Michael.Christensen@Sun.COM> | 2010-03-01 18:02:46 -0800 |
| commit | 82629e3015252bf18319ba3815c773df23e21436 (patch) | |
| tree | babd90f2440f44cae78e40aef052d2760e973ca9 /usr/src/cmd/ldmad/ldmad.c | |
| parent | d78a6b7e13de1e122f6c7e0d539522698d83ec22 (diff) | |
| download | illumos-joyent-82629e3015252bf18319ba3815c773df23e21436.tar.gz | |
PSARC 2010/004 Logical Domains Information API and ldminfo
FWARC 2009/680 Domain UUID property
FWARC 2010/058 Logical Domains Agent Chassis Serial Number Message
6680702 RFE: Want a mechanism for Solaris to know if it is an LDOM and if so what type
6873151 RFE: unique ID for LDOMs to facillitate asset tracking
6712763 RFE: Need information about control domain from within a guest domain
Diffstat (limited to 'usr/src/cmd/ldmad/ldmad.c')
| -rw-r--r-- | usr/src/cmd/ldmad/ldmad.c | 178 |
1 files changed, 147 insertions, 31 deletions
diff --git a/usr/src/cmd/ldmad/ldmad.c b/usr/src/cmd/ldmad/ldmad.c index b5d5247538..0eabe5385d 100644 --- a/usr/src/cmd/ldmad/ldmad.c +++ b/usr/src/cmd/ldmad/ldmad.c @@ -55,8 +55,12 @@ #include <stdio.h> #include <stdlib.h> #include <strings.h> +#include <synch.h> #include <syslog.h> +#include <thread.h> #include <unistd.h> +#include <sys/debug.h> +#include <sys/ldoms.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/wait.h> @@ -66,12 +70,17 @@ #define LDMA_MODULE "ldm-agent-daemon" #define LDMA_CONTROL_DOMAIN_DHDL 0 /* id of the control domain */ -#define LDMA_DOMAIN_NAME_MAXLEN MAXNAMELEN + +typedef struct ldma_connexion_t { + ds_hdl_t hdl; /* connexion handle */ + ds_domain_hdl_t dhdl; /* connexion domain handle */ + ds_ver_t ver; /* connexion version */ +} ldma_connexion_t; typedef struct ldma_agent { ldma_agent_info_t *info; /* agent information */ - ds_hdl_t conn_hdl; /* connexion handler */ - ds_ver_t conn_ver; /* connexion version */ + mutex_t conn_lock; /* connexion table lock */ + ldma_connexion_t conn[LDOMS_MAX_DOMAINS]; /* connexions */ } ldma_agent_t; /* information about existing agents */ @@ -93,6 +102,106 @@ static char *cmdname; static pid_t daemon_pid = 0; /* + * Lookup connexion in agent connexion table. + */ +static ldma_connexion_t * +ldma_connexion_lookup(ldma_agent_t *agent, ds_hdl_t hdl) +{ + ldma_connexion_t *connp; + int i; + + ASSERT(MUTEX_HELD(&agent->conn_lock)); + for (connp = agent->conn, i = 0; i < LDOMS_MAX_DOMAINS; i++, connp++) { + if (connp->hdl == hdl) + return (connp); + } + return (NULL); +} + +/* + * Add connextion to agent connexion table. + */ +static int +ldma_connexion_add(ldma_agent_t *agent, ds_hdl_t hdl, ds_domain_hdl_t dhdl, + ds_ver_t *verp) +{ + ldma_connexion_t *connp; + ldma_connexion_t *availp = NULL; + int i; + + (void) mutex_lock(&agent->conn_lock); + for (connp = agent->conn, i = 0; i < LDOMS_MAX_DOMAINS; i++, connp++) { + if (connp->hdl == hdl) + break; + if (availp == NULL && connp->hdl == DS_INVALID_HDL) + availp = connp; + } + + if (i < LDOMS_MAX_DOMAINS) { + (void) mutex_unlock(&agent->conn_lock); + LDMA_INFO("agent %s hdl %llx already exists", agent->info->name, + hdl); + return (0); + } + + if (!availp) { + (void) mutex_unlock(&agent->conn_lock); + LDMA_INFO("agent %s too many connections", agent->info->name); + return (0); + } + + LDMA_DBG("agent %s adding connection (%x) %llx, %llx, %d.%d", + agent->info->name, availp, hdl, dhdl, verp->major, verp->minor); + + availp->hdl = hdl; + availp->dhdl = dhdl; + availp->ver = *verp; + (void) mutex_unlock(&agent->conn_lock); + return (1); +} + +/* + * Delete connexion from agent connexion table. + */ +static int +ldma_connexion_delete(ldma_agent_t *agent, ds_hdl_t hdl) +{ + ldma_connexion_t *connp; + + (void) mutex_lock(&agent->conn_lock); + if ((connp = ldma_connexion_lookup(agent, hdl)) == NULL) { + (void) mutex_unlock(&agent->conn_lock); + LDMA_INFO("agent %s connection delete failed to find %llx", + agent->info->name, hdl); + return (0); + } + + LDMA_DBG("agent %s deleting connection (%x) %llx", agent->info->name, + connp, hdl); + + connp->hdl = DS_INVALID_HDL; + connp->dhdl = 0; + connp->ver.major = 0; + connp->ver.minor = 0; + (void) mutex_unlock(&agent->conn_lock); + return (1); +} + +/* + * Initialize connexion table. + */ +static void +ldma_connexion_init(ldma_agent_t *agent) +{ + ldma_connexion_t *connp; + int i; + + for (connp = agent->conn, i = 0; i < LDOMS_MAX_DOMAINS; i++, connp++) { + connp->hdl = DS_INVALID_HDL; + } +} + +/* * Allocate a new message with the specified message number (msg_num), * message type (msg_type) and message data length (msg_dlen). Return * NULL if the allocation has failed. @@ -141,9 +250,9 @@ ldma_reg_cb(ds_hdl_t hdl, ds_cb_arg_t arg, ds_ver_t *ver, ds_domain_hdl_t dhdl) { ldma_agent_t *agent = (ldma_agent_t *)arg; - char dname[LDMA_DOMAIN_NAME_MAXLEN]; + char dname[LDOMS_MAX_NAME_LEN]; - if (ds_dom_hdl_to_name(dhdl, dname, LDMA_DOMAIN_NAME_MAXLEN) != 0) { + if (ds_dom_hdl_to_name(dhdl, dname, LDOMS_MAX_NAME_LEN) != 0) { (void) strcpy(dname, "<unknown>"); } @@ -151,19 +260,11 @@ ldma_reg_cb(ds_hdl_t hdl, ds_cb_arg_t arg, ds_ver_t *ver, agent->info->name, hdl, dhdl, dname, ver->major, ver->minor); /* - * Record client information if the connexion is from the control - * domain. The domain service framework only allows connexion of a - * domain with the control domain. However, if the agent is running - * on the control domain then it can see connexions coming from any - * domains. That's why we explicitly have to check if the connexion - * is effectively with the control domain. + * Record client information. Access control is done on a + * message-by-message basis upon receipt of the message. */ - if (dhdl == LDMA_CONTROL_DOMAIN_DHDL) { - agent->conn_hdl = hdl; - agent->conn_ver.major = ver->major; - agent->conn_ver.minor = ver->minor; - } else { - LDMA_INFO("agent %s will ignore any request from distrusted " + if (!ldma_connexion_add(agent, hdl, dhdl, ver)) { + LDMA_INFO("agent %s failed to add connection from " "domain %s", agent->info->name, dname); } } @@ -179,13 +280,9 @@ ldma_unreg_cb(ds_hdl_t hdl, ds_cb_arg_t arg) LDMA_DBG("%s: UNREGISTER hdl=%llx", agent->info->name, hdl); - if (agent->conn_hdl == hdl) { - agent->conn_hdl = 0; - agent->conn_ver.major = 0; - agent->conn_ver.minor = 0; - } else { - LDMA_INFO("agent %s has unregistered consumer from " - "distrusted domain", agent->info->name); + if (!ldma_connexion_delete(agent, hdl)) { + LDMA_INFO("agent %s failed to unregister handle %llx", + agent->info->name, hdl); } } @@ -203,6 +300,9 @@ ldma_data_cb(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf, size_t len) ldma_msg_handler_t *handler; ldma_message_header_t *request = buf; ldma_message_header_t *reply = NULL; + ldma_connexion_t *connp; + ds_ver_t conn_ver; + ds_domain_hdl_t conn_dhdl; ldma_request_status_t status; size_t request_dlen, reply_len, reply_dlen = 0; int i; @@ -220,8 +320,16 @@ ldma_data_cb(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf, size_t len) "dlen=%d", agent->info->name, hdl, request->msg_num, request->msg_type, request->msg_info, request_dlen); - /* reject any request which is not from the control domain */ - if (hdl != agent->conn_hdl) { + (void) mutex_lock(&agent->conn_lock); + connp = ldma_connexion_lookup(agent, hdl); + if (connp != NULL) { + conn_dhdl = connp->dhdl; + conn_ver = connp->ver; + } + (void) mutex_unlock(&agent->conn_lock); + + /* reject any request which is not in the connexion table */ + if (connp == NULL) { LDMA_DBG("%s: DATA hdl=%llx, rejecting request from a " "distrusted domain", agent->info->name, hdl); status = LDMA_REQ_DENIED; @@ -245,6 +353,15 @@ ldma_data_cb(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf, size_t len) goto do_reply; } + /* reject any request from a guest which is not allowed */ + if ((conn_dhdl != LDMA_CONTROL_DOMAIN_DHDL) && + (handler->msg_flags & LDMA_MSGFLG_ACCESS_ANY) == 0) { + LDMA_DBG("%s: DATA hdl=%llx, rejecting request from a " + "distrusted domain", agent->info->name, hdl); + status = LDMA_REQ_DENIED; + goto do_reply; + } + if (handler->msg_handler == NULL) { /* * This type of message is defined by the agent but it @@ -259,8 +376,8 @@ ldma_data_cb(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf, size_t len) } /* invoke the message handler of the agent */ - status = (*handler->msg_handler)(&agent->conn_ver, request, - request_dlen, &reply, &reply_dlen); + status = (*handler->msg_handler)(&conn_ver, request, request_dlen, + &reply, &reply_dlen); LDMA_DBG("%s: DATA hdl=%llx, handler stat=%d reply=%p rlen=%d", agent->info->name, hdl, status, (void *)reply, reply_dlen); @@ -330,9 +447,8 @@ ldma_register(ldma_agent_info_t *agent_info) goto register_fail; agent->info = agent_info; - agent->conn_hdl = 0; - agent->conn_ver.major = 0; - agent->conn_ver.minor = 0; + (void) mutex_init(&agent->conn_lock, USYNC_THREAD, NULL); + ldma_connexion_init(agent); ds_cap.svc_id = agent_info->name; ds_cap.vers = agent_info->vers; |
