summaryrefslogtreecommitdiff
path: root/server/dispatch.c.auth
diff options
context:
space:
mode:
authorGravatar Greg Hudson <ghudson@mit.edu>1997-09-14 17:50:06 +0000
committerGravatar Greg Hudson <ghudson@mit.edu>1997-09-14 17:50:06 +0000
commitac16f380e349fa39ec7e26bccb5456cb300006a5 (patch)
treec07ca88af97b4f6b77d28a2dc723d2e4621ed302 /server/dispatch.c.auth
parentd33e482744fad80d95cdd89ed380c5b8401e49bf (diff)
Pull in sources from zephyr locker. See /mit/zephyr/repository for
detailed change information.
Diffstat (limited to 'server/dispatch.c.auth')
-rw-r--r--server/dispatch.c.auth1078
1 files changed, 0 insertions, 1078 deletions
diff --git a/server/dispatch.c.auth b/server/dispatch.c.auth
deleted file mode 100644
index 8707c2f..0000000
--- a/server/dispatch.c.auth
+++ /dev/null
@@ -1,1078 +0,0 @@
-/* This file is part of the Project Athena Zephyr Notification System.
- * It contains functions for dispatching a notice.
- *
- * Created by: John T. Kohl
- *
- * $Source$
- * $Author$
- *
- * Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology.
- * For copying and distribution information, see the file
- * "mit-copyright.h".
- */
-
-#include <zephyr/mit-copyright.h>
-
-#ifndef lint
-#ifndef SABER
-static char rcsid_dispatch_c[] =
- "$Id$";
-#endif
-#endif
-
-#include "zserver.h"
-#include <sys/socket.h>
-
-#ifdef DEBUG
-Zconst char *ZNoticeKinds[9] = {"UNSAFE", "UNACKED", "ACKED", "HMACK",
- "HMCTL", "SERVACK", "SERVNAK", "CLIENTACK",
- "STAT"};
-#endif
-/*
- *
- * External Routines:
- *
- * void dispatch(notice, auth, who)
- * ZNotice_t *notice;
- * int auth;
- * struct sockaddr_in *who;
- *
- * void clt_ack(notice, who, sent)
- * ZNotice_t *notice;
- * struct sockaddr_in *who;
- * ZSentType sent;
- *
- * void nack_release(client)
- * ZClient_t *client;
- *
- * void sendit(notice, auth, who)
- * ZNotice_t *notice;
- * int auth;
- * struct sockaddr_in *who;
- *
- * void xmit(notice, dest, auth, client)
- * ZNotice_t *notice;
- * struct sockaddr_in *dest;
- * int auth;
- * ZClient_t *client;
- */
-
-
-/* patchable magic numbers controlling the retransmission rate and count */
-int num_rexmits = NUM_REXMITS;
-long rexmit_secs = REXMIT_SECS;
-long abs_timo = REXMIT_SECS*NUM_REXMITS + 10;
-
-ZSTRING *class_control, *class_admin, *class_hm, *class_ulogin,
- *class_ulocate;
-
-#ifdef __STDC__
-# define P(s) s
-#else
-# define P(s) ()
-#endif
-
-static void nack_cancel P((register ZNotice_t *, struct sockaddr_in *));
-static void dispatch P((ZNotice_t *, int, struct sockaddr_in *, int));
-static int send_to_dest P((ZNotice_t *, int, ZDestination *dest, int));
-
-#undef P
-
-ZStatistic interserver_notices = {0, "inter-server notices"};
-ZStatistic hm_packets = {0, "hostmanager packets"};
-ZStatistic control_notices = {0, "client control notices"};
-ZStatistic message_notices = {0, "message notices"};
-ZStatistic login_notices = {0, "login notices"};
-ZStatistic i_s_ctls = {0, "inter-server control notices"};
-ZStatistic i_s_logins = {0, "inter-server login notices"};
-ZStatistic i_s_admins = {0, "inter-server admin notices"};
-ZStatistic i_s_locates = {0, "inter-server locate notices"};
-ZStatistic locate_notices = {0, "locate notices"};
-ZStatistic admin_notices = {0, "admin notices"};
-
-static void
-#ifdef __STDC__
-dump_stats (void *arg)
-#else
-dump_stats (arg)
-void *arg;
-#endif
-{
- syslog(LOG_INFO, "stats: %s: %d", hm_packets.str, hm_packets.val);
- syslog(LOG_INFO, "stats: %s: %d", control_notices.str,
- control_notices.val);
- syslog(LOG_INFO, "stats: %s: %d", message_notices.str,
- message_notices.val);
- syslog(LOG_INFO, "stats: %s: %d", login_notices.str,
- login_notices.val);
- syslog(LOG_INFO, "stats: %s: %d", locate_notices.str,
- locate_notices.val);
- syslog(LOG_INFO, "stats: %s: %d", admin_notices.str,
- admin_notices.val);
- syslog(LOG_INFO, "stats: %s: %d", interserver_notices.str,
- interserver_notices.val);
- syslog(LOG_INFO, "stats: %s: %d", i_s_ctls.str, i_s_ctls.val);
- syslog(LOG_INFO, "stats: %s: %d", i_s_logins.str, i_s_logins.val);
- syslog(LOG_INFO, "stats: %s: %d", i_s_admins.str, i_s_admins.val);
- syslog(LOG_INFO, "stats: %s: %d", i_s_locates.str, i_s_locates.val);
- /* log stuff once an hour */
- (void) timer_set_rel ((long) 6*60*60, dump_stats, arg);
-}
-
-/*
- * Handle an input packet.
- * Warning: this function may be called from within a brain dump.
- */
-
-void
-handle_packet()
-{
- Code_t status;
- ZPacket_t input_packet; /* from the network */
- ZNotice_t new_notice; /* parsed from input_packet */
- int input_len; /* len of packet */
- struct sockaddr_in input_sin; /* Zconstructed for authent */
- struct sockaddr_in whoisit; /* for holding peer's address */
- int authentic; /* authentic flag */
- ZSrvPending_t *pending; /* pending packet */
- ZHostList_t *host; /* host ptr */
- int from_server; /* packet is from another server */
-#ifdef DEBUG
- static int first_time = 1;
-#endif
-
-#ifdef DEBUG
- /* Dump statistics five minutes after startup */
- if (first_time) {
- first_time = 0;
- (void) timer_set_rel (5*60, dump_stats, (void *) 0);
- }
-#endif
- /* handle traffic */
-
- if (otherservers[me_server_idx].zs_update_queue) {
- /* something here for me; take care of it */
-#if 1
- zdbug((LOG_DEBUG, "internal queue process"));
-#endif
-
- pending = otherservers[me_server_idx].zs_update_queue->q_forw;
- host = hostm_find_host(&(pending->pend_who.sin_addr));
- if (host && host->zh_locked) {
- /* can't deal with it now. to preserve ordering,
- we can't process other packets, esp. since we
- may block since we don't really know if there
- are things in the real queue. */
-#if 1
- zdbug((LOG_DEBUG,"host %s is locked",
- inet_ntoa(host->zh_addr.sin_addr)));
-#endif
- return;
- }
- pending = server_dequeue(me_server); /* we can do it, remove */
-
- if ((status = ZParseNotice(pending->pend_packet,
- pending->pend_len,
- &new_notice)) != ZERR_NONE) {
- syslog(LOG_ERR,
- "bad notice parse (%s): %s",
- inet_ntoa(pending->pend_who.sin_addr),
- error_message(status));
- } else
- dispatch(&new_notice, pending->pend_auth,
- &pending->pend_who, 1);
- server_pending_free(pending);
- return;
- }
- /*
- * nothing in internal queue, go to the external library
- * queue/socket
- */
- if ((status = ZReceivePacket(input_packet,
- &input_len,
- &whoisit)) != ZERR_NONE) {
- syslog(LOG_ERR,
- "bad packet receive: %s from %s",
- error_message(status), inet_ntoa(whoisit.sin_addr));
- return;
- }
- npackets++;
- if ((status = ZParseNotice(input_packet,
- input_len,
- &new_notice)) != ZERR_NONE) {
- syslog(LOG_ERR,
- "bad notice parse (%s): %s",
- inet_ntoa(whoisit.sin_addr),
- error_message(status));
- return;
- }
- if (server_which_server(&whoisit)) {
- /* we need to parse twice--once to get
- the source addr, second to check
- authentication */
- (void) memset((caddr_t) &input_sin, 0,
- sizeof(input_sin));
- input_sin.sin_addr.s_addr = new_notice.z_sender_addr.s_addr;
- input_sin.sin_port = new_notice.z_port;
- input_sin.sin_family = AF_INET;
- authentic = ZCheckAuthentication(&new_notice, &input_sin);
- from_server = 1;
- } else {
- from_server = 0;
- authentic = ZCheckAuthentication(&new_notice, &whoisit);
- }
-
- if (whoisit.sin_port != hm_port &&
- strcasecmp (new_notice.z_class,ZEPHYR_ADMIN_CLASS) &&
- whoisit.sin_port != sock_sin.sin_port &&
- new_notice.z_kind != CLIENTACK) {
- syslog(LOG_ERR,
- "bad port %s/%d",
- inet_ntoa(whoisit.sin_addr),
- ntohs(whoisit.sin_port));
- return;
- }
-
- message_notices.val++;
- dispatch(&new_notice, authentic, &whoisit, from_server);
- return;
-}
-/*
- * Dispatch a notice.
- */
-
-static void
-dispatch(notice, auth, who, from_server)
- ZNotice_t *notice;
- int auth;
- struct sockaddr_in *who;
- int from_server;
-{
- Code_t status;
- ZSTRING *notice_class;
- struct sockaddr_in who2;
- int authflag;
-#ifdef DEBUG
- char dbg_buf[BUFSIZ];
-#endif
-
- /* Set "authflag" to 1 or 0 for handler functions. Treat
- * ZAUTH_CKSUM_FAILED as authentic except for sendit(), which is
- * handled below. */
- switch (auth) {
- case ZAUTH_YES:
- case ZAUTH_CKSUM_FAILED:
- authflag = 1;
- break;
- case ZAUTH_FAILED:
- case ZAUTH_NO:
- default:
- authflag = 0;
- break;
- }
-
- if ((int) notice->z_kind < (int) UNSAFE ||
- (int) notice->z_kind > (int) CLIENTACK) {
- syslog(LOG_NOTICE, "bad notice kind 0x%x from %s",
- (int) notice->z_kind,
- inet_ntoa(who->sin_addr));
- return;
- }
-#if 0
- if (zdebug) {
- (void) sprintf (dbg_buf,
- "disp:%s '%s' '%s' '%s' notice to '%s' from '%s' %s/%d/%d",
- ZNoticeKinds[(int) notice->z_kind],
- notice->z_class,
- notice->z_class_inst,
- notice->z_opcode,
- notice->z_recipient,
- notice->z_sender,
- inet_ntoa(who->sin_addr),
- ntohs(who->sin_port),
- ntohs(notice->z_port));
- syslog (LOG_DEBUG, "%s", dbg_buf);
- }
-#endif
-
- if (notice->z_kind == CLIENTACK) {
- nack_cancel(notice, who);
- return;
- }
-
- who2 = *who;
-#if 0
- if (0 && from_server) {
- /* incorporate server_dispatch here */
- }
-#endif
- notice_class = make_zstring(notice->z_class,1);
-
- if (from_server) {
- interserver_notices.val++;
- status = server_dispatch(notice, auth, who);
- } else if (class_is_hm(notice_class)) {
- hm_packets.val++;
- status = hostm_dispatch(notice, auth, who, me_server);
- } else if (class_is_control(notice_class)) {
- control_notices.val++;
- status = control_dispatch(notice, auth, who, me_server);
- } else if (class_is_ulogin(notice_class)) {
- login_notices.val++;
- status = ulogin_dispatch(notice, auth, who, me_server);
- } else if (class_is_ulocate(notice_class)) {
- locate_notices.val++;
- status = ulocate_dispatch(notice, auth, who, me_server);
- } else if (class_is_admin(notice_class)) {
- admin_notices.val++;
- status = server_adispatch(notice, auth, who, me_server);
- } else {
- if (auth == ZAUTH_CKSUM_FAILED)
- authflag = 0;
- sendit (notice, auth, who);
- free_zstring(notice_class);
- return;
- }
-
- if (status == ZSRV_REQUEUE) {
-#ifdef CONCURRENT
- server_self_queue(notice, auth, who);
-#else
- syslog(LOG_ERR, "requeue while not concurr");
- abort();
-#endif
- }
- free_zstring(notice_class);
-}
-
-/*
- * Send a notice off to those clients who have subscribed to it.
- */
-
-void
-sendit(notice, auth, who)
- ZNotice_t *notice;
- int auth;
- struct sockaddr_in *who;
-{
- static int send_counter = 0;
- int any = 0;
- ZAcl_t *acl;
- ZDestination dest;
- ZSTRING *class;
-
- class = make_zstring(notice->z_class,1);
- if ((acl = class_get_acl(class)) != NULLZACLT) {
- /* if controlled and not auth, fail */
- if (!auth) {
- syslog(LOG_WARNING, "sendit unauthentic %s from %s",
- notice->z_class, notice->z_sender);
- clt_ack(notice, who, AUTH_FAILED);
- free_zstring(class);
- return;
- }
- /* if not auth to transmit, fail */
- if (!access_check(notice->z_sender, acl, TRANSMIT)) {
- syslog(LOG_WARNING, "sendit unauthorized %s from %s",
- notice->z_class, notice->z_sender);
- clt_ack(notice, who, AUTH_FAILED);
- free_zstring(class);
- return;
- }
- /* sender != inst and not auth to send to others --> fail */
- if ((strcmp (notice->z_sender, notice->z_class_inst)) &&
- (!access_check(notice->z_sender, acl, INSTUID))) {
- syslog(LOG_WARNING,
- "sendit unauth uid %s %s.%s",
- notice->z_sender,
- notice->z_class,
- notice->z_class_inst);
- clt_ack(notice, who, AUTH_FAILED);
- free_zstring(class);
- return;
- }
- }
- if (memcmp(&notice->z_sender_addr.s_addr, &who->sin_addr.s_addr,
- sizeof(notice->z_sender_addr.s_addr))) {
- /* someone is playing games... */
- /* inet_ntoa returns pointer to static area */
- /* max size is 255.255.255.255 */
- char buffer[16];
- (void) strcpy(buffer, inet_ntoa(who->sin_addr));
- if (!auth) {
- syslog(LOG_WARNING, "sendit unauthentic fake packet: claimed %s, real %s",
- inet_ntoa(notice->z_sender_addr), buffer);
- clt_ack(notice, who, AUTH_FAILED);
- free_zstring(class);
- return;
- }
- if (ntohl(notice->z_sender_addr.s_addr) != 0) {
- syslog(LOG_WARNING, "sendit invalid address: claimed %s, real %s",
- inet_ntoa(notice->z_sender_addr), buffer);
- clt_ack(notice, who, AUTH_FAILED);
- free_zstring(class);
- return;
- }
- syslog(LOG_WARNING, "sendit addr mismatch: claimed %s, real %s",
- inet_ntoa(notice->z_sender_addr), buffer);
- }
-
- /* Increment the send counter, used to prevent duplicate sends to
- * clients. On the off-chance that we wrap around to 0, skip over
- * it to prevent missing clients which have never had a packet
- * sent to them. */
- send_counter++;
- if (send_counter == 0)
- send_counter = 1;
-
- /* Send to clients subscribed to the triplet itself. */
- dest.classname = class;
- dest.inst = make_zstring(notice->z_class_inst, 1);
- dest.recip = make_zstring(notice->z_recipient, 0);
- if (send_to_dest(notice, auth, &dest, send_counter))
- any = 1;
-
- /* Send to clients subscribed to the triplet with the instance
- * substituted with the wildcard instance. */
- free_zstring(dest.inst);
- dest.inst = wildcard_instance;
- if (send_to_dest(notice, auth, &dest, send_counter))
- any = 1;
-
- free_zstring(class);
- free_zstring(dest.recip);
- if (any)
- ack(notice, who);
- else
- nack(notice, who);
-}
-
-/*
- * Send to each client in the list. Avoid duplicates by setting
- * last_send on each client to send_counter, a nonce which is updated
- * by sendit() above.
- */
-
-static int
-send_to_dest(notice, auth, dest, send_counter)
- ZNotice_t *notice;
- int auth;
- ZDestination *dest;
- int send_counter;
-{
- register ZClientList_t *list, *p;
- register ZClient_t *client;
- register int any = 0;
-
- list = triplet_lookup(dest);
- if (list != NULLZCLT) {
- for (p = list->q_forw; p != list; p = p->q_forw) {
- client = p->zclt_client;
- if (client->last_send == send_counter)
- continue;
- client->last_send = send_counter;
- xmit(notice, &(client->zct_sin), auth, client);
- any = 1;
- }
- }
- return any;
-}
-
-/*
- * Clean up the not-yet-acked queue and release anything destined
- * for the client.
- */
-
-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;)
- if ((nacked->na_addr.sin_addr.s_addr == client->zct_sin.sin_addr.s_addr) &&
- (nacked->na_addr.sin_port == client->zct_sin.sin_port)) {
- /* go back, since remque will change things */
- nack2 = nacked->q_back;
- timer_reset(nacked->na_timer);
- xremque(nacked);
- xfree(nacked->na_packet);
- xfree(nacked);
- /* now that the remque adjusted the linked list,
- we go forward again */
- nacked = nack2->q_forw;
- } else
- nacked = nacked->q_forw;
- return;
-}
-
-/*
- * Send one packet of a fragmented message to a client. After transmitting,
- * put it onto the not ack'ed list.
- */
-
-/* the arguments must be the same as the arguments to Z_XmitFragment */
-/*ARGSUSED*/
-Code_t
-xmit_frag(notice, buf, len, waitforack)
- ZNotice_t *notice;
- char *buf;
- int len;
- int waitforack;
-{
- char *savebuf;
- register ZNotAcked_t *nacked;
- Code_t retval;
-
- if ((retval = ZSendPacket(buf, len, 0)) != ZERR_NONE) {
- syslog(LOG_WARNING, "xmit_frag send: %s",
- error_message(retval));
- return(retval);
- }
-
- /* now we've sent it, mark it as not ack'ed */
-
- if (!(nacked = (ZNotAcked_t *)xmalloc(sizeof(ZNotAcked_t)))) {
- /* no space: just punt */
- syslog(LOG_WARNING, "xmit_frag nack malloc");
- return(ENOMEM);
- }
-
- if (!(savebuf = (char *)xmalloc(len))) {
- /* no space: just punt */
- syslog(LOG_WARNING, "xmit_frag pack malloc");
- return(ENOMEM);
- }
-
- (void) memcpy(savebuf, buf, len);
-
- nacked->na_rexmits = 0;
- nacked->na_packet = savebuf;
- nacked->na_srv_idx = 0;
- nacked->na_addr = ZGetDestAddr();
- nacked->na_packsz = len;
- nacked->na_uid = notice->z_uid;
- nacked->q_forw = nacked->q_back = nacked;
- nacked->na_abstimo = NOW + abs_timo;
-
- /* set a timer to retransmit when done */
- nacked->na_timer = timer_set_rel(rexmit_secs,
- rexmit,
- (void *) nacked);
- /* chain in */
- xinsque(nacked, nacklist);
- return(ZERR_NONE);
-}
-
-/*
- * Send the notice to the client. After transmitting, put it onto the
- * not ack'ed list.
- */
-
-void
-xmit(notice, dest, auth, client)
- ZNotice_t *notice;
- struct sockaddr_in *dest;
- int auth;
- ZClient_t *client;
-{
- caddr_t noticepack;
- register ZNotAcked_t *nacked;
- int packlen;
- Code_t retval;
-
-#if 0
- zdbug((LOG_DEBUG,"xmit"));
-#endif
-
- if (!(noticepack = (caddr_t) xmalloc(sizeof(ZPacket_t)))) {
- syslog(LOG_ERR, "xmit malloc");
- return; /* DON'T put on nack list */
- }
-
- packlen = sizeof(ZPacket_t);
-
- if (auth && client) { /*
- we are distributing authentic and
- we have a pointer to auth info
- */
-#ifdef KERBEROS
-
- 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 /* !KERBEROS */
- notice->z_auth = 1;
- if ((retval = ZFormatSmallRawNotice(notice,
- noticepack,
- &packlen))
- != ZERR_NONE) {
- syslog(LOG_ERR, "xmit auth/raw format: %s",
- error_message(retval));
- xfree(noticepack);
- return;
- }
-#endif /* KERBEROS */
- } else {
- notice->z_auth = 0;
- notice->z_authent_len = 0;
- notice->z_ascii_authent = (char *)"";
- if ((retval = ZFormatSmallRawNotice(notice,
- noticepack,
- &packlen)) != ZERR_NONE) {
- syslog(LOG_ERR, "xmit format: %s",
- error_message(retval));
- xfree(noticepack);
- return; /* DON'T put on nack list */
- }
- }
-#if 0
- zdbug((LOG_DEBUG," to %s/%d",inet_ntoa(dest->sin_addr),
- ntohs(dest->sin_port)));
-#endif
- if ((retval = ZSetDestAddr(dest)) != ZERR_NONE) {
- syslog(LOG_WARNING, "xmit set addr: %s",
- error_message(retval));
- xfree(noticepack);
- return;
- }
- if ((retval = ZSendPacket(noticepack, packlen, 0)) != ZERR_NONE) {
- syslog(LOG_WARNING, "xmit xmit: (%s/%d) %s",
- inet_ntoa(dest->sin_addr), ntohs(dest->sin_port),
- error_message(retval));
- xfree(noticepack);
- return;
- }
-
- /* now we've sent it, mark it as not ack'ed */
-
- if (!(nacked = (ZNotAcked_t *)xmalloc(sizeof(ZNotAcked_t)))) {
- /* no space: just punt */
- syslog(LOG_WARNING, "xmit nack malloc");
- xfree(noticepack);
- return;
- }
-
- nacked->na_rexmits = 0;
- nacked->na_packet = noticepack;
- nacked->na_srv_idx = 0; /* XXX */
- nacked->na_addr = *dest;
- 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 to retransmit when done */
- nacked->na_timer = timer_set_rel(rexmit_secs,
- rexmit,
- (void *) nacked);
- /* chain in */
- xinsque(nacked, nacklist);
-
-}
-
-
-/*
- * Retransmit the packet specified. If we have timed out or retransmitted
- * too many times, punt the packet and initiate the host recovery algorithm
- * Else, increment the count and re-send the notice packet.
- */
-
-void
-#ifdef __STDC__
-rexmit(void *arg)
-#else
-rexmit(arg)
- void *arg;
-#endif
-{
- register ZNotAcked_t *nackpacket = (ZNotAcked_t*) arg;
- int retval;
- ZNotice_t dummy_notice;
- register ZClient_t *client;
-
-#if 1
- zdbug((LOG_DEBUG,"rexmit"));
-#endif
-
- if (++(nackpacket->na_rexmits) > num_rexmits ||
- NOW > nackpacket->na_abstimo) {
- /* possibly dead client */
-
- dummy_notice.z_port = nackpacket->na_addr.sin_port;
-
- client = client_which_client(&nackpacket->na_addr,
- &dummy_notice);
-
- /* unlink & free packet */
- xremque(nackpacket);
- xfree(nackpacket->na_packet);
- xfree(nackpacket);
-
- /* initiate recovery */
- if (client)
- server_recover(client);
- return;
- }
-
- /* retransmit the packet */
-
-#if 0
- zdbug((LOG_DEBUG," to %s/%d",
- inet_ntoa(nackpacket->na_addr.sin_addr),
- ntohs(nackpacket->na_addr.sin_port)));
-#endif
- if ((retval = ZSetDestAddr(&nackpacket->na_addr))
- != ZERR_NONE) {
- syslog(LOG_WARNING, "rexmit set addr: %s",
- error_message(retval));
- goto requeue;
-
- }
- if ((retval = ZSendPacket(nackpacket->na_packet,
- nackpacket->na_packsz, 0)) != ZERR_NONE)
- syslog(LOG_WARNING, "rexmit xmit: %s", error_message(retval));
-
-requeue:
- /* reset the timer */
- nackpacket->na_timer = timer_set_rel(rexmit_secs,
- rexmit,
- (void *) nackpacket);
- return;
-
-}
-
-/*
- * Send an acknowledgement to the sending client, by sending back the
- * header from the original notice with the z_kind field changed to either
- * SERVACK or SERVNAK, and the contents of the message either SENT or
- * NOT_SENT, depending on the value of the sent argument.
- */
-
-void
-clt_ack(notice, who, sent)
- ZNotice_t *notice;
- struct sockaddr_in *who;
- ZSentType sent;
-{
- ZNotice_t acknotice;
- ZPacket_t ackpack;
- int packlen;
- int notme = 0;
- char *sent_name;
- Code_t retval;
-
- if (bdumping) { /* don't ack while dumping */
-#if 1
- zdbug((LOG_DEBUG,"bdumping, no ack"));
-#endif
- return;
- }
-
- acknotice = *notice;
-
- acknotice.z_kind = SERVACK;
- switch (sent) {
- case SENT:
- acknotice.z_message = ZSRVACK_SENT;
- sent_name = "sent";
- break;
- case NOT_FOUND:
- acknotice.z_message = ZSRVACK_FAIL;
- acknotice.z_kind = SERVNAK;
- sent_name = "fail";
- break;
- case AUTH_FAILED:
- acknotice.z_kind = SERVNAK;
- acknotice.z_message = ZSRVACK_NOTSENT;
- sent_name = "nak/not_sent";
- break;
- case NOT_SENT:
- acknotice.z_message = ZSRVACK_NOTSENT;
- sent_name = "not_sent";
- break;
- default:
- abort ();
- }
-
-#if 0
- zdbug((LOG_DEBUG,"clt_ack type %s for %d to %s/%d",
- sent_name,
- ntohs(notice->z_port),
- inet_ntoa(who->sin_addr),
- ntohs(who->sin_port)));
-#endif
-
- if (!server_which_server(who) &&
- (hostm_find_server(&who->sin_addr) != me_server)) {
-#if 0
- zdbug((LOG_DEBUG,"not me"));
-#endif
- notme = 1;
- }
-
- acknotice.z_multinotice = "";
-
- /* leave room for the trailing null */
- acknotice.z_message_len = strlen(acknotice.z_message) + 1;
-
- packlen = sizeof(ackpack);
-
- if ((retval = ZFormatSmallRawNotice(&acknotice,
- ackpack,
- &packlen)) != ZERR_NONE) {
- syslog(LOG_ERR, "clt_ack format: %s",error_message(retval));
- return;
- }
- if ((retval = ZSetDestAddr(who)) != ZERR_NONE) {
- syslog(LOG_WARNING, "clt_ack set addr: %s",
- error_message(retval));
- return;
- }
- if ((retval = ZSendPacket(ackpack, packlen, 0)) != ZERR_NONE) {
- syslog(LOG_WARNING, "clt_ack xmit: %s", error_message(retval));
- return;
- }
- else
- zdbug ((LOG_DEBUG, "packet sent"));
- if (notme)
- hostm_deathgram(who, me_server);
- return;
-}
-
-/*
- * An ack has arrived.
- * remove the packet matching this notice from the not-yet-acked queue
- */
-
-static void
-nack_cancel(notice, who)
- register ZNotice_t *notice;
- struct sockaddr_in *who;
-{
- register ZNotAcked_t *nacked;
-
- /* search the not-yet-acked list for this packet, and
- flush it. */
-#if 0
- zdbug((LOG_DEBUG, "nack_cancel: %s:%08X,%08X",
- inet_ntoa (notice->z_uid.zuid_addr),
- notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec));
-#endif
- for (nacked = nacklist->q_forw;
- nacked != nacklist;
- nacked = nacked->q_forw)
- if ((nacked->na_addr.sin_addr.s_addr == who->sin_addr.s_addr) &&
- (nacked->na_addr.sin_port == who->sin_port))
- if (ZCompareUID(&nacked->na_uid, &notice->z_uid)) {
- timer_reset(nacked->na_timer);
- xfree(nacked->na_packet);
- xremque(nacked);
- xfree(nacked);
- return;
- }
-#if 1
- zdbug((LOG_DEBUG,"nack_cancel: nack not found %s:%08X,%08X",
- inet_ntoa (notice->z_uid.zuid_addr),
- notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec));
-#endif
- return;
-}
-
-/* for compatibility when sending subscription information to old clients */
-#ifdef OLD_COMPAT
-#define OLD_ZEPHYR_VERSION "ZEPH0.0"
-#endif /* OLD_COMPAT */
-
-/*
- * Dispatch a ZEPHYR_CTL notice.
- */
-
-Code_t
-control_dispatch(notice, auth, who, server)
- ZNotice_t *notice;
- int auth;
- struct sockaddr_in *who;
- ZServerDesc_t *server;
-{
- register char *opcode = notice->z_opcode;
- ZClient_t *client;
- ZHostList_t *host;
- Code_t retval;
- int wantdefs;
-
- /*
- * ZEPHYR_CTL Opcodes expected are:
- * BOOT (inst HM): host has booted; flush data.
- * CLIENT_SUBSCRIBE: process with the subscription mananger.
- * CLIENT_UNSUBSCRIBE: ""
- * CLIENT_CANCELSUB: ""
- */
-
- zdbug ((LOG_DEBUG, "ctl_disp: opc=%s", opcode));
-
- if (!strcasecmp (notice->z_class_inst, ZEPHYR_CTL_HM))
- return(hostm_dispatch(notice, auth, who, server));
- else if (!strcmp (opcode, CLIENT_GIMMESUBS) ||
- !strcmp (opcode, CLIENT_GIMMEDEFS)) {
- /* this special case is before the auth check so that
- someone who has no subscriptions does NOT get a SERVNAK
- but rather an empty list. Note we must therefore
- check authentication inside subscr_sendlist */
-#ifdef OLD_COMPAT
- /* only acknowledge if *not* old version; the old version
- acknowledges the packet with the reply */
- if (strcmp (notice->z_version, OLD_ZEPHYR_VERSION))
- ack(notice, who);
-#else /* !OLD_COMPAT */
- ack(notice, who);
-#endif /* OLD_COMPAT */
- subscr_sendlist(notice, auth, who);
- return(ZERR_NONE);
- } else if (!auth) {
-#if 0
- zdbug((LOG_DEBUG,"unauth ctrl_disp"));
-#endif
- if (server == me_server)
- clt_ack(notice, who, AUTH_FAILED);
- return(ZERR_NONE);
- }
-
- /* the rest of the expected opcodes modify state; check for
- unlocked host first */
- host = hostm_find_host(&who->sin_addr);
- if (host && host->zh_locked)
- return(ZSRV_REQUEUE);
-
- wantdefs = strcmp (opcode, CLIENT_SUBSCRIBE_NODEFS);
- if (!wantdefs || !strcmp (opcode, CLIENT_SUBSCRIBE)) {
- /* subscription notice */
- if (!(client = client_which_client(who, notice))) {
- if ((retval = client_register(notice,
- who,
- &client,
- server,
- wantdefs)) != ZERR_NONE)
- {
- syslog(LOG_NOTICE,
- "subscr. register %s/%s/%d failed: %s",
- notice->z_sender,
- inet_ntoa(who->sin_addr),
- ntohs(notice->z_port),
- error_message(retval));
- if (server == me_server) {
- if (retval == ZSRV_BADSUBPORT) {
- clt_ack(notice, who, AUTH_FAILED);
- } else
- hostm_deathgram(who, me_server);
- }
- return(ZERR_NONE);
- }
- if (!(client = client_which_client(who, notice))) {
- syslog(LOG_CRIT, "subscr reg. failure");
- abort();
- }
- }
- if (strcmp (client->zct_principal->string, notice->z_sender)) {
- /* you may only subscribe for your own clients */
- if (server == me_server)
- clt_ack(notice, who, AUTH_FAILED);
- return(ZERR_NONE);
- }
-#ifdef KERBEROS
- /* in case it's changed */
- (void) memcpy((caddr_t) client->zct_cblock, (caddr_t) ZGetSession(),
- sizeof(C_Block));
-#endif
- if ((retval = subscr_subscribe(client,notice)) != ZERR_NONE) {
- syslog(LOG_WARNING, "subscr failed: %s",
- error_message(retval));
- if (server == me_server)
- nack(notice, who);
- return(ZERR_NONE);
- }
- } else if (!strcmp(opcode, CLIENT_UNSUBSCRIBE)) {
- if ((client = client_which_client(who,notice)) != NULLZCNT) {
- if (strcmp(client->zct_principal->string, notice->z_sender)) {
- /* you may only cancel for your own clients */
- if (server == me_server)
- clt_ack(notice, who, AUTH_FAILED);
- return(ZERR_NONE);
- }
-#if 0
- if (zdebug) {
- if (server == me_server)
- syslog (LOG_DEBUG,
- "subscription cancel for %s/%d\n",
- inet_ntoa (who->sin_addr),
- ntohs (who->sin_port));
- else
- syslog (LOG_DEBUG,
- "subscription cancel for %s/%d from %s\n",
- inet_ntoa (who->sin_addr),
- ntohs (who->sin_port),
- server->addr);
- }
-#endif
- (void) subscr_cancel(who, notice);
- } else {
- nack(notice, who);
- return(ZERR_NONE);
- }
- } else if (!strcmp(opcode, CLIENT_CANCELSUB)) {
- /* canceling subscriptions implies I can punt info about
- this client */
- if ((client = client_which_client(who,notice)) != NULLZCNT) {
- if (strcmp(client->zct_principal->string, notice->z_sender)) {
- /* you may only cancel for your own clients */
- if (server == me_server)
- clt_ack(notice, who, AUTH_FAILED);
- return(ZERR_NONE);
- }
- if (host) {
- /* don't flush locations here, let him
- do it explicitly */
-#if 0
- zdbug((LOG_DEBUG, "cancelsub clt_dereg %s/%d",
- inet_ntoa (who->sin_addr),
- ntohs (who->sin_port)));
-#endif
- hostm_lose_ignore(client);
- (void) client_deregister(client, host, 0);
- }
-
- }
- if (!client || !host) {
-#if 0
- zdbug((LOG_DEBUG,"can_sub not found client"));
-#endif
- if (server == me_server)
- nack(notice, who);
- return(ZERR_NONE);
- }
- } else {
- syslog(LOG_WARNING, "unknown ctl opcode %s", opcode);
- if (server == me_server)
- nack(notice, who);
- return(ZERR_NONE);
- }
-
- if (server == me_server) {
- ack(notice, who);
- server_forward(notice, auth, who);
- }
- return(ZERR_NONE);
-}
-
-