OpenSolaris_b135/cmd/auditreduce/token.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.
 */


/*
 * Token processing for auditreduce.
 */

#include <locale.h>
#include <sys/zone.h>
#include "auditr.h"
#include "toktable.h"

extern int	re_exec2(char *);

static void	anchor_path(char *path);
static char	*collapse_path(char *s);
static void	get_string(adr_t *adr, char **p);
static int	ipc_type_match(int flag, char type);
static void	skip_string(adr_t *adr);
static int	xgeneric(adr_t *adr);

#if	AUDIT_REC
void
print_id(int id)
{
	char *suffix;

	if ((id < 0) || (id > MAXTOKEN) ||
	    (tokentable[id].func == NOFUNC)) {
		(void) fprintf(stderr,
		    "token_processing: token %d not found\n", id);
		return;
	}

	switch (id) {
	case AUT_NEWGROUPS:
		suffix = "_new";
		break;
	case AUT_ATTR32:
		suffix = "32";
		break;
	case AUT_ARG64:
	case AUT_RETURN64:
	case AUT_ATTR64:
	case AUT_HEADER64:
	case AUT_SUBJECT64:
	case AUT_PROCESS64:
	case AUT_OTHER_FILE64:
		suffix = "64";
		break;
	case AUT_SOCKET_EX:
	case AUT_IN_ADDR_EX:
		suffix = "_ex";
		break;
	case AUT_HEADER32_EX:
	case AUT_SUBJECT32_EX:
	case AUT_PROCESS32_EX:
		suffix = "32_ex";
		break;
	case AUT_HEADER64_EX:
	case AUT_SUBJECT64_EX:
	case AUT_PROCESS64_EX:
		suffix = "64_ex";
		break;
	default:
		suffix = "";
		break;
	}
	(void) fprintf(stderr, "token_processing: %s%s\n",
	    tokentable[id].t_name, suffix);
}
#endif	/* AUDIT_REC */

/*
 * Process a token in a record to determine whether the record is interesting.
 */

int
token_processing(adr_t *adr, int tokenid)
{
	if ((tokenid > 0) && (tokenid <= MAXTOKEN) &&
	    (tokentable[tokenid].func != NOFUNC)) {
#if	AUDIT_REC
		print_id(tokenid);
#endif	/* AUDIT_REC */
		return ((*tokentable[tokenid].func)(adr));
	}

	/* here if token id is not in table */
	return (-2);
}


/* There should not be any file or header tokens in the middle of a record */

/* ARGSUSED */
int
file_token(adr_t *adr)
{
	return (-2);
}

/* ARGSUSED */
int
file64_token(adr_t *adr)
{
	return (-2);
}

/* ARGSUSED */
int
header_token(adr_t *adr)
{
	return (-2);
}

/* ARGSUSED */
int
header32_ex_token(adr_t *adr)
{
	return (-2);
}

/* ARGSUSED */
int
header64_ex_token(adr_t *adr)
{
	return (-2);
}

/* ARGSUSED */
int
header64_token(adr_t *adr)
{
	return (-2);
}


/*
 * ======================================================
 *  The following token processing routines return
 *  -1: if the record is not interesting
 *  -2: if an error is found
 * ======================================================
 */

int
trailer_token(adr_t *adr)
{
	short	magic_number;
	uint32_t bytes;

	adrm_u_short(adr, (ushort_t *)&magic_number, 1);
	if (magic_number != AUT_TRAILER_MAGIC) {
		(void) fprintf(stderr, "%s\n",
		    gettext("auditreduce: Bad trailer token"));
		return (-2);
	}
	adrm_u_int32(adr, &bytes, 1);

	return (-1);
}


/*
 * Format of arbitrary data token:
 *	arbitrary data token id	adr char
 * 	how to print		adr_char
 *	basic unit		adr_char
 *	unit count		adr_char, specifying number of units of
 *	data items		depends on basic unit
 *
 */
int
arbitrary_data_token(adr_t *adr)
{
	int	i;
	char	c1;
	short	c2;
	int32_t	c3;
	int64_t c4;
	char	how_to_print, basic_unit, unit_count;

	/* get how_to_print, basic_unit, and unit_count */
	adrm_char(adr, &how_to_print, 1);
	adrm_char(adr, &basic_unit, 1);
	adrm_char(adr, &unit_count, 1);
	for (i = 0; i < unit_count; i++) {
		switch (basic_unit) {
			/* case AUR_BYTE: has same value as AUR_CHAR */
		case AUR_CHAR:
			adrm_char(adr, &c1, 1);
			break;
		case AUR_SHORT:
			adrm_short(adr, &c2, 1);
			break;
		case AUR_INT32:
			adrm_int32(adr, (int32_t *)&c3, 1);
			break;
		case AUR_INT64:
			adrm_int64(adr, (int64_t *)&c4, 1);
			break;
		default:
			return (-2);
			break;
		}
	}
	return (-1);
}


/*
 * Format of opaque token:
 *	opaque token id		adr_char
 *	size			adr_short
 *	data			adr_char, size times
 *
 */
int
opaque_token(adr_t *adr)
{
	skip_string(adr);
	return (-1);
}



/*
 * Format of return32 value token:
 * 	return value token id	adr_char
 *	error number		adr_char
 *	return value		adr_u_int32
 *
 */
int
return_value32_token(adr_t *adr)
{
	char		errnum;
	uint32_t	value;

	adrm_char(adr, &errnum, 1);
	adrm_u_int32(adr, &value, 1);
	if ((flags & M_SORF) &&
	    ((global_class & mask.am_success) && (errnum == 0)) ||
	    ((global_class & mask.am_failure) && (errnum != 0))) {
		checkflags |= M_SORF;
	}
	return (-1);
}

/*
 * Format of return64 value token:
 * 	return value token id	adr_char
 *	error number		adr_char
 *	return value		adr_u_int64
 *
 */
int
return_value64_token(adr_t *adr)
{
	char		errnum;
	uint64_t	value;

	adrm_char(adr, &errnum, 1);
	adrm_u_int64(adr, &value, 1);
	if ((flags & M_SORF) &&
	    ((global_class & mask.am_success) && (errnum == 0)) ||
	    ((global_class & mask.am_failure) && (errnum != 0))) {
		checkflags |= M_SORF;
	}
	return (-1);
}


