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