wusbd.c revision ff0e937b36dcde1a47ff7b00aa76a491c0dc07a8
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include <signal.h>
#include <door.h>
#include <libsysevent.h>
#include <fcntl.h>
#include <syslog.h>
#include <pthread.h>
#include <dirent.h>
#include <locale.h>
#include <alloca.h> /* alloca */
#include <errno.h>
#include <pwd.h>
#include <priv_utils.h>
#include <priv.h>
#include "crypto_util.h"
#include "wusbd.h"
/* deamon exit status code */
#define CONFIG_ERROR 1
#define FATAL_ERROR 2
#define PKTOKEN "Sun Software PKCS#11 softtoken "
/* Restrict the max number association for one host to 200 */
#define HOST_MAX 100
#define DEV_MAX 200
/* global mutext for door service */
static void wusbd_daemon_enter();
static void wusbd_daemon_leave(char *, int);
/* cc utility funcs */
static int save_cc(const wusb_cc_info_t *);
static int save_cc_to_list(const wusb_cc_info_t *);
static int save_cc_to_store(const wusb_cc_info_t *);
static void refresh(int);
static void event_handler(sysevent_t *);
/* daemon init functions */
static int wusbd_daemonize_init(void);
static void wusbd_daemonize_fini(int, int);
static int init_daemon_pid();
static int init_sys_evnt();
static int init_door_srv();
static int init_global_cc_list();
static void print_prv();
static void exit_clean(int);
/* walk on all hosts in system */
typedef void (* host_func)(const char *);
static void all_hosts_iterate(host_func);
/* walk on all cc list */
typedef int (* cc_list_func)(wusb_cc_list_t *, void *);
static void global_list_iterate(cc_list_func, void *);
static void add_to_global_list(wusb_cc_list_t *);
static void remove_from_global_list(wusb_cc_list_t *);
/* update cc list device status */
static void clean_all_cc_list();
static void update_cc_list(const char *);
static void update_all_cc_list();
static int update_cc_file();
static int add_all_cc_to_host(const char *, uint8_t);
static int remove_all_cc_from_host(uint8_t);
static int create_host_cc(const char *);
static void check_host(const char *);
static void check_all_host();
static void stop_all_host();
/* cc list entry funcs */
static int clean_cc_list(wusb_cc_list_t *, void *);
static int print_cc_list(wusb_cc_list_t *, void *);
static int copy_cc_list(wusb_cc_list_t *, void *);
static int write_cc_list(wusb_cc_list_t *, void *);
/* door service utility funcs */
static int wusbd_check_auth(const char *);
/* daemon log utilities */
static void wusbd_info(const char *, ...);
static void wusbd_warn(const char *, ...);
static void wusbd_log(const char *, ...);
/* host-id / dev-id util funcs */
static uint8_t assign_host_id(void);
static int get_host_path(int, char *);
static int load_host_mac(const char *, uint8_t *);
/* searching helper funcs */
static int find_host_id(uint8_t *);
static void copy_list_back(char *);
static int start_host(const char *);
static int stop_host(const char *);
/* remove dev funcs */
static int remove_all_dev(uint8_t);
/* dev_ctrl check funcs */
static int wusbd_do_ca(const char *, const char *, wusb_cc_info_t *, char);
/* cc generation methods */
static int generate_wusb_CC(wusb_cc_t *);
typedef struct {
const char *auth;
static wusbd_door_func_t dfuncs[] =
{
{ WUSB_AUTH_READ, wusbd_do_list },
};
static void
wusbd_sig_handler(int sigval)
{
switch (sigval) {
case 0:
case SIGPIPE:
wusbd_info("SIG PIPE received");
break;
case SIGHUP:
wusbd_info("Refreshing dameon");
/* Refresh config was triggered */
break;
default:
(void) pthread_mutex_lock(&mutex_cclock);
wusbd_info("Stop all host before exit");
(void) pthread_mutex_unlock(&mutex_cclock);
exit_clean(0);
break;
}
}
/*
* Daemon.
* use "--daemon" to start daemon
*/
void
daemonize() {
int pfd = -1;
(void) sigfillset(&set);
pfd = wusbd_daemonize_init();
wusbd_info("daemonize: start daemon ");
wusbd_log("daemonize: mutext cclock init failed!");
}
if (init_daemon_pid() < 0) {
wusbd_log("daemonize: init daemon pid fail");
goto fail;
}
if (init_global_cc_list() < 0) {
wusbd_log("daemonize: init global cc fail");
goto fail;
}
if (init_sys_evnt() < 0) {
wusbd_log("daemonize: init sys evnt fail");
goto fail;
}
if (init_door_srv() < 0) {
wusbd_log("daemonize: init door serv fail");
goto fail;
}
wusbd_daemonize_fini(pfd, 0);
/*CONSTCOND*/
while (1) {
(void) pause();
}
fail:
}
/* Respond client's list request. */
/*ARGSUSED*/
static int
{
/* update CC status */
/* 2 bytes command result */
/* 4 bytes cc list number */
/* length of all clists */
/* use alloca here */
wusbd_warn("wusb_do_list: alloca buffer failed");
return (WUSBA_FAILURE);
}
/* command result */
/* cc number */
/* wusb_device_info_t * cc_cnt */
/* debug only */
/*
* Update the cc file because we may get the device type if
* device is connected
*/
(void) update_cc_file();
return (WUSBA_SUCCESS);
}
/* Respond client's associate request. */
/* ARGSUSED */
static int
{
char host_path[MAXPATHLEN];
/* get associate request */
/* LINTED E_BAD_PTR_CAST_ALIGN */
/* check if host id exist */
wusbd_warn("wusbd_do_association:asso_ctrl.host = %d err = %s",
goto done;
}
wusbd_warn("wusbd_do_association:host = %d not attached",
goto done;
}
/* check if it is cable device */
wusbd_warn("wusbd_do_association: asso_ctrl.type = %d",
goto done;
}
/* do assocation now */
wusbd_warn("wusbd_do_association: wusbd_do_ca failed");
goto done;
}
done:
return (rval);
}
/* Respond client's remove-dev request. */
/* ARGSUSED */
static int
{
/* LINTED E_BAD_PTR_CAST_ALIGN */
/* LINTED E_BAD_PTR_CAST_ALIGN */
wusbd_warn("wusbd_do_remove_dev: dev-id = %d.%d failed",
goto done;
}
/* remove only one device */
wusbd_warn("wusbd_do_remove_dev: dev-id = %d.%d failed",
goto done;
}
} else {
/* remove all the device associated to the host */
wusbd_warn("wusbd_do_remove_dev: host-id = %d failed",
goto done;
}
}
if (update_cc_file() < 0) {
wusbd_warn("wusbd_do_remove_dev: update cc file failed");
goto done;
}
done:
return (rval);
}
/* Respond client's remove-host request. */
/* ARGSUSED */
static int
{
char host_path[MAXPATHLEN];
/* LINTED E_BAD_PTR_CAST_ALIGN */
/* LINTED E_BAD_PTR_CAST_ALIGN */
wusbd_warn("wusbd_do_remove_host :host_ctrl->host = %d failed",
goto done;
}
wusbd_warn("wusbd_do_remove_host :host_ctrl->host = %d failed",
goto done;
}
wusbd_warn("wusbd_do_host:host_ctrl->host = %d not attached",
} else {
/*
* Stop host if possible, if the host can not
* be stoped we just remove the host cc from
* system, this means the host should be re-plugged
* before any new association since the CHID info is
* gone.
*/
wusbd_warn("wusbd_do_remove_host: host_path = %s",
}
}
/* remove the last CC for host */
if (update_cc_file() < 0) {
wusbd_warn("wusbd_do_remove_host: update cc failed");
goto done;
}
wusbd_info("wusbd_do_remove_host complete ");
done:
return (rval);
}
/* Respond client's enable-host request. */
static int
{
return (WUSBA_SUCCESS);
}
/* Respond client's disable-host request. */
static int
{
return (WUSBA_SUCCESS);
}
/*
* wusbd_do_host is the only wrapper for any host related cmds.
* It will call door_return, so it will
* not return and its return val should be omitted by callers
*/
/* ARGSUSED */
static int
{
char host_path[MAXPATHLEN];
/* LINTED E_BAD_PTR_CAST_ALIGN */
/* LINTED E_BAD_PTR_CAST_ALIGN */
wusbd_warn("wusbd_do_host: host-id = %d failed",
goto done;
}
wusbd_warn("wusbd_do_host:host_ctrl->host = %d not attached",
goto done;
}
if (!flag) {
wusbd_warn("wusbd_do_host: host_path = %s stop failed",
goto done;
}
} else {
/* start the host */
if (start_host(host_path) < 0) {
wusbd_warn("wusbd_do_host: host = %s start failed",
goto done;
}
}
done:
return (rval);
}
/*
* door server handler
* Do not allocate memory dynamically in this function. Upon
* door_return(), the server is blocked in the kernel context. No
* place to free that memory. see
*/
/* ARGSUSED */
static void
{
/* check if it is an valid wusb door call */
wusbd_warn("door_srv: argp = 0x%p arg_size = %d",
goto fail;
}
/* LINTED E_BAD_PTR_CAST_ALIGN */
wusbd_warn("door_srv: dcall->cmdss = %d",
goto fail;
}
/* chk auths should be done first for any cmd */
wusbd_warn("door_srv: cmdss = %d, auth = %s",
goto fail;
}
/*
* Any wusbd_do_xx will return the door service
*/
return;
fail:
}
/*
* Check the status of every CC. And update it in the list so that
* client can know if it's connected/disconnected.
*/
static void
update_cc_list(const char *host)
{
int hostid = 0;
int hstate = -1;
int fd = -1;
int i;
return;
}
return;
}
wusbd_warn("update_cc_list: host = %s, err = %s",
return;
}
/* update host states */
wusbd_warn("update_cc_list: WUSB_HC_GET_HSTATE, err = %s",
return;
}
for (i = 1; i < DEV_MAX; i++) {
continue;
}
}
wusbd_info("update_cc_list: type = %s, state = %d",
}
}
}
/* find the host cc infor with host id */
static wusb_cc_info_t *
{
return (NULL);
}
}
/* find the device CDID with host id */
static wusb_cc_info_t *
{
int j = 0;
for (j = 1; j < DEV_MAX; j++) {
}
}
return (NULL);
}
/* find the host id with mac address */
static int
{
int i = 0;
for (i = 1; i < HOST_MAX; i++) {
return (i);
}
}
return (0);
}
static int
{
int ccfd = -1;
wusbd_warn("update_cc_file: CC store file = %s, %s",
return (WUSBA_FAILURE);
}
return (WUSBA_SUCCESS);
}
/*
* ca_****: Cable Assocation helpers
* to setup an association for host and device
*/
static int
{
wusbd_warn("ca_get_info: CBAF_IOCTL_GET_ASSO_INFO: err = %s",
return (WUSBA_FAILURE);
}
return (WUSBA_SUCCESS);
}
static int
{
wusbd_warn("ca_set_host: CBAF_IOCTL_SET_HOST_INFO: err = %s",
return (WUSBA_FAILURE);
}
return (WUSBA_SUCCESS);
}
static int
{
void *ca_buf;
wusbd_info("ca_get_req: NumAssociates = %d",
wusbd_warn("ca_get_req: ca_buf = NULL");
return (WUSBA_FAILURE);
}
wusbd_warn("ca_get_req: CBAF_IOCTL_GET_ASSO_REQS: err = %s",
return (WUSBA_FAILURE);
}
/* currently not used */
return (WUSBA_SUCCESS);
}
static int
{
wusbd_warn("ca_get_dev failed");
return (WUSBA_FAILURE);
}
wusbd_info("ca_get_devinfo: DeviceFriendlyName = %s",
wusbd_info("ca_get_devinfo: bandgroup = %d",
wusbd_info("ca_get_devinfo: LangID = %d",
return (WUSBA_SUCCESS);
}
static int
{
wusbd_warn("ca_connect_cc: CBAF_IOCTL_SET_CONNECTION: err = %s",
return (WUSBA_FAILURE);
}
return (WUSBA_SUCCESS);
}
static int
{
wusbd_warn("ca_create_cc: generate cc failed!");
return (WUSBA_FAILURE);
}
return (WUSBA_SUCCESS);
}
static int
{
int fd = -1;
int hstate = -1;
wusbd_warn("ca_add_cc: filename = %s, err = %s",
return (WUSBA_FAILURE);
}
wusbd_warn("ca_add_cc: ioctl = WUSB_HC_ADD_CC, err = %s",
goto fail;
}
wusbd_warn("ca_add_cc: ioctl = WUSB_HC_GET_HSTATE, err = %s",
goto fail;
}
if (hstate != WUSB_HC_STARTED) {
wusbd_warn("ca_add_cc: ioctl = WUSB_HC_START, err = %s",
goto fail;
}
}
return (WUSBA_SUCCESS);
fail:
return (WUSBA_FAILURE);
}
static int
{
return (WUSBA_FAILURE);
}
wusbd_warn("ca_save_cc: save cc failed");
return (WUSBA_FAILURE);
}
return (WUSBA_SUCCESS);
}
static int
{
int fd;
wusbd_info("wusbd_do_ca start\n");
/* IMPORTANT: Do NOT open it with O_RDWR */
if (fd == -1) {
return (WUSBA_FAILURE);
}
/*
* The first parts to set up a cable associaiton.
* Refer to: [Association Models Supplement to the
* Certified Wireless Universal Serial Bus Specification]
* chapter 4.
*
* 1. Send GET_ASSOCIATION_INFORMATION to the cable device
* and get the number of association requests.
*
* 2. Send GET_ASSOCIATION_INFORMATION again to get the
* all the association requests.
*
* 3. Send SET_ASSOCIATION_RESPONSE with the host CHID
*
* 4. Send GET_ASSOCIATION_REQUEST to get the exisiting CC
* infor from the device.
*
*/
wusbd_warn("wusbd_do_ca: get asso info failed!");
goto cleanup;
}
wusbd_warn("wusbd_do_ca: get asso req failed!");
goto cleanup;
}
wusbd_warn("wusbd_do_ca: set host info failred");
goto cleanup;
}
wusbd_warn("wusbd_do_ca: get device infor failed");
goto cleanup;
}
/*
* The second part to setup cable association.
*
* 1. Create a CC from exsiting host_cc for the devices
*
* 2. Send new cc to the cable device to save in its hardware
*
* 3. Add new cc to the host controller
*
* 4. Save the cc to the cc list and cc store file
*
* Done!
*/
wusbd_warn("wusbd_do_ca: ca create cc failed!");
goto cleanup;
}
/*
* Check if CDID exist in the host cc list, if so, We need to update
* the exisiting cc infor with a new ck, do the association with the
* updated cc.
* See "Association Models Supplement to the WUSB Specification"
* Chapter 4
*/
if (old_cc) {
wusbd_warn("wusbd_do_ca: Association exist, use old CDID");
/* update old cc with the new ck and copy back */
}
wusbd_warn("wusbd_do_ca: ca connect cc failed!");
goto cleanup;
}
wusbd_warn("wusbd_do_ca: ca add cc failed!");
return (WUSBA_FAILURE);
}
if (!old_cc) {
/* a new cc save to file */
wusbd_warn("wusbd_do_ca: ca save cc failed!");
return (WUSBA_FAILURE);
}
} else {
/* Just update the cc file */
if (update_cc_file() < 0) {
wusbd_warn("wusbd_do_ca: update old cc failed");
return (WUSBA_FAILURE);
}
}
wusbd_info("wusbd_do_ca: Set cable connection complete!");
return (WUSBA_SUCCESS);
return (WUSBA_FAILURE);
}
/*
* wusb cc infor generation helpers
* generate_wusb_CC: Generate CC infor for a device and host
* generate_wusb_CHID: Generate CHID for a host
* generate_wusb_CDID: Generate CDID for a device
* generate_wusb_CK : Generate CK for an assocation
*/
static int
{
int rval = WUSBA_SUCCESS;
wusbd_info("generate_wusb_CC: start");
wusbd_warn("generate_wusb_CC: Crypto init failed");
return (WUSBA_FAILURE);
}
wusbd_warn("generate_wusb_CC: crate cdid failed");
goto done;
}
wusbd_warn("generate_wusb_CC: crate ck failed");
goto done;
}
done:
wusbd_info("generate_wusb_CC: complete");
return (rval);
}
static int
{
/*
* CHID construction :
* 0 - 5 : MAC serial
* 6 - 7 : arbitrary
* 8 - 15 : random from seed = (MAC..) || (hostid||time)) || hrtime
*/
int rval = WUSBA_SUCCESS;
wusbd_info("generate_wusb_CHID: start");
wusbd_warn("generate_wusb_CHID: Crypto init failed");
goto done;
}
p += 8;
wusbd_warn("generate_wusb_CHID: random failed");
}
wusbd_info("generate_wusb_CHID complete");
done:
return (rval);
}
static int
{
/* TODO : need better generation mechanism */
}
static int
{
/* TODO : need better generation mechanism */
}
/* Log to dmesg and smf log */
static void
wusbd_warn(const char *format, ...)
{
}
static void
{
}
/* Log to smf log in DEBUG version */
/* ARGSUSED */
static void
wusbd_info(const char *format, ...)
{
#ifdef DEBUG
#endif
}
/*
* Find an unused host id and return it.
* The wusbadm use two digits to represent a host. This means
* hostid can't be greater than 99.
*/
static uint8_t
assign_host_id(void)
{
uint8_t i;
for (i = 1; i < HOST_MAX; i++) {
if (devids[i][0] == 0) {
wusbd_info("assign_host_id: rval = %d", i);
return (i);
}
}
return (0); /* illegal value */
}
/*
* traverse the CC store, search in the specified host,
* find an unused device id, return it.
* The wusbadm use 3 digits to represent a device. This means
* devid can't be greater than 999.
*/
static uint16_t
{
uint16_t i;
return (0);
}
for (i = 1; i < DEV_MAX; i++) {
return (i);
}
}
return (0); /* illegal value */
}
/* Release a dev id, eg: remove dev */
static void
{
return;
}
}
/*
* init_door_srv.
* Create the door file and attach door service
* to the door file
*/
static int
{
wusbd_warn("init_door_srv: door_creat: err = %s",
goto fail;
}
wusbd_warn("init_door_srv: creat: err = %s",
goto fail;
}
wusbd_warn("init_door_srv: fattach err = %s",
goto fail;
}
return (WUSBA_SUCCESS);
fail:
return (WUSBA_FAILURE);
}
/* Print a cc list entry */
/* ARGSUSED */
static int
{
return (WUSBA_SUCCESS);
}
/* write a cc list entry back to file fd */
static int
{
wusbd_info("write_cc_list: host-id = %d dev-id = %d",
return (WUSBA_SUCCESS);
}
sizeof (wusb_cc_info_t)) {
wusbd_warn("write_cc_list: write err = %s ",
return (WUSBA_FAILURE);
}
return (WUSBA_SUCCESS);
}
/* clean up the status of the cc list entry */
/* ARGSUSED */
static int
{
return (WUSBA_SUCCESS);
}
/* copy a cc list entry to a device info buffer */
static int
{
*buf += sizeof (wusb_device_info_t);
return (WUSBA_SUCCESS);
}
/* save cc to list and file */
static int
{
/* save CC to file */
if (save_cc_to_store(ccinfo) < 0) {
wusbd_warn("save_cc: Failed to save CC to file");
return (WUSBA_FAILURE);
}
/* save cc to global list */
if (save_cc_to_list(ccinfo) < 0) {
wusbd_warn("save_cc: Failed to save CC to list");
return (WUSBA_FAILURE);
}
return (WUSBA_SUCCESS);
}
/* create cc list entry and add to global list */
static int
{
wusbd_warn("save_cc_to_list: newlist = NULL");
return (WUSBA_FAILURE);
}
return (WUSBA_SUCCESS);
}
/* save cc info to the host */
static int
{
int rval = WUSBA_FAILURE;
int ccfd = -1;
/*
* If a device association is just used for one time
* we will not save it to the store file. See wusbadm(1)
*/
return (WUSBA_SUCCESS);
}
/* open cc file */
wusbd_warn("save_cc_to_store:CC file = %s, err = %s",
goto done;
}
/* seek to the end of the file */
wusbd_warn("save_cc_to_store: seek fail err = %s",
goto done;
}
/* save ccinfo to cc file */
sizeof (wusb_cc_info_t)) {
wusbd_warn("write to store fail: %s - %d",
goto done;
}
done:
wusbd_info("save_cc_to_store: complete");
return (rval);
}
/*
* load all the cc to the host controller
* 1. walk thru the cc list and find the device cc info
* related to this host.
* 2. add the cc to the host controller
* 3. start the host controller
*/
static int
{
int fd = -1;
int j = 0;
/* open host file */
wusbd_warn("add_all_cc_to_host: host = %s err = %s",
return (WUSBA_FAILURE);
}
/* Find all the device cc and add cc to host controler */
for (j = 0; j < DEV_MAX; j++) {
continue;
}
wusbd_warn(" add_all_cc_to_host: ioctl = WUSB_HC_ADD_CC"
"hostid = %d, fail ", hostid);
return (WUSBA_FAILURE);
}
}
wusbd_info("add_all_cc_to_host complete");
return (WUSBA_SUCCESS);
}
/* Remove all the cc infor from a host device */
static int
{
int fd = -1;
int rval = 0;
char host_path[MAXPATHLEN];
wusbd_warn("remove_all_cc_from_host:hostid = %d not attached",
hostid);
return (WUSBA_FAILURE);
}
wusbd_warn("remove_all_cc_from host: host = %s err = %s",
return (WUSBA_FAILURE);
}
if (rval < 0) {
wusbd_warn("remove_all_cc_from_host: WUSB_HC_STOP: err = %s",
return (WUSBA_FAILURE);
}
return (WUSBA_SUCCESS);
}
/*
* Initialize the global cc list from the store file
* set in the global devids
*/
static int
init_global_cc_list(void)
{
int ccfd = -1;
/*
* open the cc file. when daemon starts for the first time
* and device Conection Context informaion is stored in this
* file. global cc list is the map in the dameon for the
* file.
*/
wusbd_warn("init_global_cc_list: CC store file = %s, err = %s",
goto fail;
}
/* initialize globle cc list from cc file */
wusbd_warn("init_global_cc_list: list = NULL");
goto fail;
}
/* set devids */
/* add the list to the global cc list */
}
return (WUSBA_SUCCESS);
fail:
return (WUSBA_FAILURE);
}
/* destroy the global CC list */
static void
destroy_global_cc_list(void)
{
cc_cnt--;
}
cc_cnt = 0;
}
/*
* Add a new list to the global cc list.
* incremental order.
*/
static void
{
wusbd_info("add_to_global_list: start");
wusbd_info("host-id = %d, dev-id = %d, type = %s",
/* first cc list */
if (global_cclist == NULL) {
goto done;
}
/* new cc list header */
tmp = global_cclist;
goto done;
}
/* find where to insert the new cc */
continue;
}
continue;
}
break;
}
done:
cc_cnt++;
wusbd_info("add_to_global_list: complete");
}
/* Remove a list from the global cc list */
static void
{
wusbd_info("remove_from_global_list: host-id:%d, dev-id:%d, path:%s",
/* first list */
if (global_cclist == list) {
goto found;
}
goto found;
}
}
wusbd_warn("remove_from_global_list: cc not found ");
return;
cc_cnt--;
wusbd_info("remove_from_global_list: complete");
}
/*
* It is useful make a wrapper to work thru each entry in the global
* lists. it is used widely for to travers the whole list
*/
static void
{
while (list) {
break;
}
}
static void
{
wusbd_info("clean_all_cc_list: start");
wusbd_info("clean_all_cc_list: complete");
}
/* Copy the cc list to buffer */
static void
copy_list_back(char *buf)
{
}
static void
{
char filename[MAXPATHLEN];
wusbd_warn("all_hosts_iterate: dir = %s, err = %s",
return;
}
}
}
}
static int
{
char filename[MAXPATHLEN];
int rval = WUSBA_FAILURE;
wusbd_warn("all_hosts_iterate: dir = %s, err = %s",
return (rval);
}
wusbd_warn("get_host_path: host = %s failed",
filename);
continue;
}
filename);
break;
}
}
}
return (rval);
}
/* Check all the host device */
static void
{
wusbd_info("check_all_host :start");
wusbd_info("check_all_host :finished");
}
/* Stop the host device */
static void
{
wusbd_info("stop_all_host :start");
wusbd_info("stop_all_host :finished");
}
/*
* update the cc list information
* stat of the device and host, device nodename
*/
static void
{
wusbd_info("update_all_cc_list :start");
if (global_cclist) {
} else {
wusbd_info("update_all_cc_list :global_cclist = NULL");
}
wusbd_info("update_all_cc_list :complete");
}
/*
* Get credential of the door_call client and check
*/
static int
wusbd_check_auth(const char *auth_str)
{
if (door_ucred(&pcred) < 0) {
return (WUSBA_FAILURE);
}
/* remember to do this */
return (WUSBA_FAILURE);
}
return (WUSBA_SUCCESS);
}
static int
{
int fd = -1;
int rval = WUSBA_FAILURE;
goto done;
}
/* Get the mac address of the host */
wusbd_warn("load_host_mac: WUSB_HC_GET_MAC_ADDR: err = %s",
goto done;
}
done:
wusbd_info("load_host_mac complete");
return (rval);
}
/*
* create host cc
* 1. create the cc for host
* 2. save the cc to list & cc store file
*/
static int
create_host_cc(const char *filename)
{
wusbd_warn("create_host_cc: host = %s, load mac failed",
filename);
return (WUSBA_FAILURE);
}
/* assign CHID */
wusbd_warn("create_host_cc: host = %s, reate chid failed",
filename);
return (WUSBA_FAILURE);
}
/* Todo: only support hwa */
/* don't allocate dev id here , for host, dev id set to 0 */
wusbd_warn("create_host_cc: assign_host_id = 0");
return (WUSBA_FAILURE);
}
/* save cc infor to host and cc file */
wusbd_warn("create_host_cc: save_cc failed");
return (WUSBA_FAILURE);
}
return (WUSBA_SUCCESS);
}
/*
* Add CCs to hosts upon startup
* OR add CCs to the host which is newly hotplugged in
*/
static void
check_host(const char *host)
{
int hostid = 0;
return;
}
wusbd_info("check_host: host = %s host-id = %d found",
/* start the host */
(void) start_host(host);
} else {
/* check host again */
(void) check_host(host);
}
}
}
/*
* Remove one cc from host
* Args:
* hostid - hostid for the cc
* devid - devid for the cc
*/
static int
{
int fd = -1;
char host_path[MAXPATHLEN];
wusbd_warn("remove_cc_from_host:hostid = %d not attached",
hostid);
return (WUSBA_FAILURE);
}
wusbd_warn("remove_cc_from_host: host = %s err = %s",
return (WUSBA_FAILURE);
}
wusbd_warn("remove_cc_from_host: WUSB_HC_REM_CC err = %s",
return (WUSBA_FAILURE);
}
return (WUSBA_SUCCESS);
}
static int
{
int fd = -1;
int hstate = -1;
return (WUSBA_FAILURE);
}
/*
* We'll only send the cmd to stop host while host has already
* need to reset hardware or may cause issue while it it is stopping.
* So just do it at the right time.
*/
wusbd_warn("stop_host: WUSB_HC_GET_HSTATE: err = %s",
goto fail;
}
if (hstate == WUSB_HC_STARTED) {
wusbd_warn("stop_host: WUSB_HC_STOP: err = %s",
goto fail;
}
}
return (WUSBA_SUCCESS);
fail:
return (WUSBA_FAILURE);
}
static int
start_host(const char *host)
{
int fd = -1;
int hstate = -1;
return (WUSBA_FAILURE);
}
/*
* Check if the host is already start. if the host has been started.
* it is not proper to send the start command to the host controller,
* because it may cause some issue for host contoller reset the
* hardware
*/
wusbd_warn("start_host: ioctl = WUSB_HC_GET_HSTATE err = %s",
goto fail;
}
if (hstate != WUSB_HC_STARTED) {
wusbd_warn("start_host: WUSB_HC_START: err = %s",
goto fail;
}
}
wusbd_info("start_host: complete");
return (WUSBA_SUCCESS);
fail:
return (WUSBA_FAILURE);
}
/* Check the args of a dev ctrl door call request */
static uint16_t
{
return (WUSBADM_INVAL_HOSTID);
}
wusbd_warn("check_dev_ctrl: host-id = %02d cc = NULL",
return (WUSBADM_NO_HOST);
}
wusbd_warn("check_dev_ctrl: dev-id = %03d, max: %d",
return (WUSBADM_INVAL_DEVID);
}
wusbd_warn("check_dev_ctl: dev-id = %02d.%03d, cc = NULL",
return (WUSBADM_NO_DEVICE);
}
return (WUSBADM_OK);
}
/* Check the args of a host ctrl door call request */
static uint16_t
{
return (WUSBADM_INVAL_HOSTID);
}
wusbd_warn("check_host_ctrl: host-id = %02d, cc = NULL",
return (WUSBADM_NO_HOST);
}
wusbd_warn("check_host_ctrl: dev-id = %03d no zero",
return (WUSBADM_INVAL_DEVID);
}
return (WUSBADM_OK);
}
/* Remove one dev from the cc list */
static int
{
wusbd_warn("remove_one_dev: hostid = %d, devid = %d"
}
return (WUSBA_SUCCESS);
}
/* Remove all dev from the cc list */
static int
{
int i = 0;
if (remove_all_cc_from_host(hostid) < 0) {
wusbd_warn("remove_all_dev: hostid = %d. remove all cc failed",
hostid);
}
for (i = 1; i < DEV_MAX; i++) {
if (list) {
free_dev_id(hostid, i);
}
}
wusbd_warn("remove_all_dev complete");
return (WUSBA_SUCCESS);
}
static int
{
const char *subclass_list[] = {
0
};
wusbd_warn("init_sys_evnt: sysevent bind handle: err = %s",
goto fail;
}
wusbd_warn("init_sys_evnt: sysevent subscribe: err = %s",
goto fail;
}
return (WUSBA_SUCCESS);
fail:
return (WUSBA_FAILURE);
}
/*
* Only one daemon is running in the system
* Create pid file to save the pid of the daemon
* process, the pid file is also used by svcadm to
* stop the daemon
*/
static int
{
int fd;
char pid[20];
== -1) {
wusbd_warn("dameon is already running! ");
return (WUSBA_FAILURE);
}
/* save pid to the file */
wusbd_warn("write pid file failed! ");
return (WUSBA_FAILURE);
}
return (WUSBA_SUCCESS);
}
static void
exit_clean(int ret)
{
wusbd_warn("Remove door file, pid file");
(void) pthread_mutex_destroy(&mutex_cclock);
closelog();
}
/*
* Refresh daemon. svcadm restart will send a SIGHUP to the daemon
* destroy the cc list and reload it from cc now. Update the status
* of each cc list by checking all the hosts in the system.
*/
/* ARGSUSED */
static void
{
wusbd_info("refresh: daemon is restarting..");
(void) pthread_mutex_lock(&mutex_cclock);
(void) init_global_cc_list();
(void) pthread_mutex_unlock(&mutex_cclock);
wusbd_info("refresh: daemon is ok now");
}
/* update host CC when a wireless host is plugged */
static void
{
wusbd_warn("event_handler: can not get attr list");
return;
}
/* check if the device is host device and update cc list */
char filename[MAXPATHLEN];
(void) pthread_mutex_lock(&mutex_cclock);
(void) pthread_mutex_unlock(&mutex_cclock);
}
}
/* For debug only */
void
{
#ifdef DEBUG
wusbd_info("PRIV_PERMITTED:\n");
wusbd_info("\t%s\n",
}
wusbd_info("PRIV_EFFECTIVE:\n");
wusbd_info("\t%s\n",
}
wusbd_info("PRIV_INHERITABLE:\n");
wusbd_info("\t%s\n",
}
wusbd_info("PRIV_LIMIT:\n");
wusbd_info("\t%s\n",
}
#endif
}
/* wusb daemon init */
static int
{
int rc;
/*
* Remove all the privs not needed for the daemon.
* PRIV_SYS_MOUNT: requred by starting door serv.
* PRIV_FILE_DAC_WRITE: requred by attach door file.
* PRIV_SYS_CONFIG, required by register sys event.
* PRIV_SYS_DEVICES, required by driver ioctl.
*/
0, 0,
NULL);
if (rc != 0) {
wusbd_warn("insufficient privileges");
}
/*
* Block all signals prior to the fork and leave them blocked in the
* parent so we don't get in a situation where the parent gets SIGINT
* and returns non-zero exit status and the child is actually running.
* In the child, restore the signal mask once we've done our setsid().
*/
(void) sigfillset(&set);
wusbd_warn("unable to create pipe");
closelog();
}
closelog();
wusbd_warn("unable to fork");
closelog();
}
/*
* If we're the parent process, wait for either the child to send us
* the appropriate exit status over the pipe or for the read to fail
* (presumably with 0 for EOF if our child terminated abnormally).
* If the read fails, exit with either the child's exit status if it
* exited or with SMF_EXIT_ERR_FATAL if it died from a fatal signal.
*/
if (pid != 0) {
}
(void) setsid();
(void) chdir("/");
(void) umask(022);
return (pfds[1]);
}
/* wusb daemon fini */
static void
{
/*
* Now that we're running, if a pipe fd was specified, write an exit
* status to it to indicate that our parent process can safely detach.
* Then proceed to loading the remaining non-built-in modules.
*/
if (fd >= 0) {
}
#if 0
/* Leave the stderr for smf log */
#endif
}
/* Remove all the privs not needed. leave SYS_DEVICE only */
(char *)NULL);
print_prv();
}
/* Each door call handler should get the lock */
static void
{
wusbd_info("wusbd_daemon_enter: enter");
(void) pthread_mutex_lock(&mutex_cclock);
}
/* Each door call handler should release the lock */
static void
{
wusbd_info("wusbd_daemon_leave");
(void) pthread_mutex_unlock(&mutex_cclock);
}