/*
 * Format of sequence token:
 *	sequence token id	adr_char
 *	audit_count		int32_t
 *
 */
int
sequence_token(adr_t *adr)
{
	int32_t	audit_count;

	adrm_int32(adr, &audit_count, 1);
	return (-1);
}


/*
 * Format of text token:
 *	text token id		adr_char
 * 	text			adr_string
 *
 */
int
text_token(adr_t *adr)
{
	skip_string(adr);
	return (-1);
}


/*
 * Format of ip_addr token:
 *	ip token id	adr_char
 *	address		adr_int32
 *
 */
int
ip_addr_token(adr_t *adr)
{
	int32_t	address;

	adrm_char(adr, (char *)&address, 4);

	return (-1);
}

/*
 * Format of ip_addr_ex token:
 *	ip token id	adr_char
 *	ip type		adr_int32
 *	address		4*adr_int32
 *
 */
int
ip_addr_ex_token(adr_t *adr)
{
	int32_t	address[4];
	int32_t type;

	adrm_int32(adr, (int32_t *)&type, 1);
	adrm_int32(adr, (int32_t *)&address, 4);

	return (-1);
}

/*
 * Format of ip token:
 *	ip header token id	adr_char
 *	version			adr_char
 *	type of service		adr_char
 *	length			adr_short
 *	id			adr_u_short
 *	offset			adr_u_short
 *	ttl			adr_char
 *	protocol		adr_char
 *	checksum		adr_u_short
 *	source address		adr_int32
 *	destination address	adr_int32
 *
 */
int
ip_token(adr_t *adr)
{
	char	version;
	char	type;
	short	len;
	unsigned short	id, offset, checksum;
	char	ttl, protocol;
	int32_t	src, dest;

	adrm_char(adr, &version, 1);
	adrm_char(adr, &type, 1);
	adrm_short(adr, &len, 1);
	adrm_u_short(adr, &id, 1);
	adrm_u_short(adr, &offset, 1);
	adrm_char(adr, &ttl, 1);
	adrm_char(adr, &protocol, 1);
	adrm_u_short(adr, &checksum, 1);
	adrm_char(adr, (char *)&src, 4);
	adrm_char(adr, (char *)&dest, 4);

	return (-1);
}


/*
 * Format of iport token:
 *	ip port address token id	adr_char
 *	port address			adr_short
 *
 */
int
iport_token(adr_t *adr)
{
	short	address;

	adrm_short(adr, &address, 1);

	return (-1);
}


/*
 * Format of groups token:
 *	group token id		adr_char
 *	group list		adr_int32, 16 times
 *
 */
int
group_token(adr_t *adr)
{
	int	gid[16];
	int	i;
	int	flag = 0;

	for (i = 0; i < 16; i++) {
		adrm_int32(adr, (int32_t *)&gid[i], 1);
		if (flags & M_GROUPR) {
			if ((unsigned short)m_groupr == gid[i])
				flag = 1;
		}
	}

	if (flags & M_GROUPR) {
		if (flag)
			checkflags |= M_GROUPR;
	}
	return (-1);
}

/*
 * Format of newgroups token:
 *	group token id		adr_char
 *	number of groups	adr_short
 *	group list		adr_int32, "number" times
 *
 */
int
newgroup_token(adr_t *adr)
{
	gid_t	gid;
	int	i;
	short int   number;

	adrm_short(adr, &number, 1);

	for (i = 0; i < number; i++) {
		adrm_int32(adr, (int32_t *)&gid, 1);
		if (flags & M_GROUPR) {
			if (m_groupr == gid)
				checkflags |= M_GROUPR;
		}
	}

	return (-1);
}

/*
 * Format of argument32 token:
 *	argument token id	adr_char
 *	argument number		adr_char
 *	argument value		adr_int32
 *	argument description	adr_string
 *
 */
int
argument32_token(adr_t *adr)
{
	char	arg_num;
	int32_t	arg_val;

	adrm_char(adr, &arg_num, 1);
	adrm_int32(adr, &arg_val, 1);
	skip_string(adr);

	return (-1);
}

/*
 * Format of argument64 token:
 *	argument token id	adr_char
 *	argument number		adr_char
 *	argument value		adr_int64
 *	argument description	adr_string
 *
 */
int
argument64_token(adr_t *adr)
{
	char	arg_num;
	int64_t	arg_val;

	adrm_char(adr, &arg_num, 1);
	adrm_int64(adr, &arg_val, 1);
	skip_string(adr);

	return (-1);
}

/*
 * Format of acl token:
 *	acl token id		adr_char
 *	acl type		adr_u_int32
 *	acl value		adr_u_int32 (depends on type)
 *	file mode		adr_u_int (in octal)
 */
int
acl_token(adr_t *adr)
{

	int32_t	id;
	int32_t	mode;
	int32_t	type;

	adrm_int32(adr, &type, 1);
	adrm_int32(adr, &id, 1);
	adrm_int32(adr, &mode, 1);

	return (-1);
}

/*
 * Format of ace token:
 *	ace token id		adr_char
 *	ace who			adr_u_int32 (uid/gid)
 *	access mask		adr_u_int32
 *	ace flags		adr_u_int16
 *	ace type		adr_u_int16
 */
int
ace_token(adr_t *adr)
{
	uid_t		who;
	uint32_t	access_mask;
	uint16_t	flags, type;

	adrm_uid(adr, &who, 1);
	adrm_u_int32(adr, &access_mask, 1);
	adrm_u_short(adr, &flags, 1);
	adrm_u_short(adr, &type, 1);

	return (-1);
}

/*
 * Format of attribute token: (old pre SunOS 5.7 format)
 *	attribute token id	adr_char
 * 	mode			adr_int32 (printed in octal)
 *	uid			adr_int32
 *	gid			adr_int32
 *	file system id		adr_int32
 *	node id			adr_int32
 *	device			adr_int32
 *
 */
