16cefaae1SJack Meng /* 26cefaae1SJack Meng * CDDL HEADER START 36cefaae1SJack Meng * 46cefaae1SJack Meng * The contents of this file are subject to the terms of the 56cefaae1SJack Meng * Common Development and Distribution License (the "License"). 66cefaae1SJack Meng * You may not use this file except in compliance with the License. 76cefaae1SJack Meng * 86cefaae1SJack Meng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 96cefaae1SJack Meng * or http://www.opensolaris.org/os/licensing. 106cefaae1SJack Meng * See the License for the specific language governing permissions 116cefaae1SJack Meng * and limitations under the License. 126cefaae1SJack Meng * 136cefaae1SJack Meng * When distributing Covered Code, include this CDDL HEADER in each 146cefaae1SJack Meng * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 156cefaae1SJack Meng * If applicable, add the following below this CDDL HEADER, with the 166cefaae1SJack Meng * fields enclosed by brackets "[]" replaced with your own identifying 176cefaae1SJack Meng * information: Portions Copyright [yyyy] [name of copyright owner] 186cefaae1SJack Meng * 196cefaae1SJack Meng * CDDL HEADER END 206cefaae1SJack Meng */ 216cefaae1SJack Meng 226cefaae1SJack Meng /* 23dedec472SJack Meng * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 246cefaae1SJack Meng * Use is subject to license terms. 256cefaae1SJack Meng */ 266cefaae1SJack Meng 276cefaae1SJack Meng /* 286cefaae1SJack Meng * Commmon routines, handling iscsi boot props 296cefaae1SJack Meng */ 306cefaae1SJack Meng 316cefaae1SJack Meng #include <sys/types.h> 32*4870e0a7SRichard PALO #include <sys/null.h> 336cefaae1SJack Meng #include <sys/bootprops.h> 346cefaae1SJack Meng #include <sys/cmn_err.h> 356cefaae1SJack Meng #include <sys/socket.h> 366cefaae1SJack Meng #include <sys/kmem.h> 376cefaae1SJack Meng #include <netinet/in.h> 386cefaae1SJack Meng 396cefaae1SJack Meng extern void *memset(void *s, int c, size_t n); 406cefaae1SJack Meng extern int memcmp(const void *s1, const void *s2, size_t n); 416cefaae1SJack Meng extern void bcopy(const void *s1, void *s2, size_t n); 426cefaae1SJack Meng extern size_t strlen(const char *s); 436cefaae1SJack Meng static void kinet_ntoa(char *buf, void *in, int af); 446cefaae1SJack Meng extern ib_boot_prop_t *iscsiboot_prop; 456cefaae1SJack Meng 466cefaae1SJack Meng int iscsi_print_bootprop = 0; 476cefaae1SJack Meng 486cefaae1SJack Meng #define ISCSI_BOOTPROP_BUFLEN 256 496cefaae1SJack Meng 50dedec472SJack Meng static int replace_sp_c(unsigned char *dst, unsigned char *source, size_t n); 51dedec472SJack Meng 526cefaae1SJack Meng static void 536cefaae1SJack Meng iscsi_bootprop_print(int level, char *str) 546cefaae1SJack Meng { 556cefaae1SJack Meng if (str == NULL) { 566cefaae1SJack Meng return; 576cefaae1SJack Meng } 586cefaae1SJack Meng if (iscsi_print_bootprop == 1) { 596cefaae1SJack Meng cmn_err(level, "%s", str); 606cefaae1SJack Meng } 616cefaae1SJack Meng } 626cefaae1SJack Meng 636cefaae1SJack Meng static void 646cefaae1SJack Meng iscsi_print_initiator_property(ib_ini_prop_t *ibinitp) 656cefaae1SJack Meng { 666cefaae1SJack Meng char outbuf[ISCSI_BOOTPROP_BUFLEN] = {0}; 676cefaae1SJack Meng 686cefaae1SJack Meng if (ibinitp == NULL) { 696cefaae1SJack Meng return; 706cefaae1SJack Meng } 716cefaae1SJack Meng 726cefaae1SJack Meng if (ibinitp->ini_name != NULL) { 736cefaae1SJack Meng (void) sprintf(outbuf, 746cefaae1SJack Meng "Initiator Name : %s\n", 756cefaae1SJack Meng ibinitp->ini_name); 766cefaae1SJack Meng iscsi_bootprop_print(CE_CONT, outbuf); 776cefaae1SJack Meng } 786cefaae1SJack Meng 796cefaae1SJack Meng if (ibinitp->ini_chap_name != NULL) { 806cefaae1SJack Meng (void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN); 816cefaae1SJack Meng (void) sprintf(outbuf, 826cefaae1SJack Meng "Initiator CHAP Name : %s\n", 836cefaae1SJack Meng ibinitp->ini_chap_name); 846cefaae1SJack Meng 856cefaae1SJack Meng iscsi_bootprop_print(CE_CONT, outbuf); 866cefaae1SJack Meng } 876cefaae1SJack Meng } 886cefaae1SJack Meng 896cefaae1SJack Meng static void 906cefaae1SJack Meng iscsi_print_nic_property(ib_nic_prop_t *nicp) 916cefaae1SJack Meng { 926cefaae1SJack Meng char outbuf[ISCSI_BOOTPROP_BUFLEN] = {0}; 936cefaae1SJack Meng char ipaddr[50] = {0}; 946cefaae1SJack Meng int n = 0; 956cefaae1SJack Meng 966cefaae1SJack Meng if (nicp == NULL) { 976cefaae1SJack Meng return; 986cefaae1SJack Meng } 996cefaae1SJack Meng 1006cefaae1SJack Meng kinet_ntoa(ipaddr, &nicp->nic_ip_u, nicp->sin_family); 1016cefaae1SJack Meng n = snprintf(outbuf, ISCSI_BOOTPROP_BUFLEN, 1026cefaae1SJack Meng "Local IP addr : %s\n", ipaddr); 1036cefaae1SJack Meng 1046cefaae1SJack Meng (void) memset(ipaddr, 0, 50); 1056cefaae1SJack Meng kinet_ntoa(ipaddr, &nicp->nic_gw_u, nicp->sin_family); 1066cefaae1SJack Meng n = n + snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n, 1076cefaae1SJack Meng "Local gateway : %s\n", ipaddr); 1086cefaae1SJack Meng 1096cefaae1SJack Meng (void) memset(ipaddr, 0, 50); 1106cefaae1SJack Meng kinet_ntoa(ipaddr, &nicp->nic_dhcp_u, nicp->sin_family); 1116cefaae1SJack Meng n = n + snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n, 1126cefaae1SJack Meng "Local DHCP : %s\n", ipaddr); 1136cefaae1SJack Meng 1146cefaae1SJack Meng (void) snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n, 1156cefaae1SJack Meng "Local MAC : %02x:%02x:%02x:%02x:%02x:%02x\n", 1166cefaae1SJack Meng nicp->nic_mac[0], 1176cefaae1SJack Meng nicp->nic_mac[1], 1186cefaae1SJack Meng nicp->nic_mac[2], 1196cefaae1SJack Meng nicp->nic_mac[3], 1206cefaae1SJack Meng nicp->nic_mac[4], 1216cefaae1SJack Meng nicp->nic_mac[5]); 1226cefaae1SJack Meng 1236cefaae1SJack Meng iscsi_bootprop_print(CE_CONT, outbuf); 1246cefaae1SJack Meng } 1256cefaae1SJack Meng 1266cefaae1SJack Meng static void 1276cefaae1SJack Meng iscsi_print_tgt_property(ib_tgt_prop_t *itgtp) 1286cefaae1SJack Meng { 1296cefaae1SJack Meng char outbuf[ISCSI_BOOTPROP_BUFLEN] = {0}; 1306cefaae1SJack Meng char ipaddr[50] = {0}; 1316cefaae1SJack Meng 1326cefaae1SJack Meng if (itgtp == NULL) { 1336cefaae1SJack Meng return; 1346cefaae1SJack Meng } 1356cefaae1SJack Meng 1366cefaae1SJack Meng if (itgtp->tgt_name != NULL) { 1376cefaae1SJack Meng (void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN); 1386cefaae1SJack Meng (void) sprintf(outbuf, 1396cefaae1SJack Meng "Target Name : %s\n", 1406cefaae1SJack Meng itgtp->tgt_name); 1416cefaae1SJack Meng iscsi_bootprop_print(CE_CONT, outbuf); 1426cefaae1SJack Meng } 1436cefaae1SJack Meng 1446cefaae1SJack Meng kinet_ntoa(ipaddr, &itgtp->tgt_ip_u, itgtp->sin_family); 1456cefaae1SJack Meng (void) sprintf(outbuf, 1466cefaae1SJack Meng "Target IP : %s\n" 1476cefaae1SJack Meng "Target Port : %d\n" 1486cefaae1SJack Meng "Boot LUN : %02x%02x-%02x%02x-%02x%02x-%02x%02x\n", 1496cefaae1SJack Meng ipaddr, 1506cefaae1SJack Meng itgtp->tgt_port, 1516cefaae1SJack Meng itgtp->tgt_boot_lun[0], 1526cefaae1SJack Meng itgtp->tgt_boot_lun[1], 1536cefaae1SJack Meng itgtp->tgt_boot_lun[2], 1546cefaae1SJack Meng itgtp->tgt_boot_lun[3], 1556cefaae1SJack Meng itgtp->tgt_boot_lun[4], 1566cefaae1SJack Meng itgtp->tgt_boot_lun[5], 1576cefaae1SJack Meng itgtp->tgt_boot_lun[6], 1586cefaae1SJack Meng itgtp->tgt_boot_lun[7]); 1596cefaae1SJack Meng iscsi_bootprop_print(CE_CONT, outbuf); 1606cefaae1SJack Meng 1616cefaae1SJack Meng if (itgtp->tgt_chap_name != NULL) { 1626cefaae1SJack Meng (void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN); 1636cefaae1SJack Meng (void) sprintf(outbuf, 1646cefaae1SJack Meng "CHAP Name : %s\n", 1656cefaae1SJack Meng itgtp->tgt_chap_name); 1666cefaae1SJack Meng iscsi_bootprop_print(CE_CONT, outbuf); 1676cefaae1SJack Meng } 1686cefaae1SJack Meng } 1696cefaae1SJack Meng 1706cefaae1SJack Meng void 1716cefaae1SJack Meng iscsi_print_boot_property() 1726cefaae1SJack Meng { 1736cefaae1SJack Meng if (iscsiboot_prop == NULL) { 1746cefaae1SJack Meng return; 1756cefaae1SJack Meng } 1766cefaae1SJack Meng 1776cefaae1SJack Meng iscsi_print_initiator_property( 1786cefaae1SJack Meng &iscsiboot_prop->boot_init); 1796cefaae1SJack Meng 1806cefaae1SJack Meng iscsi_print_nic_property(&iscsiboot_prop->boot_nic); 1816cefaae1SJack Meng 1826cefaae1SJack Meng iscsi_print_tgt_property(&iscsiboot_prop->boot_tgt); 1836cefaae1SJack Meng } 1846cefaae1SJack Meng 1856cefaae1SJack Meng void 1866cefaae1SJack Meng iscsi_boot_free_ini(ib_ini_prop_t *init) 1876cefaae1SJack Meng { 1886cefaae1SJack Meng if (init == NULL) { 1896cefaae1SJack Meng return; 1906cefaae1SJack Meng } 1916cefaae1SJack Meng 1926cefaae1SJack Meng if (init->ini_name != NULL) { 193dedec472SJack Meng kmem_free(init->ini_name, init->ini_name_len); 1946cefaae1SJack Meng init->ini_name = NULL; 195dedec472SJack Meng init->ini_name_len = 0; 1966cefaae1SJack Meng } 1976cefaae1SJack Meng if (init->ini_chap_name != NULL) { 1986cefaae1SJack Meng kmem_free(init->ini_chap_name, 199dedec472SJack Meng init->ini_chap_name_len); 2006cefaae1SJack Meng init->ini_chap_name = NULL; 201dedec472SJack Meng init->ini_chap_name_len = 0; 2026cefaae1SJack Meng } 2036cefaae1SJack Meng if (init->ini_chap_sec != NULL) { 2046cefaae1SJack Meng kmem_free(init->ini_chap_sec, 205dedec472SJack Meng init->ini_chap_sec_len); 2066cefaae1SJack Meng init->ini_chap_sec = NULL; 207dedec472SJack Meng init->ini_chap_sec_len = 0; 2086cefaae1SJack Meng } 2096cefaae1SJack Meng } 2106cefaae1SJack Meng 2116cefaae1SJack Meng void 2126cefaae1SJack Meng iscsi_boot_free_tgt(ib_tgt_prop_t *target) 2136cefaae1SJack Meng { 2146cefaae1SJack Meng if (target == NULL) { 2156cefaae1SJack Meng return; 2166cefaae1SJack Meng } 2176cefaae1SJack Meng 2186cefaae1SJack Meng if (target->tgt_name != NULL) { 2196cefaae1SJack Meng kmem_free(target->tgt_name, 220dedec472SJack Meng target->tgt_name_len); 2216cefaae1SJack Meng target->tgt_name = NULL; 222dedec472SJack Meng target->tgt_name_len = 0; 2236cefaae1SJack Meng } 2246cefaae1SJack Meng if (target->tgt_chap_name != NULL) { 2256cefaae1SJack Meng kmem_free(target->tgt_chap_name, 226dedec472SJack Meng target->tgt_chap_name_len); 2276cefaae1SJack Meng target->tgt_chap_name = NULL; 228dedec472SJack Meng target->tgt_chap_name_len = 0; 2296cefaae1SJack Meng } 2306cefaae1SJack Meng if (target->tgt_chap_sec != NULL) { 2316cefaae1SJack Meng kmem_free(target->tgt_chap_sec, 232dedec472SJack Meng target->tgt_chap_sec_len); 2336cefaae1SJack Meng target->tgt_chap_sec = NULL; 234dedec472SJack Meng target->tgt_chap_sec_len = 0; 235dedec472SJack Meng } 236dedec472SJack Meng if (target->tgt_boot_par != NULL) { 237dedec472SJack Meng kmem_free(target->tgt_boot_par, 238dedec472SJack Meng target->tgt_boot_par_len); 239dedec472SJack Meng target->tgt_boot_par = NULL; 240dedec472SJack Meng target->tgt_boot_par_len = 0; 2416cefaae1SJack Meng } 2426cefaae1SJack Meng } 2436cefaae1SJack Meng 2446cefaae1SJack Meng /* 2456cefaae1SJack Meng * Free the memory used by boot property. 2466cefaae1SJack Meng */ 2476cefaae1SJack Meng void 2486cefaae1SJack Meng iscsi_boot_prop_free() 2496cefaae1SJack Meng { 2506cefaae1SJack Meng ib_boot_prop_t *tmp; 2516cefaae1SJack Meng 2526cefaae1SJack Meng if (iscsiboot_prop == NULL) { 2536cefaae1SJack Meng return; 2546cefaae1SJack Meng } 2556cefaae1SJack Meng tmp = iscsiboot_prop; 2566cefaae1SJack Meng iscsiboot_prop = NULL; 2576cefaae1SJack Meng iscsi_boot_free_ini(&(tmp->boot_init)); 2586cefaae1SJack Meng iscsi_boot_free_tgt(&(tmp->boot_tgt)); 2596cefaae1SJack Meng } 2606cefaae1SJack Meng 2616cefaae1SJack Meng static void 2626cefaae1SJack Meng kinet_ntoa(char *buf, void *in, int af) 2636cefaae1SJack Meng { 2646cefaae1SJack Meng unsigned char *p = NULL; 2656cefaae1SJack Meng int i = 0; 2666cefaae1SJack Meng 2676cefaae1SJack Meng if (buf == NULL || in == NULL) { 2686cefaae1SJack Meng return; 2696cefaae1SJack Meng } 2706cefaae1SJack Meng p = (unsigned char *)in; 2716cefaae1SJack Meng if (af == AF_INET) { 2726cefaae1SJack Meng (void) sprintf(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 2736cefaae1SJack Meng } else { 2746cefaae1SJack Meng for (i = 0; i < 14; i = i + 2) { 2756cefaae1SJack Meng (void) sprintf(buf, "%02x%02x:", p[i], p[i+1]); 2766cefaae1SJack Meng buf = buf + 5; 2776cefaae1SJack Meng } 2786cefaae1SJack Meng (void) sprintf(buf, "%02x%02x", p[i], p[i+1]); 2796cefaae1SJack Meng } 2806cefaae1SJack Meng } 281dedec472SJack Meng 282dedec472SJack Meng #ifndef BO_MAXOBJNAME 283dedec472SJack Meng #define BO_MAXOBJNAME 256 284dedec472SJack Meng #endif 285dedec472SJack Meng 286dedec472SJack Meng #ifndef ISCSI_BOOT_ISID 287dedec472SJack Meng #define ISCSI_BOOT_ISID "0000" 288dedec472SJack Meng #endif 289dedec472SJack Meng 290dedec472SJack Meng /* 291dedec472SJack Meng * Generate the 'ssd' bootpath of an iSCSI boot device 292dedec472SJack Meng * The caller is responsible to alloc the buf with BO_MAXOBJNAME length 293dedec472SJack Meng */ 294dedec472SJack Meng void 295dedec472SJack Meng get_iscsi_bootpath_vhci(char *bootpath) 296dedec472SJack Meng { 297dedec472SJack Meng uint16_t *lun_num; 298dedec472SJack Meng 299dedec472SJack Meng if (iscsiboot_prop == NULL) 300dedec472SJack Meng ld_ib_prop(); 301dedec472SJack Meng if (iscsiboot_prop == NULL) 302dedec472SJack Meng return; 303dedec472SJack Meng lun_num = (uint16_t *)(&iscsiboot_prop->boot_tgt.tgt_boot_lun[0]); 304dedec472SJack Meng (void) snprintf(bootpath, BO_MAXOBJNAME, "/iscsi/ssd@%s%s%04X,%d:%s", 305dedec472SJack Meng ISCSI_BOOT_ISID, iscsiboot_prop->boot_tgt.tgt_name, 306dedec472SJack Meng iscsiboot_prop->boot_tgt.tgt_tpgt, lun_num[0], 307dedec472SJack Meng iscsiboot_prop->boot_tgt.tgt_boot_par); 308dedec472SJack Meng } 309dedec472SJack Meng 310dedec472SJack Meng /* 311dedec472SJack Meng * Generate the 'disk' bootpath of an iSCSI boot device 312dedec472SJack Meng * The caller is responsible to alloc the buf with BO_MAXOBJNAME length 313dedec472SJack Meng */ 314dedec472SJack Meng void 315dedec472SJack Meng get_iscsi_bootpath_phy(char *bootpath) 316dedec472SJack Meng { 317dedec472SJack Meng uint16_t lun_num = 0; 318dedec472SJack Meng uchar_t replaced_name[BO_MAXOBJNAME] = {0}; 319dedec472SJack Meng 320dedec472SJack Meng if (iscsiboot_prop == NULL) 321dedec472SJack Meng ld_ib_prop(); 322dedec472SJack Meng if (iscsiboot_prop == NULL) 323dedec472SJack Meng return; 324dedec472SJack Meng if (replace_sp_c(replaced_name, iscsiboot_prop->boot_tgt.tgt_name, 325dedec472SJack Meng iscsiboot_prop->boot_tgt.tgt_name_len) != 0) { 326dedec472SJack Meng return; 327dedec472SJack Meng } 328dedec472SJack Meng lun_num = *(uint16_t *)(&iscsiboot_prop->boot_tgt.tgt_boot_lun[0]); 329dedec472SJack Meng (void) snprintf(bootpath, BO_MAXOBJNAME, "/iscsi/disk@%s%s%04X,%d:%s", 330dedec472SJack Meng ISCSI_BOOT_ISID, replaced_name, iscsiboot_prop->boot_tgt.tgt_tpgt, 331dedec472SJack Meng lun_num, iscsiboot_prop->boot_tgt.tgt_boot_par); 332dedec472SJack Meng } 333dedec472SJack Meng 334dedec472SJack Meng static int replace_sp_c(unsigned char *dst, unsigned char *source, size_t n) 335dedec472SJack Meng { 336dedec472SJack Meng unsigned char *p = NULL; 337dedec472SJack Meng int i = 0; 338dedec472SJack Meng 339dedec472SJack Meng if (source == NULL || dst == NULL || n == 0) { 340dedec472SJack Meng return (-1); 341dedec472SJack Meng } 342dedec472SJack Meng 343dedec472SJack Meng for (p = source; *p != '\0'; p++, i++) { 344dedec472SJack Meng if (i >= n) { 345dedec472SJack Meng return (-1); 346dedec472SJack Meng } 347dedec472SJack Meng switch (*p) { 348dedec472SJack Meng case ':': 349dedec472SJack Meng *dst = '%'; 350dedec472SJack Meng dst++; 351dedec472SJack Meng *dst = '3'; 352dedec472SJack Meng dst++; 353dedec472SJack Meng *dst = 'A'; 354dedec472SJack Meng dst++; 355dedec472SJack Meng break; 356dedec472SJack Meng case ' ': 357dedec472SJack Meng *dst = '%'; 358dedec472SJack Meng dst++; 359dedec472SJack Meng *dst = '2'; 360dedec472SJack Meng dst++; 361dedec472SJack Meng *dst = '0'; 362dedec472SJack Meng dst++; 363dedec472SJack Meng break; 364dedec472SJack Meng case '@': 365dedec472SJack Meng *dst = '%'; 366dedec472SJack Meng dst++; 367dedec472SJack Meng *dst = '4'; 368dedec472SJack Meng dst++; 369dedec472SJack Meng *dst = '0'; 370dedec472SJack Meng dst++; 371dedec472SJack Meng break; 372dedec472SJack Meng case '/': 373dedec472SJack Meng *dst = '%'; 374dedec472SJack Meng dst++; 375dedec472SJack Meng *dst = '2'; 376dedec472SJack Meng dst++; 377dedec472SJack Meng *dst = 'F'; 378dedec472SJack Meng dst++; 379dedec472SJack Meng break; 380dedec472SJack Meng default: 381dedec472SJack Meng *dst = *p; 382dedec472SJack Meng dst++; 383dedec472SJack Meng } 384dedec472SJack Meng } 385dedec472SJack Meng *dst = '\0'; 386dedec472SJack Meng 387dedec472SJack Meng return (0); 388dedec472SJack Meng } 389