diff options
author | John Kohl <jtkohl@mit.edu> | 1987-07-01 00:15:34 +0000 |
---|---|---|
committer | John Kohl <jtkohl@mit.edu> | 1987-07-01 00:15:34 +0000 |
commit | 478c419fa7eefc83ef1f92c18ca1d62dd78130c4 (patch) | |
tree | 88a69fcba3740b5bb4f8f51075ebeeb13fb4036a | |
parent | 86cbbc339a0cb723c1a7dcd77808b8dacc810457 (diff) |
first release version
-rw-r--r-- | server/client.c | 125 | ||||
-rw-r--r-- | server/dispatch.c | 295 | ||||
-rw-r--r-- | server/hostm.c | 182 | ||||
-rw-r--r-- | server/subscr.c | 258 | ||||
-rw-r--r-- | server/zserver.h | 238 |
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, ¬ice->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) ¬ice->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__ |