int
attribute_token(adr_t *adr)
{
	int32_t	dev;
	int32_t	file_sysid;
	int32_t	gid;
	int32_t	mode;
	int32_t	nodeid;
	int32_t	uid;

	adrm_int32(adr, &mode, 1);
	adrm_int32(adr, &uid, 1);
	adrm_int32(adr, &gid, 1);
	adrm_int32(adr, &file_sysid, 1);
	adrm_int32(adr, &nodeid, 1);
	adrm_int32(adr, &dev, 1);

	if (!new_mode && (flags & M_USERE)) {
		if (m_usere == uid)
			checkflags |= M_USERE;
	}
	if (!new_mode && (flags & M_GROUPE)) {
		if (m_groupe == gid)
			checkflags |= M_GROUPE;
	}

	if (flags & M_OBJECT) {
		if ((obj_flag & OBJ_FGROUP) &&
		    (obj_group == gid))
			checkflags |= M_OBJECT;
		else if ((obj_flag & OBJ_FOWNER) &&
		    (obj_owner == uid))
			checkflags |= M_OBJECT;
	}
	return (-1);
}

/*
 * Format of attribute32 token:
 *	attribute token id	adr_char
 * 	mode			adr_int32 (printed in octal)
 *	uid			adr_int32
 *	gid			adr_int32
 *	file system id		adr_int32
 *	node id			adr_int64
 *	device			adr_int32
 *
 */
int
attribute32_token(adr_t *adr)
{
	int32_t	dev;
	int32_t	file_sysid;
	int32_t	gid;
	int32_t	mode;
	int64_t	nodeid;
	int32_t	uid;

	adrm_int32(adr, &mode, 1);
	adrm_int32(adr, &uid, 1);
	adrm_int32(adr, &gid, 1);
	adrm_int32(adr, &file_sysid, 1);
	adrm_int64(adr, &nodeid, 1);
	adrm_int32(adr, &dev, 1);

	if (!new_mode && (flags & M_USERE)) {
		if (m_usere == uid)
			checkflags |= M_USERE;
	}
	if (!new_mode && (flags & M_GROUPE)) {
		if (m_groupe == gid)
			checkflags |= M_GROUPE;
	}

	if (flags & M_OBJECT) {
		if ((obj_flag & OBJ_FGROUP) &&
		    (obj_group == gid))
			checkflags |= M_OBJECT;
		else if ((obj_flag & OBJ_FOWNER) &&
		    (obj_owner == uid))
			checkflags |= M_OBJECT;
	}
	return (-1);
}

/*
 * Format of attribute64 token:
 *	attribute token id	adr_char
 * 	mode			adr_int32 (printed in octal)
 *	uid			adr_int32
 *	gid			adr_int32
 *	file system id		adr_int32
 *	node id			adr_int64
 *	device			adr_int64
 *
 */
int
attribute64_token(adr_t *adr)
{
	int64_t	dev;
	int32_t	file_sysid;
	int32_t	gid;
	int32_t	mode;
	int64_t	nodeid;
	int32_t	uid;

	adrm_int32(adr, &mode, 1);
	adrm_int32(adr, &uid, 1);
	adrm_int32(adr, &gid, 1);
	adrm_int32(adr, &file_sysid, 1);
	adrm_int64(adr, &nodeid, 1);
	adrm_int64(adr, &dev, 1);

	if (!new_mode && (flags & M_USERE)) {
		if (m_usere == uid)
			checkflags |= M_USERE;
	}
	if (!new_mode && (flags & M_GROUPE)) {
		if (m_groupe == gid)
			checkflags |= M_GROUPE;
	}

	if (flags & M_OBJECT) {
		if ((obj_flag & OBJ_FGROUP) &&
		    (obj_group == gid))
			checkflags |= M_OBJECT;
		else if ((obj_flag & OBJ_FOWNER) &&
		    (obj_owner == uid))
			checkflags |= M_OBJECT;
	}
	return (-1);
}


/*
 * Format of command token:
 *	attribute token id	adr_char
 *	argc			adr_short
 *	argv len		adr_short	variable amount of argv len
 *	argv text		argv len	and text
 *	.
 *	.
 *	.
 *	envp count		adr_short	variable amount of envp len
 *	envp len		adr_short	and text
 *	envp text		envp		len
 *	.
 *	.
 *	.
 *
 */
int
cmd_token(adr_t *adr)
{
	short	cnt;
	short	i;

	adrm_short(adr, &cnt, 1);

	for (i = 0; i < cnt; i++)
		skip_string(adr);

	adrm_short(adr, &cnt, 1);

	for (i = 0; i < cnt; i++)
		skip_string(adr);

	return (-1);
}


/*
 * Format of exit token:
 *	attribute token id	adr_char
 *	return value		adr_int32
 *	errno			adr_int32
 *
 */
int
exit_token(adr_t *adr)
{
	int32_t	retval;
	int32_t	errno;

	adrm_int32(adr, &retval, 1);
	adrm_int32(adr, &errno, 1);
	return (-1);
}

/*
 * Format of strings array token:
 *	token id		adr_char
 *	count value		adr_int32
 *	strings			null terminated strings
 */
static int
strings_common_token(adr_t *adr)
{
	int count, i;
	char c;

	adrm_int32(adr, (int32_t *)&count, 1);
	for (i = 1; i <= count; i++) {
		adrm_char(adr, &c, 1);
		while (c != (char)0)
			adrm_char(adr, &c, 1);
	}
	/* no dump option here, since we will have variable length fields */
	return (-1);
}

int
path_attr_token(adr_t *adr)
{
	return (strings_common_token(adr));
}

int
exec_args_token(adr_t *adr)
{
	return (strings_common_token(adr));
}

int
exec_env_token(adr_t *adr)
{
	return (strings_common_token(adr));
}

/*
 * Format of liaison token:
 */
int
liaison_token(adr_t *adr)
{
	int32_t	li;

	adrm_int32(adr, &li, 1);
	return (-1);
}


/*
 * Format of path token:
 *	path				adr_string
 */
int
path_token(adr_t *adr)
{
	if ((flags & M_OBJECT) && (obj_flag == OBJ_PATH)) {
		char *path;

		get_string(adr, &path);
		if (path[0] != '/')
			/*
			 * anchor the path. user apps may not do it.
			 */
			anchor_path(path);
		/*
		 * match against the collapsed path. that is what user sees.
		 */
		if (re_exec2(collapse_path(path)) == 1)
			checkflags |= M_OBJECT;
		free(path);
	} else {
		skip_string(adr);
	}
	return (-1);
}


