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