/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Commmon routines, handling iscsi boot props */ #include #include #include #include #include #include #include extern void *memset(void *s, int c, size_t n); extern int memcmp(const void *s1, const void *s2, size_t n); extern void bcopy(const void *s1, void *s2, size_t n); extern size_t strlen(const char *s); static void kinet_ntoa(char *buf, void *in, int af); extern ib_boot_prop_t *iscsiboot_prop; int iscsi_print_bootprop = 0; #define ISCSI_BOOTPROP_BUFLEN 256 static int replace_sp_c(unsigned char *dst, unsigned char *source, size_t n); static void iscsi_bootprop_print(int level, char *str) { if (str == NULL) { return; } if (iscsi_print_bootprop == 1) { cmn_err(level, "%s", str); } } static void iscsi_print_initiator_property(ib_ini_prop_t *ibinitp) { char outbuf[ISCSI_BOOTPROP_BUFLEN] = {0}; if (ibinitp == NULL) { return; } if (ibinitp->ini_name != NULL) { (void) sprintf(outbuf, "Initiator Name : %s\n", ibinitp->ini_name); iscsi_bootprop_print(CE_CONT, outbuf); } if (ibinitp->ini_chap_name != NULL) { (void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN); (void) sprintf(outbuf, "Initiator CHAP Name : %s\n", ibinitp->ini_chap_name); iscsi_bootprop_print(CE_CONT, outbuf); } } static void iscsi_print_nic_property(ib_nic_prop_t *nicp) { char outbuf[ISCSI_BOOTPROP_BUFLEN] = {0}; char ipaddr[50] = {0}; int n = 0; if (nicp == NULL) { return; } kinet_ntoa(ipaddr, &nicp->nic_ip_u, nicp->sin_family); n = snprintf(outbuf, ISCSI_BOOTPROP_BUFLEN, "Local IP addr : %s\n", ipaddr); (void) memset(ipaddr, 0, 50); kinet_ntoa(ipaddr, &nicp->nic_gw_u, nicp->sin_family); n = n + snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n, "Local gateway : %s\n", ipaddr); (void) memset(ipaddr, 0, 50); kinet_ntoa(ipaddr, &nicp->nic_dhcp_u, nicp->sin_family); n = n + snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n, "Local DHCP : %s\n", ipaddr); (void) snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n, "Local MAC : %02x:%02x:%02x:%02x:%02x:%02x\n", nicp->nic_mac[0], nicp->nic_mac[1], nicp->nic_mac[2], nicp->nic_mac[3], nicp->nic_mac[4], nicp->nic_mac[5]); iscsi_bootprop_print(CE_CONT, outbuf); } static void iscsi_print_tgt_property(ib_tgt_prop_t *itgtp) { char outbuf[ISCSI_BOOTPROP_BUFLEN] = {0}; char ipaddr[50] = {0}; if (itgtp == NULL) { return; } if (itgtp->tgt_name != NULL) { (void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN); (void) sprintf(outbuf, "Target Name : %s\n", itgtp->tgt_name); iscsi_bootprop_print(CE_CONT, outbuf); } kinet_ntoa(ipaddr, &itgtp->tgt_ip_u, itgtp->sin_family); (void) sprintf(outbuf, "Target IP : %s\n" "Target Port : %d\n" "Boot LUN : %02x%02x-%02x%02x-%02x%02x-%02x%02x\n", ipaddr, itgtp->tgt_port, itgtp->tgt_boot_lun[0], itgtp->tgt_boot_lun[1], itgtp->tgt_boot_lun[2], itgtp->tgt_boot_lun[3], itgtp->tgt_boot_lun[4], itgtp->tgt_boot_lun[5], itgtp->tgt_boot_lun[6], itgtp->tgt_boot_lun[7]); iscsi_bootprop_print(CE_CONT, outbuf); if (itgtp->tgt_chap_name != NULL) { (void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN); (void) sprintf(outbuf, "CHAP Name : %s\n", itgtp->tgt_chap_name); iscsi_bootprop_print(CE_CONT, outbuf); } } void iscsi_print_boot_property() { if (iscsiboot_prop == NULL) { return; } iscsi_print_initiator_property( &iscsiboot_prop->boot_init); iscsi_print_nic_property(&iscsiboot_prop->boot_nic); iscsi_print_tgt_property(&iscsiboot_prop->boot_tgt); } void iscsi_boot_free_ini(ib_ini_prop_t *init) { if (init == NULL) { return; } if (init->ini_name != NULL) { kmem_free(init->ini_name, init->ini_name_len); init->ini_name = NULL; init->ini_name_len = 0; } if (init->ini_chap_name != NULL) { kmem_free(init->ini_chap_name, init->ini_chap_name_len); init->ini_chap_name = NULL; init->ini_chap_name_len = 0; } if (init->ini_chap_sec != NULL) { kmem_free(init->ini_chap_sec, init->ini_chap_sec_len); init->ini_chap_sec = NULL; init->ini_chap_sec_len = 0; } } void iscsi_boot_free_tgt(ib_tgt_prop_t *target) { if (target == NULL) { return; } if (target->tgt_name != NULL) { kmem_free(target->tgt_name, target->tgt_name_len); target->tgt_name = NULL; target->tgt_name_len = 0; } if (target->tgt_chap_name != NULL) { kmem_free(target->tgt_chap_name, target->tgt_chap_name_len); target->tgt_chap_name = NULL; target->tgt_chap_name_len = 0; } if (target->tgt_chap_sec != NULL) { kmem_free(target->tgt_chap_sec, target->tgt_chap_sec_len); target->tgt_chap_sec = NULL; target->tgt_chap_sec_len = 0; } if (target->tgt_boot_par != NULL) { kmem_free(target->tgt_boot_par, target->tgt_boot_par_len); target->tgt_boot_par = NULL; target->tgt_boot_par_len = 0; } } /* * Free the memory used by boot property. */ void iscsi_boot_prop_free() { ib_boot_prop_t *tmp; if (iscsiboot_prop == NULL) { return; } tmp = iscsiboot_prop; iscsiboot_prop = NULL; iscsi_boot_free_ini(&(tmp->boot_init)); iscsi_boot_free_tgt(&(tmp->boot_tgt)); } static void kinet_ntoa(char *buf, void *in, int af) { unsigned char *p = NULL; int i = 0; if (buf == NULL || in == NULL) { return; } p = (unsigned char *)in; if (af == AF_INET) { (void) sprintf(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); } else { for (i = 0; i < 14; i = i + 2) { (void) sprintf(buf, "%02x%02x:", p[i], p[i+1]); buf = buf + 5; } (void) sprintf(buf, "%02x%02x", p[i], p[i+1]); } } #ifndef BO_MAXOBJNAME #define BO_MAXOBJNAME 256 #endif #ifndef ISCSI_BOOT_ISID #define ISCSI_BOOT_ISID "0000" #endif /* * Generate the 'ssd' bootpath of an iSCSI boot device * The caller is responsible to alloc the buf with BO_MAXOBJNAME length */ void get_iscsi_bootpath_vhci(char *bootpath) { uint16_t *lun_num; if (iscsiboot_prop == NULL) ld_ib_prop(); if (iscsiboot_prop == NULL) return; lun_num = (uint16_t *)(&iscsiboot_prop->boot_tgt.tgt_boot_lun[0]); (void) snprintf(bootpath, BO_MAXOBJNAME, "/iscsi/ssd@%s%s%04X,%d:%s", ISCSI_BOOT_ISID, iscsiboot_prop->boot_tgt.tgt_name, iscsiboot_prop->boot_tgt.tgt_tpgt, lun_num[0], iscsiboot_prop->boot_tgt.tgt_boot_par); } /* * Generate the 'disk' bootpath of an iSCSI boot device * The caller is responsible to alloc the buf with BO_MAXOBJNAME length */ void get_iscsi_bootpath_phy(char *bootpath) { uint16_t lun_num = 0; uchar_t replaced_name[BO_MAXOBJNAME] = {0}; if (iscsiboot_prop == NULL) ld_ib_prop(); if (iscsiboot_prop == NULL) return; if (replace_sp_c(replaced_name, iscsiboot_prop->boot_tgt.tgt_name, iscsiboot_prop->boot_tgt.tgt_name_len) != 0) { return; } lun_num = *(uint16_t *)(&iscsiboot_prop->boot_tgt.tgt_boot_lun[0]); (void) snprintf(bootpath, BO_MAXOBJNAME, "/iscsi/disk@%s%s%04X,%d:%s", ISCSI_BOOT_ISID, replaced_name, iscsiboot_prop->boot_tgt.tgt_tpgt, lun_num, iscsiboot_prop->boot_tgt.tgt_boot_par); } static int replace_sp_c(unsigned char *dst, unsigned char *source, size_t n) { unsigned char *p = NULL; int i = 0; if (source == NULL || dst == NULL || n == 0) { return (-1); } for (p = source; *p != '\0'; p++, i++) { if (i >= n) { return (-1); } switch (*p) { case ':': *dst = '%'; dst++; *dst = '3'; dst++; *dst = 'A'; dst++; break; case ' ': *dst = '%'; dst++; *dst = '2'; dst++; *dst = '0'; dst++; break; case '@': *dst = '%'; dst++; *dst = '4'; dst++; *dst = '0'; dst++; break; case '/': *dst = '%'; dst++; *dst = '2'; dst++; *dst = 'F'; dst++; break; default: *dst = *p; dst++; } } *dst = '\0'; return (0); }