/*
 * Format of System V IPC permission token:
 *	System V IPC permission token id	adr_char
 * 	uid					adr_int32
 *	gid					adr_int32
 *	cuid					adr_int32
 *	cgid					adr_int32
 *	mode					adr_int32
 *	seq					adr_int32
 *	key					adr_int32
 */
int
s5_IPC_perm_token(adr_t *adr)
{
	int32_t	uid, gid, cuid, cgid, mode, seq;
	int32_t	key;

	adrm_int32(adr, &uid, 1);
	adrm_int32(adr, &gid, 1);
	adrm_int32(adr, &cuid, 1);
	adrm_int32(adr, &cgid, 1);
	adrm_int32(adr, &mode, 1);
	adrm_int32(adr, &seq, 1);
	adrm_int32(adr, &key, 1);

	if (!new_mode && (flags & M_USERE)) {
		if (m_usere == uid)
			checkflags |= M_USERE;
	}

	if (!new_mode && (flags & M_USERE)) {
		if (m_usere == cuid)
			checkflags |= M_USERE;
	}

	if (!new_mode && (flags & M_GROUPR)) {
		if (m_groupr == gid)
			checkflags |= M_GROUPR;
	}

	if (!new_mode && (flags & M_GROUPR)) {
		if (m_groupr == cgid)
			checkflags |= M_GROUPR;
	}

	if ((flags & M_OBJECT) &&
	    ((obj_owner == uid) ||
	    (obj_owner == cuid) ||
	    (obj_group == gid) ||
	    (obj_group == cgid))) {

		switch (obj_flag) {
		case OBJ_MSGGROUP:
		case OBJ_MSGOWNER:
			if (ipc_type_match(OBJ_MSG, ipc_type))
				checkflags |= M_OBJECT;
			break;
		case OBJ_SEMGROUP:
		case OBJ_SEMOWNER:
			if (ipc_type_match(OBJ_SEM, ipc_type))
				checkflags |= M_OBJECT;
			break;
		case OBJ_SHMGROUP:
		case OBJ_SHMOWNER:
			if (ipc_type_match(OBJ_SHM, ipc_type))
				checkflags |= M_OBJECT;
			break;
		}
	}
	return (-1);
}


/*
 * Format of process32 token:
 *	process token id	adr_char
 *	auid			adr_int32
 *	euid			adr_int32
 *	egid 			adr_int32
 * 	ruid			adr_int32
 *	rgid			adr_int32
 * 	pid			adr_int32
 * 	sid			adr_int32
 * 	termid			adr_int32*2
 *
 */
int
process32_token(adr_t *adr)
{
	int32_t	auid, euid, egid, ruid, rgid, pid;
	int32_t	sid;
	int32_t port, machine;

	adrm_int32(adr, &auid, 1);
	adrm_int32(adr, &euid, 1);
	adrm_int32(adr, &egid, 1);
	adrm_int32(adr, &ruid, 1);
	adrm_int32(adr, &rgid, 1);
	adrm_int32(adr, &pid, 1);
	adrm_int32(adr, &sid, 1);
	adrm_int32(adr, &port, 1);
	adrm_int32(adr, &machine, 1);

	if (!new_mode && (flags & M_USERA)) {
		if (m_usera == auid)
			checkflags |= M_USERA;
	}
	if (!new_mode && (flags & M_USERE)) {
		if (m_usere == euid)
			checkflags |= M_USERE;
	}
	if (!new_mode && (flags & M_USERR)) {
		if (m_userr == ruid)
			checkflags |= M_USERR;
	}
	if (!new_mode && (flags & M_GROUPR)) {
		if (m_groupr == rgid)
			checkflags |= M_GROUPR;
	}
	if (!new_mode && (flags & M_GROUPE)) {
		if (m_groupe == egid)
			checkflags |= M_GROUPE;
	}

	if (flags & M_OBJECT) {
		if ((obj_flag & OBJ_PROC) &&
		    (obj_id == pid)) {
			checkflags |= M_OBJECT;
		} else if ((obj_flag & OBJ_PGROUP) &&
		    ((obj_group == egid) ||
		    (obj_group == rgid))) {
			checkflags |= M_OBJECT;
		} else if ((obj_flag & OBJ_POWNER) &&
		    ((obj_owner == euid) ||
		    (obj_group == ruid))) {
			checkflags |= M_OBJECT;
		}
	}
	return (-1);
}

/*
 * Format of process32 token:
 *	process token id	adr_char
 *	auid			adr_int32
 *	euid			adr_int32
 *	egid 			adr_int32
 * 	ruid			adr_int32
 *	rgid			adr_int32
 * 	pid			adr_int32
 * 	sid			adr_int32
 * 	termid			adr_int32*6
 *
 */
int
process32_ex_token(adr_t *adr)
{
	int32_t	auid, euid, egid, ruid, rgid, pid;
	int32_t	sid;
	int32_t port, type, addr[4];

	adrm_int32(adr, &auid, 1);
	adrm_int32(adr, &euid, 1);
	adrm_int32(adr, &egid, 1);
	adrm_int32(adr, &ruid, 1);
	adrm_int32(adr, &rgid, 1);
	adrm_int32(adr, &pid, 1);
	adrm_int32(adr, &sid, 1);
	adrm_int32(adr, &port, 1);
	adrm_int32(adr, &type, 1);
	adrm_int32(adr, &addr[0], 4);

	if (!new_mode && (flags & M_USERA)) {
		if (m_usera == auid)
			checkflags = checkflags | M_USERA;
	}
	if (!new_mode && (flags & M_USERE)) {
		if (m_usere == euid)
			checkflags = checkflags | M_USERE;
	}
	if (!new_mode && (flags & M_USERR)) {
		if (m_userr == ruid)
			checkflags = checkflags | M_USERR;
	}
	if (!new_mode && (flags & M_GROUPR)) {
		if (m_groupr == egid)
			checkflags = checkflags | M_GROUPR;
	}
	if (!new_mode && (flags & M_GROUPE)) {
		if (m_groupe == egid)
			checkflags = checkflags | M_GROUPE;
	}

	if (flags & M_OBJECT) {
		if ((obj_flag & OBJ_PROC) &&
		    (obj_id == pid)) {
			checkflags = checkflags | M_OBJECT;
		} else if ((obj_flag & OBJ_PGROUP) &&
		    ((obj_group == egid) ||
		    (obj_group == rgid))) {
			checkflags = checkflags | M_OBJECT;
		} else if ((obj_flag & OBJ_POWNER) &&
		    ((obj_owner == euid) ||
		    (obj_group == ruid))) {
			checkflags = checkflags | M_OBJECT;
		}
	}
	return (-1);
}

