summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar John Kohl <jtkohl@mit.edu>1987-07-01 00:15:34 +0000
committerGravatar John Kohl <jtkohl@mit.edu>1987-07-01 00:15:34 +0000
commit478c419fa7eefc83ef1f92c18ca1d62dd78130c4 (patch)
tree88a69fcba3740b5bb4f8f51075ebeeb13fb4036a
parent86cbbc339a0cb723c1a7dcd77808b8dacc810457 (diff)
first release version
-rw-r--r--server/client.c125
-rw-r--r--server/dispatch.c295
-rw-r--r--server/hostm.c182
-rw-r--r--server/subscr.c258
-rw-r--r--server/zserver.h238
5 files changed, 819 insertions, 279 deletions
diff --git a/server/client.c b/server/client.c
index 27acda4..9882a8c 100644
--- a/server/client.c
+++ b/server/client.c
@@ -14,24 +14,29 @@
#include <zephyr/mit-copyright.h>
#ifndef lint
+#ifndef SABER
static char rcsid_client_s_c[] = "$Header$";
+#endif SABER
#endif lint
/*
* External functions:
*
- * Code_t client_register(notice, client, server)
+ * Code_t client_register(notice, who, client, server)
* ZNotice_t *notice;
+ * struct sockaddr_in *who;
* ZClient_t **client; (RETURN)
* ZServerDesc_t *server;
*
* Code_t client_deregister(client)
* ZClient_t *client;
*
- * ZClient_t *client_which_client(notice)
+ * ZClient_t *client_which_client(who, notice)
+ * struct sockaddr_in *who;
* ZNotice_t *notice;
*/
#include "zserver.h"
+#include <sys/socket.h>
/*
* register a client: allocate space, find or insert the address in the
@@ -42,17 +47,18 @@ static char rcsid_client_s_c[] = "$Header$";
* The caller should check by calling client_which_client
*/
Code_t
-client_register(notice, client, server)
+client_register(notice, who, client, server)
ZNotice_t *notice;
+struct sockaddr_in *who;
register ZClient_t **client; /* RETURN */
ZServerDesc_t *server;
{
register ZHostList_t *hlp = server->zs_hosts;
register ZHostList_t *hlp2;
- register ZClientList_t *clist, *clist2;
+ register ZClientList_t *clist;
/* allocate a client struct */
- if ((*client = (ZClient_t *) malloc(sizeof(ZClient_t))) == NULLZCNT)
+ if ((*client = (ZClient_t *) xmalloc(sizeof(ZClient_t))) == NULLZCNT)
return(ENOMEM);
/* chain the client's host onto this server's host list */
@@ -60,36 +66,19 @@ ZServerDesc_t *server;
if (!hlp) /* bad host list */
return(EINVAL);
- for (hlp2 = hlp->q_forw; hlp2 != hlp; hlp2 = hlp2->q_forw) {
- if (bcmp(&hlp2->zh_addr, &notice->z_sender_addr, sizeof(struct in_addr)))
- /* already here */
- break;
- }
- if (hlp2 == hlp) { /* not here */
- if (!(hlp2 = (ZHostList_t *) malloc(sizeof(ZHostList_t)))) {
- free(*client);
- return(ENOMEM);
- }
- hlp2->zh_addr = notice->z_sender_addr;
- hlp2->zh_clients = NULLZCLT;
- insque(hlp2, hlp);
- }
+ if ((hlp2 = hostm_find_host(&who->sin_addr)) == NULLZHLT)
+ /* not here */
+ return(ZSRV_HNOTFOUND);
/* hlp2 is now pointing to the client's host's address struct */
- if ((clist = hlp2->zh_clients) == NULLZCLT) {
- /* doesn't already have a client on this ip addr */
- if ((clist2 = (ZClientList_t *)malloc(sizeof(ZClientList_t))) == NULLZCLT) {
- free(*client);
- return(ENOMEM);
- }
- clist2->q_forw = clist2->q_back = clist;
-
- hlp2->zh_clients = clist2;
+ if (hlp2->zh_clients == NULLZCLT) {
+ xfree(*client);
+ return(EINVAL);
}
- if ((clist = (ZClientList_t *)malloc(sizeof(ZClientList_t))) == NULLZCLT) {
- free(*client);
+ if ((clist = (ZClientList_t *)xmalloc(sizeof(ZClientList_t))) == NULLZCLT) {
+ xfree(*client);
return(ENOMEM);
}
@@ -97,30 +86,90 @@ ZServerDesc_t *server;
clist->zclt_client = *client;
/* initialize the struct */
- bzero(&(*client)->zct_sin, sizeof(struct sockaddr_in));
+ bzero((caddr_t) &(*client)->zct_sin, sizeof(struct sockaddr_in));
+ (*client)->zct_sin.sin_addr.s_addr = who->sin_addr.s_addr;
(*client)->zct_sin.sin_port = notice->z_port;
- (*client)->zct_sin.sin_addr = notice->z_sender_addr;
+ (*client)->zct_sin.sin_family = AF_INET;
(*client)->zct_subs = NULLZST;
- /* chain him in */
+ /* chain him in to the clients list in the host list*/
- insque(clist2, clist);
+ xinsque(clist, hlp2->zh_clients);
return(ZERR_NONE);
}
/*
- * Deregister the client, freeing resources.
+ * Deregister the client, freeing resources.
+ * Remove any packets in the nack queue, release subscriptions, and
+ * dequeue him from the host.
*/
-Code_t
-client_deregister(client)
+void
+client_deregister(client, host)
ZClient_t *client;
+ZHostList_t *host;
{
+ ZClientList_t *clients;
+
+ /* release any not-acked packets in the rexmit queue */
+ nack_release(client);
+
+ /* release subscriptions */
+ (void) subscr_cancel_client(client);
+
+ /* unthread and release this client */
+
+ if (host->zh_clients != NULLZCLT)
+ for (clients = host->zh_clients->q_forw;
+ clients != host->zh_clients;
+ clients = clients->q_forw)
+ if (clients->zclt_client == client) {
+ xremque(clients);
+ xfree(client);
+ xfree(clients);
+ return;
+ }
+ syslog(LOG_CRIT, "clt_dereg: clt not in host list");
+ abort();
+ /*NOTREACHED*/
}
+/*
+ * find the client which sent the notice
+ */
+
ZClient_t *
-client_which_client(notice)
+client_which_client(who, notice)
+struct sockaddr_in *who;
ZNotice_t *notice;
{
+ register ZHostList_t *hlt;
+ register ZClientList_t *clients;
+
+ zdbug1("which_client entry");
+
+ if ((hlt = hostm_find_host(&who->sin_addr)) == NULLZHLT) {
+ zdbug1("host not found");
+ return(NULLZCNT);
+ }
+
+ zdbug2("host %s",inet_ntoa(hlt->zh_addr.sin_addr));
+
+ if (hlt->zh_clients == NULLZCLT) {
+ zdbug1("no clients");
+ return(NULLZCNT);
+ }
+
+ for (clients = hlt->zh_clients->q_forw;
+ clients != hlt->zh_clients;
+ clients = clients->q_forw)
+ if (clients->zclt_client->zct_sin.sin_port == notice->z_port) {
+ zdbug2("match port %d", ntohs(notice->z_port));
+ return(clients->zclt_client);
+ }
+ zdbug1("no port");
+
+ return(NULLZCNT);
}
+
diff --git a/server/dispatch.c b/server/dispatch.c
index 520ec02..0d43332 100644
--- a/server/dispatch.c
+++ b/server/dispatch.c
@@ -14,7 +14,9 @@
#include <zephyr/mit-copyright.h>
#ifndef lint
+#ifndef SABER
static char rcsid_dispatch_c[] = "$Header$";
+#endif SABER
#endif lint
#include "zserver.h"
@@ -34,30 +36,71 @@ static char rcsid_dispatch_c[] = "$Header$";
*
*/
-static void xmit(), rexmit();
+static void xmit(), rexmit(), nack_cancel();
static int is_server();
int num_rexmits = NUM_REXMITS; /* patchable... */
long rexmit_secs = REXMIT_SECS;
+long abs_timo = REXMIT_SECS*NUM_REXMITS;
+
+#ifdef DEBUG
+static char *pktypes[] = {
+ "UNSAFE",
+ "UNACKED",
+ "ACKED",
+ "HMACK",
+ "HMCTL",
+ "SERVACK",
+ "SERVNAK",
+ "CLIENTACK"
+};
+#endif DEBUG
/*
* Dispatch a notice.
*/
void
dispatch(notice, auth, who)
-ZNotice_t *notice;
+register ZNotice_t *notice;
int auth;
struct sockaddr_in *who;
{
- register ZClientList_t *clientlist, *ptr;
- int acked = 0;
+#ifdef DEBUG
+ if (zdebug) {
+ char buf[4096];
+
+ (void) sprintf(buf, "disp:%s '%s' '%s' '%s' '%s' '%s' %s/%d/%d",
+ pktypes[(int) notice->z_kind],
+ notice->z_class,
+ notice->z_class_inst,
+ notice->z_opcode,
+ notice->z_sender,
+ notice->z_recipient,
+ inet_ntoa(who->sin_addr),
+ ntohs(who->sin_port),
+ ntohs(notice->z_port));
+ syslog(LOG_DEBUG, buf);
+ }
+#endif DEBUG
+ if (notice->z_kind == CLIENTACK) {
+ nack_cancel(notice, who);
+ return;
+ }
if (is_server(who)) {
server_dispatch(notice, auth, who);
return;
- }
- if (class_is_control(notice)) {
- control_handle(notice, auth, who);
+ } else if (class_is_hm(notice)) {
+ syslog(LOG_WARNING, "HM_CTL received?");
+ return;
+ } else if (class_is_control(notice)) {
+ control_dispatch(notice, auth, who);
+ return;
+ } else if (class_is_ulogin(notice)) {
+ ulogin_dispatch(notice, auth, who);
+ return;
+ } else if (class_is_ulocate(notice)) {
+ ulocate_dispatch(notice, auth, who);
return;
} else if (class_is_admin(notice)) {
/* this had better be a HELLO message--start of acquisition
@@ -70,30 +113,48 @@ struct sockaddr_in *who;
inet_ntoa(who->sin_addr),
ntohs(who->sin_port));
return;
- } else if (class_is_restricted(notice) &&
- !access_check(notice, XMIT)) {
- syslog(LOG_WARNING, "disp unauthorized %s", notice->z_class);
- return;
}
-
+
/* oh well, do the dirty work */
- if ((clientlist = subscr_match_list(notice)) == NULLZCLT) {
- clt_ack(notice, who, NOT_SENT);
+ sendit(notice, auth, who);
+}
+
+void
+sendit(notice, auth, who)
+register ZNotice_t *notice;
+int auth;
+struct sockaddr_in *who;
+{
+ int acked = 0;
+ ZAcl_t *acl;
+ register ZClientList_t *clientlist, *ptr;
+
+ if ((acl = class_get_acl(notice->z_class)) != NULLZACLT &&
+ (!auth || !access_check(notice, acl, TRANSMIT))) {
+ syslog(LOG_WARNING, "sendit unauthorized %s", notice->z_class);
+ clt_ack(notice, who, AUTH_FAILED);
return;
- }
- for (ptr = clientlist->q_forw; ptr != clientlist; ptr = ptr->q_forw) {
- /* for each client who gets this notice,
- send it along */
- xmit(notice, ptr->zclt_client);
- if (!acked) {
- acked = 1;
- clt_ack(notice, who, SENT);
+ }
+ if ((clientlist = subscr_match_list(notice)) != NULLZCLT) {
+ for (ptr = clientlist->q_forw;
+ ptr != clientlist;
+ ptr = ptr->q_forw) {
+ /* for each client who gets this notice,
+ send it along */
+ xmit(notice, ptr->zclt_client, auth);
+ if (!acked) {
+ acked = 1;
+ ack(notice, who);
+ }
}
+ subscr_list_free(clientlist);
}
+
if (!acked)
- clt_ack(notice, who, NOT_SENT);
+ nack(notice, who);
}
+
/*
* Is this from a server?
*/
@@ -109,8 +170,7 @@ struct sockaddr_in *who;
/* just look over the server list */
for (servs = otherservers, num = 0; num < nservers; num++, servs++)
- if (!bcmp(&servs->zs_addr.sin_addr, who->sin_addr,
- sizeof(struct in_addr)))
+ if (servs->zs_addr.sin_addr.s_addr == who->sin_addr.s_addr)
return(1);
return(0);
}
@@ -120,26 +180,44 @@ struct sockaddr_in *who;
*/
static void
-xmit(notice, client)
+xmit(notice, client, auth)
register ZNotice_t *notice;
ZClient_t *client;
+int auth;
{
- ZPacket_t *noticepack;
- register ZNotAcked_t *nack;
+ caddr_t noticepack;
+ register ZNotAcked_t *nacked;
int packlen;
Code_t retval;
- if ((noticepack = (ZPacket_t *) malloc(sizeof(ZPacket_t))) == NULLZPT){
+ zdbug1("xmit");
+ if ((noticepack = (caddr_t) xmalloc(sizeof(ZPacket_t))) == (caddr_t) NULL) {
syslog(LOG_ERR, "xmit malloc");
return; /* DON'T put on nack list */
}
+
packlen = sizeof(ZPacket_t);
- if ((retval = ZFormatNotice(notice, noticepack, packlen, &packlen)) != ZERR_NONE) {
- syslog(LOG_ERR, "xmit format: %s", error_message(retval));
- return; /* DON'T put on nack list */
+ if (auth) { /* we are distributing authentic */
+ if ((retval = ZFormatAuthenticNotice(notice, noticepack, packlen, &packlen, client->zct_cblock)) != ZERR_NONE) {
+ syslog(LOG_ERR, "xmit auth format: %s",
+ error_message(retval));
+ xfree(noticepack);
+ return;
+ }
+ } else {
+ notice->z_auth = 0;
+ notice->z_authent_len = 0;
+ notice->z_ascii_authent = (char *)"";
+ if ((retval = ZFormatRawNotice(notice, noticepack, packlen, &packlen)) != ZERR_NONE) {
+ syslog(LOG_ERR, "xmit format: %s", error_message(retval));
+ xfree(noticepack);
+ return; /* DON'T put on nack list */
+ }
}
+ zdbug3(" to %s/%d",inet_ntoa(client->zct_sin.sin_addr),
+ ntohs(client->zct_sin.sin_port));
if ((retval = ZSetDestAddr(&client->zct_sin)) != ZERR_NONE) {
syslog(LOG_WARNING, "xmit set addr: %s",
error_message(retval));
@@ -152,40 +230,70 @@ ZClient_t *client;
/* now we've sent it, mark it as not ack'ed */
- if ((nack = (ZNotAcked_t *)malloc(sizeof(ZNotAcked_t))) == NULLZNAT) {
+ if ((nacked = (ZNotAcked_t *)xmalloc(sizeof(ZNotAcked_t))) == NULLZNAT) {
/* no space: just punt */
syslog(LOG_WARNING, "xmit nack malloc");
return;
}
- nack->na_rexmits = 0;
- nack->na_packet = noticepack;
- nack->na_client = client;
-
+ nacked->na_rexmits = 0;
+ nacked->na_packet = noticepack;
+ nacked->na_client = client;
+ nacked->na_packsz = packlen;
+ nacked->na_uid = notice->z_uid;
+ nacked->q_forw = nacked->q_back = nacked;
+ nacked->na_abstimo = NOW + abs_timo;
+ /* set a timer */
+ nacked->na_timer = timer_set_rel (rexmit_secs, rexmit, (caddr_t) nacked);
/* chain in */
- insque(nacklist, nack);
+ xinsque(nacked, nacklist);
+#ifdef DEBUG
+ if (zdebug)
+ dump_nack();
+#endif DEBUG
- /* set a timer */
- nack->na_timer = timer_set_rel (rexmit_secs, rexmit, (caddr_t) nack);
}
+#ifdef DEBUG
+dump_nack()
+{
+ register ZNotAcked_t *nacked;
+
+ /* search the not-yet-acked list for anything destined to him, and
+ flush it. */
+ for (nacked = nacklist->q_forw; nacked != nacklist; nacked = nacked->q_forw)
+ syslog(LOG_DEBUG, "nck 0x%x, tmr 0x%x, clt 0x%x",
+ nacked, nacked->na_timer, nacked->na_client);
+}
+#endif DEBUG
+
static void
rexmit(nackpacket)
register ZNotAcked_t *nackpacket;
{
- ZClient_t *client;
int retval;
- if (++(nackpacket->na_rexmits) > num_rexmits) {
+ register ZClient_t *client;
+ zdbug1("rexmit");
+
+ if (++(nackpacket->na_rexmits) > num_rexmits ||
+ NOW > nackpacket->na_abstimo) {
/* possibly dead client */
- /* remove timer */
- timer_reset(nackpacket->na_timer);
- /* unlink & free packet */
- remque(nackpacket);
- free(nackpacket->na_packet);
+
client = nackpacket->na_client;
- free(nackpacket);
+ syslog(LOG_WARNING, "lost client %s %d",
+ inet_ntoa(client->zct_sin.sin_addr),
+ ntohs(client->zct_sin.sin_port));
+ /* unlink & free packet */
+ xremque(nackpacket);
+ xfree(nackpacket->na_packet);
+ xfree(nackpacket);
+
+#ifdef DEBUG
+ if (zdebug)
+ dump_nack();
+#endif DEBUG
/* initiate recovery */
server_recover(client);
return;
@@ -193,15 +301,25 @@ register ZNotAcked_t *nackpacket;
/* retransmit the packet */
+ zdbug3(" to %s/%d",inet_ntoa(nackpacket->na_client->zct_sin.sin_addr),
+ ntohs(nackpacket->na_client->zct_sin.sin_port));
if ((retval = ZSetDestAddr(&nackpacket->na_client->zct_sin)) != ZERR_NONE) {
syslog(LOG_WARNING, "rexmit set addr: %s",
error_message(retval));
- return;
+ goto requeue;
+
}
if ((retval = ZSendPacket(nackpacket->na_packet,
nackpacket->na_packsz)) != ZERR_NONE)
syslog(LOG_WARNING, "rexmit xmit: %s", error_message(retval));
+requeue:
+ /* reset the timer */
+ nackpacket->na_timer = timer_set_rel (rexmit_secs, rexmit, (caddr_t) nackpacket);
+#ifdef DEBUG
+ if (zdebug)
+ dump_nack();
+#endif DEBUG
return;
}
@@ -217,15 +335,33 @@ ZSentType sent;
int packlen;
Code_t retval;
+ zdbug3("clt_ack type %d for %d", (int) sent, ntohs(notice->z_port));
+ zdbug3(" to %s/%d",inet_ntoa(who->sin_addr), ntohs(who->sin_port));
+
+ if (hostm_find_server(&who->sin_addr) != me_server) {
+ zdbug1("not me");
+ return;
+ }
acknotice = *notice;
acknotice.z_kind = SERVACK;
- if (sent == SENT)
+ switch (sent) {
+ case SENT:
acknotice.z_message = ZSRVACK_SENT;
- else
+ break;
+ case NOT_FOUND:
+ acknotice.z_message = ZSRVACK_FAIL;
+ acknotice.z_kind = SERVNAK;
+ break;
+ case AUTH_FAILED:
+ acknotice.z_kind = SERVNAK;
+ /* fall thru */
+ case NOT_SENT:
acknotice.z_message = ZSRVACK_NOTSENT;
+ break;
+ }
- /* Don't forget room for the null */
+ /* leave room for the trailing null */
acknotice.z_message_len = strlen(acknotice.z_message) + 1;
packlen = sizeof(ackpack);
@@ -245,3 +381,58 @@ ZSentType sent;
}
return;
}
+
+void
+nack_release(client)
+ZClient_t *client;
+{
+ register ZNotAcked_t *nacked, *nack2;
+
+ /* search the not-yet-acked list for anything destined to him, and
+ flush it. */
+ for (nacked = nacklist->q_forw; nacked != nacklist; nacked = nacked->q_forw)
+ if (nacked->na_client == client) {
+ zdbug3("nack_rel: punt 0x%x, 0x%x",nacked, nacked->na_timer);
+ nack2 = nacked->q_forw; /* go back */
+ timer_reset(nacked->na_timer);
+ xfree(nacked->na_packet);
+ xremque(nacked);
+ nacked = nack2->q_back; /* the remque will have frobbed things */
+ }
+ return;
+}
+
+static void
+nack_cancel(notice, who)
+register ZNotice_t *notice;
+struct sockaddr_in *who;
+{
+ register ZNotAcked_t *nacked;
+ ZClient_t *client;
+
+ notice->z_port = who->sin_port; /* set the origin of the ack to the client who is responding */
+ if ((client = client_which_client(who, notice)) == NULLZCNT) {
+ zdbug1("nack clt not found");
+ return;
+ }
+
+ zdbug2("nack_can: 0x%x", notice->z_uid.zuid_addr.s_addr);
+ zdbug3(" %d %d", notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec);
+ /* search the not-yet-acked list for this packet, and
+ flush it. */
+ for (nacked = nacklist->q_forw; nacked != nacklist; nacked = nacked->q_forw)
+ if ((nacked->na_client == client))
+ if (!bcmp((caddr_t) &nacked->na_uid, (caddr_t) &notice->z_uid, sizeof(nacked->na_uid))) {
+ zdbug1("nack_canceled");
+ timer_reset(nacked->na_timer);
+ xfree(nacked->na_packet);
+ xremque(nacked);
+ return;
+ } else {
+ zdbug1("not this one");
+ zdbug2("nack_can: 0x%x", nacked->na_uid.zuid_addr.s_addr);
+ zdbug3(" %d %d", nacked->na_uid.tv.tv_sec, nacked->na_uid.tv.tv_usec);
+ }
+ zdbug1("nack not found");
+ return;
+}
diff --git a/server/hostm.c b/server/hostm.c
index 879bd90..5a1abc8 100644
--- a/server/hostm.c
+++ b/server/hostm.c
@@ -42,17 +42,22 @@ static char rcsid_hostm_s_c[] = "$Header$";
* void hostm_shutdown()
*
*/
-#define NULLZHLTP ((ZHostList_t **) 0)
-#define NULLZSDTP ((ZServerDesc_t **) 0)
-static ZHostList_t **all_hosts = NULLZHLTP;
-static ZServerDesc_t **all_hosts_servers = NULLZSDTP;
+struct hostlist {
+ ZHostList_t *host;
+ ZServerDesc_t *server;
+};
+
+#define NULLHLT ((struct hostlist *) 0)
+
+static struct hostlist *all_hosts;
static int num_hosts; /* number of hosts in all_hosts */
static void host_detach(), flush(), deathgram(), insert_host(), remove_host();
static Code_t host_attach();
+static int cmp_hostlist();
/*
* We received a HostManager packet. process accordingly.
@@ -64,24 +69,30 @@ int auth;
struct sockaddr_in *who;
{
ZServerDesc_t *owner;
+ ZHostList_t *host;
char *opcode = notice->z_opcode;
Code_t retval;
+
+ zdbug1("hm_disp");
+ owner = hostm_find_server(&who->sin_addr);
if (!strcmp(opcode, HM_BOOT)) {
- if ((owner = hostm_find_server(&who->sin_addr)) == me_server) {
+ zdbug2("boot %s",inet_ntoa(who->sin_addr));
+ if (owner == &otherservers[me_server_idx]) {
zdbug1("hm_disp flushing");
/* I own him. Just cancel any subscriptions */
flush(who, me_server);
} else if (owner == NULLZSDT) {
- zdbug1("hm_disp acquiring");
+ zdbug1("acquiring");
/* no owner. Acquire him. */
- if ((retval = host_attach(who, me_server)) != ZERR_NONE)
+ if ((retval = host_attach(who, me_server)) != ZERR_NONE) {
syslog(LOG_WARNING, "hattach failed: %s",
error_message(retval));
return;
+ }
} else {
- zdbug1("hm_disp hostm_flush'ing");
+ zdbug1("hostm_flush'ing");
/* He has switched servers. Take him, then
tell the owner and other hosts to flush. */
hostm_flush(hostm_find_host(&who->sin_addr), owner);
@@ -91,6 +102,13 @@ struct sockaddr_in *who;
syslog(LOG_WARNING, "hattach failed: %s",
error_message(retval));
}
+ ack(notice, who);
+ } else if (!strcmp(opcode, HM_FLUSH)) {
+ zdbug2("hm_disp flush %s", inet_ntoa(who->sin_addr));
+ if (owner == NULLZSDT || (host = hostm_find_host(&who->sin_addr)) == NULLZHLT)
+ return;
+ hostm_flush(host, owner);
+ return;
} else {
syslog(LOG_WARNING, "hm_disp: unknown opcode %s",opcode);
return;
@@ -112,6 +130,7 @@ ZServerDesc_t *server;
/* and remque()s the client */
client_deregister(clt->zclt_client, host);
+ uloc_hflush(&host->zh_addr);
host_detach(&host->zh_addr.sin_addr, server);
/* XXX tell other servers */
return;
@@ -126,6 +145,7 @@ hostm_shutdown()
register ZHostList_t *hosts = otherservers[me_server_idx].zs_hosts;
register ZHostList_t *host;
+ zdbug1("hostm_shutdown");
if (hosts == NULLZHLT)
return;
@@ -150,7 +170,7 @@ struct in_addr *addr;
{
register int i, rlo, rhi;
- if (all_hosts == (ZHostList_t **) 0)
+ if (all_hosts == NULLHLT)
return(NULLZHLT);
/* i is the current host we are checking */
@@ -161,8 +181,8 @@ struct in_addr *addr;
rlo = 0;
rhi = num_hosts - 1; /* first index is 0 */
- while (all_hosts[i]->zh_addr.sin_addr.s_addr != addr->s_addr) {
- if (all_hosts[i]->zh_addr.sin_addr.s_addr < addr->s_addr)
+ while ((all_hosts[i].host)->zh_addr.sin_addr.s_addr != addr->s_addr) {
+ if ((all_hosts[i].host)->zh_addr.sin_addr.s_addr < addr->s_addr)
rlo = i + 1;
else
rhi = i - 1;
@@ -170,7 +190,7 @@ struct in_addr *addr;
return(NULLZHLT);
i = (rhi + rlo) >> 1; /* split the diff */
}
- return(all_hosts[i]);
+ return(all_hosts[i].host);
}
ZServerDesc_t *
@@ -179,7 +199,7 @@ struct in_addr *addr;
{
register int i, rlo, rhi;
- if (all_hosts == (ZHostList_t **) 0)
+ if (all_hosts == NULLHLT)
return(NULLZSDT);
/* i is the current host we are checking */
@@ -190,8 +210,8 @@ struct in_addr *addr;
rlo = 0;
rhi = num_hosts - 1; /* first index is 0 */
- while (all_hosts[i]->zh_addr.sin_addr.s_addr != addr->s_addr) {
- if (all_hosts[i]->zh_addr.sin_addr.s_addr < addr->s_addr)
+ while ((all_hosts[i].host)->zh_addr.sin_addr.s_addr != addr->s_addr) {
+ if ((all_hosts[i].host)->zh_addr.sin_addr.s_addr < addr->s_addr)
rlo = i + 1;
else
rhi = i - 1;
@@ -199,7 +219,7 @@ struct in_addr *addr;
return(NULLZSDT);
i = (rhi + rlo) >> 1; /* split the diff */
}
- return(all_hosts_servers[i]);
+ return(all_hosts[i].server);
}
static void
@@ -207,52 +227,48 @@ insert_host(host, server)
ZHostList_t *host;
ZServerDesc_t *server;
{
- ZHostList_t **oldlist;
- ZServerDesc_t **oldservs;
+ struct hostlist *oldlist;
register int i = 0;
+ zdbug2("insert_host %s",inet_ntoa(host->zh_addr.sin_addr));
+
if (hostm_find_host(&host->zh_addr.sin_addr) != NULLZHLT)
return;
num_hosts++;
oldlist = all_hosts;
- oldservs = all_hosts_servers;
- if ((all_hosts = (ZHostList_t **) malloc(num_hosts * sizeof(ZHostList_t *))) == NULLZHLTP) {
- syslog(LOG_CRIT, "insert_host: nomem");
- abort();
+ if (!oldlist) { /* this is the first */
+ if ((all_hosts = (struct hostlist *) xmalloc(num_hosts * sizeof(struct hostlist))) == NULLHLT) {
+ syslog(LOG_CRIT, "insert_host: nomem");
+ abort();
+ }
+ all_hosts[0].host = host;
+ all_hosts[0].server = server;
+ return;
}
- if ((all_hosts_servers = (ZServerDesc_t **) malloc(num_hosts * sizeof(ZServerDesc_t *))) == NULLZSDTP) {
- syslog(LOG_CRIT, "insert_host: nomem servers");
+ if ((all_hosts = (struct hostlist *) realloc((caddr_t) oldlist, (unsigned) num_hosts * sizeof(struct hostlist))) == NULLHLT) {
+ syslog(LOG_CRIT, "insert_host: nomem");
abort();
}
- if (!oldlist) { /* this is the first */
- all_hosts[0] = host;
- all_hosts_servers[0] = server;
- return;
- }
+ all_hosts[num_hosts - 1].host = host;
+ all_hosts[num_hosts - 1].server = server;
- /* copy old pointers */
- while (i < (num_hosts - 1) && oldlist[i]->zh_addr.sin_addr.s_addr < host->zh_addr.sin_addr.s_addr) {
- all_hosts[i] = oldlist[i];
- all_hosts_servers[i] = oldservs[i];
- i++;
- }
+ /* sort it */
- /* add this one */
- all_hosts[i] = host;
- all_hosts_servers[i++] = server;
+ qsort((caddr_t) all_hosts, num_hosts, sizeof(struct hostlist), cmp_hostlist);
- /* copy the rest */
- while (i < num_hosts) {
- all_hosts[i] = oldlist[i - 1];
- all_hosts_servers[i] = oldservs[i - 1];
- i++;
+#ifdef DEBUG
+ if (zdebug) {
+ char buf[512];
+ for (i = 0; i < num_hosts; i++)
+ syslog(LOG_DEBUG, "%d: %s %s",i,
+ strcpy(buf,inet_ntoa((all_hosts[i].host)->zh_addr.sin_addr)),
+ inet_ntoa((all_hosts[i].server)->zs_addr.sin_addr));
}
- free(oldlist);
- free(oldservs);
+#endif DEBUG
return;
}
@@ -260,46 +276,63 @@ static void
remove_host(host)
ZHostList_t *host;
{
- ZHostList_t **oldlist;
- ZServerDesc_t **oldservs;
+ struct hostlist *oldlist;
register int i = 0;
+ zdbug1("remove_host");
if (hostm_find_host(&host->zh_addr.sin_addr) == NULLZHLT)
return;
- num_hosts--;
+ if (--num_hosts == 0) {
+ zdbug1("last host");
+ xfree(all_hosts);
+ all_hosts = NULLHLT;
+ return;
+ }
+
oldlist = all_hosts;
- oldservs = all_hosts_servers;
- if ((all_hosts = (ZHostList_t **) malloc(num_hosts * sizeof(ZHostList_t *))) == NULLZHLTP) {
+ if ((all_hosts = (struct hostlist *) xmalloc(num_hosts * sizeof(struct hostlist))) == NULLHLT) {
syslog(LOG_CRIT, "remove_host: nomem");
abort();
}
- if ((all_hosts_servers = (ZServerDesc_t **) malloc(num_hosts * sizeof(ZServerDesc_t *))) == NULLZSDTP) {
- syslog(LOG_CRIT, "remove_host: nomem servers");
- abort();
- }
/* copy old pointers */
- while (i < num_hosts && oldlist[i]->zh_addr.sin_addr.s_addr < host->zh_addr.sin_addr.s_addr) {
+ while (i < num_hosts && (oldlist[i].host)->zh_addr.sin_addr.s_addr < host->zh_addr.sin_addr.s_addr) {
all_hosts[i] = oldlist[i];
- all_hosts_servers[i] = oldservs[i];
i++;
}
i++; /* skip over this one */
/* copy the rest */
- while (i < num_hosts) {
+ while (i <= num_hosts) {
all_hosts[i - 1] = oldlist[i];
- all_hosts_servers[i - 1] = oldservs[i];
i++;
}
- free(oldlist);
- free(oldservs);
+ xfree(oldlist);
+#ifdef DEBUG
+ if (zdebug) {
+ char buf[512];
+ for (i = 0; i < num_hosts; i++)
+ syslog(LOG_DEBUG, "%d: %s %s",i,
+ strcpy(buf,inet_ntoa((all_hosts[i].host)->zh_addr.sin_addr)),
+ inet_ntoa((all_hosts[i].server)->zs_addr.sin_addr));
+ }
+#endif DEBUG
return;
}
+static int
+cmp_hostlist(el1, el2)
+struct hostlist *el1, *el2;
+{
+ if (el1->host->zh_addr.sin_addr.s_addr <
+ el2->host->zh_addr.sin_addr.s_addr) return (-1);
+ else if (el1->host->zh_addr.sin_addr.s_addr ==
+ el2->host->zh_addr.sin_addr.s_addr) return (0);
+ else return(1);
+}
/*
* Flush the info for this host, but maintain ownership.
*/
@@ -311,6 +344,7 @@ ZServerDesc_t *server;
{
register ZHostList_t *hlp = server->zs_hosts;
register ZHostList_t *hlp2;
+ Code_t retval;
zdbug2("flush %s",inet_ntoa(who->sin_addr));
@@ -324,7 +358,9 @@ ZServerDesc_t *server;
return;
}
hostm_flush(hlp2, server);
- host_attach(who, server);
+ if ((retval = host_attach(who, server)) != ZERR_NONE)
+ syslog(LOG_ERR, "flush h_attach: %s",
+ error_message(retval));
}
/*
@@ -340,13 +376,13 @@ ZServerDesc_t *server;
register ZClientList_t *clist;
/* allocate a header */
- if ((hlist = (ZHostList_t *)malloc(sizeof(ZHostList_t))) == NULLZHLT) {
+ if ((hlist = (ZHostList_t *)xmalloc(sizeof(ZHostList_t))) == NULLZHLT) {
syslog(LOG_WARNING, "hm_attach malloc");
return(ENOMEM);
}
/* set up */
- if ((clist = (ZClientList_t *)malloc(sizeof(ZClientList_t))) == NULLZCLT) {
- free(hlist);
+ if ((clist = (ZClientList_t *)xmalloc(sizeof(ZClientList_t))) == NULLZCLT) {
+ xfree(hlist);
return(ENOMEM);
}
clist->q_forw = clist->q_back = clist;
@@ -357,7 +393,7 @@ ZServerDesc_t *server;
/* chain in */
insert_host(hlist, server);
- insque(hlist, server->zs_hosts);
+ xinsque(hlist, server->zs_hosts);
return(ZERR_NONE);
}
@@ -380,10 +416,10 @@ ZServerDesc_t *server;
return;
}
- free(hlist->zh_clients);
- remque(hlist);
+ xfree(hlist->zh_clients);
+ xremque(hlist);
remove_host(hlist);
- free(hlist);
+ xfree(hlist);
return;
}
@@ -396,15 +432,17 @@ struct sockaddr_in *sin;
ZNotice_t shutnotice;
ZPacket_t shutpack;
+ zdbug2("deathgram %s",inet_ntoa(sin->sin_addr));
+
/* fill in the shutdown notice */
shutnotice.z_kind = HMCTL;
shutnotice.z_port = sock_sin.sin_port;
- shutnotice.z_class = HM_CLASS;
- shutnotice.z_class_inst = ZEPHYR_CTL_SERVER;
+ shutnotice.z_class = HM_CTL_CLASS;
+ shutnotice.z_class_inst = HM_CTL_SERVER;
shutnotice.z_opcode = SERVER_SHUTDOWN;
- shutnotice.z_sender = ZEPHYR_CTL_SERVER;
- shutnotice.z_recipient = ZEPHYR_CTL_HM;
+ shutnotice.z_sender = HM_CTL_SERVER;
+ shutnotice.z_recipient = "foo";
shutnotice.z_message = NULL;
shutnotice.z_message_len = 0;
diff --git a/server/subscr.c b/server/subscr.c
index 2036f47..1e847e2 100644
--- a/server/subscr.c
+++ b/server/subscr.c
@@ -14,7 +14,9 @@
#include <zephyr/mit-copyright.h>
#ifndef lint
+#ifndef SABER
static char rcsid_subscr_s_c[] = "$Header$";
+#endif SABER
#endif lint
/*
@@ -22,10 +24,12 @@ static char rcsid_subscr_s_c[] = "$Header$";
*
* External functions:
*
- * Code_t subscr_subscribe(notice)
+ * Code_t subscr_subscribe(sin, notice)
+ * struct sockaddr_in *sin;
* ZNotice_t *notice;
*
- * Code_t subscr_cancel(notice)
+ * Code_t subscr_cancel(sin, notice)
+ * struct sockaddr_in *sin;
* ZNotice_t *notice;
*
* Code_t subscr_cancel_client(client)
@@ -46,23 +50,25 @@ static char rcsid_subscr_s_c[] = "$Header$";
extern char *re_comp(), *rindex(), *index();
static ZSubscr_t *extract_subscriptions();
-static int subscr_equiv();
+static int subscr_equiv(), clt_unique();
static void free_subscriptions(), free_sub();
+/*
+ * subscribe the client to types described in notice.
+ */
+
Code_t
-subscr_subscribe(notice)
+subscr_subscribe(who, notice)
+ZClient_t *who;
ZNotice_t *notice;
{
- ZClient_t *who;
register ZSubscr_t *subs, *subs2, *newsubs, *subs3;
+ ZAcl_t *acl;
Code_t retval;
- if ((who = client_which_client(notice)) == NULLZCNT)
- return(ZSRV_NOCLT);
-
if (who->zct_subs == NULLZST) {
/* allocate a subscription head */
- if ((subs = (ZSubscr_t *) malloc(sizeof(ZSubscr_t))) == NULLZST)
+ if ((subs = (ZSubscr_t *) xmalloc(sizeof(ZSubscr_t))) == NULLZST)
return(ENOMEM);
subs->q_forw = subs->q_back = subs;
who->zct_subs = subs;
@@ -76,6 +82,12 @@ ZNotice_t *notice;
subs = subs->q_forw) {
/* for each new subscription */
+ if ((acl = class_get_acl(subs->zst_class)) != NULLZACLT &&
+ !access_check(notice, acl, SUBSCRIBE)) {
+ syslog(LOG_WARNING, "subscr unauth %s %s",
+ notice->z_sender, subs->zst_class);
+ continue;
+ }
for (subs2 = who->zct_subs->q_forw;
subs2 != who->zct_subs;
subs2 = subs2->q_forw) {
@@ -86,7 +98,7 @@ ZNotice_t *notice;
/* ok, we are a new subscription. register and chain on. */
- if ((subs3 = (ZSubscr_t *) malloc(sizeof(ZSubscr_t))) == NULLZST) {
+ if ((subs3 = (ZSubscr_t *) xmalloc(sizeof(ZSubscr_t))) == NULLZST) {
free_subscriptions(newsubs);
return(ENOMEM);
}
@@ -99,8 +111,9 @@ ZNotice_t *notice;
subs3->zst_class = strsave(subs->zst_class);
subs3->zst_classinst = strsave(subs->zst_classinst);
subs3->zst_recipient = strsave(subs->zst_recipient);
+ subs3->q_forw = subs3->q_back = subs3;
- insque(who->zct_subs, subs3);
+ xinsque(subs3, who->zct_subs);
duplicate: ; /* just go on to the next */
}
@@ -124,52 +137,59 @@ register ZSubscr_t *s1, *s2;
return(1);
}
+#define ADVANCE(xx) { cp += (strlen(cp) + 1); \
+ if (cp >= notice->z_message + notice->z_message_len) { \
+ syslog(LOG_WARNING, "malformed subscription %d", xx); \
+ return(subs); \
+ }}
+
static ZSubscr_t *
extract_subscriptions(notice)
register ZNotice_t *notice;
{
register ZSubscr_t *subs = NULLZST, *subs2;
- register int len = notice->z_message_len;
register char *recip, *class, *classinst;
register char *cp = notice->z_message;
char *buf;
/* parse the data area for the subscriptions */
while (cp < notice->z_message + notice->z_message_len) {
- recip = buf = cp;
- if ((cp = index(buf, ',')) == NULL) {
- syslog(LOG_WARNING, "malformed subscription 1 %s",
- buf);
- return(subs);
- }
- *cp++ = '\0';
class = buf = cp;
- if ((cp = index(buf, ',')) == NULL) {
- syslog(LOG_WARNING, "malformed subscription 2 %s",
- buf);
+ if (*buf == '\0')
+ /* we've exhausted the subscriptions */
+ return(subs);
+ zdbug2("class %s",cp);
+ ADVANCE(1);
+ classinst = buf = cp;
+ zdbug2("clinst %s",cp);
+ ADVANCE(2);
+ recip = cp;
+ zdbug2("recip %s",cp);
+ cp += (strlen(cp) + 1);
+ if (cp > notice->z_message + notice->z_message_len) {
+ syslog(LOG_WARNING, "malformed sub 3");
return(subs);
}
- *cp++ = '\0';
- classinst = cp;
- cp += strlen(classinst);
if (subs == NULLZST) {
- if ((subs = (ZSubscr_t *) malloc(sizeof(ZSubscr_t))) == NULLZST) {
+ if ((subs = (ZSubscr_t *) xmalloc(sizeof(ZSubscr_t))) == NULLZST) {
syslog(LOG_WARNING, "ex_subs: no mem");
return(NULLZST);
}
subs->q_forw = subs->q_back = subs;
+ subs->zst_class = subs->zst_classinst = subs->zst_recipient = NULL;
}
- if ((subs2 = (ZSubscr_t *) malloc(sizeof(ZSubscr_t))) == NULLZST) {
+ if ((subs2 = (ZSubscr_t *) xmalloc(sizeof(ZSubscr_t))) == NULLZST) {
syslog(LOG_WARNING, "ex_subs: no mem 2");
- return(NULLZST);
+ return(subs);
}
subs2->zst_class = strsave(class);
subs2->zst_classinst = strsave(classinst);
subs2->zst_recipient = strsave(recip);
+ subs2->q_forw = subs2->q_back = subs2;
- insque(subs, subs2);
+ xinsque(subs2, subs);
}
- return;
+ return(subs);
}
static void
@@ -178,30 +198,28 @@ register ZSubscr_t *subs;
{
register ZSubscr_t *sub;
- free(subs->zst_class);
- free(subs->zst_classinst);
- free(subs->zst_recipient);
-
for (sub = subs->q_forw; sub != subs; sub = subs->q_forw) {
- free(sub->zst_class);
- free(sub->zst_classinst);
- free(sub->zst_recipient);
- remque(sub);
- free(sub);
+ xfree(sub->zst_class);
+ xfree(sub->zst_classinst);
+ xfree(sub->zst_recipient);
+ xremque(sub);
+ xfree(sub);
}
- free(subs);
+ xfree(subs);
return;
}
Code_t
-subscr_cancel(notice)
+subscr_cancel(sin,notice)
+struct sockaddr_in *sin;
ZNotice_t *notice;
{
ZClient_t *who;
register ZSubscr_t *subs, *subs2;
Code_t retval;
- if ((who = client_which_client(notice)) == NULLZCNT)
+ zdbug1("subscr_cancel");
+ if ((who = client_which_client(sin, notice)) == NULLZCNT)
return(ZSRV_NOCLT);
if (who->zct_subs == NULLZST)
@@ -214,14 +232,22 @@ ZNotice_t *notice;
subs2 != who->zct_subs;
subs2 = subs2->q_forw) {
/* for each existing subscription */
- if (subscr_equiv(subs, subs2)) { /* duplicate? */
- remque(subs2);
+ /* is this what we are canceling? */
+ if (subscr_equiv(subs, subs2)) {
+ xremque(subs2);
if (class_deregister(who, subs2->zst_class) != ZERR_NONE) {
syslog(LOG_ERR, "subscr_cancel: not registered!");
abort();
/*NOTREACHED*/
}
free_sub(subs2);
+ /* make sure we are still registered for all the
+ classes */
+ for (subs2 = who->zct_subs->q_forw;
+ subs2 != who->zct_subs;
+ subs2 = subs2->q_forw)
+ if ((retval = class_register(who, subs2->zst_class)) != ZERR_NONE)
+ return(retval);
return(ZERR_NONE);
}
}
@@ -232,95 +258,126 @@ static void
free_sub(sub)
ZSubscr_t *sub;
{
- free(sub->zst_class);
- free(sub->zst_classinst);
- free(sub->zst_recipient);
- free(sub);
+ xfree(sub->zst_class);
+ xfree(sub->zst_classinst);
+ xfree(sub->zst_recipient);
+ xfree(sub);
return;
}
-Code_t
+void
subscr_cancel_client(client)
register ZClient_t *client;
{
register ZSubscr_t *subs;
+ zdbug1("subscr_cancel_client");
if (client->zct_subs == NULLZST)
- return(ZERR_NONE);
+ return;
for (subs = client->zct_subs->q_forw;
subs != client->zct_subs;
subs = client->zct_subs->q_forw) {
+ zdbug2("sub_can %s",subs->zst_class);
if (class_deregister(client, subs->zst_class) != ZERR_NONE) {
- syslog(LOG_ERR, "sub_can_clt: not registered!");
- abort();
- /*NOTREACHED*/
+ zdbug1("sub_can_clt: not registered!");
}
- remque(subs);
+
+ xremque(subs);
free_sub(subs);
}
- return(ZERR_NONE);
+
+ /* also flush the head of the queue */
+ /* subs is now client->zct_subs */
+ xfree(subs);
+ client->zct_subs = NULLZST;
+
+ return;
}
Code_t
-subscr_cancel_host(addr, server)
+subscr_cancel_host(addr)
struct in_addr *addr;
-ZServerDesc_t *server;
{
register ZHostList_t *hosts;
register ZClientList_t *clist = NULLZCLT, *clt;
- /* find list of clients */
- for (hosts = server->zs_hosts;
- hosts != server->zs_hosts;
- hosts = hosts->q_forw) {
- if (!bcmp(*addr, hosts->zh_addr, sizeof (struct in_addr))) {
- clist = hosts->zh_clients;
- break;
- }
- }
- if (hosts != server->zs_hosts)
- return(ZSRV_WRONGSRV);
+ if ((hosts = hostm_find_host(addr)) == NULLZHLT)
+ return(ZSRV_HNOTFOUND);
+ clist = hosts->zh_clients;
/* flush each one */
for (clt = clist->q_forw; clt != clist; clt = clt->q_forw)
- (void) subscr_cancel_client(clt);
+ (void) subscr_cancel_client(clt->zclt_client);
return(ZERR_NONE);
}
/*
* Here is the bulk of the work in the subscription manager.
* We grovel over the list of clients possibly interested in this
- * notice, and copy into a list on a match.
+ * notice, and copy into a list on a match. Make sure we only add any given
+ * client once.
*/
ZClientList_t *
subscr_match_list(notice)
ZNotice_t *notice;
{
- register ZClientList_t *hits, *clients, *clients2, *hit2;
+ register ZClientList_t *hits, *clients, *majik, *clients2, *hit2;
- if ((hits = (ZClientList_t *) malloc(sizeof(ZClientList_t))) == NULLZCLT)
+ if ((hits = (ZClientList_t *) xmalloc(sizeof(ZClientList_t))) == NULLZCLT)
return(NULLZCLT);
hits->q_forw = hits->q_back = hits;
- if ((clients = class_lookup(notice->z_class)) == NULLZCLT)
- return(NULLZCLT);
+ if ((clients = class_lookup(notice->z_class)) == NULLZCLT) {
+ if ((majik = class_lookup(MATCHALL_CLASS)) == NULLZCLT)
+ return(NULLZCLT);
+ } else
+ majik = class_lookup(MATCHALL_CLASS);
+
+ if (clients != NULLZCLT)
+ for (clients2 = clients->q_forw;
+ clients2 != clients;
+ clients2 = clients2->q_forw)
+ if (cl_match(notice, clients2->zclt_client)) {
+ if (!clt_unique(clients2->zclt_client, hits)) {
+ zdbug2("dup 0x%x", clients2->zclt_client);
+ continue;
+ }
+ zdbug2("matched 0x%x", clients2->zclt_client);
+ /* we hit */
+ if ((hit2 = (ZClientList_t *) xmalloc(sizeof(ZClientList_t))) == NULLZCLT) {
+ syslog(LOG_WARNING,
+ "subscr_match: punting/no mem");
+ return(hits);
+ }
+ hit2->zclt_client = clients2->zclt_client;
+ hit2->q_forw = hit2->q_back = hit2;
+
+ xinsque(hit2, hits);
+ } else zdbug2("didn't match 0x%x",
+ clients2->zclt_client);
- for (clients2 = clients->q_forw;
- clients2 != clients;
- clients2 = clients2->q_forw)
- if (client_match(notice, clients2->zclt_client)) {
+ if (majik != NULLZCLT)
+ for (clients2 = majik->q_forw;
+ clients2 != majik;
+ clients2 = clients2->q_forw) {
+ if (!clt_unique(clients2->zclt_client, hits)) {
+ zdbug2("dup 0x%x", clients2->zclt_client);
+ continue;
+ }
+ zdbug2("matched 0x%x", clients2->zclt_client);
/* we hit */
- if ((hit2 = (ZClientList_t *) malloc(sizeof(ZClientList_t))) == NULLZCLT) {
- syslog(LOG_WARNING, "subscr_match: punting/no mem");
+ if ((hit2 = (ZClientList_t *) xmalloc(sizeof(ZClientList_t))) == NULLZCLT) {
+ syslog(LOG_WARNING,
+ "subscr_match(majik): punting/no mem");
return(hits);
}
hit2->zclt_client = clients2->zclt_client;
- insque(hits, hit2);
- }
-
+ hit2->q_forw = hit2->q_back = hit2;
+ xinsque(hit2, hits);
+ }
if (hits->q_forw == hits)
return(NULLZCLT);
return(hits);
@@ -333,19 +390,36 @@ ZClientList_t *list;
register ZClientList_t *lyst;
for (lyst = list->q_forw; lyst != list; lyst = list->q_forw) {
- remque(lyst);
- free(lyst);
+ xremque(lyst);
+ xfree(lyst);
}
- free(list);
+ xfree(list);
return;
}
-#define ZCLASS_MATCHALL "ZMATCH_ALL"
+/*
+ * is this client unique to this list? 0 = no, 1 = yes
+ */
+static int
+clt_unique(clt, clist)
+ZClient_t *clt;
+ZClientList_t *clist;
+{
+ register ZClientList_t *client;
+
+ for (client = clist->q_forw;
+ client != clist;
+ client = client->q_forw)
+ if (client->zclt_client == clt)
+ return(0);
+ return(1);
+}
+
/*
* is this client listening to this notice? 1=yes, 0=no
*/
static int
-client_match(notice, client)
+cl_match(notice, client)
register ZNotice_t *notice;
register ZClient_t *client;
{
@@ -353,7 +427,7 @@ register ZClient_t *client;
char *reresult;
if (client->zct_subs == NULLZST) {
- syslog(LOG_WARNING, "client_match w/ no subs");
+ syslog(LOG_WARNING, "cl_match w/ no subs");
return(0);
}
@@ -362,10 +436,8 @@ register ZClient_t *client;
subs = subs->q_forw) {
/* for each subscription, do regex matching */
/* we don't regex the class, since wildcard
- matching on the class is disallowed. However,
- we do check for the Magic Class */
- if (strcmp(ZCLASS_MATCHALL, subs->zst_class) &&
- strcmp(notice->z_class, subs->zst_class))
+ matching on the class is disallowed. */
+ if (strcmp(notice->z_class, subs->zst_class))
continue; /* no match */
if ((reresult = re_comp(subs->zst_classinst)) != NULL) {
syslog(LOG_WARNING, "re_comp error %s on '%s'",
diff --git a/server/zserver.h b/server/zserver.h
index 7b0b361..73eee80 100644
--- a/server/zserver.h
+++ b/server/zserver.h
@@ -1,3 +1,5 @@
+#ifndef __ZSERVER_H__
+#define __ZSERVER_H__
/* This file is part of the Project Athena Zephyr Notification System.
* It contains declarations for use in the server.
*
@@ -5,52 +7,240 @@
*
* $Source$
* $Author$
+ * $Header$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
+#include <zephyr/mit-copyright.h>
+
+#include <zephyr/zephyr.h> /* which includes <errno.h>,
+ <sys/types.h>,
+ <netinet/in.h>,
+ <sys/time.h>,
+ <stdio.h> */
+#include <arpa/inet.h>
+#include <zephyr/acl.h>
+
+#include <syslog.h>
+#include "timer.h"
+#include "zsrv_err.h"
+
/* definitions for the Zephyr server */
/* structures */
-typedef struct _ZClientDesc_t {
-/* struct _ZClientDesc_t *q_forw;
- struct _ZClientDesc_t *q_back;*/
- char *dummy;
-} ZClientDesc_t;
+typedef struct _ZSubscr_t {
+ struct _ZSubscr_t *q_forw; /* links in client's subscr. queue */
+ struct _ZSubscr_t *q_back;
+ char *zst_class; /* class of messages */
+ char *zst_classinst; /* class-inst of messages */
+ char *zst_recipient; /* recipient of messages */
+} ZSubscr_t;
-typedef struct _ZEntity_t {
- char *filler; /* fill this in later */
-} ZEntity_t;
+typedef struct _ZClient_t {
+ struct sockaddr_in zct_sin; /* ipaddr/port of client */
+ struct _ZSubscr_t *zct_subs; /* subscriptions */
+ C_Block zct_cblock; /* session key for this client */
+} ZClient_t;
typedef struct _ZClientList_t {
- struct _ZClientList_t *q_forw;
- struct _ZClientList_t *q_back;
- ZClientDesc_t *client;
+ struct _ZClientList_t *q_forw;
+ struct _ZClientList_t *q_back;
+ ZClient_t *zclt_client;
} ZClientList_t;
+typedef struct _ZAcl_t {
+ char *acl_filename;
+} ZAcl_t;
+
+typedef enum _ZAccess_t {
+ TRANSMIT, /* use transmission acl */
+ SUBSCRIBE /* use subscription acl */
+} ZAccess_t;
+
typedef struct _ZClass_t {
- struct _ZClass_t *q_forw;
- struct _ZClass_t *q_back;
- char *classname;
- ZClientList_t *clientlist;
+ struct _ZClass_t *q_forw;
+ struct _ZClass_t *q_back;
+ char *zct_classname;
+ ZAcl_t *zct_acl;
+ ZClientList_t *zct_clientlist;
} ZClass_t;
+typedef struct _ZHMClient_t { /* host manager */
+ struct _ZHMClient_t *q_forw;
+ struct _ZHMClient_t *q_back;
+ struct sockaddr_in zhmct_sin;
+ long zhmct_nexttime; /* time of next keepalive */
+} ZHMClient_t;
-#define NULLZCT ((ZClass_t *) 0)
-#define NULLZCDT ((ZClientDesc_t *) 0)
-#define NULLZCLT ((ZClientList_t *) 0)
+typedef struct _ZHostList_t {
+ struct _ZHostList_t *q_forw;
+ struct _ZHostList_t *q_back;
+ struct _ZClientList_t *zh_clients;
+ struct sockaddr_in zh_addr; /* IP addr/port of hostmanager */
+} ZHostList_t;
+
+typedef enum _server_state {
+ SERV_UP, /* Server is up */
+ SERV_TARDY, /* Server due for a hello */
+ SERV_DEAD, /* Server is considered dead */
+ SERV_STARTING /* Server is between dead and up */
+} server_state;
+
+typedef struct _ZServerDesc_t {
+ server_state zs_state; /* server's state */
+ struct sockaddr_in zs_addr; /* server's address */
+ long zs_timeout; /* Length of timeout in sec */
+ timer zs_timer; /* timer struct for this server */
+ int zs_numsent; /* number of hello's sent */
+ ZHostList_t *zs_hosts; /* pointer to list of info from this
+ server */
+} ZServerDesc_t;
+typedef struct _ZNotAcked_t {
+ struct _ZNotAcked_t *q_forw; /* link to next */
+ struct _ZNotAcked_t *q_back; /* link to prev */
+ timer na_timer; /* timer for retransmit */
+ long na_abstimo; /* absolute timeout to drop after */
+ int na_rexmits; /* number of retransmits */
+ caddr_t na_packet; /* ptr to packet */
+ int na_packsz; /* size of packet */
+ ZUnique_Id_t na_uid; /* uid of packet */
+ ZClient_t *na_client; /* address to send to */
+} ZNotAcked_t;
+
+typedef enum _ZSentType {
+ NOT_SENT, /* message was not xmitted */
+ SENT, /* message was xmitted */
+ AUTH_FAILED, /* authentication failed */
+ NOT_FOUND /* user not found for uloc */
+} ZSentType;
+/* this is just for lint */
+struct qelem {
+ struct qelem *q_forw;
+ struct qelem *q_back;
+ char *q_data;
+};
/* Function declarations */
+
+/* found in access_s.c */
+extern int access_check();
+
+/* found in brain_dump.c */
+extern void get_brain_dump(), send_brain_dump();
+
+/* found in class_s.c */
+extern Code_t class_register(), class_deregister();
+extern ZClientList_t *class_lookup();
+extern ZAcl_t *class_get_acl();
+extern int class_is_control(), class_is_admin(), class_is_hm(), class_is_uloc();
+
+/* found in client_s.c */
+extern Code_t client_register();
+extern void client_deregister();
+extern ZClient_t *client_which_client();
/* found in common.c */
extern char *strsave();
-/* found in cm.c */
-extern Code_t cm_register();
-extern Code_t cm_deregister();
-extern ZClientList_t *cm_lookup();
+/* found in dispatch.c */
+extern void dispatch(), clt_ack(), nack_release(), sendit();
+
+/* found in hostm_s.c */
+extern void hostm_dispatch(), hostm_flush(), hostm_shutdown();
+extern ZHostList_t *hostm_find_host();
+extern ZServerDesc_t *hostm_find_server();
+
+/* found in server_s.c */
+extern void server_timo(), server_dispatch(), server_recover();
+Code_t server_register();
+ZServerDesc_t *server_owner();
+
+/* found in subscr_s.c */
+extern Code_t subscr_cancel(), subscr_subscribe();
+extern ZClientList_t * subscr_match_list();
+extern void subscr_list_free(), subscr_cancel_client();
+
+/* found in uloc_s.c */
+extern void ulogin_dispatch(), ulocate_dispatch(), uloc_hflush();
+
+/* found in zctl.c */
+extern void control_dispatch();
+
+/* found in libc.a */
+char *malloc(), *realloc();
+
+/* global identifiers */
+
+/* found in main.c */
+extern struct in_addr my_addr; /* my inet address */
+extern struct sockaddr_in sock_sin; /* socket descriptors */
+extern int srv_socket; /* dgram sockets for clients
+ and other servers */
+extern int zdebug;
+extern char myname[]; /* domain name of this host */
+extern ZServerDesc_t *otherservers; /* array of servers */
+extern int me_server_idx; /* me (in the array of servers) */
+extern int nservers; /* number of other servers*/
+extern ZNotAcked_t *nacklist; /* list of not ack'ed packets */
+
+/* useful defines */
+
+#define REXMIT_SECS ((long) 10) /* rexmit delay on normal notices */
+#define NUM_REXMITS (5) /* number of rexmits */
+
+#define TIMO_UP ((long) 10) /* timeout between up and tardy */
+#define TIMO_TARDY ((long) 30) /* timeout btw tardy hellos */
+#define TIMO_DEAD ((long)(15*60)) /* timeout between hello's for dead */
+
+#define H_NUM_TARDY 5 /* num hello's before going dead
+ when tardy */
+#define H_NUM_STARTING 2 /* num hello's before going dead
+ when starting */
+
+#define NULLZCT ((ZClass_t *) 0)
+#define NULLZCNT ((ZClient_t *) 0)
+#define NULLZCLT ((ZClientList_t *) 0)
+#define NULLHMCT ((ZHMClient_t *) 0)
+#define NULLZST ((ZSubscr_t *) 0)
+#define NULLZHLT ((ZHostList_t *) 0)
+#define NULLZNAT ((ZNotAcked_t *) 0)
+#define NULLZACLT ((ZAcl_t *) 0)
+#define NULLZPT ((ZPacket_t *) 0)
+#define NULLZSDT ((ZServerDesc_t *) 0)
+
+#define me_server &otherservers[me_server_idx]
+
+#define ack(a,b) clt_ack(a,b,SENT)
+#define nack(a,b) clt_ack(a,b,NOT_SENT)
+
+/* these are to keep lint happy */
+#define xfree(foo) free((caddr_t) (foo))
+#define xinsque(a,b) insque((struct qelem *)(a), (struct qelem *)(b))
+#define xremque(a) remque((struct qelem *)(a))
+#define xmalloc(a) malloc((unsigned)(a))
+
+/* the magic class to match all packets */
+#define MATCHALL_CLASS "ZMATCH_ALL"
+
+/* ACL's for pre-registered classes */
+#define ZEPHYR_CTL_ACL "/usr/athena/lib/zephyr/zctl.acl"
+#define HM_ACL "/usr/athena/lib/zephyr/hm.acl"
+#define LOGIN_ACL "/usr/athena/lib/zephyr/login.acl"
+#define LOCATE_ACL "/usr/athena/lib/zephyr/locate.acl"
+#define MATCH_ALL_ACL "/usr/athena/lib/zephyr/matchall.acl"
+
+/* debugging macros */
+#ifdef DEBUG
+#define zdbug1(s1) if (zdebug) syslog(LOG_DEBUG, s1);
+#define zdbug2(s1,s2) if (zdebug) syslog(LOG_DEBUG, s1, s2);
+#define zdbug3(s1,s2,s3) if (zdebug) syslog(LOG_DEBUG, s1, s2, s3);
+#else !DEBUG
+#define zdbug1(s1)
+#define zdbug2(s1,s2)
+#define zdbug3(s1,s2,s3)
+#endif DEBUG
-/* server internal error codes */
-#define ZERR_S_BADASSOC 2000 /* client not associated with class */
+#endif !__ZSERVER_H__