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*db8b037bSRichard 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
iscsi_bootprop_print(int level,char * str)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
iscsi_print_initiator_property(ib_ini_prop_t * ibinitp)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
iscsi_print_nic_property(ib_nic_prop_t * nicp)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
iscsi_print_tgt_property(ib_tgt_prop_t * itgtp)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
iscsi_print_boot_property()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
iscsi_boot_free_ini(ib_ini_prop_t * init)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
iscsi_boot_free_tgt(ib_tgt_prop_t * target)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
iscsi_boot_prop_free()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
kinet_ntoa(char * buf,void * in,int af)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
get_iscsi_bootpath_vhci(char * bootpath)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
get_iscsi_bootpath_phy(char * bootpath)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
replace_sp_c(unsigned char * dst,unsigned char * source,size_t n)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