/*
 * Format of process64 token:
 *	process token id	adr_char
 *	auid			adr_int32
 *	euid			adr_int32
 *	egid 			adr_int32
 * 	ruid			adr_int32
 *	rgid			adr_int32
 * 	pid			adr_int32
 * 	sid			adr_int32
 * 	termid			adr_int64+adr_int32
 *
 */
int
process64_token(adr_t *adr)
{
	int32_t	auid, euid, egid, ruid, rgid, pid;
	int32_t	sid;
	int64_t port;
	int32_t machine;

	adrm_int32(adr, &auid, 1);
	adrm_int32(adr, &euid, 1);
	adrm_int32(adr, &egid, 1);
	adrm_int32(adr, &ruid, 1);
	adrm_int32(adr, &rgid, 1);
	adrm_int32(adr, &pid, 1);
	adrm_int32(adr, &sid, 1);
	adrm_int64(adr, &port, 1);
	adrm_int32(adr, &machine, 1);

	if (!new_mode && (flags & M_USERA)) {
		if (m_usera == auid)
			checkflags |= M_USERA;
	}
	if (!new_mode && (flags & M_USERE)) {
		if (m_usere == euid)
			checkflags |= M_USERE;
	}
	if (!new_mode && (flags & M_USERR)) {
		if (m_userr == ruid)
			checkflags |= M_USERR;
	}
	if (!new_mode && (flags & M_GROUPR)) {
		if (m_groupr == rgid)
			checkflags |= M_GROUPR;
	}
	if (!new_mode && (flags & M_GROUPE)) {
		if (m_groupe == egid)
			checkflags |= M_GROUPE;
	}

	if (flags & M_OBJECT) {
		if ((obj_flag & OBJ_PROC) &&
		    (obj_id == pid)) {
			checkflags |= M_OBJECT;
		} else if ((obj_flag & OBJ_PGROUP) &&
		    ((obj_group == egid) ||
		    (obj_group == rgid))) {
			checkflags |= M_OBJECT;
		} else if ((obj_flag & OBJ_POWNER) &&
		    ((obj_owner == euid) ||
		    (obj_group == ruid))) {
			checkflags |= M_OBJECT;
		}
	}
	return (-1);
}

/*
 * Format of process64 token:
 *	process token id	adr_char
 *	auid			adr_int32
 *	euid			adr_int32
 *	egid 			adr_int32
 * 	ruid			adr_int32
 *	rgid			adr_int32
 * 	pid			adr_int32
 * 	sid			adr_int32
 * 	termid			adr_int64+5*adr_int32
 *
 */
int
process64_ex_token(adr_t *adr)
{
	int32_t	auid, euid, egid, ruid, rgid, pid;
	int32_t	sid;
	int64_t port;
	int32_t type, addr[4];

	adrm_int32(adr, &auid, 1);
	adrm_int32(adr, &euid, 1);
	adrm_int32(adr, &egid, 1);
	adrm_int32(adr, &ruid, 1);
	adrm_int32(adr, &rgid, 1);
	adrm_int32(adr, &pid, 1);
	adrm_int32(adr, &sid, 1);
	adrm_int64(adr, &port, 1);
	adrm_int32(adr, &type, 1);
	adrm_int32(adr, &addr[0], 4);

	if (!new_mode && (flags & M_USERA)) {
		if (m_usera == auid)
			checkflags = checkflags | M_USERA;
	}
	if (!new_mode && (flags & M_USERE)) {
		if (m_usere == euid)
			checkflags = checkflags | M_USERE;
	}
	if (!new_mode && (flags & M_USERR)) {
		if (m_userr == ruid)
			checkflags = checkflags | M_USERR;
	}
	if (!new_mode && (flags & M_GROUPR)) {
		if (m_groupr == egid)
			checkflags = checkflags | M_GROUPR;
	}
	if (!new_mode && (flags & M_GROUPE)) {
		if (m_groupe == egid)
			checkflags = checkflags | M_GROUPE;
	}

	if (flags & M_OBJECT) {
		if ((obj_flag & OBJ_PROC) &&
		    (obj_id == pid)) {
			checkflags = checkflags | M_OBJECT;
		} else if ((obj_flag & OBJ_PGROUP) &&
		    ((obj_group == egid) ||
		    (obj_group == rgid))) {
			checkflags = checkflags | M_OBJECT;
		} else if ((obj_flag & OBJ_POWNER) &&
		    ((obj_owner == euid) ||
		    (obj_group == ruid))) {
			checkflags = checkflags | M_OBJECT;
		}
	}
	return (-1);
}

/*
 * Format of System V IPC token:
 *	System V IPC token id	adr_char
 *	object id		adr_int32
 *
 */
int
s5_IPC_token(adr_t *adr)
{
	int32_t	ipc_id;

	adrm_char(adr, &ipc_type, 1);	/* Global */
	adrm_int32(adr, &ipc_id, 1);

	if ((flags & M_OBJECT) &&
	    ipc_type_match(obj_flag, ipc_type) &&
	    (obj_id == ipc_id))
		checkflags |= M_OBJECT;

	return (-1);
}


/*
 * Format of socket token:
 *	socket_type		adrm_short
 *	remote_port		adrm_short
 *	remote_inaddr		adrm_int32
 *
 */
int
socket_token(adr_t *adr)
{
	short	socket_type;
	short	remote_port;
	int32_t	remote_inaddr;

	adrm_short(adr, &socket_type, 1);
	adrm_short(adr, &remote_port, 1);
	adrm_char(adr, (char *)&remote_inaddr, 4);

	if ((flags & M_OBJECT) && (obj_flag == OBJ_SOCK)) {
		if (socket_flag == SOCKFLG_MACHINE) {
			if (remote_inaddr == obj_id)
				checkflags |= M_OBJECT;
		} else if (socket_flag == SOCKFLG_PORT) {
			if (remote_port == obj_id)
				checkflags |= M_OBJECT;
		}
	}
	return (-1);
}


