Home | History | Annotate | Download | only in os
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*
     28  * Commmon routines, handling iscsi boot props
     29  */
     30 
     31 #include <sys/types.h>
     32 #include <sys/bootprops.h>
     33 #include <sys/cmn_err.h>
     34 #include <sys/socket.h>
     35 #include <sys/kmem.h>
     36 #include <netinet/in.h>
     37 
     38 extern void *memset(void *s, int c, size_t n);
     39 extern int memcmp(const void *s1, const void *s2, size_t n);
     40 extern void bcopy(const void *s1, void *s2, size_t n);
     41 extern size_t strlen(const char *s);
     42 static void kinet_ntoa(char *buf, void *in, int af);
     43 extern ib_boot_prop_t *iscsiboot_prop;
     44 
     45 int  iscsi_print_bootprop	=	0;
     46 
     47 #define	ISCSI_BOOTPROP_BUFLEN	256
     48 
     49 #ifndef	NULL
     50 #define	NULL	0
     51 #endif
     52 
     53 static int replace_sp_c(unsigned char *dst, unsigned char *source, size_t n);
     54 
     55 static void
     56 iscsi_bootprop_print(int level, char *str)
     57 {
     58 	if (str == NULL) {
     59 		return;
     60 	}
     61 	if (iscsi_print_bootprop == 1) {
     62 		cmn_err(level, "%s", str);
     63 	}
     64 }
     65 
     66 static void
     67 iscsi_print_initiator_property(ib_ini_prop_t *ibinitp)
     68 {
     69 	char	outbuf[ISCSI_BOOTPROP_BUFLEN] = {0};
     70 
     71 	if (ibinitp == NULL) {
     72 		return;
     73 	}
     74 
     75 	if (ibinitp->ini_name != NULL) {
     76 		(void) sprintf(outbuf,
     77 		    "Initiator Name : %s\n",
     78 		    ibinitp->ini_name);
     79 		iscsi_bootprop_print(CE_CONT, outbuf);
     80 	}
     81 
     82 	if (ibinitp->ini_chap_name != NULL) {
     83 		(void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN);
     84 		(void) sprintf(outbuf,
     85 		    "Initiator CHAP Name  : %s\n",
     86 		    ibinitp->ini_chap_name);
     87 
     88 		iscsi_bootprop_print(CE_CONT, outbuf);
     89 	}
     90 }
     91 
     92 static void
     93 iscsi_print_nic_property(ib_nic_prop_t *nicp)
     94 {
     95 	char	outbuf[ISCSI_BOOTPROP_BUFLEN] = {0};
     96 	char	ipaddr[50]  =	{0};
     97 	int	n	    =	0;
     98 
     99 	if (nicp == NULL) {
    100 		return;
    101 	}
    102 
    103 	kinet_ntoa(ipaddr, &nicp->nic_ip_u, nicp->sin_family);
    104 	n = snprintf(outbuf, ISCSI_BOOTPROP_BUFLEN,
    105 	    "Local IP addr  : %s\n", ipaddr);
    106 
    107 	(void) memset(ipaddr, 0, 50);
    108 	kinet_ntoa(ipaddr, &nicp->nic_gw_u, nicp->sin_family);
    109 	n = n + snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n,
    110 	    "Local gateway  : %s\n", ipaddr);
    111 
    112 	(void) memset(ipaddr, 0, 50);
    113 	kinet_ntoa(ipaddr, &nicp->nic_dhcp_u, nicp->sin_family);
    114 	n = n + snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n,
    115 	    "Local DHCP     : %s\n", ipaddr);
    116 
    117 	(void) snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n,
    118 	    "Local MAC      : %02x:%02x:%02x:%02x:%02x:%02x\n",
    119 	    nicp->nic_mac[0],
    120 	    nicp->nic_mac[1],
    121 	    nicp->nic_mac[2],
    122 	    nicp->nic_mac[3],
    123 	    nicp->nic_mac[4],
    124 	    nicp->nic_mac[5]);
    125 
    126 	iscsi_bootprop_print(CE_CONT, outbuf);
    127 }
    128 
    129 static void
    130 iscsi_print_tgt_property(ib_tgt_prop_t *itgtp)
    131 {
    132 	char	outbuf[ISCSI_BOOTPROP_BUFLEN] = {0};
    133 	char	ipaddr[50]  =	{0};
    134 
    135 	if (itgtp == NULL) {
    136 		return;
    137 	}
    138 
    139 	if (itgtp->tgt_name != NULL) {
    140 		(void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN);
    141 		(void) sprintf(outbuf,
    142 		    "Target Name    : %s\n",
    143 		    itgtp->tgt_name);
    144 		iscsi_bootprop_print(CE_CONT, outbuf);
    145 	}
    146 
    147 	kinet_ntoa(ipaddr, &itgtp->tgt_ip_u, itgtp->sin_family);
    148 	(void) sprintf(outbuf,
    149 	    "Target IP      : %s\n"
    150 	    "Target Port    : %d\n"
    151 	    "Boot LUN       : %02x%02x-%02x%02x-%02x%02x-%02x%02x\n",
    152 	    ipaddr,
    153 	    itgtp->tgt_port,
    154 	    itgtp->tgt_boot_lun[0],
    155 	    itgtp->tgt_boot_lun[1],
    156 	    itgtp->tgt_boot_lun[2],
    157 	    itgtp->tgt_boot_lun[3],
    158 	    itgtp->tgt_boot_lun[4],
    159 	    itgtp->tgt_boot_lun[5],
    160 	    itgtp->tgt_boot_lun[6],
    161 	    itgtp->tgt_boot_lun[7]);
    162 	iscsi_bootprop_print(CE_CONT, outbuf);
    163 
    164 	if (itgtp->tgt_chap_name != NULL) {
    165 		(void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN);
    166 		(void) sprintf(outbuf,
    167 		    "CHAP Name      : %s\n",
    168 		    itgtp->tgt_chap_name);
    169 		iscsi_bootprop_print(CE_CONT, outbuf);
    170 	}
    171 }
    172 
    173 void
    174 iscsi_print_boot_property()
    175 {
    176 	if (iscsiboot_prop == NULL) {
    177 		return;
    178 	}
    179 
    180 	iscsi_print_initiator_property(
    181 	    &iscsiboot_prop->boot_init);
    182 
    183 	iscsi_print_nic_property(&iscsiboot_prop->boot_nic);
    184 
    185 	iscsi_print_tgt_property(&iscsiboot_prop->boot_tgt);
    186 }
    187 
    188 void
    189 iscsi_boot_free_ini(ib_ini_prop_t *init)
    190 {
    191 	if (init == NULL) {
    192 		return;
    193 	}
    194 
    195 	if (init->ini_name != NULL) {
    196 		kmem_free(init->ini_name, init->ini_name_len);
    197 		init->ini_name = NULL;
    198 		init->ini_name_len = 0;
    199 	}
    200 	if (init->ini_chap_name != NULL) {
    201 		kmem_free(init->ini_chap_name,
    202 		    init->ini_chap_name_len);
    203 		init->ini_chap_name = NULL;
    204 		init->ini_chap_name_len = 0;
    205 	}
    206 	if (init->ini_chap_sec != NULL) {
    207 		kmem_free(init->ini_chap_sec,
    208 		    init->ini_chap_sec_len);
    209 		init->ini_chap_sec = NULL;
    210 		init->ini_chap_sec_len = 0;
    211 	}
    212 }
    213 
    214 void
    215 iscsi_boot_free_tgt(ib_tgt_prop_t *target)
    216 {
    217 	if (target == NULL) {
    218 		return;
    219 	}
    220 
    221 	if (target->tgt_name != NULL) {
    222 		kmem_free(target->tgt_name,
    223 		    target->tgt_name_len);
    224 		target->tgt_name = NULL;
    225 		target->tgt_name_len = 0;
    226 	}
    227 	if (target->tgt_chap_name != NULL) {
    228 		kmem_free(target->tgt_chap_name,
    229 		    target->tgt_chap_name_len);
    230 		target->tgt_chap_name = NULL;
    231 		target->tgt_chap_name_len = 0;
    232 	}
    233 	if (target->tgt_chap_sec != NULL) {
    234 		kmem_free(target->tgt_chap_sec,
    235 		    target->tgt_chap_sec_len);
    236 		target->tgt_chap_sec = NULL;
    237 		target->tgt_chap_sec_len = 0;
    238 	}
    239 	if (target->tgt_boot_par != NULL) {
    240 		kmem_free(target->tgt_boot_par,
    241 		    target->tgt_boot_par_len);
    242 		target->tgt_boot_par = NULL;
    243 		target->tgt_boot_par_len = 0;
    244 	}
    245 }
    246 
    247 /*
    248  * Free the memory used by boot property.
    249  */
    250 void
    251 iscsi_boot_prop_free()
    252 {
    253 	ib_boot_prop_t	*tmp;
    254 
    255 	if (iscsiboot_prop == NULL) {
    256 		return;
    257 	}
    258 	tmp = iscsiboot_prop;
    259 	iscsiboot_prop = NULL;
    260 	iscsi_boot_free_ini(&(tmp->boot_init));
    261 	iscsi_boot_free_tgt(&(tmp->boot_tgt));
    262 }
    263 
    264 static void
    265 kinet_ntoa(char *buf, void *in, int af)
    266 {
    267 	unsigned char   *p =    NULL;
    268 	int	i = 0;
    269 
    270 	if (buf == NULL || in == NULL) {
    271 		return;
    272 	}
    273 	p = (unsigned char *)in;
    274 	if (af == AF_INET) {
    275 		(void) sprintf(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
    276 	} else {
    277 		for (i = 0; i < 14; i = i + 2) {
    278 			(void) sprintf(buf, "%02x%02x:", p[i], p[i+1]);
    279 			buf = buf + 5;
    280 		}
    281 		(void) sprintf(buf, "%02x%02x", p[i], p[i+1]);
    282 	}
    283 }
    284 
    285 #ifndef	BO_MAXOBJNAME
    286 #define	BO_MAXOBJNAME	256
    287 #endif
    288 
    289 #ifndef ISCSI_BOOT_ISID
    290 #define	ISCSI_BOOT_ISID	"0000"
    291 #endif
    292 
    293 /*
    294  * Generate the 'ssd' bootpath of an iSCSI boot device
    295  * The caller is responsible to alloc the buf with BO_MAXOBJNAME length
    296  */
    297 void
    298 get_iscsi_bootpath_vhci(char *bootpath)
    299 {
    300 	uint16_t	*lun_num;
    301 
    302 	if (iscsiboot_prop == NULL)
    303 		ld_ib_prop();
    304 	if (iscsiboot_prop == NULL)
    305 		return;
    306 	lun_num = (uint16_t *)(&iscsiboot_prop->boot_tgt.tgt_boot_lun[0]);
    307 	(void) snprintf(bootpath, BO_MAXOBJNAME, "/iscsi/ssd@%s%s%04X,%d:%s",
    308 	    ISCSI_BOOT_ISID, iscsiboot_prop->boot_tgt.tgt_name,
    309 	    iscsiboot_prop->boot_tgt.tgt_tpgt, lun_num[0],
    310 	    iscsiboot_prop->boot_tgt.tgt_boot_par);
    311 }
    312 
    313 /*
    314  * Generate the 'disk' bootpath of an iSCSI boot device
    315  * The caller is responsible to alloc the buf with BO_MAXOBJNAME length
    316  */
    317 void
    318 get_iscsi_bootpath_phy(char *bootpath)
    319 {
    320 	uint16_t	lun_num		= 0;
    321 	uchar_t		replaced_name[BO_MAXOBJNAME] = {0};
    322 
    323 	if (iscsiboot_prop == NULL)
    324 		ld_ib_prop();
    325 	if (iscsiboot_prop == NULL)
    326 		return;
    327 	if (replace_sp_c(replaced_name, iscsiboot_prop->boot_tgt.tgt_name,
    328 	    iscsiboot_prop->boot_tgt.tgt_name_len) != 0) {
    329 		return;
    330 	}
    331 	lun_num = *(uint16_t *)(&iscsiboot_prop->boot_tgt.tgt_boot_lun[0]);
    332 	(void) snprintf(bootpath, BO_MAXOBJNAME, "/iscsi/disk@%s%s%04X,%d:%s",
    333 	    ISCSI_BOOT_ISID, replaced_name, iscsiboot_prop->boot_tgt.tgt_tpgt,
    334 	    lun_num, iscsiboot_prop->boot_tgt.tgt_boot_par);
    335 }
    336 
    337 static int replace_sp_c(unsigned char *dst, unsigned char *source, size_t n)
    338 {
    339 	unsigned char	*p	= NULL;
    340 	int		i	= 0;
    341 
    342 	if (source == NULL || dst == NULL || n == 0) {
    343 		return (-1);
    344 	}
    345 
    346 	for (p = source; *p != '\0'; p++, i++) {
    347 		if (i >= n) {
    348 			return (-1);
    349 		}
    350 		switch (*p) {
    351 		case ':':
    352 			*dst = '%';
    353 			dst++;
    354 			*dst = '3';
    355 			dst++;
    356 			*dst = 'A';
    357 			dst++;
    358 			break;
    359 		case ' ':
    360 			*dst = '%';
    361 			dst++;
    362 			*dst = '2';
    363 			dst++;
    364 			*dst = '0';
    365 			dst++;
    366 			break;
    367 		case '@':
    368 			*dst = '%';
    369 			dst++;
    370 			*dst = '4';
    371 			dst++;
    372 			*dst = '0';
    373 			dst++;
    374 			break;
    375 		case '/':
    376 			*dst = '%';
    377 			dst++;
    378 			*dst = '2';
    379 			dst++;
    380 			*dst = 'F';
    381 			dst++;
    382 			break;
    383 		default:
    384 			*dst = *p;
    385 			dst++;
    386 		}
    387 	}
    388 	*dst = '\0';
    389 
    390 	return (0);
    391 }
    392