1
0
Files
2022-09-29 17:59:04 +03:00

1814 lines
44 KiB
C

#ident "$Revision: 1.8 $"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/t6satmp.h>
#include <sys/t6samp.h>
#include <sys/time.h>
#include <sys/capability.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <rpcsvc/ypclnt.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <getopt.h>
#include <netdb.h>
#include "atomic.h"
#include "defaults.h"
#include "debug.h"
#include "client.h"
#include "generic_list.h"
#include "lrep.h"
#include "name.h"
#include "ref.h"
#include "request.h"
#include "server.h"
#include "sem.h"
#include "timer.h"
#include "thread.h"
typedef int so_set[2];
typedef struct timer_client
{
so_set so;
struct sockaddr_in host;
struct sockaddr_in token_server;
satmp_header hdr;
union
{
init_request *irq;
get_tok_request *gtr;
get_attr_request *gar;
void *req;
u_int hid;
} __tc_request;
} timer_client;
#define tc_irq __tc_request.irq
#define tc_gtr __tc_request.gtr
#define tc_gar __tc_request.gar
#define tc_req __tc_request.req
#define tc_hid __tc_request.hid
#define CHECK_BUFLEN(len, max) { \
if ((len) > (max)) { \
return; \
} \
}
#define dgram_max 0x2000
static const int DEMONSO = 0; /* socket for satmpd<->satmpd messages */
static const int KERNSO = 1; /* socket for kernel<->satmpd messages */
static const cap_value_t cap_priv_port[] = {CAP_PRIV_PORT};
static const cap_value_t cap_network_mgt[] = {CAP_NETWORK_MGT};
static const time_t timeout = 3 * USECS_PER_SEC;
static const unsigned int retries = 3;
/*******************************************************************
* PROTOCOL DEBUG ROUTINES
******************************************************************/
static char *
result_text (u_char result)
{
static char *satmp_result_names[] =
{
"SATMP_REPLY_OK",
"SATMP_INVALID_VERSION",
"SATMP_INVALID_GENERATION",
"SATMP_UNSUPPORTED_MESSAGE",
"SATMP_FORMAT_ERROR",
"SATMP_TRANSLATION_ERROR",
"SATMP_NO_DOT",
"SATMP_NO_MAPPING",
"SATMP_INTERNAL_ERROR"
};
if (result <= 7)
return (satmp_result_names[result]);
if (result == 255)
return (satmp_result_names[8]);
return ("Unknown");
}
static char *
message_name (u_char message_number)
{
static char *satmp_message_names[] =
{
"SATMP_FLUSH_REPLY", /* 162 */
"SATMP_GET_ATTR_REQUEST", /* 163 */
"SATMP_GET_ATTR_REPLY", /* 164 */
"SATMP_INIT_REQUEST", /* 165 */
"SATMP_INIT_REPLY", /* 166 */
"SATMP_FLUSH_REMOTE_CACHE", /* 167 */
"SATMP_GET_TOK_REQUEST", /* 173 */
"SATMP_GET_TOK_REPLY", /* 174 */
"SATMP_SEND_INIT_REQUEST", /* 200 */
"SATMP_SEND_GET_ATTR_REQUEST", /* 201 */
"SATMP_SEND_GET_TOK_REQUEST", /* 202 */
"SATMP_SEND_FLUSH_REMOTE_CACHE", /* 203 */
"SATMP_EXIT", /* 204 */
"SATMP_GET_LRTOK_REQUEST", /* 210 */
"SATMP_GET_LRTOK_REPLY", /* 211 */
};
if (message_number >= SATMP_FLUSH_REPLY &&
message_number <= SATMP_FLUSH_REMOTE_CACHE)
return (satmp_message_names[message_number - 162]);
if (message_number >= SATMP_GET_TOK_REQUEST &&
message_number <= SATMP_GET_TOK_REPLY)
return (satmp_message_names[message_number - 173 + 6]);
if (message_number >= SATMP_SEND_INIT_REQUEST &&
message_number <= SATMP_EXIT)
return (satmp_message_names[message_number - 200 + 8]);
if (message_number >= SATMP_GET_LRTOK_REQUEST &&
message_number <= SATMP_GET_LRTOK_REPLY)
return (satmp_message_names[message_number - 210 + 13]);
return ("UNSUPPORTED");
}
/*******************************************************************
* PROTOCOL ROUTINES
******************************************************************/
/*
* this must exactly track copy_from_header()
*/
static size_t
header_size (void)
{
satmp_header *hdr;
return (2 + sizeof (hdr->message_length) + sizeof (hdr->message_esi));
}
static void
copy_from_header (char *bufptr, satmp_header *hdr)
{
u_short t16;
/* message number */
*bufptr++ = hdr->message_number;
/* message status */
*bufptr++ = hdr->message_status;
/* message length */
t16 = htons (hdr->message_length);
memcpy (bufptr, &t16, sizeof (t16));
bufptr += sizeof (t16);
/* extended session identifier */
memcpy (bufptr, &hdr->message_esi, sizeof (hdr->message_esi));
bufptr += sizeof (hdr->message_esi);
}
static char *
copy_to_header (char *bufptr, satmp_header *hdr)
{
u_short t16;
/* message number */
hdr->message_number = *bufptr++;
/* message status */
hdr->message_status = *bufptr++;
/* message length */
memcpy (&t16, bufptr, sizeof (t16));
bufptr += sizeof (t16);
hdr->message_length = ntohs (t16);
/* extended session identifier */
memcpy (&hdr->message_esi, bufptr, sizeof (hdr->message_esi));
bufptr += sizeof (hdr->message_esi);
return (bufptr);
}
static void
send_buffer (int so, void *buf, size_t size, struct sockaddr_in *to)
{
int mlen;
do
{
mlen = sendto (so, buf, size, 0, to, sizeof (*to));
} while (mlen == -1 && errno == EINTR);
if (mlen == -1 && errno != EINTR)
debug_print ("sendto: %s\n", strerror (errno));
}
static void
send_header (int so, struct sockaddr_in *to, satmp_header *hdr)
{
char buf[sizeof (*hdr)], *bufptr = buf + header_size ();
/* request header */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s sent\n", message_name (hdr->message_number));
hdr->message_length = bufptr - buf;
copy_from_header (buf, hdr);
send_buffer (so, buf, bufptr - buf, to);
}
static void
send_init_request (int so, struct sockaddr_in *to, satmp_header *hdr,
init_request *req)
{
char buf[dgram_max], *bufptr = buf;
u_short raf_count, dot_count, t16;
u_int t32;
/* reserve space for header */
bufptr += header_size ();
/* request header */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s sent\n", message_name (hdr->message_number));
/* extended session identifier */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\tesi: 0x%llx\n", hdr->message_esi);
/* hostid */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\thostid: 0x%x\n", req->hostid);
/* copy reply header */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\tgeneration: %u\n", req->generation);
t32 = htonl (req->generation);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
/* version */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\tversion: %hu\n", req->version);
t16 = htons (req->version);
memcpy (bufptr, &t16, sizeof (t16));
bufptr += sizeof (t16);
/* reserved */
*bufptr++ = 0;
/* server state */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\tserver state: %u\n",
(unsigned) req->server_state);
*bufptr++ = req->server_state;
/* token server address */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\ttoken server: %u\n", req->token_server);
t32 = htonl (req->token_server);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
/* backup server address */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\tbackup server: %u\n", req->backup_server);
t32 = htonl (req->backup_server);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
for (raf_count = 0; raf_count < req->format_count; raf_count++)
{
init_request_attr_format *iraf;
iraf = &req->format[raf_count];
/* attribute type */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tattribute: %hu\n", iraf->attribute);
t16 = htons (iraf->attribute);
memcpy (bufptr, &t16, sizeof (t16));
bufptr += sizeof (t16);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* number of DOTS to follow */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tDOT count: %hu\n", iraf->dot_count);
t16 = htons (iraf->dot_count);
memcpy (bufptr, &t16, sizeof (t16));
bufptr += sizeof (t16);
CHECK_BUFLEN (bufptr - buf, dgram_max);
for (dot_count = 0; dot_count < iraf->dot_count; dot_count++)
{
init_request_dot_rep *irdr;
irdr = &iraf->dot[dot_count];
/* weight of this DOT */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\t\tDOT weight: %u\n",
(unsigned) irdr->weight);
*bufptr++ = irdr->weight;
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* network representation flags */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\t\tDOT flags: %u\n",
(unsigned) irdr->flags);
*bufptr++ = irdr->flags;
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* length of DOT name */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\t\tDOT length: %hu\n",
irdr->length);
t16 = htons (irdr->length);
memcpy (bufptr, &t16, sizeof (t16));
bufptr += sizeof (t16);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* the DOT name itself */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\t\tDOT name: %s\n",
irdr->dot_name);
memcpy (bufptr, irdr->dot_name, irdr->length);
bufptr += irdr->length;
CHECK_BUFLEN (bufptr - buf, dgram_max);
}
}
hdr->message_length = bufptr - buf;
copy_from_header (buf, hdr);
send_buffer (so, buf, bufptr - buf, to);
}
static void
send_init_reply (int so, struct sockaddr_in *to, satmp_header *hdr,
init_reply *rep)
{
send_init_request (so, to, hdr, (init_request *) rep);
}
static void
send_get_tok_request (int so, struct sockaddr_in *to, satmp_header *hdr,
get_tok_request *req)
{
char buf[dgram_max], *bufptr = buf;
u_short i;
u_int t32;
/* reserve space for header */
bufptr += header_size ();
/* request header */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s sent\n", message_name (hdr->message_number));
/* copy generation */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\tgeneration: %u\n", req->generation);
t32 = htonl (req->generation);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
for (i = 0; i < req->attr_spec_count; i++)
{
get_tok_request_attr_spec *gtras;
u_short t16;
gtras = &req->attr_spec[i];
/* attribute type */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tattribute: %hu\n", gtras->attribute);
t16 = htons (gtras->attribute);
memcpy (bufptr, &t16, sizeof (t16));
bufptr += sizeof (t16);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* length of network representation */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tnr length: %hu\n", gtras->nr_length);
t16 = htons (gtras->nr_length);
memcpy (bufptr, &t16, sizeof (t16));
bufptr += sizeof (t16);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* mapping identifier */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tmapping identifier: %u\n",
gtras->mid);
t32 = htonl (gtras->mid);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* network representation itself */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tnetwork rep: %s\n", gtras->nr);
memcpy (bufptr, gtras->nr, gtras->nr_length);
bufptr += gtras->nr_length;
CHECK_BUFLEN (bufptr - buf, dgram_max);
}
hdr->message_length = bufptr - buf;
copy_from_header (buf, hdr);
send_buffer (so, buf, bufptr - buf, to);
}
static void
send_get_tok_reply (int so, struct sockaddr_in *to, satmp_header *hdr,
get_tok_reply *rep)
{
char buf[dgram_max], *bufptr = buf;
u_short i;
u_int t32;
/* reserve space for header */
bufptr += header_size ();
/* request header */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s sent\n", message_name (hdr->message_number));
/* extended session identifier */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\tesi: 0x%llx\n", hdr->message_esi);
/* copy generation */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\tgeneration: %u\n", rep->generation);
t32 = htonl (rep->generation);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
for (i = 0; i < rep->token_spec_count; i++)
{
get_tok_reply_token_spec *gtrts;
u_short t16;
gtrts = &rep->token_spec[i];
/* attribute type */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tattribute: %hu\n", gtrts->attribute);
t16 = htons (gtrts->attribute);
memcpy (bufptr, &t16, sizeof (t16));
bufptr += sizeof (t16);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* mapping identifier */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tmapping identifier: %u\n",
gtrts->mid);
t32 = htonl (gtrts->mid);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* token */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\ttoken: 0x%08.8x\n", gtrts->token);
t32 = htonl (gtrts->token);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
CHECK_BUFLEN (bufptr - buf, dgram_max);
}
hdr->message_length = bufptr - buf;
copy_from_header (buf, hdr);
send_buffer (so, buf, bufptr - buf, to);
}
static void
send_get_attr_request (int so, struct sockaddr_in *to, satmp_header *hdr,
get_attr_request *req)
{
char buf[dgram_max], *bufptr = buf;
u_short i;
u_int t32;
/* reserve space for header */
bufptr += header_size ();
/* request header */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s sent\n", message_name (hdr->message_number));
/* copy generation */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\tgeneration: %u\n", req->generation);
t32 = htonl (req->generation);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
/* copy requests */
for (i = 0; i < req->token_spec_count; i++)
{
get_attr_request_token_spec *garts;
u_short t16;
garts = &req->token_spec[i];
/* attribute type */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tattribute: %hu\n", garts->attribute);
t16 = htons (garts->attribute);
memcpy (bufptr, &t16, sizeof (t16));
bufptr += sizeof (t16);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* mid */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tmapping identifier: %u\n",
(unsigned) 0);
t32 = 0;
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* token */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\ttoken: 0x%08.8x\n", garts->token);
t32 = htonl (garts->token);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
CHECK_BUFLEN (bufptr - buf, dgram_max);
}
hdr->message_length = bufptr - buf;
copy_from_header (buf, hdr);
send_buffer (so, buf, bufptr - buf, to);
}
static void
send_get_attr_reply (int so, struct sockaddr_in *to, satmp_header *hdr,
get_attr_reply *rep, int kernel)
{
char buf[dgram_max], *bufptr = buf;
u_short i;
u_int t32;
/* reserve space for header */
bufptr += header_size ();
/* request header */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s sent %s\n",
message_name (hdr->message_number),
kernel ? "to kernel" : "to remote host");
/* extended session identifier */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\tesi: 0x%llx\n", hdr->message_esi);
/* copy hostid */
if (kernel)
{
/* copy hostid */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\thostid: 0x%x\n", rep->hostid);
t32 = htonl (rep->hostid);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
}
/* copy generation */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\tgeneration: %u\n", rep->generation);
t32 = htonl (rep->generation);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
/* copy reply specs */
for (i = 0; i < rep->attr_spec_count; i++)
{
get_attr_reply_attr_spec *garas;
u_short t16;
garas = &rep->attr_spec[i];
/* attribute type */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tattribute: %hu\n", garas->attribute);
t16 = htons (garas->attribute);
memcpy (bufptr, &t16, sizeof (t16));
bufptr += sizeof (t16);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* length of network representation */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tnr length: %hu\n", garas->nr_length);
t16 = htons (garas->nr_length);
memcpy (bufptr, &t16, sizeof (t16));
bufptr += sizeof (t16);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* token */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\ttoken: 0x%08.8x\n", garas->token);
t32 = htonl (garas->token);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* status */
if (kernel)
{
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tstatus: %u\n",
(unsigned) garas->status);
*bufptr++ = garas->status;
CHECK_BUFLEN (bufptr - buf, dgram_max);
if (debug_on (DEBUG_PROTOCOL))
{
char *text;
if (garas->nr != NULL)
{
text = lrep_to_text (garas->nr,
garas->attribute);
debug_print ("\t\tlocal rep: %s\n",
text);
destroy_lrep (text, garas->attribute);
}
else
debug_print ("\t\tlocal rep: not available\n");
}
if (garas->nr != NULL)
{
memcpy (bufptr, garas->nr, garas->nr_length);
bufptr += garas->nr_length;
CHECK_BUFLEN (bufptr - buf, dgram_max);
}
}
else
{
/* network representation itself */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tnetwork rep: %s\n",
garas->nr);
memcpy (bufptr, garas->nr, garas->nr_length);
bufptr += garas->nr_length;
CHECK_BUFLEN (bufptr - buf, dgram_max);
}
}
hdr->message_length = bufptr - buf;
copy_from_header (buf, hdr);
if (kernel)
{
if (satmp_get_attr_reply (so, buf, bufptr - buf) == -1)
debug_print ("\t\tsatmp_get_attr_reply: %s\n",
strerror (errno));
}
else
send_buffer (so, buf, bufptr - buf, to);
}
/* ARGSUSED */
static void
send_get_lrtok_reply (int so, struct sockaddr_in *to, satmp_header *hdr,
get_lrtok_reply *rep)
{
char buf[dgram_max], *bufptr = buf;
u_short i;
u_int t32;
/* reserve space for header */
bufptr += header_size ();
/* request header */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s sent\n", message_name (hdr->message_number));
/* extended session identifier */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\tesi: 0x%llx\n", hdr->message_esi);
/* copy hostid */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\thostid: 0x%x\n", rep->hostid);
t32 = htonl (rep->hostid);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
/* copy generation */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\tgeneration: %u\n", rep->generation);
t32 = htonl (rep->generation);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
for (i = 0; i < rep->token_spec_count; i++)
{
get_lrtok_reply_token_spec *glrts;
u_short t16;
glrts = &rep->token_spec[i];
/* attribute type */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tattribute: %hu\n", glrts->attribute);
t16 = htons (glrts->attribute);
memcpy (bufptr, &t16, sizeof (t16));
bufptr += sizeof (t16);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* mapping identifier */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tmapping identifier: %u\n",
glrts->mid);
t32 = htonl (glrts->mid);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* token */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\ttoken: 0x%08.8x\n", glrts->token);
t32 = htonl (glrts->token);
memcpy (bufptr, &t32, sizeof (t32));
bufptr += sizeof (t32);
CHECK_BUFLEN (bufptr - buf, dgram_max);
/* status */
if (debug_on (DEBUG_PROTOCOL))
debug_print ("\t\tstatus: %u\n",
(unsigned) glrts->status);
*bufptr++ = glrts->status;
CHECK_BUFLEN (bufptr - buf, dgram_max);
}
hdr->message_length = bufptr - buf;
copy_from_header (buf, hdr);
if (satmp_get_lrtok_reply (so, buf, bufptr - buf) == -1)
debug_print ("\t\tsatmp_get_lrtok_reply: %s\n",
strerror (errno));
}
/*******************************************************************
* TIMEOUT CALLBACKS
******************************************************************/
static void
init_request_notify (void *arg)
{
timer_client *client = (timer_client *) arg;
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s: timed out\n",
message_name (SATMP_INIT_REQUEST));
if (satmp_init_reply (client->so[KERNSO], client->hdr.message_esi,
IRQ_FLAG_FAILED, 0) == -1)
debug_print ("satmp_init_reply: %s\n", strerror (errno));
}
static void
init_request_destroy (void *arg)
{
timer_client *client = (timer_client *) arg;
destroy_init_request (client->tc_irq);
free (client->tc_irq);
free (client);
}
static void
init_request_retry (void *arg)
{
timer_client *client = (timer_client *) arg;
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s: retry\n",
message_name (SATMP_INIT_REQUEST));
send_init_request (client->so[DEMONSO], &client->token_server,
&client->hdr, client->tc_irq);
}
/* ARGSUSED */
static void
send_flush_notify (void *arg)
{
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s: timed out\n",
message_name (SATMP_FLUSH_REMOTE_CACHE));
}
static void
send_flush_destroy (void *arg)
{
timer_client *client = (timer_client *) arg;
free (client);
}
static void
send_flush_retry (void *arg)
{
timer_client *client = (timer_client *) arg;
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s: retry\n",
message_name (SATMP_FLUSH_REMOTE_CACHE));
send_header (client->so[DEMONSO], &client->token_server, &client->hdr);
}
/* ARGSUSED */
static void
send_tok_notify (void *arg)
{
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s: timed out\n",
message_name (SATMP_GET_TOK_REQUEST));
}
static void
send_tok_destroy (void *arg)
{
timer_client *client = (timer_client *) arg;
destroy_get_tok_request (client->tc_gtr);
free (client->tc_gtr);
free (client);
}
static void
send_tok_retry (void *arg)
{
timer_client *client = (timer_client *) arg;
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s: retry\n",
message_name (SATMP_GET_TOK_REQUEST));
send_get_tok_request (client->so[DEMONSO], &client->token_server,
&client->hdr, client->tc_gtr);
}
static void
send_attr_notify (void *arg)
{
timer_client *client = (timer_client *) arg;
get_attr_reply rep;
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s: timed out\n",
message_name (SATMP_GET_ATTR_REQUEST));
(void) get_attr_reply_failed (SATMP_INTERNAL_ERROR, client->tc_gar,
&rep);
send_get_attr_reply (client->so[KERNSO], &client->host, &client->hdr,
&rep, 1);
destroy_get_attr_reply (&rep);
}
static void
send_attr_destroy (void *arg)
{
timer_client *client = (timer_client *) arg;
destroy_get_attr_request (client->tc_gar);
free (client->tc_gar);
free (client);
}
static void
send_attr_retry (void *arg)
{
timer_client *client = (timer_client *) arg;
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s: retry\n",
message_name (SATMP_GET_ATTR_REQUEST));
send_get_attr_request (client->so[DEMONSO], &client->token_server,
&client->hdr, client->tc_gar);
}
/*******************************************************************
* MAIN REQUEST LOOP
******************************************************************/
static void
timer_client_init (timer_client *client, int so[],
struct sockaddr_in *host, struct sockaddr_in *token_server,
satmp_header *hdr, void *request)
{
memcpy (client->so, so, sizeof (client->so));
memcpy (&client->host, host, sizeof (*host));
memcpy (&client->token_server, token_server, sizeof (*token_server));
memcpy (&client->hdr, hdr, sizeof (*hdr));
client->tc_req = request;
}
typedef struct {
satmp_header hdr;
struct sockaddr_in from;
char buf[dgram_max], *bufptr;
size_t buflen;
u_int hostid;
so_set so;
} request_t;
static atomic esi_seq;
static thread_rtn
reqvec (void *arg)
{
request_t *request = (request_t *) arg;
int err;
satmp_header hdr = request->hdr;
struct sockaddr_in from = request->from, to;
size_t buflen = request->buflen;
u_int hostid = request->hostid;
char *bufptr = request->bufptr;
int demonso = request->so[DEMONSO];
int kernso = request->so[KERNSO];
switch (hdr.message_number)
{
case SATMP_FLUSH_REMOTE_CACHE:
{
init_request req, *reqp;
timer_client *client;
/* flush cache */
hdr.message_number = SATMP_FLUSH_REPLY;
hdr.message_status = receive_flush_remote_cache (hostid);
send_header (demonso, &from, &hdr);
/* create request */
req.hostid = hostid;
hdr.message_status = create_init_request (&req);
if (hdr.message_status != SATMP_REPLY_OK)
break;
/* allocate request & client */
reqp = (init_request *) malloc (sizeof (*reqp));
client = (timer_client *) malloc (sizeof (*client));
if (reqp == NULL || client == NULL)
{
destroy_init_request (&req);
free (reqp);
free (client);
break;
}
hdr.message_number = SATMP_INIT_REQUEST;
hdr.message_esi = (satmp_esi_t) incatomic (&esi_seq);
memcpy (reqp, &req, sizeof (req));
timer_client_init (client, request->so, &from, &from,
&hdr, reqp);
/* send SATMP_INIT_REQUEST message to sender */
send_init_request (demonso, &from, &hdr, reqp);
if (timer_set (timeout, retries, hdr.message_esi,
client, init_request_notify,
init_request_retry,
init_request_destroy))
init_request_destroy (client);
break;
}
case SATMP_FLUSH_REPLY:
{
timer_client *client;
client = timer_cancel (hdr.message_esi);
if (client != NULL)
send_flush_destroy (client);
break;
}
case SATMP_INIT_REQUEST:
{
init_request req;
init_reply rep;
rep.hostid = req.hostid = hostid;
hdr.message_number = SATMP_INIT_REPLY;
if (init_request_buffer (bufptr, buflen, &req))
{
hdr.message_status = SATMP_INTERNAL_ERROR;
send_header (demonso, &from, &hdr);
break;
}
hdr.message_status = receive_init_request (&req, &rep);
send_init_reply (demonso, &from, &hdr, &rep);
destroy_init_request (&req);
destroy_init_reply (&rep);
break;
}
case SATMP_INIT_REPLY:
{
init_reply rep;
timer_client *client;
client = timer_cancel (hdr.message_esi);
if (client == NULL)
break;
rep.hostid = client->host.sin_addr.s_addr;
if (init_reply_buffer (bufptr, buflen, &rep))
{
satmp_init_reply (kernso, hdr.message_esi,
IRQ_FLAG_FAILED, 0);
init_request_destroy (client);
break;
}
if (receive_init_reply (&rep) == SATMP_REPLY_OK)
satmp_init_reply (kernso, client->hdr.message_esi, IRQ_FLAG_OK, rep.generation);
else
satmp_init_reply (kernso, client->hdr.message_esi, IRQ_FLAG_FAILED, 0);
init_request_destroy (client);
destroy_init_reply (&rep);
break;
}
case SATMP_GET_TOK_REQUEST:
{
get_tok_request req;
get_tok_reply rep;
req.hostid = hostid;
hdr.message_number = SATMP_GET_TOK_REPLY;
if (get_tok_request_buffer (bufptr, buflen, &req))
{
hdr.message_status = SATMP_INTERNAL_ERROR;
send_header (demonso, &from, &hdr);
break;
}
hdr.message_status = receive_get_tok_request (&req,
&rep);
send_get_tok_reply (demonso, &from, &hdr, &rep);
destroy_get_tok_request (&req);
destroy_get_tok_reply (&rep);
break;
}
case SATMP_GET_TOK_REPLY:
{
get_tok_reply rep;
get_tok_request *req;
timer_client *client;
client = timer_cancel (hdr.message_esi);
if (client == NULL)
break;
req = client->tc_gtr;
rep.hostid = client->host.sin_addr.s_addr;
if (get_tok_reply_buffer (bufptr, buflen, &rep) == 0)
{
hdr.message_status =
receive_get_tok_reply (req, &rep);
destroy_get_tok_reply (&rep);
}
send_tok_destroy (client);
break;
}
case SATMP_GET_ATTR_REQUEST:
{
get_attr_request req;
get_attr_reply rep;
req.hostid = hostid;
hdr.message_number = SATMP_GET_ATTR_REPLY;
if (get_attr_request_buffer (bufptr, buflen, &req))
{
hdr.message_status = SATMP_INTERNAL_ERROR;
send_header (demonso, &from, &hdr);
break;
}
hdr.message_status = receive_get_attr_request (&req,
&rep);
send_get_attr_reply (demonso, &from, &hdr, &rep, 0);
destroy_get_attr_request (&req);
destroy_get_attr_reply (&rep);
break;
}
case SATMP_GET_ATTR_REPLY:
{
get_attr_reply rep;
timer_client *client;
client = timer_cancel (hdr.message_esi);
if (client == NULL)
break;
rep.hostid = client->host.sin_addr.s_addr;
switch (hdr.message_status)
{
case SATMP_INVALID_GENERATION:
(void) receive_flush_remote_cache (client->host.sin_addr.s_addr);
case SATMP_UNSUPPORTED_MESSAGE:
case SATMP_FORMAT_ERROR:
case SATMP_INTERNAL_ERROR:
if (get_attr_reply_failed (hdr.message_status, client->tc_gar, &rep) == 0)
{
send_get_attr_reply (kernso, &client->host, &hdr, &rep, 1);
destroy_get_attr_reply (&rep);
}
send_attr_destroy (client);
goto get_attr_reply_out;
}
if (err = get_attr_reply_buffer (bufptr, buflen, &rep))
{
if (get_attr_reply_failed (err, client->tc_gar, &rep) == 0)
{
send_get_attr_reply (kernso, &client->host, &hdr, &rep, 1);
destroy_get_attr_reply (&rep);
}
send_attr_destroy (client);
break;
}
hdr.message_status = receive_get_attr_reply (&rep);
destroy_get_attr_reply (&rep);
xlate_get_attr_reply (client->tc_gar, &rep);
send_get_attr_reply (kernso, &client->host, &hdr,
&rep, 1);
destroy_get_attr_reply (&rep);
send_attr_destroy (client);
get_attr_reply_out:
break;
}
case SATMP_GET_LRTOK_REQUEST:
{
get_lrtok_request req;
get_lrtok_reply rep;
hdr.message_number = SATMP_GET_LRTOK_REPLY;
if (get_lrtok_request_buffer (bufptr, buflen, &req))
{
hdr.message_status = SATMP_INTERNAL_ERROR;
send_header (demonso, &from, &hdr);
break;
}
hdr.message_status = receive_get_lrtok_request (&req,
&rep);
send_get_lrtok_reply (kernso, &from, &hdr, &rep);
destroy_get_lrtok_request (&req);
destroy_get_lrtok_reply (&rep);
break;
}
case SATMP_SEND_INIT_REQUEST:
{
init_request req, *reqp;
host_cmd cmd;
timer_client *client;
if (host_cmd_buffer (bufptr, buflen, &cmd))
{
if (debug_on (DEBUG_PROTOCOL))
debug_print ("SATMP_SEND_INIT_REQUEST: bad buffer\n");
satmp_init_reply (kernso, hdr.message_esi,
IRQ_FLAG_FAILED, 0);
break;
}
/* send ack if command didn't come from the kernel */
if (!cmd.kernel)
send_header (demonso, &from, &hdr);
/* create request */
req.hostid = cmd.hostid;
hdr.message_status = create_init_request (&req);
if (hdr.message_status != SATMP_REPLY_OK)
{
if (debug_on (DEBUG_PROTOCOL))
debug_print ("SATMP_SEND_INIT_REQUEST: request creation failed\n");
satmp_init_reply (kernso, hdr.message_esi,
IRQ_FLAG_FAILED, 0);
break;
}
/* allocate request & client */
reqp = (init_request *) malloc (sizeof (*reqp));
client = (timer_client *) malloc (sizeof (*client));
if (reqp == NULL || client == NULL)
{
if (debug_on (DEBUG_PROTOCOL))
debug_print ("SATMP_SEND_INIT_REQUEST: cannot allocate memory\n");
destroy_init_request (&req);
free (reqp);
free (client);
satmp_init_reply (kernso, hdr.message_esi,
IRQ_FLAG_FAILED, 0);
break;
}
hdr.message_number = SATMP_INIT_REQUEST;
from.sin_addr.s_addr = cmd.hostid;
from.sin_port = cmd.port;
memcpy (reqp, &req, sizeof (req));
timer_client_init (client, request->so, &from, &from,
&hdr, reqp);
/* send SATMP_INIT_REQUEST message to specified host */
send_init_request (demonso, &from, &hdr, reqp);
if (timer_set (timeout, retries, hdr.message_esi,
client, init_request_notify,
init_request_retry,
init_request_destroy))
init_request_destroy (client);
break;
}
case SATMP_SEND_FLUSH_REMOTE_CACHE:
{
host_cmd cmd;
timer_client *client;
if (host_cmd_buffer (bufptr, buflen, &cmd))
break;
/* send ack if command didn't come from the kernel */
if (!cmd.kernel)
send_header (demonso, &from, &hdr);
client = (timer_client *) malloc (sizeof (*client));
if (client == NULL)
break;
hdr.message_number = SATMP_FLUSH_REMOTE_CACHE;
hdr.message_status = SATMP_REPLY_OK;
from.sin_addr.s_addr = cmd.hostid;
from.sin_port = cmd.port;
send_header (demonso, &from, &hdr);
timer_client_init (client, request->so, &from, &from,
&hdr, (void *) cmd.hostid);
if (timer_set (timeout, retries, hdr.message_esi,
client, send_flush_notify,
send_flush_retry, send_flush_destroy))
send_flush_destroy (client);
break;
}
case SATMP_SEND_GET_ATTR_REQUEST:
{
get_attr_request req, *reqp;
get_attr_reply rep;
host_cmd cmd;
timer_client *client;
if (get_attr_admin_buffer (bufptr, buflen, &cmd, &req))
break;
/* send ack if command didn't come from the kernel */
if (!cmd.kernel)
send_header (demonso, &from, &hdr);
hdr.message_number = SATMP_GET_ATTR_REQUEST;
hdr.message_status = SATMP_REPLY_OK;
from.sin_addr.s_addr = rep.hostid = cmd.hostid;
from.sin_port = cmd.port;
to = from;
if (get_client_server (cmd.hostid, &to))
{
if (get_attr_reply_failed (SATMP_INTERNAL_ERROR, &req, &rep) == 0)
{
send_get_attr_reply (kernso, &from,
&hdr, &rep, 1);
destroy_get_attr_reply (&rep);
}
destroy_get_attr_request (&req);
break;
}
reqp = (get_attr_request *) malloc (sizeof (*reqp));
client = (timer_client *) malloc (sizeof (*client));
if (reqp == NULL || client == NULL)
{
if (get_attr_reply_failed (SATMP_INTERNAL_ERROR, &req, &rep) == 0)
{
send_get_attr_reply (kernso, &from,
&hdr, &rep, 1);
destroy_get_attr_reply (&rep);
}
destroy_get_attr_request (&req);
free (reqp);
free (client);
break;
}
memcpy (reqp, &req, sizeof (req));
timer_client_init (client, request->so, &from, &to, &hdr, reqp);
send_get_attr_request (demonso, &to, &hdr, reqp);
if (timer_set (timeout, retries, hdr.message_esi,
client, send_attr_notify,
send_attr_retry, send_attr_destroy))
send_attr_destroy (client);
break;
}
case SATMP_SEND_GET_TOK_REQUEST:
{
get_tok_request req, *reqp;
host_cmd cmd;
timer_client *client;
if (get_tok_admin_buffer (bufptr, buflen, &cmd, &req))
break;
/* send ack if command didn't come from the kernel */
if (!cmd.kernel)
send_header (demonso, &from, &hdr);
hdr.message_number = SATMP_GET_TOK_REQUEST;
hdr.message_status = SATMP_REPLY_OK;
from.sin_addr.s_addr = cmd.hostid;
from.sin_port = cmd.port;
to = from;
if (get_client_server (cmd.hostid, &to))
{
destroy_get_tok_request (&req);
break;
}
reqp = (get_tok_request *) malloc (sizeof (*reqp));
client = (timer_client *) malloc (sizeof (*client));
if (reqp == NULL || client == NULL)
{
destroy_get_tok_request (&req);
free (reqp);
free (client);
break;
}
memcpy (reqp, &req, sizeof (req));
timer_client_init (client, request->so, &from, &to, &hdr, reqp);
send_get_tok_request (demonso, &to, &hdr, reqp);
if (timer_set (timeout, retries, hdr.message_esi,
client, send_tok_notify,
send_tok_retry, send_tok_destroy))
send_tok_destroy (client);
break;
}
case SATMP_EXIT:
exit (0);
break;
default:
if (debug_on (DEBUG_PROTOCOL))
debug_print ("%s message: %d\n",
message_name (hdr.message_number),
(unsigned) hdr.message_number);
hdr.message_status = SATMP_UNSUPPORTED_MESSAGE;
send_header (demonso, &from, &hdr);
break;
}
free (request);
thread_return (0);
}
static void
handle_requests (so_set so)
{
request_t *req;
int fromlen, mlen, sockfd, nfds;
thread_id tid;
fd_set rfds, ofds;
nfds = (so[DEMONSO] > so[KERNSO] ? so[DEMONSO] : so[KERNSO]);
FD_ZERO (&ofds);
FD_SET (so[DEMONSO], &ofds);
FD_SET (so[KERNSO], &ofds);
reselect:
rfds = ofds;
if (select (nfds + 1, &rfds, (fd_set *) NULL, (fd_set *) NULL,
(struct timeval *) NULL) == -1)
goto reselect;
again:
if (FD_ISSET (so[KERNSO], &rfds))
sockfd = so[KERNSO];
else if (FD_ISSET (so[DEMONSO], &rfds))
sockfd = so[DEMONSO];
else
goto reselect;
FD_CLR (sockfd, &rfds);
req = (request_t *) malloc (sizeof (*req));
if (req == NULL)
goto reselect;
memcpy (req->so, so, sizeof (req->so));
/* get message header */
fromlen = sizeof (req->from);
mlen = recvfrom (sockfd, req->buf, sizeof (req->buf), 0, &req->from,
&fromlen);
if (mlen < header_size ())
{
if (debug_on (DEBUG_PROTOCOL))
if (mlen == -1)
debug_print ("recvfrom: %s\n", strerror (errno));
else
debug_print ("short datagram from host 0x%x\n", req->from.sin_addr.s_addr);
free (req);
goto reselect;
}
/* ignore untrusted clients */
if (req->from.sin_port > IPPORT_RESERVED)
{
if (debug_on (DEBUG_PROTOCOL))
debug_print ("request from untrusted host 0x%x\n",
req->from.sin_addr.s_addr);
free (req);
goto reselect;
}
req->hostid = req->from.sin_addr.s_addr;
/* get header info */
req->bufptr = copy_to_header (req->buf, &req->hdr);
req->buflen = (req->buf + req->hdr.message_length) - req->bufptr;
/* verify header info */
if (req->hdr.message_length != mlen)
{
if (debug_on (DEBUG_PROTOCOL))
debug_print ("invalid message length:"
"got 0x%hx bytes, expected 0x%x bytes\n",
req->hdr.message_length,
(unsigned int) mlen);
free (req);
goto reselect;
}
/* do stuff according to message number */
if (debug_on (DEBUG_PROTOCOL))
{
debug_print ("%s received\n",
message_name (req->hdr.message_number));
debug_print ("\tesi: 0x%llx\n", req->hdr.message_esi);
}
/* create thread to handle request */
if (thread_create (reqvec, &tid, (void *) req) == -1)
free (req);
/*
* If requests are pending on the other socket, handle them before
* waiting in select again. This ensures that handling requests from
* one socket doesn't starve the other.
*/
if (FD_ISSET (so[DEMONSO], &rfds) || FD_ISSET (so[KERNSO], &rfds))
goto again;
else
goto reselect;
}
static void
usage (const char *program)
{
fprintf (stderr, "Usage: %s [-c [configdir] -d [%s] -l [logfile] -p [port]]\n", program, name_debug_opts ());
exit (EXIT_FAILURE);
}
static void
deconfigure_databases (void)
{
deconfigure_lrep_mappings ();
deconfigure_client ();
deconfigure_server ();
}
static int
configure_databases (const char *configdir)
{
if (configure_server (configdir) ||
configure_client (configdir) ||
configure_lrep_mappings (configdir))
return (1);
if (atexit (deconfigure_databases) == 0)
return (0);
deconfigure_databases ();
return (1);
}
static void
kill_daemon (void)
{
cap_t ocap = cap_acquire (1, cap_network_mgt);
if (satmp_done () == -1)
debug_print ("satmp_done: %s\n", strerror (errno));
cap_surrender (ocap);
}
static void
sighup (int sig)
{
/*
* In the future, this will reconfigure
* satmpd internal databases, rather than
* exit and die.
*/
kill_daemon ();
deconfigure_databases ();
_exit (sig);
}
static void
sigint (int sig)
{
kill_daemon ();
deconfigure_databases ();
_exit (sig);
}
/*
* Enabled privileged listen, so TCB communication
* from other daemons can be received.
*
* Set session ID to 1, so SAMP attributes are
* not attached to satmpd communication.
*/
static int
socket_priv_session (int so)
{
t6attr_t t6attr;
t6mask_t t6mask;
cap_t ocap;
uid_t sid = T6SAMP_PRIV_SID;
int failed;
int r = 0;
ocap = cap_acquire (1, cap_network_mgt);
if (t6mls_socket (so, T6_ON) == -1)
{
cap_surrender (ocap);
return (-1);
}
cap_surrender (ocap);
/* allocate control block */
t6attr = t6alloc_blk (T6M_SESSION_ID);
if (t6attr == (t6attr_t) NULL)
return (-1);
ocap = cap_acquire (1, cap_network_mgt);
failed = (t6set_attr (T6_SESSION_ID, (void *) &sid, t6attr) == -1 ||
t6set_endpt_default (so, T6M_SESSION_ID, t6attr) == -1);
cap_surrender (ocap);
/* free memory */
t6free_blk (t6attr);
/* return error if setting the session id failed */
if (failed)
return (-1);
/* set the connection mask to enable these attributes */
if ((r = t6get_endpt_mask (so, &t6mask)) == 0)
{
ocap = cap_acquire (1, cap_network_mgt);
r = t6set_endpt_mask (so, t6mask | T6M_SESSION_ID);
cap_surrender (ocap);
}
return (r);
}
static int
create_socket (int port)
{
struct sockaddr_in addr; /* address of daemon's socket */
int so, on = 1;
cap_t ocap;
memset ((void *) &addr, '\0', sizeof (addr));
addr.sin_port = port;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
so = socket (AF_INET, SOCK_DGRAM, 0);
if (so == -1)
return (so);
/* permit immediate reuse of this socket address */
if (setsockopt (so, SOL_SOCKET, SO_REUSEADDR, (void *) &on,
sizeof (on)) == -1)
{
close (so);
return (-1);
}
/* bind socket */
ocap = cap_acquire (1, cap_priv_port);
if (bind (so, (struct sockaddr *) &addr, sizeof (addr)) == -1)
{
cap_surrender (ocap);
close (so);
return (-1);
}
cap_surrender (ocap);
/* set session id */
if (socket_priv_session (so) == -1)
{
close (so);
return (-1);
}
return (so);
}
int
main (int argc, char *argv[])
{
int port = DEFAULT_SATMPD_PORT;
int error = 0, c;
so_set so;
char *program;
char *configdir = DEFAULT_CONFIG_DIR;
struct sigaction act;
cap_t ocap;
init_reply rep;
/* continue only if T6 is enabled */
if (sysconf (_SC_IP_SECOPTS) <= 0)
{
fprintf (stderr, "satmpd: IP Security not enabled - exiting\n");
exit (0);
}
/* turn off yp */
_yp_disabled = 1;
/* get program name */
program = strrchr (argv[0], '/');
if (program == NULL)
program = argv[0];
else
program++;
/* parse option arguments */
while (!error && (c = getopt (argc, argv, "c:d:l:p:")) != -1)
{
switch (c)
{
char *end;
case 'c':
configdir = optarg;
break;
case 'd':
if (parse_debug_opts (optarg))
error++;
break;
case 'l':
debug_set_log (optarg);
break;
case 'p':
port = (int) strtol (optarg, &end, 10);
if ((port == 0 && end == optarg) ||
*end != '\0')
error++;
break;
case '?':
error++;
break;
}
}
/* exit on errors or extraneous arguments */
if (error || optind < argc)
usage (program);
/* turn ourselves into a daemon, preserving debug_fp */
if (is_debug_state (DEBUG_ALL_OFF) &&
_daemonize (_DF_NOCHDIR, fileno (debug_fp), -1, -1) == -1)
{
fprintf (stderr, "satmpd: _daemonize failed\n");
exit (1);
}
/* create socket */
if ((so[DEMONSO] = create_socket (port)) == -1 ||
(so[KERNSO] = create_socket (0)) == -1)
{
debug_print ("socket: %s\n", strerror (errno));
exit (EXIT_FAILURE);
}
/* register daemon death */
if (atexit (kill_daemon))
{
debug_print ("cannot register kill_daemon\n");
kill_daemon ();
exit (EXIT_FAILURE);
}
/* set signal handlers */
act.sa_flags = 0;
if (sigemptyset (&act.sa_mask) == -1)
{
debug_print ("sigemptyset: %s\n", strerror (errno));
exit (EXIT_FAILURE);
}
/* handle SIGHUP */
act.sa_handler = sighup;
if (sigaction (SIGHUP, &act, (struct sigaction *) NULL) == -1)
{
debug_print ("sigaction: %s\n", strerror (errno));
exit (EXIT_FAILURE);
}
/* handle SIGINT & SIGTERM */
act.sa_handler = sigint;
if (sigaction (SIGINT, &act, (struct sigaction *) NULL) == -1 ||
sigaction (SIGTERM, &act, (struct sigaction *) NULL) == -1)
{
debug_print ("sigaction: %s\n", strerror (errno));
exit (EXIT_FAILURE);
}
#ifndef PTHREADS
/* ignore SIGCHLD */
act.sa_handler = SIG_IGN;
#ifdef SA_NOCLDWAIT
/* prevent creation of zombies */
act.sa_flags |= SA_NOCLDWAIT;
#endif
if (sigaction (SIGCHLD, &act, (struct sigaction *) NULL) == -1)
{
debug_print ("sigaction: %s\n", strerror (errno));
exit (EXIT_FAILURE);
}
#endif
/* initialize global semaphore area */
if (sem_initialize () == -1)
{
debug_print ("cannot initialize mutex subsystem\n");
exit (EXIT_FAILURE);
}
/* initialize timer queues */
if (timer_initialize () == -1)
{
debug_print ("cannot initialize timer subsystem\n");
exit (EXIT_FAILURE);
}
/* initialize atomic operations */
if (atomic_initialize () == -1)
{
debug_print ("cannot initialize atomic op subsystem\n");
exit (EXIT_FAILURE);
}
/* initialize databases */
if (configure_databases (configdir))
{
debug_print ("cannot configure databases\n");
exit (EXIT_FAILURE);
}
/* install synthetic reply for localhost */
if ((error = create_loopback_reply (&rep)) ||
(error = receive_init_reply (&rep)))
{
debug_print ("synthetic loopback reply: %s\n",
result_text (error));
exit (EXIT_FAILURE);
}
destroy_init_reply (&rep);
if (name_initialize () == -1)
{
debug_print ("cannot start name subsystem\n");
exit (EXIT_FAILURE);
}
/* start timer subsystem */
if (timer_threads_start () == -1)
{
debug_print ("cannot start timer threads\n");
exit (EXIT_FAILURE);
}
/* initialize kernel<->satmpd interface */
ocap = cap_acquire (1, cap_network_mgt);
if (satmp_init (so[KERNSO], server_generation) == -1)
{
cap_surrender (ocap);
debug_print ("satmp_init: %s\n", strerror (errno));
exit (EXIT_FAILURE);
}
cap_surrender (ocap);
#if 0
/* re-enable yp */
_yp_disabled = 0;
#endif
/* create atomic variables */
iniatomic (&esi_seq, 0);
/* Request Loop */
handle_requests (so);
return (0);
}