/*
 * Format of socket token:
 *	socket_type		adrm_short
 *	remote_port		adrm_short
 *	remote_inaddr		adrm_int32
 *
 */
int
socket_ex_token(adr_t *adr)
{
	short	socket_domain;
	short	socket_type;
	short	ip_size;
	short	local_port;
	int32_t	local_inaddr[4];
	short	remote_port;
	int32_t	remote_inaddr[4];

	adrm_short(adr, &socket_domain, 1);
	adrm_short(adr, &socket_type, 1);
	adrm_short(adr, &ip_size, 1);

	/* validate ip size */
	if ((ip_size != AU_IPv6) && (ip_size != AU_IPv4))
		return (0);

	adrm_short(adr, &local_port, 1);
	adrm_char(adr, (char *)local_inaddr, ip_size);

	adrm_short(adr, &remote_port, 1);
	adrm_char(adr, (char *)remote_inaddr, ip_size);

	/* if IP type mis-match, then nothing to do */
	if (ip_size != ip_type)
		return (-1);

	if ((flags & M_OBJECT) && (obj_flag == OBJ_SOCK)) {
		if (socket_flag == SOCKFLG_MACHINE) {
			if (ip_type == AU_IPv4) {
				if ((local_inaddr[0] == obj_id) ||
				    (remote_inaddr[0] == obj_id))
					checkflags |= M_OBJECT;
			} else {
				if (((local_inaddr[0] == ip_ipv6[0]) &&
				    (local_inaddr[1] == ip_ipv6[1]) &&
				    (local_inaddr[2] == ip_ipv6[2]) &&
				    (local_inaddr[3] == ip_ipv6[3])) ||
				    ((remote_inaddr[0] == ip_ipv6[0]) &&
				    (remote_inaddr[1] == ip_ipv6[1]) &&
				    (remote_inaddr[2] == ip_ipv6[2]) &&
				    (remote_inaddr[3] == ip_ipv6[3])))
					checkflags |= M_OBJECT;
			}
		} else if (socket_flag == SOCKFLG_PORT) {
			if ((local_port == obj_id) || (remote_port == obj_id))
				checkflags |= M_OBJECT;
		}
	}
	return (-1);
}


/*
 * Format of subject32 token:
 *	subject token id	adr_char
 *	auid			adr_int32
 *	euid			adr_int32
 *	egid 			adr_int32
 * 	ruid			adr_int32
 *	rgid			adr_int32
 * 	pid			adr_int32
 * 	sid			adr_int32
 * 	termid			adr_int32*2
 *
 */
int
subject32_token(adr_t *adr)
{
	int32_t	auid, euid, egid, ruid, rgid, pid;
	int32_t	sid;
	int32_t port, machine;

	adrm_int32(adr, &auid, 1);
	adrm_int32(adr, &euid, 1);
	adrm_int32(adr, &egid, 1);
	adrm_int32(adr, &ruid, 1);
	adrm_int32(adr, &rgid, 1);
	adrm_int32(adr, &pid, 1);
	adrm_int32(adr, &sid, 1);
	adrm_int32(adr, &port, 1);
	adrm_int32(adr, &machine, 1);

	if (flags & M_SUBJECT) {
		if (subj_id == pid)
			checkflags |= M_SUBJECT;
	}
	if (flags & M_USERA) {
		if (m_usera == auid)
			checkflags |= M_USERA;
	}
	if (flags & M_USERE) {
		if (m_usere == euid)
			checkflags |= M_USERE;
	}
	if (flags & M_USERR) {
		if (m_userr == ruid)
			checkflags |= M_USERR;
	}
	if (flags & M_GROUPR) {
		if (m_groupr == rgid)
			checkflags |= M_GROUPR;
	}
	if (flags & M_GROUPE) {
		if (m_groupe == egid)
			checkflags |= M_GROUPE;
	}
	if (flags & M_SID) {
		if (m_sid == (au_asid_t)sid)
			checkflags |= M_SID;
	}
	return (-1);
}

/*
 * Format of subject32_ex token:
 *	subject token id	adr_char
 *	auid			adr_int32
 *	euid			adr_int32
 *	egid 			adr_int32
 * 	ruid			adr_int32
 *	rgid			adr_int32
 * 	pid			adr_int32
 * 	sid			adr_int32
 * 	termid_addr		adr_int32*6
 *
 */
int
subject32_ex_token(adr_t *adr)
{
	int32_t	auid, euid, egid, ruid, rgid, pid;
	int32_t	sid;
	int32_t port, type, addr[4];

	adrm_int32(adr, &auid, 1);
	adrm_int32(adr, &euid, 1);
	adrm_int32(adr, &egid, 1);
	adrm_int32(adr, &ruid, 1);
	adrm_int32(adr, &rgid, 1);
	adrm_int32(adr, &pid, 1);
	adrm_int32(adr, &sid, 1);
	adrm_int32(adr, &port, 1);
	adrm_int32(adr, &type, 1);
	adrm_int32(adr, &addr[0], 4);

	if (flags & M_SUBJECT) {
		if (subj_id == pid)
			checkflags = checkflags | M_SUBJECT;
	}
	if (flags & M_USERA) {
		if (m_usera == auid)
			checkflags = checkflags | M_USERA;
	}
	if (flags & M_USERE) {
		if (m_usere == euid)
			checkflags = checkflags | M_USERE;
	}
	if (flags & M_USERR) {
		if (m_userr == ruid)
			checkflags = checkflags | M_USERR;
	}
	if (flags & M_GROUPR) {
		if (m_groupr == egid)
			checkflags = checkflags | M_GROUPR;
	}
	if (flags & M_GROUPE) {
		if (m_groupe == egid)
			checkflags = checkflags | M_GROUPE;
	}
	if (flags & M_SID) {
		if (m_sid == (au_asid_t)sid)
			checkflags = checkflags | M_SID;
	}
	return (-1);
}

/*
 * Format of subject64 token:
 *	subject token id	adr_char
 *	auid			adr_int32
 *	euid			adr_int32
 *	egid 			adr_int32
 * 	ruid			adr_int32
 *	rgid			adr_int32
 * 	pid			adr_int32
 * 	sid			adr_int32
 * 	termid			adr_int64+adr_int32
 *
 */
