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 /*
23*dedec472SJack 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>
326cefaae1SJack Meng #include <sys/bootprops.h>
336cefaae1SJack Meng #include <sys/cmn_err.h>
346cefaae1SJack Meng #include <sys/socket.h>
356cefaae1SJack Meng #include <sys/kmem.h>
366cefaae1SJack Meng #include <netinet/in.h>
376cefaae1SJack Meng
386cefaae1SJack Meng extern void *memset(void *s, int c, size_t n);
396cefaae1SJack Meng extern int memcmp(const void *s1, const void *s2, size_t n);
406cefaae1SJack Meng extern void bcopy(const void *s1, void *s2, size_t n);
416cefaae1SJack Meng extern size_t strlen(const char *s);
426cefaae1SJack Meng static void kinet_ntoa(char *buf, void *in, int af);
436cefaae1SJack Meng extern ib_boot_prop_t *iscsiboot_prop;
446cefaae1SJack Meng
456cefaae1SJack Meng int iscsi_print_bootprop = 0;
466cefaae1SJack Meng
476cefaae1SJack Meng #define ISCSI_BOOTPROP_BUFLEN 256
486cefaae1SJack Meng
496cefaae1SJack Meng #ifndef NULL
506cefaae1SJack Meng #define NULL 0
516cefaae1SJack Meng #endif
526cefaae1SJack Meng
53*dedec472SJack Meng static int replace_sp_c(unsigned char *dst, unsigned char *source, size_t n);
54*dedec472SJack Meng
556cefaae1SJack Meng static void
iscsi_bootprop_print(int level,char * str)566cefaae1SJack Meng iscsi_bootprop_print(int level, char *str)
576cefaae1SJack Meng {
586cefaae1SJack Meng if (str == NULL) {
596cefaae1SJack Meng return;
606cefaae1SJack Meng }
616cefaae1SJack Meng if (iscsi_print_bootprop == 1) {
626cefaae1SJack Meng cmn_err(level, "%s", str);
636cefaae1SJack Meng }
646cefaae1SJack Meng }
656cefaae1SJack Meng
666cefaae1SJack Meng static void
iscsi_print_initiator_property(ib_ini_prop_t * ibinitp)676cefaae1SJack Meng iscsi_print_initiator_property(ib_ini_prop_t *ibinitp)
686cefaae1SJack Meng {
696cefaae1SJack Meng char outbuf[ISCSI_BOOTPROP_BUFLEN] = {0};
706cefaae1SJack Meng
716cefaae1SJack Meng if (ibinitp == NULL) {
726cefaae1SJack Meng return;
736cefaae1SJack Meng }
746cefaae1SJack Meng
756cefaae1SJack Meng if (ibinitp->ini_name != NULL) {
766cefaae1SJack Meng (void) sprintf(outbuf,
776cefaae1SJack Meng "Initiator Name : %s\n",
786cefaae1SJack Meng ibinitp->ini_name);
796cefaae1SJack Meng iscsi_bootprop_print(CE_CONT, outbuf);
806cefaae1SJack Meng }
816cefaae1SJack Meng
826cefaae1SJack Meng if (ibinitp->ini_chap_name != NULL) {
836cefaae1SJack Meng (void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN);
846cefaae1SJack Meng (void) sprintf(outbuf,
856cefaae1SJack Meng "Initiator CHAP Name : %s\n",
866cefaae1SJack Meng ibinitp->ini_chap_name);
876cefaae1SJack Meng
886cefaae1SJack Meng iscsi_bootprop_print(CE_CONT, outbuf);
896cefaae1SJack Meng }
906cefaae1SJack Meng }
916cefaae1SJack Meng
926cefaae1SJack Meng static void
iscsi_print_nic_property(ib_nic_prop_t * nicp)936cefaae1SJack Meng iscsi_print_nic_property(ib_nic_prop_t *nicp)
946cefaae1SJack Meng {
956cefaae1SJack Meng char outbuf[ISCSI_BOOTPROP_BUFLEN] = {0};
966cefaae1SJack Meng char ipaddr[50] = {0};
976cefaae1SJack Meng int n = 0;
986cefaae1SJack Meng
996cefaae1SJack Meng if (nicp == NULL) {
1006cefaae1SJack Meng return;
1016cefaae1SJack Meng }
1026cefaae1SJack Meng
1036cefaae1SJack Meng kinet_ntoa(ipaddr, &nicp->nic_ip_u, nicp->sin_family);
1046cefaae1SJack Meng n = snprintf(outbuf, ISCSI_BOOTPROP_BUFLEN,
1056cefaae1SJack Meng "Local IP addr : %s\n", ipaddr);
1066cefaae1SJack Meng
1076cefaae1SJack Meng (void) memset(ipaddr, 0, 50);
1086cefaae1SJack Meng kinet_ntoa(ipaddr, &nicp->nic_gw_u, nicp->sin_family);
1096cefaae1SJack Meng n = n + snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n,
1106cefaae1SJack Meng "Local gateway : %s\n", ipaddr);
1116cefaae1SJack Meng
1126cefaae1SJack Meng (void) memset(ipaddr, 0, 50);
1136cefaae1SJack Meng kinet_ntoa(ipaddr, &nicp->nic_dhcp_u, nicp->sin_family);
1146cefaae1SJack Meng n = n + snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n,
1156cefaae1SJack Meng "Local DHCP : %s\n", ipaddr);
1166cefaae1SJack Meng
1176cefaae1SJack Meng (void) snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n,
1186cefaae1SJack Meng "Local MAC : %02x:%02x:%02x:%02x:%02x:%02x\n",
1196cefaae1SJack Meng nicp->nic_mac[0],
1206cefaae1SJack Meng nicp->nic_mac[1],
1216cefaae1SJack Meng nicp->nic_mac[2],
1226cefaae1SJack Meng nicp->nic_mac[3],
1236cefaae1SJack Meng nicp->nic_mac[4],
1246cefaae1SJack Meng nicp->nic_mac[5]);
1256cefaae1SJack Meng
1266cefaae1SJack Meng iscsi_bootprop_print(CE_CONT, outbuf);
1276cefaae1SJack Meng }
1286cefaae1SJack Meng
1296cefaae1SJack Meng static void
iscsi_print_tgt_property(ib_tgt_prop_t * itgtp)1306cefaae1SJack Meng iscsi_print_tgt_property(ib_tgt_prop_t *itgtp)
1316cefaae1SJack Meng {
1326cefaae1SJack Meng char outbuf[ISCSI_BOOTPROP_BUFLEN] = {0};
1336cefaae1SJack Meng char ipaddr[50] = {0};
1346cefaae1SJack Meng
1356cefaae1SJack Meng if (itgtp == NULL) {
1366cefaae1SJack Meng return;
1376cefaae1SJack Meng }
1386cefaae1SJack Meng
1396cefaae1SJack Meng if (itgtp->tgt_name != NULL) {
1406cefaae1SJack Meng (void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN);
1416cefaae1SJack Meng (void) sprintf(outbuf,
1426cefaae1SJack Meng "Target Name : %s\n",
1436cefaae1SJack Meng itgtp->tgt_name);
1446cefaae1SJack Meng iscsi_bootprop_print(CE_CONT, outbuf);
1456cefaae1SJack Meng }
1466cefaae1SJack Meng
1476cefaae1SJack Meng kinet_ntoa(ipaddr, &itgtp->tgt_ip_u, itgtp->sin_family);
1486cefaae1SJack Meng (void) sprintf(outbuf,
1496cefaae1SJack Meng "Target IP : %s\n"
1506cefaae1SJack Meng "Target Port : %d\n"
1516cefaae1SJack Meng "Boot LUN : %02x%02x-%02x%02x-%02x%02x-%02x%02x\n",
1526cefaae1SJack Meng ipaddr,
1536cefaae1SJack Meng itgtp->tgt_port,
1546cefaae1SJack Meng itgtp->tgt_boot_lun[0],
1556cefaae1SJack Meng itgtp->tgt_boot_lun[1],
1566cefaae1SJack Meng itgtp->tgt_boot_lun[2],
1576cefaae1SJack Meng itgtp->tgt_boot_lun[3],
1586cefaae1SJack Meng itgtp->tgt_boot_lun[4],
1596cefaae1SJack Meng itgtp->tgt_boot_lun[5],
1606cefaae1SJack Meng itgtp->tgt_boot_lun[6],
1616cefaae1SJack Meng itgtp->tgt_boot_lun[7]);
1626cefaae1SJack Meng iscsi_bootprop_print(CE_CONT, outbuf);
1636cefaae1SJack Meng
1646cefaae1SJack Meng if (itgtp->tgt_chap_name != NULL) {
1656cefaae1SJack Meng (void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN);
1666cefaae1SJack Meng (void) sprintf(outbuf,
1676cefaae1SJack Meng "CHAP Name : %s\n",
1686cefaae1SJack Meng itgtp->tgt_chap_name);
1696cefaae1SJack Meng iscsi_bootprop_print(CE_CONT, outbuf);
1706cefaae1SJack Meng }
1716cefaae1SJack Meng }
1726cefaae1SJack Meng
1736cefaae1SJack Meng void
iscsi_print_boot_property()1746cefaae1SJack Meng iscsi_print_boot_property()
1756cefaae1SJack Meng {
1766cefaae1SJack Meng if (iscsiboot_prop == NULL) {
1776cefaae1SJack Meng return;
1786cefaae1SJack Meng }
1796cefaae1SJack Meng
1806cefaae1SJack Meng iscsi_print_initiator_property(
1816cefaae1SJack Meng &iscsiboot_prop->boot_init);
1826cefaae1SJack Meng
1836cefaae1SJack Meng iscsi_print_nic_property(&iscsiboot_prop->boot_nic);
1846cefaae1SJack Meng
1856cefaae1SJack Meng iscsi_print_tgt_property(&iscsiboot_prop->boot_tgt);
1866cefaae1SJack Meng }
1876cefaae1SJack Meng
1886cefaae1SJack Meng void
iscsi_boot_free_ini(ib_ini_prop_t * init)1896cefaae1SJack Meng iscsi_boot_free_ini(ib_ini_prop_t *init)
1906cefaae1SJack Meng {
1916cefaae1SJack Meng if (init == NULL) {
1926cefaae1SJack Meng return;
1936cefaae1SJack Meng }
1946cefaae1SJack Meng
1956cefaae1SJack Meng if (init->ini_name != NULL) {
196*dedec472SJack Meng kmem_free(init->ini_name, init->ini_name_len);
1976cefaae1SJack Meng init->ini_name = NULL;
198*dedec472SJack Meng init->ini_name_len = 0;
1996cefaae1SJack Meng }
2006cefaae1SJack Meng if (init->ini_chap_name != NULL) {
2016cefaae1SJack Meng kmem_free(init->ini_chap_name,
202*dedec472SJack Meng init->ini_chap_name_len);
2036cefaae1SJack Meng init->ini_chap_name = NULL;
204*dedec472SJack Meng init->ini_chap_name_len = 0;
2056cefaae1SJack Meng }
2066cefaae1SJack Meng if (init->ini_chap_sec != NULL) {
2076cefaae1SJack Meng kmem_free(init->ini_chap_sec,
208*dedec472SJack Meng init->ini_chap_sec_len);
2096cefaae1SJack Meng init->ini_chap_sec = NULL;
210*dedec472SJack Meng init->ini_chap_sec_len = 0;
2116cefaae1SJack Meng }
2126cefaae1SJack Meng }
2136cefaae1SJack Meng
2146cefaae1SJack Meng void
iscsi_boot_free_tgt(ib_tgt_prop_t * target)2156cefaae1SJack Meng iscsi_boot_free_tgt(ib_tgt_prop_t *target)
2166cefaae1SJack Meng {
2176cefaae1SJack Meng if (target == NULL) {
2186cefaae1SJack Meng return;
2196cefaae1SJack Meng }
2206cefaae1SJack Meng
2216cefaae1SJack Meng if (target->tgt_name != NULL) {
2226cefaae1SJack Meng kmem_free(target->tgt_name,
223*dedec472SJack Meng target->tgt_name_len);
2246cefaae1SJack Meng target->tgt_name = NULL;
225*dedec472SJack Meng target->tgt_name_len = 0;
2266cefaae1SJack Meng }
2276cefaae1SJack Meng if (target->tgt_chap_name != NULL) {
2286cefaae1SJack Meng kmem_free(target->tgt_chap_name,
229*dedec472SJack Meng target->tgt_chap_name_len);
2306cefaae1SJack Meng target->tgt_chap_name = NULL;
231*dedec472SJack Meng target->tgt_chap_name_len = 0;
2326cefaae1SJack Meng }
2336cefaae1SJack Meng if (target->tgt_chap_sec != NULL) {
2346cefaae1SJack Meng kmem_free(target->tgt_chap_sec,
235*dedec472SJack Meng target->tgt_chap_sec_len);
2366cefaae1SJack Meng target->tgt_chap_sec = NULL;
237*dedec472SJack Meng target->tgt_chap_sec_len = 0;
238*dedec472SJack Meng }
239*dedec472SJack Meng if (target->tgt_boot_par != NULL) {
240*dedec472SJack Meng kmem_free(target->tgt_boot_par,
241*dedec472SJack Meng target->tgt_boot_par_len);
242*dedec472SJack Meng target->tgt_boot_par = NULL;
243*dedec472SJack Meng target->tgt_boot_par_len = 0;
2446cefaae1SJack Meng }
2456cefaae1SJack Meng }
2466cefaae1SJack Meng
2476cefaae1SJack Meng /*
2486cefaae1SJack Meng * Free the memory used by boot property.
2496cefaae1SJack Meng */
2506cefaae1SJack Meng void
iscsi_boot_prop_free()2516cefaae1SJack Meng iscsi_boot_prop_free()
2526cefaae1SJack Meng {
2536cefaae1SJack Meng ib_boot_prop_t *tmp;
2546cefaae1SJack Meng
2556cefaae1SJack Meng if (iscsiboot_prop == NULL) {
2566cefaae1SJack Meng return;
2576cefaae1SJack Meng }
2586cefaae1SJack Meng tmp = iscsiboot_prop;
2596cefaae1SJack Meng iscsiboot_prop = NULL;
2606cefaae1SJack Meng iscsi_boot_free_ini(&(tmp->boot_init));
2616cefaae1SJack Meng iscsi_boot_free_tgt(&(tmp->boot_tgt));
2626cefaae1SJack Meng }
2636cefaae1SJack Meng
2646cefaae1SJack Meng static void
kinet_ntoa(char * buf,void * in,int af)2656cefaae1SJack Meng kinet_ntoa(char *buf, void *in, int af)
2666cefaae1SJack Meng {
2676cefaae1SJack Meng unsigned char *p = NULL;
2686cefaae1SJack Meng int i = 0;
2696cefaae1SJack Meng
2706cefaae1SJack Meng if (buf == NULL || in == NULL) {
2716cefaae1SJack Meng return;
2726cefaae1SJack Meng }
2736cefaae1SJack Meng p = (unsigned char *)in;
2746cefaae1SJack Meng if (af == AF_INET) {
2756cefaae1SJack Meng (void) sprintf(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
2766cefaae1SJack Meng } else {
2776cefaae1SJack Meng for (i = 0; i < 14; i = i + 2) {
2786cefaae1SJack Meng (void) sprintf(buf, "%02x%02x:", p[i], p[i+1]);
2796cefaae1SJack Meng buf = buf + 5;
2806cefaae1SJack Meng }
2816cefaae1SJack Meng (void) sprintf(buf, "%02x%02x", p[i], p[i+1]);
2826cefaae1SJack Meng }
2836cefaae1SJack Meng }
284*dedec472SJack Meng
285*dedec472SJack Meng #ifndef BO_MAXOBJNAME
286*dedec472SJack Meng #define BO_MAXOBJNAME 256
287*dedec472SJack Meng #endif
288*dedec472SJack Meng
289*dedec472SJack Meng #ifndef ISCSI_BOOT_ISID
290*dedec472SJack Meng #define ISCSI_BOOT_ISID "0000"
291*dedec472SJack Meng #endif
292*dedec472SJack Meng
293*dedec472SJack Meng /*
294*dedec472SJack Meng * Generate the 'ssd' bootpath of an iSCSI boot device
295*dedec472SJack Meng * The caller is responsible to alloc the buf with BO_MAXOBJNAME length
296*dedec472SJack Meng */
297*dedec472SJack Meng void
get_iscsi_bootpath_vhci(char * bootpath)298*dedec472SJack Meng get_iscsi_bootpath_vhci(char *bootpath)
299*dedec472SJack Meng {
300*dedec472SJack Meng uint16_t *lun_num;
301*dedec472SJack Meng
302*dedec472SJack Meng if (iscsiboot_prop == NULL)
303*dedec472SJack Meng ld_ib_prop();
304*dedec472SJack Meng if (iscsiboot_prop == NULL)
305*dedec472SJack Meng return;
306*dedec472SJack Meng lun_num = (uint16_t *)(&iscsiboot_prop->boot_tgt.tgt_boot_lun[0]);
307*dedec472SJack Meng (void) snprintf(bootpath, BO_MAXOBJNAME, "/iscsi/ssd@%s%s%04X,%d:%s",
308*dedec472SJack Meng ISCSI_BOOT_ISID, iscsiboot_prop->boot_tgt.tgt_name,
309*dedec472SJack Meng iscsiboot_prop->boot_tgt.tgt_tpgt, lun_num[0],
310*dedec472SJack Meng iscsiboot_prop->boot_tgt.tgt_boot_par);
311*dedec472SJack Meng }
312*dedec472SJack Meng
313*dedec472SJack Meng /*
314*dedec472SJack Meng * Generate the 'disk' bootpath of an iSCSI boot device
315*dedec472SJack Meng * The caller is responsible to alloc the buf with BO_MAXOBJNAME length
316*dedec472SJack Meng */
317*dedec472SJack Meng void
get_iscsi_bootpath_phy(char * bootpath)318*dedec472SJack Meng get_iscsi_bootpath_phy(char *bootpath)
319*dedec472SJack Meng {
320*dedec472SJack Meng uint16_t lun_num = 0;
321*dedec472SJack Meng uchar_t replaced_name[BO_MAXOBJNAME] = {0};
322*dedec472SJack Meng
323*dedec472SJack Meng if (iscsiboot_prop == NULL)
324*dedec472SJack Meng ld_ib_prop();
325*dedec472SJack Meng if (iscsiboot_prop == NULL)
326*dedec472SJack Meng return;
327*dedec472SJack Meng if (replace_sp_c(replaced_name, iscsiboot_prop->boot_tgt.tgt_name,
328*dedec472SJack Meng iscsiboot_prop->boot_tgt.tgt_name_len) != 0) {
329*dedec472SJack Meng return;
330*dedec472SJack Meng }
331*dedec472SJack Meng lun_num = *(uint16_t *)(&iscsiboot_prop->boot_tgt.tgt_boot_lun[0]);
332*dedec472SJack Meng (void) snprintf(bootpath, BO_MAXOBJNAME, "/iscsi/disk@%s%s%04X,%d:%s",
333*dedec472SJack Meng ISCSI_BOOT_ISID, replaced_name, iscsiboot_prop->boot_tgt.tgt_tpgt,
334*dedec472SJack Meng lun_num, iscsiboot_prop->boot_tgt.tgt_boot_par);
335*dedec472SJack Meng }
336*dedec472SJack Meng
replace_sp_c(unsigned char * dst,unsigned char * source,size_t n)337*dedec472SJack Meng static int replace_sp_c(unsigned char *dst, unsigned char *source, size_t n)
338*dedec472SJack Meng {
339*dedec472SJack Meng unsigned char *p = NULL;
340*dedec472SJack Meng int i = 0;
341*dedec472SJack Meng
342*dedec472SJack Meng if (source == NULL || dst == NULL || n == 0) {
343*dedec472SJack Meng return (-1);
344*dedec472SJack Meng }
345*dedec472SJack Meng
346*dedec472SJack Meng for (p = source; *p != '\0'; p++, i++) {
347*dedec472SJack Meng if (i >= n) {
348*dedec472SJack Meng return (-1);
349*dedec472SJack Meng }
350*dedec472SJack Meng switch (*p) {
351*dedec472SJack Meng case ':':
352*dedec472SJack Meng *dst = '%';
353*dedec472SJack Meng dst++;
354*dedec472SJack Meng *dst = '3';
355*dedec472SJack Meng dst++;
356*dedec472SJack Meng *dst = 'A';
357*dedec472SJack Meng dst++;
358*dedec472SJack Meng break;
359*dedec472SJack Meng case ' ':
360*dedec472SJack Meng *dst = '%';
361*dedec472SJack Meng dst++;
362*dedec472SJack Meng *dst = '2';
363*dedec472SJack Meng dst++;
364*dedec472SJack Meng *dst = '0';
365*dedec472SJack Meng dst++;
366*dedec472SJack Meng break;
367*dedec472SJack Meng case '@':
368*dedec472SJack Meng *dst = '%';
369*dedec472SJack Meng dst++;
370*dedec472SJack Meng *dst = '4';
371*dedec472SJack Meng dst++;
372*dedec472SJack Meng *dst = '0';
373*dedec472SJack Meng dst++;
374*dedec472SJack Meng break;
375*dedec472SJack Meng case '/':
376*dedec472SJack Meng *dst = '%';
377*dedec472SJack Meng dst++;
378*dedec472SJack Meng *dst = '2';
379*dedec472SJack Meng dst++;
380*dedec472SJack Meng *dst = 'F';
381*dedec472SJack Meng dst++;
382*dedec472SJack Meng break;
383*dedec472SJack Meng default:
384*dedec472SJack Meng *dst = *p;
385*dedec472SJack Meng dst++;
386*dedec472SJack Meng }
387*dedec472SJack Meng }
388*dedec472SJack Meng *dst = '\0';
389*dedec472SJack Meng
390*dedec472SJack Meng return (0);
391*dedec472SJack Meng }
392