#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <libgen.h>
#include <fcntl.h>
#include <stddef.h>
#include <signal.h>
#include <port.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/note.h>
#include <sys/resource.h>
#include <unistd.h>
#include <sys/socket.h>
#include <errno.h>
#include <ucred.h>
#include <priv_utils.h>
#include <net/if.h>
#include <libilb.h>
#include <assert.h>
#include <inet/ilb.h>
#include <libintl.h>
#include <fcntl.h>
#include <rpcsvc/daemon_utils.h>
#include "libilb_impl.h"
#include "ilbd.h"
#define ILBD_VERSION "1.0"
#define ILBD_COPYRIGHT \
"Copyright (c) 2005, 2010, Oracle and/or its affiliates. " \
"All rights reserved.\n"
static uint32_t reply_buf[ILBD_MSG_SIZE / sizeof (uint32_t)];
static void
ilbd_free_cli(ilbd_client_t *cli)
{
(void) close(cli->cli_sd);
if (cli->cli_cmd == ILBD_SHOW_NAT)
ilbd_show_nat_cleanup();
if (cli->cli_cmd == ILBD_SHOW_PERSIST)
ilbd_show_sticky_cleanup();
if (cli->cli_saved_reply != NULL)
free(cli->cli_saved_reply);
if (cli->cli_peer_ucredp != NULL)
ucred_free(cli->cli_peer_ucredp);
free(cli->cli_pw_buf);
free(cli);
}
static void
ilbd_reset_kernel_state(void)
{
ilb_status_t rc;
ilb_name_cmd_t kcmd;
kcmd.cmd = ILB_DESTROY_RULE;
kcmd.flags = ILB_RULE_ALLRULES;
kcmd.name[0] = '\0';
rc = do_ioctl(&kcmd, 0);
if (rc != ILB_STATUS_OK)
logdebug("ilbd_reset_kernel_state: do_ioctl failed: %s",
strerror(errno));
}
static void
ilbd_cleanup(int sig)
{
(void) remove(SOCKET_PATH);
ilbd_reset_kernel_state();
exit(0);
}
static int
ilbd_create_client_socket(void)
{
int s;
mode_t omask;
struct sockaddr_un sa;
int sobufsz;
s = socket(PF_UNIX, SOCK_SEQPACKET, 0);
if (s == -1) {
perror("ilbd_create_client_socket: socket to"
" client failed");
exit(errno);
}
if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
perror("ilbd_create_client_socket: fcntl(FD_CLOEXEC)");
exit(errno);
}
sobufsz = ILBD_MSG_SIZE;
if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sobufsz,
sizeof (sobufsz)) != 0) {
perror("ilbd_creat_client_socket: setsockopt(SO_SNDBUF) "
"failed");
exit(errno);
}
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &sobufsz,
sizeof (sobufsz)) != 0) {
perror("ilbd_creat_client_socket: setsockopt(SO_RCVBUF) "
"failed");
exit(errno);
}
omask = umask(0);
(void) remove(SOCKET_PATH);
bzero(&sa, sizeof (sa));
sa.sun_family = AF_UNIX;
(void) strlcpy(sa.sun_path, SOCKET_PATH, sizeof (sa.sun_path));
if (bind(s, (struct sockaddr *)&sa, sizeof (sa)) != 0) {
perror("ilbd_create_client_socket(): bind to client"
" socket failed");
exit(errno);
}
(void) umask(omask);
#define QLEN 16
if (listen(s, QLEN) != 0) {
perror("ilbd_create_client_socket: listen to client"
" socket failed");
exit(errno);
}
(void) signal(SIGHUP, SIG_IGN);
(void) signal(SIGPIPE, SIG_IGN);
(void) signal(SIGSTOP, SIG_IGN);
(void) signal(SIGTSTP, SIG_IGN);
(void) signal(SIGTTIN, SIG_IGN);
(void) signal(SIGTTOU, SIG_IGN);
(void) signal(SIGINT, ilbd_cleanup);
(void) signal(SIGTERM, ilbd_cleanup);
(void) signal(SIGQUIT, ilbd_cleanup);
return (s);
}
static size_t
ilbd_cmd_size(const ilb_comm_t *ic)
{
size_t cmd_sz;
cmd_sz = sizeof (*ic);
switch (ic->ic_cmd) {
case ILBD_RETRIEVE_SG_NAMES:
case ILBD_RETRIEVE_RULE_NAMES:
case ILBD_RETRIEVE_HC_NAMES:
case ILBD_CMD_OK:
break;
case ILBD_CMD_ERROR:
cmd_sz += sizeof (ilb_status_t);
break;
case ILBD_RETRIEVE_SG_HOSTS:
case ILBD_CREATE_SERVERGROUP:
case ILBD_DESTROY_SERVERGROUP:
case ILBD_DESTROY_RULE:
case ILBD_ENABLE_RULE:
case ILBD_DISABLE_RULE:
case ILBD_RETRIEVE_RULE:
case ILBD_DESTROY_HC:
case ILBD_GET_HC_INFO:
case ILBD_GET_HC_SRVS:
cmd_sz += sizeof (ilbd_name_t);
break;
case ILBD_ENABLE_SERVER:
case ILBD_DISABLE_SERVER:
case ILBD_ADD_SERVER_TO_GROUP:
case ILBD_REM_SERVER_FROM_GROUP:
cmd_sz += sizeof (ilb_sg_info_t);
break;
case ILBD_SRV_ADDR2ID:
case ILBD_SRV_ID2ADDR:
cmd_sz += sizeof (ilb_sg_info_t) + sizeof (ilb_sg_srv_t);
break;
case ILBD_CREATE_RULE:
cmd_sz += sizeof (ilb_rule_info_t);
break;
case ILBD_CREATE_HC:
cmd_sz += sizeof (ilb_hc_info_t);
break;
case ILBD_SHOW_NAT:
case ILBD_SHOW_PERSIST:
cmd_sz += sizeof (ilb_show_info_t);
break;
}
return (cmd_sz);
}
static ilb_status_t
ilbd_check_req_size(ilb_comm_t *ic, size_t ic_sz)
{
ilb_status_t rc = ILB_STATUS_OK;
ilb_sg_info_t *sg_info;
ilbd_namelist_t *nlist;
switch (ic->ic_cmd) {
case ILBD_CREATE_SERVERGROUP:
case ILBD_ENABLE_SERVER:
case ILBD_DISABLE_SERVER:
case ILBD_ADD_SERVER_TO_GROUP:
case ILBD_REM_SERVER_FROM_GROUP:
sg_info = (ilb_sg_info_t *)&ic->ic_data;
if (ic_sz < ilbd_cmd_size(ic) + sg_info->sg_srvcount *
sizeof (ilb_sg_srv_t)) {
rc = ILB_STATUS_EINVAL;
}
break;
case ILBD_ENABLE_RULE:
case ILBD_DISABLE_RULE:
case ILBD_DESTROY_RULE:
nlist = (ilbd_namelist_t *)&ic->ic_data;
if (ic_sz < ilbd_cmd_size(ic) + nlist->ilbl_count *
sizeof (ilbd_name_t)) {
rc = ILB_STATUS_EINVAL;
}
break;
}
return (rc);
}
static ilb_status_t
consume_common_struct(ilb_comm_t *ic, size_t ic_sz, ilbd_client_t *cli,
int ev_port)
{
ilb_status_t rc;
struct passwd *ps;
size_t rbufsz;
ssize_t ret;
boolean_t standard_reply = B_TRUE;
ilbd_name_t name;
cli->cli_ev = ILBD_EVENT_REQ;
ps = &cli->cli_pw;
rbufsz = ILBD_MSG_SIZE;
if (ic_sz < ilbd_cmd_size(ic)) {
rc = ILB_STATUS_EINVAL;
goto out;
}
switch (ic->ic_cmd) {
case ILBD_CREATE_SERVERGROUP: {
ilb_sg_info_t sg_info;
(void) strlcpy(sg_info.sg_name, (char *)&(ic->ic_data),
sizeof (sg_info.sg_name));
rc = ilbd_create_sg(&sg_info, ev_port, ps,
cli->cli_peer_ucredp);
break;
}
case ILBD_DESTROY_SERVERGROUP:
(void) strlcpy(name, (char *)&(ic->ic_data), sizeof (name));
rc = ilbd_destroy_sg(name, ps, cli->cli_peer_ucredp);
break;
case ILBD_ADD_SERVER_TO_GROUP:
if ((rc = ilbd_check_req_size(ic, ic_sz)) != ILB_STATUS_OK)
break;
rc = ilbd_add_server_to_group((ilb_sg_info_t *)&ic->ic_data,
ev_port, ps, cli->cli_peer_ucredp);
break;
case ILBD_REM_SERVER_FROM_GROUP:
if ((rc = ilbd_check_req_size(ic, ic_sz)) != ILB_STATUS_OK)
break;
rc = ilbd_rem_server_from_group((ilb_sg_info_t *)&ic->ic_data,
ev_port, ps, cli->cli_peer_ucredp);
break;
case ILBD_ENABLE_SERVER:
if ((rc = ilbd_check_req_size(ic, ic_sz)) != ILB_STATUS_OK)
break;
rc = ilbd_enable_server((ilb_sg_info_t *)&ic->ic_data, ps,
cli->cli_peer_ucredp);
break;
case ILBD_DISABLE_SERVER:
if ((rc = ilbd_check_req_size(ic, ic_sz)) != ILB_STATUS_OK)
break;
rc = ilbd_disable_server((ilb_sg_info_t *)&ic->ic_data, ps,
cli->cli_peer_ucredp);
break;
case ILBD_SRV_ADDR2ID:
rc = ilbd_address_to_srvID((ilb_sg_info_t *)&ic->ic_data,
reply_buf, &rbufsz);
if (rc == ILB_STATUS_OK)
standard_reply = B_FALSE;
break;
case ILBD_SRV_ID2ADDR:
rc = ilbd_srvID_to_address((ilb_sg_info_t *)&ic->ic_data,
reply_buf, &rbufsz);
if (rc == ILB_STATUS_OK)
standard_reply = B_FALSE;
break;
case ILBD_RETRIEVE_SG_HOSTS:
(void) strlcpy(name, (char *)&(ic->ic_data), sizeof (name));
rc = ilbd_retrieve_sg_hosts(name, reply_buf, &rbufsz);
if (rc == ILB_STATUS_OK)
standard_reply = B_FALSE;
break;
case ILBD_RETRIEVE_SG_NAMES:
case ILBD_RETRIEVE_RULE_NAMES:
case ILBD_RETRIEVE_HC_NAMES:
rc = ilbd_retrieve_names(ic->ic_cmd, reply_buf, &rbufsz);
if (rc == ILB_STATUS_OK)
standard_reply = B_FALSE;
break;
case ILBD_CREATE_RULE:
rc = ilbd_create_rule((ilb_rule_info_t *)&ic->ic_data, ev_port,
ps, cli->cli_peer_ucredp);
break;
case ILBD_DESTROY_RULE:
(void) strlcpy(name, (char *)&(ic->ic_data), sizeof (name));
rc = ilbd_destroy_rule(name, ps, cli->cli_peer_ucredp);
break;
case ILBD_ENABLE_RULE:
(void) strlcpy(name, (char *)&(ic->ic_data), sizeof (name));
rc = ilbd_enable_rule(name, ps, cli->cli_peer_ucredp);
break;
case ILBD_DISABLE_RULE:
(void) strlcpy(name, (char *)&(ic->ic_data), sizeof (name));
rc = ilbd_disable_rule(name, ps, cli->cli_peer_ucredp);
break;
case ILBD_RETRIEVE_RULE:
(void) strlcpy(name, (char *)&(ic->ic_data), sizeof (name));
rc = ilbd_retrieve_rule(name, reply_buf, &rbufsz);
if (rc == ILB_STATUS_OK)
standard_reply = B_FALSE;
break;
case ILBD_CREATE_HC:
rc = ilbd_create_hc((ilb_hc_info_t *)&ic->ic_data, ev_port, ps,
cli->cli_peer_ucredp);
break;
case ILBD_DESTROY_HC:
(void) strlcpy(name, (char *)&(ic->ic_data), sizeof (name));
rc = ilbd_destroy_hc(name, ps, cli->cli_peer_ucredp);
break;
case ILBD_GET_HC_INFO:
(void) strlcpy(name, (char *)&(ic->ic_data), sizeof (name));
rc = ilbd_get_hc_info(name, reply_buf, &rbufsz);
if (rc == ILB_STATUS_OK)
standard_reply = B_FALSE;
break;
case ILBD_GET_HC_SRVS:
(void) strlcpy(name, (char *)&(ic->ic_data), sizeof (name));
rc = ilbd_get_hc_srvs(name, reply_buf, &rbufsz);
if (rc == ILB_STATUS_OK)
standard_reply = B_FALSE;
break;
case ILBD_SHOW_NAT:
rc = ilbd_show_nat(cli, ic, reply_buf, &rbufsz);
if (rc == ILB_STATUS_OK)
standard_reply = B_FALSE;
break;
case ILBD_SHOW_PERSIST:
rc = ilbd_show_sticky(cli, ic, reply_buf, &rbufsz);
if (rc == ILB_STATUS_OK)
standard_reply = B_FALSE;
break;
default:
logdebug("consume_common_struct: unknown command");
rc = ILB_STATUS_INVAL_CMD;
break;
}
out:
if (standard_reply) {
if (rc == ILB_STATUS_OK)
ilbd_reply_ok(reply_buf, &rbufsz);
else
ilbd_reply_err(reply_buf, &rbufsz, rc);
}
if ((ret = send(cli->cli_sd, reply_buf, rbufsz, 0)) != rbufsz) {
if (ret == -1) {
if (errno != EWOULDBLOCK) {
logdebug("consume_common_struct: send: %s",
strerror(errno));
rc = ILB_STATUS_SEND;
goto err_out;
}
assert(cli->cli_saved_reply == NULL);
if ((cli->cli_saved_reply = malloc(rbufsz)) == NULL) {
logdebug("consume_common_struct: failure to "
"allocate memory to save reply");
rc = ILB_STATUS_SEND;
goto err_out;
}
bcopy(reply_buf, cli->cli_saved_reply, rbufsz);
cli->cli_saved_size = rbufsz;
return (ILB_STATUS_EWOULDBLOCK);
}
}
err_out:
return (rc);
}
static void
new_req(int ev_port, int listener, void *ev_obj)
{
struct sockaddr sa;
int sa_len;
int new_sd;
int sflags;
ilbd_client_t *cli = NULL;
int res;
uid_t uid;
sa_len = sizeof (sa);
if ((new_sd = accept(listener, &sa, &sa_len)) == -1) {
if (errno != EINTR && errno != EMFILE)
logperror("new_req: accept failed");
goto done;
}
if ((sflags = fcntl(new_sd, F_GETFL, 0)) == -1) {
logperror("new_req: fcntl(F_GETFL)");
goto clean_up;
}
if (fcntl(new_sd, F_SETFL, sflags | O_NONBLOCK) == -1) {
logperror("new_req: fcntl(F_SETFL)");
goto clean_up;
}
if (fcntl(new_sd, F_SETFD, FD_CLOEXEC) == -1) {
logperror("new_req: fcntl(FD_CLOEXEC)");
goto clean_up;
}
if ((cli = calloc(1, sizeof (ilbd_client_t))) == NULL) {
logerr("new_req: malloc(ilbd_client_t)");
goto clean_up;
}
res = getpeerucred(new_sd, &cli->cli_peer_ucredp);
if (res == -1) {
logperror("new_req: getpeerucred failed");
goto clean_up;
}
if ((uid = ucred_getruid(cli->cli_peer_ucredp)) == (uid_t)-1) {
logperror("new_req: ucred_getruid failed");
goto clean_up;
}
cli->cli_pw_bufsz = (size_t)sysconf(_SC_GETPW_R_SIZE_MAX);
if ((cli->cli_pw_buf = malloc(cli->cli_pw_bufsz)) == NULL) {
logerr("new_req: malloc(cli_pw_buf)");
goto clean_up;
}
if (getpwuid_r(uid, &cli->cli_pw, cli->cli_pw_buf,
cli->cli_pw_bufsz) == NULL) {
logperror("new_req: invalid user");
goto clean_up;
}
cli->cli_ev = ILBD_EVENT_REQ;
cli->cli_sd = new_sd;
cli->cli_cmd = ILBD_BAD_CMD;
cli->cli_saved_reply = NULL;
cli->cli_saved_size = 0;
if (port_associate(ev_port, PORT_SOURCE_FD, new_sd, POLLRDNORM,
cli) == -1) {
logperror("new_req: port_associate(cli) failed");
clean_up:
if (cli != NULL) {
if (cli->cli_peer_ucredp != NULL)
ucred_free(cli->cli_peer_ucredp);
free(cli->cli_pw_buf);
free(cli);
}
(void) close(new_sd);
}
done:
if (port_associate(ev_port, PORT_SOURCE_FD, listener, POLLRDNORM,
ev_obj) == -1) {
logperror("new_req: port_associate(listener) failed");
exit(1);
}
}
static void
handle_req(int ev_port, ilbd_event_t event, ilbd_client_t *cli)
{
union {
ilb_comm_t ic;
uint32_t buf[ILBD_MSG_SIZE / sizeof (uint32_t)];
} ic_u;
int rc = ILB_STATUS_OK;
ssize_t r;
if (event == ILBD_EVENT_REQ) {
if (cli->cli_saved_reply != NULL) {
logerr("handle_req: misbehaving client, more than one "
"outstanding request");
rc = ILB_STATUS_INTERNAL;
goto err_out;
}
r = recv(cli->cli_sd, (void *)ic_u.buf, sizeof (ic_u.buf), 0);
if (r < 0) {
if (errno != EINTR) {
logperror("handle_req: read failed");
rc = ILB_STATUS_READ;
goto err_out;
}
goto done;
}
cli->cli_cmd = ic_u.ic.ic_cmd;
rc = consume_common_struct(&ic_u.ic, r, cli, ev_port);
if (rc == ILB_STATUS_EWOULDBLOCK)
goto blocked;
if (rc == ILB_STATUS_SEND)
goto err_out;
} else {
assert(event == ILBD_EVENT_REP_OK);
assert(cli->cli_saved_reply != NULL);
if (send(cli->cli_sd, cli->cli_saved_reply,
cli->cli_saved_size, 0) != cli->cli_saved_size) {
if (errno != EWOULDBLOCK) {
logdebug("handle_req: send: %s",
strerror(errno));
rc = ILB_STATUS_SEND;
goto err_out;
}
goto blocked;
}
free(cli->cli_saved_reply);
cli->cli_saved_reply = NULL;
cli->cli_saved_size = 0;
}
done:
cli->cli_ev = ILBD_EVENT_REQ;
if (port_associate(ev_port, PORT_SOURCE_FD, cli->cli_sd,
POLLRDNORM, cli) == -1) {
logperror("handle_req: port_associate(POLLRDNORM)");
rc = ILB_STATUS_INTERNAL;
goto err_out;
}
return;
blocked:
cli->cli_ev = ILBD_EVENT_REP_OK;
if (port_associate(ev_port, PORT_SOURCE_FD, cli->cli_sd, POLLWRNORM,
cli) == -1) {
logperror("handle_req: port_associate(POLLWRNORM)");
rc = ILB_STATUS_INTERNAL;
goto err_out;
}
return;
err_out:
ilbd_free_cli(cli);
}
static void
i_ilbd_read_config(int ev_port)
{
logdebug("i_ilbd_read_config: port %d", ev_port);
(void) ilbd_walk_sg_pgs(ilbd_create_sg, &ev_port, NULL);
(void) ilbd_walk_hc_pgs(ilbd_create_hc, &ev_port, NULL);
(void) ilbd_walk_rule_pgs(ilbd_create_rule, &ev_port, NULL);
}
static void
main_loop(int listener)
{
port_event_t p_ev;
int ev_port, ev_port_obj;
ilbd_event_obj_t ev_obj;
ilbd_timer_event_obj_t timer_ev_obj;
ev_port = port_create();
if (ev_port == -1) {
logperror("main_loop: port_create failed");
exit(-1);
}
ilbd_hc_timer_init(ev_port, &timer_ev_obj);
ev_obj.ev = ILBD_EVENT_NEW_REQ;
if (port_associate(ev_port, PORT_SOURCE_FD, listener, POLLRDNORM,
&ev_obj) == -1) {
logperror("main_loop: port_associate failed");
exit(1);
}
i_ilbd_read_config(ev_port);
ilbd_hc_timer_update(&timer_ev_obj);
_NOTE(CONSTCOND)
while (B_TRUE) {
int r;
ilbd_event_t event;
ilbd_client_t *cli;
r = port_get(ev_port, &p_ev, NULL);
if (r == -1) {
if (errno == EINTR)
continue;
logperror("main_loop: port_get failed");
break;
}
ev_port_obj = p_ev.portev_object;
event = ((ilbd_event_obj_t *)p_ev.portev_user)->ev;
switch (event) {
case ILBD_EVENT_TIMER:
ilbd_hc_timeout();
break;
case ILBD_EVENT_PROBE:
ilbd_hc_probe_return(ev_port, ev_port_obj,
p_ev.portev_events,
(ilbd_hc_probe_event_t *)p_ev.portev_user);
break;
case ILBD_EVENT_NEW_REQ:
assert(ev_port_obj == listener);
if (p_ev.portev_events & (POLLHUP|POLLERR)) {
logerr("main_loop: listener error");
exit(1);
}
new_req(ev_port, ev_port_obj, &ev_obj);
break;
case ILBD_EVENT_REP_OK:
case ILBD_EVENT_REQ:
cli = (ilbd_client_t *)p_ev.portev_user;
assert(ev_port_obj == cli->cli_sd);
if (p_ev.portev_events & (POLLHUP|POLLERR)) {
ilbd_free_cli(cli);
break;
}
handle_req(ev_port, event, cli);
break;
default:
logerr("main_loop: unknown event %d", event);
exit(EXIT_FAILURE);
break;
}
ilbd_hc_timer_update(&timer_ev_obj);
}
}
static void
i_ilbd_setup_lists(void)
{
i_setup_sg_hlist();
i_setup_rule_hlist();
i_ilbd_setup_hc_list();
}
static void
Usage(char *name)
{
(void) fprintf(stderr, gettext("Usage: %s [-d|--debug]\n"), name);
exit(1);
}
static void
print_version(char *name)
{
(void) printf("%s %s\n", basename(name), ILBD_VERSION);
(void) printf(gettext(ILBD_COPYRIGHT));
exit(0);
}
static void
set_rlim(void)
{
struct rlimit rlp;
if (getrlimit(RLIMIT_NOFILE, &rlp) == -1) {
perror("ilbd: getrlimit");
exit(errno);
}
rlp.rlim_cur = rlp.rlim_max;
if (setrlimit(RLIMIT_NOFILE, &rlp) == -1) {
perror("ilbd: setrlimit");
exit(errno);
}
}
int
main(int argc, char **argv)
{
int s;
int c;
(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
static const char daemon_dir[] = DAEMON_DIR;
(void) textdomain(TEXT_DOMAIN);
while ((c = getopt(argc, argv, ":V?d(debug)")) != -1) {
switch ((char)c) {
case '?': Usage(argv[0]);
break;
case 'V': print_version(argv[0]);
break;
case 'd': ilbd_enable_debug();
break;
default: Usage(argv[0]);
break;
}
}
ilbd_reset_kernel_state();
set_rlim();
if (mkdir(daemon_dir, DAEMON_DIR_MODE) == 0 || errno == EEXIST) {
(void) chmod(daemon_dir, DAEMON_DIR_MODE);
(void) chown(daemon_dir, DAEMON_UID, DAEMON_GID);
} else {
perror("main: mkdir failed");
exit(errno);
}
if (__init_daemon_priv(PU_RESETGROUPS | PU_LIMITPRIVS | PU_INHERITPRIVS,
DAEMON_UID, DAEMON_GID, PRIV_PROC_OWNER, PRIV_PROC_AUDIT,
PRIV_NET_ICMPACCESS, PRIV_SYS_IP_CONFIG, NULL) == -1) {
(void) fprintf(stderr, "Insufficient privileges\n");
exit(EXIT_FAILURE);
}
s = ilbd_create_client_socket();
if (!is_debugging_on()) {
logdebug("daemonizing...");
if (daemon(0, 0) != 0) {
logperror("daemon failed");
exit(EXIT_FAILURE);
}
}
(void) priv_set(PRIV_OFF, PRIV_INHERITABLE, PRIV_PROC_OWNER,
PRIV_PROC_AUDIT, NULL);
if (!is_debugging_on())
openlog("ilbd", LOG_PID, LOG_DAEMON);
i_ilbd_setup_lists();
main_loop(s);
logdebug("main(): terminating");
(void) remove(SOCKET_PATH);
ilbd_reset_kernel_state();
return (0);
}