int
subject64_token(adr_t *adr)
{
	int32_t	auid, euid, egid, ruid, rgid, pid;
	int32_t	sid;
	int64_t port;
	int32_t machine;

	adrm_int32(adr, &auid, 1);
	adrm_int32(adr, &euid, 1);
	adrm_int32(adr, &egid, 1);
	adrm_int32(adr, &ruid, 1);
	adrm_int32(adr, &rgid, 1);
	adrm_int32(adr, &pid, 1);
	adrm_int32(adr, &sid, 1);
	adrm_int64(adr, &port, 1);
	adrm_int32(adr, &machine, 1);

	if (flags & M_SUBJECT) {
		if (subj_id == pid)
			checkflags |= M_SUBJECT;
	}
	if (flags & M_USERA) {
		if (m_usera == auid)
			checkflags |= M_USERA;
	}
	if (flags & M_USERE) {
		if (m_usere == euid)
			checkflags |= M_USERE;
	}
	if (flags & M_USERR) {
		if (m_userr == ruid)
			checkflags |= M_USERR;
	}
	if (flags & M_GROUPR) {
		if (m_groupr == rgid)
			checkflags |= M_GROUPR;
	}
	if (flags & M_GROUPE) {
		if (m_groupe == egid)
			checkflags |= M_GROUPE;
	}
	if (flags & M_SID) {
		if (m_sid == (au_asid_t)sid)
			checkflags |= M_SID;
	}
	return (-1);
}

/*
 * Format of subject64 token:
 *	subject token id	adr_char
 *	auid			adr_int32
 *	euid			adr_int32
 *	egid 			adr_int32
 * 	ruid			adr_int32
 *	rgid			adr_int32
 * 	pid			adr_int32
 * 	sid			adr_int32
 * 	termid			adr_int64+5*adr_int32
 *
 */
int
subject64_ex_token(adr_t *adr)
{
	int32_t	auid, euid, egid, ruid, rgid, pid;
	int32_t	sid;
	int64_t port;
	int32_t type, addr[4];

	adrm_int32(adr, &auid, 1);
	adrm_int32(adr, &euid, 1);
	adrm_int32(adr, &egid, 1);
	adrm_int32(adr, &ruid, 1);
	adrm_int32(adr, &rgid, 1);
	adrm_int32(adr, &pid, 1);
	adrm_int32(adr, &sid, 1);
	adrm_int64(adr, &port, 1);
	adrm_int32(adr, &type, 1);
	adrm_int32(adr, &addr[0], 4);

	if (flags & M_SUBJECT) {
		if (subj_id == pid)
			checkflags = checkflags | M_SUBJECT;
	}
	if (flags & M_USERA) {
		if (m_usera == auid)
			checkflags = checkflags | M_USERA;
	}
	if (flags & M_USERE) {
		if (m_usere == euid)
			checkflags = checkflags | M_USERE;
	}
	if (flags & M_USERR) {
		if (m_userr == ruid)
			checkflags = checkflags | M_USERR;
	}
	if (flags & M_GROUPR) {
		if (m_groupr == egid)
			checkflags = checkflags | M_GROUPR;
	}
	if (flags & M_GROUPE) {
		if (m_groupe == egid)
			checkflags = checkflags | M_GROUPE;
	}
	if (flags & M_SID) {
		if (m_sid == (au_asid_t)sid)
			checkflags = checkflags | M_SID;
	}
	return (-1);
}

/*
 * -----------------------------------------------------------------------
 * tid_token(): Process tid token and display contents
 *
 * Format of tid token:
 *	tid token id			adr_char
 * 	address type			adr_char
 *	For address type of AU_IPADR...
 *		remote port		adr_short
 *		local port		adr_short
 *		IP type			adr_int32
 *		IP addr			adr_int32 if IPv4
 *		IP addr			4 x adr_int32 if IPv6
 * address types other than AU_IPADR are not yet defined
 * -----------------------------------------------------------------------
 */
int
tid_token(adr_t *adr)
{
	int32_t	address[4];
	int32_t	ip_type;
	char	tid_type;
	short	rport;
	short	lport;

	adrm_char(adr, &tid_type, 1);
	switch (tid_type) {
	case AU_IPADR:
		adrm_short(adr, &rport, 1);
		adrm_short(adr, &lport, 1);
		adrm_int32(adr, &ip_type, 1);
		adrm_char(adr, (char *)&address, ip_type);
		break;
	default:
		return (0);
	}
	return (-1);
}

/*
 * -----------------------------------------------------------------------
 * zonename_token(): Process zonename token and display contents
 *
 * Format of zonename token:
 *	zonename token id		adr_char
 * 	zone name			adr_string
 * -----------------------------------------------------------------------
 */
int
zonename_token(adr_t *adr)
{
	char	*name;

	if (flags & M_ZONENAME) {
		get_string(adr, &name);
		if (strncmp(zonename, name, ZONENAME_MAX) == 0)
			checkflags |= M_ZONENAME;
		free(name);
	} else {
		skip_string(adr);
	}
	return (-1);
}

/*
 * fmri_token():
 *
 * Format of fmri token:
 * 	fmri				adr_string
 */
int
fmri_token(adr_t *adr)
{
	if ((flags & M_OBJECT) && (obj_flag == OBJ_FMRI)) {
		char	*fmri_name;

		get_string(adr, &fmri_name);

		/* match token against service instance */
		if (scf_cmp_pattern(fmri_name, &fmri) == 1) {
			checkflags |= M_OBJECT;
		}
		free(fmri_name);
	} else {
		skip_string(adr);
	}
	return (-1);
}

/*
 * Format of xatom token:
 */
int
xatom_token(adr_t *adr)
{
	skip_string(adr);

	return (-1);
}

/*
 * Format of xselect token:
 */
int
xselect_token(adr_t *adr)
{
	skip_string(adr);
	skip_string(adr);
	skip_string(adr);

	return (-1);
}

/*
 * anchor a path name with a slash
 * assume we have enough space
 */
void
anchor_path(char *path)
{
	(void) memmove((void *)(path + 1), (void *)path, strlen(path) + 1);
	*path = '/';
}


/*
 * copy path to collapsed path.
 * collapsed path does not contain:
 *	successive slashes
 *	instances of dot-slash
 *	instances of dot-dot-slash
 * passed path must be anchored with a '/'
 */
