xref: /illumos-gate/usr/src/uts/common/os/iscsiboot_prop.c (revision 56f33205c9ed776c3c909e07d52e94610a675740)
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