/*
* 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
* 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
*/
/*
*/
/*
* util.c contains a set of miscellaneous utility functions which,
* among other things:
* - start a child process
* - look up the zone name
*/
#include <assert.h>
#include <errno.h>
#include <libdllink.h>
#include <limits.h>
#include <libscf.h>
#include <pthread.h>
#include <pwd.h>
#include <spawn.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stropts.h>
#include <unistd.h>
#include <wait.h>
#include <zone.h>
#include "util.h"
#include "llp.h"
extern char **environ;
extern sigset_t original_sigmask;
/*
* A holder for all the resources needed to get a property value
* using libscf.
*/
typedef struct scf_resources {
static int uid_cnt;
void
nwamd_escalate(void) {
(void) pthread_mutex_lock(&uid_mutex);
if (uid == 0)
if (uid_cnt++ == 0) {
}
}
(void) pthread_mutex_unlock(&uid_mutex);
}
void
nwamd_deescalate(void) {
(void) pthread_mutex_lock(&uid_mutex);
if (--uid_cnt == 0) {
/* build up our minimal set of privs. */
/*
* Since our zone might not have all these privs,
* just ask for those that are available.
*/
}
/*
* Need to ensure permitted set contains all privs so we can
* escalate later.
*/
}
/*
* We need to find a smaller set of privs that are important to
* us. Otherwise we really are not gaining much by doing this.
*/
}
}
(void) pthread_mutex_unlock(&uid_mutex);
}
/*
*
* This starts a child process determined by command. If command contains a
* slash then it is assumed to be a full path; otherwise the path is searched
* for an executable file with the name command. Command is also used as
* argv[0] of the new process. The rest of the arguments of the function
* up to the first NULL make up pointers to arguments of the new process.
*
* This function returns child exit status on success and -1 on failure.
*
* NOTE: original_sigmask must be set before this function is called.
*/
int
{
vbuf[0] = 0;
n = sizeof (vbuf);
}
return (-1);
}
(void) sigfillset(&fullset);
return (-1);
}
return (-1);
}
POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK)) != 0) {
return (-1);
}
environ)) > 0) {
return (-1);
}
return (-1);
}
strsignal(i));
return (-2);
} else {
return (WEXITSTATUS(status));
}
}
/*
* For global zone, check if the link is used by a non-global
* zone, note that the non-global zones doesn't need this check,
* because zoneadm has taken care of this when the zone boots.
* In the global zone, we ignore events for local-zone-owned links
* since these are taken care of by the local zone's network
* configuration services.
*/
{
int ret;
if (zoneid == GLOBAL_ZONEID) {
"could not get linkid for %s: %s",
return (B_FALSE);
}
if (ret == 0) {
"%s is used by non-global zone: %s",
return (B_FALSE);
}
}
return (B_TRUE);
}
/*
* Inputs:
* res is a pointer to the scf_resources_t to be released.
*/
static void
{
}
/*
* Inputs:
* fmri is the instance to look up
* Outputs:
* res is a pointer to an scf_resources_t. This is an internal
* structure that holds all the handles needed to get a specific
* property from the running snapshot; on a successful return it
* contains the scf_value_t that should be passed to the desired
* scf_value_get_foo() function, and must be freed after use by
* calling release_scf_resources(). On a failure return, any
* resources that may have been assigned to res are released, so
* the caller does not need to do any cleanup in the failure case.
* Returns:
* 0 on success
* -1 on failure
*/
static int
{
return (-1);
}
return (-1);
}
goto failure;
}
goto failure;
}
goto failure;
}
goto failure;
}
goto failure;
}
goto failure;
}
goto failure;
}
goto failure;
}
goto failure;
}
return (0);
scf_strerror(scf_error()));
return (-1);
}
/*
* Inputs:
* fmri is the instance to look up
* pg is the property group to look up
* prop is the property within that group to look up
* running specifies if running snapshot is to be used
* Outputs:
* res is a pointer to an scf_resources_t. This is an internal
* structure that holds all the handles needed to get a specific
* property from the running snapshot; on a successful return it
* contains the scf_value_t that should be passed to the desired
* scf_value_get_foo() function, and must be freed after use by
* calling release_scf_resources(). On a failure return, any
* resources that may have been assigned to res are released, so
* the caller does not need to do any cleanup in the failure case.
* Returns:
* 0 on success
* -1 on failure
*/
static int
{
return (-1);
goto failure;
}
goto failure;
}
goto failure;
}
return (0);
return (-1);
}
/*
* Inputs:
* lfmri is the instance fmri to look up
* lpg is the property group to look up
* lprop is the property within that group to look up
* Outputs:
* answer is a pointer to the property value
* Returns:
* 0 on success
* -1 on failure
* If successful, the property value is retured in *answer.
* Otherwise, *answer is undefined, and it is up to the caller to decide
* how to handle that case.
*/
int
{
/*
* an error was already logged by get_property_value,
* and it released any resources assigned to res before
* returning.
*/
return (result);
}
goto cleanup;
}
result = 0;
return (result);
}
/*
* Inputs:
* lfmri is the instance fmri to look up
* lpg is the property group to look up
* lprop is the property within that group to look up
* buf is the place to put the answer
* bufsz is the size of buf
* Outputs:
*
* Returns:
* 0 on success
* -1 on failure
* If successful, the property value is retured in buf.
* Otherwise, buf is undefined, and it is up to the caller to decide
* how to handle that case.
*/
int
{
/*
* The above function fails when trying to get a
* non-persistent property group from the running snapshot.
* Try going for the non-running snapshot.
*/
/*
* an error was already logged by get_property_value,
* and it released any resources assigned to res before
* returning.
*/
return (result);
}
}
goto cleanup;
result = 0;
return (result);
}
/*
* Inputs:
* lfmri is the instance fmri to look up
* lpg is the property group to look up
* lprop is the property within that group to look up
* Outputs:
* answer is a pointer to the property value
* Returns:
* 0 on success
* -1 on failure
* If successful, the property value is retured in *answer.
* Otherwise, *answer is undefined, and it is up to the caller to decide
* how to handle that case.
*/
int
{
/*
* an error was already logged by get_property_value,
* and it released any resources assigned to res before
* returning.
*/
return (result);
}
goto cleanup;
}
result = 0;
return (result);
}
static int
{
goto failure;
}
if (new) {
goto failure;
}
} else {
goto failure;
}
}
goto failure;
}
if (result == 0) {
goto failure;
}
"for %s; retrying", propname);
goto retry;
}
if (result == -1)
goto failure;
return (0);
return (-1);
}
int
{
return (-1);
if (scf_error() != SCF_ERROR_EXISTS)
goto failure;
goto failure;
}
goto failure;
return (0);
return (-1);
}
int
const char *str)
{
return (-1);
if (scf_error() != SCF_ERROR_EXISTS)
goto failure;
goto failure;
}
goto failure;
goto failure;
return (0);
return (-1);
}
/*
* Deletes property prop from property group pg in SMF instance fmri.
* Returns 0 on success, -1 on failure.
*/
int
{
return (-1);
if (scf_error() != SCF_ERROR_EXISTS)
goto failure;
goto failure;
}
goto failure;
goto failure;
goto failure;
if (result == 0) {
goto failure;
goto retry;
}
if (result == -1)
goto failure;
return (0);
return (-1);
}