xref: /titanic_44/usr/src/cmd/luxadm/fabric_conf.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte 
27*fcf3ce44SJohn Forte 
28*fcf3ce44SJohn Forte 
29*fcf3ce44SJohn Forte #include <stdlib.h>
30*fcf3ce44SJohn Forte #include <stdio.h>
31*fcf3ce44SJohn Forte #include <unistd.h>
32*fcf3ce44SJohn Forte #include <sys/types.h>
33*fcf3ce44SJohn Forte #include <sys/stat.h>
34*fcf3ce44SJohn Forte #include <fcntl.h>
35*fcf3ce44SJohn Forte #include <errno.h>
36*fcf3ce44SJohn Forte #include <string.h>
37*fcf3ce44SJohn Forte #include <stdarg.h>
38*fcf3ce44SJohn Forte #include <syslog.h>
39*fcf3ce44SJohn Forte #include <libdevice.h>
40*fcf3ce44SJohn Forte #include <sys/fibre-channel/fcio.h>
41*fcf3ce44SJohn Forte #include "common.h"
42*fcf3ce44SJohn Forte 
43*fcf3ce44SJohn Forte static int parse_line(char *line, char *path, char *wwn, char *filename);
44*fcf3ce44SJohn Forte static int create_ap_instance(char *ap_id, char *wwn_string,
45*fcf3ce44SJohn Forte 	char *filename, char *line);
46*fcf3ce44SJohn Forte static void log_error(char *msg_id, char *input_tmplt, ...);
47*fcf3ce44SJohn Forte static char ctoi(char c);
48*fcf3ce44SJohn Forte 
49*fcf3ce44SJohn Forte /*
50*fcf3ce44SJohn Forte  *  Simple wrapper for syslog error messages.
51*fcf3ce44SJohn Forte  *  Allows easy addition of syserr output if desired.
52*fcf3ce44SJohn Forte  */
53*fcf3ce44SJohn Forte static void
log_error(char * msg_id,char * input_tmplt,...)54*fcf3ce44SJohn Forte log_error(char *msg_id, char *input_tmplt, ...)
55*fcf3ce44SJohn Forte {
56*fcf3ce44SJohn Forte 	va_list ap;
57*fcf3ce44SJohn Forte 	char input_merged_msg[200];
58*fcf3ce44SJohn Forte 	char *msg_template = "ID[luxadm.create_fabric_device.%s] %s";
59*fcf3ce44SJohn Forte 	/*
60*fcf3ce44SJohn Forte 	 * First %s for msg_id in merged msg.
61*fcf3ce44SJohn Forte 	 * Second %s is for  input merged_msg
62*fcf3ce44SJohn Forte 	 */
63*fcf3ce44SJohn Forte 	char *merged_msg;
64*fcf3ce44SJohn Forte 
65*fcf3ce44SJohn Forte 	va_start(ap, input_tmplt);
66*fcf3ce44SJohn Forte 	/* insert caller's args */
67*fcf3ce44SJohn Forte 	(void) vsprintf(input_merged_msg, input_tmplt, ap);
68*fcf3ce44SJohn Forte 	va_end(ap);
69*fcf3ce44SJohn Forte 
70*fcf3ce44SJohn Forte 	merged_msg = (char *)malloc(strlen(msg_template) +
71*fcf3ce44SJohn Forte 		strlen(input_merged_msg) +
72*fcf3ce44SJohn Forte 		strlen(msg_id) + 1);
73*fcf3ce44SJohn Forte 	if (merged_msg == NULL) {
74*fcf3ce44SJohn Forte 		syslog(LOG_ERR,
75*fcf3ce44SJohn Forte 		"ID[luxadm.create_fabric_device.2317] "
76*fcf3ce44SJohn Forte 			"malloc failure, %s", strerror(errno));
77*fcf3ce44SJohn Forte 	} else {
78*fcf3ce44SJohn Forte 		sprintf(merged_msg, msg_template, msg_id, input_merged_msg);
79*fcf3ce44SJohn Forte 			/* first insert msg_id */
80*fcf3ce44SJohn Forte 		syslog(LOG_ERR, merged_msg, "");
81*fcf3ce44SJohn Forte 		(void) puts(merged_msg);	/* also print message */
82*fcf3ce44SJohn Forte 		free(merged_msg);
83*fcf3ce44SJohn Forte 	}
84*fcf3ce44SJohn Forte }
85*fcf3ce44SJohn Forte 
86*fcf3ce44SJohn Forte /*
87*fcf3ce44SJohn Forte  *   Routines for reading tapestry repository file
88*fcf3ce44SJohn Forte  */
89*fcf3ce44SJohn Forte 
90*fcf3ce44SJohn Forte #define	COMMENT_CHAR '#'
91*fcf3ce44SJohn Forte int
read_repos_file(char * repos_filename)92*fcf3ce44SJohn Forte read_repos_file(char *repos_filename)
93*fcf3ce44SJohn Forte {
94*fcf3ce44SJohn Forte 	int fd;
95*fcf3ce44SJohn Forte 	char *line;
96*fcf3ce44SJohn Forte 	char *tmp_ptr, *mmap_ptr;
97*fcf3ce44SJohn Forte 	char path[MAXPATHLEN];
98*fcf3ce44SJohn Forte 	int ret;
99*fcf3ce44SJohn Forte 	char wwn[FC_WWN_SIZE*2+1];
100*fcf3ce44SJohn Forte 	struct stat stbuf;
101*fcf3ce44SJohn Forte 	unsigned int filesize;
102*fcf3ce44SJohn Forte 	unsigned int bytes_read;
103*fcf3ce44SJohn Forte 
104*fcf3ce44SJohn Forte 	if (repos_filename == NULL || *repos_filename == NULL) {
105*fcf3ce44SJohn Forte 		log_error("2310",
106*fcf3ce44SJohn Forte 		"filename missing for -f option of "
107*fcf3ce44SJohn Forte 		"luxadm -e create_fabric_device");
108*fcf3ce44SJohn Forte 		return (-1);
109*fcf3ce44SJohn Forte 	}
110*fcf3ce44SJohn Forte 
111*fcf3ce44SJohn Forte 	fd = open(repos_filename, O_RDONLY);
112*fcf3ce44SJohn Forte 
113*fcf3ce44SJohn Forte 	if (fd == -1) {
114*fcf3ce44SJohn Forte 		log_error("2311",
115*fcf3ce44SJohn Forte 		"fopen failed: cannot open repository file %s. %d",
116*fcf3ce44SJohn Forte 		repos_filename, strerror(errno));
117*fcf3ce44SJohn Forte 		return (-1);
118*fcf3ce44SJohn Forte 	}
119*fcf3ce44SJohn Forte 
120*fcf3ce44SJohn Forte 	if (fstat(fd, &stbuf) == -1) {
121*fcf3ce44SJohn Forte 		close(fd);
122*fcf3ce44SJohn Forte 		log_error("2312",
123*fcf3ce44SJohn Forte 		"stat failed on file %s. %s",
124*fcf3ce44SJohn Forte 		repos_filename, strerror(errno));
125*fcf3ce44SJohn Forte 		return (-1);
126*fcf3ce44SJohn Forte 	}
127*fcf3ce44SJohn Forte 	filesize = stbuf.st_size;
128*fcf3ce44SJohn Forte 	tmp_ptr = mmap_ptr = mmap((caddr_t)0, filesize,
129*fcf3ce44SJohn Forte 			(PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0);
130*fcf3ce44SJohn Forte 
131*fcf3ce44SJohn Forte 	if (mmap_ptr == MAP_FAILED) {
132*fcf3ce44SJohn Forte 		log_error("2315",
133*fcf3ce44SJohn Forte 		"Failed to mmap file %s. %s",
134*fcf3ce44SJohn Forte 		repos_filename, strerror(errno));
135*fcf3ce44SJohn Forte 		return (-1);
136*fcf3ce44SJohn Forte 	}
137*fcf3ce44SJohn Forte 
138*fcf3ce44SJohn Forte 	bytes_read = 0;
139*fcf3ce44SJohn Forte 	while (bytes_read < filesize) {
140*fcf3ce44SJohn Forte 		line = tmp_ptr;
141*fcf3ce44SJohn Forte 		while (bytes_read < filesize && *tmp_ptr != '\n') {
142*fcf3ce44SJohn Forte 			bytes_read++;
143*fcf3ce44SJohn Forte 			tmp_ptr++;
144*fcf3ce44SJohn Forte 		}
145*fcf3ce44SJohn Forte 		if (*tmp_ptr == '\n') {
146*fcf3ce44SJohn Forte 			*tmp_ptr = NULL;
147*fcf3ce44SJohn Forte 			tmp_ptr++;
148*fcf3ce44SJohn Forte 			bytes_read++;
149*fcf3ce44SJohn Forte 		}
150*fcf3ce44SJohn Forte 
151*fcf3ce44SJohn Forte 		/* If the line is a comment, read another line */
152*fcf3ce44SJohn Forte 		if (*line == COMMENT_CHAR) {
153*fcf3ce44SJohn Forte 			continue;
154*fcf3ce44SJohn Forte 		}
155*fcf3ce44SJohn Forte 		ret = parse_line(line, path, wwn, repos_filename);
156*fcf3ce44SJohn Forte 		if (ret == 0) {
157*fcf3ce44SJohn Forte 			ret = create_ap_instance(path,
158*fcf3ce44SJohn Forte 			    wwn, repos_filename, line);
159*fcf3ce44SJohn Forte 		}
160*fcf3ce44SJohn Forte 	}
161*fcf3ce44SJohn Forte 
162*fcf3ce44SJohn Forte 	ret = close(fd);
163*fcf3ce44SJohn Forte 	ret = munmap(mmap_ptr, filesize);
164*fcf3ce44SJohn Forte 	return (ret);
165*fcf3ce44SJohn Forte }
166*fcf3ce44SJohn Forte 
167*fcf3ce44SJohn Forte /*
168*fcf3ce44SJohn Forte  * Input is paramater 1 - a line from repository
169*fcf3ce44SJohn Forte  * Output is other parameters, the path to the attachment point,
170*fcf3ce44SJohn Forte  * and the port wwn are parsed from the repository
171*fcf3ce44SJohn Forte  * Format is
172*fcf3ce44SJohn Forte  *	"/devices/pci..../fp@1,0:fc::wwn"
173*fcf3ce44SJohn Forte  * If controller name is missing, that's okay.  Other fields
174*fcf3ce44SJohn Forte  * must be present
175*fcf3ce44SJohn Forte  *
176*fcf3ce44SJohn Forte  * Return 0 on success or -1 on failure; all failures logged to syslog.
177*fcf3ce44SJohn Forte  */
178*fcf3ce44SJohn Forte #define	WWN_DELIM "::"
179*fcf3ce44SJohn Forte static int
parse_line(char * line,char * path,char * wwn,char * filename)180*fcf3ce44SJohn Forte parse_line(char *line, char *path, char *wwn, char *filename)
181*fcf3ce44SJohn Forte {
182*fcf3ce44SJohn Forte 	char *p_path, *p_wwn, *p_delim;
183*fcf3ce44SJohn Forte 	char *line_copy;
184*fcf3ce44SJohn Forte 
185*fcf3ce44SJohn Forte 	line_copy = strdup(line);
186*fcf3ce44SJohn Forte 	if (line_copy == NULL) {
187*fcf3ce44SJohn Forte 		log_error("2317",
188*fcf3ce44SJohn Forte 			"malloc failure, %s", strerror(errno));
189*fcf3ce44SJohn Forte 	}
190*fcf3ce44SJohn Forte 	p_path = line_copy;
191*fcf3ce44SJohn Forte 	p_delim = strstr(p_path, WWN_DELIM);
192*fcf3ce44SJohn Forte 	if (p_delim == NULL) {
193*fcf3ce44SJohn Forte 		log_error("2313",
194*fcf3ce44SJohn Forte 			"Invalid line (%s) in file %s.", line, filename);
195*fcf3ce44SJohn Forte 		free(line_copy);
196*fcf3ce44SJohn Forte 		return (-1);
197*fcf3ce44SJohn Forte 	}
198*fcf3ce44SJohn Forte 	*p_delim = NULL;	/* NULL terminate path */
199*fcf3ce44SJohn Forte 
200*fcf3ce44SJohn Forte 	if (strlcpy(path, p_path, MAXPATHLEN) >= MAXPATHLEN) {
201*fcf3ce44SJohn Forte 		log_error("2318",
202*fcf3ce44SJohn Forte 			"Path too long (%s) in file %s.", p_path, filename);
203*fcf3ce44SJohn Forte 		free(line_copy);
204*fcf3ce44SJohn Forte 		return (-1);
205*fcf3ce44SJohn Forte 	}
206*fcf3ce44SJohn Forte 
207*fcf3ce44SJohn Forte 	p_wwn = p_delim + strlen(WWN_DELIM);
208*fcf3ce44SJohn Forte 	/*
209*fcf3ce44SJohn Forte 	 * Now look for the blank delimiter before the controller
210*fcf3ce44SJohn Forte 	 *
211*fcf3ce44SJohn Forte 	 * This is just the case when there may be a controller #
212*fcf3ce44SJohn Forte 	 * after the attachment point and WWN. For example -
213*fcf3ce44SJohn Forte 	 * /devices/pci@b,2000/pci@2/SUNW,qlc@4/fp@0,0:fc::220000203707f4f1 c4
214*fcf3ce44SJohn Forte 	 */
215*fcf3ce44SJohn Forte 	p_delim = strchr(p_wwn, ' ');
216*fcf3ce44SJohn Forte 	if (p_delim != NULL) {
217*fcf3ce44SJohn Forte 		/* now p_delim points to blank */
218*fcf3ce44SJohn Forte 		*p_delim = NULL;	/* terminate wwn at delim */
219*fcf3ce44SJohn Forte 	} else {
220*fcf3ce44SJohn Forte 		char *p_last_char;
221*fcf3ce44SJohn Forte 		p_last_char = p_wwn+strlen(p_wwn)-1;
222*fcf3ce44SJohn Forte 		if (*p_last_char == '\n') {
223*fcf3ce44SJohn Forte 			*p_last_char = NULL;
224*fcf3ce44SJohn Forte 		}
225*fcf3ce44SJohn Forte 	}
226*fcf3ce44SJohn Forte 	strcpy(wwn, p_wwn);
227*fcf3ce44SJohn Forte 	free(line_copy);
228*fcf3ce44SJohn Forte 	return (0);
229*fcf3ce44SJohn Forte }
230*fcf3ce44SJohn Forte 
231*fcf3ce44SJohn Forte static char
ctoi(char c)232*fcf3ce44SJohn Forte ctoi(char c)
233*fcf3ce44SJohn Forte {
234*fcf3ce44SJohn Forte 	if ((c >= '0') && (c <= '9'))
235*fcf3ce44SJohn Forte 		c -= '0';
236*fcf3ce44SJohn Forte 	else if ((c >= 'A') && (c <= 'F'))
237*fcf3ce44SJohn Forte 		c = c - 'A' + 10;
238*fcf3ce44SJohn Forte 	else if ((c >= 'a') && (c <= 'f'))
239*fcf3ce44SJohn Forte 		c = c - 'a' + 10;
240*fcf3ce44SJohn Forte 	else
241*fcf3ce44SJohn Forte 		c = -1;
242*fcf3ce44SJohn Forte 	return (c);
243*fcf3ce44SJohn Forte }
244*fcf3ce44SJohn Forte 
245*fcf3ce44SJohn Forte /*
246*fcf3ce44SJohn Forte  * "string" is Input and "port_wwn" has the output
247*fcf3ce44SJohn Forte  *
248*fcf3ce44SJohn Forte  * This function converts a string to WWN.
249*fcf3ce44SJohn Forte  * For example a string like
250*fcf3ce44SJohn Forte  * "220000203707F4F1" gets converted to 0x220000203707F4F1 ...
251*fcf3ce44SJohn Forte  * where
252*fcf3ce44SJohn Forte  * port_wwn[0] = 0x22,
253*fcf3ce44SJohn Forte  * port_wwn[1] = 0x00,
254*fcf3ce44SJohn Forte  * port_wwn[2] = 0x00,
255*fcf3ce44SJohn Forte  * port_wwn[3] = 0x20,
256*fcf3ce44SJohn Forte  * port_wwn[4] = 0x37,
257*fcf3ce44SJohn Forte  * port_wwn[5] = 0x07,
258*fcf3ce44SJohn Forte  * port_wwn[6] = 0xF4, and
259*fcf3ce44SJohn Forte  * port_wwn[7] = 0xF1
260*fcf3ce44SJohn Forte  */
261*fcf3ce44SJohn Forte static int
string_to_wwn(const uchar_t * string,uchar_t * port_wwn)262*fcf3ce44SJohn Forte string_to_wwn(const uchar_t *string, uchar_t *port_wwn)
263*fcf3ce44SJohn Forte {
264*fcf3ce44SJohn Forte 	int	i;
265*fcf3ce44SJohn Forte 	char	c, c1;
266*fcf3ce44SJohn Forte 	uchar_t	*wwnp;
267*fcf3ce44SJohn Forte 
268*fcf3ce44SJohn Forte 	wwnp = port_wwn;
269*fcf3ce44SJohn Forte 	for (i = 0; i < WWN_SIZE; i++, wwnp++) {
270*fcf3ce44SJohn Forte 
271*fcf3ce44SJohn Forte 		c = ctoi(*string++);
272*fcf3ce44SJohn Forte 		c1 = ctoi(*string++);
273*fcf3ce44SJohn Forte 		if (c == -1 || c1 == -1)
274*fcf3ce44SJohn Forte 			return (-1);
275*fcf3ce44SJohn Forte 		*wwnp = ((c << 4) + c1);
276*fcf3ce44SJohn Forte 	}
277*fcf3ce44SJohn Forte 
278*fcf3ce44SJohn Forte 	return (0);
279*fcf3ce44SJohn Forte }
280*fcf3ce44SJohn Forte 
281*fcf3ce44SJohn Forte static int
create_ap_instance(char * ap_id,char * wwn_string,char * filename,char * line)282*fcf3ce44SJohn Forte create_ap_instance(char *ap_id, char *wwn_string,
283*fcf3ce44SJohn Forte 		    char *filename, char *line)
284*fcf3ce44SJohn Forte {
285*fcf3ce44SJohn Forte 	devctl_hdl_t bus_handle, dev_handle;
286*fcf3ce44SJohn Forte 	devctl_ddef_t ddef_handle;
287*fcf3ce44SJohn Forte 	int ret;
288*fcf3ce44SJohn Forte 	uchar_t wwn_array[FC_WWN_SIZE];
289*fcf3ce44SJohn Forte 
290*fcf3ce44SJohn Forte 	ddef_handle = devctl_ddef_alloc("dummy", 0);
291*fcf3ce44SJohn Forte 	if (ddef_handle == NULL) {
292*fcf3ce44SJohn Forte 		log_error("2314",
293*fcf3ce44SJohn Forte 		"Internal error to process line (%s) "
294*fcf3ce44SJohn Forte 		"in file: %s. %s",
295*fcf3ce44SJohn Forte 		line, filename, strerror(errno));
296*fcf3ce44SJohn Forte 		return (-1);
297*fcf3ce44SJohn Forte 	}
298*fcf3ce44SJohn Forte 	/*
299*fcf3ce44SJohn Forte 	 * g_string_to_wwn() has not been used here because it
300*fcf3ce44SJohn Forte 	 * prepends 2 NULLs.
301*fcf3ce44SJohn Forte 	 */
302*fcf3ce44SJohn Forte 	if (string_to_wwn((uchar_t *)wwn_string, wwn_array) != 0) {
303*fcf3ce44SJohn Forte 		log_error("2314",
304*fcf3ce44SJohn Forte 		"Internal error to process line (%s) "
305*fcf3ce44SJohn Forte 		"in file: %s. %s",
306*fcf3ce44SJohn Forte 		line, filename, strerror(errno));
307*fcf3ce44SJohn Forte 		devctl_ddef_free(ddef_handle);
308*fcf3ce44SJohn Forte 		return (-1);
309*fcf3ce44SJohn Forte 	}
310*fcf3ce44SJohn Forte 	(void) devctl_ddef_byte_array(ddef_handle,
311*fcf3ce44SJohn Forte 		"port-wwn", FC_WWN_SIZE, wwn_array);
312*fcf3ce44SJohn Forte 
313*fcf3ce44SJohn Forte 	if ((bus_handle = devctl_bus_acquire(ap_id, 0)) == NULL) {
314*fcf3ce44SJohn Forte 		devctl_ddef_free(ddef_handle);
315*fcf3ce44SJohn Forte 		log_error("2314",
316*fcf3ce44SJohn Forte 		"Internal error to process line (%s) "
317*fcf3ce44SJohn Forte 		"in file: %s. %s",
318*fcf3ce44SJohn Forte 		line, filename, strerror(errno));
319*fcf3ce44SJohn Forte 		return (-1);
320*fcf3ce44SJohn Forte 	}
321*fcf3ce44SJohn Forte 	if (ret =
322*fcf3ce44SJohn Forte 	    devctl_bus_dev_create(bus_handle, ddef_handle, 0, &dev_handle)) {
323*fcf3ce44SJohn Forte 		devctl_ddef_free(ddef_handle);
324*fcf3ce44SJohn Forte 		devctl_release(bus_handle);
325*fcf3ce44SJohn Forte 		log_error("2316",
326*fcf3ce44SJohn Forte 		"configuration failed for line (%s) "
327*fcf3ce44SJohn Forte 		"in file: %s. %s",
328*fcf3ce44SJohn Forte 		line, filename, strerror(errno));
329*fcf3ce44SJohn Forte 		return (-1);
330*fcf3ce44SJohn Forte 	}
331*fcf3ce44SJohn Forte 	devctl_release(dev_handle);
332*fcf3ce44SJohn Forte 	devctl_ddef_free(ddef_handle);
333*fcf3ce44SJohn Forte 	devctl_release(bus_handle);
334*fcf3ce44SJohn Forte 	return (ret);
335*fcf3ce44SJohn Forte }
336