xref: /illumos-gate/usr/src/common/tsol/stol.c (revision 4201a95e)
145916cd2Sjpk /*
245916cd2Sjpk  * CDDL HEADER START
345916cd2Sjpk  *
445916cd2Sjpk  * The contents of this file are subject to the terms of the
545916cd2Sjpk  * Common Development and Distribution License (the "License").
645916cd2Sjpk  * You may not use this file except in compliance with the License.
745916cd2Sjpk  *
845916cd2Sjpk  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
945916cd2Sjpk  * or http://www.opensolaris.org/os/licensing.
1045916cd2Sjpk  * See the License for the specific language governing permissions
1145916cd2Sjpk  * and limitations under the License.
1245916cd2Sjpk  *
1345916cd2Sjpk  * When distributing Covered Code, include this CDDL HEADER in each
1445916cd2Sjpk  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1545916cd2Sjpk  * If applicable, add the following below this CDDL HEADER, with the
1645916cd2Sjpk  * fields enclosed by brackets "[]" replaced with your own identifying
1745916cd2Sjpk  * information: Portions Copyright [yyyy] [name of copyright owner]
1845916cd2Sjpk  *
1945916cd2Sjpk  * CDDL HEADER END
2045916cd2Sjpk  */
2145916cd2Sjpk /*
22ad355aa0Sgww  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2345916cd2Sjpk  * Use is subject to license terms.
2445916cd2Sjpk  */
2545916cd2Sjpk 
26*4201a95eSRic Aleshire #if !defined(_KERNEL)
2745916cd2Sjpk #include <errno.h>
2845916cd2Sjpk #include <stdio.h>
2945916cd2Sjpk #include <stdlib.h>
3045916cd2Sjpk #include <string.h>
31*4201a95eSRic Aleshire #include <ctype.h>
3245916cd2Sjpk #include <strings.h>
33*4201a95eSRic Aleshire #else /* !defined(_KERNEL) */
34*4201a95eSRic Aleshire #include <sys/systm.h>
35*4201a95eSRic Aleshire #endif /* !defined(_KERNEL) */
3645916cd2Sjpk 
3745916cd2Sjpk #include <sys/mman.h>
3845916cd2Sjpk #include <sys/tsol/label_macro.h>
3945916cd2Sjpk 
40*4201a95eSRic Aleshire #include <sys/tsol/label.h>
4145916cd2Sjpk 
42*4201a95eSRic Aleshire #if !defined(_KERNEL)
4345916cd2Sjpk #include "clnt.h"
4445916cd2Sjpk #include "labeld.h"
45*4201a95eSRic Aleshire #else /* !defined(_KERNEL) */
46*4201a95eSRic Aleshire #include <util/strtolctype.h>
47*4201a95eSRic Aleshire 
48*4201a95eSRic Aleshire #define	L_DEFAULT	0x0
49*4201a95eSRic Aleshire #define	L_NO_CORRECTION	0x2
50*4201a95eSRic Aleshire #endif /* !defined(_KERNEL) */
5145916cd2Sjpk 
5245916cd2Sjpk #define	IS_LOW(s) \
5345916cd2Sjpk 	((strncasecmp(s, ADMIN_LOW, (sizeof (ADMIN_LOW) - 1)) == 0) && \
5445916cd2Sjpk 	(s[sizeof (ADMIN_LOW) - 1] == '\0'))
5545916cd2Sjpk #define	IS_HIGH(s) \
5645916cd2Sjpk 	((strncasecmp(s, ADMIN_HIGH, (sizeof (ADMIN_HIGH) - 1)) == 0) && \
5745916cd2Sjpk 	(s[sizeof (ADMIN_HIGH) - 1] == '\0'))
5845916cd2Sjpk #define	IS_HEX(f, s) \
5945916cd2Sjpk 	(((((f) == L_NO_CORRECTION)) || ((f) == L_DEFAULT)) && \
6045916cd2Sjpk 	(((s)[0] == '0') && (((s)[1] == 'x') || ((s)[1] == 'X'))))
6145916cd2Sjpk 
6245916cd2Sjpk static boolean_t
unhex(const char ** h,uchar_t * l,int len)63*4201a95eSRic Aleshire unhex(const char **h, uchar_t *l, int len)
6445916cd2Sjpk {
65*4201a95eSRic Aleshire 	const char	*hx = *h;
6645916cd2Sjpk 	char	ch;
6745916cd2Sjpk 	uchar_t	byte;
6845916cd2Sjpk 
6945916cd2Sjpk 	for (; len--; ) {
7045916cd2Sjpk 		ch = *hx++;
7145916cd2Sjpk 		if (!isxdigit(ch))
7245916cd2Sjpk 			return (B_FALSE);
7345916cd2Sjpk 		if (isdigit(ch))
7445916cd2Sjpk 			byte = ch - '0';
7545916cd2Sjpk 		else
7645916cd2Sjpk 			byte = ch - (isupper(ch) ? 'A' - 10 : 'a' - 10);
7745916cd2Sjpk 		byte <<= 4;
7845916cd2Sjpk 		ch = *hx++;
79e9d1e0cdSgww 		if (!isxdigit(ch))
80e9d1e0cdSgww 			return (B_FALSE);
8145916cd2Sjpk 		if (isdigit(ch))
8245916cd2Sjpk 			byte |= ch - '0';
8345916cd2Sjpk 		else
8445916cd2Sjpk 			byte |= ch - (isupper(ch) ? 'A' - 10 : 'a' - 10);
8545916cd2Sjpk 		*l++ = byte;
8645916cd2Sjpk 	}
8745916cd2Sjpk 	*h = hx;
8845916cd2Sjpk 	return (B_TRUE);
8945916cd2Sjpk }
9045916cd2Sjpk 
9145916cd2Sjpk /*
9245916cd2Sjpk  * Formats accepted:
9345916cd2Sjpk  * 0x + 4 class + 64 comps + end of string
9445916cd2Sjpk  * 0x + 4 class + '-' + ll + '-' + comps + end of string
9545916cd2Sjpk  * ll = number of words to fill out the entire comps field
9645916cd2Sjpk  *      presumes trailing zero for comps
9745916cd2Sjpk  *
9845916cd2Sjpk  * So in the case of 256 comps (i.e., 8 compartment words):
9945916cd2Sjpk  * 0x0006-08-7ff3f
10045916cd2Sjpk  * 0x + Classification + Compartments + end of string
10145916cd2Sjpk  * 0[xX]hhh...
10245916cd2Sjpk  */
10345916cd2Sjpk 
10445916cd2Sjpk static int
htol(const char * s,m_label_t * l)105*4201a95eSRic Aleshire htol(const char *s, m_label_t *l)
10645916cd2Sjpk {
107*4201a95eSRic Aleshire 	const char	*h = &s[2];	/* skip 0[xX] */
10845916cd2Sjpk 	uchar_t *lp = (uchar_t *)&(((_mac_label_impl_t *)l)->_lclass);
10945916cd2Sjpk 	size_t	len = sizeof (_mac_label_impl_t) - 4;
11045916cd2Sjpk 	int	bytes;
11145916cd2Sjpk 
112dc8169d4Sgww 	/* unpack 16 bit signed classification */
113dc8169d4Sgww 	if (!unhex(&h, lp, 2) || (LCLASS(l) < 0)) {
114dc8169d4Sgww 		return (-1);
11545916cd2Sjpk 	}
11645916cd2Sjpk 	lp = (uchar_t *)&(((_mac_label_impl_t *)l)->_comps);
11745916cd2Sjpk 	if (h[0] == '-' && h[3] == '-') {
11845916cd2Sjpk 		uchar_t size;
11945916cd2Sjpk 
12045916cd2Sjpk 		/* length specified of internal text label */
12145916cd2Sjpk 		h++;	/* skip '-' */
12245916cd2Sjpk 		if (!unhex(&h, &size, 1)) {
123dc8169d4Sgww 			return (-1);
12445916cd2Sjpk 		}
1254788ac75Sgww 		/* convert size from words to bytes */
1264788ac75Sgww 		if ((size * sizeof (uint32_t)) > len) {
12745916cd2Sjpk 			/*
12845916cd2Sjpk 			 * internal label greater than will fit in current
12945916cd2Sjpk 			 * binary.
13045916cd2Sjpk 			 */
131dc8169d4Sgww 			return (-1);
13245916cd2Sjpk 		}
13345916cd2Sjpk 		bzero(lp, len);
13445916cd2Sjpk 		h++;	/* skip '-' */
13545916cd2Sjpk 	}
136dc8169d4Sgww 	bytes = strlen(h)/2;
137dc8169d4Sgww 	if ((bytes > len) ||
138dc8169d4Sgww 	    (bytes*2 != strlen(h)) ||
139dc8169d4Sgww 	    !unhex(&h, lp, bytes)) {
140dc8169d4Sgww 		return (-1);
14145916cd2Sjpk 	}
14245916cd2Sjpk 	return (0);
14345916cd2Sjpk }
14445916cd2Sjpk 
145*4201a95eSRic Aleshire /*
146*4201a95eSRic Aleshire  * hexstr_to_label -- parse a string representing a hex label into a
147*4201a95eSRic Aleshire  *			binary label.  Only admin high/low and hex are
148*4201a95eSRic Aleshire  *			accepted.
149*4201a95eSRic Aleshire  *
150*4201a95eSRic Aleshire  *	Returns	 0, success.
151*4201a95eSRic Aleshire  *		-1, failure
152*4201a95eSRic Aleshire  */
153*4201a95eSRic Aleshire int
hexstr_to_label(const char * s,m_label_t * l)154*4201a95eSRic Aleshire hexstr_to_label(const char *s, m_label_t *l)
155*4201a95eSRic Aleshire {
156*4201a95eSRic Aleshire 	uint_t	f = L_DEFAULT;
157*4201a95eSRic Aleshire 
158*4201a95eSRic Aleshire 	/* translate hex, admin_low and admin_high */
159*4201a95eSRic Aleshire 	if (IS_LOW(s)) {
160*4201a95eSRic Aleshire 		_LOW_LABEL(l, SUN_MAC_ID);
161*4201a95eSRic Aleshire 		return (0);
162*4201a95eSRic Aleshire 	} else if (IS_HIGH(s)) {
163*4201a95eSRic Aleshire 		_HIGH_LABEL(l, SUN_MAC_ID);
164*4201a95eSRic Aleshire 		return (0);
165*4201a95eSRic Aleshire 	} else if (IS_HEX(f, s)) {
166*4201a95eSRic Aleshire 		_LOW_LABEL(l, SUN_MAC_ID);
167*4201a95eSRic Aleshire 		if (htol(s, l) == 0)
168*4201a95eSRic Aleshire 			return (0);
169*4201a95eSRic Aleshire 	}
170*4201a95eSRic Aleshire 
171*4201a95eSRic Aleshire 	return (-1);
172*4201a95eSRic Aleshire }
173*4201a95eSRic Aleshire 
174*4201a95eSRic Aleshire #if !defined(_KERNEL)
17545916cd2Sjpk static int
convert_id(m_label_type_t t)17645916cd2Sjpk convert_id(m_label_type_t t)
17745916cd2Sjpk {
17845916cd2Sjpk 	switch (t) {
17945916cd2Sjpk 	case MAC_LABEL:
18045916cd2Sjpk 		return (SUN_MAC_ID);
18145916cd2Sjpk 	case USER_CLEAR:
18245916cd2Sjpk 		return (SUN_UCLR_ID);
18345916cd2Sjpk 	default:
18445916cd2Sjpk 		return (-1);
18545916cd2Sjpk 	}
18645916cd2Sjpk }
18745916cd2Sjpk 
18845916cd2Sjpk /*
18945916cd2Sjpk  * str_to_label -- parse a string into the requested label type.
19045916cd2Sjpk  *
19145916cd2Sjpk  *	Entry	s = string to parse.
19245916cd2Sjpk  *		l = label to create or modify.
19345916cd2Sjpk  *		t = label type (MAC_LABEL, USER_CLEAR).
19445916cd2Sjpk  *		f = flags
19545916cd2Sjpk  *			L_DEFAULT,
19645916cd2Sjpk  *			L_MODIFY_EXISTING, use the existing label as a basis for
19745916cd2Sjpk  *				the parse string.
19845916cd2Sjpk  *			L_NO_CORRECTION, s must be correct and full by the
19945916cd2Sjpk  *				label_encoding rules.
200ad355aa0Sgww  *			L_CHECK_AR, for non-hex s, MAC_LABEL, check the l_e AR
20145916cd2Sjpk  *
20245916cd2Sjpk  *	Exit	l = parsed label value.
20345916cd2Sjpk  *		e = index into string of error.
204dc8169d4Sgww  *		  = M_BAD_STRING (-3 L_BAD_LABEL) or could be zero,
205dc8169d4Sgww  *		    indicates entire string,
206dc8169d4Sgww  *	        e = M_BAD_LABEL (-2 L_BAD_CLASSIFICATION), problems with l
207ad355aa0Sgww  *		e = M_OUTSIDE_AR (-4 unrelated to L_BAD_* return values)
20845916cd2Sjpk  *
20945916cd2Sjpk  *	Returns	 0, success.
21045916cd2Sjpk  *		-1, failure
21145916cd2Sjpk  *			errno = ENOTSUP, the underlying label mechanism
21245916cd2Sjpk  *				does not support label parsing.
21345916cd2Sjpk  *				ENOMEM, unable to allocate memory for l.
21445916cd2Sjpk  *				EINVAL, invalid argument, l != NULL or
21545916cd2Sjpk  *				invalid label type for the underlying
21645916cd2Sjpk  *				label mechanism.
21745916cd2Sjpk  */
21845916cd2Sjpk #define	_M_GOOD_LABEL	-1	/* gfi L_GOOD_LABEL */
21945916cd2Sjpk int
str_to_label(const char * str,m_label_t ** l,const m_label_type_t t,uint_t f,int * e)22045916cd2Sjpk str_to_label(const char *str, m_label_t **l, const m_label_type_t t, uint_t f,
22145916cd2Sjpk     int *e)
22245916cd2Sjpk {
223dc8169d4Sgww 	char		*s = strdup(str);
224dc8169d4Sgww 	char		*st = s;
22545916cd2Sjpk 	char		*p;
22645916cd2Sjpk 	labeld_data_t	call;
22745916cd2Sjpk 	labeld_data_t	*callp = &call;
22845916cd2Sjpk 	size_t		bufsize = sizeof (labeld_data_t);
22945916cd2Sjpk 	size_t		datasize;
230dc8169d4Sgww 	int		err = M_BAD_LABEL;
23145916cd2Sjpk 	int		id = convert_id(t);
23245916cd2Sjpk 	boolean_t	new = B_FALSE;
233ad355aa0Sgww 	uint_t		lf = (f & ~L_CHECK_AR);	/* because L_DEFAULT == 0 */
23445916cd2Sjpk 
235dc8169d4Sgww 	if (st == NULL) {
236dc8169d4Sgww 		errno = ENOMEM;
237dc8169d4Sgww 		return (-1);
238dc8169d4Sgww 	}
23945916cd2Sjpk 	if (*l == NULL) {
24045916cd2Sjpk 		if ((*l = m_label_alloc(t)) == NULL) {
241dc8169d4Sgww 			free(st);
24245916cd2Sjpk 			return (-1);
24345916cd2Sjpk 		}
24445916cd2Sjpk 		if (id == -1) {
24545916cd2Sjpk 			goto badlabel;
24645916cd2Sjpk 		}
24745916cd2Sjpk 		_LOW_LABEL(*l, id);
24845916cd2Sjpk 		new = B_TRUE;
24945916cd2Sjpk 	} else if (_MTYPE(*l, SUN_INVALID_ID) &&
250ad355aa0Sgww 	    ((lf == L_NO_CORRECTION) || (lf == L_DEFAULT))) {
25145916cd2Sjpk 		_LOW_LABEL(*l, id);
25245916cd2Sjpk 		new = B_TRUE;
25345916cd2Sjpk 	} else if (!(_MTYPE(*l, SUN_MAC_ID) || _MTYPE(*l, SUN_CLR_ID))) {
25445916cd2Sjpk 		goto badlabel;
25545916cd2Sjpk 	}
25645916cd2Sjpk 
25745916cd2Sjpk 	if (new == B_FALSE && id == -1) {
25845916cd2Sjpk 		goto badlabel;
25945916cd2Sjpk 	}
26045916cd2Sjpk 
26145916cd2Sjpk 	/* get to the beginning of the string to parse */
26245916cd2Sjpk 	while (isspace(*s)) {
26345916cd2Sjpk 		s++;
26445916cd2Sjpk 	}
26545916cd2Sjpk 
26645916cd2Sjpk 	/* accept a leading '[' and trailing ']' for old times sake */
26745916cd2Sjpk 	if (*s == '[') {
268dc8169d4Sgww 		*s = ' ';
26945916cd2Sjpk 		s++;
27045916cd2Sjpk 		while (isspace(*s)) {
27145916cd2Sjpk 			s++;
27245916cd2Sjpk 		}
27345916cd2Sjpk 	}
27445916cd2Sjpk 	p = s;
27545916cd2Sjpk 	while (*p != '\0' && *p != ']') {
27645916cd2Sjpk 		p++;
27745916cd2Sjpk 	}
27845916cd2Sjpk 
27945916cd2Sjpk 	/* strip trailing spaces */
28045916cd2Sjpk 	while (p != s && isspace(*(p-1))) {
28145916cd2Sjpk 		--p;
28245916cd2Sjpk 	}
28345916cd2Sjpk 	*p = '\0';	/* end of string */
28445916cd2Sjpk 
28545916cd2Sjpk 	/* translate hex, admin_low and admin_high */
28645916cd2Sjpk 	id = _MGETTYPE(*l);
28745916cd2Sjpk 	if (IS_LOW(s)) {
28845916cd2Sjpk 		_LOW_LABEL(*l, id);
289dc8169d4Sgww 		goto goodlabel;
29045916cd2Sjpk 	} else if (IS_HIGH(s)) {
29145916cd2Sjpk 		_HIGH_LABEL(*l, id);
292dc8169d4Sgww 		goto goodlabel;
293ad355aa0Sgww 	} else if (IS_HEX(lf, s)) {
294dc8169d4Sgww 		if (htol(s, *l) != 0) {
295dc8169d4Sgww 			/* whole string in error */
296dc8169d4Sgww 			err = 0;
297dc8169d4Sgww 			goto badlabel;
298dc8169d4Sgww 		}
299dc8169d4Sgww 		goto goodlabel;
30045916cd2Sjpk 	}
30145916cd2Sjpk #define	slcall callp->param.acall.cargs.sl_arg
30245916cd2Sjpk #define	slret callp->param.aret.rvals.sl_ret
30345916cd2Sjpk 	/* now try label server */
30445916cd2Sjpk 
305e9d1e0cdSgww 	datasize = CALL_SIZE_STR(sl_call_t, strlen(st) + 1);
30645916cd2Sjpk 	if (datasize > bufsize) {
30745916cd2Sjpk 		if ((callp = malloc(datasize)) == NULL) {
308dc8169d4Sgww 			free(st);
30945916cd2Sjpk 			return (-1);
31045916cd2Sjpk 		}
31145916cd2Sjpk 		bufsize = datasize;
31245916cd2Sjpk 	}
31345916cd2Sjpk 	callp->callop = STOL;
31445916cd2Sjpk 	slcall.label = **l;
31545916cd2Sjpk 	slcall.flags = f;
31645916cd2Sjpk 	if (new)
31745916cd2Sjpk 		slcall.flags |= L_NEW_LABEL;
318dc8169d4Sgww 	(void) strcpy(slcall.string, st);
31945916cd2Sjpk 	/*
32045916cd2Sjpk 	 * callp->reterr = L_GOOD_LABEL (-1) == OK;
32145916cd2Sjpk 	 *		   L_BAD_CLASSIFICATION (-2) == bad input
32245916cd2Sjpk 	 *			classification: class
323dc8169d4Sgww 	 *		   L_BAD_LABEL (-3) == either string or input label bad
324ad355aa0Sgww 	 *		   M_OUTSIDE_AR (-4) == resultant MAC_LABEL is out
325ad355aa0Sgww 	 *			l_e accreditation range
32645916cd2Sjpk 	 *		   O'E == offset in string 0 == entire string.
32745916cd2Sjpk 	 */
32845916cd2Sjpk 	if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) {
32945916cd2Sjpk 
33045916cd2Sjpk 		err = callp->reterr;
33145916cd2Sjpk 		if (callp != &call) {
33245916cd2Sjpk 			/* free allocated buffer */
333dc8169d4Sgww 			free(callp);
33445916cd2Sjpk 		}
33545916cd2Sjpk 		switch (err) {
33645916cd2Sjpk 		case _M_GOOD_LABEL:	/* L_GOOD_LABEL */
33745916cd2Sjpk 			**l = slret.label;
338dc8169d4Sgww 			goto goodlabel;
33945916cd2Sjpk 		case M_BAD_LABEL:	/* L_BAD_CLASSIFICATION */
34045916cd2Sjpk 		case M_BAD_STRING:	/* L_BAD_LABEL */
34145916cd2Sjpk 		default:
342dc8169d4Sgww 			goto badlabel;
34345916cd2Sjpk 		}
34445916cd2Sjpk 	}
34545916cd2Sjpk 	switch (callp->reterr) {
34645916cd2Sjpk 	case NOSERVER:
34745916cd2Sjpk 		errno = ENOTSUP;
34845916cd2Sjpk 		break;
34945916cd2Sjpk 	default:
35045916cd2Sjpk 		errno = EINVAL;
35145916cd2Sjpk 		break;
35245916cd2Sjpk 	}
353dc8169d4Sgww 	free(st);
35445916cd2Sjpk 	return (-1);
35545916cd2Sjpk 
35645916cd2Sjpk badlabel:
35745916cd2Sjpk 	errno = EINVAL;
358dc8169d4Sgww 	free(st);
35945916cd2Sjpk 	if (e != NULL)
360dc8169d4Sgww 		*e = err;
36145916cd2Sjpk 	return (-1);
362dc8169d4Sgww 
363dc8169d4Sgww goodlabel:
364dc8169d4Sgww 	free(st);
365dc8169d4Sgww 	return (0);
36645916cd2Sjpk }
36745916cd2Sjpk #undef	slcall
36845916cd2Sjpk #undef	slret
36945916cd2Sjpk 
37045916cd2Sjpk /*
37145916cd2Sjpk  * m_label_alloc -- allocate a label structure
37245916cd2Sjpk  *
37345916cd2Sjpk  *	Entry	t = label type (MAC_LABEL, USER_CLEAR).
37445916cd2Sjpk  *
37545916cd2Sjpk  *	Exit	If error, NULL, errno set to ENOMEM
37645916cd2Sjpk  *		Otherwise, pointer to m_label_t memory
37745916cd2Sjpk  */
37845916cd2Sjpk 
37945916cd2Sjpk /* ARGUSED */
38045916cd2Sjpk m_label_t *
m_label_alloc(const m_label_type_t t)38145916cd2Sjpk m_label_alloc(const m_label_type_t t)
38245916cd2Sjpk {
38345916cd2Sjpk 	m_label_t *l;
38445916cd2Sjpk 
38545916cd2Sjpk 	switch (t) {
38645916cd2Sjpk 	case MAC_LABEL:
38745916cd2Sjpk 	case USER_CLEAR:
38845916cd2Sjpk 		if ((l = malloc(sizeof (_mac_label_impl_t))) == NULL) {
38945916cd2Sjpk 			return (NULL);
39045916cd2Sjpk 		}
39145916cd2Sjpk 		_MSETTYPE(l, SUN_INVALID_ID);
39245916cd2Sjpk 		break;
39345916cd2Sjpk 	default:
39445916cd2Sjpk 		errno = EINVAL;
39545916cd2Sjpk 		return (NULL);
39645916cd2Sjpk 	}
39745916cd2Sjpk 	return (l);
39845916cd2Sjpk }
39945916cd2Sjpk 
40045916cd2Sjpk /*
40145916cd2Sjpk  * m_label_dup -- make a duplicate copy of the given label.
40245916cd2Sjpk  *
40345916cd2Sjpk  *	Entry	l = label to duplicate.
40445916cd2Sjpk  *
40545916cd2Sjpk  *	Exit	d = duplicate copy of l.
40645916cd2Sjpk  *
40745916cd2Sjpk  *	Returns	 0, success
40845916cd2Sjpk  *		-1, if error.
40945916cd2Sjpk  *			errno = ENOTSUP, the underlying label mechanism
41045916cd2Sjpk  *				does not support label duplication.
41145916cd2Sjpk  *				ENOMEM, unable to allocate memory for d.
41245916cd2Sjpk  *				EINVAL, invalid argument, l == NULL or
41345916cd2Sjpk  *				invalid label type for the underlying
41445916cd2Sjpk  *				label mechanism.
41545916cd2Sjpk  */
41645916cd2Sjpk 
41745916cd2Sjpk int
m_label_dup(m_label_t ** d,const m_label_t * l)41845916cd2Sjpk m_label_dup(m_label_t **d, const m_label_t *l)
41945916cd2Sjpk {
42045916cd2Sjpk 	if (d == NULL || *d != NULL) {
42145916cd2Sjpk 		errno = EINVAL;
42245916cd2Sjpk 		return (-1);
42345916cd2Sjpk 	}
42445916cd2Sjpk 	if ((*d = malloc(sizeof (_mac_label_impl_t))) == NULL) {
42545916cd2Sjpk 		errno = ENOMEM;
42645916cd2Sjpk 		return (-1);
42745916cd2Sjpk 	}
42845916cd2Sjpk 
42945916cd2Sjpk 	(void) memcpy(*d, l, sizeof (_mac_label_impl_t));
43045916cd2Sjpk 	return (0);
43145916cd2Sjpk }
43245916cd2Sjpk 
43345916cd2Sjpk /*
43445916cd2Sjpk  * m_label_free -- free label structure
43545916cd2Sjpk  *
43645916cd2Sjpk  *	Entry	l = label to free.
43745916cd2Sjpk  *
43845916cd2Sjpk  *	Exit	memory freed.
43945916cd2Sjpk  *
44045916cd2Sjpk  */
44145916cd2Sjpk 
44245916cd2Sjpk void
m_label_free(m_label_t * l)44345916cd2Sjpk m_label_free(m_label_t *l)
44445916cd2Sjpk {
44545916cd2Sjpk 	if (l)
44645916cd2Sjpk 		free(l);
44745916cd2Sjpk }
448*4201a95eSRic Aleshire #endif /* !defined(_KERNEL) */
449