OpenSolaris_b135/common/tsol/ltos.c

Compare this file to the similar file:
Show the results in this format:

/*
 * 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 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#if !defined(_KERNEL)
#include <errno.h>
#endif /* !defined(_KERNEL) */

#include <sys/types.h>
#include <sys/mman.h>
#include <sys/tsol/label_macro.h>

#include <sys/tsol/label.h>

#if !defined(_KERNEL)
#include "clnt.h"
#include "labeld.h"
#endif /* !defined(_KERNEL) */

#if defined(_KERNEL)
#include <sys/systm.h>
#include <sys/sunddi.h>
#else
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#endif



static _mac_label_impl_t low;
static _mac_label_impl_t high;
static int	inited = 0;

#if defined(_KERNEL)
#define	malloc(l)	kmem_alloc(l, KM_NOSLEEP)
#define	freeit(a, l)		kmem_free(a, l)
#else /* defined(_KERNEL) */
#define	freeit(a, l)		free(a)
#endif /* defined(_KERNEL) */

/* 0x + Classification + '-' + ll + '-' + Compartments + end of string */
#define	_HEX_SIZE 2+(sizeof (Classification_t)*2)+4+\
	(sizeof (Compartments_t)*2)+1

/* 0x + Classification + '-' + ll + '-' + end of string */
#define	_MIN_HEX (2 + (sizeof (Classification_t)*2) + 4 + 1)

static char digits[] = "0123456789abcdef";

#define	HEX(h, i, l, s) \
	for (; i < s; /* */) {\
	h[i++] = digits[(unsigned int)(*l >> 4)];\
	h[i++] = digits[(unsigned int)(*l++&0xF)]; }

static int
__hex(char **s, const m_label_t *l)
{
	char	*hex;
	int	i = 0;
	uchar_t *hl;
	int	hex_len;
	uchar_t *len;

	hl = (uchar_t  *)&(((_mac_label_impl_t *)l)->_c_len);
	len = hl;

	if (*len == 0) {
		/* old binary label */
		hex_len = _HEX_SIZE;
	} else {
		hex_len = _MIN_HEX + (*len * sizeof (uint32_t) * 2);
	}

	if ((hex = malloc(hex_len)) == NULL) {
		return (-1);
	}

	/* header */

	hex[i++] = '0';
	hex[i++] = 'x';

	/* classification */

	hl++;		/* start at classification */
	HEX(hex, i, hl, 6);

	/* Add compartments length */
	hex[i++] = '-';
	HEX(hex, i, len, 9);
	hex[i++] = '-';

	/* compartments */
	HEX(hex, i, hl, hex_len-1);
	hex[i] = '\0';

	/* truncate trailing zeros */

	while (hex[i-1] == '0' && hex[i-2] == '0') {
		i -= 2;
	}
	hex[i] = '\0';

	if ((*s = strdup(hex)) == NULL) {
		freeit(hex, hex_len);
		return (-1);
	}

	freeit(hex, hex_len);
	return (0);

}

int
l_to_str_internal(const m_label_t *l, char **s)
{
	if (inited == 0) {
		inited = 1;
		_BSLLOW(&low);
		_BSLHIGH(&high);
	}

	if (!(_MTYPE(l, SUN_MAC_ID) || _MTYPE(l, SUN_UCLR_ID))) {
#if !defined(_KERNEL)
		errno = EINVAL;
#endif /* !defined(_KERNEL) */
		*s = NULL;
		return (-1);
	}
	if (_MEQUAL(&low, (_mac_label_impl_t *)l)) {
		if ((*s = strdup(ADMIN_LOW)) == NULL) {
			return (-1);
		}
		return (0);
	}
	if (_MEQUAL(&high, (_mac_label_impl_t *)l)) {
		if ((*s = strdup(ADMIN_HIGH)) == NULL) {
			return (-1);
		}
		return (0);
	}

	return (__hex(s, l));
}

#if !defined(_KERNEL)
/*
 * label_to_str -- convert a label to the requested type of string.
 *
 *	Entry	l = label to convert;
 *		t = type of conversion;
 *		f = flags for conversion type;
 *
 *	Exit	*s = allocated converted string;
 *		     Caller must call free() to free.
 *
 *	Returns	0, success.
 *		-1, error, errno set; *s = NULL.
 *
 *	Calls	labeld
 */

