sckmdrv.c revision 07d06da50d310a325b457d6330165aebab1e0064
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Common Development and Distribution License (the "License").
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You may not use this file except in compliance with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Starcat IPSec Key Management Driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This driver runs on a Starcat Domain. It processes requests received
03831d35f7499c87d51205817c93e9a8d42c4baestevel * from the System Controller (SC) from IOSRAM, passes these requests
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to the sckmd daemon by means of an open/close/ioctl interface, and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sends corresponding status information back to the SC.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Requests received from the SC consist of IPsec security associations
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (SAs) needed to secure the communication between SC and Domain daemons
03831d35f7499c87d51205817c93e9a8d42c4baestevel * communicating using the Management Network (MAN).
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCKM_DEBUG0(f, s) if ((f)& sckm_debug_flags) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCKM_DEBUG1(f, s, a) if ((f)& sckm_debug_flags) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCKM_DEBUG2(f, s, a, b) if ((f)& sckm_debug_flags) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCKM_DEBUG3(f, s, a, b, c) if ((f)& sckm_debug_flags) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCKM_DEBUG4(f, s, a, b, c, d) if ((f)& sckm_debug_flags) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCKM_DEBUG5(f, s, a, b, c, d, e) if ((f)& sckm_debug_flags) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCKM_DEBUG6(f, s, a, b, c, d, e, ff) if ((f)& sckm_debug_flags) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCKM_DEBUG1(f, s, a)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCKM_DEBUG2(f, s, a, b)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCKM_DEBUG3(f, s, a, b, c)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCKM_DEBUG4(f, s, a, b, c, d)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCKM_DEBUG5(f, s, a, b, c, d, e)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define D_TASK 0x00100000 /* mailbox task processing */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sckm_open(dev_t *, int, int, struct cred *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sckm_close(dev_t, int, int, struct cred *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sckm_ioctl(dev_t, int, intptr_t, int, struct cred *, int *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* streamtab */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sckm_attach(dev_info_t *, ddi_attach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sckm_detach(dev_info_t *, ddi_detach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sckm_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* refcnt */
193974072f41a843678abf5f61979c748687e66bSherry Moore "Key Management Driver",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Private definitions.
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCKM_DAEMON_TIMEOUT 4000000 /* in microseconds */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCKM_NUM_TASKQ 2 /* # of task queue entries */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For processing mailbox layer events.
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic clock_t sckm_getmsg_timeout = SCKM_DEF_GETMSG_TIMEOUT*1000;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For synchronization with key management daemon.
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kcondvar_t sckm_udata_cv; /* daemon waits on data */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kcondvar_t sckm_cons_cv; /* wait for daemon to consume data */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic boolean_t sckm_udata_req = B_FALSE; /* data available for daemon */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sckm_ioctl_getreq_t sckm_udata; /* request for daemon */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sckm_ioctl_status_t sckm_udata_status; /* status from daemon */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Other misc private variables.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Private functions prototypes.
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void sckm_mbox_callback(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void sckm_process_msg(uint32_t cmd, uint64_t transid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize outgoing mailbox (KDSC)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((ret = mboxsc_init(KEY_KDSC, MBOXSC_MBOX_OUT, NULL)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed initializing outgoing mailbox "
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize incoming mailbox (SCKD)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed initializing incoming mailbox "
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((ret = mboxsc_ctrl(KEY_SCKD, MBOXSC_CMD_GETMSG_TIMEOUT_RANGE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)&timeout_range)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sckm_getmsg_timeout < timeout_range.min_timeout) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sckm_getmsg_timeout > timeout_range.max_timeout) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize variables needed for synchronization with daemon.
03831d35f7499c87d51205817c93e9a8d42c4baestevel sckm_udata.buf = kmem_alloc(SCKM_SCKD_MAXDATA, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel req_data = (sckm_mbox_req_hdr_t *)kmem_alloc(SCKM_SCKD_MAXDATA,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rep_data = (sckm_mbox_rep_hdr_t *)kmem_alloc(SCKM_KDSC_MAXDATA,
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((sckm_udata.buf == NULL) || (req_data == NULL) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* free what was successfully allocated */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* uninitialize mailboxes, remove module, and return error */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create mutex for task processing, protection of taskq
03831d35f7499c87d51205817c93e9a8d42c4baestevel * pointer, and create taskq.
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&sckm_task_mutex, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&sckm_taskq_ptr_mutex, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sckm_taskq = taskq_create("sckm_taskq", 1, minclsyspri,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Wait for scheduled tasks to complete, then destroy task queue.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Terminate incoming and outgoing IOSRAM mailboxes
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Destroy module synchronization objects and free memory
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCKM_DEBUG1(D_ATTACH, "in sckm_attach, cmd=%d", cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCKM_DEBUG0(D_ATTACH, "out sckm_attach (DDI_SUCCESS)");
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCKM_DEBUG1(D_ATTACH, "in sckm_detach, cmd=%d", cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCKM_DEBUG0(D_ATTACH, "out sckm_detach (DDI_SUCCESS)");
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelsckm_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCKM_DEBUG1(D_ATTACH, "in sckm_info, infocmd=%d", infocmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *result = (void *)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelsckm_open(dev_t *devp, int flag, int otyp, struct cred *cred)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* check credentials of calling process */
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCKM_DEBUG0(D_OPEN, "sckm_open: attempt by non-root proc");
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* enforce exclusive access */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelsckm_close(dev_t dev, int flag, int otyp, struct cred *cred)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevelsckm_copyin_ioctl_getreq(intptr_t userarg, sckm_ioctl_getreq_t *driverarg,
03831d35f7499c87d51205817c93e9a8d42c4baestevel driverarg->buf = (caddr_t)(uintptr_t)driverarg32.buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else /* ! _MULTI_DATAMODEL */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* _MULTI_DATAMODEL */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevelsckm_copyout_ioctl_getreq(sckm_ioctl_getreq_t *driverarg, intptr_t userarg,
03831d35f7499c87d51205817c93e9a8d42c4baestevel driverarg32.buf = (caddr32_t)(uintptr_t)driverarg->buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else /* ! _MULTI_DATAMODEL */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* _MULTI_DATAMODEL */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelsckm_ioctl(dev_t dev, int cmd, intptr_t data, int flag,
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: got SCKM_IOCTL_GETREQ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* sanity check argument */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* wait for request from SC */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cv_wait_sig(&sckm_udata_cv, &sckm_umutex) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: got SCKM_IOCTL_STATUS");
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCKM_DEBUG3(D_IOCTL, "sckm_ioctl: arg transid=0x%lx, "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "status=%d, sadb_msg_errno=%d", arg.transid, arg.status,
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* fail if no status is expected, or if it does not match */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!sckm_udata_req || sckm_udata.transid != arg.transid) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* update status information for event handler */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(&arg, &sckm_udata_status, sizeof (sckm_ioctl_status_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* signal event handler that request has been processed */
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: signaling event handler"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " that data has been processed");
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCKM_DEBUG1(D_IOCTL, "out sckm_ioctl, rval=%d", rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sckm_mbox_callback
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Callback routine registered with the IOSRAM mailbox protocol driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Invoked when a message is received on the mailbox.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!taskq_dispatch(sckm_taskq, sckm_mbox_task, NULL, KM_NOSLEEP)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Too many tasks already pending. Do not queue a new
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sckm_mbox_task
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Dispatched on taskq from the IOSRAM mailbox callback
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sckm_mbox_callback when a message is received on the incoming
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get mailbox message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel "calling mboxsc_getmsg()\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval = mboxsc_getmsg(KEY_SCKD, &type, &cmd, &transid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "type=0x%x cmd=0x%x length=%d transid=0x%lx\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* check message length */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* protocol error, drop message */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "message of length %d, min %lu",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* check version of message received */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (req_data->sckm_version != SCKM_PROTOCOL_VERSION) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "version %d, expected %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send reply with SCKM_SADB_ERR_VERSION error
03831d35f7499c87d51205817c93e9a8d42c4baestevel * so that SC can adopt correct protocol version
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for this domain.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* process message */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sckm_process_msg
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Process a message received from the SC. Invoked by sckm_event_task().
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* sanity check request */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "zero length");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SADB message is too short, send corresponding
03831d35f7499c87d51205817c93e9a8d42c4baestevel * error message to SC.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* initialize request for daemon */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sckm_udata.buf_len = len-sizeof (sckm_mbox_req_hdr_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(req_data+1, sckm_udata.buf, sckm_udata.buf_len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "unknown cmd %x received from SC", cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Received unknown command from SC. Send corresponding
03831d35f7499c87d51205817c93e9a8d42c4baestevel * error message to SC.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * At this point, we know that the request is valid, so pass
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the request to the daemon.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* wait for daemon to process request */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni if (cv_reltimedwait(&sckm_cons_cv, &sckm_umutex,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drv_usectohz(SCKM_DAEMON_TIMEOUT), TR_CLOCK_TICK) == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Daemon did not process the data, report this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * error to the SC.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Daemon processed data, return status to SC */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "error, errno=%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel "bad request");
03831d35f7499c87d51205817c93e9a8d42c4baestevel "supported");
03831d35f7499c87d51205817c93e9a8d42c4baestevel "from key engine");
03831d35f7499c87d51205817c93e9a8d42c4baestevel "an error");
03831d35f7499c87d51205817c93e9a8d42c4baestevel "SADB message type");
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* send reply back to SC */
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCKM_DEBUG1(D_TASK, "failed sending reply to SC (%d)", rv);