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