xref: /titanic_52/usr/src/lib/libnsctl/common/machdep.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 #include <sys/types.h>
27*fcf3ce44SJohn Forte #include <sys/utsname.h>
28*fcf3ce44SJohn Forte #include <fcntl.h>
29*fcf3ce44SJohn Forte #include <sys/param.h>
30*fcf3ce44SJohn Forte #include <unistd.h>
31*fcf3ce44SJohn Forte #include <stdarg.h>
32*fcf3ce44SJohn Forte #include <errno.h>
33*fcf3ce44SJohn Forte #include <stdio.h>
34*fcf3ce44SJohn Forte #include <stdlib.h>
35*fcf3ce44SJohn Forte #include <string.h>
36*fcf3ce44SJohn Forte 
37*fcf3ce44SJohn Forte #include "libnsctl.h"
38*fcf3ce44SJohn Forte #include <nsctl.h>
39*fcf3ce44SJohn Forte #include <sys/ncall/ncall.h>
40*fcf3ce44SJohn Forte 
41*fcf3ce44SJohn Forte 
42*fcf3ce44SJohn Forte 
43*fcf3ce44SJohn Forte /*
44*fcf3ce44SJohn Forte  * Internal routine to fetch all the current nodes that are
45*fcf3ce44SJohn Forte  * considered 'up'.
46*fcf3ce44SJohn Forte  * Returns the number of ncall_info structures that are valid
47*fcf3ce44SJohn Forte  * returned via the nodelist pointer, or -1 on an error.
48*fcf3ce44SJohn Forte  * If the call succeeds, then the memory returned via the
49*fcf3ce44SJohn Forte  * nodelist pointer needs to be freed by the caller.
50*fcf3ce44SJohn Forte  */
51*fcf3ce44SJohn Forte 
52*fcf3ce44SJohn Forte static int
53*fcf3ce44SJohn Forte nsc_getcurrentnodes(ncall_node_t **nodelist)
54*fcf3ce44SJohn Forte {
55*fcf3ce44SJohn Forte 	ncall_node_t *mynodelist;
56*fcf3ce44SJohn Forte 	int size;
57*fcf3ce44SJohn Forte 	int fd;
58*fcf3ce44SJohn Forte 	int rc = -1;
59*fcf3ce44SJohn Forte 	int save_errno = 0;
60*fcf3ce44SJohn Forte 	int ioctlcmd;
61*fcf3ce44SJohn Forte 
62*fcf3ce44SJohn Forte 	if (nodelist == NULL) {
63*fcf3ce44SJohn Forte 		errno = EINVAL;
64*fcf3ce44SJohn Forte 		return (-1);
65*fcf3ce44SJohn Forte 	}
66*fcf3ce44SJohn Forte 	*nodelist = NULL;
67*fcf3ce44SJohn Forte 	if ((fd = open("/dev/ncall", O_RDONLY)) < 0) {
68*fcf3ce44SJohn Forte 		return (-1);
69*fcf3ce44SJohn Forte 	}
70*fcf3ce44SJohn Forte 	if ((size = ioctl(fd, NC_IOC_GETNETNODES, NULL)) < 1) {
71*fcf3ce44SJohn Forte 		size = 1;
72*fcf3ce44SJohn Forte 		ioctlcmd = NC_IOC_GETNODE;
73*fcf3ce44SJohn Forte 	} else {
74*fcf3ce44SJohn Forte 		ioctlcmd = NC_IOC_GETNETNODES;
75*fcf3ce44SJohn Forte 	}
76*fcf3ce44SJohn Forte 
77*fcf3ce44SJohn Forte 	mynodelist = malloc(size * sizeof (*mynodelist));
78*fcf3ce44SJohn Forte 	if (mynodelist == NULL) {
79*fcf3ce44SJohn Forte 		save_errno = ENOMEM;
80*fcf3ce44SJohn Forte 	} else {
81*fcf3ce44SJohn Forte 		rc = ioctl(fd, ioctlcmd, mynodelist);
82*fcf3ce44SJohn Forte 		if (rc < 0) {
83*fcf3ce44SJohn Forte 			save_errno = errno;
84*fcf3ce44SJohn Forte 			free(mynodelist);
85*fcf3ce44SJohn Forte 		} else {
86*fcf3ce44SJohn Forte 			/* fixup return value for single node ioctl */
87*fcf3ce44SJohn Forte 			if (ioctlcmd == NC_IOC_GETNODE)
88*fcf3ce44SJohn Forte 				rc = 1;
89*fcf3ce44SJohn Forte 			*nodelist = mynodelist;
90*fcf3ce44SJohn Forte 		}
91*fcf3ce44SJohn Forte 	}
92*fcf3ce44SJohn Forte 	close(fd);
93*fcf3ce44SJohn Forte 	errno = save_errno;
94*fcf3ce44SJohn Forte 	return (rc);
95*fcf3ce44SJohn Forte }
96*fcf3ce44SJohn Forte 
97*fcf3ce44SJohn Forte 
98*fcf3ce44SJohn Forte /*
99*fcf3ce44SJohn Forte  * return the system id (the current value in the kernel
100*fcf3ce44SJohn Forte  * currently running).
101*fcf3ce44SJohn Forte  *
102*fcf3ce44SJohn Forte  * on error return -1 and set errno.
103*fcf3ce44SJohn Forte  */
104*fcf3ce44SJohn Forte int
105*fcf3ce44SJohn Forte nsc_getsystemid(int *id)
106*fcf3ce44SJohn Forte {
107*fcf3ce44SJohn Forte 	ncall_node_t node;
108*fcf3ce44SJohn Forte 	int rval = 0;
109*fcf3ce44SJohn Forte 	int save_errno = 0;
110*fcf3ce44SJohn Forte 	int fd;
111*fcf3ce44SJohn Forte 
112*fcf3ce44SJohn Forte 	*id = 0;
113*fcf3ce44SJohn Forte 
114*fcf3ce44SJohn Forte 	fd = open("/dev/ncall", O_RDONLY);
115*fcf3ce44SJohn Forte 	if (fd < 0)
116*fcf3ce44SJohn Forte 		return (-1);
117*fcf3ce44SJohn Forte 
118*fcf3ce44SJohn Forte 	memset(&node, 0, sizeof (node));
119*fcf3ce44SJohn Forte 
120*fcf3ce44SJohn Forte 	rval = ioctl(fd, NC_IOC_GETNODE, &node);
121*fcf3ce44SJohn Forte 	if (rval < 0)
122*fcf3ce44SJohn Forte 		save_errno = errno;
123*fcf3ce44SJohn Forte 	else {
124*fcf3ce44SJohn Forte 		*id = node.nc_nodeid;
125*fcf3ce44SJohn Forte 		/*
126*fcf3ce44SJohn Forte 		 * Return 0, not the mirror node id as returned
127*fcf3ce44SJohn Forte 		 * from the ioctl.
128*fcf3ce44SJohn Forte 		 */
129*fcf3ce44SJohn Forte 		rval = 0;
130*fcf3ce44SJohn Forte 	}
131*fcf3ce44SJohn Forte 
132*fcf3ce44SJohn Forte 	close(fd);
133*fcf3ce44SJohn Forte 
134*fcf3ce44SJohn Forte 	errno = save_errno;
135*fcf3ce44SJohn Forte 	return (rval);
136*fcf3ce44SJohn Forte }
137*fcf3ce44SJohn Forte 
138*fcf3ce44SJohn Forte 
139*fcf3ce44SJohn Forte /*
140*fcf3ce44SJohn Forte  * Runtime Solaris release checking.
141*fcf3ce44SJohn Forte  *
142*fcf3ce44SJohn Forte  * Compare the build release to the runtime release to check for an
143*fcf3ce44SJohn Forte  * acceptable match.
144*fcf3ce44SJohn Forte  *
145*fcf3ce44SJohn Forte  * Arguments:
146*fcf3ce44SJohn Forte  *	build_ver   - the string Solaris build release (e.g. "5.8")
147*fcf3ce44SJohn Forte  *	map         - optional array of nsc_release_t defining
148*fcf3ce44SJohn Forte  *			acceptable build release / runtime release
149*fcf3ce44SJohn Forte  *			matches. If supplied, must end will a NULL
150*fcf3ce44SJohn Forte  *			array element.  See src/head/nsctl.h for info.
151*fcf3ce44SJohn Forte  *	reqd        - used to return the required OS versions if the
152*fcf3ce44SJohn Forte  *			return value is not -1.  The returned string
153*fcf3ce44SJohn Forte  *			is readonly.
154*fcf3ce44SJohn Forte  *
155*fcf3ce44SJohn Forte  * Returns:
156*fcf3ce44SJohn Forte  *	TRUE	- acceptable match
157*fcf3ce44SJohn Forte  *	FALSE	- no match (component should not continue to run)
158*fcf3ce44SJohn Forte  *	-1	- error (errno is set)
159*fcf3ce44SJohn Forte  */
160*fcf3ce44SJohn Forte 
161*fcf3ce44SJohn Forte int
162*fcf3ce44SJohn Forte nsc_check_release(const char *build_rel, nsc_release_t *map, char **reqd)
163*fcf3ce44SJohn Forte {
164*fcf3ce44SJohn Forte 	struct utsname uts;
165*fcf3ce44SJohn Forte 	nsc_release_t *mp;
166*fcf3ce44SJohn Forte 	const char *sep = ", ";
167*fcf3ce44SJohn Forte 	char *cp, *tofree, *last;
168*fcf3ce44SJohn Forte 	int rc;
169*fcf3ce44SJohn Forte 
170*fcf3ce44SJohn Forte 	if (reqd)
171*fcf3ce44SJohn Forte 		*reqd = NULL;
172*fcf3ce44SJohn Forte 
173*fcf3ce44SJohn Forte 	if (build_rel == NULL || *build_rel == '\0') {
174*fcf3ce44SJohn Forte 		errno = EINVAL;
175*fcf3ce44SJohn Forte 		return (-1);
176*fcf3ce44SJohn Forte 	}
177*fcf3ce44SJohn Forte 
178*fcf3ce44SJohn Forte 	/* assume that build_rel is the required release for now */
179*fcf3ce44SJohn Forte 	if (reqd)
180*fcf3ce44SJohn Forte 		*reqd = (char *)build_rel;
181*fcf3ce44SJohn Forte 
182*fcf3ce44SJohn Forte 	if (uname(&uts) < 0)
183*fcf3ce44SJohn Forte 		return (-1);
184*fcf3ce44SJohn Forte 
185*fcf3ce44SJohn Forte 	/* build release == runtime release is always acceptable */
186*fcf3ce44SJohn Forte 	if (strcmp(build_rel, uts.release) == 0)
187*fcf3ce44SJohn Forte 		return (TRUE);
188*fcf3ce44SJohn Forte 
189*fcf3ce44SJohn Forte 	if (map == NULL)
190*fcf3ce44SJohn Forte 		return (FALSE);
191*fcf3ce44SJohn Forte 
192*fcf3ce44SJohn Forte 	rc = FALSE;
193*fcf3ce44SJohn Forte 	tofree = NULL;
194*fcf3ce44SJohn Forte 
195*fcf3ce44SJohn Forte 	for (mp = map; mp->build != NULL && mp->runtime != NULL; mp++) {
196*fcf3ce44SJohn Forte 		if (strcmp(mp->build, build_rel) == 0) {
197*fcf3ce44SJohn Forte 			/*
198*fcf3ce44SJohn Forte 			 * found an entry for this build release
199*fcf3ce44SJohn Forte 			 * - search for a match in the runtime releases
200*fcf3ce44SJohn Forte 			 */
201*fcf3ce44SJohn Forte 
202*fcf3ce44SJohn Forte 			/* reset reqd to this entry */
203*fcf3ce44SJohn Forte 			if (reqd)
204*fcf3ce44SJohn Forte 				*reqd = (char *)mp->runtime;
205*fcf3ce44SJohn Forte 
206*fcf3ce44SJohn Forte 			/*
207*fcf3ce44SJohn Forte 			 * operate on a copy of the string since strtok
208*fcf3ce44SJohn Forte 			 * is destructive.
209*fcf3ce44SJohn Forte 			 */
210*fcf3ce44SJohn Forte 			tofree = cp = strdup(mp->runtime);
211*fcf3ce44SJohn Forte 			if (cp == NULL) {
212*fcf3ce44SJohn Forte 				errno = ENOMEM;
213*fcf3ce44SJohn Forte 				rc = -1;
214*fcf3ce44SJohn Forte 				break;
215*fcf3ce44SJohn Forte 			}
216*fcf3ce44SJohn Forte 
217*fcf3ce44SJohn Forte 			cp = strtok_r(cp, sep, &last);
218*fcf3ce44SJohn Forte 			while (cp != NULL) {
219*fcf3ce44SJohn Forte 				if (strcmp(cp, uts.release) == 0) {
220*fcf3ce44SJohn Forte 					rc = TRUE;
221*fcf3ce44SJohn Forte 					break;
222*fcf3ce44SJohn Forte 				}
223*fcf3ce44SJohn Forte 
224*fcf3ce44SJohn Forte 				cp = strtok_r(NULL, sep, &last);
225*fcf3ce44SJohn Forte 			}
226*fcf3ce44SJohn Forte 
227*fcf3ce44SJohn Forte 			break;
228*fcf3ce44SJohn Forte 		}
229*fcf3ce44SJohn Forte 	}
230*fcf3ce44SJohn Forte 
231*fcf3ce44SJohn Forte 	if (tofree)
232*fcf3ce44SJohn Forte 		free(tofree);
233*fcf3ce44SJohn Forte 
234*fcf3ce44SJohn Forte 	return (rc);
235*fcf3ce44SJohn Forte }
236*fcf3ce44SJohn Forte 
237*fcf3ce44SJohn Forte 
238*fcf3ce44SJohn Forte /*
239*fcf3ce44SJohn Forte  * return the system id corresponding to name
240*fcf3ce44SJohn Forte  *
241*fcf3ce44SJohn Forte  * on error return -1 and set errno.
242*fcf3ce44SJohn Forte  */
243*fcf3ce44SJohn Forte int
244*fcf3ce44SJohn Forte nsc_name_to_id(char *name, int *id)
245*fcf3ce44SJohn Forte {
246*fcf3ce44SJohn Forte 	ncall_node_t *nodes;
247*fcf3ce44SJohn Forte 	int rval = 0;
248*fcf3ce44SJohn Forte 	int nodecnt;
249*fcf3ce44SJohn Forte 	int slot;
250*fcf3ce44SJohn Forte 
251*fcf3ce44SJohn Forte 	*id = 0;
252*fcf3ce44SJohn Forte 
253*fcf3ce44SJohn Forte 	nodecnt = nsc_getcurrentnodes(&nodes);
254*fcf3ce44SJohn Forte 	if (nodecnt < 0) {
255*fcf3ce44SJohn Forte 		rval = -1;
256*fcf3ce44SJohn Forte 	} else {
257*fcf3ce44SJohn Forte 		for (slot = 0; slot < nodecnt; slot++) {
258*fcf3ce44SJohn Forte 			if (strcmp(name, nodes[slot].nc_nodename) == 0) {
259*fcf3ce44SJohn Forte 				*id = nodes[slot].nc_nodeid;
260*fcf3ce44SJohn Forte 				break;
261*fcf3ce44SJohn Forte 			}
262*fcf3ce44SJohn Forte 		}
263*fcf3ce44SJohn Forte 		if (slot >= nodecnt) {
264*fcf3ce44SJohn Forte 			errno = ENOENT;
265*fcf3ce44SJohn Forte 			rval = -1;
266*fcf3ce44SJohn Forte 		}
267*fcf3ce44SJohn Forte 		free(nodes);
268*fcf3ce44SJohn Forte 	}
269*fcf3ce44SJohn Forte 	return (rval);
270*fcf3ce44SJohn Forte }
271*fcf3ce44SJohn Forte 
272*fcf3ce44SJohn Forte /*
273*fcf3ce44SJohn Forte  * return the node name corresponding to system id
274*fcf3ce44SJohn Forte  *
275*fcf3ce44SJohn Forte  * on error return -1 and set errno.
276*fcf3ce44SJohn Forte  * The returned string has been strdup() and needs
277*fcf3ce44SJohn Forte  * to be freed by the caller.
278*fcf3ce44SJohn Forte  */
279*fcf3ce44SJohn Forte int
280*fcf3ce44SJohn Forte nsc_id_to_name(char **name, int id)
281*fcf3ce44SJohn Forte {
282*fcf3ce44SJohn Forte 	ncall_node_t *nodes;
283*fcf3ce44SJohn Forte 	int rval = 0;
284*fcf3ce44SJohn Forte 	int nodecnt;
285*fcf3ce44SJohn Forte 	int slot;
286*fcf3ce44SJohn Forte 	char *foundname;
287*fcf3ce44SJohn Forte 
288*fcf3ce44SJohn Forte 	*name = 0;
289*fcf3ce44SJohn Forte 	foundname = NULL;
290*fcf3ce44SJohn Forte 
291*fcf3ce44SJohn Forte 	nodecnt = nsc_getcurrentnodes(&nodes);
292*fcf3ce44SJohn Forte 	if (nodecnt < 0) {
293*fcf3ce44SJohn Forte 		rval = -1;
294*fcf3ce44SJohn Forte 	} else {
295*fcf3ce44SJohn Forte 		for (slot = 0; slot < nodecnt; slot++) {
296*fcf3ce44SJohn Forte 			if (nodes[slot].nc_nodeid == id) {
297*fcf3ce44SJohn Forte 				foundname = strdup(nodes[slot].nc_nodename);
298*fcf3ce44SJohn Forte 				if (foundname) {
299*fcf3ce44SJohn Forte 					*name = foundname;
300*fcf3ce44SJohn Forte 				} else {
301*fcf3ce44SJohn Forte 					errno = ENOMEM;
302*fcf3ce44SJohn Forte 					rval = -1;
303*fcf3ce44SJohn Forte 				}
304*fcf3ce44SJohn Forte 				break;
305*fcf3ce44SJohn Forte 			}
306*fcf3ce44SJohn Forte 		}
307*fcf3ce44SJohn Forte 		if (slot >= nodecnt) {
308*fcf3ce44SJohn Forte 			errno = ENOENT;
309*fcf3ce44SJohn Forte 			rval = -1;
310*fcf3ce44SJohn Forte 		}
311*fcf3ce44SJohn Forte 		free(nodes);
312*fcf3ce44SJohn Forte 	}
313*fcf3ce44SJohn Forte 	return (rval);
314*fcf3ce44SJohn Forte }
315