diff options
Diffstat (limited to 'usr/src/lib/libnsctl/common/machdep.c')
| -rw-r--r-- | usr/src/lib/libnsctl/common/machdep.c | 314 | 
1 files changed, 314 insertions, 0 deletions
| diff --git a/usr/src/lib/libnsctl/common/machdep.c b/usr/src/lib/libnsctl/common/machdep.c new file mode 100644 index 0000000000..d577995ad1 --- /dev/null +++ b/usr/src/lib/libnsctl/common/machdep.c @@ -0,0 +1,314 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc.  All rights reserved. + * Use is subject to license terms. + */ + +#include <sys/types.h> +#include <sys/utsname.h> +#include <fcntl.h> +#include <sys/param.h> +#include <unistd.h> +#include <stdarg.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "libnsctl.h" +#include <nsctl.h> +#include <sys/ncall/ncall.h> + + + +/* + * Internal routine to fetch all the current nodes that are + * considered 'up'. + * Returns the number of ncall_info structures that are valid + * returned via the nodelist pointer, or -1 on an error. + * If the call succeeds, then the memory returned via the + * nodelist pointer needs to be freed by the caller. + */ + +static int +nsc_getcurrentnodes(ncall_node_t **nodelist) +{ +	ncall_node_t *mynodelist; +	int size; +	int fd; +	int rc = -1; +	int save_errno = 0; +	int ioctlcmd; + +	if (nodelist == NULL) { +		errno = EINVAL; +		return (-1); +	} +	*nodelist = NULL; +	if ((fd = open("/dev/ncall", O_RDONLY)) < 0) { +		return (-1); +	} +	if ((size = ioctl(fd, NC_IOC_GETNETNODES, NULL)) < 1) { +		size = 1; +		ioctlcmd = NC_IOC_GETNODE; +	} else { +		ioctlcmd = NC_IOC_GETNETNODES; +	} + +	mynodelist = malloc(size * sizeof (*mynodelist)); +	if (mynodelist == NULL) { +		save_errno = ENOMEM; +	} else { +		rc = ioctl(fd, ioctlcmd, mynodelist); +		if (rc < 0) { +			save_errno = errno; +			free(mynodelist); +		} else { +			/* fixup return value for single node ioctl */ +			if (ioctlcmd == NC_IOC_GETNODE) +				rc = 1; +			*nodelist = mynodelist; +		} +	} +	close(fd); +	errno = save_errno; +	return (rc); +} + + +/* + * return the system id (the current value in the kernel + * currently running). + * + * on error return -1 and set errno. + */ +int +nsc_getsystemid(int *id) +{ +	ncall_node_t node; +	int rval = 0; +	int save_errno = 0; +	int fd; + +	*id = 0; + +	fd = open("/dev/ncall", O_RDONLY); +	if (fd < 0) +		return (-1); + +	memset(&node, 0, sizeof (node)); + +	rval = ioctl(fd, NC_IOC_GETNODE, &node); +	if (rval < 0) +		save_errno = errno; +	else { +		*id = node.nc_nodeid; +		/* +		 * Return 0, not the mirror node id as returned +		 * from the ioctl. +		 */ +		rval = 0; +	} + +	close(fd); + +	errno = save_errno; +	return (rval); +} + + +/* + * Runtime Solaris release checking. + * + * Compare the build release to the runtime release to check for an + * acceptable match. + * + * Arguments: + *	build_ver   - the string Solaris build release (e.g. "5.8") + *	map         - optional array of nsc_release_t defining + *			acceptable build release / runtime release + *			matches. If supplied, must end will a NULL + *			array element.  See src/head/nsctl.h for info. + *	reqd        - used to return the required OS versions if the + *			return value is not -1.  The returned string + *			is readonly. + * + * Returns: + *	TRUE	- acceptable match + *	FALSE	- no match (component should not continue to run) + *	-1	- error (errno is set) + */ + +int +nsc_check_release(const char *build_rel, nsc_release_t *map, char **reqd) +{ +	struct utsname uts; +	nsc_release_t *mp; +	const char *sep = ", "; +	char *cp, *tofree, *last; +	int rc; + +	if (reqd) +		*reqd = NULL; + +	if (build_rel == NULL || *build_rel == '\0') { +		errno = EINVAL; +		return (-1); +	} + +	/* assume that build_rel is the required release for now */ +	if (reqd) +		*reqd = (char *)build_rel; + +	if (uname(&uts) < 0) +		return (-1); + +	/* build release == runtime release is always acceptable */ +	if (strcmp(build_rel, uts.release) == 0) +		return (TRUE); + +	if (map == NULL) +		return (FALSE); + +	rc = FALSE; +	tofree = NULL; + +	for (mp = map; mp->build != NULL && mp->runtime != NULL; mp++) { +		if (strcmp(mp->build, build_rel) == 0) { +			/* +			 * found an entry for this build release +			 * - search for a match in the runtime releases +			 */ + +			/* reset reqd to this entry */ +			if (reqd) +				*reqd = (char *)mp->runtime; + +			/* +			 * operate on a copy of the string since strtok +			 * is destructive. +			 */ +			tofree = cp = strdup(mp->runtime); +			if (cp == NULL) { +				errno = ENOMEM; +				rc = -1; +				break; +			} + +			cp = strtok_r(cp, sep, &last); +			while (cp != NULL) { +				if (strcmp(cp, uts.release) == 0) { +					rc = TRUE; +					break; +				} + +				cp = strtok_r(NULL, sep, &last); +			} + +			break; +		} +	} + +	if (tofree) +		free(tofree); + +	return (rc); +} + + +/* + * return the system id corresponding to name + * + * on error return -1 and set errno. + */ +int +nsc_name_to_id(char *name, int *id) +{ +	ncall_node_t *nodes; +	int rval = 0; +	int nodecnt; +	int slot; + +	*id = 0; + +	nodecnt = nsc_getcurrentnodes(&nodes); +	if (nodecnt < 0) { +		rval = -1; +	} else { +		for (slot = 0; slot < nodecnt; slot++) { +			if (strcmp(name, nodes[slot].nc_nodename) == 0) { +				*id = nodes[slot].nc_nodeid; +				break; +			} +		} +		if (slot >= nodecnt) { +			errno = ENOENT; +			rval = -1; +		} +		free(nodes); +	} +	return (rval); +} + +/* + * return the node name corresponding to system id + * + * on error return -1 and set errno. + * The returned string has been strdup() and needs + * to be freed by the caller. + */ +int +nsc_id_to_name(char **name, int id) +{ +	ncall_node_t *nodes; +	int rval = 0; +	int nodecnt; +	int slot; +	char *foundname; + +	*name = 0; +	foundname = NULL; + +	nodecnt = nsc_getcurrentnodes(&nodes); +	if (nodecnt < 0) { +		rval = -1; +	} else { +		for (slot = 0; slot < nodecnt; slot++) { +			if (nodes[slot].nc_nodeid == id) { +				foundname = strdup(nodes[slot].nc_nodename); +				if (foundname) { +					*name = foundname; +				} else { +					errno = ENOMEM; +					rval = -1; +				} +				break; +			} +		} +		if (slot >= nodecnt) { +			errno = ENOENT; +			rval = -1; +		} +		free(nodes); +	} +	return (rval); +} | 
