11708Sstevel /*
21708Sstevel * CDDL HEADER START
31708Sstevel *
41708Sstevel * The contents of this file are subject to the terms of the
51708Sstevel * Common Development and Distribution License (the "License").
61708Sstevel * You may not use this file except in compliance with the License.
71708Sstevel *
81708Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91708Sstevel * or http://www.opensolaris.org/os/licensing.
101708Sstevel * See the License for the specific language governing permissions
111708Sstevel * and limitations under the License.
121708Sstevel *
131708Sstevel * When distributing Covered Code, include this CDDL HEADER in each
141708Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151708Sstevel * If applicable, add the following below this CDDL HEADER, with the
161708Sstevel * fields enclosed by brackets "[]" replaced with your own identifying
171708Sstevel * information: Portions Copyright [yyyy] [name of copyright owner]
181708Sstevel *
191708Sstevel * CDDL HEADER END
201708Sstevel */
211708Sstevel
221708Sstevel /*
2311066Srafael.vanoni@sun.com * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
241708Sstevel * Use is subject to license terms.
251708Sstevel */
261708Sstevel
271708Sstevel
281708Sstevel /*
291708Sstevel * Starcat IPSec Key Management Driver.
301708Sstevel *
311708Sstevel * This driver runs on a Starcat Domain. It processes requests received
321708Sstevel * from the System Controller (SC) from IOSRAM, passes these requests
331708Sstevel * to the sckmd daemon by means of an open/close/ioctl interface, and
341708Sstevel * sends corresponding status information back to the SC.
351708Sstevel *
361708Sstevel * Requests received from the SC consist of IPsec security associations
371708Sstevel * (SAs) needed to secure the communication between SC and Domain daemons
381708Sstevel * communicating using the Management Network (MAN).
391708Sstevel */
401708Sstevel
411708Sstevel #include <sys/types.h>
421708Sstevel #include <sys/cmn_err.h>
431708Sstevel #include <sys/kmem.h>
441708Sstevel #include <sys/errno.h>
451708Sstevel #include <sys/file.h>
461708Sstevel #include <sys/open.h>
471708Sstevel #include <sys/stat.h>
481708Sstevel #include <sys/conf.h>
491708Sstevel #include <sys/ddi.h>
501708Sstevel #include <sys/cmn_err.h>
511708Sstevel #include <sys/sunddi.h>
521708Sstevel #include <sys/sunndi.h>
531708Sstevel #include <sys/ddi_impldefs.h>
541708Sstevel #include <sys/ndi_impldefs.h>
551708Sstevel #include <sys/modctl.h>
561708Sstevel #include <sys/disp.h>
571708Sstevel #include <sys/async.h>
581708Sstevel #include <sys/mboxsc.h>
591708Sstevel #include <sys/sckm_msg.h>
601708Sstevel #include <sys/sckm_io.h>
611708Sstevel #include <sys/taskq.h>
621708Sstevel #include <sys/note.h>
631708Sstevel
641708Sstevel #ifdef DEBUG
651708Sstevel static uint_t sckm_debug_flags = 0x0;
661708Sstevel #define SCKM_DEBUG0(f, s) if ((f)& sckm_debug_flags) \
671708Sstevel cmn_err(CE_CONT, s)
681708Sstevel #define SCKM_DEBUG1(f, s, a) if ((f)& sckm_debug_flags) \
691708Sstevel cmn_err(CE_CONT, s, a)
701708Sstevel #define SCKM_DEBUG2(f, s, a, b) if ((f)& sckm_debug_flags) \
711708Sstevel cmn_err(CE_CONT, s, a, b)
721708Sstevel #define SCKM_DEBUG3(f, s, a, b, c) if ((f)& sckm_debug_flags) \
731708Sstevel cmn_err(CE_CONT, s, a, b, c)
741708Sstevel #define SCKM_DEBUG4(f, s, a, b, c, d) if ((f)& sckm_debug_flags) \
751708Sstevel cmn_err(CE_CONT, s, a, b, c, d)
761708Sstevel #define SCKM_DEBUG5(f, s, a, b, c, d, e) if ((f)& sckm_debug_flags) \
771708Sstevel cmn_err(CE_CONT, s, a, b, c, d, e)
781708Sstevel #define SCKM_DEBUG6(f, s, a, b, c, d, e, ff) if ((f)& sckm_debug_flags) \
791708Sstevel cmn_err(CE_CONT, s, a, b, c, d, e, ff)
801708Sstevel #else
811708Sstevel #define SCKM_DEBUG0(f, s)
821708Sstevel #define SCKM_DEBUG1(f, s, a)
831708Sstevel #define SCKM_DEBUG2(f, s, a, b)
841708Sstevel #define SCKM_DEBUG3(f, s, a, b, c)
851708Sstevel #define SCKM_DEBUG4(f, s, a, b, c, d)
861708Sstevel #define SCKM_DEBUG5(f, s, a, b, c, d, e)
871708Sstevel #define SCKM_DEBUG6(f, s, a, b, c, d, e, ff)
881708Sstevel #endif /* DEBUG */
891708Sstevel
901708Sstevel #define D_INIT 0x00000001 /* _init/_fini/_info */
911708Sstevel #define D_ATTACH 0x00000002 /* attach/detach */
921708Sstevel #define D_OPEN 0x00000008 /* open/close */
931708Sstevel #define D_IOCTL 0x00010000 /* ioctl */
941708Sstevel #define D_TASK 0x00100000 /* mailbox task processing */
951708Sstevel #define D_CALLBACK 0x00200000 /* mailbox callback */
961708Sstevel
971708Sstevel static int sckm_open(dev_t *, int, int, struct cred *);
981708Sstevel static int sckm_close(dev_t, int, int, struct cred *);
991708Sstevel static int sckm_ioctl(dev_t, int, intptr_t, int, struct cred *, int *);
1001708Sstevel
1011708Sstevel static struct cb_ops sckm_cb_ops = {
1021708Sstevel sckm_open, /* open */
1031708Sstevel sckm_close, /* close */
1041708Sstevel nodev, /* strategy */
1051708Sstevel nodev, /* print */
1061708Sstevel nodev, /* dump */
1071708Sstevel nodev, /* read */
1081708Sstevel nodev, /* write */
1091708Sstevel sckm_ioctl, /* ioctl */
1101708Sstevel nodev, /* devmap */
1111708Sstevel nodev, /* mmap */
1121708Sstevel nodev, /* segmap */
1131708Sstevel nochpoll, /* poll */
1141708Sstevel ddi_prop_op, /* prop_op */
1151708Sstevel 0, /* streamtab */
1161708Sstevel D_NEW | D_MP /* Driver compatibility flag */
1171708Sstevel };
1181708Sstevel
1191708Sstevel static int sckm_attach(dev_info_t *, ddi_attach_cmd_t);
1201708Sstevel static int sckm_detach(dev_info_t *, ddi_detach_cmd_t);
1211708Sstevel static int sckm_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
1221708Sstevel
1231708Sstevel static struct dev_ops sckm_ops = {
1241708Sstevel DEVO_REV, /* devo_rev, */
1251708Sstevel 0, /* refcnt */
1261708Sstevel sckm_info, /* get_dev_info */
1271708Sstevel nulldev, /* identify */
1281708Sstevel nulldev, /* probe */
1291708Sstevel sckm_attach, /* attach */
1301708Sstevel sckm_detach, /* detach */
1311708Sstevel nodev, /* reset */
1321708Sstevel &sckm_cb_ops, /* driver operations */
1337656SSherry.Moore@Sun.COM (struct bus_ops *)0, /* no bus operations */
1347656SSherry.Moore@Sun.COM NULL, /* power */
1357656SSherry.Moore@Sun.COM ddi_quiesce_not_needed, /* quiesce */
1361708Sstevel };
1371708Sstevel
1381708Sstevel static struct modldrv modldrv = {
1391708Sstevel &mod_driverops,
1407656SSherry.Moore@Sun.COM "Key Management Driver",
1411708Sstevel &sckm_ops,
1421708Sstevel };
1431708Sstevel
1441708Sstevel static struct modlinkage modlinkage = {
1451708Sstevel MODREV_1,
1461708Sstevel &modldrv,
1471708Sstevel NULL
1481708Sstevel };
1491708Sstevel
1501708Sstevel /*
1511708Sstevel * Private definitions.
1521708Sstevel */
1531708Sstevel #define SCKM_DEF_GETMSG_TIMEOUT 60 /* in seconds */
1541708Sstevel #define SCKM_DAEMON_TIMEOUT 4000000 /* in microseconds */
1551708Sstevel #define SCKM_NUM_TASKQ 2 /* # of task queue entries */
1561708Sstevel
1571708Sstevel /*
1581708Sstevel * For processing mailbox layer events.
1591708Sstevel */
1601708Sstevel static kmutex_t sckm_task_mutex;
1611708Sstevel static kmutex_t sckm_taskq_ptr_mutex;
1621708Sstevel static clock_t sckm_getmsg_timeout = SCKM_DEF_GETMSG_TIMEOUT*1000;
1631708Sstevel static taskq_t *sckm_taskq = NULL;
1641708Sstevel static sckm_mbox_req_hdr_t *req_data = NULL;
1651708Sstevel static sckm_mbox_rep_hdr_t *rep_data = NULL;
1661708Sstevel
1671708Sstevel
1681708Sstevel /*
1691708Sstevel * For synchronization with key management daemon.
1701708Sstevel */
1711708Sstevel static kmutex_t sckm_umutex;
1721708Sstevel static kcondvar_t sckm_udata_cv; /* daemon waits on data */
1731708Sstevel static kcondvar_t sckm_cons_cv; /* wait for daemon to consume data */
1741708Sstevel static boolean_t sckm_udata_req = B_FALSE; /* data available for daemon */
1751708Sstevel static sckm_ioctl_getreq_t sckm_udata; /* request for daemon */
1761708Sstevel static sckm_ioctl_status_t sckm_udata_status; /* status from daemon */
1771708Sstevel
1781708Sstevel /*
1791708Sstevel * Other misc private variables.
1801708Sstevel */
1811708Sstevel static dev_info_t *sckm_devi = NULL;
1821708Sstevel static boolean_t sckm_oflag = B_FALSE;
1831708Sstevel
1841708Sstevel /*
1851708Sstevel * Private functions prototypes.
1861708Sstevel */
1871708Sstevel static void sckm_mbox_callback(void);
1881708Sstevel static void sckm_mbox_task(void *arg);
1891708Sstevel static void sckm_process_msg(uint32_t cmd, uint64_t transid,
1901708Sstevel uint32_t len, sckm_mbox_req_hdr_t *req_data,
1911708Sstevel sckm_mbox_rep_hdr_t *rep_data);
1921708Sstevel
1931708Sstevel
1941708Sstevel int
_init(void)1951708Sstevel _init(void)
1961708Sstevel {
1971708Sstevel mboxsc_timeout_range_t timeout_range;
1981708Sstevel int ret;
1991708Sstevel
2001708Sstevel SCKM_DEBUG0(D_INIT, "in _init");
2011708Sstevel
2021708Sstevel /*
2031708Sstevel * Initialize outgoing mailbox (KDSC)
2041708Sstevel */
2051708Sstevel if ((ret = mboxsc_init(KEY_KDSC, MBOXSC_MBOX_OUT, NULL)) != 0) {
2061708Sstevel cmn_err(CE_WARN, "failed initializing outgoing mailbox "
2071708Sstevel "(%d)", ret);
2081708Sstevel return (ret);
2091708Sstevel }
2101708Sstevel
2111708Sstevel /*
2121708Sstevel * Initialize incoming mailbox (SCKD)
2131708Sstevel */
2141708Sstevel if ((ret = mboxsc_init(KEY_SCKD, MBOXSC_MBOX_IN,
2151708Sstevel sckm_mbox_callback)) != 0) {
2161708Sstevel cmn_err(CE_WARN, "failed initializing incoming mailbox "
2171708Sstevel "(%d)\n", ret);
218*11311SSurya.Prakki@Sun.COM (void) mboxsc_fini(KEY_KDSC);
2191708Sstevel return (ret);
2201708Sstevel }
2211708Sstevel
2221708Sstevel if ((ret = mboxsc_ctrl(KEY_SCKD, MBOXSC_CMD_GETMSG_TIMEOUT_RANGE,
2231708Sstevel (void *)&timeout_range)) != 0) {
224*11311SSurya.Prakki@Sun.COM (void) mboxsc_fini(KEY_SCKD);
225*11311SSurya.Prakki@Sun.COM (void) mboxsc_fini(KEY_KDSC);
2261708Sstevel return (ret);
2271708Sstevel }
2281708Sstevel
2291708Sstevel if (sckm_getmsg_timeout < timeout_range.min_timeout) {
2301708Sstevel sckm_getmsg_timeout = timeout_range.min_timeout;
2311708Sstevel cmn_err(CE_WARN, "resetting getmsg timeout to %lx",
2321708Sstevel sckm_getmsg_timeout);
2331708Sstevel }
2341708Sstevel
2351708Sstevel if (sckm_getmsg_timeout > timeout_range.max_timeout) {
2361708Sstevel sckm_getmsg_timeout = timeout_range.max_timeout;
2371708Sstevel cmn_err(CE_WARN, "resetting getmsg timeout to %lx",
2381708Sstevel sckm_getmsg_timeout);
2391708Sstevel }
2401708Sstevel
2411708Sstevel if ((ret = mod_install(&modlinkage)) != 0) {
242*11311SSurya.Prakki@Sun.COM (void) mboxsc_fini(KEY_KDSC);
243*11311SSurya.Prakki@Sun.COM (void) mboxsc_fini(KEY_SCKD);
2441708Sstevel return (ret);
2451708Sstevel }
2461708Sstevel
2471708Sstevel /*
2481708Sstevel * Initialize variables needed for synchronization with daemon.
2491708Sstevel */
2501708Sstevel sckm_udata.buf = kmem_alloc(SCKM_SCKD_MAXDATA, KM_SLEEP);
2511708Sstevel req_data = (sckm_mbox_req_hdr_t *)kmem_alloc(SCKM_SCKD_MAXDATA,
2521708Sstevel KM_SLEEP);
2531708Sstevel rep_data = (sckm_mbox_rep_hdr_t *)kmem_alloc(SCKM_KDSC_MAXDATA,
2541708Sstevel KM_SLEEP);
2551708Sstevel
2561708Sstevel if ((sckm_udata.buf == NULL) || (req_data == NULL) ||
2571708Sstevel (rep_data == NULL)) {
2581708Sstevel cmn_err(CE_WARN, "not enough memory during _init");
2591708Sstevel
2601708Sstevel /* free what was successfully allocated */
2611708Sstevel if (sckm_udata.buf != NULL)
2621708Sstevel kmem_free(sckm_udata.buf, SCKM_SCKD_MAXDATA);
2631708Sstevel if (req_data != NULL)
2641708Sstevel kmem_free(req_data, SCKM_SCKD_MAXDATA);
2651708Sstevel if (rep_data != NULL)
2661708Sstevel kmem_free(rep_data, SCKM_KDSC_MAXDATA);
2671708Sstevel sckm_udata.buf = NULL;
2681708Sstevel req_data = NULL;
2691708Sstevel rep_data = NULL;
2701708Sstevel
2711708Sstevel /* uninitialize mailboxes, remove module, and return error */
272*11311SSurya.Prakki@Sun.COM (void) mboxsc_fini(KEY_KDSC);
273*11311SSurya.Prakki@Sun.COM (void) mboxsc_fini(KEY_SCKD);
274*11311SSurya.Prakki@Sun.COM (void) mod_remove(&modlinkage);
2751708Sstevel return (-1);
2761708Sstevel }
2771708Sstevel
2781708Sstevel cv_init(&sckm_udata_cv, NULL, CV_DRIVER, NULL);
2791708Sstevel cv_init(&sckm_cons_cv, NULL, CV_DRIVER, NULL);
2801708Sstevel mutex_init(&sckm_umutex, NULL, MUTEX_DRIVER, NULL);
2811708Sstevel
2821708Sstevel /*
2831708Sstevel * Create mutex for task processing, protection of taskq
2841708Sstevel * pointer, and create taskq.
2851708Sstevel */
2861708Sstevel mutex_init(&sckm_task_mutex, NULL, MUTEX_DRIVER, NULL);
2871708Sstevel mutex_init(&sckm_taskq_ptr_mutex, NULL, MUTEX_DRIVER, NULL);
2881708Sstevel sckm_taskq = taskq_create("sckm_taskq", 1, minclsyspri,
2891708Sstevel SCKM_NUM_TASKQ, SCKM_NUM_TASKQ, TASKQ_PREPOPULATE);
2901708Sstevel
2911708Sstevel SCKM_DEBUG1(D_INIT, "out _init ret=%d\n", ret);
2921708Sstevel return (ret);
2931708Sstevel }
2941708Sstevel
2951708Sstevel int
_fini(void)2961708Sstevel _fini(void)
2971708Sstevel {
2981708Sstevel int ret;
2991708Sstevel
3001708Sstevel SCKM_DEBUG0(D_INIT, "in _fini");
3011708Sstevel
3021708Sstevel if ((ret = mod_remove(&modlinkage)) != 0) {
3031708Sstevel return (ret);
3041708Sstevel }
3051708Sstevel
3061708Sstevel /*
3071708Sstevel * Wait for scheduled tasks to complete, then destroy task queue.
3081708Sstevel */
3091708Sstevel mutex_enter(&sckm_taskq_ptr_mutex);
3101708Sstevel if (sckm_taskq != NULL) {
3111708Sstevel taskq_destroy(sckm_taskq);
3121708Sstevel sckm_taskq = NULL;
3131708Sstevel }
3141708Sstevel mutex_exit(&sckm_taskq_ptr_mutex);
3151708Sstevel
3161708Sstevel /*
3171708Sstevel * Terminate incoming and outgoing IOSRAM mailboxes
3181708Sstevel */
319*11311SSurya.Prakki@Sun.COM (void) mboxsc_fini(KEY_KDSC);
320*11311SSurya.Prakki@Sun.COM (void) mboxsc_fini(KEY_SCKD);
3211708Sstevel
3221708Sstevel /*
3231708Sstevel * Destroy module synchronization objects and free memory
3241708Sstevel */
3251708Sstevel mutex_destroy(&sckm_task_mutex);
3261708Sstevel mutex_destroy(&sckm_taskq_ptr_mutex);
3271708Sstevel mutex_destroy(&sckm_umutex);
3281708Sstevel cv_destroy(&sckm_cons_cv);
3291708Sstevel
3301708Sstevel if (sckm_udata.buf != NULL) {
3311708Sstevel kmem_free(sckm_udata.buf, SCKM_SCKD_MAXDATA);
3321708Sstevel sckm_udata.buf = NULL;
3331708Sstevel }
3341708Sstevel if (rep_data != NULL) {
3351708Sstevel kmem_free(rep_data, SCKM_KDSC_MAXDATA);
3361708Sstevel rep_data = NULL;
3371708Sstevel }
3381708Sstevel if (req_data != NULL) {
3391708Sstevel kmem_free(req_data, SCKM_SCKD_MAXDATA);
3401708Sstevel req_data = NULL;
3411708Sstevel }
3421708Sstevel
3431708Sstevel return (ret);
3441708Sstevel }
3451708Sstevel
3461708Sstevel int
_info(struct modinfo * modinfop)3471708Sstevel _info(struct modinfo *modinfop)
3481708Sstevel {
3491708Sstevel SCKM_DEBUG0(D_INIT, "in _info");
3501708Sstevel return (mod_info(&modlinkage, modinfop));
3511708Sstevel }
3521708Sstevel
3531708Sstevel static int
sckm_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)3541708Sstevel sckm_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
3551708Sstevel {
3561708Sstevel SCKM_DEBUG1(D_ATTACH, "in sckm_attach, cmd=%d", cmd);
3571708Sstevel
3581708Sstevel switch (cmd) {
3591708Sstevel case DDI_ATTACH:
3601708Sstevel SCKM_DEBUG0(D_ATTACH, "sckm_attach: DDI_ATTACH");
3611708Sstevel if (ddi_create_minor_node(devi, "sckmdrv", S_IFCHR,
3621708Sstevel 0, NULL, NULL) == DDI_FAILURE) {
3631708Sstevel cmn_err(CE_WARN, "ddi_create_minor_node failed");
3641708Sstevel ddi_remove_minor_node(devi, NULL);
3651708Sstevel return (DDI_FAILURE);
3661708Sstevel }
3671708Sstevel sckm_devi = devi;
3681708Sstevel break;
3691708Sstevel case DDI_SUSPEND:
3701708Sstevel SCKM_DEBUG0(D_ATTACH, "sckm_attach: DDI_SUSPEND");
3711708Sstevel break;
3721708Sstevel default:
3731708Sstevel cmn_err(CE_WARN, "sckm_attach: bad cmd %d\n", cmd);
3741708Sstevel return (DDI_FAILURE);
3751708Sstevel }
3761708Sstevel
3771708Sstevel SCKM_DEBUG0(D_ATTACH, "out sckm_attach (DDI_SUCCESS)");
3781708Sstevel return (DDI_SUCCESS);
3791708Sstevel }
3801708Sstevel
3811708Sstevel static int
sckm_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)3821708Sstevel sckm_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
3831708Sstevel {
3841708Sstevel SCKM_DEBUG1(D_ATTACH, "in sckm_detach, cmd=%d", cmd);
3851708Sstevel
3861708Sstevel switch (cmd) {
3871708Sstevel case DDI_DETACH:
3881708Sstevel SCKM_DEBUG0(D_ATTACH, "sckm_detach: DDI_DETACH");
3891708Sstevel ddi_remove_minor_node(devi, NULL);
3901708Sstevel break;
3911708Sstevel case DDI_SUSPEND:
3921708Sstevel SCKM_DEBUG0(D_ATTACH, "sckm_detach: DDI_DETACH");
3931708Sstevel break;
3941708Sstevel default:
3951708Sstevel cmn_err(CE_WARN, "sckm_detach: bad cmd %d\n", cmd);
3961708Sstevel return (DDI_FAILURE);
3971708Sstevel }
3981708Sstevel
3991708Sstevel SCKM_DEBUG0(D_ATTACH, "out sckm_detach (DDI_SUCCESS)");
4001708Sstevel return (DDI_SUCCESS);
4011708Sstevel }
4021708Sstevel
4031708Sstevel /* ARGSUSED */
4041708Sstevel static int
sckm_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)4051708Sstevel sckm_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
4061708Sstevel void **result)
4071708Sstevel {
4081708Sstevel int rv;
4091708Sstevel
4101708Sstevel SCKM_DEBUG1(D_ATTACH, "in sckm_info, infocmd=%d", infocmd);
4111708Sstevel
4121708Sstevel switch (infocmd) {
4131708Sstevel case DDI_INFO_DEVT2DEVINFO:
4141708Sstevel *result = (void *)sckm_devi;
4151708Sstevel rv = DDI_SUCCESS;
4161708Sstevel break;
4171708Sstevel case DDI_INFO_DEVT2INSTANCE:
4181708Sstevel *result = (void *)0;
4191708Sstevel rv = DDI_SUCCESS;
4201708Sstevel break;
4211708Sstevel default:
4221708Sstevel rv = DDI_FAILURE;
4231708Sstevel }
4241708Sstevel
4251708Sstevel SCKM_DEBUG1(D_ATTACH, "out sckm_info, rv=%d", rv);
4261708Sstevel return (rv);
4271708Sstevel }
4281708Sstevel
4291708Sstevel /*ARGSUSED*/
4301708Sstevel static int
sckm_open(dev_t * devp,int flag,int otyp,struct cred * cred)4311708Sstevel sckm_open(dev_t *devp, int flag, int otyp, struct cred *cred)
4321708Sstevel {
4331708Sstevel SCKM_DEBUG0(D_OPEN, "in sckm_open");
4341708Sstevel
4351708Sstevel /* check credentials of calling process */
4361708Sstevel if (drv_priv(cred)) {
4371708Sstevel SCKM_DEBUG0(D_OPEN, "sckm_open: attempt by non-root proc");
4381708Sstevel return (EPERM);
4391708Sstevel }
4401708Sstevel
4411708Sstevel /* enforce exclusive access */
4421708Sstevel mutex_enter(&sckm_umutex);
4431708Sstevel if (sckm_oflag == B_TRUE) {
4441708Sstevel SCKM_DEBUG0(D_OPEN, "sckm_open: already open");
4451708Sstevel mutex_exit(&sckm_umutex);
4461708Sstevel return (EBUSY);
4471708Sstevel }
4481708Sstevel sckm_oflag = B_TRUE;
4491708Sstevel mutex_exit(&sckm_umutex);
4501708Sstevel
4511708Sstevel SCKM_DEBUG0(D_OPEN, "sckm_open: succcess");
4521708Sstevel return (0);
4531708Sstevel }
4541708Sstevel
4551708Sstevel /*ARGSUSED*/
4561708Sstevel static int
sckm_close(dev_t dev,int flag,int otyp,struct cred * cred)4571708Sstevel sckm_close(dev_t dev, int flag, int otyp, struct cred *cred)
4581708Sstevel {
4591708Sstevel SCKM_DEBUG0(D_OPEN, "in sckm_close");
4601708Sstevel
4611708Sstevel mutex_enter(&sckm_umutex);
4621708Sstevel sckm_oflag = B_FALSE;
4631708Sstevel mutex_exit(&sckm_umutex);
4641708Sstevel
4651708Sstevel return (0);
4661708Sstevel }
4671708Sstevel
4681708Sstevel
4691708Sstevel static int
sckm_copyin_ioctl_getreq(intptr_t userarg,sckm_ioctl_getreq_t * driverarg,int flag)4701708Sstevel sckm_copyin_ioctl_getreq(intptr_t userarg, sckm_ioctl_getreq_t *driverarg,
4711708Sstevel int flag)
4721708Sstevel {
4731708Sstevel #ifdef _MULTI_DATAMODEL
4741708Sstevel switch (ddi_model_convert_from(flag & FMODELS)) {
4751708Sstevel case DDI_MODEL_ILP32: {
4761708Sstevel sckm_ioctl_getreq32_t driverarg32;
4771708Sstevel if (ddi_copyin((caddr_t)userarg, &driverarg32,
4781708Sstevel sizeof (sckm_ioctl_getreq32_t), flag)) {
4791708Sstevel return (EFAULT);
4801708Sstevel }
4811708Sstevel driverarg->transid = driverarg32.transid;
4821708Sstevel driverarg->type = driverarg32.type;
4831708Sstevel driverarg->buf = (caddr_t)(uintptr_t)driverarg32.buf;
4841708Sstevel driverarg->buf_len = driverarg32.buf_len;
4851708Sstevel break;
4861708Sstevel }
4871708Sstevel case DDI_MODEL_NONE: {
4881708Sstevel if (ddi_copyin((caddr_t)userarg, &driverarg,
4891708Sstevel sizeof (sckm_ioctl_getreq_t), flag)) {
4901708Sstevel return (EFAULT);
4911708Sstevel }
4921708Sstevel break;
4931708Sstevel }
4941708Sstevel }
4951708Sstevel #else /* ! _MULTI_DATAMODEL */
4961708Sstevel if (ddi_copyin((caddr_t)userarg, &driverarg,
4971708Sstevel sizeof (sckm_ioctl_getreq_t), flag)) {
4981708Sstevel return (EFAULT);
4991708Sstevel }
5001708Sstevel #endif /* _MULTI_DATAMODEL */
5011708Sstevel return (0);
5021708Sstevel }
5031708Sstevel
5041708Sstevel
5051708Sstevel static int
sckm_copyout_ioctl_getreq(sckm_ioctl_getreq_t * driverarg,intptr_t userarg,int flag)5061708Sstevel sckm_copyout_ioctl_getreq(sckm_ioctl_getreq_t *driverarg, intptr_t userarg,
5071708Sstevel int flag)
5081708Sstevel {
5091708Sstevel #ifdef _MULTI_DATAMODEL
5101708Sstevel switch (ddi_model_convert_from(flag & FMODELS)) {
5111708Sstevel case DDI_MODEL_ILP32: {
5121708Sstevel sckm_ioctl_getreq32_t driverarg32;
5131708Sstevel driverarg32.transid = driverarg->transid;
5141708Sstevel driverarg32.type = driverarg->type;
5151708Sstevel driverarg32.buf = (caddr32_t)(uintptr_t)driverarg->buf;
5161708Sstevel driverarg32.buf_len = driverarg->buf_len;
5171708Sstevel if (ddi_copyout(&driverarg32, (caddr_t)userarg,
5181708Sstevel sizeof (sckm_ioctl_getreq32_t), flag)) {
5191708Sstevel return (EFAULT);
5201708Sstevel }
5211708Sstevel break;
5221708Sstevel }
5231708Sstevel case DDI_MODEL_NONE:
5241708Sstevel if (ddi_copyout(driverarg, (caddr_t)userarg,
5251708Sstevel sizeof (sckm_ioctl_getreq_t), flag)) {
5261708Sstevel return (EFAULT);
5271708Sstevel }
5281708Sstevel break;
5291708Sstevel }
5301708Sstevel #else /* ! _MULTI_DATAMODEL */
5311708Sstevel if (ddi_copyout(driverarg, (caddr_t)userarg,
5321708Sstevel sizeof (sckm_ioctl_getreq_t), flag)) {
5331708Sstevel return (EFAULT);
5341708Sstevel }
5351708Sstevel #endif /* _MULTI_DATAMODEL */
5361708Sstevel return (0);
5371708Sstevel }
5381708Sstevel
5391708Sstevel
5401708Sstevel /*ARGSUSED*/
5411708Sstevel static int
sckm_ioctl(dev_t dev,int cmd,intptr_t data,int flag,cred_t * cred,int * rvalp)5421708Sstevel sckm_ioctl(dev_t dev, int cmd, intptr_t data, int flag,
5431708Sstevel cred_t *cred, int *rvalp)
5441708Sstevel {
5451708Sstevel int rval = 0;
5461708Sstevel
5471708Sstevel SCKM_DEBUG0(D_IOCTL, "in sckm_ioctl");
5481708Sstevel
5491708Sstevel switch (cmd) {
5501708Sstevel case SCKM_IOCTL_GETREQ: {
5511708Sstevel sckm_ioctl_getreq_t arg;
5521708Sstevel
5531708Sstevel SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: got SCKM_IOCTL_GETREQ");
5541708Sstevel if (sckm_copyin_ioctl_getreq(data, &arg, flag)) {
5551708Sstevel return (EFAULT);
5561708Sstevel }
5571708Sstevel
5581708Sstevel /* sanity check argument */
5591708Sstevel if (arg.buf_len < SCKM_SCKD_MAXDATA) {
5601708Sstevel SCKM_DEBUG2(D_IOCTL, "sckm_ioctl: usr buffer too "
5611708Sstevel "small (%d < %d)", arg.buf_len, SCKM_SCKD_MAXDATA);
5621708Sstevel return (ENOSPC);
5631708Sstevel }
5641708Sstevel
5651708Sstevel mutex_enter(&sckm_umutex);
5661708Sstevel
5671708Sstevel /* wait for request from SC */
5681708Sstevel while (!sckm_udata_req) {
5691708Sstevel SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: waiting for msg");
5701708Sstevel if (cv_wait_sig(&sckm_udata_cv, &sckm_umutex) == 0) {
5711708Sstevel mutex_exit(&sckm_umutex);
5721708Sstevel return (EINTR);
5731708Sstevel }
5741708Sstevel }
5751708Sstevel SCKM_DEBUG1(D_IOCTL, "sckm_ioctl: msg available "
5767656SSherry.Moore@Sun.COM "transid = 0x%lx", sckm_udata.transid);
5771708Sstevel
5781708Sstevel arg.transid = sckm_udata.transid;
5791708Sstevel arg.type = sckm_udata.type;
5801708Sstevel if (ddi_copyout(sckm_udata.buf, arg.buf,
5811708Sstevel sckm_udata.buf_len, flag)) {
5821708Sstevel mutex_exit(&sckm_umutex);
5831708Sstevel return (EFAULT);
5841708Sstevel }
5851708Sstevel arg.buf_len = sckm_udata.buf_len;
5861708Sstevel
5871708Sstevel mutex_exit(&sckm_umutex);
5881708Sstevel if (sckm_copyout_ioctl_getreq(&arg, data, flag)) {
5891708Sstevel return (EFAULT);
5901708Sstevel }
5911708Sstevel break;
5921708Sstevel }
5931708Sstevel case SCKM_IOCTL_STATUS: {
5941708Sstevel sckm_ioctl_status_t arg;
5951708Sstevel SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: got SCKM_IOCTL_STATUS");
5961708Sstevel if (ddi_copyin((caddr_t)data, &arg,
5971708Sstevel sizeof (sckm_ioctl_status_t), flag)) {
5981708Sstevel cmn_err(CE_WARN, "sckm_ioctl: ddi_copyin failed");
5991708Sstevel return (EFAULT);
6001708Sstevel }
6011708Sstevel SCKM_DEBUG3(D_IOCTL, "sckm_ioctl: arg transid=0x%lx, "
6021708Sstevel "status=%d, sadb_msg_errno=%d", arg.transid, arg.status,
6031708Sstevel arg.sadb_msg_errno);
6041708Sstevel
6051708Sstevel mutex_enter(&sckm_umutex);
6061708Sstevel
6071708Sstevel /* fail if no status is expected, or if it does not match */
6081708Sstevel if (!sckm_udata_req || sckm_udata.transid != arg.transid) {
6091708Sstevel mutex_exit(&sckm_umutex);
6101708Sstevel return (EINVAL);
6111708Sstevel }
6121708Sstevel
6131708Sstevel /* update status information for event handler */
6141708Sstevel bcopy(&arg, &sckm_udata_status, sizeof (sckm_ioctl_status_t));
6151708Sstevel
6161708Sstevel /* signal event handler that request has been processed */
6171708Sstevel SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: signaling event handler"
6181708Sstevel " that data has been processed");
6191708Sstevel cv_signal(&sckm_cons_cv);
6201708Sstevel sckm_udata_req = B_FALSE;
6211708Sstevel
6221708Sstevel mutex_exit(&sckm_umutex);
6231708Sstevel break;
6241708Sstevel }
6251708Sstevel default:
6261708Sstevel SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: unknown command");
6271708Sstevel rval = EINVAL;
6281708Sstevel }
6291708Sstevel
6301708Sstevel SCKM_DEBUG1(D_IOCTL, "out sckm_ioctl, rval=%d", rval);
6311708Sstevel return (rval);
6321708Sstevel }
6331708Sstevel
6341708Sstevel
6351708Sstevel /*
6361708Sstevel * sckm_mbox_callback
6371708Sstevel *
6381708Sstevel * Callback routine registered with the IOSRAM mailbox protocol driver.
6391708Sstevel * Invoked when a message is received on the mailbox.
6401708Sstevel */
6411708Sstevel static void
sckm_mbox_callback(void)6421708Sstevel sckm_mbox_callback(void)
6431708Sstevel {
6441708Sstevel SCKM_DEBUG0(D_CALLBACK, "in sckm_mbox_callback()");
6451708Sstevel
6461708Sstevel mutex_enter(&sckm_taskq_ptr_mutex);
6471708Sstevel
6481708Sstevel if (sckm_taskq == NULL) {
6491708Sstevel mutex_exit(&sckm_taskq_ptr_mutex);
6501708Sstevel return;
6511708Sstevel }
6521708Sstevel
6531708Sstevel if (!taskq_dispatch(sckm_taskq, sckm_mbox_task, NULL, KM_NOSLEEP)) {
6541708Sstevel /*
6551708Sstevel * Too many tasks already pending. Do not queue a new
6561708Sstevel * request.
6571708Sstevel */
6581708Sstevel SCKM_DEBUG0(D_CALLBACK, "failed dispatching task");
6591708Sstevel }
6601708Sstevel
6611708Sstevel mutex_exit(&sckm_taskq_ptr_mutex);
6621708Sstevel
6631708Sstevel SCKM_DEBUG0(D_CALLBACK, "out sckm_mbox_callback()");
6641708Sstevel }
6651708Sstevel
6661708Sstevel
6671708Sstevel /*
6681708Sstevel * sckm_mbox_task
6691708Sstevel *
6701708Sstevel * Dispatched on taskq from the IOSRAM mailbox callback
6711708Sstevel * sckm_mbox_callback when a message is received on the incoming
6721708Sstevel * mailbox.
6731708Sstevel */
6741708Sstevel static void
sckm_mbox_task(void * ignored)6751708Sstevel sckm_mbox_task(void *ignored)
6761708Sstevel {
6771708Sstevel _NOTE(ARGUNUSED(ignored))
6781708Sstevel uint32_t type, cmd, length;
6791708Sstevel uint64_t transid;
6801708Sstevel int rval;
6811708Sstevel
6821708Sstevel SCKM_DEBUG0(D_TASK, "in sckm_mbox_task\n");
6831708Sstevel
6841708Sstevel mutex_enter(&sckm_task_mutex);
6851708Sstevel
6861708Sstevel if (req_data == NULL || rep_data == NULL) {
6871708Sstevel SCKM_DEBUG0(D_TASK, "sckm_mbox_task: no buffers");
6881708Sstevel mutex_exit(&sckm_task_mutex);
6891708Sstevel return;
6901708Sstevel }
6911708Sstevel
6921708Sstevel /*
6931708Sstevel * Get mailbox message.
6941708Sstevel */
6951708Sstevel
6961708Sstevel type = MBOXSC_MSG_REQUEST;
6971708Sstevel length = SCKM_SCKD_MAXDATA;
6981708Sstevel cmd = 0;
6991708Sstevel transid = 0;
7001708Sstevel
7011708Sstevel SCKM_DEBUG0(D_TASK, "sckm_mbox_task: "
7021708Sstevel "calling mboxsc_getmsg()\n");
7031708Sstevel rval = mboxsc_getmsg(KEY_SCKD, &type, &cmd, &transid,
7041708Sstevel &length, req_data, sckm_getmsg_timeout);
7051708Sstevel
7061708Sstevel if (rval != 0) {
7071708Sstevel SCKM_DEBUG1(D_TASK, "sckm_mbox_task: "
7081708Sstevel "mboxsc_getmsg() failed (%d)\n", rval);
7091708Sstevel mutex_exit(&sckm_task_mutex);
7101708Sstevel return;
7111708Sstevel }
7121708Sstevel
7131708Sstevel SCKM_DEBUG4(D_TASK, "sckm_mbox_task: "
7141708Sstevel "type=0x%x cmd=0x%x length=%d transid=0x%lx\n",
7151708Sstevel type, cmd, length, transid);
7161708Sstevel
7171708Sstevel /* check message length */
7181708Sstevel if (length < sizeof (sckm_mbox_req_hdr_t)) {
7191708Sstevel /* protocol error, drop message */
7201708Sstevel SCKM_DEBUG2(D_TASK, "received short "
7211708Sstevel "message of length %d, min %lu",
7221708Sstevel length, sizeof (sckm_mbox_req_hdr_t));
7231708Sstevel mutex_exit(&sckm_task_mutex);
7241708Sstevel return;
7251708Sstevel }
7261708Sstevel
7271708Sstevel /* check version of message received */
7281708Sstevel if (req_data->sckm_version != SCKM_PROTOCOL_VERSION) {
7291708Sstevel SCKM_DEBUG2(D_TASK, "received protocol "
7301708Sstevel "version %d, expected %d",
7311708Sstevel req_data->sckm_version, SCKM_PROTOCOL_VERSION);
7321708Sstevel /*
7331708Sstevel * Send reply with SCKM_SADB_ERR_VERSION error
7341708Sstevel * so that SC can adopt correct protocol version
7351708Sstevel * for this domain.
7361708Sstevel */
7371708Sstevel rep_data->sckm_version = SCKM_PROTOCOL_VERSION;
7381708Sstevel rep_data->status = SCKM_ERR_VERSION;
7391708Sstevel
7401708Sstevel rval = mboxsc_putmsg(KEY_KDSC, MBOXSC_MSG_REPLY,
7411708Sstevel cmd, &transid, sizeof (sckm_mbox_rep_hdr_t),
7421708Sstevel rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT);
7431708Sstevel
7441708Sstevel if (rval != 0) {
7451708Sstevel SCKM_DEBUG1(D_TASK, "sckm_mbox_task: "
7461708Sstevel "mboxsc_putmsg() failed (%d)\n", rval);
7471708Sstevel mutex_exit(&sckm_task_mutex);
7481708Sstevel return;
7491708Sstevel }
7501708Sstevel }
7511708Sstevel
7521708Sstevel /* process message */
7531708Sstevel sckm_process_msg(cmd, transid, length,
7541708Sstevel req_data, rep_data);
7551708Sstevel
7561708Sstevel mutex_exit(&sckm_task_mutex);
7571708Sstevel }
7581708Sstevel
7591708Sstevel /*
7601708Sstevel * sckm_process_msg
7611708Sstevel *
7621708Sstevel * Process a message received from the SC. Invoked by sckm_event_task().
7631708Sstevel */
7641708Sstevel static void
sckm_process_msg(uint32_t cmd,uint64_t transid,uint32_t len,sckm_mbox_req_hdr_t * req_data,sckm_mbox_rep_hdr_t * rep_data)7651708Sstevel sckm_process_msg(uint32_t cmd, uint64_t transid,
7661708Sstevel uint32_t len, sckm_mbox_req_hdr_t *req_data,
7671708Sstevel sckm_mbox_rep_hdr_t *rep_data)
7681708Sstevel {
7691708Sstevel int rv;
7701708Sstevel
7711708Sstevel mutex_enter(&sckm_umutex);
7721708Sstevel
7731708Sstevel switch (cmd) {
7741708Sstevel case SCKM_MSG_SADB: {
7751708Sstevel int sadb_msglen;
7761708Sstevel
7771708Sstevel sadb_msglen = len-sizeof (sckm_mbox_req_hdr_t);
7781708Sstevel SCKM_DEBUG1(D_TASK, "received SCKM_MSG_SADB len=%d",
7791708Sstevel sadb_msglen);
7801708Sstevel
7811708Sstevel /* sanity check request */
7821708Sstevel if (len-sizeof (sckm_mbox_req_hdr_t) <= 0) {
7831708Sstevel SCKM_DEBUG0(D_TASK, "bad SADB message, "
7841708Sstevel "zero length");
7851708Sstevel /*
7861708Sstevel * SADB message is too short, send corresponding
7871708Sstevel * error message to SC.
7881708Sstevel */
7891708Sstevel rep_data->sckm_version = SCKM_PROTOCOL_VERSION;
7901708Sstevel rep_data->status = SCKM_ERR_SADB_MSG;
7911708Sstevel
7921708Sstevel if ((rv = mboxsc_putmsg(KEY_KDSC, MBOXSC_MSG_REPLY,
7931708Sstevel cmd, &transid, sizeof (sckm_mbox_rep_hdr_t),
7941708Sstevel rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT)) != 0) {
7951708Sstevel SCKM_DEBUG1(D_TASK, "sckm_mbox_task: "
7961708Sstevel "mboxsc_putmsg() failed (%d)\n", rv);
7971708Sstevel }
7981708Sstevel mutex_exit(&sckm_umutex);
7991708Sstevel return;
8001708Sstevel }
8011708Sstevel
8021708Sstevel /* initialize request for daemon */
8031708Sstevel sckm_udata.transid = transid;
8041708Sstevel sckm_udata.type = SCKM_IOCTL_REQ_SADB;
8051708Sstevel sckm_udata.buf_len = len-sizeof (sckm_mbox_req_hdr_t);
8061708Sstevel bcopy(req_data+1, sckm_udata.buf, sckm_udata.buf_len);
8071708Sstevel
8081708Sstevel break;
8091708Sstevel }
8101708Sstevel default:
8111708Sstevel cmn_err(CE_WARN, "unknown cmd %x received from SC", cmd);
8121708Sstevel /*
8131708Sstevel * Received unknown command from SC. Send corresponding
8141708Sstevel * error message to SC.
8151708Sstevel */
8161708Sstevel rep_data->sckm_version = SCKM_PROTOCOL_VERSION;
8171708Sstevel rep_data->status = SCKM_ERR_BAD_CMD;
8181708Sstevel
8191708Sstevel if ((rv = mboxsc_putmsg(KEY_KDSC, MBOXSC_MSG_REPLY,
8201708Sstevel cmd, &transid, sizeof (sckm_mbox_rep_hdr_t),
8211708Sstevel rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT)) != 0) {
8221708Sstevel SCKM_DEBUG1(D_TASK, "sckm_mbox_task: "
8231708Sstevel "mboxsc_putmsg() failed (%d)\n", rv);
8241708Sstevel }
8251708Sstevel mutex_exit(&sckm_umutex);
8261708Sstevel return;
8271708Sstevel }
8281708Sstevel
8291708Sstevel /*
8301708Sstevel * At this point, we know that the request is valid, so pass
8311708Sstevel * the request to the daemon.
8321708Sstevel */
8331708Sstevel SCKM_DEBUG0(D_TASK, "waking up daemon");
8341708Sstevel sckm_udata_req = B_TRUE;
8351708Sstevel cv_signal(&sckm_udata_cv);
8361708Sstevel
8371708Sstevel /* wait for daemon to process request */
83811066Srafael.vanoni@sun.com if (cv_reltimedwait(&sckm_cons_cv, &sckm_umutex,
83911066Srafael.vanoni@sun.com drv_usectohz(SCKM_DAEMON_TIMEOUT), TR_CLOCK_TICK) == -1) {
8401708Sstevel /*
8411708Sstevel * Daemon did not process the data, report this
8421708Sstevel * error to the SC.
8431708Sstevel */
8441708Sstevel SCKM_DEBUG0(D_TASK, "daemon timeout!!");
8451708Sstevel rep_data->sckm_version = SCKM_PROTOCOL_VERSION;
8461708Sstevel rep_data->status = SCKM_ERR_DAEMON;
8471708Sstevel } else {
8481708Sstevel /* Daemon processed data, return status to SC */
8491708Sstevel SCKM_DEBUG0(D_TASK, "daemon processed data");
8501708Sstevel rep_data->sckm_version = SCKM_PROTOCOL_VERSION;
8511708Sstevel switch (sckm_udata_status.status) {
8521708Sstevel case SCKM_IOCTL_STAT_SUCCESS:
8531708Sstevel SCKM_DEBUG0(D_TASK, "daemon returned success");
8541708Sstevel rep_data->status = SCKM_SUCCESS;
8551708Sstevel break;
8561708Sstevel case SCKM_IOCTL_STAT_ERR_PFKEY:
8571708Sstevel SCKM_DEBUG1(D_TASK, "daemon returned PF_KEY "
8581708Sstevel "error, errno=%d",
8591708Sstevel sckm_udata_status.sadb_msg_errno);
8601708Sstevel rep_data->status = SCKM_ERR_SADB_PFKEY;
8611708Sstevel rep_data->sadb_msg_errno =
8621708Sstevel sckm_udata_status.sadb_msg_errno;
8631708Sstevel break;
8641708Sstevel case SCKM_IOCTL_STAT_ERR_REQ:
8651708Sstevel SCKM_DEBUG0(D_TASK, "daemon returned "
8661708Sstevel "bad request");
8671708Sstevel rep_data->status = SCKM_ERR_DAEMON;
8681708Sstevel break;
8691708Sstevel case SCKM_IOCTL_STAT_ERR_VERSION:
8701708Sstevel SCKM_DEBUG0(D_TASK, "PF_KEY version not "
8711708Sstevel "supported");
8721708Sstevel rep_data->status = SCKM_ERR_SADB_VERSION;
8731708Sstevel rep_data->sadb_msg_version =
8741708Sstevel sckm_udata_status.sadb_msg_version;
8751708Sstevel break;
8761708Sstevel case SCKM_IOCTL_STAT_ERR_TIMEOUT:
8771708Sstevel SCKM_DEBUG0(D_TASK, "no response received "
8781708Sstevel "from key engine");
8791708Sstevel rep_data->status = SCKM_ERR_SADB_TIMEOUT;
8801708Sstevel break;
8811708Sstevel case SCKM_IOCTL_STAT_ERR_OTHER:
8821708Sstevel SCKM_DEBUG0(D_TASK, "daemon encountered "
8831708Sstevel "an error");
8841708Sstevel rep_data->status = SCKM_ERR_DAEMON;
8851708Sstevel break;
8861708Sstevel case SCKM_IOCTL_STAT_ERR_SADB_TYPE:
8871708Sstevel SCKM_DEBUG0(D_TASK, "daemon returned bad "
8881708Sstevel "SADB message type");
8891708Sstevel rep_data->status = SCKM_ERR_SADB_BAD_TYPE;
8901708Sstevel break;
8911708Sstevel default:
8921708Sstevel cmn_err(CE_WARN, "SCKM daemon returned "
8931708Sstevel "invalid status %d", sckm_udata_status.status);
8941708Sstevel rep_data->status = SCKM_ERR_DAEMON;
8951708Sstevel }
8961708Sstevel }
8971708Sstevel
8981708Sstevel /* send reply back to SC */
8991708Sstevel if ((rv = mboxsc_putmsg(KEY_KDSC, MBOXSC_MSG_REPLY,
9001708Sstevel cmd, &transid, sizeof (sckm_mbox_rep_hdr_t),
9011708Sstevel rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT)) != 0) {
9021708Sstevel SCKM_DEBUG1(D_TASK, "failed sending reply to SC (%d)", rv);
9031708Sstevel } else {
9041708Sstevel SCKM_DEBUG0(D_TASK, "reply sent to SC");
9051708Sstevel }
9061708Sstevel
9071708Sstevel sckm_udata_req = B_FALSE;
9081708Sstevel mutex_exit(&sckm_umutex);
9091708Sstevel }
910