269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * CDDL HEADER START
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * The contents of this file are subject to the terms of the
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Common Development and Distribution License (the "License").
269473047d747f7815af570197e4ef7322d3632cEvan Yan * You may not use this file except in compliance with the License.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
269473047d747f7815af570197e4ef7322d3632cEvan Yan * or http://www.opensolaris.org/os/licensing.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * See the License for the specific language governing permissions
269473047d747f7815af570197e4ef7322d3632cEvan Yan * and limitations under the License.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * When distributing Covered Code, include this CDDL HEADER in each
269473047d747f7815af570197e4ef7322d3632cEvan Yan * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * If applicable, add the following below this CDDL HEADER, with the
269473047d747f7815af570197e4ef7322d3632cEvan Yan * fields enclosed by brackets "[]" replaced with your own identifying
269473047d747f7815af570197e4ef7322d3632cEvan Yan * information: Portions Copyright [yyyy] [name of copyright owner]
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * CDDL HEADER END
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Use is subject to license terms.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <stdio.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <stdlib.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <unistd.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <fcntl.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <errno.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <strings.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <alloca.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <door.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <pthread.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <synch.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <pwd.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <auth_list.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <auth_attr.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <bsm/adt.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <bsm/adt_event.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/sunddi.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/ddi_hp.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <libnvpair.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <libhotplug.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <libhotplug_impl.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include "hotplugd_impl.h"
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Buffer management for results.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yantypedef struct i_buffer {
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint64_t seqnum;
269473047d747f7815af570197e4ef7322d3632cEvan Yan char *buffer;
269473047d747f7815af570197e4ef7322d3632cEvan Yan struct i_buffer *next;
269473047d747f7815af570197e4ef7322d3632cEvan Yan} i_buffer_t;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic uint64_t buffer_seqnum = 1;
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic i_buffer_t *buffer_list = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic pthread_mutex_t buffer_lock = PTHREAD_MUTEX_INITIALIZER;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Door file descriptor.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int door_fd = -1;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Function prototypes.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void door_server(void *, char *, size_t, door_desc_t *, uint_t);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int check_auth(ucred_t *, const char *);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int cmd_getinfo(nvlist_t *, nvlist_t **);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int cmd_changestate(nvlist_t *, nvlist_t **);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int cmd_private(hp_cmd_t, nvlist_t *, nvlist_t **);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void add_buffer(uint64_t, char *);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void free_buffer(uint64_t);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic uint64_t get_seqnum(void);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic char *state_str(int);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int audit_session(ucred_t *, adt_session_data_t **);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void audit_changestate(ucred_t *, char *, char *, char *, int, int,
269473047d747f7815af570197e4ef7322d3632cEvan Yan int);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void audit_setprivate(ucred_t *, char *, char *, char *, char *,
269473047d747f7815af570197e4ef7322d3632cEvan Yan int);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * door_server_init()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Create the door file, and initialize the door server.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanboolean_t
269473047d747f7815af570197e4ef7322d3632cEvan Yandoor_server_init(void)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan int fd;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Create the door file */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((fd = open(HOTPLUGD_DOOR, O_CREAT|O_EXCL|O_RDONLY, 0644)) == -1) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (errno == EEXIST) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Door service is already running.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot open door file '%s': %s\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan HOTPLUGD_DOOR, strerror(errno));
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (B_FALSE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) close(fd);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Initialize the door service */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((door_fd = door_create(door_server, NULL,
269473047d747f7815af570197e4ef7322d3632cEvan Yan DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) == -1) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot create door service: %s\n", strerror(errno));
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (B_FALSE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Cleanup stale door associations */
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) fdetach(HOTPLUGD_DOOR);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Associate door service with door file */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (fattach(door_fd, HOTPLUGD_DOOR) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot attach to door file '%s': %s\n", HOTPLUGD_DOOR,
269473047d747f7815af570197e4ef7322d3632cEvan Yan strerror(errno));
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) door_revoke(door_fd);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) fdetach(HOTPLUGD_DOOR);
269473047d747f7815af570197e4ef7322d3632cEvan Yan door_fd = -1;
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (B_FALSE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (B_TRUE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * door_server_fini()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Terminate and cleanup the door server.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanvoid
269473047d747f7815af570197e4ef7322d3632cEvan Yandoor_server_fini(void)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (door_fd != -1) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) door_revoke(door_fd);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) fdetach(HOTPLUGD_DOOR);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) unlink(HOTPLUGD_DOOR);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * door_server()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * This routine is the handler which responds to each door call.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Each incoming door call is expected to send a packed nvlist
269473047d747f7815af570197e4ef7322d3632cEvan Yan * of arguments which describe the requested action. And each
269473047d747f7815af570197e4ef7322d3632cEvan Yan * response is sent back as a packed nvlist of results.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Results are always allocated on the heap. A global list of
269473047d747f7815af570197e4ef7322d3632cEvan Yan * allocated result buffers is managed, and each one is tracked
269473047d747f7815af570197e4ef7322d3632cEvan Yan * by a unique sequence number. The final step in the protocol
269473047d747f7815af570197e4ef7322d3632cEvan Yan * is for the caller to send a short response using the sequence
269473047d747f7815af570197e4ef7322d3632cEvan Yan * number when the buffer can be released.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*ARGSUSED*/
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void
269473047d747f7815af570197e4ef7322d3632cEvan Yandoor_server(void *cookie, char *argp, size_t sz, door_desc_t *dp, uint_t ndesc)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan nvlist_t *args = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan nvlist_t *results = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan hp_cmd_t cmd;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rv;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("Door call: cookie=%p, argp=%p, sz=%d\n", cookie, (void *)argp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan sz);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Special case to free a results buffer */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (sz == sizeof (uint64_t)) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan free_buffer(*(uint64_t *)(uintptr_t)argp);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) door_return(NULL, 0, NULL, 0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Unpack the arguments nvlist */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (nvlist_unpack(argp, sz, &args, 0) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot unpack door arguments.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = EINVAL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto fail;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Extract the requested command */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (nvlist_lookup_int32(args, HPD_CMD, (int32_t *)&cmd) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot decode door command.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = EINVAL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto fail;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Implement the command */
269473047d747f7815af570197e4ef7322d3632cEvan Yan switch (cmd) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan case HP_CMD_GETINFO:
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = cmd_getinfo(args, &results);
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case HP_CMD_CHANGESTATE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = cmd_changestate(args, &results);
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case HP_CMD_SETPRIVATE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan case HP_CMD_GETPRIVATE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = cmd_private(cmd, args, &results);
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan default:
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = EINVAL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* The arguments nvlist is no longer needed */
269473047d747f7815af570197e4ef7322d3632cEvan Yan nvlist_free(args);
269473047d747f7815af570197e4ef7322d3632cEvan Yan args = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * If an nvlist was constructed for the results,
269473047d747f7815af570197e4ef7322d3632cEvan Yan * then pack the results nvlist and return it.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (results != NULL) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint64_t seqnum;
269473047d747f7815af570197e4ef7322d3632cEvan Yan char *buf = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan size_t len = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Add a sequence number to the results */
269473047d747f7815af570197e4ef7322d3632cEvan Yan seqnum = get_seqnum();
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (nvlist_add_uint64(results, HPD_SEQNUM, seqnum) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot add sequence number.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = EFAULT;
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto fail;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Pack the results nvlist */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (nvlist_pack(results, &buf, &len,
269473047d747f7815af570197e4ef7322d3632cEvan Yan NV_ENCODE_NATIVE, 0) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot pack door results.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = EFAULT;
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto fail;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Link results buffer into list */
269473047d747f7815af570197e4ef7322d3632cEvan Yan add_buffer(seqnum, buf);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* The results nvlist is no longer needed */
269473047d747f7815af570197e4ef7322d3632cEvan Yan nvlist_free(results);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Return the results */
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) door_return(buf, len, NULL, 0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Return result code (when no nvlist) */
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) door_return((char *)&rv, sizeof (int), NULL, 0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yanfail:
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Door call failed (%s)\n", strerror(rv));
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(args);
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(results);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) door_return((char *)&rv, sizeof (int), NULL, 0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * check_auth()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Perform an RBAC authorization check.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yancheck_auth(ucred_t *ucred, const char *auth)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan struct passwd pwd;
269473047d747f7815af570197e4ef7322d3632cEvan Yan uid_t euid;
269473047d747f7815af570197e4ef7322d3632cEvan Yan char buf[MAXPATHLEN];
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan euid = ucred_geteuid(ucred);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((getpwuid_r(euid, &pwd, buf, sizeof (buf)) == NULL) ||
269473047d747f7815af570197e4ef7322d3632cEvan Yan (chkauthattr(auth, pwd.pw_name) == 0)) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_info("Unauthorized door call.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (-1);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * cmd_getinfo()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Implements the door command to get a hotplug information snapshot.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yancmd_getinfo(nvlist_t *args, nvlist_t **resultsp)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan hp_node_t root;
269473047d747f7815af570197e4ef7322d3632cEvan Yan nvlist_t *results;
269473047d747f7815af570197e4ef7322d3632cEvan Yan char *path;
269473047d747f7815af570197e4ef7322d3632cEvan Yan char *connection;
269473047d747f7815af570197e4ef7322d3632cEvan Yan char *buf = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan size_t len = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint_t flags;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rv;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_getinfo:\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Get arguments */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (nvlist_lookup_string(args, HPD_PATH, &path) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_getinfo: invalid arguments.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EINVAL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (nvlist_lookup_string(args, HPD_CONNECTION, &connection) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan connection = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (nvlist_lookup_uint32(args, HPD_FLAGS, (uint32_t *)&flags) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan flags = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Get and pack the requested snapshot */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((rv = getinfo(path, connection, flags, &root)) == 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = hp_pack(root, &buf, &len);
269473047d747f7815af570197e4ef7322d3632cEvan Yan hp_fini(root);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_getinfo: getinfo(): rv = %d, buf = %p.\n", rv,
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)buf);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * If the above failed or there is no snapshot,
269473047d747f7815af570197e4ef7322d3632cEvan Yan * then only return a status code.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (buf == NULL)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EFAULT);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Allocate nvlist for results */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (nvlist_alloc(&results, NV_UNIQUE_NAME_TYPE, 0) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_getinfo: nvlist_alloc() failed.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan free(buf);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ENOMEM);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Add snapshot and successful status to results */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((nvlist_add_int32(results, HPD_STATUS, 0) != 0) ||
269473047d747f7815af570197e4ef7322d3632cEvan Yan (nvlist_add_byte_array(results, HPD_INFO,
269473047d747f7815af570197e4ef7322d3632cEvan Yan (uchar_t *)buf, len) != 0)) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_getinfo: nvlist add failure.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan nvlist_free(results);
269473047d747f7815af570197e4ef7322d3632cEvan Yan free(buf);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ENOMEM);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Packed snapshot no longer needed */
269473047d747f7815af570197e4ef7322d3632cEvan Yan free(buf);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Success */
269473047d747f7815af570197e4ef7322d3632cEvan Yan *resultsp = results;
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * cmd_changestate()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Implements the door command to initate a state change operation.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * NOTE: requires 'modify' authorization.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yancmd_changestate(nvlist_t *args, nvlist_t **resultsp)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan hp_node_t root = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan nvlist_t *results = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan char *path, *connection;
269473047d747f7815af570197e4ef7322d3632cEvan Yan ucred_t *uc = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint_t flags;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rv, state, old_state, status;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_changestate:\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Get arguments */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((nvlist_lookup_string(args, HPD_PATH, &path) != 0) ||
269473047d747f7815af570197e4ef7322d3632cEvan Yan (nvlist_lookup_string(args, HPD_CONNECTION, &connection) != 0) ||
269473047d747f7815af570197e4ef7322d3632cEvan Yan (nvlist_lookup_int32(args, HPD_STATE, &state) != 0)) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_changestate: invalid arguments.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EINVAL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (nvlist_lookup_uint32(args, HPD_FLAGS, (uint32_t *)&flags) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan flags = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Get caller's credentials */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (door_ucred(&uc) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot get door credentials (%s)\n", strerror(errno));
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EACCES);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Check authorization */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (check_auth(uc, HP_MODIFY_AUTH) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_changestate: access denied.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan audit_changestate(uc, HP_MODIFY_AUTH, path, connection,
269473047d747f7815af570197e4ef7322d3632cEvan Yan state, -1, ADT_FAIL_VALUE_AUTH);
269473047d747f7815af570197e4ef7322d3632cEvan Yan ucred_free(uc);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EACCES);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Perform the state change operation */
269473047d747f7815af570197e4ef7322d3632cEvan Yan status = changestate(path, connection, state, flags, &old_state, &root);
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_changestate: changestate() == %d\n", status);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Audit the operation */
269473047d747f7815af570197e4ef7322d3632cEvan Yan audit_changestate(uc, HP_MODIFY_AUTH, path, connection, state,
269473047d747f7815af570197e4ef7322d3632cEvan Yan old_state, status);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Caller's credentials no longer needed */
269473047d747f7815af570197e4ef7322d3632cEvan Yan ucred_free(uc);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Pack the results into an nvlist if there is an error snapshot.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * If any error occurs while packing the results, the original
269473047d747f7815af570197e4ef7322d3632cEvan Yan * error code from changestate() above is still returned.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (root != NULL) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan char *buf = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan size_t len = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_changestate: results nvlist required.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Pack and discard the error snapshot */
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = hp_pack(root, &buf, &len);
269473047d747f7815af570197e4ef7322d3632cEvan Yan hp_fini(root);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_changestate: hp_pack() failed (%s).\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan strerror(rv));
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (status);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Allocate nvlist for results */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (nvlist_alloc(&results, NV_UNIQUE_NAME_TYPE, 0) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_changestate: nvlist_alloc() failed.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan free(buf);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (status);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Add the results into the nvlist */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((nvlist_add_int32(results, HPD_STATUS, status) != 0) ||
269473047d747f7815af570197e4ef7322d3632cEvan Yan (nvlist_add_byte_array(results, HPD_INFO, (uchar_t *)buf,
269473047d747f7815af570197e4ef7322d3632cEvan Yan len) != 0)) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_changestate: nvlist add failed.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan nvlist_free(results);
269473047d747f7815af570197e4ef7322d3632cEvan Yan free(buf);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (status);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan *resultsp = results;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (status);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * cmd_private()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Implementation of the door command to set or get bus private options.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * NOTE: requires 'modify' authorization for the 'set' command.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yancmd_private(hp_cmd_t cmd, nvlist_t *args, nvlist_t **resultsp)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan nvlist_t *results = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan ucred_t *uc = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan char *path, *connection, *options;
269473047d747f7815af570197e4ef7322d3632cEvan Yan char *values = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int status;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_private:\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Get caller's credentials */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((cmd == HP_CMD_SETPRIVATE) && (door_ucred(&uc) != 0)) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot get door credentials (%s)\n", strerror(errno));
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EACCES);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Get arguments */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((nvlist_lookup_string(args, HPD_PATH, &path) != 0) ||
269473047d747f7815af570197e4ef7322d3632cEvan Yan (nvlist_lookup_string(args, HPD_CONNECTION, &connection) != 0) ||
269473047d747f7815af570197e4ef7322d3632cEvan Yan (nvlist_lookup_string(args, HPD_OPTIONS, &options) != 0)) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_private: invalid arguments.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EINVAL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Check authorization */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((cmd == HP_CMD_SETPRIVATE) &&
269473047d747f7815af570197e4ef7322d3632cEvan Yan (check_auth(uc, HP_MODIFY_AUTH) != 0)) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_private: access denied.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan audit_setprivate(uc, HP_MODIFY_AUTH, path, connection, options,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ADT_FAIL_VALUE_AUTH);
269473047d747f7815af570197e4ef7322d3632cEvan Yan ucred_free(uc);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EACCES);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Perform the operation */
269473047d747f7815af570197e4ef7322d3632cEvan Yan status = private_options(path, connection, cmd, options, &values);
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_private: private_options() == %d\n", status);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Audit the operation */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (cmd == HP_CMD_SETPRIVATE) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan audit_setprivate(uc, HP_MODIFY_AUTH, path, connection, options,
269473047d747f7815af570197e4ef7322d3632cEvan Yan status);
269473047d747f7815af570197e4ef7322d3632cEvan Yan ucred_free(uc);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Construct an nvlist if values were returned */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (values != NULL) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Allocate nvlist for results */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (nvlist_alloc(&results, NV_UNIQUE_NAME_TYPE, 0) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_private: nvlist_alloc() failed.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan free(values);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ENOMEM);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Add values and status to the results */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((nvlist_add_int32(results, HPD_STATUS, status) != 0) ||
269473047d747f7815af570197e4ef7322d3632cEvan Yan (nvlist_add_string(results, HPD_OPTIONS, values) != 0)) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("cmd_private: nvlist add failed.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan nvlist_free(results);
269473047d747f7815af570197e4ef7322d3632cEvan Yan free(values);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ENOMEM);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* The values string is no longer needed */
269473047d747f7815af570197e4ef7322d3632cEvan Yan free(values);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan *resultsp = results;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (status);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * get_seqnum()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Allocate the next unique sequence number for a results buffer.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic uint64_t
269473047d747f7815af570197e4ef7322d3632cEvan Yanget_seqnum(void)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint64_t seqnum;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) pthread_mutex_lock(&buffer_lock);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan seqnum = buffer_seqnum++;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) pthread_mutex_unlock(&buffer_lock);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (seqnum);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * add_buffer()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Link a results buffer into the list containing all buffers.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void
269473047d747f7815af570197e4ef7322d3632cEvan Yanadd_buffer(uint64_t seqnum, char *buf)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan i_buffer_t *node;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((node = (i_buffer_t *)malloc(sizeof (i_buffer_t))) == NULL) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* The consequence is a memory leak. */
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot allocate results buffer: %s\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan strerror(errno));
269473047d747f7815af570197e4ef7322d3632cEvan Yan return;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan node->seqnum = seqnum;
269473047d747f7815af570197e4ef7322d3632cEvan Yan node->buffer = buf;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) pthread_mutex_lock(&buffer_lock);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan node->next = buffer_list;
269473047d747f7815af570197e4ef7322d3632cEvan Yan buffer_list = node;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) pthread_mutex_unlock(&buffer_lock);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * free_buffer()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Remove a results buffer from the list containing all buffers.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void
269473047d747f7815af570197e4ef7322d3632cEvan Yanfree_buffer(uint64_t seqnum)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan i_buffer_t *node, *prev;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) pthread_mutex_lock(&buffer_lock);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan prev = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan node = buffer_list;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan while (node) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (node->seqnum == seqnum) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan dprintf("Free buffer %lld\n", seqnum);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (prev) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan prev->next = node->next;
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else {
269473047d747f7815af570197e4ef7322d3632cEvan Yan buffer_list = node->next;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan free(node->buffer);
269473047d747f7815af570197e4ef7322d3632cEvan Yan free(node);
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan prev = node;
269473047d747f7815af570197e4ef7322d3632cEvan Yan node = node->next;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) pthread_mutex_unlock(&buffer_lock);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * audit_session()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Initialize an audit session.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanaudit_session(ucred_t *ucred, adt_session_data_t **sessionp)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan adt_session_data_t *session;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (adt_start_session(&session, NULL, 0) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot start audit session.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (-1);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (adt_set_from_ucred(session, ucred, ADT_NEW) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot set audit session from ucred.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) adt_end_session(session);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (-1);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan *sessionp = session;
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * audit_changestate()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Audit a 'changestate' door command.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void
269473047d747f7815af570197e4ef7322d3632cEvan Yanaudit_changestate(ucred_t *ucred, char *auth, char *path, char *connection,
269473047d747f7815af570197e4ef7322d3632cEvan Yan int new_state, int old_state, int result)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan adt_session_data_t *session;
269473047d747f7815af570197e4ef7322d3632cEvan Yan adt_event_data_t *event;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int pass_fail, fail_reason;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (audit_session(ucred, &session) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((event = adt_alloc_event(session, ADT_hotplug_state)) == NULL) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) adt_end_session(session);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (result == 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan pass_fail = ADT_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan fail_reason = ADT_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else {
269473047d747f7815af570197e4ef7322d3632cEvan Yan pass_fail = ADT_FAILURE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan fail_reason = result;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan event->adt_hotplug_state.auth_used = auth;
269473047d747f7815af570197e4ef7322d3632cEvan Yan event->adt_hotplug_state.device_path = path;
269473047d747f7815af570197e4ef7322d3632cEvan Yan event->adt_hotplug_state.connection = connection;
269473047d747f7815af570197e4ef7322d3632cEvan Yan event->adt_hotplug_state.new_state = state_str(new_state);
269473047d747f7815af570197e4ef7322d3632cEvan Yan event->adt_hotplug_state.old_state = state_str(old_state);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Put the event */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (adt_put_event(event, pass_fail, fail_reason) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot put audit event.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan adt_free_event(event);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) adt_end_session(session);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * audit_setprivate()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Audit a 'set private' door command.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void
269473047d747f7815af570197e4ef7322d3632cEvan Yanaudit_setprivate(ucred_t *ucred, char *auth, char *path, char *connection,
269473047d747f7815af570197e4ef7322d3632cEvan Yan char *options, int result)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan adt_session_data_t *session;
269473047d747f7815af570197e4ef7322d3632cEvan Yan adt_event_data_t *event;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int pass_fail, fail_reason;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (audit_session(ucred, &session) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((event = adt_alloc_event(session, ADT_hotplug_set)) == NULL) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) adt_end_session(session);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (result == 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan pass_fail = ADT_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan fail_reason = ADT_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else {
269473047d747f7815af570197e4ef7322d3632cEvan Yan pass_fail = ADT_FAILURE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan fail_reason = result;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan event->adt_hotplug_set.auth_used = auth;
269473047d747f7815af570197e4ef7322d3632cEvan Yan event->adt_hotplug_set.device_path = path;
269473047d747f7815af570197e4ef7322d3632cEvan Yan event->adt_hotplug_set.connection = connection;
269473047d747f7815af570197e4ef7322d3632cEvan Yan event->adt_hotplug_set.options = options;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Put the event */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (adt_put_event(event, pass_fail, fail_reason) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot put audit event.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan adt_free_event(event);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) adt_end_session(session);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * state_str()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Convert a state from integer to string.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic char *
269473047d747f7815af570197e4ef7322d3632cEvan Yanstate_str(int state)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan switch (state) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_EMPTY:
269473047d747f7815af570197e4ef7322d3632cEvan Yan return ("EMPTY");
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_PRESENT:
269473047d747f7815af570197e4ef7322d3632cEvan Yan return ("PRESENT");
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_POWERED:
269473047d747f7815af570197e4ef7322d3632cEvan Yan return ("POWERED");
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_ENABLED:
269473047d747f7815af570197e4ef7322d3632cEvan Yan return ("ENABLED");
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_PORT_EMPTY:
269473047d747f7815af570197e4ef7322d3632cEvan Yan return ("PORT-EMPTY");
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_PORT_PRESENT:
269473047d747f7815af570197e4ef7322d3632cEvan Yan return ("PORT-PRESENT");
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_OFFLINE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan return ("OFFLINE");
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_ATTACHED:
269473047d747f7815af570197e4ef7322d3632cEvan Yan return ("ATTACHED");
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_MAINTENANCE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan return ("MAINTENANCE");
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_ONLINE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan return ("ONLINE");
269473047d747f7815af570197e4ef7322d3632cEvan Yan default:
269473047d747f7815af570197e4ef7322d3632cEvan Yan return ("UNKNOWN");
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan}