11772Sjl139090 /* 21772Sjl139090 * CDDL HEADER START 31772Sjl139090 * 41772Sjl139090 * The contents of this file are subject to the terms of the 51772Sjl139090 * Common Development and Distribution License (the "License"). 61772Sjl139090 * You may not use this file except in compliance with the License. 71772Sjl139090 * 81772Sjl139090 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91772Sjl139090 * or http://www.opensolaris.org/os/licensing. 101772Sjl139090 * See the License for the specific language governing permissions 111772Sjl139090 * and limitations under the License. 121772Sjl139090 * 131772Sjl139090 * When distributing Covered Code, include this CDDL HEADER in each 141772Sjl139090 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151772Sjl139090 * If applicable, add the following below this CDDL HEADER, with the 161772Sjl139090 * fields enclosed by brackets "[]" replaced with your own identifying 171772Sjl139090 * information: Portions Copyright [yyyy] [name of copyright owner] 181772Sjl139090 * 191772Sjl139090 * CDDL HEADER END 201772Sjl139090 */ 211772Sjl139090 /* 227656SSherry.Moore@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 231772Sjl139090 * Use is subject to license terms. 241772Sjl139090 */ 251772Sjl139090 261772Sjl139090 271772Sjl139090 /* 281772Sjl139090 * OPL IPSec Key Management Driver. 291772Sjl139090 * 301772Sjl139090 * This driver runs on a OPL Domain. It processes requests received 311772Sjl139090 * from the OPL Service Processor (SP) via mailbox message. It passes 321772Sjl139090 * these requests to the sckmd daemon by means of an /ioctl interface. 331772Sjl139090 * 341772Sjl139090 * Requests received from the SP consist of IPsec security associations 351772Sjl139090 * (SAs) needed to secure the communication between SC and Domain daemons 361772Sjl139090 * communicating using DSCP. 371772Sjl139090 */ 381772Sjl139090 391772Sjl139090 #include <sys/types.h> 401772Sjl139090 #include <sys/cmn_err.h> 411772Sjl139090 #include <sys/kmem.h> 421772Sjl139090 #include <sys/errno.h> 431772Sjl139090 #include <sys/file.h> 441772Sjl139090 #include <sys/open.h> 451772Sjl139090 #include <sys/stat.h> 461772Sjl139090 #include <sys/conf.h> 471772Sjl139090 #include <sys/ddi.h> 481772Sjl139090 #include <sys/cmn_err.h> 491772Sjl139090 #include <sys/sunddi.h> 501772Sjl139090 #include <sys/sunndi.h> 511772Sjl139090 #include <sys/ddi_impldefs.h> 521772Sjl139090 #include <sys/ndi_impldefs.h> 531772Sjl139090 #include <sys/modctl.h> 541772Sjl139090 #include <sys/disp.h> 551772Sjl139090 #include <sys/note.h> 561772Sjl139090 #include <sys/byteorder.h> 571772Sjl139090 #include <sys/sdt.h> 581772Sjl139090 591772Sjl139090 #include <sys/scfd/scfdscpif.h> 601772Sjl139090 #include <sys/oplkm_msg.h> 611772Sjl139090 #include <sys/sckm_io.h> 621772Sjl139090 #include <sys/oplkm.h> 631772Sjl139090 641772Sjl139090 #define OKM_NODENAME "oplkmdrv" /* Node name */ 651772Sjl139090 #define OKM_TARGET_ID 0 /* Target ID */ 661772Sjl139090 #define OKM_SM_TOUT 5000 /* small timeout (5msec) */ 671772Sjl139090 #define OKM_LG_TOUT 50000 /* large timeout (50msec) */ 681772Sjl139090 #define OKM_MB_TOUT 10000000 /* Mailbox timeout (10sec) */ 691772Sjl139090 701772Sjl139090 okms_t okms_global; /* Global instance structure */ 711772Sjl139090 721772Sjl139090 #ifdef DEBUG 731772Sjl139090 uint32_t okm_debug = DBG_WARN; 741772Sjl139090 #endif 751772Sjl139090 761772Sjl139090 /* 771772Sjl139090 * Prototypes for the module related functions. 781772Sjl139090 */ 791772Sjl139090 int okm_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 801772Sjl139090 int okm_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 811772Sjl139090 int okm_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result); 821772Sjl139090 int okm_open(dev_t *devp, int flag, int otyp, struct cred *cred); 831772Sjl139090 int okm_close(dev_t dev, int flag, int otyp, struct cred *cred); 841772Sjl139090 int okm_ioctl(dev_t dev, int cmd, intptr_t data, int flag, 851772Sjl139090 cred_t *cred, int *rvalp); 861772Sjl139090 871772Sjl139090 /* 881772Sjl139090 * Prototypes for the internal functions. 891772Sjl139090 */ 901772Sjl139090 int okm_get_req(okms_t *okmsp, sckm_ioctl_getreq_t *ireqp, 911772Sjl139090 intptr_t data, int flag); 921772Sjl139090 int okm_process_req(okms_t *okmsp, okm_req_hdr_t *reqp, uint32_t len, 931772Sjl139090 sckm_ioctl_getreq_t *ireqp, intptr_t data, int flag); 941772Sjl139090 int okm_process_status(okms_t *okmsp, sckm_ioctl_status_t *ireply); 951772Sjl139090 void okm_event_handler(scf_event_t event, void *arg); 961772Sjl139090 int okm_send_reply(okms_t *okmsp, uint32_t transid, uint32_t status, 971772Sjl139090 uint32_t sadb_err, uint32_t sadb_ver); 981772Sjl139090 int block_until_ready(okms_t *okmsp); 991772Sjl139090 static int okm_copyin_ioctl_getreq(intptr_t userarg, 1001772Sjl139090 sckm_ioctl_getreq_t *driverarg, int flag); 1011772Sjl139090 static int okm_copyout_ioctl_getreq(sckm_ioctl_getreq_t *driverarg, 1021772Sjl139090 intptr_t userarg, int flag); 1031772Sjl139090 static void okm_cleanup(okms_t *okmsp); 1041772Sjl139090 static int okm_mbox_init(okms_t *okmsp); 1051772Sjl139090 static void okm_mbox_fini(okms_t *okmsp); 1061772Sjl139090 static clock_t okm_timeout_val(int error); 1071772Sjl139090 1081772Sjl139090 1091772Sjl139090 struct cb_ops okm_cb_ops = { 1101772Sjl139090 okm_open, /* open */ 1111772Sjl139090 okm_close, /* close */ 1121772Sjl139090 nodev, /* strategy */ 1131772Sjl139090 nodev, /* print */ 1141772Sjl139090 nodev, /* dump */ 1151772Sjl139090 nodev, /* read */ 1161772Sjl139090 nodev, /* write */ 1171772Sjl139090 okm_ioctl, /* ioctl */ 1181772Sjl139090 nodev, /* devmap */ 1191772Sjl139090 nodev, /* mmap */ 1201772Sjl139090 nodev, /* segmap */ 1211772Sjl139090 nochpoll, /* poll */ 1221772Sjl139090 ddi_prop_op, /* prop_op */ 1231772Sjl139090 0, /* streamtab */ 1241772Sjl139090 D_NEW | D_MP /* Driver compatibility flag */ 1251772Sjl139090 }; 1261772Sjl139090 1271772Sjl139090 struct dev_ops okm_ops = { 1281772Sjl139090 DEVO_REV, /* devo_rev, */ 1291772Sjl139090 0, /* refcnt */ 1301772Sjl139090 okm_info, /* get_dev_info */ 1311772Sjl139090 nulldev, /* identify */ 1321772Sjl139090 nulldev, /* probe */ 1331772Sjl139090 okm_attach, /* attach */ 1341772Sjl139090 okm_detach, /* detach */ 1351772Sjl139090 nodev, /* reset */ 1361772Sjl139090 &okm_cb_ops, /* driver operations */ 1377656SSherry.Moore@Sun.COM (struct bus_ops *)0, /* no bus operations */ 1387656SSherry.Moore@Sun.COM NULL, /* power */ 1397656SSherry.Moore@Sun.COM ddi_quiesce_not_needed, /* quiesce */ 1401772Sjl139090 }; 1411772Sjl139090 1421772Sjl139090 struct modldrv modldrv = { 1431772Sjl139090 &mod_driverops, 1447656SSherry.Moore@Sun.COM "OPL Key Management Driver", 1451772Sjl139090 &okm_ops, 1461772Sjl139090 }; 1471772Sjl139090 1481772Sjl139090 struct modlinkage modlinkage = { 1491772Sjl139090 MODREV_1, 1501772Sjl139090 &modldrv, 1511772Sjl139090 NULL 1521772Sjl139090 }; 1531772Sjl139090 1541772Sjl139090 1551772Sjl139090 /* 1561772Sjl139090 * _init - Module's init routine. 1571772Sjl139090 */ 1581772Sjl139090 int 1591772Sjl139090 _init(void) 1601772Sjl139090 { 1611772Sjl139090 int ret; 1621772Sjl139090 1631772Sjl139090 if ((ret = mod_install(&modlinkage)) != 0) { 1641772Sjl139090 cmn_err(CE_WARN, "mod_install failed, error = %d", ret); 1651772Sjl139090 } 1661772Sjl139090 return (ret); 1671772Sjl139090 } 1681772Sjl139090 1691772Sjl139090 /* 1701772Sjl139090 * _fini - Module's fini routine. 1711772Sjl139090 */ 1721772Sjl139090 int 1731772Sjl139090 _fini(void) 1741772Sjl139090 { 1751772Sjl139090 int ret; 1761772Sjl139090 1771772Sjl139090 if ((ret = mod_remove(&modlinkage)) != 0) { 1781772Sjl139090 return (ret); 1791772Sjl139090 } 1801772Sjl139090 return (ret); 1811772Sjl139090 } 1821772Sjl139090 1831772Sjl139090 /* 1841772Sjl139090 * _info - Module's info routine. 1851772Sjl139090 */ 1861772Sjl139090 int 1871772Sjl139090 _info(struct modinfo *modinfop) 1881772Sjl139090 { 1891772Sjl139090 return (mod_info(&modlinkage, modinfop)); 1901772Sjl139090 } 1911772Sjl139090 1921772Sjl139090 /* 1931772Sjl139090 * okm_attach - Module's attach routine. 1941772Sjl139090 * 1951772Sjl139090 * Description: Initializes the modules state structure and create 1961772Sjl139090 * the minor device node. 1971772Sjl139090 */ 1981772Sjl139090 int 1991772Sjl139090 okm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2001772Sjl139090 { 2011772Sjl139090 int instance; 2021772Sjl139090 okms_t *okmsp = &okms_global; 2031772Sjl139090 2041772Sjl139090 instance = ddi_get_instance(dip); 2051772Sjl139090 2061772Sjl139090 /* Only one instance is supported. */ 2071772Sjl139090 if (instance != 0) { 2081772Sjl139090 return (DDI_FAILURE); 2091772Sjl139090 } 2101772Sjl139090 2111772Sjl139090 if (cmd != DDI_ATTACH) { 2121772Sjl139090 return (DDI_FAILURE); 2131772Sjl139090 } 2141772Sjl139090 2151772Sjl139090 okmsp->km_dip = dip; 216*8459SJerry.Gilliam@Sun.COM okmsp->km_major = ddi_driver_major(dip); 2171772Sjl139090 okmsp->km_inst = instance; 2181772Sjl139090 2191772Sjl139090 /* 2201772Sjl139090 * Get an interrupt block cookie corresponding to the 2211772Sjl139090 * interrupt priority of the event handler. 2221772Sjl139090 * Assert that the event priority is not redefined to 2231772Sjl139090 * some other priority. 2241772Sjl139090 */ 2251772Sjl139090 /* LINTED */ 2261772Sjl139090 ASSERT(SCF_EVENT_PRI == DDI_SOFTINT_LOW); 2271772Sjl139090 if (ddi_get_soft_iblock_cookie(dip, SCF_EVENT_PRI, 2281772Sjl139090 &okmsp->km_ibcookie) != DDI_SUCCESS) { 2291772Sjl139090 cmn_err(CE_WARN, "ddi_get_soft_iblock_cookie failed."); 2301772Sjl139090 return (DDI_FAILURE); 2311772Sjl139090 } 2321772Sjl139090 mutex_init(&okmsp->km_lock, NULL, MUTEX_DRIVER, 2331772Sjl139090 (void *)okmsp->km_ibcookie); 2341772Sjl139090 okmsp->km_clean |= OKM_CLEAN_LOCK; 2351772Sjl139090 cv_init(&okmsp->km_wait, NULL, CV_DRIVER, NULL); 2361772Sjl139090 okmsp->km_clean |= OKM_CLEAN_CV; 2371772Sjl139090 2381772Sjl139090 /* 2391772Sjl139090 * set clean_node ahead as remove_node has to be called even 2401772Sjl139090 * if create node fails. 2411772Sjl139090 */ 2421772Sjl139090 okmsp->km_clean |= OKM_CLEAN_NODE; 2431772Sjl139090 if (ddi_create_minor_node(dip, OKM_NODENAME, S_IFCHR, 2441772Sjl139090 instance, NULL, NULL) == DDI_FAILURE) { 2451772Sjl139090 cmn_err(CE_WARN, "Device node creation failed"); 2461772Sjl139090 okm_cleanup(okmsp); 2471772Sjl139090 return (DDI_FAILURE); 2481772Sjl139090 } 2491772Sjl139090 2501772Sjl139090 ddi_set_driver_private(dip, (caddr_t)okmsp); 2511772Sjl139090 ddi_report_dev(dip); 2521772Sjl139090 return (DDI_SUCCESS); 2531772Sjl139090 } 2541772Sjl139090 2551772Sjl139090 /* 2561772Sjl139090 * okm_detach - Module's detach routine. 2571772Sjl139090 * 2581772Sjl139090 * Description: Cleans up the module's state structures and any other 2591772Sjl139090 * relevant data. 2601772Sjl139090 */ 2611772Sjl139090 int 2621772Sjl139090 okm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2631772Sjl139090 { 2641772Sjl139090 okms_t *okmsp; 2651772Sjl139090 2661772Sjl139090 if (cmd != DDI_DETACH) { 2671772Sjl139090 return (DDI_FAILURE); 2681772Sjl139090 } 2691772Sjl139090 2701772Sjl139090 if ((okmsp = ddi_get_driver_private(dip)) == NULL) { 2711772Sjl139090 return (DDI_FAILURE); 2721772Sjl139090 } 2731772Sjl139090 2741772Sjl139090 mutex_enter(&okmsp->km_lock); 2751772Sjl139090 /* 2761772Sjl139090 * Check if the mailbox is still in use. 2771772Sjl139090 */ 2781772Sjl139090 if (okmsp->km_state & OKM_MB_INITED) { 2791772Sjl139090 mutex_exit(&okmsp->km_lock); 2801772Sjl139090 cmn_err(CE_WARN, "Detach failure: Mailbox in use"); 2811772Sjl139090 return (DDI_FAILURE); 2821772Sjl139090 } 2831772Sjl139090 mutex_exit(&okmsp->km_lock); 2841772Sjl139090 okm_cleanup(okmsp); 2851772Sjl139090 ddi_set_driver_private(dip, NULL); 2861772Sjl139090 return (DDI_SUCCESS); 2871772Sjl139090 } 2881772Sjl139090 2891772Sjl139090 /* 2901772Sjl139090 * okm_info - Module's info routine. 2911772Sjl139090 */ 2921772Sjl139090 /* ARGSUSED */ 2931772Sjl139090 int 2941772Sjl139090 okm_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2951772Sjl139090 { 2961772Sjl139090 okms_t *okmsp; 2971772Sjl139090 minor_t minor; 2981772Sjl139090 int ret = DDI_FAILURE; 2991772Sjl139090 3001772Sjl139090 switch (infocmd) { 3011772Sjl139090 case DDI_INFO_DEVT2DEVINFO: 3021772Sjl139090 minor = getminor((dev_t)arg); 3031772Sjl139090 okmsp = ddi_get_driver_private(dip); 3041772Sjl139090 if (okmsp == NULL) { 3051772Sjl139090 *result = NULL; 3061772Sjl139090 } else { 3071772Sjl139090 *result = okmsp->km_dip; 3081772Sjl139090 ret = DDI_SUCCESS; 3091772Sjl139090 } 3101772Sjl139090 break; 3111772Sjl139090 3121772Sjl139090 case DDI_INFO_DEVT2INSTANCE: 3131772Sjl139090 minor = getminor((dev_t)arg); 3141772Sjl139090 *result = (void *)(uintptr_t)minor; 3151772Sjl139090 ret = DDI_SUCCESS; 3161772Sjl139090 3171772Sjl139090 default: 3181772Sjl139090 break; 3191772Sjl139090 } 3201772Sjl139090 return (ret); 3211772Sjl139090 } 3221772Sjl139090 3231772Sjl139090 /* 3241772Sjl139090 * okm_open - Device open routine. 3251772Sjl139090 * 3261772Sjl139090 * Description: Initializes the mailbox and waits until the mailbox 3271772Sjl139090 * gets connected. Only one open at a time is supported. 3281772Sjl139090 */ 3291772Sjl139090 /*ARGSUSED*/ 3301772Sjl139090 int 3311772Sjl139090 okm_open(dev_t *devp, int flag, int otyp, struct cred *cred) 3321772Sjl139090 { 3331772Sjl139090 okms_t *okmsp = &okms_global; 3341772Sjl139090 int ret = 0; 3351772Sjl139090 3361772Sjl139090 DPRINTF(DBG_DRV, ("okm_open: called\n")); 3371772Sjl139090 mutex_enter(&okmsp->km_lock); 3381772Sjl139090 if (okmsp->km_state & OKM_OPENED) { 3391772Sjl139090 /* Only one open supported */ 3401772Sjl139090 mutex_exit(&okmsp->km_lock); 3411772Sjl139090 DPRINTF(DBG_WARN, ("okm_open: already opened\n")); 3421772Sjl139090 return (EBUSY); 3431772Sjl139090 } 3441772Sjl139090 okmsp->km_state |= OKM_OPENED; 3451772Sjl139090 ret = block_until_ready(okmsp); 3461772Sjl139090 if (ret != 0) { 3471772Sjl139090 okmsp->km_state &= ~OKM_OPENED; 3481772Sjl139090 } 3491772Sjl139090 mutex_exit(&okmsp->km_lock); 3501772Sjl139090 DPRINTF(DBG_DRV, ("okm_open: ret=%d\n", ret)); 3511772Sjl139090 return (ret); 3521772Sjl139090 } 3531772Sjl139090 3541772Sjl139090 /* 3551772Sjl139090 * block_until_ready - Function to wait until the mailbox is ready to use. 3561772Sjl139090 * 3571772Sjl139090 * Description: It initializes the mailbox and waits for the mailbox 3581772Sjl139090 * state to transition to connected. 3591772Sjl139090 */ 3601772Sjl139090 int 3611772Sjl139090 block_until_ready(okms_t *okmsp) 3621772Sjl139090 { 3631772Sjl139090 int ret = 0; 3641772Sjl139090 3651772Sjl139090 DPRINTF(DBG_DRV, ("block_until_ready: called\n")); 3661772Sjl139090 ASSERT(MUTEX_HELD(&okmsp->km_lock)); 3671772Sjl139090 3681772Sjl139090 if (okmsp->km_state & OKM_MB_DISC) { 3691772Sjl139090 DPRINTF(DBG_DRV, ("block_until_ready: closing the mailbox\n")); 3701772Sjl139090 okm_mbox_fini(okmsp); 3711772Sjl139090 } 3721772Sjl139090 if (okmsp->km_state & OKM_MB_CONN) { 3731772Sjl139090 DPRINTF(DBG_DRV, ("block_until_ready: mailbox connected\n")); 3741772Sjl139090 return (0); 3751772Sjl139090 } 3761772Sjl139090 /* 3771772Sjl139090 * Initialize mailbox. 3781772Sjl139090 */ 3791772Sjl139090 if ((ret = okm_mbox_init(okmsp)) != 0) { 3801772Sjl139090 DPRINTF(DBG_MBOX, 3811772Sjl139090 ("block_until_ready: mailbox init failed ret=%d\n", ret)); 3821772Sjl139090 return (ret); 3831772Sjl139090 } 3841772Sjl139090 DPRINTF(DBG_DRV, ("block_until_ready: ret=%d", ret)); 3851772Sjl139090 return (ret); 3861772Sjl139090 } 3871772Sjl139090 3881772Sjl139090 /* 3891772Sjl139090 * okm_close - Device close routine. 3901772Sjl139090 * 3911772Sjl139090 * Description: Closes the mailbox. 3921772Sjl139090 */ 3931772Sjl139090 /*ARGSUSED*/ 3941772Sjl139090 int 3951772Sjl139090 okm_close(dev_t dev, int flag, int otyp, struct cred *cred) 3961772Sjl139090 { 3971772Sjl139090 okms_t *okmsp = &okms_global; 3981772Sjl139090 3991772Sjl139090 DPRINTF(DBG_DRV, ("okm_close: called\n")); 4001772Sjl139090 /* Close the lower layer first */ 4011772Sjl139090 mutex_enter(&okmsp->km_lock); 4021772Sjl139090 okm_mbox_fini(okmsp); 4031772Sjl139090 okmsp->km_state = 0; 4041772Sjl139090 mutex_exit(&okmsp->km_lock); 4051772Sjl139090 return (0); 4061772Sjl139090 } 4071772Sjl139090 4081772Sjl139090 4091772Sjl139090 /* 4101772Sjl139090 * okm_ioctl - Device ioctl routine. 4111772Sjl139090 * 4121772Sjl139090 * Description: Processes ioctls from the daemon. 4131772Sjl139090 */ 4141772Sjl139090 /*ARGSUSED*/ 4151772Sjl139090 int 4161772Sjl139090 okm_ioctl(dev_t dev, int cmd, intptr_t data, int flag, cred_t *cred, int *rvalp) 4171772Sjl139090 { 4181772Sjl139090 okms_t *okmsp = &okms_global; 4191772Sjl139090 sckm_ioctl_getreq_t ireq; 4201772Sjl139090 sckm_ioctl_status_t istatus; 4211772Sjl139090 int ret = 0; 4221772Sjl139090 4231772Sjl139090 switch (cmd) { 4241772Sjl139090 case SCKM_IOCTL_GETREQ: 4251772Sjl139090 4261772Sjl139090 DPRINTF(DBG_DRV, ("okm_ioctl: GETREQ\n")); 4271772Sjl139090 if (okm_copyin_ioctl_getreq(data, &ireq, flag)) { 4281772Sjl139090 return (EFAULT); 4291772Sjl139090 } 4301772Sjl139090 4311772Sjl139090 ret = okm_get_req(okmsp, &ireq, data, flag); 4321772Sjl139090 DPRINTF(DBG_DRV, ("okm_ioctl: GETREQ ret=%d\n", ret)); 4331772Sjl139090 break; 4341772Sjl139090 4351772Sjl139090 case SCKM_IOCTL_STATUS: 4361772Sjl139090 4371772Sjl139090 DPRINTF(DBG_DRV, ("okm_ioctl: STATUS\n")); 4381772Sjl139090 if (ddi_copyin((caddr_t)data, &istatus, 4391772Sjl139090 sizeof (sckm_ioctl_status_t), flag)) { 4401772Sjl139090 return (EFAULT); 4411772Sjl139090 } 4421772Sjl139090 ret = okm_process_status(okmsp, &istatus); 4431772Sjl139090 DPRINTF(DBG_DRV, ("okm_ioctl: STATUS ret=%d\n", ret)); 4441772Sjl139090 break; 4451772Sjl139090 4461772Sjl139090 default: 4471772Sjl139090 DPRINTF(DBG_DRV, ("okm_ioctl: UNKNOWN ioctl\n")); 4481772Sjl139090 ret = EINVAL; 4491772Sjl139090 } 4501772Sjl139090 return (ret); 4511772Sjl139090 } 4521772Sjl139090 4531772Sjl139090 /* 4541772Sjl139090 * okm_get_req - Get a request from the mailbox. 4551772Sjl139090 * 4561772Sjl139090 * Description: It blocks until a message is received, then processes 4571772Sjl139090 * the message and returns it to the requestor. 4581772Sjl139090 */ 4591772Sjl139090 int 4601772Sjl139090 okm_get_req(okms_t *okmsp, sckm_ioctl_getreq_t *ireqp, intptr_t data, int flag) 4611772Sjl139090 { 4621772Sjl139090 okm_req_hdr_t *reqp; 4631772Sjl139090 caddr_t msgbuf; 4641772Sjl139090 uint32_t len; 4651772Sjl139090 int ret; 4661772Sjl139090 4671772Sjl139090 DPRINTF(DBG_DRV, ("okm_getreq: called\n")); 4681772Sjl139090 mutex_enter(&okmsp->km_lock); 4691772Sjl139090 if ((ret = block_until_ready(okmsp)) != 0) { 4701772Sjl139090 mutex_exit(&okmsp->km_lock); 4711772Sjl139090 DPRINTF(DBG_WARN, ("okm_getreq: failed ret=%d\n", ret)); 4721772Sjl139090 return (ret); 4731772Sjl139090 } 4741772Sjl139090 4751772Sjl139090 if (okmsp->km_reqp != NULL) { 4761772Sjl139090 DPRINTF(DBG_DRV, ("okm_getreq: req cached\n")); 4771772Sjl139090 reqp = okmsp->km_reqp; 4781772Sjl139090 len = okmsp->km_reqlen; 4791772Sjl139090 okmsp->km_reqp = NULL; 4801772Sjl139090 okmsp->km_reqlen = 0; 4811772Sjl139090 } else { 4821772Sjl139090 retry: 4831772Sjl139090 while (OKM_MBOX_READY(okmsp) && 4841772Sjl139090 ((ret = scf_mb_canget(okmsp->km_target, 4851772Sjl139090 okmsp->km_key, &len)) != 0)) { 4861772Sjl139090 if (ret != ENOMSG) { 4871772Sjl139090 DPRINTF(DBG_WARN, ("okm_getreq: Unknown " 4881772Sjl139090 "mbox failure=%d\n", ret)); 4891772Sjl139090 mutex_exit(&okmsp->km_lock); 4901772Sjl139090 return (EIO); 4911772Sjl139090 } 4921772Sjl139090 DPRINTF(DBG_MBOX, ("okm_getreq: waiting for mesg\n")); 4931772Sjl139090 if (cv_wait_sig(&okmsp->km_wait, 4941772Sjl139090 &okmsp->km_lock) <= 0) { 4951772Sjl139090 mutex_exit(&okmsp->km_lock); 4961772Sjl139090 DPRINTF(DBG_DRV, ("okm_getreq:interrupted\n")); 4971772Sjl139090 return (EINTR); 4981772Sjl139090 } 4991772Sjl139090 } 5001772Sjl139090 if (!OKM_MBOX_READY(okmsp)) { 5011772Sjl139090 mutex_exit(&okmsp->km_lock); 5021772Sjl139090 DPRINTF(DBG_WARN, ("okm_getreq: mailbox not ready\n")); 5031772Sjl139090 return (EIO); 5041772Sjl139090 } 5051772Sjl139090 ASSERT(len != 0); 5061772Sjl139090 msgbuf = kmem_alloc(len, KM_SLEEP); 5071772Sjl139090 okmsp->km_sg_rcv.msc_dptr = msgbuf; 5081772Sjl139090 okmsp->km_sg_rcv.msc_len = len; 5091772Sjl139090 5101772Sjl139090 DPRINTF(DBG_MBOX, ("okm_getreq: getmsg\n")); 5111772Sjl139090 ret = scf_mb_getmsg(okmsp->km_target, okmsp->km_key, len, 1, 5121772Sjl139090 &okmsp->km_sg_rcv, 0); 5131772Sjl139090 if (ret == ENOMSG || ret == EMSGSIZE) { 5141772Sjl139090 kmem_free(msgbuf, len); 5151772Sjl139090 DPRINTF(DBG_MBOX, ("okm_getreq: nomsg ret=%d\n", ret)); 5161772Sjl139090 goto retry; 5171772Sjl139090 } else if (ret != 0) { 5181772Sjl139090 kmem_free(msgbuf, len); 5191772Sjl139090 mutex_exit(&okmsp->km_lock); 5201772Sjl139090 DPRINTF(DBG_WARN, 5211772Sjl139090 ("okm_getreq: Unknown mbox failure=%d\n", ret)); 5221772Sjl139090 return (EIO); 5231772Sjl139090 } 5241772Sjl139090 5251772Sjl139090 /* check message length */ 5261772Sjl139090 if (len < sizeof (okm_req_hdr_t)) { 5271772Sjl139090 /* protocol error, drop message */ 5281772Sjl139090 kmem_free(msgbuf, len); 5291772Sjl139090 mutex_exit(&okmsp->km_lock); 5301772Sjl139090 DPRINTF(DBG_WARN, ("okm_getreq: Bad message\n")); 5311772Sjl139090 return (EBADMSG); 5321772Sjl139090 } 5331772Sjl139090 5341772Sjl139090 reqp = (okm_req_hdr_t *)msgbuf; 5351772Sjl139090 reqp->krq_version = ntohl(reqp->krq_version); 5361772Sjl139090 reqp->krq_transid = ntohl(reqp->krq_transid); 5371772Sjl139090 reqp->krq_cmd = ntohl(reqp->krq_cmd); 5381772Sjl139090 reqp->krq_reserved = ntohl(reqp->krq_reserved); 5391772Sjl139090 5401772Sjl139090 /* check version of the message received */ 5411772Sjl139090 if (reqp->krq_version != OKM_PROTOCOL_VERSION) { 5421772Sjl139090 okm_send_reply(okmsp, reqp->krq_transid, 5431772Sjl139090 OKM_ERR_VERSION, 0, 0); 5441772Sjl139090 kmem_free(msgbuf, len); 5451772Sjl139090 mutex_exit(&okmsp->km_lock); 5461772Sjl139090 DPRINTF(DBG_WARN, ("okm_getreq: Unknown version=%d\n", 5471772Sjl139090 reqp->krq_version)); 5481772Sjl139090 return (EBADMSG); 5491772Sjl139090 } 5501772Sjl139090 } 5511772Sjl139090 5521772Sjl139090 /* process message */ 5531772Sjl139090 ret = okm_process_req(okmsp, reqp, len, ireqp, data, flag); 5541772Sjl139090 if (okmsp->km_reqp == NULL) { 5551772Sjl139090 /* 5561772Sjl139090 * The message is not saved, so free the buffer. 5571772Sjl139090 */ 5581772Sjl139090 kmem_free(reqp, len); 5591772Sjl139090 } 5601772Sjl139090 mutex_exit(&okmsp->km_lock); 5611772Sjl139090 DPRINTF(DBG_DRV, ("okm_getreq: ret=%d\n", ret)); 5621772Sjl139090 return (ret); 5631772Sjl139090 } 5641772Sjl139090 5651772Sjl139090 5661772Sjl139090 /* 5671772Sjl139090 * okm_process_req - Process the request. 5681772Sjl139090 * 5691772Sjl139090 * Description: Validate the request and then give the request to the 5701772Sjl139090 * daemon. 5711772Sjl139090 */ 5721772Sjl139090 int 5731772Sjl139090 okm_process_req(okms_t *okmsp, okm_req_hdr_t *reqp, uint32_t len, 5741772Sjl139090 sckm_ioctl_getreq_t *ireqp, intptr_t data, int flag) 5751772Sjl139090 { 5761772Sjl139090 void *req_datap = (void *)(((char *)reqp) + sizeof (okm_req_hdr_t)); 5771772Sjl139090 int sadb_msglen = len - sizeof (okm_req_hdr_t); 5781772Sjl139090 5791772Sjl139090 DPRINTF(DBG_DRV, ("okm_process_req: called\n")); 5801772Sjl139090 DUMP_REQ(reqp, len); 5811772Sjl139090 5821772Sjl139090 switch (reqp->krq_cmd) { 5831772Sjl139090 case OKM_MSG_SADB: 5841772Sjl139090 /* sanity check request */ 5851772Sjl139090 if (sadb_msglen <= 0) { 5861772Sjl139090 okm_send_reply(okmsp, reqp->krq_transid, 5871772Sjl139090 OKM_ERR_SADB_MSG, 0, 0); 5881772Sjl139090 DPRINTF(DBG_WARN, ("okm_process_req: bad message\n")); 5891772Sjl139090 return (EBADMSG); 5901772Sjl139090 } 5911772Sjl139090 5921772Sjl139090 /* 5931772Sjl139090 * Save the message, prior to giving it to the daemon. 5941772Sjl139090 */ 5951772Sjl139090 okmsp->km_reqp = reqp; 5961772Sjl139090 okmsp->km_reqlen = len; 5971772Sjl139090 5981772Sjl139090 if (ireqp->buf_len < len) { 5991772Sjl139090 DPRINTF(DBG_WARN, 6001772Sjl139090 ("okm_process_req: not enough space\n")); 6011772Sjl139090 return (ENOSPC); 6021772Sjl139090 } 6031772Sjl139090 6041772Sjl139090 ireqp->transid = reqp->krq_transid; 6051772Sjl139090 ireqp->type = SCKM_IOCTL_REQ_SADB; 6061772Sjl139090 if (ddi_copyout(req_datap, ireqp->buf, sadb_msglen, flag)) { 6071772Sjl139090 DPRINTF(DBG_WARN, 6081772Sjl139090 ("okm_process_req: copyout failed\n")); 6091772Sjl139090 return (EFAULT); 6101772Sjl139090 } 6111772Sjl139090 ireqp->buf_len = sadb_msglen; 6121772Sjl139090 if (okm_copyout_ioctl_getreq(ireqp, data, flag)) { 6131772Sjl139090 DPRINTF(DBG_WARN, 6141772Sjl139090 ("okm_process_req: copyout failed\n")); 6151772Sjl139090 return (EFAULT); 6161772Sjl139090 } 6171772Sjl139090 break; 6181772Sjl139090 6191772Sjl139090 default: 6201772Sjl139090 cmn_err(CE_WARN, "Unknown cmd 0x%x received", reqp->krq_cmd); 6211772Sjl139090 /* 6221772Sjl139090 * Received an unknown command, send corresponding 6231772Sjl139090 * error message. 6241772Sjl139090 */ 6251772Sjl139090 okm_send_reply(okmsp, reqp->krq_transid, OKM_ERR_BAD_CMD, 0, 0); 6261772Sjl139090 return (EBADMSG); 6271772Sjl139090 } 6281772Sjl139090 DPRINTF(DBG_DRV, ("okm_process_req: ret=0\n")); 6291772Sjl139090 return (0); 6301772Sjl139090 } 6311772Sjl139090 6321772Sjl139090 /* 6331772Sjl139090 * okm_process_status - Process the status from the daemon. 6341772Sjl139090 * 6351772Sjl139090 * Description: Processes the status received from the daemon and sends 6361772Sjl139090 * corresponding message to the SP. 6371772Sjl139090 */ 6381772Sjl139090 int 6391772Sjl139090 okm_process_status(okms_t *okmsp, sckm_ioctl_status_t *ireply) 6401772Sjl139090 { 6411772Sjl139090 uint32_t status; 6421772Sjl139090 uint32_t sadb_msg_errno = 0; 6431772Sjl139090 uint32_t sadb_msg_version = 0; 6441772Sjl139090 okm_req_hdr_t *reqp = okmsp->km_reqp; 6451772Sjl139090 int ret; 6461772Sjl139090 6471772Sjl139090 DPRINTF(DBG_DRV, ("okm_process_status: called\n")); 6481772Sjl139090 mutex_enter(&okmsp->km_lock); 6491772Sjl139090 if ((ret = block_until_ready(okmsp)) != 0) { 6501772Sjl139090 mutex_exit(&okmsp->km_lock); 6511772Sjl139090 DPRINTF(DBG_WARN, 6521772Sjl139090 ("okm_process_status: Unknown failure=%d\n", ret)); 6531772Sjl139090 return (ret); 6541772Sjl139090 } 6551772Sjl139090 6561772Sjl139090 /* fail if no status is expected, or if it does not match */ 6571772Sjl139090 if (!okmsp->km_reqp || (reqp->krq_transid != ireply->transid)) { 6581772Sjl139090 mutex_exit(&okmsp->km_lock); 6591772Sjl139090 DPRINTF(DBG_WARN, 6601772Sjl139090 ("okm_process_status: req/transid mismatch\n")); 6611772Sjl139090 return (EINVAL); 6621772Sjl139090 } 6631772Sjl139090 6641772Sjl139090 switch (ireply->status) { 6651772Sjl139090 case SCKM_IOCTL_STAT_SUCCESS: 6661772Sjl139090 DPRINTF(DBG_DRV, ("okm_process_status: SUCCESS\n")); 6671772Sjl139090 status = OKM_SUCCESS; 6681772Sjl139090 break; 6691772Sjl139090 case SCKM_IOCTL_STAT_ERR_PFKEY: 6701772Sjl139090 DPRINTF(DBG_DRV, ("okm_process_status: PFKEY ERROR\n")); 6711772Sjl139090 status = OKM_ERR_SADB_PFKEY; 6721772Sjl139090 sadb_msg_errno = ireply->sadb_msg_errno; 6731772Sjl139090 break; 6741772Sjl139090 case SCKM_IOCTL_STAT_ERR_REQ: 6751772Sjl139090 DPRINTF(DBG_DRV, ("okm_process_status: REQ ERROR\n")); 6761772Sjl139090 status = OKM_ERR_DAEMON; 6771772Sjl139090 break; 6781772Sjl139090 case SCKM_IOCTL_STAT_ERR_VERSION: 6791772Sjl139090 DPRINTF(DBG_DRV, ("okm_process_status: SADB VERSION ERROR\n")); 6801772Sjl139090 status = OKM_ERR_SADB_VERSION; 6811772Sjl139090 sadb_msg_version = ireply->sadb_msg_version; 6821772Sjl139090 break; 6831772Sjl139090 case SCKM_IOCTL_STAT_ERR_TIMEOUT: 6841772Sjl139090 DPRINTF(DBG_DRV, ("okm_process_status: TIMEOUT ERR\n")); 6851772Sjl139090 status = OKM_ERR_SADB_TIMEOUT; 6861772Sjl139090 break; 6871772Sjl139090 case SCKM_IOCTL_STAT_ERR_OTHER: 6881772Sjl139090 DPRINTF(DBG_DRV, ("okm_process_status: OTHER ERR\n")); 6891772Sjl139090 status = OKM_ERR_DAEMON; 6901772Sjl139090 break; 6911772Sjl139090 case SCKM_IOCTL_STAT_ERR_SADB_TYPE: 6921772Sjl139090 DPRINTF(DBG_DRV, ("okm_process_status: SADB TYPE ERR\n")); 6931772Sjl139090 status = OKM_ERR_SADB_BAD_TYPE; 6941772Sjl139090 break; 6951772Sjl139090 default: 6961772Sjl139090 cmn_err(CE_WARN, "SCKM daemon returned invalid status %d\n", 6971772Sjl139090 ireply->status); 6981772Sjl139090 status = OKM_ERR_DAEMON; 6991772Sjl139090 } 7001772Sjl139090 ret = okm_send_reply(okmsp, ireply->transid, status, 7011772Sjl139090 sadb_msg_errno, sadb_msg_version); 7021772Sjl139090 /* 7031772Sjl139090 * Clean up the cached request now. 7041772Sjl139090 */ 7051772Sjl139090 if (ret == 0) { 7061772Sjl139090 kmem_free(okmsp->km_reqp, okmsp->km_reqlen); 7071772Sjl139090 okmsp->km_reqp = NULL; 7081772Sjl139090 okmsp->km_reqlen = 0; 7091772Sjl139090 } 7101772Sjl139090 mutex_exit(&okmsp->km_lock); 7111772Sjl139090 DPRINTF(DBG_DRV, ("okm_process_status: ret=%d\n", ret)); 7121772Sjl139090 return (ret); 7131772Sjl139090 } 7141772Sjl139090 7151772Sjl139090 /* 7161772Sjl139090 * okm_copyin_ioctl_getreq - copy-in the ioctl request from the daemon. 7171772Sjl139090 */ 7181772Sjl139090 7191772Sjl139090 static int 7201772Sjl139090 okm_copyin_ioctl_getreq(intptr_t userarg, sckm_ioctl_getreq_t *driverarg, 7211772Sjl139090 int flag) 7221772Sjl139090 { 7231772Sjl139090 #ifdef _MULTI_DATAMODEL 7241772Sjl139090 switch (ddi_model_convert_from(flag & FMODELS)) { 7251772Sjl139090 case DDI_MODEL_ILP32: { 7261772Sjl139090 sckm_ioctl_getreq32_t driverarg32; 7271772Sjl139090 if (ddi_copyin((caddr_t)userarg, &driverarg32, 7281772Sjl139090 sizeof (sckm_ioctl_getreq32_t), flag)) { 7291772Sjl139090 return (EFAULT); 7301772Sjl139090 } 7311772Sjl139090 driverarg->transid = driverarg32.transid; 7321772Sjl139090 driverarg->type = driverarg32.type; 7331772Sjl139090 driverarg->buf = (caddr_t)(uintptr_t)driverarg32.buf; 7341772Sjl139090 driverarg->buf_len = driverarg32.buf_len; 7351772Sjl139090 break; 7361772Sjl139090 } 7371772Sjl139090 case DDI_MODEL_NONE: { 7381772Sjl139090 if (ddi_copyin((caddr_t)userarg, &driverarg, 7391772Sjl139090 sizeof (sckm_ioctl_getreq_t), flag)) { 7401772Sjl139090 return (EFAULT); 7411772Sjl139090 } 7421772Sjl139090 break; 7431772Sjl139090 } 7441772Sjl139090 } 7451772Sjl139090 #else /* ! _MULTI_DATAMODEL */ 7461772Sjl139090 if (ddi_copyin((caddr_t)userarg, &driverarg, 7471772Sjl139090 sizeof (sckm_ioctl_getreq_t), flag)) { 7481772Sjl139090 return (EFAULT); 7491772Sjl139090 } 7501772Sjl139090 #endif /* _MULTI_DATAMODEL */ 7511772Sjl139090 return (0); 7521772Sjl139090 } 7531772Sjl139090 7541772Sjl139090 7551772Sjl139090 /* 7561772Sjl139090 * okm_copyout_ioctl_getreq - copy-out the request to the daemon. 7571772Sjl139090 */ 7581772Sjl139090 static int 7591772Sjl139090 okm_copyout_ioctl_getreq(sckm_ioctl_getreq_t *driverarg, intptr_t userarg, 7601772Sjl139090 int flag) 7611772Sjl139090 { 7621772Sjl139090 #ifdef _MULTI_DATAMODEL 7631772Sjl139090 switch (ddi_model_convert_from(flag & FMODELS)) { 7641772Sjl139090 case DDI_MODEL_ILP32: { 7651772Sjl139090 sckm_ioctl_getreq32_t driverarg32; 7661772Sjl139090 driverarg32.transid = driverarg->transid; 7671772Sjl139090 driverarg32.type = driverarg->type; 7681772Sjl139090 driverarg32.buf = (caddr32_t)(uintptr_t)driverarg->buf; 7691772Sjl139090 driverarg32.buf_len = driverarg->buf_len; 7701772Sjl139090 if (ddi_copyout(&driverarg32, (caddr_t)userarg, 7711772Sjl139090 sizeof (sckm_ioctl_getreq32_t), flag)) { 7721772Sjl139090 return (EFAULT); 7731772Sjl139090 } 7741772Sjl139090 break; 7751772Sjl139090 } 7761772Sjl139090 case DDI_MODEL_NONE: 7771772Sjl139090 if (ddi_copyout(driverarg, (caddr_t)userarg, 7781772Sjl139090 sizeof (sckm_ioctl_getreq_t), flag)) { 7791772Sjl139090 return (EFAULT); 7801772Sjl139090 } 7811772Sjl139090 break; 7821772Sjl139090 } 7831772Sjl139090 #else /* ! _MULTI_DATAMODEL */ 7841772Sjl139090 if (ddi_copyout(driverarg, (caddr_t)userarg, 7851772Sjl139090 sizeof (sckm_ioctl_getreq_t), flag)) { 7861772Sjl139090 return (EFAULT); 7871772Sjl139090 } 7881772Sjl139090 #endif /* _MULTI_DATAMODEL */ 7891772Sjl139090 return (0); 7901772Sjl139090 } 7911772Sjl139090 7921772Sjl139090 /* 7931772Sjl139090 * okm_cleanup - Cleanup routine. 7941772Sjl139090 */ 7951772Sjl139090 static void 7961772Sjl139090 okm_cleanup(okms_t *okmsp) 7971772Sjl139090 { 7981772Sjl139090 7991772Sjl139090 ASSERT(okmsp != NULL); 8001772Sjl139090 if (okmsp->km_clean & OKM_CLEAN_NODE) { 8011772Sjl139090 ddi_remove_minor_node(okmsp->km_dip, NULL); 8021772Sjl139090 } 8031772Sjl139090 if (okmsp->km_clean & OKM_CLEAN_LOCK) 8041772Sjl139090 mutex_destroy(&okmsp->km_lock); 8051772Sjl139090 if (okmsp->km_clean & OKM_CLEAN_CV) 8061772Sjl139090 cv_destroy(&okmsp->km_wait); 8071772Sjl139090 if (okmsp->km_reqp != NULL) { 8081772Sjl139090 kmem_free(okmsp->km_reqp, okmsp->km_reqlen); 8091772Sjl139090 okmsp->km_reqp = NULL; 8101772Sjl139090 okmsp->km_reqlen = 0; 8111772Sjl139090 } 8121772Sjl139090 ddi_set_driver_private(okmsp->km_dip, NULL); 8131772Sjl139090 } 8141772Sjl139090 8151772Sjl139090 /* 8161772Sjl139090 * okm_mbox_init - Mailbox specific initialization. 8171772Sjl139090 */ 8181772Sjl139090 static int 8191772Sjl139090 okm_mbox_init(okms_t *okmsp) 8201772Sjl139090 { 8211772Sjl139090 int ret; 8221772Sjl139090 clock_t tout; 8231772Sjl139090 8241772Sjl139090 ASSERT(MUTEX_HELD(&okmsp->km_lock)); 8251772Sjl139090 okmsp->km_target = OKM_TARGET_ID; 8261772Sjl139090 okmsp->km_key = DKMD_KEY; 8271772Sjl139090 okmsp->km_state &= ~OKM_MB_INITED; 8281772Sjl139090 8291772Sjl139090 /* Iterate until mailbox gets connected */ 8301772Sjl139090 while (!(okmsp->km_state & OKM_MB_CONN)) { 8311772Sjl139090 DPRINTF(DBG_MBOX, ("okm_mbox_init: calling mb_init\n")); 8321772Sjl139090 ret = scf_mb_init(okmsp->km_target, okmsp->km_key, 8331772Sjl139090 okm_event_handler, (void *)okmsp); 8341772Sjl139090 DPRINTF(DBG_MBOX, ("okm_mbox_init: mb_init ret=%d\n", ret)); 8351772Sjl139090 8362126Sraghuram if (ret != 0) { 8372126Sraghuram DPRINTF(DBG_MBOX, 8382126Sraghuram ("okm_mbox_init: failed ret =%d\n", ret)); 8392126Sraghuram DTRACE_PROBE1(okm_mbox_fail, int, ret); 8402126Sraghuram } else { 8411772Sjl139090 okmsp->km_state |= OKM_MB_INITED; 8421772Sjl139090 8431772Sjl139090 /* Block until the mailbox is ready to communicate. */ 8441772Sjl139090 while (!(okmsp->km_state & 8451772Sjl139090 (OKM_MB_CONN | OKM_MB_DISC))) { 8461772Sjl139090 8471772Sjl139090 if (cv_wait_sig(&okmsp->km_wait, 8481772Sjl139090 &okmsp->km_lock) <= 0) { 8491772Sjl139090 /* interrupted */ 8501772Sjl139090 ret = EINTR; 8511772Sjl139090 break; 8521772Sjl139090 } 8531772Sjl139090 } 8541772Sjl139090 } 8551772Sjl139090 8561772Sjl139090 if ((ret != 0) || (okmsp->km_state & OKM_MB_DISC)) { 8571772Sjl139090 8582126Sraghuram if (okmsp->km_state & OKM_MB_INITED) { 8592126Sraghuram (void) scf_mb_fini(okmsp->km_target, 8602126Sraghuram okmsp->km_key); 8612126Sraghuram } 8622126Sraghuram if (okmsp->km_state & OKM_MB_DISC) { 8632126Sraghuram DPRINTF(DBG_WARN, 8642126Sraghuram ("okm_mbox_init: mbox DISC_ERROR\n")); 8652126Sraghuram DTRACE_PROBE1(okm_mbox_fail, 8662126Sraghuram int, OKM_MB_DISC); 8672126Sraghuram } 8682126Sraghuram 8692126Sraghuram okmsp->km_state &= ~(OKM_MB_INITED | OKM_MB_DISC | 8702126Sraghuram OKM_MB_CONN); 8712126Sraghuram 8722126Sraghuram if (ret == EINTR) { 8732126Sraghuram return (ret); 8742126Sraghuram } 8751772Sjl139090 8761772Sjl139090 /* 8771772Sjl139090 * If there was failure, then wait for 8781772Sjl139090 * OKM_MB_TOUT secs and retry again. 8791772Sjl139090 */ 8801772Sjl139090 8811772Sjl139090 DPRINTF(DBG_MBOX, ("okm_mbox_init: waiting...\n")); 8821772Sjl139090 tout = ddi_get_lbolt() + drv_usectohz(OKM_MB_TOUT); 8831772Sjl139090 ret = cv_timedwait_sig(&okmsp->km_wait, 8841772Sjl139090 &okmsp->km_lock, tout); 8851772Sjl139090 if (ret == 0) { 8861772Sjl139090 /* if interrupted, return immediately. */ 8871772Sjl139090 DPRINTF(DBG_MBOX, 8881772Sjl139090 ("okm_mbox_init: interrupted\n")); 8891772Sjl139090 return (EINTR); 8901772Sjl139090 } 8911772Sjl139090 } 8921772Sjl139090 } 8931772Sjl139090 8941772Sjl139090 ret = scf_mb_ctrl(okmsp->km_target, okmsp->km_key, 8951772Sjl139090 SCF_MBOP_MAXMSGSIZE, &okmsp->km_maxsz); 8961772Sjl139090 8971772Sjl139090 /* 8981772Sjl139090 * The max msg size should be at least the size of reply 8991772Sjl139090 * we need to send. 9001772Sjl139090 */ 9011772Sjl139090 if ((ret == 0) && (okmsp->km_maxsz < sizeof (okm_rep_hdr_t))) { 9021772Sjl139090 cmn_err(CE_WARN, "Max message size expected >= %ld " 9031772Sjl139090 "but found %d\n", sizeof (okm_rep_hdr_t), okmsp->km_maxsz); 9041772Sjl139090 ret = EIO; 9051772Sjl139090 } 9061772Sjl139090 if (ret != 0) { 9071772Sjl139090 okmsp->km_state &= ~OKM_MB_INITED; 9081772Sjl139090 (void) scf_mb_fini(okmsp->km_target, okmsp->km_key); 9091772Sjl139090 } 9101772Sjl139090 DPRINTF(DBG_MBOX, ("okm_mbox_init: mb_init ret=%d\n", ret)); 9111772Sjl139090 return (ret); 9121772Sjl139090 } 9131772Sjl139090 9141772Sjl139090 /* 9151772Sjl139090 * okm_mbox_fini - Mailbox de-initialization. 9161772Sjl139090 */ 9171772Sjl139090 static void 9181772Sjl139090 okm_mbox_fini(okms_t *okmsp) 9191772Sjl139090 { 9201772Sjl139090 int ret = 0; 9211772Sjl139090 9221772Sjl139090 ASSERT(MUTEX_HELD(&okmsp->km_lock)); 9231772Sjl139090 if (okmsp->km_state & OKM_MB_INITED) { 9241772Sjl139090 DPRINTF(DBG_MBOX, ("okm_mbox_fini: calling mb_fini\n")); 9251772Sjl139090 ret = scf_mb_fini(okmsp->km_target, okmsp->km_key); 9261772Sjl139090 DPRINTF(DBG_MBOX, ("okm_mbox_fini: mb_fini ret=%d\n", ret)); 9271772Sjl139090 if (ret != 0) { 9281772Sjl139090 cmn_err(CE_WARN, 9291772Sjl139090 "Failed to close the Mailbox error=%d", ret); 9301772Sjl139090 } 9311772Sjl139090 okmsp->km_state &= ~(OKM_MB_INITED | OKM_MB_CONN | OKM_MB_DISC); 9321772Sjl139090 } 9331772Sjl139090 } 9341772Sjl139090 9351772Sjl139090 /* 9361772Sjl139090 * okm_event_handler - Mailbox event handler. 9371772Sjl139090 * 9381772Sjl139090 * Description: Implements a state machine to handle all the mailbox 9391772Sjl139090 * events. For each event, it sets the appropriate state 9401772Sjl139090 * flag and wakes up the threads waiting for that event. 9411772Sjl139090 */ 9421772Sjl139090 void 9431772Sjl139090 okm_event_handler(scf_event_t event, void *arg) 9441772Sjl139090 { 9451772Sjl139090 okms_t *okmsp = (okms_t *)arg; 9461772Sjl139090 9471772Sjl139090 DPRINTF(DBG_MBOX, ("okm_event_handler: called\n")); 9481772Sjl139090 ASSERT(okmsp != NULL); 9491772Sjl139090 mutex_enter(&okmsp->km_lock); 9501772Sjl139090 if (!(okmsp->km_state & OKM_MB_INITED)) { 9511772Sjl139090 /* 9521772Sjl139090 * Ignore all events if the state flag indicates that the 9531772Sjl139090 * mailbox not initialized, this may happen during the close. 9541772Sjl139090 */ 9551772Sjl139090 mutex_exit(&okmsp->km_lock); 9561772Sjl139090 DPRINTF(DBG_MBOX, 9571772Sjl139090 ("okm_event_handler: event=0x%X - mailbox not inited \n", 9581772Sjl139090 event)); 9591772Sjl139090 return; 9601772Sjl139090 } 9611772Sjl139090 switch (event) { 9621772Sjl139090 case SCF_MB_CONN_OK: 9631772Sjl139090 DPRINTF(DBG_MBOX, ("okm_event_handler: Event CONN_OK\n")); 9641772Sjl139090 /* 9651772Sjl139090 * Now the mailbox is ready to use, lets wake up 9661772Sjl139090 * any one waiting for this event. 9671772Sjl139090 */ 9681772Sjl139090 okmsp->km_state |= OKM_MB_CONN; 9691772Sjl139090 cv_broadcast(&okmsp->km_wait); 9701772Sjl139090 break; 9711772Sjl139090 9721772Sjl139090 case SCF_MB_MSG_DATA: 9731772Sjl139090 DPRINTF(DBG_MBOX, ("okm_event_handler: Event MSG_DATA\n")); 9741772Sjl139090 /* 9751772Sjl139090 * A message is available in the mailbox, 9761772Sjl139090 * wakeup if any one is ready to read the message. 9771772Sjl139090 */ 9781772Sjl139090 if (OKM_MBOX_READY(okmsp)) { 9791772Sjl139090 cv_broadcast(&okmsp->km_wait); 9801772Sjl139090 } 9811772Sjl139090 break; 9821772Sjl139090 9831772Sjl139090 case SCF_MB_SPACE: 9841772Sjl139090 DPRINTF(DBG_MBOX, ("okm_event_handler: Event MB_SPACE\n")); 9851772Sjl139090 /* 9861772Sjl139090 * Now the mailbox is ready to transmit, lets 9871772Sjl139090 * wakeup if any one is waiting to write. 9881772Sjl139090 */ 9891772Sjl139090 if (OKM_MBOX_READY(okmsp)) { 9901772Sjl139090 cv_broadcast(&okmsp->km_wait); 9911772Sjl139090 } 9921772Sjl139090 break; 9931772Sjl139090 case SCF_MB_DISC_ERROR: 9941772Sjl139090 DPRINTF(DBG_MBOX, ("okm_event_handler: Event DISC_ERROR\n")); 9951772Sjl139090 okmsp->km_state &= ~OKM_MB_CONN; 9961772Sjl139090 okmsp->km_state |= OKM_MB_DISC; 9971772Sjl139090 cv_broadcast(&okmsp->km_wait); 9981772Sjl139090 break; 9991772Sjl139090 default: 10001772Sjl139090 cmn_err(CE_WARN, "Unexpected event received\n"); 10011772Sjl139090 } 10021772Sjl139090 mutex_exit(&okmsp->km_lock); 10031772Sjl139090 } 10041772Sjl139090 10051772Sjl139090 /* 10061772Sjl139090 * okm_send_reply - Send a mailbox reply message. 10071772Sjl139090 */ 10081772Sjl139090 int 10091772Sjl139090 okm_send_reply(okms_t *okmsp, uint32_t transid, 10101772Sjl139090 uint32_t status, uint32_t sadb_err, uint32_t sadb_ver) 10111772Sjl139090 { 10121772Sjl139090 okm_rep_hdr_t reply; 10131772Sjl139090 int ret = EIO; 10141772Sjl139090 10151772Sjl139090 DPRINTF(DBG_DRV, ("okm_send_reply: called\n")); 10161772Sjl139090 ASSERT(MUTEX_HELD(&okmsp->km_lock)); 10171772Sjl139090 reply.krp_version = htonl(OKM_PROTOCOL_VERSION); 10181772Sjl139090 reply.krp_transid = htonl(transid); 10191772Sjl139090 reply.krp_status = htonl(status); 10201772Sjl139090 reply.krp_sadb_errno = htonl(sadb_err); 10211772Sjl139090 reply.krp_sadb_version = htonl(sadb_ver); 10221772Sjl139090 okmsp->km_sg_tx.msc_dptr = (caddr_t)&reply; 10231772Sjl139090 okmsp->km_sg_tx.msc_len = sizeof (reply); 10241772Sjl139090 DUMP_REPLY(&reply); 10251772Sjl139090 10261772Sjl139090 while (OKM_MBOX_READY(okmsp)) { 10271772Sjl139090 DPRINTF(DBG_MBOX, ("okm_send_reply: sending reply\n")); 10281772Sjl139090 ret = scf_mb_putmsg(okmsp->km_target, okmsp->km_key, 10291772Sjl139090 sizeof (reply), 1, &okmsp->km_sg_tx, 0); 10301772Sjl139090 DPRINTF(DBG_MBOX, ("okm_send_reply: putmsg ret=%d\n", ret)); 10311772Sjl139090 if (ret == EBUSY || ret == ENOSPC) { 10321772Sjl139090 /* mailbox is busy, poll/retry */ 10331772Sjl139090 if (cv_timedwait_sig(&okmsp->km_wait, 10341772Sjl139090 &okmsp->km_lock, okm_timeout_val(ret)) == 0) { 10351772Sjl139090 /* interrupted */ 10361772Sjl139090 ret = EINTR; 10371772Sjl139090 DPRINTF(DBG_DRV, 10381772Sjl139090 ("okm_send_reply: interrupted\n")); 10391772Sjl139090 break; 10401772Sjl139090 } 10411772Sjl139090 } else { 10421772Sjl139090 break; 10431772Sjl139090 } 10441772Sjl139090 } 10451772Sjl139090 DPRINTF(DBG_DRV, ("okm_send_reply: ret=%d\n", ret)); 10461772Sjl139090 return (ret); 10471772Sjl139090 } 10481772Sjl139090 10491772Sjl139090 /* 10501772Sjl139090 * okm_timeout_val -- Return appropriate timeout value. 10511772Sjl139090 * 10521772Sjl139090 * A small timeout value is returned for EBUSY as the mailbox busy 10531772Sjl139090 * condition may go away sooner and we are expected to poll. 10541772Sjl139090 * 10551772Sjl139090 * A larger timeout value is returned for ENOSPC case, as the condition 10561772Sjl139090 * depends on the peer to release buffer space. 10571772Sjl139090 * NOTE: there will also be an event(SCF_MB_SPACE) but a timeout is 10581772Sjl139090 * used for reliability purposes. 10591772Sjl139090 */ 10601772Sjl139090 static clock_t 10611772Sjl139090 okm_timeout_val(int error) 10621772Sjl139090 { 10631772Sjl139090 clock_t tval; 10641772Sjl139090 10651772Sjl139090 ASSERT(error == EBUSY || error == ENOSPC); 10661772Sjl139090 10671772Sjl139090 if (error == EBUSY) { 10681772Sjl139090 tval = OKM_SM_TOUT; 10691772Sjl139090 } else { 10701772Sjl139090 tval = OKM_LG_TOUT; 10711772Sjl139090 } 10721772Sjl139090 return (drv_usectohz(tval)); 10731772Sjl139090 } 10741772Sjl139090 10751772Sjl139090 #ifdef DEBUG 10761772Sjl139090 static void 10771772Sjl139090 okm_print_req(okm_req_hdr_t *reqp, uint32_t len) 10781772Sjl139090 { 10791772Sjl139090 uint8_t *datap = (uint8_t *)(((char *)reqp) + sizeof (okm_req_hdr_t)); 10801772Sjl139090 int msglen = len - sizeof (okm_req_hdr_t); 10811772Sjl139090 int i, j; 10821772Sjl139090 #define BYTES_PER_LINE 20 10831772Sjl139090 char bytestr[BYTES_PER_LINE * 3 + 1]; 10841772Sjl139090 10851772Sjl139090 if (!(okm_debug & DBG_MESG)) 10861772Sjl139090 return; 10871772Sjl139090 printf("OKM: Request ver=%d transid=%d cmd=%s\n", 10881772Sjl139090 reqp->krq_version, reqp->krq_transid, 10891772Sjl139090 ((reqp->krq_cmd == OKM_MSG_SADB) ? "MSG_SADB" : "UNKNOWN")); 10901772Sjl139090 for (i = 0; i < msglen; ) { 10911772Sjl139090 for (j = 0; (j < BYTES_PER_LINE) && (i < msglen); j++, i++) { 10921772Sjl139090 sprintf(&bytestr[j * 3], "%02X ", datap[i]); 10931772Sjl139090 } 10941772Sjl139090 if (j != 0) { 10951772Sjl139090 printf("\t%s\n", bytestr); 10961772Sjl139090 } 10971772Sjl139090 } 10981772Sjl139090 } 10991772Sjl139090 11001772Sjl139090 static void 11011772Sjl139090 okm_print_rep(okm_rep_hdr_t *repp) 11021772Sjl139090 { 11031772Sjl139090 if (!(okm_debug & DBG_MESG)) 11041772Sjl139090 return; 11051772Sjl139090 printf("OKM: Reply Ver=%d Transid=%d Status=%d ", 11061772Sjl139090 repp->krp_version, repp->krp_transid, repp->krp_status); 11071772Sjl139090 printf("Sadb_errno=%d Sadb_ver=%d\n", repp->krp_sadb_errno, 11081772Sjl139090 repp->krp_sadb_version); 11091772Sjl139090 } 11101772Sjl139090 #endif 1111