char *
collapse_path(char *s)
{
	int	id;	/* index of where we are in destination string */
	int	is;	/* index of where we are in source string */
	int	slashseen;	/* have we seen a slash */
	int	ls;		/* length of source string */

	ls = strlen(s) + 1;

	slashseen = 0;
	for (is = 0, id = 0; is < ls; is++) {
		/* thats all folks, we've reached the end of input */
		if (s[is] == '\0') {
			if (id > 1 && s[id-1] == '/') {
				--id;
			}
			s[id++] = '\0';
			break;
		}
		/* previous character was a / */
		if (slashseen) {
			if (s[is] == '/')
				continue;	/* another slash, ignore it */
		} else if (s[is] == '/') {
			/* we see a /, just copy it and try again */
			slashseen = 1;
			s[id++] = '/';
			continue;
		}
		/* /./ seen */
		if (s[is] == '.' && s[is+1] == '/') {
			is += 1;
			continue;
		}
		/* XXX/. seen */
		if (s[is] == '.' && s[is+1] == '\0') {
			if (id > 1)
				id--;
			continue;
		}
		/* XXX/.. seen */
		if (s[is] == '.' && s[is+1] == '.' && s[is+2] == '\0') {
			is += 1;
			if (id > 0)
				id--;
			while (id > 0 && s[--id] != '/')
				;
			id++;
			continue;
		}
		/* XXX/../ seen */
		if (s[is] == '.' && s[is+1] == '.' && s[is+2] == '/') {
			is += 2;
			if (id > 0)
				id--;
			while (id > 0 && s[--id] != '/')
				;
			id++;
			continue;
		}
		while (is < ls && (s[id++] = s[is++]) != '/')
			;
		is--;
	}
	return (s);
}


int
ipc_type_match(int flag, char type)
{
	if (flag == OBJ_SEM && type == AT_IPC_SEM)
		return (1);

	if (flag == OBJ_MSG && type == AT_IPC_MSG)
		return (1);

	if (flag == OBJ_SHM && type == AT_IPC_SHM)
		return (1);

	return (0);
}


void
skip_string(adr_t *adr)
{
	ushort_t	c;

	adrm_u_short(adr, &c, 1);
	adr->adr_now += c;
}


void
get_string(adr_t *adr, char **p)
{
	ushort_t	c;

	adrm_u_short(adr, &c, 1);
	*p = a_calloc(1, (size_t)c);
	adrm_char(adr, *p, c);
}


/*
 * Format of host token:
 *	host  		ard_uint32
 */
int
host_token(adr_t *adr)
{
	uint32_t host;

	adrm_u_int32(adr, &host, 1);

	return (-1);
}

/*
 * Format of useofauth token:
 *	uauth token id		adr_char
 * 	uauth			adr_string
 *
 */
int
useofauth_token(adr_t *adr)
{
	skip_string(adr);
	return (-1);
}

int
xcolormap_token(adr_t *adr)
{
	return (xgeneric(adr));
}

int
xcursor_token(adr_t *adr)
{
	return (xgeneric(adr));
}

int
xfont_token(adr_t *adr)
{
	return (xgeneric(adr));
}

int
xgc_token(adr_t *adr)
{
	return (xgeneric(adr));
}

int
xpixmap_token(adr_t *adr)
{
	return (xgeneric(adr));
}

int
xwindow_token(adr_t *adr)
{
	return (xgeneric(adr));
}


/*
 * Format of xgeneric token:
 *	XID			adr_int32
 *	creator UID		adr_int32
 *
 * Includes:  xcolormap, xcursor, xfont, xgc, xpixmap, and xwindow
 */
int
xgeneric(adr_t *adr)
{
	int32_t xid;
	int32_t uid;

	adrm_int32(adr, &xid, 1);
	adrm_int32(adr, &uid, 1);

	if (flags & M_USERE) {
		if (m_usere == uid)
			checkflags = checkflags | M_USERE;
	}

	return (-1);
}


/*
 * Format of xproperty token:
 *	XID			adr_int32
 *	creator UID		adr_int32
 *	atom string		adr_string
 */
int
xproperty_token(adr_t *adr)
{
	int32_t	xid;
	int32_t uid;

	adrm_int32(adr, &xid, 1);
	adrm_int32(adr, &uid, 1);
	skip_string(adr);

	if (flags & M_USERE) {
		if (m_usere == uid)
			checkflags = checkflags | M_USERE;
	}

	return (-1);
}


/*
 * Format of xclient token:
 * 	xclient id		adr_int32
 */
int
xclient_token(adr_t *adr)
{
	int32_t	client_id;

	adrm_int32(adr, &client_id, 1);

	return (-1);
}

/*
 * Format of privilege set token:
 *	priv_set type		string
 *	priv_set		string
 */

int
privilege_token(adr_t *adr)
{
	skip_string(adr);	/* set type name */
	skip_string(adr);	/* privilege set */
	return (-1);
}

/*
 * Format of label token:
 *      label ID                1 byte
 *      compartment length      1 byte
 *      classification          2 bytes
 *      compartment words       <compartment length> * 4 bytes
 */
int
label_token(adr_t *adr)
{
	static m_label_t *label = NULL;
	static size32_t l_size;
	int len;

	if (label == NULL) {
		label = m_label_alloc(MAC_LABEL);
		l_size = blabel_size() - 4;
	}

	if (label == NULL) {
		/* out of memory, should never happen; skip label */
		char	l;	/* length */

		adr->adr_now += sizeof (char);
		adrm_char(adr, (char *)&l, 1);
		adr->adr_now += sizeof (short) + (4 * l);
		return (-1);
	}

	adrm_char(adr, (char *)label, 4);
	len = (int)(((char *)label)[1] * 4);
	if (len > l_size) {
		return (-1);
	}
	adrm_char(adr, &((char *)label)[4], len);

	if (flags & M_LABEL) {
		if (blinrange(label, m_label))
			checkflags = checkflags | M_LABEL;
	}

	return (-1);
}


/*
 * Format of useofpriv token:
 *	success/failure		adr_char
 *	privilege(s)		adr_string
 */
/* ARGSUSED */
int
useofpriv_token(adr_t *adr)
{
	char	flag;

	adrm_char(adr, &flag, 1);
	skip_string(adr);
	return (-1);
}