int
label_to_str(const m_label_t *l, char **s, const m_label_str_t t, uint_t f)
{
	labeld_data_t	call;
	labeld_data_t	*callp = &call;
	size_t	bufsize = sizeof (labeld_data_t);
	size_t	datasize;
	int	err;
	int	string_start = 0;

	if (inited == 0) {
		inited = 1;
		_BSLLOW(&low);
		_BSLHIGH(&high);
	}

#define	lscall callp->param.acall.cargs.ls_arg
#define	lsret callp->param.aret.rvals.ls_ret
	switch (t) {
	case M_LABEL:
		call.callop = LTOS;
		lscall.label = *l;
		lscall.flags = f;
		datasize = CALL_SIZE(ls_call_t, 0);
		if ((err = __call_labeld(&callp, &bufsize, &datasize)) ==
		    SUCCESS) {
			if (callp->reterr != 0) {
				errno = EINVAL;
				*s = NULL;
				return (-1);
			}
			*s = strdup(lsret.buf);
			if (callp != &call) {
				/* release returned buffer */
				(void) munmap((void *)callp, bufsize);
			}
			if (*s == NULL) {
				return (-1);
			}
			return (0);
		}
		switch (err) {
		case NOSERVER:
			/* server not present */
			/* special case admin_low and admin_high */

			if (_MEQUAL(&low, (_mac_label_impl_t *)l)) {
				if ((*s = strdup(ADMIN_LOW)) == NULL) {
					return (-1);
				}
				return (0);
			} else if (_MEQUAL(&high, (_mac_label_impl_t *)l)) {
				if ((*s = strdup(ADMIN_HIGH)) == NULL) {
					return (-1);
				}
				return (0);
			}
			errno = ENOTSUP;
			break;
		default:
			errno = EINVAL;
			break;
		}
		*s = NULL;
		return (-1);
#undef	lscall
#undef	lsret

	case M_INTERNAL: {
		return (l_to_str_internal(l, s));
	}

#define	ccall callp->param.acall.cargs.color_arg
#define	cret callp->param.aret.rvals.color_ret
	case M_COLOR:
		datasize = CALL_SIZE(color_call_t, 0);
		call.callop = BLTOCOLOR;
		ccall.label = *l;

		if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) {
			if (callp->reterr != 0) {
				errno = EINVAL;
				*s = NULL;
				return (-1);
			}
			*s = strdup(cret.color);
			if (callp != &call) {
				/* release returned buffer */
				(void) munmap((void *)callp, bufsize);
			}
			if (*s == NULL) {
				return (-1);
			}
			return (0);
		} else {
			errno = ENOTSUP;
			*s = NULL;
			return (-1);
		}
#undef	ccall
#undef	cret

#define	prcall	callp->param.acall.cargs.pr_arg
#define	prret	callp->param.aret.rvals.pr_ret
	case PRINTER_TOP_BOTTOM:
		call.callop = PR_TOP;
		break;
	case PRINTER_LABEL:
		call.callop = PR_LABEL;
		break;
	case PRINTER_CAVEATS:
		call.callop = PR_CAVEATS;
		string_start = 1;	/* compensate for leading space */
		break;
	case PRINTER_CHANNELS:
		call.callop = PR_CHANNELS;
		string_start = 1;	/* compensate for leading space */
		break;
	default:
		errno = EINVAL;
		*s = NULL;
		return (-1);
	}
	/* do the common printer calls */
	datasize = CALL_SIZE(pr_call_t, 0);
	prcall.label = *l;
	prcall.flags = f;
	if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) {
		if (callp->reterr != 0) {
			errno = EINVAL;
			*s = NULL;
			return (-1);
		}
		*s = strdup(&prret.buf[string_start]);
		if (callp != &call) {
			/* release returned buffer */
			(void) munmap((void *)callp, bufsize);
		}
		if (*s == NULL) {
			return (-1);
		}
		return (0);
	} else {
		errno = ENOTSUP;
		*s = NULL;
		return (-1);
	}
#undef	prcall
#undef	prret
}
#endif /* !defined(_KERNEL) */