sckmdrv.c revision 193974072f41a843678abf5f61979c748687e66b
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Starcat IPSec Key Management Driver.
*
* This driver runs on a Starcat Domain. It processes requests received
* from the System Controller (SC) from IOSRAM, passes these requests
* sends corresponding status information back to the SC.
*
* Requests received from the SC consist of IPsec security associations
* (SAs) needed to secure the communication between SC and Domain daemons
* communicating using the Management Network (MAN).
*/
#include <sys/ddi_impldefs.h>
#include <sys/ndi_impldefs.h>
#include <sys/sckm_msg.h>
#ifdef DEBUG
#define SCKM_DEBUG0(f, s) if ((f)& sckm_debug_flags) \
#define SCKM_DEBUG1(f, s, a) if ((f)& sckm_debug_flags) \
#define SCKM_DEBUG2(f, s, a, b) if ((f)& sckm_debug_flags) \
#define SCKM_DEBUG3(f, s, a, b, c) if ((f)& sckm_debug_flags) \
#define SCKM_DEBUG4(f, s, a, b, c, d) if ((f)& sckm_debug_flags) \
#define SCKM_DEBUG5(f, s, a, b, c, d, e) if ((f)& sckm_debug_flags) \
#else
#define SCKM_DEBUG0(f, s)
#define SCKM_DEBUG1(f, s, a)
#define SCKM_DEBUG2(f, s, a, b)
#define SCKM_DEBUG3(f, s, a, b, c)
#define SCKM_DEBUG4(f, s, a, b, c, d)
#define SCKM_DEBUG5(f, s, a, b, c, d, e)
#define SCKM_DEBUG6(f, s, a, b, c, d, e, ff)
#endif /* DEBUG */
static struct cb_ops sckm_cb_ops = {
sckm_open, /* open */
sckm_close, /* close */
nodev, /* strategy */
nodev, /* print */
nodev, /* dump */
nodev, /* read */
nodev, /* write */
sckm_ioctl, /* ioctl */
nodev, /* devmap */
nodev, /* mmap */
nodev, /* segmap */
nochpoll, /* poll */
ddi_prop_op, /* prop_op */
0, /* streamtab */
};
DEVO_REV, /* devo_rev, */
0, /* refcnt */
sckm_info, /* get_dev_info */
nulldev, /* identify */
nulldev, /* probe */
sckm_attach, /* attach */
sckm_detach, /* detach */
nodev, /* reset */
&sckm_cb_ops, /* driver operations */
(struct bus_ops *)0, /* no bus operations */
NULL, /* power */
ddi_quiesce_not_needed, /* quiesce */
};
"Key Management Driver",
&sckm_ops,
};
static struct modlinkage modlinkage = {
&modldrv,
};
/*
* Private definitions.
*/
/*
* For processing mailbox layer events.
*/
static kmutex_t sckm_task_mutex;
static kmutex_t sckm_taskq_ptr_mutex;
/*
* For synchronization with key management daemon.
*/
static kmutex_t sckm_umutex;
/*
* Other misc private variables.
*/
/*
* Private functions prototypes.
*/
static void sckm_mbox_callback(void);
static void sckm_mbox_task(void *arg);
int
_init(void)
{
int ret;
/*
* Initialize outgoing mailbox (KDSC)
*/
"(%d)", ret);
return (ret);
}
/*
* Initialize incoming mailbox (SCKD)
*/
sckm_mbox_callback)) != 0) {
"(%d)\n", ret);
return (ret);
}
(void *)&timeout_range)) != 0) {
return (ret);
}
}
}
return (ret);
}
/*
* Initialize variables needed for synchronization with daemon.
*/
KM_SLEEP);
KM_SLEEP);
/* free what was successfully allocated */
/* uninitialize mailboxes, remove module, and return error */
return (-1);
}
/*
* Create mutex for task processing, protection of taskq
* pointer, and create taskq.
*/
return (ret);
}
int
_fini(void)
{
int ret;
return (ret);
}
/*
* Wait for scheduled tasks to complete, then destroy task queue.
*/
if (sckm_taskq != NULL) {
sckm_taskq = NULL;
}
/*
* Terminate incoming and outgoing IOSRAM mailboxes
*/
/*
* Destroy module synchronization objects and free memory
*/
}
}
}
return (ret);
}
int
{
}
static int
{
switch (cmd) {
case DDI_ATTACH:
return (DDI_FAILURE);
}
break;
case DDI_SUSPEND:
break;
default:
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
{
switch (cmd) {
case DDI_DETACH:
break;
case DDI_SUSPEND:
break;
default:
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/* ARGSUSED */
static int
void **result)
{
int rv;
switch (infocmd) {
case DDI_INFO_DEVT2DEVINFO:
rv = DDI_SUCCESS;
break;
case DDI_INFO_DEVT2INSTANCE:
*result = (void *)0;
rv = DDI_SUCCESS;
break;
default:
rv = DDI_FAILURE;
}
return (rv);
}
/*ARGSUSED*/
static int
{
/* check credentials of calling process */
return (EPERM);
}
/* enforce exclusive access */
if (sckm_oflag == B_TRUE) {
return (EBUSY);
}
sckm_oflag = B_TRUE;
return (0);
}
/*ARGSUSED*/
static int
{
return (0);
}
static int
int flag)
{
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32: {
sizeof (sckm_ioctl_getreq32_t), flag)) {
return (EFAULT);
}
break;
}
case DDI_MODEL_NONE: {
sizeof (sckm_ioctl_getreq_t), flag)) {
return (EFAULT);
}
break;
}
}
#else /* ! _MULTI_DATAMODEL */
sizeof (sckm_ioctl_getreq_t), flag)) {
return (EFAULT);
}
#endif /* _MULTI_DATAMODEL */
return (0);
}
static int
int flag)
{
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32: {
sizeof (sckm_ioctl_getreq32_t), flag)) {
return (EFAULT);
}
break;
}
case DDI_MODEL_NONE:
sizeof (sckm_ioctl_getreq_t), flag)) {
return (EFAULT);
}
break;
}
#else /* ! _MULTI_DATAMODEL */
sizeof (sckm_ioctl_getreq_t), flag)) {
return (EFAULT);
}
#endif /* _MULTI_DATAMODEL */
return (0);
}
/*ARGSUSED*/
static int
{
int rval = 0;
switch (cmd) {
case SCKM_IOCTL_GETREQ: {
return (EFAULT);
}
/* sanity check argument */
return (ENOSPC);
}
/* wait for request from SC */
while (!sckm_udata_req) {
return (EINTR);
}
}
return (EFAULT);
}
return (EFAULT);
}
break;
}
case SCKM_IOCTL_STATUS: {
sizeof (sckm_ioctl_status_t), flag)) {
return (EFAULT);
}
/* fail if no status is expected, or if it does not match */
return (EINVAL);
}
/* update status information for event handler */
/* signal event handler that request has been processed */
" that data has been processed");
break;
}
default:
}
return (rval);
}
/*
* sckm_mbox_callback
*
* Callback routine registered with the IOSRAM mailbox protocol driver.
* Invoked when a message is received on the mailbox.
*/
static void
sckm_mbox_callback(void)
{
if (sckm_taskq == NULL) {
return;
}
/*
* Too many tasks already pending. Do not queue a new
* request.
*/
}
}
/*
* sckm_mbox_task
*
* Dispatched on taskq from the IOSRAM mailbox callback
* sckm_mbox_callback when a message is received on the incoming
* mailbox.
*/
static void
sckm_mbox_task(void *ignored)
{
int rval;
return;
}
/*
* Get mailbox message.
*/
cmd = 0;
transid = 0;
"calling mboxsc_getmsg()\n");
if (rval != 0) {
"mboxsc_getmsg() failed (%d)\n", rval);
return;
}
"type=0x%x cmd=0x%x length=%d transid=0x%lx\n",
/* check message length */
if (length < sizeof (sckm_mbox_req_hdr_t)) {
/* protocol error, drop message */
"message of length %d, min %lu",
length, sizeof (sckm_mbox_req_hdr_t));
return;
}
/* check version of message received */
"version %d, expected %d",
/*
* Send reply with SCKM_SADB_ERR_VERSION error
* so that SC can adopt correct protocol version
* for this domain.
*/
if (rval != 0) {
"mboxsc_putmsg() failed (%d)\n", rval);
return;
}
}
/* process message */
}
/*
* sckm_process_msg
*
* Process a message received from the SC. Invoked by sckm_event_task().
*/
static void
{
int rv;
switch (cmd) {
case SCKM_MSG_SADB: {
int sadb_msglen;
/* sanity check request */
if (len-sizeof (sckm_mbox_req_hdr_t) <= 0) {
"zero length");
/*
* SADB message is too short, send corresponding
* error message to SC.
*/
rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT)) != 0) {
"mboxsc_putmsg() failed (%d)\n", rv);
}
return;
}
/* initialize request for daemon */
break;
}
default:
/*
* Received unknown command from SC. Send corresponding
* error message to SC.
*/
rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT)) != 0) {
"mboxsc_putmsg() failed (%d)\n", rv);
}
return;
}
/*
* At this point, we know that the request is valid, so pass
* the request to the daemon.
*/
/* wait for daemon to process request */
/*
* Daemon did not process the data, report this
* error to the SC.
*/
} else {
/* Daemon processed data, return status to SC */
switch (sckm_udata_status.status) {
case SCKM_IOCTL_STAT_SUCCESS:
break;
"error, errno=%d",
break;
case SCKM_IOCTL_STAT_ERR_REQ:
"bad request");
break;
"supported");
break;
"from key engine");
break;
"an error");
break;
"SADB message type");
break;
default:
}
}
/* send reply back to SC */
rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT)) != 0) {
} else {
}
}