103831d35Sstevel /* 203831d35Sstevel * CDDL HEADER START 303831d35Sstevel * 403831d35Sstevel * The contents of this file are subject to the terms of the 503831d35Sstevel * Common Development and Distribution License (the "License"). 603831d35Sstevel * You may not use this file except in compliance with the License. 703831d35Sstevel * 803831d35Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 903831d35Sstevel * or http://www.opensolaris.org/os/licensing. 1003831d35Sstevel * See the License for the specific language governing permissions 1103831d35Sstevel * and limitations under the License. 1203831d35Sstevel * 1303831d35Sstevel * When distributing Covered Code, include this CDDL HEADER in each 1403831d35Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1503831d35Sstevel * If applicable, add the following below this CDDL HEADER, with the 1603831d35Sstevel * fields enclosed by brackets "[]" replaced with your own identifying 1703831d35Sstevel * information: Portions Copyright [yyyy] [name of copyright owner] 1803831d35Sstevel * 1903831d35Sstevel * CDDL HEADER END 2003831d35Sstevel */ 2103831d35Sstevel 2203831d35Sstevel /* 23d3d50737SRafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2403831d35Sstevel * Use is subject to license terms. 2503831d35Sstevel */ 2603831d35Sstevel 2703831d35Sstevel 2803831d35Sstevel /* 2903831d35Sstevel * Starcat IPSec Key Management Driver. 3003831d35Sstevel * 3103831d35Sstevel * This driver runs on a Starcat Domain. It processes requests received 3203831d35Sstevel * from the System Controller (SC) from IOSRAM, passes these requests 3303831d35Sstevel * to the sckmd daemon by means of an open/close/ioctl interface, and 3403831d35Sstevel * sends corresponding status information back to the SC. 3503831d35Sstevel * 3603831d35Sstevel * Requests received from the SC consist of IPsec security associations 3703831d35Sstevel * (SAs) needed to secure the communication between SC and Domain daemons 3803831d35Sstevel * communicating using the Management Network (MAN). 3903831d35Sstevel */ 4003831d35Sstevel 4103831d35Sstevel #include <sys/types.h> 4203831d35Sstevel #include <sys/cmn_err.h> 4303831d35Sstevel #include <sys/kmem.h> 4403831d35Sstevel #include <sys/errno.h> 4503831d35Sstevel #include <sys/file.h> 4603831d35Sstevel #include <sys/open.h> 4703831d35Sstevel #include <sys/stat.h> 4803831d35Sstevel #include <sys/conf.h> 4903831d35Sstevel #include <sys/ddi.h> 5003831d35Sstevel #include <sys/cmn_err.h> 5103831d35Sstevel #include <sys/sunddi.h> 5203831d35Sstevel #include <sys/sunndi.h> 5303831d35Sstevel #include <sys/ddi_impldefs.h> 5403831d35Sstevel #include <sys/ndi_impldefs.h> 5503831d35Sstevel #include <sys/modctl.h> 5603831d35Sstevel #include <sys/disp.h> 5703831d35Sstevel #include <sys/async.h> 5803831d35Sstevel #include <sys/mboxsc.h> 5903831d35Sstevel #include <sys/sckm_msg.h> 6003831d35Sstevel #include <sys/sckm_io.h> 6103831d35Sstevel #include <sys/taskq.h> 6203831d35Sstevel #include <sys/note.h> 6303831d35Sstevel 6403831d35Sstevel #ifdef DEBUG 6503831d35Sstevel static uint_t sckm_debug_flags = 0x0; 6603831d35Sstevel #define SCKM_DEBUG0(f, s) if ((f)& sckm_debug_flags) \ 6703831d35Sstevel cmn_err(CE_CONT, s) 6803831d35Sstevel #define SCKM_DEBUG1(f, s, a) if ((f)& sckm_debug_flags) \ 6903831d35Sstevel cmn_err(CE_CONT, s, a) 7003831d35Sstevel #define SCKM_DEBUG2(f, s, a, b) if ((f)& sckm_debug_flags) \ 7103831d35Sstevel cmn_err(CE_CONT, s, a, b) 7203831d35Sstevel #define SCKM_DEBUG3(f, s, a, b, c) if ((f)& sckm_debug_flags) \ 7303831d35Sstevel cmn_err(CE_CONT, s, a, b, c) 7403831d35Sstevel #define SCKM_DEBUG4(f, s, a, b, c, d) if ((f)& sckm_debug_flags) \ 7503831d35Sstevel cmn_err(CE_CONT, s, a, b, c, d) 7603831d35Sstevel #define SCKM_DEBUG5(f, s, a, b, c, d, e) if ((f)& sckm_debug_flags) \ 7703831d35Sstevel cmn_err(CE_CONT, s, a, b, c, d, e) 7803831d35Sstevel #define SCKM_DEBUG6(f, s, a, b, c, d, e, ff) if ((f)& sckm_debug_flags) \ 7903831d35Sstevel cmn_err(CE_CONT, s, a, b, c, d, e, ff) 8003831d35Sstevel #else 8103831d35Sstevel #define SCKM_DEBUG0(f, s) 8203831d35Sstevel #define SCKM_DEBUG1(f, s, a) 8303831d35Sstevel #define SCKM_DEBUG2(f, s, a, b) 8403831d35Sstevel #define SCKM_DEBUG3(f, s, a, b, c) 8503831d35Sstevel #define SCKM_DEBUG4(f, s, a, b, c, d) 8603831d35Sstevel #define SCKM_DEBUG5(f, s, a, b, c, d, e) 8703831d35Sstevel #define SCKM_DEBUG6(f, s, a, b, c, d, e, ff) 8803831d35Sstevel #endif /* DEBUG */ 8903831d35Sstevel 9003831d35Sstevel #define D_INIT 0x00000001 /* _init/_fini/_info */ 9103831d35Sstevel #define D_ATTACH 0x00000002 /* attach/detach */ 9203831d35Sstevel #define D_OPEN 0x00000008 /* open/close */ 9303831d35Sstevel #define D_IOCTL 0x00010000 /* ioctl */ 9403831d35Sstevel #define D_TASK 0x00100000 /* mailbox task processing */ 9503831d35Sstevel #define D_CALLBACK 0x00200000 /* mailbox callback */ 9603831d35Sstevel 9703831d35Sstevel static int sckm_open(dev_t *, int, int, struct cred *); 9803831d35Sstevel static int sckm_close(dev_t, int, int, struct cred *); 9903831d35Sstevel static int sckm_ioctl(dev_t, int, intptr_t, int, struct cred *, int *); 10003831d35Sstevel 10103831d35Sstevel static struct cb_ops sckm_cb_ops = { 10203831d35Sstevel sckm_open, /* open */ 10303831d35Sstevel sckm_close, /* close */ 10403831d35Sstevel nodev, /* strategy */ 10503831d35Sstevel nodev, /* print */ 10603831d35Sstevel nodev, /* dump */ 10703831d35Sstevel nodev, /* read */ 10803831d35Sstevel nodev, /* write */ 10903831d35Sstevel sckm_ioctl, /* ioctl */ 11003831d35Sstevel nodev, /* devmap */ 11103831d35Sstevel nodev, /* mmap */ 11203831d35Sstevel nodev, /* segmap */ 11303831d35Sstevel nochpoll, /* poll */ 11403831d35Sstevel ddi_prop_op, /* prop_op */ 11503831d35Sstevel 0, /* streamtab */ 11603831d35Sstevel D_NEW | D_MP /* Driver compatibility flag */ 11703831d35Sstevel }; 11803831d35Sstevel 11903831d35Sstevel static int sckm_attach(dev_info_t *, ddi_attach_cmd_t); 12003831d35Sstevel static int sckm_detach(dev_info_t *, ddi_detach_cmd_t); 12103831d35Sstevel static int sckm_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 12203831d35Sstevel 12303831d35Sstevel static struct dev_ops sckm_ops = { 12403831d35Sstevel DEVO_REV, /* devo_rev, */ 12503831d35Sstevel 0, /* refcnt */ 12603831d35Sstevel sckm_info, /* get_dev_info */ 12703831d35Sstevel nulldev, /* identify */ 12803831d35Sstevel nulldev, /* probe */ 12903831d35Sstevel sckm_attach, /* attach */ 13003831d35Sstevel sckm_detach, /* detach */ 13103831d35Sstevel nodev, /* reset */ 13203831d35Sstevel &sckm_cb_ops, /* driver operations */ 13319397407SSherry Moore (struct bus_ops *)0, /* no bus operations */ 13419397407SSherry Moore NULL, /* power */ 13519397407SSherry Moore ddi_quiesce_not_needed, /* quiesce */ 13603831d35Sstevel }; 13703831d35Sstevel 13803831d35Sstevel static struct modldrv modldrv = { 13903831d35Sstevel &mod_driverops, 14019397407SSherry Moore "Key Management Driver", 14103831d35Sstevel &sckm_ops, 14203831d35Sstevel }; 14303831d35Sstevel 14403831d35Sstevel static struct modlinkage modlinkage = { 14503831d35Sstevel MODREV_1, 14603831d35Sstevel &modldrv, 14703831d35Sstevel NULL 14803831d35Sstevel }; 14903831d35Sstevel 15003831d35Sstevel /* 15103831d35Sstevel * Private definitions. 15203831d35Sstevel */ 15303831d35Sstevel #define SCKM_DEF_GETMSG_TIMEOUT 60 /* in seconds */ 15403831d35Sstevel #define SCKM_DAEMON_TIMEOUT 4000000 /* in microseconds */ 15503831d35Sstevel #define SCKM_NUM_TASKQ 2 /* # of task queue entries */ 15603831d35Sstevel 15703831d35Sstevel /* 15803831d35Sstevel * For processing mailbox layer events. 15903831d35Sstevel */ 16003831d35Sstevel static kmutex_t sckm_task_mutex; 16103831d35Sstevel static kmutex_t sckm_taskq_ptr_mutex; 16203831d35Sstevel static clock_t sckm_getmsg_timeout = SCKM_DEF_GETMSG_TIMEOUT*1000; 16303831d35Sstevel static taskq_t *sckm_taskq = NULL; 16403831d35Sstevel static sckm_mbox_req_hdr_t *req_data = NULL; 16503831d35Sstevel static sckm_mbox_rep_hdr_t *rep_data = NULL; 16603831d35Sstevel 16703831d35Sstevel 16803831d35Sstevel /* 16903831d35Sstevel * For synchronization with key management daemon. 17003831d35Sstevel */ 17103831d35Sstevel static kmutex_t sckm_umutex; 17203831d35Sstevel static kcondvar_t sckm_udata_cv; /* daemon waits on data */ 17303831d35Sstevel static kcondvar_t sckm_cons_cv; /* wait for daemon to consume data */ 17403831d35Sstevel static boolean_t sckm_udata_req = B_FALSE; /* data available for daemon */ 17503831d35Sstevel static sckm_ioctl_getreq_t sckm_udata; /* request for daemon */ 17603831d35Sstevel static sckm_ioctl_status_t sckm_udata_status; /* status from daemon */ 17703831d35Sstevel 17803831d35Sstevel /* 17903831d35Sstevel * Other misc private variables. 18003831d35Sstevel */ 18103831d35Sstevel static dev_info_t *sckm_devi = NULL; 18203831d35Sstevel static boolean_t sckm_oflag = B_FALSE; 18303831d35Sstevel 18403831d35Sstevel /* 18503831d35Sstevel * Private functions prototypes. 18603831d35Sstevel */ 18703831d35Sstevel static void sckm_mbox_callback(void); 18803831d35Sstevel static void sckm_mbox_task(void *arg); 18903831d35Sstevel static void sckm_process_msg(uint32_t cmd, uint64_t transid, 19003831d35Sstevel uint32_t len, sckm_mbox_req_hdr_t *req_data, 19103831d35Sstevel sckm_mbox_rep_hdr_t *rep_data); 19203831d35Sstevel 19303831d35Sstevel 19403831d35Sstevel int 19503831d35Sstevel _init(void) 19603831d35Sstevel { 19703831d35Sstevel mboxsc_timeout_range_t timeout_range; 19803831d35Sstevel int ret; 19903831d35Sstevel 20003831d35Sstevel SCKM_DEBUG0(D_INIT, "in _init"); 20103831d35Sstevel 20203831d35Sstevel /* 20303831d35Sstevel * Initialize outgoing mailbox (KDSC) 20403831d35Sstevel */ 20503831d35Sstevel if ((ret = mboxsc_init(KEY_KDSC, MBOXSC_MBOX_OUT, NULL)) != 0) { 20603831d35Sstevel cmn_err(CE_WARN, "failed initializing outgoing mailbox " 20703831d35Sstevel "(%d)", ret); 20803831d35Sstevel return (ret); 20903831d35Sstevel } 21003831d35Sstevel 21103831d35Sstevel /* 21203831d35Sstevel * Initialize incoming mailbox (SCKD) 21303831d35Sstevel */ 21403831d35Sstevel if ((ret = mboxsc_init(KEY_SCKD, MBOXSC_MBOX_IN, 21503831d35Sstevel sckm_mbox_callback)) != 0) { 21603831d35Sstevel cmn_err(CE_WARN, "failed initializing incoming mailbox " 21703831d35Sstevel "(%d)\n", ret); 218*07d06da5SSurya Prakki (void) mboxsc_fini(KEY_KDSC); 21903831d35Sstevel return (ret); 22003831d35Sstevel } 22103831d35Sstevel 22203831d35Sstevel if ((ret = mboxsc_ctrl(KEY_SCKD, MBOXSC_CMD_GETMSG_TIMEOUT_RANGE, 22303831d35Sstevel (void *)&timeout_range)) != 0) { 224*07d06da5SSurya Prakki (void) mboxsc_fini(KEY_SCKD); 225*07d06da5SSurya Prakki (void) mboxsc_fini(KEY_KDSC); 22603831d35Sstevel return (ret); 22703831d35Sstevel } 22803831d35Sstevel 22903831d35Sstevel if (sckm_getmsg_timeout < timeout_range.min_timeout) { 23003831d35Sstevel sckm_getmsg_timeout = timeout_range.min_timeout; 23103831d35Sstevel cmn_err(CE_WARN, "resetting getmsg timeout to %lx", 23203831d35Sstevel sckm_getmsg_timeout); 23303831d35Sstevel } 23403831d35Sstevel 23503831d35Sstevel if (sckm_getmsg_timeout > timeout_range.max_timeout) { 23603831d35Sstevel sckm_getmsg_timeout = timeout_range.max_timeout; 23703831d35Sstevel cmn_err(CE_WARN, "resetting getmsg timeout to %lx", 23803831d35Sstevel sckm_getmsg_timeout); 23903831d35Sstevel } 24003831d35Sstevel 24103831d35Sstevel if ((ret = mod_install(&modlinkage)) != 0) { 242*07d06da5SSurya Prakki (void) mboxsc_fini(KEY_KDSC); 243*07d06da5SSurya Prakki (void) mboxsc_fini(KEY_SCKD); 24403831d35Sstevel return (ret); 24503831d35Sstevel } 24603831d35Sstevel 24703831d35Sstevel /* 24803831d35Sstevel * Initialize variables needed for synchronization with daemon. 24903831d35Sstevel */ 25003831d35Sstevel sckm_udata.buf = kmem_alloc(SCKM_SCKD_MAXDATA, KM_SLEEP); 25103831d35Sstevel req_data = (sckm_mbox_req_hdr_t *)kmem_alloc(SCKM_SCKD_MAXDATA, 25203831d35Sstevel KM_SLEEP); 25303831d35Sstevel rep_data = (sckm_mbox_rep_hdr_t *)kmem_alloc(SCKM_KDSC_MAXDATA, 25403831d35Sstevel KM_SLEEP); 25503831d35Sstevel 25603831d35Sstevel if ((sckm_udata.buf == NULL) || (req_data == NULL) || 25703831d35Sstevel (rep_data == NULL)) { 25803831d35Sstevel cmn_err(CE_WARN, "not enough memory during _init"); 25903831d35Sstevel 26003831d35Sstevel /* free what was successfully allocated */ 26103831d35Sstevel if (sckm_udata.buf != NULL) 26203831d35Sstevel kmem_free(sckm_udata.buf, SCKM_SCKD_MAXDATA); 26303831d35Sstevel if (req_data != NULL) 26403831d35Sstevel kmem_free(req_data, SCKM_SCKD_MAXDATA); 26503831d35Sstevel if (rep_data != NULL) 26603831d35Sstevel kmem_free(rep_data, SCKM_KDSC_MAXDATA); 26703831d35Sstevel sckm_udata.buf = NULL; 26803831d35Sstevel req_data = NULL; 26903831d35Sstevel rep_data = NULL; 27003831d35Sstevel 27103831d35Sstevel /* uninitialize mailboxes, remove module, and return error */ 272*07d06da5SSurya Prakki (void) mboxsc_fini(KEY_KDSC); 273*07d06da5SSurya Prakki (void) mboxsc_fini(KEY_SCKD); 274*07d06da5SSurya Prakki (void) mod_remove(&modlinkage); 27503831d35Sstevel return (-1); 27603831d35Sstevel } 27703831d35Sstevel 27803831d35Sstevel cv_init(&sckm_udata_cv, NULL, CV_DRIVER, NULL); 27903831d35Sstevel cv_init(&sckm_cons_cv, NULL, CV_DRIVER, NULL); 28003831d35Sstevel mutex_init(&sckm_umutex, NULL, MUTEX_DRIVER, NULL); 28103831d35Sstevel 28203831d35Sstevel /* 28303831d35Sstevel * Create mutex for task processing, protection of taskq 28403831d35Sstevel * pointer, and create taskq. 28503831d35Sstevel */ 28603831d35Sstevel mutex_init(&sckm_task_mutex, NULL, MUTEX_DRIVER, NULL); 28703831d35Sstevel mutex_init(&sckm_taskq_ptr_mutex, NULL, MUTEX_DRIVER, NULL); 28803831d35Sstevel sckm_taskq = taskq_create("sckm_taskq", 1, minclsyspri, 28903831d35Sstevel SCKM_NUM_TASKQ, SCKM_NUM_TASKQ, TASKQ_PREPOPULATE); 29003831d35Sstevel 29103831d35Sstevel SCKM_DEBUG1(D_INIT, "out _init ret=%d\n", ret); 29203831d35Sstevel return (ret); 29303831d35Sstevel } 29403831d35Sstevel 29503831d35Sstevel int 29603831d35Sstevel _fini(void) 29703831d35Sstevel { 29803831d35Sstevel int ret; 29903831d35Sstevel 30003831d35Sstevel SCKM_DEBUG0(D_INIT, "in _fini"); 30103831d35Sstevel 30203831d35Sstevel if ((ret = mod_remove(&modlinkage)) != 0) { 30303831d35Sstevel return (ret); 30403831d35Sstevel } 30503831d35Sstevel 30603831d35Sstevel /* 30703831d35Sstevel * Wait for scheduled tasks to complete, then destroy task queue. 30803831d35Sstevel */ 30903831d35Sstevel mutex_enter(&sckm_taskq_ptr_mutex); 31003831d35Sstevel if (sckm_taskq != NULL) { 31103831d35Sstevel taskq_destroy(sckm_taskq); 31203831d35Sstevel sckm_taskq = NULL; 31303831d35Sstevel } 31403831d35Sstevel mutex_exit(&sckm_taskq_ptr_mutex); 31503831d35Sstevel 31603831d35Sstevel /* 31703831d35Sstevel * Terminate incoming and outgoing IOSRAM mailboxes 31803831d35Sstevel */ 319*07d06da5SSurya Prakki (void) mboxsc_fini(KEY_KDSC); 320*07d06da5SSurya Prakki (void) mboxsc_fini(KEY_SCKD); 32103831d35Sstevel 32203831d35Sstevel /* 32303831d35Sstevel * Destroy module synchronization objects and free memory 32403831d35Sstevel */ 32503831d35Sstevel mutex_destroy(&sckm_task_mutex); 32603831d35Sstevel mutex_destroy(&sckm_taskq_ptr_mutex); 32703831d35Sstevel mutex_destroy(&sckm_umutex); 32803831d35Sstevel cv_destroy(&sckm_cons_cv); 32903831d35Sstevel 33003831d35Sstevel if (sckm_udata.buf != NULL) { 33103831d35Sstevel kmem_free(sckm_udata.buf, SCKM_SCKD_MAXDATA); 33203831d35Sstevel sckm_udata.buf = NULL; 33303831d35Sstevel } 33403831d35Sstevel if (rep_data != NULL) { 33503831d35Sstevel kmem_free(rep_data, SCKM_KDSC_MAXDATA); 33603831d35Sstevel rep_data = NULL; 33703831d35Sstevel } 33803831d35Sstevel if (req_data != NULL) { 33903831d35Sstevel kmem_free(req_data, SCKM_SCKD_MAXDATA); 34003831d35Sstevel req_data = NULL; 34103831d35Sstevel } 34203831d35Sstevel 34303831d35Sstevel return (ret); 34403831d35Sstevel } 34503831d35Sstevel 34603831d35Sstevel int 34703831d35Sstevel _info(struct modinfo *modinfop) 34803831d35Sstevel { 34903831d35Sstevel SCKM_DEBUG0(D_INIT, "in _info"); 35003831d35Sstevel return (mod_info(&modlinkage, modinfop)); 35103831d35Sstevel } 35203831d35Sstevel 35303831d35Sstevel static int 35403831d35Sstevel sckm_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 35503831d35Sstevel { 35603831d35Sstevel SCKM_DEBUG1(D_ATTACH, "in sckm_attach, cmd=%d", cmd); 35703831d35Sstevel 35803831d35Sstevel switch (cmd) { 35903831d35Sstevel case DDI_ATTACH: 36003831d35Sstevel SCKM_DEBUG0(D_ATTACH, "sckm_attach: DDI_ATTACH"); 36103831d35Sstevel if (ddi_create_minor_node(devi, "sckmdrv", S_IFCHR, 36203831d35Sstevel 0, NULL, NULL) == DDI_FAILURE) { 36303831d35Sstevel cmn_err(CE_WARN, "ddi_create_minor_node failed"); 36403831d35Sstevel ddi_remove_minor_node(devi, NULL); 36503831d35Sstevel return (DDI_FAILURE); 36603831d35Sstevel } 36703831d35Sstevel sckm_devi = devi; 36803831d35Sstevel break; 36903831d35Sstevel case DDI_SUSPEND: 37003831d35Sstevel SCKM_DEBUG0(D_ATTACH, "sckm_attach: DDI_SUSPEND"); 37103831d35Sstevel break; 37203831d35Sstevel default: 37303831d35Sstevel cmn_err(CE_WARN, "sckm_attach: bad cmd %d\n", cmd); 37403831d35Sstevel return (DDI_FAILURE); 37503831d35Sstevel } 37603831d35Sstevel 37703831d35Sstevel SCKM_DEBUG0(D_ATTACH, "out sckm_attach (DDI_SUCCESS)"); 37803831d35Sstevel return (DDI_SUCCESS); 37903831d35Sstevel } 38003831d35Sstevel 38103831d35Sstevel static int 38203831d35Sstevel sckm_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 38303831d35Sstevel { 38403831d35Sstevel SCKM_DEBUG1(D_ATTACH, "in sckm_detach, cmd=%d", cmd); 38503831d35Sstevel 38603831d35Sstevel switch (cmd) { 38703831d35Sstevel case DDI_DETACH: 38803831d35Sstevel SCKM_DEBUG0(D_ATTACH, "sckm_detach: DDI_DETACH"); 38903831d35Sstevel ddi_remove_minor_node(devi, NULL); 39003831d35Sstevel break; 39103831d35Sstevel case DDI_SUSPEND: 39203831d35Sstevel SCKM_DEBUG0(D_ATTACH, "sckm_detach: DDI_DETACH"); 39303831d35Sstevel break; 39403831d35Sstevel default: 39503831d35Sstevel cmn_err(CE_WARN, "sckm_detach: bad cmd %d\n", cmd); 39603831d35Sstevel return (DDI_FAILURE); 39703831d35Sstevel } 39803831d35Sstevel 39903831d35Sstevel SCKM_DEBUG0(D_ATTACH, "out sckm_detach (DDI_SUCCESS)"); 40003831d35Sstevel return (DDI_SUCCESS); 40103831d35Sstevel } 40203831d35Sstevel 40303831d35Sstevel /* ARGSUSED */ 40403831d35Sstevel static int 40503831d35Sstevel sckm_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 40603831d35Sstevel void **result) 40703831d35Sstevel { 40803831d35Sstevel int rv; 40903831d35Sstevel 41003831d35Sstevel SCKM_DEBUG1(D_ATTACH, "in sckm_info, infocmd=%d", infocmd); 41103831d35Sstevel 41203831d35Sstevel switch (infocmd) { 41303831d35Sstevel case DDI_INFO_DEVT2DEVINFO: 41403831d35Sstevel *result = (void *)sckm_devi; 41503831d35Sstevel rv = DDI_SUCCESS; 41603831d35Sstevel break; 41703831d35Sstevel case DDI_INFO_DEVT2INSTANCE: 41803831d35Sstevel *result = (void *)0; 41903831d35Sstevel rv = DDI_SUCCESS; 42003831d35Sstevel break; 42103831d35Sstevel default: 42203831d35Sstevel rv = DDI_FAILURE; 42303831d35Sstevel } 42403831d35Sstevel 42503831d35Sstevel SCKM_DEBUG1(D_ATTACH, "out sckm_info, rv=%d", rv); 42603831d35Sstevel return (rv); 42703831d35Sstevel } 42803831d35Sstevel 42903831d35Sstevel /*ARGSUSED*/ 43003831d35Sstevel static int 43103831d35Sstevel sckm_open(dev_t *devp, int flag, int otyp, struct cred *cred) 43203831d35Sstevel { 43303831d35Sstevel SCKM_DEBUG0(D_OPEN, "in sckm_open"); 43403831d35Sstevel 43503831d35Sstevel /* check credentials of calling process */ 43603831d35Sstevel if (drv_priv(cred)) { 43703831d35Sstevel SCKM_DEBUG0(D_OPEN, "sckm_open: attempt by non-root proc"); 43803831d35Sstevel return (EPERM); 43903831d35Sstevel } 44003831d35Sstevel 44103831d35Sstevel /* enforce exclusive access */ 44203831d35Sstevel mutex_enter(&sckm_umutex); 44303831d35Sstevel if (sckm_oflag == B_TRUE) { 44403831d35Sstevel SCKM_DEBUG0(D_OPEN, "sckm_open: already open"); 44503831d35Sstevel mutex_exit(&sckm_umutex); 44603831d35Sstevel return (EBUSY); 44703831d35Sstevel } 44803831d35Sstevel sckm_oflag = B_TRUE; 44903831d35Sstevel mutex_exit(&sckm_umutex); 45003831d35Sstevel 45103831d35Sstevel SCKM_DEBUG0(D_OPEN, "sckm_open: succcess"); 45203831d35Sstevel return (0); 45303831d35Sstevel } 45403831d35Sstevel 45503831d35Sstevel /*ARGSUSED*/ 45603831d35Sstevel static int 45703831d35Sstevel sckm_close(dev_t dev, int flag, int otyp, struct cred *cred) 45803831d35Sstevel { 45903831d35Sstevel SCKM_DEBUG0(D_OPEN, "in sckm_close"); 46003831d35Sstevel 46103831d35Sstevel mutex_enter(&sckm_umutex); 46203831d35Sstevel sckm_oflag = B_FALSE; 46303831d35Sstevel mutex_exit(&sckm_umutex); 46403831d35Sstevel 46503831d35Sstevel return (0); 46603831d35Sstevel } 46703831d35Sstevel 46803831d35Sstevel 46903831d35Sstevel static int 47003831d35Sstevel sckm_copyin_ioctl_getreq(intptr_t userarg, sckm_ioctl_getreq_t *driverarg, 47103831d35Sstevel int flag) 47203831d35Sstevel { 47303831d35Sstevel #ifdef _MULTI_DATAMODEL 47403831d35Sstevel switch (ddi_model_convert_from(flag & FMODELS)) { 47503831d35Sstevel case DDI_MODEL_ILP32: { 47603831d35Sstevel sckm_ioctl_getreq32_t driverarg32; 47703831d35Sstevel if (ddi_copyin((caddr_t)userarg, &driverarg32, 47803831d35Sstevel sizeof (sckm_ioctl_getreq32_t), flag)) { 47903831d35Sstevel return (EFAULT); 48003831d35Sstevel } 48103831d35Sstevel driverarg->transid = driverarg32.transid; 48203831d35Sstevel driverarg->type = driverarg32.type; 48303831d35Sstevel driverarg->buf = (caddr_t)(uintptr_t)driverarg32.buf; 48403831d35Sstevel driverarg->buf_len = driverarg32.buf_len; 48503831d35Sstevel break; 48603831d35Sstevel } 48703831d35Sstevel case DDI_MODEL_NONE: { 48803831d35Sstevel if (ddi_copyin((caddr_t)userarg, &driverarg, 48903831d35Sstevel sizeof (sckm_ioctl_getreq_t), flag)) { 49003831d35Sstevel return (EFAULT); 49103831d35Sstevel } 49203831d35Sstevel break; 49303831d35Sstevel } 49403831d35Sstevel } 49503831d35Sstevel #else /* ! _MULTI_DATAMODEL */ 49603831d35Sstevel if (ddi_copyin((caddr_t)userarg, &driverarg, 49703831d35Sstevel sizeof (sckm_ioctl_getreq_t), flag)) { 49803831d35Sstevel return (EFAULT); 49903831d35Sstevel } 50003831d35Sstevel #endif /* _MULTI_DATAMODEL */ 50103831d35Sstevel return (0); 50203831d35Sstevel } 50303831d35Sstevel 50403831d35Sstevel 50503831d35Sstevel static int 50603831d35Sstevel sckm_copyout_ioctl_getreq(sckm_ioctl_getreq_t *driverarg, intptr_t userarg, 50703831d35Sstevel int flag) 50803831d35Sstevel { 50903831d35Sstevel #ifdef _MULTI_DATAMODEL 51003831d35Sstevel switch (ddi_model_convert_from(flag & FMODELS)) { 51103831d35Sstevel case DDI_MODEL_ILP32: { 51203831d35Sstevel sckm_ioctl_getreq32_t driverarg32; 51303831d35Sstevel driverarg32.transid = driverarg->transid; 51403831d35Sstevel driverarg32.type = driverarg->type; 51503831d35Sstevel driverarg32.buf = (caddr32_t)(uintptr_t)driverarg->buf; 51603831d35Sstevel driverarg32.buf_len = driverarg->buf_len; 51703831d35Sstevel if (ddi_copyout(&driverarg32, (caddr_t)userarg, 51803831d35Sstevel sizeof (sckm_ioctl_getreq32_t), flag)) { 51903831d35Sstevel return (EFAULT); 52003831d35Sstevel } 52103831d35Sstevel break; 52203831d35Sstevel } 52303831d35Sstevel case DDI_MODEL_NONE: 52403831d35Sstevel if (ddi_copyout(driverarg, (caddr_t)userarg, 52503831d35Sstevel sizeof (sckm_ioctl_getreq_t), flag)) { 52603831d35Sstevel return (EFAULT); 52703831d35Sstevel } 52803831d35Sstevel break; 52903831d35Sstevel } 53003831d35Sstevel #else /* ! _MULTI_DATAMODEL */ 53103831d35Sstevel if (ddi_copyout(driverarg, (caddr_t)userarg, 53203831d35Sstevel sizeof (sckm_ioctl_getreq_t), flag)) { 53303831d35Sstevel return (EFAULT); 53403831d35Sstevel } 53503831d35Sstevel #endif /* _MULTI_DATAMODEL */ 53603831d35Sstevel return (0); 53703831d35Sstevel } 53803831d35Sstevel 53903831d35Sstevel 54003831d35Sstevel /*ARGSUSED*/ 54103831d35Sstevel static int 54203831d35Sstevel sckm_ioctl(dev_t dev, int cmd, intptr_t data, int flag, 54303831d35Sstevel cred_t *cred, int *rvalp) 54403831d35Sstevel { 54503831d35Sstevel int rval = 0; 54603831d35Sstevel 54703831d35Sstevel SCKM_DEBUG0(D_IOCTL, "in sckm_ioctl"); 54803831d35Sstevel 54903831d35Sstevel switch (cmd) { 55003831d35Sstevel case SCKM_IOCTL_GETREQ: { 55103831d35Sstevel sckm_ioctl_getreq_t arg; 55203831d35Sstevel 55303831d35Sstevel SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: got SCKM_IOCTL_GETREQ"); 55403831d35Sstevel if (sckm_copyin_ioctl_getreq(data, &arg, flag)) { 55503831d35Sstevel return (EFAULT); 55603831d35Sstevel } 55703831d35Sstevel 55803831d35Sstevel /* sanity check argument */ 55903831d35Sstevel if (arg.buf_len < SCKM_SCKD_MAXDATA) { 56003831d35Sstevel SCKM_DEBUG2(D_IOCTL, "sckm_ioctl: usr buffer too " 56103831d35Sstevel "small (%d < %d)", arg.buf_len, SCKM_SCKD_MAXDATA); 56203831d35Sstevel return (ENOSPC); 56303831d35Sstevel } 56403831d35Sstevel 56503831d35Sstevel mutex_enter(&sckm_umutex); 56603831d35Sstevel 56703831d35Sstevel /* wait for request from SC */ 56803831d35Sstevel while (!sckm_udata_req) { 56903831d35Sstevel SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: waiting for msg"); 57003831d35Sstevel if (cv_wait_sig(&sckm_udata_cv, &sckm_umutex) == 0) { 57103831d35Sstevel mutex_exit(&sckm_umutex); 57203831d35Sstevel return (EINTR); 57303831d35Sstevel } 57403831d35Sstevel } 57503831d35Sstevel SCKM_DEBUG1(D_IOCTL, "sckm_ioctl: msg available " 57603831d35Sstevel "transid = 0x%lx", sckm_udata.transid); 57703831d35Sstevel 57803831d35Sstevel arg.transid = sckm_udata.transid; 57903831d35Sstevel arg.type = sckm_udata.type; 58003831d35Sstevel if (ddi_copyout(sckm_udata.buf, arg.buf, 58103831d35Sstevel sckm_udata.buf_len, flag)) { 58203831d35Sstevel mutex_exit(&sckm_umutex); 58303831d35Sstevel return (EFAULT); 58403831d35Sstevel } 58503831d35Sstevel arg.buf_len = sckm_udata.buf_len; 58603831d35Sstevel 58703831d35Sstevel mutex_exit(&sckm_umutex); 58803831d35Sstevel if (sckm_copyout_ioctl_getreq(&arg, data, flag)) { 58903831d35Sstevel return (EFAULT); 59003831d35Sstevel } 59103831d35Sstevel break; 59203831d35Sstevel } 59303831d35Sstevel case SCKM_IOCTL_STATUS: { 59403831d35Sstevel sckm_ioctl_status_t arg; 59503831d35Sstevel SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: got SCKM_IOCTL_STATUS"); 59603831d35Sstevel if (ddi_copyin((caddr_t)data, &arg, 59703831d35Sstevel sizeof (sckm_ioctl_status_t), flag)) { 59803831d35Sstevel cmn_err(CE_WARN, "sckm_ioctl: ddi_copyin failed"); 59903831d35Sstevel return (EFAULT); 60003831d35Sstevel } 60103831d35Sstevel SCKM_DEBUG3(D_IOCTL, "sckm_ioctl: arg transid=0x%lx, " 60203831d35Sstevel "status=%d, sadb_msg_errno=%d", arg.transid, arg.status, 60303831d35Sstevel arg.sadb_msg_errno); 60403831d35Sstevel 60503831d35Sstevel mutex_enter(&sckm_umutex); 60603831d35Sstevel 60703831d35Sstevel /* fail if no status is expected, or if it does not match */ 60803831d35Sstevel if (!sckm_udata_req || sckm_udata.transid != arg.transid) { 60903831d35Sstevel mutex_exit(&sckm_umutex); 61003831d35Sstevel return (EINVAL); 61103831d35Sstevel } 61203831d35Sstevel 61303831d35Sstevel /* update status information for event handler */ 61403831d35Sstevel bcopy(&arg, &sckm_udata_status, sizeof (sckm_ioctl_status_t)); 61503831d35Sstevel 61603831d35Sstevel /* signal event handler that request has been processed */ 61703831d35Sstevel SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: signaling event handler" 61803831d35Sstevel " that data has been processed"); 61903831d35Sstevel cv_signal(&sckm_cons_cv); 62003831d35Sstevel sckm_udata_req = B_FALSE; 62103831d35Sstevel 62203831d35Sstevel mutex_exit(&sckm_umutex); 62303831d35Sstevel break; 62403831d35Sstevel } 62503831d35Sstevel default: 62603831d35Sstevel SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: unknown command"); 62703831d35Sstevel rval = EINVAL; 62803831d35Sstevel } 62903831d35Sstevel 63003831d35Sstevel SCKM_DEBUG1(D_IOCTL, "out sckm_ioctl, rval=%d", rval); 63103831d35Sstevel return (rval); 63203831d35Sstevel } 63303831d35Sstevel 63403831d35Sstevel 63503831d35Sstevel /* 63603831d35Sstevel * sckm_mbox_callback 63703831d35Sstevel * 63803831d35Sstevel * Callback routine registered with the IOSRAM mailbox protocol driver. 63903831d35Sstevel * Invoked when a message is received on the mailbox. 64003831d35Sstevel */ 64103831d35Sstevel static void 64203831d35Sstevel sckm_mbox_callback(void) 64303831d35Sstevel { 64403831d35Sstevel SCKM_DEBUG0(D_CALLBACK, "in sckm_mbox_callback()"); 64503831d35Sstevel 64603831d35Sstevel mutex_enter(&sckm_taskq_ptr_mutex); 64703831d35Sstevel 64803831d35Sstevel if (sckm_taskq == NULL) { 64903831d35Sstevel mutex_exit(&sckm_taskq_ptr_mutex); 65003831d35Sstevel return; 65103831d35Sstevel } 65203831d35Sstevel 65303831d35Sstevel if (!taskq_dispatch(sckm_taskq, sckm_mbox_task, NULL, KM_NOSLEEP)) { 65403831d35Sstevel /* 65503831d35Sstevel * Too many tasks already pending. Do not queue a new 65603831d35Sstevel * request. 65703831d35Sstevel */ 65803831d35Sstevel SCKM_DEBUG0(D_CALLBACK, "failed dispatching task"); 65903831d35Sstevel } 66003831d35Sstevel 66103831d35Sstevel mutex_exit(&sckm_taskq_ptr_mutex); 66203831d35Sstevel 66303831d35Sstevel SCKM_DEBUG0(D_CALLBACK, "out sckm_mbox_callback()"); 66403831d35Sstevel } 66503831d35Sstevel 66603831d35Sstevel 66703831d35Sstevel /* 66803831d35Sstevel * sckm_mbox_task 66903831d35Sstevel * 67003831d35Sstevel * Dispatched on taskq from the IOSRAM mailbox callback 67103831d35Sstevel * sckm_mbox_callback when a message is received on the incoming 67203831d35Sstevel * mailbox. 67303831d35Sstevel */ 67403831d35Sstevel static void 67503831d35Sstevel sckm_mbox_task(void *ignored) 67603831d35Sstevel { 67703831d35Sstevel _NOTE(ARGUNUSED(ignored)) 67803831d35Sstevel uint32_t type, cmd, length; 67903831d35Sstevel uint64_t transid; 68003831d35Sstevel int rval; 68103831d35Sstevel 68203831d35Sstevel SCKM_DEBUG0(D_TASK, "in sckm_mbox_task\n"); 68303831d35Sstevel 68403831d35Sstevel mutex_enter(&sckm_task_mutex); 68503831d35Sstevel 68603831d35Sstevel if (req_data == NULL || rep_data == NULL) { 68703831d35Sstevel SCKM_DEBUG0(D_TASK, "sckm_mbox_task: no buffers"); 68803831d35Sstevel mutex_exit(&sckm_task_mutex); 68903831d35Sstevel return; 69003831d35Sstevel } 69103831d35Sstevel 69203831d35Sstevel /* 69303831d35Sstevel * Get mailbox message. 69403831d35Sstevel */ 69503831d35Sstevel 69603831d35Sstevel type = MBOXSC_MSG_REQUEST; 69703831d35Sstevel length = SCKM_SCKD_MAXDATA; 69803831d35Sstevel cmd = 0; 69903831d35Sstevel transid = 0; 70003831d35Sstevel 70103831d35Sstevel SCKM_DEBUG0(D_TASK, "sckm_mbox_task: " 70203831d35Sstevel "calling mboxsc_getmsg()\n"); 70303831d35Sstevel rval = mboxsc_getmsg(KEY_SCKD, &type, &cmd, &transid, 70403831d35Sstevel &length, req_data, sckm_getmsg_timeout); 70503831d35Sstevel 70603831d35Sstevel if (rval != 0) { 70703831d35Sstevel SCKM_DEBUG1(D_TASK, "sckm_mbox_task: " 70803831d35Sstevel "mboxsc_getmsg() failed (%d)\n", rval); 70903831d35Sstevel mutex_exit(&sckm_task_mutex); 71003831d35Sstevel return; 71103831d35Sstevel } 71203831d35Sstevel 71303831d35Sstevel SCKM_DEBUG4(D_TASK, "sckm_mbox_task: " 71403831d35Sstevel "type=0x%x cmd=0x%x length=%d transid=0x%lx\n", 71503831d35Sstevel type, cmd, length, transid); 71603831d35Sstevel 71703831d35Sstevel /* check message length */ 71803831d35Sstevel if (length < sizeof (sckm_mbox_req_hdr_t)) { 71903831d35Sstevel /* protocol error, drop message */ 72003831d35Sstevel SCKM_DEBUG2(D_TASK, "received short " 72103831d35Sstevel "message of length %d, min %lu", 72203831d35Sstevel length, sizeof (sckm_mbox_req_hdr_t)); 72303831d35Sstevel mutex_exit(&sckm_task_mutex); 72403831d35Sstevel return; 72503831d35Sstevel } 72603831d35Sstevel 72703831d35Sstevel /* check version of message received */ 72803831d35Sstevel if (req_data->sckm_version != SCKM_PROTOCOL_VERSION) { 72903831d35Sstevel SCKM_DEBUG2(D_TASK, "received protocol " 73003831d35Sstevel "version %d, expected %d", 73103831d35Sstevel req_data->sckm_version, SCKM_PROTOCOL_VERSION); 73203831d35Sstevel /* 73303831d35Sstevel * Send reply with SCKM_SADB_ERR_VERSION error 73403831d35Sstevel * so that SC can adopt correct protocol version 73503831d35Sstevel * for this domain. 73603831d35Sstevel */ 73703831d35Sstevel rep_data->sckm_version = SCKM_PROTOCOL_VERSION; 73803831d35Sstevel rep_data->status = SCKM_ERR_VERSION; 73903831d35Sstevel 74003831d35Sstevel rval = mboxsc_putmsg(KEY_KDSC, MBOXSC_MSG_REPLY, 74103831d35Sstevel cmd, &transid, sizeof (sckm_mbox_rep_hdr_t), 74203831d35Sstevel rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT); 74303831d35Sstevel 74403831d35Sstevel if (rval != 0) { 74503831d35Sstevel SCKM_DEBUG1(D_TASK, "sckm_mbox_task: " 74603831d35Sstevel "mboxsc_putmsg() failed (%d)\n", rval); 74703831d35Sstevel mutex_exit(&sckm_task_mutex); 74803831d35Sstevel return; 74903831d35Sstevel } 75003831d35Sstevel } 75103831d35Sstevel 75203831d35Sstevel /* process message */ 75303831d35Sstevel sckm_process_msg(cmd, transid, length, 75403831d35Sstevel req_data, rep_data); 75503831d35Sstevel 75603831d35Sstevel mutex_exit(&sckm_task_mutex); 75703831d35Sstevel } 75803831d35Sstevel 75903831d35Sstevel /* 76003831d35Sstevel * sckm_process_msg 76103831d35Sstevel * 76203831d35Sstevel * Process a message received from the SC. Invoked by sckm_event_task(). 76303831d35Sstevel */ 76403831d35Sstevel static void 76503831d35Sstevel sckm_process_msg(uint32_t cmd, uint64_t transid, 76603831d35Sstevel uint32_t len, sckm_mbox_req_hdr_t *req_data, 76703831d35Sstevel sckm_mbox_rep_hdr_t *rep_data) 76803831d35Sstevel { 76903831d35Sstevel int rv; 77003831d35Sstevel 77103831d35Sstevel mutex_enter(&sckm_umutex); 77203831d35Sstevel 77303831d35Sstevel switch (cmd) { 77403831d35Sstevel case SCKM_MSG_SADB: { 77503831d35Sstevel int sadb_msglen; 77603831d35Sstevel 77703831d35Sstevel sadb_msglen = len-sizeof (sckm_mbox_req_hdr_t); 77803831d35Sstevel SCKM_DEBUG1(D_TASK, "received SCKM_MSG_SADB len=%d", 77903831d35Sstevel sadb_msglen); 78003831d35Sstevel 78103831d35Sstevel /* sanity check request */ 78203831d35Sstevel if (len-sizeof (sckm_mbox_req_hdr_t) <= 0) { 78303831d35Sstevel SCKM_DEBUG0(D_TASK, "bad SADB message, " 78403831d35Sstevel "zero length"); 78503831d35Sstevel /* 78603831d35Sstevel * SADB message is too short, send corresponding 78703831d35Sstevel * error message to SC. 78803831d35Sstevel */ 78903831d35Sstevel rep_data->sckm_version = SCKM_PROTOCOL_VERSION; 79003831d35Sstevel rep_data->status = SCKM_ERR_SADB_MSG; 79103831d35Sstevel 79203831d35Sstevel if ((rv = mboxsc_putmsg(KEY_KDSC, MBOXSC_MSG_REPLY, 79303831d35Sstevel cmd, &transid, sizeof (sckm_mbox_rep_hdr_t), 79403831d35Sstevel rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT)) != 0) { 79503831d35Sstevel SCKM_DEBUG1(D_TASK, "sckm_mbox_task: " 79603831d35Sstevel "mboxsc_putmsg() failed (%d)\n", rv); 79703831d35Sstevel } 79803831d35Sstevel mutex_exit(&sckm_umutex); 79903831d35Sstevel return; 80003831d35Sstevel } 80103831d35Sstevel 80203831d35Sstevel /* initialize request for daemon */ 80303831d35Sstevel sckm_udata.transid = transid; 80403831d35Sstevel sckm_udata.type = SCKM_IOCTL_REQ_SADB; 80503831d35Sstevel sckm_udata.buf_len = len-sizeof (sckm_mbox_req_hdr_t); 80603831d35Sstevel bcopy(req_data+1, sckm_udata.buf, sckm_udata.buf_len); 80703831d35Sstevel 80803831d35Sstevel break; 80903831d35Sstevel } 81003831d35Sstevel default: 81103831d35Sstevel cmn_err(CE_WARN, "unknown cmd %x received from SC", cmd); 81203831d35Sstevel /* 81303831d35Sstevel * Received unknown command from SC. Send corresponding 81403831d35Sstevel * error message to SC. 81503831d35Sstevel */ 81603831d35Sstevel rep_data->sckm_version = SCKM_PROTOCOL_VERSION; 81703831d35Sstevel rep_data->status = SCKM_ERR_BAD_CMD; 81803831d35Sstevel 81903831d35Sstevel if ((rv = mboxsc_putmsg(KEY_KDSC, MBOXSC_MSG_REPLY, 82003831d35Sstevel cmd, &transid, sizeof (sckm_mbox_rep_hdr_t), 82103831d35Sstevel rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT)) != 0) { 82203831d35Sstevel SCKM_DEBUG1(D_TASK, "sckm_mbox_task: " 82303831d35Sstevel "mboxsc_putmsg() failed (%d)\n", rv); 82403831d35Sstevel } 82503831d35Sstevel mutex_exit(&sckm_umutex); 82603831d35Sstevel return; 82703831d35Sstevel } 82803831d35Sstevel 82903831d35Sstevel /* 83003831d35Sstevel * At this point, we know that the request is valid, so pass 83103831d35Sstevel * the request to the daemon. 83203831d35Sstevel */ 83303831d35Sstevel SCKM_DEBUG0(D_TASK, "waking up daemon"); 83403831d35Sstevel sckm_udata_req = B_TRUE; 83503831d35Sstevel cv_signal(&sckm_udata_cv); 83603831d35Sstevel 83703831d35Sstevel /* wait for daemon to process request */ 838d3d50737SRafael Vanoni if (cv_reltimedwait(&sckm_cons_cv, &sckm_umutex, 839d3d50737SRafael Vanoni drv_usectohz(SCKM_DAEMON_TIMEOUT), TR_CLOCK_TICK) == -1) { 84003831d35Sstevel /* 84103831d35Sstevel * Daemon did not process the data, report this 84203831d35Sstevel * error to the SC. 84303831d35Sstevel */ 84403831d35Sstevel SCKM_DEBUG0(D_TASK, "daemon timeout!!"); 84503831d35Sstevel rep_data->sckm_version = SCKM_PROTOCOL_VERSION; 84603831d35Sstevel rep_data->status = SCKM_ERR_DAEMON; 84703831d35Sstevel } else { 84803831d35Sstevel /* Daemon processed data, return status to SC */ 84903831d35Sstevel SCKM_DEBUG0(D_TASK, "daemon processed data"); 85003831d35Sstevel rep_data->sckm_version = SCKM_PROTOCOL_VERSION; 85103831d35Sstevel switch (sckm_udata_status.status) { 85203831d35Sstevel case SCKM_IOCTL_STAT_SUCCESS: 85303831d35Sstevel SCKM_DEBUG0(D_TASK, "daemon returned success"); 85403831d35Sstevel rep_data->status = SCKM_SUCCESS; 85503831d35Sstevel break; 85603831d35Sstevel case SCKM_IOCTL_STAT_ERR_PFKEY: 85703831d35Sstevel SCKM_DEBUG1(D_TASK, "daemon returned PF_KEY " 85803831d35Sstevel "error, errno=%d", 85903831d35Sstevel sckm_udata_status.sadb_msg_errno); 86003831d35Sstevel rep_data->status = SCKM_ERR_SADB_PFKEY; 86103831d35Sstevel rep_data->sadb_msg_errno = 86203831d35Sstevel sckm_udata_status.sadb_msg_errno; 86303831d35Sstevel break; 86403831d35Sstevel case SCKM_IOCTL_STAT_ERR_REQ: 86503831d35Sstevel SCKM_DEBUG0(D_TASK, "daemon returned " 86603831d35Sstevel "bad request"); 86703831d35Sstevel rep_data->status = SCKM_ERR_DAEMON; 86803831d35Sstevel break; 86903831d35Sstevel case SCKM_IOCTL_STAT_ERR_VERSION: 87003831d35Sstevel SCKM_DEBUG0(D_TASK, "PF_KEY version not " 87103831d35Sstevel "supported"); 87203831d35Sstevel rep_data->status = SCKM_ERR_SADB_VERSION; 87303831d35Sstevel rep_data->sadb_msg_version = 87403831d35Sstevel sckm_udata_status.sadb_msg_version; 87503831d35Sstevel break; 87603831d35Sstevel case SCKM_IOCTL_STAT_ERR_TIMEOUT: 87703831d35Sstevel SCKM_DEBUG0(D_TASK, "no response received " 87803831d35Sstevel "from key engine"); 87903831d35Sstevel rep_data->status = SCKM_ERR_SADB_TIMEOUT; 88003831d35Sstevel break; 88103831d35Sstevel case SCKM_IOCTL_STAT_ERR_OTHER: 88203831d35Sstevel SCKM_DEBUG0(D_TASK, "daemon encountered " 88303831d35Sstevel "an error"); 88403831d35Sstevel rep_data->status = SCKM_ERR_DAEMON; 88503831d35Sstevel break; 88603831d35Sstevel case SCKM_IOCTL_STAT_ERR_SADB_TYPE: 88703831d35Sstevel SCKM_DEBUG0(D_TASK, "daemon returned bad " 88803831d35Sstevel "SADB message type"); 88903831d35Sstevel rep_data->status = SCKM_ERR_SADB_BAD_TYPE; 89003831d35Sstevel break; 89103831d35Sstevel default: 89203831d35Sstevel cmn_err(CE_WARN, "SCKM daemon returned " 89303831d35Sstevel "invalid status %d", sckm_udata_status.status); 89403831d35Sstevel rep_data->status = SCKM_ERR_DAEMON; 89503831d35Sstevel } 89603831d35Sstevel } 89703831d35Sstevel 89803831d35Sstevel /* send reply back to SC */ 89903831d35Sstevel if ((rv = mboxsc_putmsg(KEY_KDSC, MBOXSC_MSG_REPLY, 90003831d35Sstevel cmd, &transid, sizeof (sckm_mbox_rep_hdr_t), 90103831d35Sstevel rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT)) != 0) { 90203831d35Sstevel SCKM_DEBUG1(D_TASK, "failed sending reply to SC (%d)", rv); 90303831d35Sstevel } else { 90403831d35Sstevel SCKM_DEBUG0(D_TASK, "reply sent to SC"); 90503831d35Sstevel } 90603831d35Sstevel 90703831d35Sstevel sckm_udata_req = B_FALSE; 90803831d35Sstevel mutex_exit(&sckm_umutex); 90903831d35Sstevel } 910