]> asedeno.scripts.mit.edu Git - 1ts-debian.git/commitdiff
Import new release
authorkcr <kcr@cbed1d16-5ef5-0310-b6a1-d4a37b08ba1f>
Wed, 20 Jun 2001 06:48:38 +0000 (06:48 +0000)
committerkcr <kcr@cbed1d16-5ef5-0310-b6a1-d4a37b08ba1f>
Wed, 20 Jun 2001 06:48:38 +0000 (06:48 +0000)
git-svn-id: svn://svn.1ts.org/debian/branches/upstream@81 cbed1d16-5ef5-0310-b6a1-d4a37b08ba1f

22 files changed:
zephyr/clients/zaway/zaway.1
zephyr/clients/zaway/zaway.c
zephyr/clients/zctl/zctl.1
zephyr/clients/znol/znol.c
zephyr/server/bdump.c
zephyr/server/class.c
zephyr/server/dispatch.c
zephyr/server/kopt.c
zephyr/server/kstuff.c
zephyr/server/main.c
zephyr/server/realm.c
zephyr/server/server.c
zephyr/server/subscr.c
zephyr/server/uloc.c
zephyr/server/zserver.h
zephyr/zhm/zhm.c
zephyr/zhm/zhm.h
zephyr/zhm/zhm_server.c
zephyr/zwgc/main.c
zephyr/zwgc/zephyr.c
zephyr/zwgc/zwgc.1
zephyr/zwgc/zwgc.desc

index 724adbc48e1be3dd985dbcb8f5ad22f042b9d763..5332cf22f5a01c54e85c91e5ca9f9f71328714a2 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: zaway.1,v 1.9 1999/07/21 12:34:18 ghudson Exp $
+.\"    $Id: zaway.1,v 1.10 2000/07/13 23:19:58 ghudson Exp $
 .\"
 .\" Copyright 1987,1988 by the Massachusetts Institute of Technology
 .\" All rights reserved.  The file /usr/include/zephyr/mit-copyright.h
@@ -77,11 +77,11 @@ not able to receive your message.
 .in -5
 .sp
 If a user name does not match any of those listed in the file, and no
-"*" or "%" field is specified, no return message is sent.
-All messages are preceded by the line "Automated reply:".
-To avoid loops, messages are not sent in response to messages beginning
-with "Automated reply:" or sent by the same Kerberos principal as the
-user running 
+"*" or "%" field is specified, no return message is sent.  All
+messages are preceded by a signature "Automated reply:".  To avoid
+loops, messages are not sent in response to messages beginning with an
+"Automated reply:" signature or sent by the same Kerberos principal as
+the user running
 .I zaway.
 
 .SH SAMPLE FILE
index 66da6e735a7502eb4d47c66764ffa80bd0fdc512..f3235e8fc481af1f5d62a23bfab912c596f7ebb1 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     Created by:     Robert French
  *
- *     $Id: zaway.c,v 1.14 1999/07/21 12:34:22 ghudson Exp $
+ *     $Id: zaway.c,v 1.15 2000/07/05 21:22:06 ghudson Exp $
  *
  *     Copyright (c) 1987, 1993 by the Massachusetts Institute of Technology.
  *     For copying and distribution information, see the file
@@ -17,7 +17,7 @@
 #include <com_err.h>
 
 #ifndef lint
-static const char rcsid_zaway_c[] = "$Id: zaway.c,v 1.14 1999/07/21 12:34:22 ghudson Exp $";
+static const char rcsid_zaway_c[] = "$Id: zaway.c,v 1.15 2000/07/05 21:22:06 ghudson Exp $";
 #endif
 
 #define MESSAGE_CLASS "MESSAGE"
@@ -113,7 +113,7 @@ int main(argc,argv)
        }
 
        fp = fopen(awayfile,"r");
-       if (!fp && argc > 1) {
+       if (!fp && argc > optind) {
                fprintf(stderr,"File %s not found!\n",awayfile);
                exit(1);
        } 
@@ -136,7 +136,8 @@ int main(argc,argv)
 
        for (;;) {
                if ((retval = ZReceiveNotice(&notice, (struct sockaddr_in *)0)) != ZERR_NONE) {
-                       com_err(argv[0],retval,"while receiving notice");
+                       if (retval != ETIMEDOUT)
+                               com_err(argv[0],retval,"while receiving notice");
                        continue;
                }
 
index 425ca096a933acd1e37b9fbad997d108456e2e2e..a200ffd7e9d8647ba5c761c5139aaaea115a2978 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: zctl.1,v 1.12 1999/01/22 23:18:29 ghudson Exp $
+.\"    $Id: zctl.1,v 1.13 2000/08/10 15:12:56 ghudson Exp $
 .\"
 .\" Copyright 1987,1988 by the Massachusetts Institute of Technology
 .\" All rights reserved.  The file /usr/include/zephyr/mit-copyright.h
@@ -125,6 +125,19 @@ performs the equivalent of a
 .B wg_startup
 command.
 .br
+The variable \fBresolved_addresses\fR determines whether zwgc will,
+for an IP address indicating the origin of a message, attempt to look
+up the hostname corresponding to that IP address. The value none
+indicates that hostnames will never be found, and that the zwgc
+fromhost variable will thus always contain an IP address (in
+dotted-decimal form). The value all indicates that there will always
+be an attempt to look up a hostname. Note that in this case, if you
+have any subscriptions with recipient ``\fI*\fR'', these subscriptions
+may be revealed to other Zephyr users who operate their own DNS name
+servers. Any other value is interpreted as a regular expression;
+hostname lookup attempts will occur only if the IP address matches
+this regular expression.
+.br
 Any variable settings you make will be stored in \fI$HOME/.zephyr.vars\fR
 .TP
 .B show \fIvar\fR [ \fIvar\fR \ ... ]
index 34de2bb1e61074812b9294a97104c85199c7c485..67f7a5e83842b28d2e3934ce8dff0dc8618fc7fe 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     Created by:     Robert French
  *
- *     $Id: znol.c,v 1.16 1999/10/15 04:59:55 ghudson Exp $
+ *     $Id: znol.c,v 1.17 2000/05/08 15:59:05 ghudson Exp $
  *
  *     Copyright (c) 1987 by the Massachusetts Institute of Technology.
  *     For copying and distribution information, see the file
@@ -16,7 +16,7 @@
 #include <pwd.h>
 
 #ifndef lint
-static const char rcsid_znol_c[] = "$Id: znol.c,v 1.16 1999/10/15 04:59:55 ghudson Exp $";
+static const char rcsid_znol_c[] = "$Id: znol.c,v 1.17 2000/05/08 15:59:05 ghudson Exp $";
 #endif 
 
 #define SUBSATONCE 7
@@ -194,7 +194,8 @@ main(argc,argv)
                if (ind == SUBSATONCE) {
                        if (!justlist)
                                if ((retval = (onoff==ON)?
-                                    ZSubscribeTo(subs,ind,(u_short)wgport):
+                                    ZSubscribeToSansDefaults(subs,ind,
+                                                             (u_short)wgport):
                                     ZUnsubscribeTo(subs,ind,(u_short)wgport)) !=
                                    ZERR_NONE) {
                                        com_err(argv[0],retval,(onoff==ON)?
@@ -210,7 +211,7 @@ main(argc,argv)
 
        if (ind && !justlist)
                if ((retval = (onoff==ON)?
-                    ZSubscribeTo(subs,ind,(u_short)wgport):
+                    ZSubscribeToSansDefaults(subs,ind,(u_short)wgport):
                     ZUnsubscribeTo(subs,ind,(u_short)wgport)) !=
                    ZERR_NONE) {
                        com_err(argv[0],retval,(onoff==ON)?
index 95a8b6efd3cf80bc5c780a1cf49c048145b82254..da5015a6c93ed701689fcaa7a132839402ca566f 100644 (file)
@@ -3,7 +3,9 @@
  *
  *     Created by:     John T. Kohl
  *
- *     $Id: bdump.c,v 1.52 1999/01/22 23:19:39 ghudson Exp $
+ *     $Source: /afs/dev.mit.edu/source/repository/athena/lib/zephyr/server/bdump.c,v $
+ *     $Id: bdump.c,v 1.54 2001/02/27 04:43:01 zacheiss Exp $
+ *     $Author: zacheiss $
  *
  *     Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
  *     For copying and distribution information, see the file
@@ -16,7 +18,7 @@
 #include <com_err.h>
 
 #ifndef lint
-static const char rcsid_bdump_c[] = "$Id: bdump.c,v 1.52 1999/01/22 23:19:39 ghudson Exp $";
+static const char rcsid_bdump_c[] = "$Id: bdump.c,v 1.54 2001/02/27 04:43:01 zacheiss Exp $";
 #endif /* lint */
 
 /*
@@ -66,7 +68,6 @@ static void cleanup __P((Server *server));
 
 #ifdef HAVE_KRB4
 static long ticket_time;
-static char my_realm[REALM_SZ];
 
 #define TKTLIFETIME    120
 #define tkt_lifetime(val) ((long) val * 5L * 60L)
@@ -474,10 +475,10 @@ bdump_get_v12 (notice, auth, who, server)
        cleanup(server);
        return;
     }
-    /* my_realm is filled in inside get_tgt() */
+
     if (strcmp(kdata.pname, SERVER_SERVICE) ||
        strcmp(kdata.pinst, SERVER_INSTANCE) ||
-       strcmp(kdata.prealm, my_realm)) {
+       strcmp(kdata.prealm, ZGetRealm())) {
        syslog(LOG_ERR, "bdump_get: peer not zephyr in lrealm: %s.%s@%s",
               kdata.pname, kdata.pinst,kdata.prealm);
        cleanup(server);
@@ -582,6 +583,8 @@ bdump_send_list_tcp(kind, addr, class_name, inst, opcode, sender, recip, lyst,
     Code_t retval;
     u_short length;
 
+    memset (&notice, 0, sizeof(notice));
     retval = ZMakeAscii(addrbuf, sizeof(addrbuf),
                        (unsigned char *) &addr->sin_addr,
                        sizeof(struct in_addr));
@@ -692,16 +695,8 @@ get_tgt()
     Sched *s;
 #endif
        
-    if (!*my_realm) {
-       retval = krb_get_lrealm(my_realm, 1);
-       if (retval != KSUCCESS) {
-           syslog(LOG_ERR,"krb_get_lrealm: %s", krb_get_err_text(retval));
-           *my_realm = '\0';
-           return(1);
-       }
-    }
     /* have they expired ? */
-    if (ticket_time < NOW - tkt_lifetime(TKTLIFETIME) + 15L) {
+    if (ticket_time < NOW - tkt_lifetime(TKTLIFETIME) + (15L * 60L)) {
        /* +15 for leeway */
 #if 0
        zdbug((LOG_DEBUG,"get new tickets: %d %d %d", ticket_time, NOW,
@@ -816,13 +811,10 @@ bdump_recv_loop(server)
        }
 #if defined (DEBUG)
        if (zdebug) {
-           char buf[4096];
-
-           sprintf(buf, "bdump:%s '%s' '%s' '%s' '%s' '%s'",
+           syslog(LOG_DEBUG, "bdump:%s '%s' '%s' '%s' '%s' '%s'",
                    ZNoticeKinds[(int) notice.z_kind], notice.z_class,
                    notice.z_class_inst, notice.z_opcode, notice.z_sender,
                    notice.z_recipient);
-           syslog(LOG_DEBUG, buf);
        }
 #endif /* DEBUG */
        if (notice.z_num_other_fields >= 1) {
@@ -847,8 +839,10 @@ bdump_recv_loop(server)
        } else if (strcmp(notice.z_opcode, ADMIN_NEWREALM) == 0) {
            /* get a realm from the message */
            realm = realm_get_realm_by_name(notice.z_message);
-           if (!realm)
-               return(ZERR_NONE);
+           if (!realm) {
+               syslog(LOG_ERR, "brl newrlm failed: no realm %s", 
+                      notice.z_message);
+           }
        } else if (strcmp(notice.z_class, LOGIN_CLASS) == 0) {
            /* 1 = tell it we are authentic */
            retval = ulogin_dispatch(&notice, 1, &who, server);
@@ -890,7 +884,7 @@ bdump_recv_loop(server)
                syslog(LOG_ERR, "brl no client");
                return ZSRV_NOCLT;
            }
-           retval = subscr_subscribe(client, &notice);
+           retval = subscr_subscribe(client, &notice, server);
            if (retval != ZERR_NONE) {
                syslog(LOG_WARNING, "brl subscr failed: %s",
                       error_message(retval));
@@ -898,16 +892,17 @@ bdump_recv_loop(server)
            }
        } else if (strcmp(notice.z_opcode, REALM_SUBSCRIBE) == 0) {
            /* add a subscription for a realm */
-           if (!realm) {
-               syslog(LOG_ERR, "brl no realm");
-               return(ZSRV_NORLM);
-           }
-           retval = subscr_realm(realm, &notice);
-           if (retval != ZERR_NONE) {
-               syslog(LOG_WARNING, "brl subscr failed: %s",
-                      error_message(retval));
-               return retval;
-           }
+           if (realm) {
+               retval = subscr_realm(realm, &notice);
+               if (retval != ZERR_NONE) {
+                   syslog(LOG_WARNING, "brl subscr failed: %s",
+                          error_message(retval));
+                   return retval;
+               }
+           } /* else 
+                /* Other side tried to send us subs for a realm we didn't
+                   know about, and so we drop them silently */
+       
        } else {
            syslog(LOG_ERR, "brl bad opcode %s",notice.z_opcode);
            return ZSRV_UNKNOWNOPCODE;
@@ -974,6 +969,8 @@ send_list(kind, port, class_name, inst, opcode, sender, recip, lyst, num)
     int packlen;
     Code_t retval;
  
+    memset (&notice, 0, sizeof(notice));
+
     notice.z_kind = kind;
     notice.z_port = port;
     notice.z_class = class_name;
@@ -1014,6 +1011,8 @@ send_normal_tcp(kind, port, class_name, inst, opcode, sender, recip,
     Code_t retval;
     u_short length;
  
+    memset (&notice, 0, sizeof(notice));
+
     notice.z_kind = kind;
     notice.z_port = port;
     notice.z_class = class_name;
index 4f92d20b4d73ec53886a47aa6990f3f4654907b8..c84286499feaae58b49cfeafa893a3f454276bbf 100644 (file)
@@ -3,7 +3,8 @@
  *
  *     Created by:     John T. Kohl
  *
- *     $Id: class.c,v 1.26 1999/01/22 23:19:40 ghudson Exp $
+ *     $Source: /afs/dev.mit.edu/source/repository/athena/lib/zephyr/server/class.c,v $
+ *     $Author: zacheiss $
  *
  *     Copyright (c) 1987 by the Massachusetts Institute of Technology.
  *     For copying and distribution information, see the file
@@ -16,7 +17,7 @@
 
 #if !defined (lint) && !defined (SABER)
 static const char rcsid_class_c[] =
-"$Id: class.c,v 1.26 1999/01/22 23:19:40 ghudson Exp $";
+"$Id: class.c,v 1.27 2001/02/27 04:43:59 zacheiss Exp $";
 #endif
 
 /*
@@ -158,6 +159,7 @@ triplet_deregister(client, dest, realm)
            if (*triplet->clients == NULL && !triplet->acl) {
                LIST_DELETE(triplet);
                free_triplet(triplet);
+               return ZSRV_EMPTYCLASS;
            }
            return ZERR_NONE;
        }
index a4ab079d08fbc59c203d4a5c756c0fd37b7dae32..276f7ea2d739b5b94a83e3c73034f035e75513c3 100644 (file)
@@ -3,7 +3,8 @@
  *
  *     Created by:     John T. Kohl
  *
- *     $Id: dispatch.c,v 1.60 2000/02/11 20:59:36 ghudson Exp $
+ *     $Source: /afs/dev.mit.edu/source/repository/athena/lib/zephyr/server/dispatch.c,v $
+ *     $Author: ghudson $
  *
  *     Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology.
  *     For copying and distribution information, see the file
@@ -17,7 +18,7 @@
 #ifndef lint
 #ifndef SABER
 static const char rcsid_dispatch_c[] =
-"$Id: dispatch.c,v 1.60 2000/02/11 20:59:36 ghudson Exp $";
+"$Id: dispatch.c,v 1.63 2001/04/10 23:28:19 ghudson Exp $";
 #endif
 #endif
 
@@ -51,10 +52,11 @@ ZCONST char *ZNoticeKinds[9] = {"UNSAFE", "UNACKED", "ACKED", "HMACK",
  * void nack_release(client)
  *     Client *client;
  *
- * void sendit(notice, auth, who)
+ * void sendit(notice, auth, who, external)
  *     ZNotice_t *notice;
  *     int auth;
  *     struct sockaddr_in *who;
+ *      int external;
  *
  * void xmit(notice, dest, auth, client)
  *     ZNotice_t *notice;
@@ -190,21 +192,33 @@ handle_packet()
        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;
-       realm = realm_which_realm(&input_sin);
-       if (realm) {
-           authentic = ZCheckRealmAuthentication(&new_notice, &input_sin,
-                                                 realm->name);
-       } else {
+        /* Should check to see if packet is from another realm's server, 
+           or a client */
+        /* Clients don't check auth of acks, nor do we make it so they
+           can in general, so this is safe. */
+        if (new_notice.z_kind == SERVACK || new_notice.z_kind == SERVNAK) {
+          authentic = ZAUTH_YES;
+        } else {
+          if (realm = realm_which_realm(&input_sin)) {
+            authentic = ZCheckRealmAuthentication(&new_notice,
+                                                  &input_sin,
+                                                  realm->name);
+          } else 
            authentic = ZCheckAuthentication(&new_notice, &input_sin);
        }
        from_server = 1;
     } else {
        from_server = 0;
-       realm = realm_which_realm(&whoisit);
-       if (realm) {
-           authentic = ZCheckRealmAuthentication(&new_notice, &whoisit,
-                                                 realm->name);
-       } else {
+        /* Clients don't check auth of acks, nor do we make it so they
+           can in general, so this is safe. */
+        if (new_notice.z_kind == SERVACK || new_notice.z_kind == SERVNAK) {
+          authentic = ZAUTH_YES;
+        } else {
+          if (realm = realm_which_realm(&whoisit)) {
+            authentic = ZCheckRealmAuthentication(&new_notice,
+                                                  &whoisit,
+                                                  realm->name);
+          } else
            authentic = ZCheckAuthentication(&new_notice, &whoisit);
        }
     }
@@ -253,13 +267,12 @@ dispatch(notice, auth, who, from_server)
     }
 #if 0
     if (zdebug) {
-       sprintf(dbg_buf,
+       syslog(LOG_DEBUG,
                "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
 
@@ -298,12 +311,13 @@ dispatch(notice, auth, who, from_server)
        admin_notices.val++;
        status = server_adispatch(notice, authflag, who, me_server);
     } else {
-       if (!bound_for_local_realm(notice)) {
+       if (!realm_bound_for_realm(ZGetRealm(), notice->z_recipient)) {
            cp = strchr(notice->z_recipient, '@');
            if (!cp ||
-               !(realm = realm_get_realm_by_name(realm_expand_realm(cp + 1))))
+               !(realm = realm_get_realm_by_name(cp + 1))) {
+               /* Foreign user, local realm */
                sendit(notice, authflag, who, 0);
-           else
+           else
                realm_handoff(notice, authflag, who, realm, 1);
        } else {
            if (notice->z_recipient[0] == '@')
@@ -338,15 +352,29 @@ sendit(notice, auth, who, external)
     String *class;
 
     class = make_string(notice->z_class, 1);
-    acl = class_get_acl(class);
-    if (acl != NULL) {
+    if (realm_bound_for_realm(ZGetRealm(), notice->z_recipient)) {
+      Realm *rlm;
+
+      acl = class_get_acl(class);
+      if (acl != NULL) {
        /* if controlled and not auth, fail */
-       if (!auth) {
-           syslog(LOG_WARNING, "sendit unauthentic %s from %s",
-                  notice->z_class, notice->z_sender);
+        if (!auth) {
+            syslog(LOG_WARNING, "sendit unauthentic %s from %s",
+                   notice->z_class, notice->z_sender);
+           clt_ack(notice, who, AUTH_FAILED);
+            free_string(class);
+            return;
+        }
+       /* if from foreign realm server, disallow if not realm of sender */
+       rlm = realm_which_realm(who);
+       if (rlm) {
+         if (!realm_sender_in_realm(rlm->name, notice->z_sender)) {
+           syslog(LOG_WARNING, "sendit auth not verifiable %s (%s) from %s",
+                  notice->z_class, rlm->name, notice->z_sender);
            clt_ack(notice, who, AUTH_FAILED);
            free_string(class);
            return;
+         }
        }
        /* if not auth to transmit, fail */
        if (!access_check(notice->z_sender, acl, TRANSMIT)) {
@@ -365,6 +393,7 @@ sendit(notice, auth, who, external)
            free_string(class);
            return;
        }
+      }
     }
     if (!realm_which_realm(who)) {
        if (memcmp(&notice->z_sender_addr.s_addr, &who->sin_addr.s_addr,
@@ -406,15 +435,17 @@ sendit(notice, auth, who, external)
     /* Send to clients subscribed to the triplet itself. */
     dest.classname = class;
     dest.inst = make_string(notice->z_class_inst, 1);
-    if (bound_for_local_realm(notice) && *notice->z_recipient == '@') {
-       dest.recip = make_string("", 0);
-    } else {
-       strncpy(recipbuf, notice->z_recipient, sizeof(recipbuf));
-       recipp = strrchr(recipbuf, '@');
-       if (recipp)
-           sprintf(recipp + 1, "%s", realm_expand_realm(recipp + 1));
-       dest.recip = make_string(recipbuf, 0);
+    if (realm_bound_for_realm(ZGetRealm(), notice->z_recipient) && 
+       *notice->z_recipient == '@') 
+      dest.recip = make_string("", 0);
+    else {
+      strncpy(recipbuf, notice->z_recipient, sizeof(recipbuf));
+      recipp = strrchr(recipbuf, '@');
+      if (recipp)
+       sprintf(recipp + 1, "%s", realm_expand_realm(recipp + 1));
+      dest.recip = make_string(recipbuf, 0);
     }
+
     if (send_to_dest(notice, auth, &dest, send_counter, external))
        any = 1;
 
@@ -458,12 +489,16 @@ send_to_dest(notice, auth, dest, send_counter, external)
        if ((*clientp)->last_send == send_counter)
            continue;
        (*clientp)->last_send = send_counter;
-       if ((*clientp)->realm && external)
+       if ((*clientp)->realm) {
+         if (external) {
            realm_handoff(notice, auth, &clientp[0]->addr, clientp[0]->realm,
                          1);
-       else
+           any = 1;
+         }
+       } else {
            xmit(notice, &((*clientp)->addr), auth, *clientp);
-       any = 1;
+           any = 1;
+       }
     }
 
     return any;
@@ -606,6 +641,104 @@ xmit(notice, dest, auth, client)
        notice->z_authent_len = 0;
        notice->z_ascii_authent = (char *)"";
        retval = ZFormatSmallRawNotice(notice, noticepack, &packlen);
+        /* This code is needed because a Zephyr can "grow" when a remote 
+         * realm name is inserted into the Zephyr before being resent out
+         * locally. It essentially matches the code in realm.c to do the
+         * same thing with authentic Zephyrs.
+         */
+        if (retval == ZERR_PKTLEN) {
+          ZNotice_t partnotice, newnotice;
+          char multi[64];
+          char *buffer, *ptr;
+          int buffer_len, hdrlen, offset, fragsize, ret_len, message_len;
+          int origoffset, origlen;
+
+          free(noticepack);
+
+          retval = ZSetDestAddr(dest);
+          if (retval != ZERR_NONE) {
+            syslog(LOG_WARNING, "xmit set addr: %s", error_message(retval));
+            return;
+          }
+
+          partnotice = *notice;
+          
+          partnotice.z_auth = 0;
+          partnotice.z_authent_len = 0;
+          partnotice.z_ascii_authent = (char *)"";
+
+          origoffset = offset = fragsize = 0;
+          origlen = notice->z_message_len;
+
+          buffer = (char *) malloc(sizeof(ZPacket_t));
+          if (!buffer) {
+            syslog(LOG_ERR, "xmit unauth refrag malloc");
+            return;                 /* DON'T put on nack list */
+          }
+          buffer_len = sizeof(ZPacket_t);
+
+          retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, 
+                                     &hdrlen, NULL, NULL);
+          if (retval != ZERR_NONE) {
+            syslog(LOG_ERR, "xmit unauth refrag fmt: failed");
+            free(buffer);
+            return;
+          }
+
+          if (notice->z_multinotice && strcmp(notice->z_multinotice, ""))
+            if (sscanf(notice->z_multinotice, "%d/%d", &origoffset, &origlen)
+                != 2) 
+              {
+                syslog(LOG_WARNING, "xmit unauth refrag: parse failed");
+                free(buffer);
+                return;
+              }
+
+              fragsize = Z_MAXPKTLEN-hdrlen-Z_FRAGFUDGE;
+
+          while (offset < notice->z_message_len || !notice->z_message_len) {
+            (void) sprintf(multi, "%d/%d", offset+origoffset, origlen);
+            partnotice.z_multinotice = multi;
+            if (offset > 0) {
+              (void) gettimeofday(&partnotice.z_uid.tv, (struct timezone *)0);
+              partnotice.z_uid.tv.tv_sec = htonl((u_long)
+                                                 partnotice.z_uid.tv.tv_sec);
+              partnotice.z_uid.tv.tv_usec = htonl((u_long)
+                                                  partnotice.z_uid.tv.tv_usec);
+              (void) memcpy((char *)&partnotice.z_uid.zuid_addr, &__My_addr,
+                            sizeof(__My_addr));
+            }
+            partnotice.z_message = notice->z_message+offset;
+            message_len = min(notice->z_message_len-offset, fragsize);
+            partnotice.z_message_len = message_len;
+
+            retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, 
+                                       &hdrlen, &ptr, NULL);
+            if (retval != ZERR_NONE) {
+              syslog(LOG_WARNING, "xmit unauth refrag raw: %s",
+                     error_message(retval));
+              free(buffer);
+              return;
+            }
+
+            ptr = buffer+hdrlen;
+
+            (void) memcpy(ptr, partnotice.z_message, partnotice.z_message_len);
+            
+            buffer_len = hdrlen+partnotice.z_message_len;
+
+            xmit_frag(&partnotice, buffer, buffer_len, 0);
+
+            offset += fragsize;
+
+            if (!notice->z_message_len)
+              break;
+          }
+          free(buffer);
+          return;
+        }
+        /* End of refrag code */
+
        if (retval != ZERR_NONE) {
            syslog(LOG_ERR, "xmit format: %s", error_message(retval));
            free(noticepack);
@@ -786,6 +919,18 @@ clt_ack(notice, who, sent)
     packlen = sizeof(ackpack);
 
     retval = ZFormatSmallRawNotice(&acknotice, ackpack, &packlen);
+
+    if (retval == ZERR_HEADERLEN) {
+      /* Since an ack header can be larger than a message header... (crock) */ 
+      acknotice.z_opcode = "";
+      acknotice.z_class = "";
+      acknotice.z_class_inst = "";
+      acknotice.z_opcode = "";
+      acknotice.z_default_format = "";
+
+      retval = ZFormatSmallRawNotice(&acknotice, ackpack, &packlen);
+    }
+
     if (retval != ZERR_NONE) {
        syslog(LOG_ERR, "clt_ack format: %s", error_message(retval));
        return;
@@ -1022,7 +1167,7 @@ control_dispatch(notice, auth, who, server)
        /* in case it's changed */
        memcpy(client->session_key, ZGetSession(), sizeof(C_Block));
 #endif
-       retval = subscr_subscribe(client, notice);
+       retval = subscr_subscribe(client, notice, server);
        if (retval != ZERR_NONE) {
            syslog(LOG_WARNING, "subscr failed: %s", error_message(retval));
            if (server == me_server)
@@ -1080,9 +1225,11 @@ control_dispatch(notice, auth, who, server)
 #endif
        client_deregister(client, 0);
     } else {
-       syslog(LOG_WARNING, "unknown ctl opcode %s", opcode);
-       if (server == me_server)
-           nack(notice, who);
+       syslog(LOG_WARNING, "unknown ctl opcode %s", opcode); 
+       if (server == me_server) {
+           if (strcmp(notice->z_class_inst, ZEPHYR_CTL_REALM) != 0)
+               nack(notice, who);
+       }
        return ZERR_NONE;
     }
 
@@ -1120,6 +1267,31 @@ hostm_shutdown()
     }
 }
 
+void
+realm_shutdown()
+{
+    int i, s, newserver;
+    struct sockaddr_in sin;
+
+    for (i = 0; i < nservers; i++) {
+        if (i != me_server_idx && otherservers[i].state == SERV_UP)
+            break;
+    }
+    zdbug((LOG_DEBUG, "rlm_shutdown"));
+
+    newserver = (i < nservers);
+    if (newserver) {
+      while (1) {
+       s = (random() % (nservers - 1)) + 1;
+       if (otherservers[s].state == SERV_UP)
+         break;
+      }
+      realm_deathgram(&otherservers[s]);
+    } else {
+      realm_deathgram(NULL);
+    }
+}
+
 static void
 hostm_deathgram(sin, server)
     struct sockaddr_in *sin;
@@ -1130,6 +1302,8 @@ hostm_deathgram(sin, server)
     ZNotice_t shutnotice;
     char *shutpack;
 
+    memset (&shutnotice, 0, sizeof(shutnotice));
+
     shutnotice.z_kind = HMCTL;
     shutnotice.z_port = sin->sin_port; /* we are sending it */
     shutnotice.z_class = HM_CTL_CLASS;
index eccdc21ba7f071ee22b6ef0ae5e799331ab10eae..9f87d22d618eff37453135421d6abdbd77b4b821 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * $Id: kopt.c,v 1.14 1999/01/22 23:19:44 ghudson Exp $
+ * $Source: /afs/dev.mit.edu/source/repository/athena/lib/zephyr/server/kopt.c,v $
+ * $Author: zacheiss $
  *
  * Copyright 1985, 1986, 1987, 1988, 1990, 1991 by the Massachusetts
  * Institute of Technology.
@@ -21,7 +22,7 @@
 #ifndef lint
 #ifndef SABER
 static const char *rcsid_rd_req_c =
-    "$Id: kopt.c,v 1.14 1999/01/22 23:19:44 ghudson Exp $";
+    "$Id: kopt.c,v 1.16 2001/02/27 04:48:01 zacheiss Exp $";
 #endif /* lint */
 #endif /* SABER */
 
@@ -296,8 +297,9 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn)
         mutual = 0;
 #endif /* lint */
     s_kvno = *ptr++;           /* get server key version */
-    strcpy(realm,ptr);         /* And the realm of the issuing KDC */
-    ptr += strlen(ptr) + 1;     /* skip the realm "hint" */
+    strncpy(realm,ptr,REALM_SZ);/* And the realm of the issuing KDC */
+    realm[REALM_SZ-1] = '\0';
+    ptr += strlen(realm) + 1;     /* skip the realm "hint" */
 
     /*
      * If "fn" is NULL, key info should already be set; don't
@@ -377,16 +379,19 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn)
 #define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED);
 
     ptr = (char *) req_id->dat;
-    strcpy(r_aname,ptr);       /* Authentication name */
+    strncpy(r_aname, ptr, ANAME_SZ);   /* Authentication name */
+    r_aname[ANAME_SZ-1] = '\0';
     ptr += strlen(r_aname) + 1;
     check_ptr();
-    strcpy(r_inst,ptr);                /* Authentication instance */
+    strncpy(r_inst, ptr, INST_SZ);     /* Authentication instance */
+    r_inst[INST_SZ-1] = '\0';
     ptr += strlen(r_inst) + 1;
     check_ptr();
-    strcpy(r_realm,ptr);       /* Authentication name */
+    strncpy(r_realm, ptr, REALM_SZ);   /* Authentication name */
+    r_realm[REALM_SZ-1] = '\0';
     ptr += strlen(r_realm) + 1;
     check_ptr();
-    memcpy(&ad->checksum, ptr, 4);     /* Checksum */
+    memcpy(&ad->checksum, ptr, 4);      /* Checksum */
     ptr += 4;
     check_ptr();
     if (swap_bytes)
@@ -492,122 +497,4 @@ krb_find_ticket(authent, ticket)
 
     return RD_AP_OK;
 }
-
-static char local_realm_buffer[REALM_SZ+1];
-
-int
-krb_get_lrealm(r,n)
-    char *r;
-    int n;
-{
-    FILE *cnffile, *fopen();
-
-    if (n > 1)
-       return KFAILURE;  /* Temporary restriction */
-
-    if (my_realm[0]) {
-       strcpy(r, my_realm);
-       return KSUCCESS;
-    }
-
-    if (local_realm_buffer[0]) {
-       strcpy(r, local_realm_buffer);
-       return KSUCCESS;
-    }
-    
-    cnffile = fopen(KRB_CONF, "r");
-    if (cnffile == NULL) {
-       if (n == 1) {
-           strcpy(r, KRB_REALM);
-           return KSUCCESS;
-       } else {
-           return KFAILURE;
-       }
-    }
-
-    if (fscanf(cnffile,"%s",r) != 1) {
-        fclose(cnffile);
-        return KFAILURE;
-    }
-    fclose(cnffile);
-    return KSUCCESS;
-}
-
-int
-decomp_ticket(tkt, flags, pname, pinstance, prealm, paddress, session,
-              life, time_sec, sname, sinstance, key, key_s)
-    KTEXT tkt;                  /* The ticket to be decoded */
-    unsigned char *flags;       /* Kerberos ticket flags */
-    char *pname;                /* Authentication name */
-    char *pinstance;            /* Principal's instance */
-    char *prealm;               /* Principal's authentication domain */
-    unsigned long *paddress; /* Net address of entity
-                                 * requesting ticket */
-    C_Block session;            /* Session key inserted in ticket */
-    int *life;                  /* Lifetime of the ticket */
-    unsigned long *time_sec; /* Issue time and date */
-    char *sname;                /* Service name */
-    char *sinstance;            /* Service instance */
-    C_Block key;                /* Service's secret key
-                                 * (to decrypt the ticket) */
-    des_key_schedule key_s;    /* The precomputed key schedule */
-{
-    static int tkt_swap_bytes;
-    unsigned char *uptr;
-    char *ptr = (char *)tkt->dat;
-
-#ifndef NOENCRYPTION
-    /* Do the decryption */
-    pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat,
-                 (long) tkt->length,key_s,(C_Block *) key,0);
-#endif /* ! NOENCRYPTION */
-
-    *flags = *ptr;              /* get flags byte */
-    ptr += sizeof(*flags);
-    tkt_swap_bytes = 0;
-    if (HOST_BYTE_ORDER != ((*flags >> K_FLAG_ORDER)& 1))
-        tkt_swap_bytes++;
-
-    if (strlen(ptr) > ANAME_SZ)
-        return(KFAILURE);
-    strcpy(pname,ptr);   /* pname */
-    ptr += strlen(pname) + 1;
-
-    if (strlen(ptr) > INST_SZ)
-        return(KFAILURE);
-    strcpy(pinstance,ptr); /* instance */
-    ptr += strlen(pinstance) + 1;
-
-    if (strlen(ptr) > REALM_SZ)
-        return(KFAILURE);
-    strcpy(prealm,ptr);  /* realm */
-    ptr += strlen(prealm) + 1;
-    /* temporary hack until realms are dealt with properly */
-    if (*prealm == 0)
-       strcpy(prealm, ZGetRealm());
-
-    memcpy((char *)paddress, ptr, 4); /* net address */
-    ptr += 4;
-
-    memcpy((char *)session, ptr, 8); /* session key */
-    ptr+= 8;
-
-    /* get lifetime, being certain we don't get negative lifetimes */
-    uptr = (unsigned char *) ptr++;
-    *life = (int) *uptr;
-
-    memcpy((char *) time_sec, ptr, 4); /* issue time */
-    ptr += 4;
-    if (tkt_swap_bytes)
-       swap_u_long(*time_sec);
-
-    strcpy(sname,ptr);   /* service name */
-    ptr += 1 + strlen(sname);
-
-    strcpy(sinstance,ptr); /* instance */
-    ptr += 1 + strlen(sinstance);
-
-    return(KSUCCESS);
-}
 #endif /* HAVE_KRB4 */
-
index 04c7113630c9563ff6e586d0dc924afe2648e3b6..5fd31c9f2a0e57b54938a9c012c3028314e457d3 100644 (file)
@@ -8,14 +8,15 @@
  *     "mit-copyright.h". 
  */
 /*
- *     $Id: kstuff.c,v 1.22 2000/02/11 20:59:35 ghudson Exp $
+ *     $Source: /afs/dev.mit.edu/source/repository/athena/lib/zephyr/server/kstuff.c,v $
+ *     $Header: /afs/dev.mit.edu/source/repository/athena/lib/zephyr/server/kstuff.c,v 1.26 2001/04/10 23:28:20 ghudson Exp $
  */
 
 #include "zserver.h"
 
 #ifndef lint
 #ifndef SABER
-static const char rcsid_kstuff_c[] = "$Id: kstuff.c,v 1.22 2000/02/11 20:59:35 ghudson Exp $";
+static const char rcsid_kstuff_c[] = "$Id: kstuff.c,v 1.26 2001/04/10 23:28:20 ghudson Exp $";
 #endif
 #endif
 
@@ -121,7 +122,6 @@ SendKerberosData(fd, ticket, service, host)
 {
     int rem;
     char p[32];
-    char krb_realm[REALM_SZ];
     int written;
     int size_to_write;
 
@@ -190,8 +190,18 @@ ZCheckRealmAuthentication(notice, from, realm)
         checksum = compute_rlm_checksum(notice, session_key);
 
         /* If checksum matches, packet is authentic.  If not, we might
-        * have an outdated session key, so keep going the slow way.
-        */
+         * have an outdated session key, so keep going the slow way.
+         */
+        if (checksum == notice->z_checksum) {
+          (void) memcpy((char *)__Zephyr_session, (char *)session_key, 
+                        sizeof(C_Block)); /* For control_dispatch() */
+          return ZAUTH_YES;
+        }
+
+        /* Try again. This way we can switch to the same checksums
+         * that the rest of Zephyr uses at a future date, but for now 
+         * we need to be compatible */
+        checksum = compute_checksum(notice, session_key);
         if (checksum == notice->z_checksum) {
            memcpy(__Zephyr_session, session_key, sizeof(C_Block));
            return ZAUTH_YES;
@@ -212,12 +222,17 @@ ZCheckRealmAuthentication(notice, from, realm)
 
     /* Check the cryptographic checksum. */
 #ifdef NOENCRYPTION
-    our_checksum = 0;
+    checksum = 0;
 #else
     checksum = compute_rlm_checksum(notice, dat.session);
 #endif
-    if (checksum != notice->z_checksum)
+    if (checksum != notice->z_checksum) {
+#ifndef NOENCRYPTION
+      checksum = compute_checksum(notice, dat.session);
+      if (checksum != notice->z_checksum)
+#endif
         return ZAUTH_FAILED;
+    }
 
     /* Record the session key, expiry time, and source principal in the
      * hash table, so we can do a fast check next time. */
@@ -296,7 +311,7 @@ ZCheckAuthentication(notice, from)
 
     /* Check the cryptographic checksum. */
 #ifdef NOENCRYPTION
-    our_checksum = 0;
+    checksum = 0;
 #else
     checksum = compute_checksum(notice, dat.session);
 #endif
index 4cc65290961ca86f6705ab4fb7c17bb867e0bec9..352c6079f0a8c08fff67eb7b93cff42d38d59787 100644 (file)
@@ -3,7 +3,8 @@
  *
  *     Created by:     John T. Kohl
  *
- *     $Id: main.c,v 1.68 1999/01/22 23:19:45 ghudson Exp $
+ *     $Source: /afs/dev.mit.edu/source/repository/athena/lib/zephyr/server/main.c,v $
+ *     $Author: zacheiss $
  *
  *     Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
  *     For copying and distribution information, see the file
@@ -18,7 +19,7 @@
 #ifndef lint
 #ifndef SABER
 static const char rcsid_main_c[] =
-    "$Id: main.c,v 1.68 1999/01/22 23:19:45 ghudson Exp $";
+    "$Id: main.c,v 1.69 2001/02/27 04:50:08 zacheiss Exp $";
 #endif
 #endif
 
@@ -300,6 +301,7 @@ main(argc, argv)
     timer_set_rel(SWEEP_INTERVAL, sweep_ticket_hash_table, NULL);
 #endif
 
+    realm_wakeup();
 #ifdef DEBUG_MALLOC
     malloc_inuse(&m_size);
 #endif
@@ -380,9 +382,14 @@ initialize()
     krb_set_tkt_string(tkt_file);
 #endif
     realm_init();
-
+    
     ZSetServerState(1);
     ZInitialize();             /* set up the library */
+#ifdef HAVE_KRB4
+    /* Override what Zinitialize set for ZGetRealm() */
+    if (*my_realm) 
+      strcpy(__Zephyr_realm, my_realm);
+#endif
     init_zsrv_err_tbl();       /* set up err table */
 
     ZSetFD(srv_socket);                /* set up the socket as the input fildes */
@@ -502,7 +509,11 @@ bye(sig)
     int sig;
 {
     server_shutdown();         /* tell other servers */
+#ifdef REALM_MGMT
+    realm_shutdown();          /* tell other realms */
+#endif
     hostm_shutdown();          /* tell our hosts */
+    kill_realm_pids();
 #ifdef HAVE_KRB4
     dest_tkt();
 #endif
@@ -624,17 +635,43 @@ static RETSIGTYPE
 reap(sig)
     int sig;
 {
+    int pid, i = 0;
     int oerrno = errno;
-
+    Realm *rlm;
 #ifdef _POSIX_VERSION
     int waitb;
-    while (waitpid(-1, &waitb, WNOHANG) == 0) ;
 #else
     union wait waitb;
-    while (wait3 (&waitb, WNOHANG, (struct rusage*) 0) == 0) ;
+#endif
+#if 1
+    zdbug((LOG_DEBUG,"reap()"));
+#endif
+#ifdef _POSIX_VERSION
+    while ((pid = waitpid(-1, &waitb, WNOHANG)) == 0) 
+      { i++; if (i > 10) break; }
+#else
+    while ((pid = wait3 (&waitb, WNOHANG, (struct rusage*) 0)) == 0) 
+      { i++; if (i > 10) break; }
 #endif
 
     errno = oerrno;
+    if (pid) {
+      if (WIFSIGNALED(waitb) == 0) {
+       if (WIFEXITED(waitb) != 0) {
+         rlm = realm_get_realm_by_pid(pid);
+         if (rlm) {
+           rlm->child_pid = 0;
+           rlm->have_tkt = 1;
+         }
+       }
+      } else {
+       rlm = realm_get_realm_by_pid(pid);
+       if (rlm) {
+         rlm->child_pid = 0;
+       }
+      }
+    }
 }
 
 static void
index 1ad55fc03a099a1f5f83f7dfb9f32d4fde387fb0..37b0df9fe008669f968da32a1b78e74e58ca61eb 100644 (file)
@@ -7,7 +7,59 @@ Realm *otherrealms;             /* points to an array of the known
                                    servers */
 int nrealms = 0;                /* number of other realms */
 
-static void get_realm_addrs __P(());
+/*
+ * External Routines:
+ *
+ * Realm *realm_which_realm(struct sockaddr_in *who)
+ * figures out if this packet came from another realm's server
+ *
+ * Realm *realm_get_realm_by_pid(int pid)
+ * figures out which realm a child handler was for
+ *
+ * void kill_realm_pids()
+ * kills all ticket getting childen
+ *
+ * char *realm_expand_realm(char *realmname)
+ * figures out what an abbreviated realm expands to
+ *
+ * Code_t realm_send_realms()
+ * loops through all realms for a brain dump
+ *
+ * int realm_bound_for_realm(char *realm, char *recip)
+ * figures out if recip is in realm, expanding recip's realm
+ *
+ * int realm_sender_in_realm(char *realm, char *sender)
+ * figures out if sender is in realm
+ * 
+ * Realm *realm_get_realm_by_name(char *name)
+ * finds a realm struct from the realm array by name, tries expansion
+ *
+ * Code_t realm_dispatch(ZNotice_t *notice, int auth, struct sockaddr_in *who,
+ *                       Server *server)
+ * dispatches a message from a foreign realm
+ *
+ * void realm_init()
+ * sets up the realm module
+ * 
+ * void realm_deathgram()
+ * tells other realms this server is going down
+ * 
+ * void realm_wakeup()
+ * tells other realms to resend their idea of their subs to us
+ *
+ * Code_t realm_control_dispatch(ZNotice_t *notice, int auth,
+ *                               struct sockaddr_in *who, Server *server,
+ *                              Realm *realm)
+ * dispatches a foreign realm control message
+ *
+ * void realm_handoff(ZNotice_t *notice, int auth, struct sockaddr_in *who,
+ *                    Realm *realm, int ack_to_sender)
+ * hands off a message to another realm
+ *
+ * void realm_dump_realms(File *fp)
+ * do a database dump of foreign realm info
+ *
+ */
 static void realm_sendit __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, Realm *realm, int ack_to_sender));
 static void realm_sendit_auth __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, Realm *realm, int ack_to_sender));
 static void rlm_ack __P((ZNotice_t *notice, Unacked *nacked));
@@ -15,175 +67,221 @@ static void rlm_nack_cancel __P((ZNotice_t *notice, struct sockaddr_in *who));
 static void rlm_new_ticket __P(());
 static void rlm_rexmit __P((void *arg));
 static Code_t realm_ulocate_dispatch __P((ZNotice_t *notice,int auth,struct sockaddr_in *who,Server *server,Realm *realm));
+static Code_t realm_new_server __P((struct sockaddr_in *, ZNotice_t *, Realm *));
+static Code_t realm_set_server __P((struct sockaddr_in *, Realm *));
 #ifdef HAVE_KRB4
 static Code_t ticket_retrieve __P((Realm *realm));
+static int ticket_lookup __P((char *realm));
+static int ticket_expired __P((CREDENTIALS *cred));
 #endif
 
+static int
+realm_get_idx_by_addr(realm, who) 
+    Realm *realm;
+    struct sockaddr_in *who;
+{
+    struct sockaddr_in *addr;
+    int a, b;
+
+    /* loop through the realms */
+    for (addr = realm->addrs, b = 0; b < realm->count; b++, addr++)
+       if (addr->sin_addr.s_addr == who->sin_addr.s_addr)
+           return(b);
+    
+    return 0;
+}
+
 char *
 realm_expand_realm(realmname)
 char *realmname;
 {
-       static char expand[REALM_SZ];
-       static char krb_realm[REALM_SZ+1];
-       char *cp1, *cp2;
-       int retval;
-       FILE *rlm_file;
-       char list_file[128];
-       char linebuf[BUFSIZ];
-       char scratch[128];
-
-       /* upcase what we got */
-       cp2 = realmname;
-       cp1 = expand;
-       while (*cp2) {
-               *cp1++ = toupper(*cp2++);
-       }
-       *cp1 = '\0';
+    Realm *realm;
+    int a;
 
-       sprintf(list_file, "%s/zephyr/%s", SYSCONFDIR, REALM_LIST_FILE);
+    /* First, look for an exact match (case insensitive) */
+#ifdef HAVE_KRB4
+    if (!strcasecmp(ZGetRealm(), realmname))
+       return(ZGetRealm());
+#endif
 
-       if ((rlm_file = fopen(list_file, "r")) == (FILE *) 0) {
-               return(expand);
-       }
+    for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
+      if (!strcasecmp(realm->name, realmname))
+       return(realm->name);
 
-       if (fgets(linebuf, BUFSIZ, rlm_file) == NULL) {
-               /* error reading */
-               (void) fclose(rlm_file);
-               return(expand);
-       }
+    /* No exact match. See if there's a partial match */
+#ifdef HAVE_KRB4
+    if (!strncasecmp(ZGetRealm(), realmname, strlen(realmname)))
+       return(ZGetRealm());
+#endif
 
-       while (1) {
-               /* run through the file, looking for admin host */
-               if (fgets(linebuf, BUFSIZ, rlm_file) == NULL) {
-                       (void) fclose(rlm_file);
-                       return(expand);
-               }
+    for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
+       if (!strncasecmp(realm->name, realmname, strlen(realmname)))
+           return(realm->name);
+    return(realmname);
+}
 
-               if (sscanf(linebuf, "%s %s", krb_realm, scratch) < 2)
-                       continue;
-               if (!strncmp(krb_realm, expand, strlen(expand))) {
-                       (void) fclose(rlm_file);
-                       return(krb_realm);
-               }
-       }
-#ifdef KERBEROS
-       if (!strncmp(my_realm, expand, strlen(expand)))
-           return(my_realm);
-#endif
-       return(expand);
+Realm *
+realm_get_realm_by_pid(pid)
+     int pid;
+{
+    Realm *realm;
+    int a;
+
+    for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
+       if (realm->child_pid == pid)
+           return(realm);
+   
+    return 0;
+}
+
+void
+kill_realm_pids()
+{
+    Realm *realm;
+    int a;
+
+    for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
+       if (realm->child_pid != 0)
+           kill(realm->child_pid, 9);
+   
+    return;
 }
 
 Realmname *
 get_realm_lists(file)
     char *file;
 {
-  Realmname *rlm_list, *rlm;
-  int ii, nused, ntotal;
-  FILE *fp;
-  char buf[REALM_SZ + MAXHOSTNAMELEN + 1]; /* one for newline */
-  char realm[REALM_SZ], server[MAXHOSTNAMELEN + 1];
+    Realmname *rlm_list, *rlm;
+    int ii, nused, ntotal;
+    FILE *fp;
+    char buf[REALM_SZ + MAXHOSTNAMELEN + 1]; /* one for newline */
+    char realm[REALM_SZ], server[MAXHOSTNAMELEN + 1];
   
-  nused = 0;
-  if (!(fp = fopen(file, "r")))
-    return((Realmname *)0);
+    nused = 0;
+    if (!(fp = fopen(file, "r")))
+       return((Realmname *)0);
   
-  /* start with 16, realloc if necessary */
-  ntotal = 16;
-  rlm_list = (Realmname *)malloc(ntotal * sizeof(Realmname));
-  if (!rlm_list) {
-    syslog(LOG_CRIT, "get_realm_lists malloc");
-    abort();
-  }
-
-  while (fgets(buf, REALM_SZ + MAXHOSTNAMELEN + 1, fp)) {
-    if (sscanf(buf, "%s %s", realm, server) != 2) {
-      syslog(LOG_CRIT, "bad format in %s", file);
-      abort();
-    }
-    for (ii = 0; ii < nused; ii++) {
-      /* look for this realm */
-      if (!strcmp(rlm_list[ii].name, realm))
-        break;
+    /* start with 16, realloc if necessary */
+    ntotal = 16;
+    rlm_list = (Realmname *)malloc(ntotal * sizeof(Realmname));
+    if (!rlm_list) {
+       syslog(LOG_CRIT, "get_realm_lists malloc");
+       abort();
     }
-    if (ii < nused) {
-      rlm = &rlm_list[ii];
-      if (rlm->nused +1 >= rlm->nservers) {
-        /* make more space */
-        rlm->servers = (char **)realloc((char *)rlm->servers, 
-                                        (unsigned)rlm->nservers * 2 * 
-                                        sizeof(char *));
-        if (!rlm->servers) {
-          syslog(LOG_CRIT, "get_realm_lists realloc");
-          abort();
-        }
-        rlm->nservers *= 2;
-      }
-      rlm->servers[rlm->nused++] = strsave(server);
-    } else {
-      /* new realm */
-      if (nused + 1 >= ntotal) {
-        /* make more space */
-        rlm_list = (Realmname *)realloc((char *)rlm_list,
-                                               (unsigned)ntotal * 2 * 
-                                               sizeof(Realmname));
-        if (!rlm_list) {
-          syslog(LOG_CRIT, "get_realm_lists realloc");
-          abort();
-        }
-        ntotal *= 2;
-      }
-      rlm = &rlm_list[nused++];
-      strcpy(rlm->name, realm);
-      rlm->nused = 0;
-      rlm->nservers = 16;
-      rlm->servers = (char **)malloc(rlm->nservers * sizeof(char *));
-      if (!rlm->servers) {
-        syslog(LOG_CRIT, "get_realm_lists malloc");
-        abort();
-      }
-      rlm->servers[rlm->nused++] = strsave(server);
+
+    while (fgets(buf, REALM_SZ + MAXHOSTNAMELEN + 1, fp)) {
+       if (sscanf(buf, "%s %s", realm, server) != 2) {
+           syslog(LOG_CRIT, "bad format in %s", file);
+           abort();
+       }
+       for (ii = 0; ii < nused; ii++) {
+           /* look for this realm */
+           if (!strcmp(rlm_list[ii].name, realm))
+               break;
+       }
+       if (ii < nused) {
+           rlm = &rlm_list[ii];
+           if (rlm->nused +1 >= rlm->nservers) {
+               /* make more space */
+               rlm->servers = (char **)realloc((char *)rlm->servers, 
+                                               (unsigned)rlm->nservers * 2 * 
+                                               sizeof(char *));
+               if (!rlm->servers) {
+                   syslog(LOG_CRIT, "get_realm_lists realloc");
+                   abort();
+               }
+               rlm->nservers *= 2;
+           }
+           rlm->servers[rlm->nused++] = strsave(server);
+       } else {
+           /* new realm */
+           if (nused + 1 >= ntotal) {
+               /* make more space */
+               rlm_list = (Realmname *)realloc((char *)rlm_list,
+                                               (unsigned)ntotal * 2 * 
+                                               sizeof(Realmname));
+               if (!rlm_list) {
+                   syslog(LOG_CRIT, "get_realm_lists realloc");
+                   abort();
+               }
+               ntotal *= 2;
+           }
+           rlm = &rlm_list[nused++];
+           strcpy(rlm->name, realm);
+           rlm->nused = 0;
+           rlm->nservers = 16;
+           rlm->servers = (char **)malloc(rlm->nservers * sizeof(char *));
+           if (!rlm->servers) {
+               syslog(LOG_CRIT, "get_realm_lists malloc");
+               abort();
+           }
+           rlm->servers[rlm->nused++] = strsave(server);
+       }
     }
-  }
-  if (nused + 1 >= ntotal) {
-    rlm_list = (Realmname *)realloc((char *)rlm_list,
-                                           (unsigned)(ntotal + 1) * 
-                                           sizeof(Realmname));
-    if (!rlm_list) {
-      syslog(LOG_CRIT, "get_realm_lists realloc");
-      abort();
+    if (nused + 1 >= ntotal) {
+       rlm_list = (Realmname *)realloc((char *)rlm_list,
+                                       (unsigned)(ntotal + 1) * 
+                                       sizeof(Realmname));
+       if (!rlm_list) {
+           syslog(LOG_CRIT, "get_realm_lists realloc");
+           abort();
+       }
     }
-  }
-  *rlm_list[nused].name = '\0';
+    *rlm_list[nused].name = '\0';
   
-  return(rlm_list);
+    return(rlm_list);
 }
 
 Code_t 
 realm_send_realms()
 {
-  int cnt, retval;
-  for (cnt = 0; cnt < nrealms; cnt++) {
-    if (retval = (subscr_send_realm_subs(&otherrealms[cnt])) != ZERR_NONE)
-      return(retval);
-  }
-  return ZERR_NONE;
+    int cnt, retval;
+    for (cnt = 0; cnt < nrealms; cnt++) {
+       if (retval = (subscr_send_realm_subs(&otherrealms[cnt])) != ZERR_NONE)
+           return(retval);
+    }
 }
 
 int
-bound_for_local_realm(notice)
-    ZNotice_t *notice;
+realm_bound_for_realm(realm, recip)
+     char *realm;
+     char *recip;
 {
-  char *realm;
-  
-  realm = strchr(notice->z_recipient, '@');
-  
-  if (!realm || !strcmp(realm_expand_realm(realm + 1), ZGetRealm()))
-    return 1;
+    char *rlm = NULL;
+    int remote = strcmp(ZGetRealm(), realm);
+    
+    if (recip)
+      rlm = strchr(recip, '@');
+    
+    if (!rlm && !remote) 
+       return 1;
 
-  return 0;
+    if (rlm && strcmp(realm_expand_realm(rlm + 1), realm) == 0)
+       return 1;
+
+    return 0;
 }
 
 int
+realm_sender_in_realm(realm, sender)
+     char *realm;
+     char *sender;
+{
+    char *rlm = NULL;
+    int remote = strcmp(ZGetRealm(), realm);
+
+    if (sender)
+       rlm = strchr(sender, '@');
+
+    if (!rlm && !remote)
+       return 1;
+
+    if (rlm && strcmp((rlm + 1), realm) == 0)
+       return 1;
+
+    return 0;
+}
+
 sender_in_realm(notice)
     ZNotice_t *notice;
 {
@@ -201,32 +299,41 @@ Realm *
 realm_which_realm(who)
     struct sockaddr_in *who;
 {
-  Realm *realm;
-  struct sockaddr_in *addr;
-  int a, b;
-
-  /* loop through the realms */
-  for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
-    /* loop through the addresses for the realm */
-    for (addr = realm->addrs, b = 0; b < realm->count; b++, addr++)
-      if (addr->sin_addr.s_addr == who->sin_addr.s_addr)
-        return(realm);
+    Realm *realm;
+    struct sockaddr_in *addr;
+    int a, b;
+
+    if (who->sin_port != srv_addr.sin_port)
+       return 0;
+
+    /* loop through the realms */
+    for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
+       /* loop through the addresses for the realm */
+       for (addr = realm->addrs, b = 0; b < realm->count; b++, addr++)
+           if (addr->sin_addr.s_addr == who->sin_addr.s_addr)
+               return(realm);
   
-  return 0;
+    return 0;
 }
 
 Realm *
 realm_get_realm_by_name(name)
-char *name;
+    char *name;
 {
-  int a;
-  Realm *realm;
+    int a;
+    Realm *realm;
 
-  for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
-    if (!strcmp(realm->name, name))
-      return(realm);
+    /* First, look for an exact match (case insensitive) */
+    for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
+       if (!strcasecmp(realm->name, name))
+           return(realm);
 
-  return 0;
+    /* Failing that, look for an inexact match */
+    for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
+       if (!strncasecmp(realm->name, name, strlen(name)))
+           return(realm);
+
+    return 0;
 }
 
 static void
@@ -234,43 +341,44 @@ rlm_nack_cancel(notice, who)
     register ZNotice_t *notice;
     struct sockaddr_in *who;
 {
-  register Realm *which = realm_which_realm(who);
-  register Unacked *nacked, *next;
-  ZNotice_t acknotice;
-  ZPacket_t retval;
+    register Realm *which = realm_which_realm(who);
+    register Unacked *nacked, *next;
+    ZPacket_t retval;
   
-#if 0
+#if 1
     zdbug((LOG_DEBUG, "rlm_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
-  if (!which) {
-    syslog(LOG_ERR, "non-realm ack?");
-    return;
-  }
+    if (!which) {
+       syslog(LOG_ERR, "non-realm ack?");
+       return;
+    }
 
-  for (nacked = rlm_nacklist; nacked; nacked = nacked->next) {
-    if (&otherrealms[nacked->dest.rlm.rlm_idx] == which) {
-      if (ZCompareUID(&nacked->uid, &notice->z_uid)) {
-        timer_reset(nacked->timer);
+    for (nacked = rlm_nacklist; nacked; nacked = nacked->next) {
+       if (&otherrealms[nacked->dest.rlm.rlm_idx] == which) {
+           /* First, note the realm appears to be up */
+           which->state = REALM_UP;
+           if (ZCompareUID(&nacked->uid, &notice->z_uid)) {
+               timer_reset(nacked->timer);
         
-        if (nacked->ack_addr.sin_addr.s_addr)
-          rlm_ack(notice, nacked);
+               if (nacked->ack_addr.sin_addr.s_addr)
+                   rlm_ack(notice, nacked);
         
-        /* free the data */
-        free(nacked->packet);
-        LIST_DELETE(nacked);
-        free(nacked);
-        return;
-      }
+               /* free the data */
+               free(nacked->packet);
+               LIST_DELETE(nacked);
+               free(nacked);
+               return;
+           }
+       }
     }
-  }
 #if 0
     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;
+    return;
 }
 
 static void
@@ -278,37 +386,37 @@ rlm_ack(notice, nacked)
     ZNotice_t *notice;
     Unacked *nacked;
 {
-  ZNotice_t acknotice;
-  ZPacket_t ackpack;
-  int packlen;
-  Code_t retval;
+    ZNotice_t acknotice;
+    ZPacket_t ackpack;
+    int packlen;
+    Code_t retval;
   
-  /* tell the original sender the result */
-  acknotice = *notice;
-  acknotice.z_message_len = strlen(acknotice.z_message) + 1;
+    /* tell the original sender the result */
+    acknotice = *notice;
+    acknotice.z_message_len = strlen(acknotice.z_message) + 1;
   
-  packlen = sizeof(ackpack);
+    packlen = sizeof(ackpack);
   
-  if ((retval = ZFormatSmallRawNotice(&acknotice, ackpack, &packlen)) != ZERR_NONE) {
-    syslog(LOG_ERR, "rlm_ack format: %s",
-           error_message(retval));
-    return;
-  }
-  zdbug((LOG_DEBUG, "rlm_ack sending to %s/%d",
-         inet_ntoa(nacked->ack_addr.sin_addr),
-         ntohs(nacked->ack_addr.sin_port)));
-        if ((retval = ZSetDestAddr(&nacked->ack_addr)) != ZERR_NONE) {
-          syslog(LOG_WARNING, "rlm_ack set addr: %s",
-                 error_message(retval));
-          return;
-        }
-  if ((retval = ZSendPacket(ackpack, packlen, 0)) != ZERR_NONE) {
-    syslog(LOG_WARNING, "rlm_ack xmit: %s", error_message(retval));
-    return;
-  }
+    if ((retval = ZFormatSmallRawNotice(&acknotice, ackpack, &packlen)) 
+       != ZERR_NONE) {
+       syslog(LOG_ERR, "rlm_ack format: %s",
+              error_message(retval));
+       return;
+    }
+    zdbug((LOG_DEBUG, "rlm_ack sending to %s/%d",
+          inet_ntoa(nacked->ack_addr.sin_addr),
+          ntohs(nacked->ack_addr.sin_port)));
+    if ((retval = ZSetDestAddr(&nacked->ack_addr)) != ZERR_NONE) {
+       syslog(LOG_WARNING, "rlm_ack set addr: %s",
+              error_message(retval));
+       return;
+    }
+    if ((retval = ZSendPacket(ackpack, packlen, 0)) != ZERR_NONE) {
+       syslog(LOG_WARNING, "rlm_ack xmit: %s", error_message(retval));
+       return;
+    }
 }
 
-
 Code_t
 realm_dispatch(notice, auth, who, server)
     ZNotice_t *notice;
@@ -316,157 +424,291 @@ realm_dispatch(notice, auth, who, server)
     struct sockaddr_in *who;
     Server *server;
 {
-        Realm *realm;
-        struct sockaddr_in newwho;
-        Code_t status = ZERR_NONE;
-        char rlm_recipient[REALM_SZ + 1];
-        int external = 0;
-        String *notice_class;
-
-        if (notice->z_kind == SERVACK || notice->z_kind == SERVNAK) {
-          rlm_nack_cancel(notice, who);
-          return(ZERR_NONE);
-        }
-        /* set up a who for the real origin */
-        memset((caddr_t) &newwho, 0, sizeof(newwho));
-        newwho.sin_family = AF_INET;
-        newwho.sin_addr.s_addr = notice->z_sender_addr.s_addr;
-        newwho.sin_port = hm_port;
-
-        /* check if it's a control message */
-        realm = realm_which_realm(who);
-
-        notice_class = make_string(notice->z_class,1);
-
-        if (class_is_admin(notice_class)) {
-          syslog(LOG_WARNING, "%s sending admin opcode %s",
-                 realm->name, notice->z_opcode);
-        } else if (class_is_hm(notice_class)) {
-                syslog(LOG_WARNING, "%s sending hm opcode %s",
-                       realm->name, notice->z_opcode);
-        } else if (class_is_control(notice_class)) {
-                status = realm_control_dispatch(notice, auth, who,
-                                                server, realm);
-        } else if (class_is_ulogin(notice_class)) {
-          /* don't need to forward this */
-          if (server == me_server) {
+    Realm *realm;
+    struct sockaddr_in newwho;
+    Code_t status = ZERR_NONE;
+    char rlm_recipient[REALM_SZ + 1];
+    int external = 0;
+    String *notice_class;
+
+    if (notice->z_kind == SERVACK || notice->z_kind == SERVNAK) {
+       rlm_nack_cancel(notice, who);
+       return(ZERR_NONE);
+    }
+    /* set up a who for the real origin */
+    memset((caddr_t) &newwho, 0, sizeof(newwho));
+    newwho.sin_family = AF_INET;
+    newwho.sin_addr.s_addr = notice->z_sender_addr.s_addr;
+    newwho.sin_port = hm_port;
+    
+    /* check if it's a control message */
+    realm = realm_which_realm(who);
+
+    notice_class = make_string(notice->z_class,1);
+    
+    if (class_is_admin(notice_class)) {
+       syslog(LOG_WARNING, "%s sending admin opcode %s",
+              realm->name, notice->z_opcode);
+    } else if (class_is_hm(notice_class)) {
+       syslog(LOG_WARNING, "%s sending hm opcode %s",
+              realm->name, notice->z_opcode);
+    } else if (class_is_control(notice_class)) {
+       status = realm_control_dispatch(notice, auth, who,
+                                       server, realm);
+    } else if (class_is_ulogin(notice_class)) {
+       /* don't need to forward this */
+       if (server == me_server) {
             sprintf(rlm_recipient, "@%s", realm->name);
             notice->z_recipient = rlm_recipient;
 
             sendit(notice, 1, who, 0);
-          }
-        } else if (class_is_ulocate(notice_class)) {
-          status = realm_ulocate_dispatch(notice, auth, who, server, realm);
-        } else {
-          /* redo the recipient */
-          if (*notice->z_recipient == '\0') {
-            sprintf(rlm_recipient, "@%s", realm->name);
-            notice->z_recipient = rlm_recipient;
-            /* only send to our realm */
-            external = 0;
-          } else if (bound_for_local_realm(notice) && *notice->z_recipient 
-                     == '@') 
-            {
-              /* we're responsible for getting this message out */
-              external = 1;
-              notice->z_recipient = "";
-            }
+       }
+    } else if (class_is_ulocate(notice_class)) {
+       status = realm_ulocate_dispatch(notice, auth, who, server, realm);
+    } else {
+       /* redo the recipient */
+       if (*notice->z_recipient == '\0') {
+           sprintf(rlm_recipient, "@%s", realm->name);
+           notice->z_recipient = rlm_recipient;
+           external = 0;
+       } else if (realm_bound_for_realm(ZGetRealm(), notice->z_recipient)
+                  && *notice->z_recipient == '@') 
+       {
+           /* we're responsible for getting this message out */
+           external = 1;
+           notice->z_recipient = "";
+       }
           
-          /* otherwise, send to local subscribers */
-          sendit(notice, auth, who, external);
-        }
+       /* otherwise, send to local subscribers */
+       sendit(notice, auth, who, external);
+    }
         
-        return(status);
+    return(status);
 }
 
 void
 realm_init()
 {
-  Client *client;
-  Realmname *rlmnames;
-  Realm *rlm;
-  int ii, jj, found;
-  struct in_addr *addresses;
-  struct hostent *hp;
-  char list_file[128];
-  char rlmprinc[ANAME_SZ+INST_SZ+REALM_SZ+3];
-
-  sprintf(list_file, "%s/zephyr/%s", SYSCONFDIR, REALM_LIST_FILE);
-  rlmnames = get_realm_lists(list_file);
-  if (!rlmnames) {
-    zdbug((LOG_DEBUG, "No other realms"));
-    nrealms = 0;
-    return;
-  }
-
-  for (nrealms = 0; *rlmnames[nrealms].name; nrealms++);
-  
-  otherrealms = (Realm *)malloc(nrealms * sizeof(Realm));
-  if (!otherrealms) {
-    syslog(LOG_CRIT, "malloc failed in get_realm_addrs");
-    abort();
-  }
-
-  for (ii = 0; ii < nrealms; ii++) {
-    rlm = &otherrealms[ii];
-    strcpy(rlm->name, rlmnames[ii].name);
-
-    addresses = (struct in_addr *)malloc(rlmnames[ii].nused * sizeof(struct in_addr));
-    if (!addresses) {
-      syslog(LOG_CRIT, "malloc failed in get_realm_addrs");
-      abort();
+    Client *client;
+    Realmname *rlmnames;
+    Realm *rlm;
+    int ii, jj, found;
+    struct in_addr *addresses;
+    struct hostent *hp;
+    char list_file[128];
+    char rlmprinc[ANAME_SZ+INST_SZ+REALM_SZ+3];
+
+    sprintf(list_file, "%s/zephyr/%s", SYSCONFDIR, REALM_LIST_FILE);
+    rlmnames = get_realm_lists(list_file);
+    if (!rlmnames) {
+       zdbug((LOG_DEBUG, "No other realms"));
+       nrealms = 0;
+       return;
     }
-    /* convert names to addresses */
-    found = 0;
-    for (jj = 0; jj < rlmnames[ii].nused; jj++) {
-      hp = gethostbyname(rlmnames[ii].servers[jj]);
-      if (hp) {
-        memmove((caddr_t) &addresses[found], (caddr_t)hp->h_addr, sizeof(struct in_addr));
-        found++;
-      } else
-        syslog(LOG_WARNING, "hostname failed, %s", rlmnames[ii].servers[jj]);
-      /* free the hostname */
-      free(rlmnames[ii].servers[jj]);
-    }
-    rlm->count = found;
-    rlm->addrs = (struct sockaddr_in *)malloc(found * sizeof (struct sockaddr_in));
-    if (!rlm->addrs) {
-      syslog(LOG_CRIT, "malloc failed in get_realm_addrs");
-      abort();
-    }
-    for (jj = 0; jj < rlm->count; jj++) {
-      rlm->addrs[jj].sin_family = AF_INET;
-      /* use the server port */
-      rlm->addrs[jj].sin_port = srv_addr.sin_port;
-      rlm->addrs[jj].sin_addr = addresses[jj];
-    }
-    client = (Client *) malloc(sizeof(Client));
-    if (!client) {
-      syslog(LOG_CRIT, "malloc failed in get_realm_addrs");
-      abort();
+    
+    for (nrealms = 0; *rlmnames[nrealms].name; nrealms++);
+    
+    otherrealms = (Realm *)malloc(nrealms * sizeof(Realm));
+    if (!otherrealms) {
+       syslog(LOG_CRIT, "malloc failed in realm_init");
+       abort();
     }
-    memset(&client->addr, 0, sizeof(struct sockaddr_in));
+
+    for (ii = 0; ii < nrealms; ii++) {
+       rlm = &otherrealms[ii];
+       strcpy(rlm->name, rlmnames[ii].name);
+       
+       addresses = (struct in_addr *)malloc(rlmnames[ii].nused * 
+                                            sizeof(struct in_addr));
+       if (!addresses) {
+           syslog(LOG_CRIT, "malloc failed in realm_init");
+           abort();
+       }
+       /* convert names to addresses */
+       found = 0;
+       for (jj = 0; jj < rlmnames[ii].nused; jj++) {
+           hp = gethostbyname(rlmnames[ii].servers[jj]);
+           if (hp) {
+               memmove((caddr_t) &addresses[found], (caddr_t)hp->h_addr, 
+                       sizeof(struct in_addr));
+               found++;
+           } else
+               syslog(LOG_WARNING, "hostname failed, %s", 
+                      rlmnames[ii].servers[jj]);
+           /* free the hostname */
+           free(rlmnames[ii].servers[jj]);
+       }
+       rlm->count = found;
+       rlm->addrs = (struct sockaddr_in *)malloc(found * 
+                                                 sizeof (struct sockaddr_in));
+       if (!rlm->addrs) {
+           syslog(LOG_CRIT, "malloc failed in realm_init");
+           abort();
+       }
+       for (jj = 0; jj < rlm->count; jj++) {
+           rlm->addrs[jj].sin_family = AF_INET;
+           /* use the server port */
+           rlm->addrs[jj].sin_port = srv_addr.sin_port;
+           rlm->addrs[jj].sin_addr = addresses[jj];
+       }
+       client = (Client *) malloc(sizeof(Client));
+       if (!client) {
+           syslog(LOG_CRIT, "malloc failed in realm_init");
+           abort();
+       }
+       memset(&client->addr, 0, sizeof(struct sockaddr_in));
 #ifdef HAVE_KRB4
-    memset(&client->session_key, 0, sizeof(client->session_key));
+       memset(&client->session_key, 0, sizeof(client->session_key));
 #endif
-    sprintf(rlmprinc, "%s.%s@%s", SERVER_SERVICE, SERVER_INSTANCE, rlm->name);
-    client->principal = make_string(rlmprinc, 0);
-    client->last_send = 0;
-    client->last_ack = NOW;
-    client->subs = NULL;
-    client->realm = rlm;
-    client->addr.sin_family = 0;
-    client->addr.sin_port = 0;
-    client->addr.sin_addr.s_addr = 0;
+       sprintf(rlmprinc, "%s.%s@%s", SERVER_SERVICE, SERVER_INSTANCE, 
+               rlm->name);
+       client->principal = make_string(rlmprinc, 0);
+       client->last_send = 0;
+       client->last_ack = NOW;
+       client->subs = NULL;
+       client->realm = rlm;
+       client->addr.sin_family = 0;
+       client->addr.sin_port = 0;
+       client->addr.sin_addr.s_addr = 0;
     
-    rlm->client = client;
-    rlm->idx = random() % rlm->count;
-    rlm->subs = NULL;
-    rlm->tkt_try = 0;
-    free(rlmnames[ii].servers);
-    free(addresses);
-  }
-  free(rlmnames);
+       rlm->client = client;
+       rlm->idx = (rlm->count) ? random() % rlm->count : 0;
+       rlm->subs = NULL;
+       rlm->remsubs = NULL;
+       rlm->child_pid = 0;
+       /* Assume the best */
+       rlm->state = REALM_TARDY;
+       rlm->have_tkt = 1;
+       free(rlmnames[ii].servers);
+       free(addresses);
+    }
+    free(rlmnames);
+}
+
+void
+realm_deathgram(server)
+    Server *server;
+{
+    Realm *realm;
+    char rlm_recipient[REALM_SZ + 1];
+    int jj = 0;
+
+    /* Get it out once, and assume foreign servers will share */
+    for (realm = otherrealms, jj = 0; jj < nrealms; jj++, realm++) {
+       ZNotice_t snotice;
+       char *pack;
+       char rlm_recipient[REALM_SZ + 1];
+       int packlen, retval;
+    
+       memset (&snotice, 0, sizeof (snotice));
+
+       snotice.z_kind = ACKED;
+       snotice.z_port = srv_addr.sin_port;
+       snotice.z_class = ZEPHYR_CTL_CLASS;
+       snotice.z_class_inst = ZEPHYR_CTL_REALM;
+       snotice.z_opcode = SERVER_SHUTDOWN;
+       snotice.z_sender = myname; /* my host name */
+       sprintf(rlm_recipient, "@%s", realm->name);
+       snotice.z_recipient = rlm_recipient;
+       snotice.z_default_format = "";
+       snotice.z_num_other_fields = 0;
+       snotice.z_default_format = "";
+       snotice.z_message = (server) ? server->addr_str : NULL;
+       snotice.z_message_len = (server) ? strlen(server->addr_str) + 1 : 0;
+
+       zdbug((LOG_DEBUG, "rlm_deathgram: suggesting %s to %s", 
+              (server) ? server->addr_str : "nothing", realm->name));
+
+       if (!ticket_lookup(realm->name))
+           if ((retval = ticket_retrieve(realm)) != ZERR_NONE) {
+               syslog(LOG_WARNING, "rlm_deathgram failed: %s", 
+                      error_message(retval));
+               return;
+           }
+
+       if ((retval = ZFormatNotice(&snotice, &pack, &packlen, ZAUTH)) 
+           != ZERR_NONE) 
+       {
+           syslog(LOG_WARNING, "rlm_deathgram format: %s",
+                  error_message(retval));
+           return;
+       }
+       if ((retval = ZParseNotice(pack, packlen, &snotice)) != ZERR_NONE) {
+           syslog(LOG_WARNING, "rlm_deathgram parse: %s",
+                  error_message(retval));
+           free(pack);
+           return;
+       }
+
+       realm_handoff(&snotice, 1, NULL, realm, 0);
+       free(pack);
+    }
+}
+
+void
+realm_wakeup()
+{
+    int jj, found = 0;
+    Realm *realm;
+    char rlm_recipient[REALM_SZ + 1];
+    
+    for (jj = 1; jj < nservers; jj++) {    /* skip limbo server */
+       if (jj != me_server_idx && otherservers[jj].state == SERV_UP)
+           found++;
+    }
+  
+    if (nservers < 2 || !found) {
+       /* if we're the only server up, send a REALM_BOOT to one of their 
+          servers here */
+       for (realm = otherrealms, jj = 0; jj < nrealms; jj++, realm++) {
+           ZNotice_t snotice;
+           char *pack;
+           char rlm_recipient[REALM_SZ + 1];
+           int packlen, retval;
+           
+           memset (&snotice, 0, sizeof (snotice));
+
+           snotice.z_opcode = REALM_BOOT;
+           snotice.z_port = srv_addr.sin_port;
+           snotice.z_class_inst = ZEPHYR_CTL_REALM;
+           snotice.z_class = ZEPHYR_CTL_CLASS;
+           snotice.z_recipient = "";
+           snotice.z_kind = ACKED;
+           snotice.z_num_other_fields = 0;
+           snotice.z_default_format = "";
+           snotice.z_sender = myname; /* my host name */
+           sprintf(rlm_recipient, "@%s", realm->name);
+           snotice.z_recipient = rlm_recipient;
+           snotice.z_default_format = "";
+           snotice.z_message = NULL;
+           snotice.z_message_len = 0;
+
+           if (!ticket_lookup(realm->name))
+               if ((retval = ticket_retrieve(realm)) != ZERR_NONE) {
+                   syslog(LOG_WARNING, "rlm_wakeup failed: %s", 
+                          error_message(retval));
+                   continue;
+               }
+
+           if ((retval = ZFormatNotice(&snotice, &pack, &packlen, ZAUTH)) 
+               != ZERR_NONE) 
+           {
+               syslog(LOG_WARNING, "rlm_wakeup format: %s",
+                      error_message(retval));
+               return;
+           }
+           if ((retval = ZParseNotice(pack, packlen, &snotice)) 
+               != ZERR_NONE) {
+               syslog(LOG_WARNING, "rlm_wakeup parse: %s",
+                      error_message(retval));
+               free(pack);
+               return;
+           }
+
+           realm_handoff(&snotice, 1, NULL, realm, 0);
+           free(pack);
+       }      
+    }
 }
 
 static Code_t
@@ -477,29 +719,35 @@ realm_ulocate_dispatch(notice, auth, who, server, realm)
     Server *server;
     Realm *realm;
 {
-  register char *opcode = notice->z_opcode;
-  Code_t status;
+    register char *opcode = notice->z_opcode;
+    Code_t status;
   
-  if (!auth) {
-    syslog(LOG_WARNING, "unauth locate msg from %s",
-           inet_ntoa(who->sin_addr));
-    clt_ack(notice, who, AUTH_FAILED);
+    if (!auth) {
+       syslog(LOG_WARNING, "unauth locate msg from %s (%s/%s/%s)",
+              inet_ntoa(who->sin_addr), 
+              notice->z_class, notice->z_class_inst, 
+              notice->z_opcode); /* XXX */
+#if 0
+       syslog(LOG_WARNING, "unauth locate msg from %s",
+              inet_ntoa(who->sin_addr));
+#endif
+       clt_ack(notice, who, AUTH_FAILED);
+       return(ZERR_NONE);
+    }
+    
+    if (!strcmp(opcode, REALM_REQ_LOCATE)) {
+       ack(notice, who);
+       ulogin_realm_locate(notice, who, realm);
+    } else if (!strcmp(opcode, REALM_ANS_LOCATE)) {
+       ack(notice, who);
+       ulogin_relay_locate(notice, who);
+    } else {
+       syslog(LOG_WARNING, "%s unknown/illegal loc opcode %s",
+              realm->name, opcode);
+       nack(notice, who);
+    }
+    
     return(ZERR_NONE);
-  }
-
-  if (!strcmp(opcode, REALM_REQ_LOCATE)) {
-    ack(notice, who);
-    ulogin_realm_locate(notice, who, realm);
-  } else if (!strcmp(opcode, REALM_ANS_LOCATE)) {
-    ack(notice, who);
-    ulogin_relay_locate(notice, who);
-  } else {
-    syslog(LOG_WARNING, "%s unknown/illegal loc opcode %s",
-           realm->name, opcode);
-    nack(notice, who);
-  }
-  
-  return(ZERR_NONE);
 }
 
 
@@ -511,48 +759,130 @@ realm_control_dispatch(notice, auth, who, server, realm)
     Server *server;
     Realm *realm;
 {
-  register char *opcode = notice->z_opcode;
-  Code_t status;
-
-  if (!auth) {
-    syslog(LOG_WARNING, "unauth ctl msg from %s",
-           inet_ntoa(who->sin_addr));
-    if (server == me_server)
-      clt_ack(notice, who, AUTH_FAILED);
-    return(ZERR_NONE);
-  }
+    register char *opcode = notice->z_opcode;
+    Code_t status;
+
+    if (!auth) {
+       syslog(LOG_WARNING, "unauth ctl msg from %s (%s/%s/%s)",
+              inet_ntoa(who->sin_addr), 
+              notice->z_class, notice->z_class_inst, 
+              notice->z_opcode); /* XXX */
+#if 0
+       syslog(LOG_WARNING, "unauth ctl msg from %s",
+              inet_ntoa(who->sin_addr));
+#endif
+       if (server == me_server)
+           clt_ack(notice, who, AUTH_FAILED);
+       return(ZERR_NONE);
+    }
 
-  if (strcmp(notice->z_class_inst, ZEPHYR_CTL_REALM)) {
-    syslog(LOG_WARNING, "Invalid rlm_dispatch instance %s",
-           notice->z_class_inst);
-    return(ZERR_NONE);
-  }
-
-  if (!strcmp(opcode, REALM_REQ_SUBSCRIBE) || !strcmp(opcode, REALM_ADD_SUBSCRIBE)) {
-    /* try to add subscriptions */
-    /* attempts to get defaults are ignored */
-    if ((status = subscr_foreign_user(notice, who, realm)) != ZERR_NONE) {
-      clt_ack(notice, who, AUTH_FAILED);
-    } else if (server == me_server) {
-      server_forward(notice, auth, who);
-      ack(notice, who);
+    if (strcmp(notice->z_class_inst, ZEPHYR_CTL_REALM)) {
+       syslog(LOG_WARNING, "Invalid rlm_dispatch instance %s",
+              notice->z_class_inst);
+       return(ZERR_NONE);
     }
-  } else if (!strcmp(opcode, REALM_UNSUBSCRIBE)) {
-    /* try to remove subscriptions */
-    if ((status = subscr_realm_cancel(who, notice, realm)) != ZERR_NONE) {
-      clt_ack(notice, who, NOT_FOUND);
-    } else if (server == me_server) {
-      server_forward(notice, auth, who);
-      ack(notice, who);
+
+    if (!strcmp(opcode, REALM_REQ_SUBSCRIBE) || !strcmp(opcode, REALM_ADD_SUBSCRIBE)) {
+       /* try to add subscriptions */
+       /* attempts to get defaults are ignored */
+       if ((status = subscr_foreign_user(notice, who, server, realm)) != ZERR_NONE) {
+           clt_ack(notice, who, AUTH_FAILED);
+       } else if (server == me_server) {
+           server_forward(notice, auth, who);
+           ack(notice, who);
+       }
+    } else if (!strcmp(opcode, REALM_UNSUBSCRIBE)) {
+       /* try to remove subscriptions */
+       if ((status = subscr_realm_cancel(who, notice, realm)) != ZERR_NONE) {
+           clt_ack(notice, who, NOT_FOUND);
+       } else if (server == me_server) {
+           server_forward(notice, auth, who);
+           ack(notice, who);
+       }
+    } else if (!strcmp(opcode, REALM_BOOT)) {
+       zdbug((LOG_DEBUG, "got a REALM_BOOT from %d (me %d)", server, me_server));
+       realm->state = REALM_STARTING;
+       realm_set_server(who, realm);
+#ifdef REALM_MGMT
+       /* resend subscriptions but only if this was to us */
+       if (server == me_server) {
+           if ((status = subscr_realm_subs(realm)) != ZERR_NONE) {
+               clt_ack(notice, who, NOT_FOUND);
+           } else {
+               /* do forward the hint in case it ever matters */
+               server_forward(notice, auth, who);
+               ack(notice, who);
+           }
+       }
+#endif
+    } else if (!strcmp(opcode, SERVER_SHUTDOWN)) {
+       /* try to remove subscriptions */
+       if ((status = realm_new_server(who, notice, realm)) != ZERR_NONE) {
+           clt_ack(notice, who, NOT_FOUND);
+       } else if (server == me_server) {
+           server_forward(notice, auth, who);
+           ack(notice, who);
+       }
+    } else {
+       syslog(LOG_WARNING, "%s unknown/illegal ctl opcode %s",
+              realm->name, opcode);
+       if (server == me_server)
+           nack(notice, who);
+       return(ZERR_NONE);
     }
-  } else {
-    syslog(LOG_WARNING, "%s unknown/illegal ctl opcode %s",
-           realm->name, opcode);
-    if (server == me_server)
-      nack(notice, who);
     return(ZERR_NONE);
-  }
-  return(ZERR_NONE);
+}
+
+static Code_t
+realm_new_server(sin, notice, realm)
+    struct sockaddr_in *sin;
+    ZNotice_t *notice;
+    Realm *realm;
+{
+    struct hostent *hp;
+    char suggested_server[MAXHOSTNAMELEN];
+    unsigned long addr;
+    Realm *rlm;
+    struct sockaddr_in sinaddr;
+    int srvidx;
+
+    if (!realm)
+       return ZSRV_NORLM;
+
+    srvidx = realm_get_idx_by_addr(realm, sin);
+    zdbug((LOG_DEBUG, "rlm_new_srv: message from %d in %s (%s)", 
+          srvidx, realm->name, inet_ntoa(sin->sin_addr)));
+    if (realm->idx == srvidx) {
+       if (notice->z_message_len) {
+           addr = inet_addr(notice->z_message);
+           sinaddr.sin_addr.s_addr = addr;
+           rlm = realm_which_realm(&sinaddr);
+           /* Not exactly */
+           if (!rlm || (rlm != realm))
+               return ZSRV_NORLM;
+           realm->idx = realm_get_idx_by_addr(realm, &sinaddr);
+       } else {
+           realm->idx = (realm->idx + 1) % realm->count;
+       } 
+       zdbug((LOG_DEBUG, "rlm_new_srv: switched servers (%s)", inet_ntoa((realm->addrs[realm->idx]).sin_addr)));
+    } else {
+      zdbug((LOG_DEBUG, "rlm_new_srv: not switching servers (%s)", inet_ntoa((realm->addrs[realm->idx]).sin_addr)));
+    }
+}
+
+static Code_t
+realm_set_server(sin, realm)
+    struct sockaddr_in *sin;
+    Realm *realm;
+{
+    Realm *rlm;
+
+    rlm = realm_which_realm(sin);
+    /* Not exactly */
+    if (!rlm || (rlm != realm))
+       return ZSRV_NORLM;
+    realm->idx = realm_get_idx_by_addr(realm, sin);
+    zdbug((LOG_DEBUG, "rlm_pick_srv: switched servers (%s)", inet_ntoa((realm->addrs[realm->idx]).sin_addr)));
 }
 
 void
@@ -564,24 +894,28 @@ realm_handoff(notice, auth, who, realm, ack_to_sender)
     int ack_to_sender;
 {
 #ifdef HAVE_KRB4
-  Code_t retval;
+    Code_t retval;
 
-  if (!auth) {
-    zdbug((LOG_DEBUG, "realm_sendit unauthentic to realm %s", realm->name)) 
-    realm_sendit(notice, who, auth, realm, ack_to_sender);
-  }
-  
-  if (!ticket_lookup(realm->name))
-    if ((retval = ticket_retrieve(realm)) != ZERR_NONE) {
-      syslog(LOG_WARNING, "rlm_handoff failed: %s", error_message(retval));
-      return;
+    if (!auth) {
+       zdbug((LOG_DEBUG, "realm_sendit unauthentic to realm %s", 
+              realm->name));
+       realm_sendit(notice, who, auth, realm, ack_to_sender);
+       return;
     }
   
-  zdbug((LOG_DEBUG, "realm_sendit to realm %s auth %d", realm->name, auth)); 
-  /* valid ticket available now, send the message */
-  realm_sendit_auth(notice, who, auth, realm, ack_to_sender);
+    if (!ticket_lookup(realm->name))
+       if ((retval = ticket_retrieve(realm)) != ZERR_NONE) {
+           syslog(LOG_WARNING, "rlm_handoff failed: %s", 
+                  error_message(retval));
+           realm_sendit(notice, who, auth, realm, ack_to_sender);
+           return;
+       }
+    
+    zdbug((LOG_DEBUG, "realm_sendit to realm %s auth %d", realm->name, auth)); 
+    /* valid ticket available now, send the message */
+    realm_sendit_auth(notice, who, auth, realm, ack_to_sender);
 #else /* HAVE_KRB4 */
-  realm_sendit(notice, who, auth, realm, ack_to_sender);
+    realm_sendit(notice, who, auth, realm, ack_to_sender);
 #endif /* HAVE_KRB4 */
 }
 
@@ -593,142 +927,174 @@ realm_sendit(notice, who, auth, realm, ack_to_sender)
     Realm *realm;
     int ack_to_sender;
 {
-  caddr_t pack;
-  int packlen;
-  Code_t retval;
-  Unacked *nacked;
+    caddr_t pack;
+    int packlen;
+    Code_t retval;
+    Unacked *nacked;
 
-  notice->z_auth = auth;
+    notice->z_auth = auth;
   
-  /* format the notice */
-  if ((retval = ZFormatRawNotice(notice, &pack, &packlen)) != ZERR_NONE) {
-    syslog(LOG_WARNING, "rlm_sendit format: %s",
-           error_message(retval));
-    return;
-  }
+    /* format the notice */
+    if ((retval = ZFormatRawNotice(notice, &pack, &packlen)) != ZERR_NONE) {
+       syslog(LOG_WARNING, "rlm_sendit format: %s",
+              error_message(retval));
+       return;
+    }
   
-  /* now send */
-  if ((retval = ZSetDestAddr(&realm->addrs[realm->idx])) != ZERR_NONE) {
-    syslog(LOG_WARNING, "rlm_sendit set addr: %s",
-           error_message(retval));
-    free(pack);
-    return;
-  }
-  if ((retval = ZSendPacket(pack, packlen, 0)) != ZERR_NONE) {
-    syslog(LOG_WARNING, "rlm_sendit xmit: %s", error_message(retval));
-    free(pack);
-    return;
-  }
-
-  /* now we've sent it, mark it as not ack'ed */
+    /* now send */
+    if ((retval = ZSetDestAddr(&realm->addrs[realm->idx])) != ZERR_NONE) {
+       syslog(LOG_WARNING, "rlm_sendit set addr: %s",
+              error_message(retval));
+       free(pack);
+       return;
+    }
+    if ((retval = ZSendPacket(pack, packlen, 0)) != ZERR_NONE) {
+       syslog(LOG_WARNING, "rlm_sendit xmit: %s", error_message(retval));
+       free(pack);
+       return;
+    }
+    
+    /* now we've sent it, mark it as not ack'ed */
   
-  if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) {
-    /* no space: just punt */
-    syslog(LOG_ERR, "rlm_sendit nack malloc");
-    free(pack);
+    if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) {
+       /* no space: just punt */
+       syslog(LOG_ERR, "rlm_sendit nack malloc");
+       free(pack);
+       return;
+    }
+
+    nacked->client = NULL;
+    nacked->rexmits = 0;
+    nacked->packet = pack;
+    nacked->dest.rlm.rlm_idx = realm - otherrealms;
+    nacked->dest.rlm.rlm_srv_idx = realm->idx;
+    nacked->packsz = packlen;
+    nacked->uid = notice->z_uid;
+    if (ack_to_sender)
+       nacked->ack_addr = *who;
+    else
+       nacked->ack_addr.sin_addr.s_addr = 0;
+
+    /* set a timer to retransmit */
+    nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked);
+    /* chain in */
+    LIST_INSERT(&rlm_nacklist, nacked);
     return;
-  }
-
-  nacked->client = NULL;
-  nacked->rexmits = 0;
-  nacked->packet = pack;
-  nacked->dest.rlm.rlm_idx = realm - otherrealms;
-  nacked->dest.rlm.rlm_srv_idx = realm->idx;
-  nacked->packsz = packlen;
-  nacked->uid = notice->z_uid;
-  if (ack_to_sender)
-    nacked->ack_addr = *who;
-  else
-    nacked->ack_addr.sin_addr.s_addr = 0;
-
-  /* set a timer to retransmit */
-  nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked);
-  /* chain in */
-  LIST_INSERT(&rlm_nacklist, nacked);
-  return;
 }
 
 static void
 packet_ctl_nack(nackpacket)
     Unacked *nackpacket;
 {
-  ZNotice_t notice;
+    ZNotice_t notice;
 
-  /* extract the notice */
-  ZParseNotice(nackpacket->packet, nackpacket->packsz, &notice);
-  nack(&notice, &nackpacket->ack_addr);
+    /* extract the notice */
+    ZParseNotice(nackpacket->packet, nackpacket->packsz, &notice);
+    if (nackpacket->ack_addr.sin_addr.s_addr != 0)
+       nack(&notice, &nackpacket->ack_addr);
+#if 1
+    else
+       syslog(LOG_WARNING, "would have acked nobody (%s/%s/%s)",
+              notice.z_class, notice.z_class_inst, notice.z_opcode); /* XXX */
+#endif
 }
 
 static void
 rlm_rexmit(arg)
     void *arg;
 {
-  Unacked *nackpacket = (Unacked *) arg;
-  Code_t retval;
-  register Realm *realm;
-  int new_srv_idx;
+    Unacked *nackpacket = (Unacked *) arg;
+    Code_t retval;
+    register Realm *realm;
+    int new_srv_idx;
 
-        zdbug((LOG_DEBUG,"rlm_rexmit"));
+    zdbug((LOG_DEBUG,"rlm_rexmit"));
 
-  realm = &otherrealms[nackpacket->dest.rlm.rlm_idx];
+    realm = &otherrealms[nackpacket->dest.rlm.rlm_idx];
 
-  zdbug((LOG_DEBUG, "rlm_rexmit: sending to %s", realm->name));
+    zdbug((LOG_DEBUG, "rlm_rexmit: sending to %s:%d (%d)",
+          realm->name, realm->idx, nackpacket->rexmits));
 
-  if (rexmit_times[(nackpacket->rexmits + 1)/(realm->count)] == -1) {
-    /* give a server ack that the packet is lost/realm dead */
-    packet_ctl_nack(nackpacket);
-    LIST_DELETE(nackpacket);
-    free(nackpacket->packet);
-    free(nackpacket);
+    if (realm->count == 0)
+       return;
 
-    zdbug((LOG_DEBUG, "rlm_rexmit: %s appears dead", realm->name));
-    return;
-  }
+    /* Check to see if we've retransmitted as many times as we can */
+    if (nackpacket->rexmits >= (NUM_REXMIT_TIMES * realm->count)) {
+       /* give a server ack that the packet is lost/realm dead */
+       packet_ctl_nack(nackpacket);
+       LIST_DELETE(nackpacket);
+       
+       zdbug((LOG_DEBUG, "rlm_rexmit: %s appears dead", realm->name));
+       realm->state = REALM_DEAD;
 
-  /* retransmit the packet, trying each server in the realm multiple times */
-#if 0
-  new_srv_idx = ((nackpacket->rexmits / NUM_REXMIT_TIMES)
-                 + nackpacket->rlm.rlm_srv_idx) % realm->count;
-#else
-  new_srv_idx = nackpacket->rexmits % realm->count;
-#endif
-  if (new_srv_idx != realm->idx)
-    realm->idx = new_srv_idx;
-
-  retval = ZSetDestAddr(&realm->addrs[realm->idx]);
-  if (retval != ZERR_NONE) {
-    syslog(LOG_WARNING, "rlm_rexmit set addr: %s", error_message(retval));
-  } else {
-    retval = ZSendPacket(nackpacket->packet, nackpacket->packsz, 0);
-    if (retval != ZERR_NONE)
-      syslog(LOG_WARNING, "rlm_rexmit xmit: %s", error_message(retval));
-  }
-  /* reset the timer */
-  if (rexmit_times[(nackpacket->rexmits + 1)/(realm->count)] != -1)
+       free(nackpacket->packet);
+       free(nackpacket);
+       return;
+    }
+
+    /* if we've reached our limit, move on to the next server */
+    if ((realm->state == REALM_TARDY) || 
+       (nackpacket->rexmits && 
+        !((nackpacket->rexmits+1) % (NUM_REXMIT_TIMES/3)))) 
+    {
+       realm->idx = (realm->idx + 1) % realm->count;
+       zdbug((LOG_DEBUG, "rlm_rexmit: %s switching servers:%d (%s)", 
+              realm->name, realm->idx, 
+              inet_ntoa((realm->addrs[realm->idx]).sin_addr)));
+    }
+
+    /* throttle back if it looks like the realm is down */
+    if ((realm->state != REALM_DEAD) || 
+       ((nackpacket->rexmits % (realm->count+1)) == 1)) {
+       /* do the retransmit */
+       retval = ZSetDestAddr(&realm->addrs[realm->idx]);
+       if (retval != ZERR_NONE) {
+           syslog(LOG_WARNING, "rlm_rexmit set addr: %s", 
+                  error_message(retval));
+       } else {
+           retval = ZSendPacket(nackpacket->packet, nackpacket->packsz, 0);
+           if (retval != ZERR_NONE)
+               syslog(LOG_WARNING, "rlm_rexmit xmit: %s",
+                      error_message(retval));
+       }
+       /* no per-server nack queues for foreign realms yet, doesn't matter */
+       nackpacket->dest.rlm.rlm_srv_idx = realm->idx;
+       zdbug((LOG_DEBUG, "rlm_rexmit(%s): send to %s", realm->name,
+              inet_ntoa((realm->addrs[realm->idx]).sin_addr)));
+    } else {
+       zdbug((LOG_DEBUG, "rlm_rexmit(%s): not sending to %s", realm->name,
+              inet_ntoa((realm->addrs[realm->idx]).sin_addr)));
+    }
+
+    /* reset the timer */
     nackpacket->rexmits++;
-  
-  nackpacket->timer = timer_set_rel(rexmit_times[(nackpacket->rexmits)/(realm->count)], rlm_rexmit, nackpacket);
-  return;
+    nackpacket->timer = 
+       timer_set_rel(rexmit_times[nackpacket->rexmits%NUM_REXMIT_TIMES], 
+                     rlm_rexmit, nackpacket);
+    if (rexmit_times[nackpacket->rexmits%NUM_REXMIT_TIMES] == -1)
+       zdbug((LOG_DEBUG, "rlm_rexmit(%s): would send at -1 to %s", 
+              realm->name, inet_ntoa((realm->addrs[realm->idx]).sin_addr)));
+    
+    return;
 }
 
 void
 realm_dump_realms(fp)
     FILE *fp;
 {
-  register int ii, jj;
+    register int ii, jj;
   
-  for (ii = 0; ii < nrealms; ii++) {
-    (void) fprintf(fp, "%d:%s\n", ii, otherrealms[ii].name);
-    for (jj = 0; jj < otherrealms[ii].count; jj++) {
-      (void) fprintf(fp, "\t%s\n",
-                     inet_ntoa(otherrealms[ii].addrs[jj].sin_addr));
+    for (ii = 0; ii < nrealms; ii++) {
+       (void) fprintf(fp, "%d:%s\n", ii, otherrealms[ii].name);
+       for (jj = 0; jj < otherrealms[ii].count; jj++) {
+           (void) fprintf(fp, "\t%s\n",
+                          inet_ntoa(otherrealms[ii].addrs[jj].sin_addr));
+       }
+       /* dump the subs */
+       subscr_dump_subs(fp, otherrealms[ii].subs);
     }
-    /* dump the subs */
-    subscr_dump_subs(fp, otherrealms[ii].subs);
-  }
 }
 
-
 #ifdef HAVE_KRB4
 static void
 realm_sendit_auth(notice, who, auth, realm, ack_to_sender)
@@ -738,344 +1104,382 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender)
     Realm *realm;
     int ack_to_sender;
 {
-  char *buffer, *ptr;
-  caddr_t pack;
-  int buffer_len, hdrlen, offset, fragsize, ret_len, message_len;
-  int origoffset, origlen;
-  Code_t retval;
-  Unacked *nacked;
-  char buf[1024], multi[64];
-  CREDENTIALS cred;
-  KTEXT_ST authent;
-  ZNotice_t partnotice, newnotice;
-
-  offset = 0;
-
-  /* first, build an authent */
-  retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm->name, &cred);
-  if (retval != GC_OK) {
-    syslog(LOG_WARNING, "rlm_sendit_auth get_cred: %s",
-           error_message(retval+krb_err_base));
-    return;
-  }
+    char *buffer, *ptr;
+    caddr_t pack;
+    int buffer_len, hdrlen, offset, fragsize, ret_len, message_len;
+    int origoffset, origlen;
+    Code_t retval;
+    Unacked *nacked;
+    char buf[1024], multi[64];
+    CREDENTIALS cred;
+    KTEXT_ST authent;
+    ZNotice_t partnotice, newnotice;
+
+    offset = 0;
+
+    /* build an authent. first, make sure we have the ticket available */
+    retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm->name, &cred);
+    if (retval != GC_OK) {
+       syslog(LOG_WARNING, "rlm_sendit_auth get_cred: %s",
+              error_message(retval+krb_err_base));
+       return;
+    }
 
-  retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
-                     realm->name, 1);
-  if (retval != MK_AP_OK) {
-    syslog(LOG_WARNING, "rlm_sendit_auth mk_req: %s",
-           error_message(retval+krb_err_base));
-    return;
-  }
+    retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, 
+                       realm->name, 1);
+    if (retval != MK_AP_OK) {
+       syslog(LOG_WARNING, "rlm_sendit_auth mk_req: %s",
+              error_message(retval+krb_err_base));
+       return;
+    }
 
-  retval = ZMakeAscii(buf, sizeof(buf), authent.dat, authent.length);
-  if (retval != ZERR_NONE) {
-    syslog(LOG_WARNING, "rlm_sendit_auth mk_ascii: %s",
-           error_message(retval));
-    return;
-  }
+    retval = ZMakeAscii(buf, sizeof(buf), authent.dat, authent.length);
+    if (retval != ZERR_NONE) {
+       syslog(LOG_WARNING, "rlm_sendit_auth mk_ascii: %s",
+              error_message(retval));
+       return;
+    }
 
-  /* set the dest addr */
-  retval = ZSetDestAddr(&realm->addrs[realm->idx]);
-  if (retval != ZERR_NONE) {
-    syslog(LOG_WARNING, "rlm_sendit_auth set addr: %s", error_message(retval));
-    return;
-  }
-
-  /* now format the notice, refragmenting if needed */
-  newnotice = *notice;
-  newnotice.z_auth = 1;
-  newnotice.z_ascii_authent = buf;
-  newnotice.z_authent_len = authent.length;
-
-  buffer = (char *) malloc(sizeof(ZPacket_t));
-  if (!buffer) {
-    syslog(LOG_ERR, "realm_sendit_auth malloc");
-    return;                 /* DON'T put on nack list */
-  }
-
-  buffer_len = sizeof(ZPacket_t);
-
-  retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, &ptr, 
-                             NULL);
-  if (retval != ZERR_NONE) {
-    syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval));
-    free(buffer);
-    return;
-  }
+    /* set the dest addr */
+    retval = ZSetDestAddr(&realm->addrs[realm->idx]);
+    if (retval != ZERR_NONE) {
+       syslog(LOG_WARNING, "rlm_sendit_auth set addr: %s", 
+              error_message(retval));
+       return;
+    }
+
+    /* now format the notice, refragmenting if needed */
+    newnotice = *notice;
+    newnotice.z_auth = 1;
+    newnotice.z_ascii_authent = buf;
+    newnotice.z_authent_len = authent.length;
+    
+    buffer = (char *) malloc(sizeof(ZPacket_t));
+    if (!buffer) {
+       syslog(LOG_ERR, "realm_sendit_auth malloc");
+       return;                 /* DON'T put on nack list */
+    }
+    
+    buffer_len = sizeof(ZPacket_t);
+    
+    retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, &ptr, 
+                              NULL);
+    if (retval != ZERR_NONE) {
+       syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval));
+       free(buffer);
+       return;
+    }
 
 #ifdef NOENCRYPTION
-  newnotice.z_checksum = 0;
+    newnotice.z_checksum = 0;
 #else
-  newnotice.z_checksum =
-    (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, cred.session);
+    newnotice.z_checksum =
+       (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, 
+                                   cred.session);
 #endif
 
-  retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, 
-                             NULL, NULL);
-  if (retval != ZERR_NONE) {
-    syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval));
-    free(buffer);
-    return;
-  }
+    retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, 
+                              NULL, NULL);
+    if (retval != ZERR_NONE) {
+       syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval));
+       free(buffer);
+       return;
+    }
   
-  /* This is not terribly pretty, but it does do its job. 
-   * If a packet we get that needs to get sent off to another realm is
-   * too big after we slap on our authent, we refragment it further,
-   * a la Z_SendFragmentedNotice. This obliviates the need for what
-   * used to be done in ZFormatAuthenticRealmNotice, as we do it here.
-   * At some point it should be pulled back out into its own function,
-   * but only the server uses it.
-   */ 
-
-  if ((newnotice.z_message_len+hdrlen > buffer_len) || 
-      (newnotice.z_message_len+hdrlen > Z_MAXPKTLEN)){
-    /* Deallocate buffer, use a local one */
-    free(buffer);
+    /* This is not terribly pretty, but it does do its job. 
+     * If a packet we get that needs to get sent off to another realm is
+     * too big after we slap on our authent, we refragment it further,
+     * a la Z_SendFragmentedNotice. This obviates the need for what
+     * used to be done in ZFormatAuthenticRealmNotice, as we do it here.
+     * At some point it should be pulled back out into its own function,
+     * but only the server uses it.
+     */ 
+
+    if ((newnotice.z_message_len+hdrlen > buffer_len) || 
+       (newnotice.z_message_len+hdrlen > Z_MAXPKTLEN)) {
+       /* Deallocate buffer, use a local one */
+       free(buffer);
     
-    partnotice = *notice;
+       partnotice = *notice;
 
-    partnotice.z_auth = 1;
-    partnotice.z_ascii_authent = buf;
-    partnotice.z_authent_len = authent.length;
+       partnotice.z_auth = 1;
+       partnotice.z_ascii_authent = buf;
+       partnotice.z_authent_len = authent.length;
 
-    origoffset = 0;
-    origlen = notice->z_message_len;
+       origoffset = 0;
+       origlen = notice->z_message_len;
 
-    if (notice->z_multinotice && strcmp(notice->z_multinotice, ""))
-      if (sscanf(notice->z_multinotice, "%d/%d", &origoffset, &origlen) != 2) {
-        syslog(LOG_WARNING, "rlm_sendit_auth frag: parse failed");
-        return;
-      }
+       if (notice->z_multinotice && strcmp(notice->z_multinotice, ""))
+           if (sscanf(notice->z_multinotice, "%d/%d", &origoffset, 
+                      &origlen) != 2) {
+               syslog(LOG_WARNING, "rlm_sendit_auth frag: parse failed");
+               return;
+           }
 
 #if 0
-    zdbug((LOG_DEBUG,"rlm_send_auth: orig: %d-%d/%d", origoffset, notice->z_message_len, origlen));
+       zdbug((LOG_DEBUG,"rlm_send_auth: orig: %d-%d/%d", origoffset, 
+              notice->z_message_len, origlen));
 #endif
 
-    fragsize = Z_MAXPKTLEN-hdrlen-Z_FRAGFUDGE;
-
-    while (offset < notice->z_message_len || !notice->z_message_len) {
-      (void) sprintf(multi, "%d/%d", offset+origoffset, origlen);
-      partnotice.z_multinotice = multi;
-      if (offset > 0) {
-        (void) gettimeofday(&partnotice.z_uid.tv, (struct timezone *)0);
-        partnotice.z_uid.tv.tv_sec = htonl((u_long) 
-                                           partnotice.z_uid.tv.tv_sec);
-        partnotice.z_uid.tv.tv_usec = htonl((u_long) 
-                                            partnotice.z_uid.tv.tv_usec);
-        (void) memcpy((char *)&partnotice.z_uid.zuid_addr, &__My_addr, 
-                      sizeof(__My_addr));
-      }
-      message_len = min(notice->z_message_len-offset, fragsize);
-      partnotice.z_message = notice->z_message+offset;
-      partnotice.z_message_len = message_len;
+       fragsize = Z_MAXPKTLEN-hdrlen-Z_FRAGFUDGE;
+
+       while (offset < notice->z_message_len || !notice->z_message_len) {
+           (void) sprintf(multi, "%d/%d", offset+origoffset, origlen);
+           partnotice.z_multinotice = multi;
+           if (offset > 0) {
+               (void) gettimeofday(&partnotice.z_uid.tv, 
+                                   (struct timezone *)0);
+               partnotice.z_uid.tv.tv_sec = htonl((u_long) 
+                                                  partnotice.z_uid.tv.tv_sec);
+               partnotice.z_uid.tv.tv_usec = 
+                   htonl((u_long) partnotice.z_uid.tv.tv_usec);
+               (void) memcpy((char *)&partnotice.z_uid.zuid_addr, &__My_addr, 
+                             sizeof(__My_addr));
+           }
+           message_len = min(notice->z_message_len-offset, fragsize);
+           partnotice.z_message = notice->z_message+offset;
+           partnotice.z_message_len = message_len;
 
 #if 0
-      zdbug((LOG_DEBUG,"rlm_send_auth: new: %d-%d/%d", origoffset+offset, message_len, origlen));
+           zdbug((LOG_DEBUG,"rlm_send_auth: new: %d-%d/%d", 
+                  origoffset+offset, message_len, origlen));
 #endif
 
-      buffer = (char *) malloc(sizeof(ZPacket_t));
-      if (!buffer) {
-        syslog(LOG_ERR, "realm_sendit_auth malloc");
-        return;                 /* DON'T put on nack list */
-      }
-
-      retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, &hdrlen, 
-                                 &ptr, NULL);
-      if (retval != ZERR_NONE) {
-        syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval));
-        free(buffer);
-        return;
-      }
+           buffer = (char *) malloc(sizeof(ZPacket_t));
+           if (!buffer) {
+               syslog(LOG_ERR, "realm_sendit_auth malloc");
+               return;                 /* DON'T put on nack list */
+           }
+           
+           retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, 
+                                      &hdrlen, &ptr, NULL);
+           if (retval != ZERR_NONE) {
+               syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", 
+                      error_message(retval));
+               free(buffer);
+               return;
+           }
 
 #ifdef NOENCRYPTION
-      partnotice.z_checksum = 0;
+           partnotice.z_checksum = 0;
 #else
-      partnotice.z_checksum =
-        (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, 
-                                    cred.session);
+           partnotice.z_checksum =
+               (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, 
+                                           cred.session);
 #endif
 
-      retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, &hdrlen, 
-                                 NULL, NULL);
-      if (retval != ZERR_NONE) {
-        syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval));
-        free(buffer);
-        return;
-      }
-
-      ptr = buffer+hdrlen;
-
-      (void) memcpy(ptr, partnotice.z_message, partnotice.z_message_len);
-
-      buffer_len = hdrlen+partnotice.z_message_len;
-
-      /* now send */
-      if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) {
-        syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s", error_message(retval));
-        free(buffer);
-        return;
-      }
-
-      offset += fragsize;
-
-      if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) {
-        /* no space: just punt */
-        syslog(LOG_ERR, "rlm_sendit_auth nack malloc");
-        free(buffer);
-        return;
-      }
-
-      nacked->rexmits = 0;
-      nacked->packet = buffer;
-      nacked->dest.rlm.rlm_idx = realm - otherrealms;
-      nacked->dest.rlm.rlm_srv_idx = realm->idx;
-      nacked->packsz = buffer_len;
-      nacked->uid = partnotice.z_uid;
-
-    /* Do the ack for the last frag, below */
-      if (ack_to_sender)
-        nacked->ack_addr = *who;
-      else
-        nacked->ack_addr.sin_addr.s_addr = 0;
-
-      /* set a timer to retransmit */
-      nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked);
-
-      /* chain in */
-      LIST_INSERT(&rlm_nacklist, nacked);
-
-      if (!notice->z_message_len)
-        break;
-    }
+           retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, 
+                                      &hdrlen, NULL, NULL);
+           if (retval != ZERR_NONE) {
+               syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", 
+                      error_message(retval));
+               free(buffer);
+               return;
+           }
+
+           ptr = buffer+hdrlen;
+
+           (void) memcpy(ptr, partnotice.z_message, partnotice.z_message_len);
+
+           buffer_len = hdrlen+partnotice.z_message_len;
+
+           /* now send */
+           if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) {
+               syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s", 
+                      error_message(retval));
+               free(buffer);
+               return;
+           }
+
+           if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) {
+               /* no space: just punt */
+               syslog(LOG_ERR, "rlm_sendit_auth nack malloc");
+               free(buffer);
+               return;
+           }
+
+           nacked->rexmits = 0;
+           nacked->packet = buffer;
+           nacked->dest.rlm.rlm_idx = realm - otherrealms;
+           nacked->dest.rlm.rlm_srv_idx = realm->idx;
+           nacked->packsz = buffer_len;
+           nacked->uid = partnotice.z_uid;
+
+           /* Do the ack for the last frag, below */
+           if (ack_to_sender)
+               nacked->ack_addr = *who;
+           else
+               nacked->ack_addr.sin_addr.s_addr = 0;
+
+           /* set a timer to retransmit */
+           nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked);
+
+           /* chain in */
+           LIST_INSERT(&rlm_nacklist, nacked);
+
+           offset += fragsize;
+           
+           if (!notice->z_message_len)
+               break;
+       }
 #if 0
-    zdbug((LOG_DEBUG, "rlm_sendit_auth frag message sent"));
+       zdbug((LOG_DEBUG, "rlm_sendit_auth frag message sent"));
 #endif
-  } else {
-    /* This is easy, no further fragmentation needed */
-    ptr = buffer+hdrlen;
+    } else {
+       /* This is easy, no further fragmentation needed */
+       ptr = buffer+hdrlen;
 
-    (void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len);
+       (void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len);
 
-    buffer_len = hdrlen+newnotice.z_message_len;
+       buffer_len = hdrlen+newnotice.z_message_len;
     
-    /* now send */
-    if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) {
-      syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s", error_message(retval));
-      free(buffer);
-      return;
-    }
+       /* now send */
+       if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) {
+           syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s", 
+                  error_message(retval));
+           free(buffer);
+           return;
+       }
 
 #if 0
-    zdbug((LOG_DEBUG, "rlm_sendit_auth message sent"));
+       zdbug((LOG_DEBUG, "rlm_sendit_auth message sent"));
 #endif
-    /* now we've sent it, mark it as not ack'ed */
+       /* now we've sent it, mark it as not ack'ed */
     
-    if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) {
-      /* no space: just punt */
-      syslog(LOG_ERR, "rlm_sendit_auth nack malloc");
-      free(buffer);
-      return;
-    }
-
-    nacked->rexmits = 0;
-    nacked->packet = buffer;
-    nacked->dest.rlm.rlm_idx = realm - otherrealms;
-    nacked->dest.rlm.rlm_srv_idx = realm->idx;
-    nacked->packsz = buffer_len;
-    nacked->uid = notice->z_uid;
+       if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) {
+           /* no space: just punt */
+           syslog(LOG_ERR, "rlm_sendit_auth nack malloc");
+           free(buffer);
+           return;
+       }
 
-    /* Do the ack for the last frag, below */
-    if (ack_to_sender)
-      nacked->ack_addr = *who;
-    else
-      nacked->ack_addr.sin_addr.s_addr = 0;
+       nacked->rexmits = 0;
+       nacked->packet = buffer;
+       nacked->dest.rlm.rlm_idx = realm - otherrealms;
+       nacked->dest.rlm.rlm_srv_idx = realm->idx;
+       nacked->packsz = buffer_len;
+       nacked->uid = notice->z_uid;
+       
+       /* Do the ack for the last frag, below */
+       if (ack_to_sender)
+           nacked->ack_addr = *who;
+       else
+           nacked->ack_addr.sin_addr.s_addr = 0;
     
-    /* set a timer to retransmit */
-    nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked);
-    /* chain in */
-    LIST_INSERT(&rlm_nacklist, nacked);
-  }
-#if 0
-  if (ack_to_sender)
-    nacked->ack_addr = *who;
-#endif
-  return;
+       /* set a timer to retransmit */
+       nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked);
+       /* chain in */
+       LIST_INSERT(&rlm_nacklist, nacked);
+    }
+    return;
 }
 
-int
+static int
 ticket_expired(cred)
 CREDENTIALS *cred;
 {
-        /* extra 15 minutes for safety margin */
-#ifdef AFS_LIFETIMES
-        return (krb_life_to_time(cred->issue_date, cred->lifetime) < NOW + 15*60);
-#else /* AFS_LIFETIMES */
-        return (cred->issue_date + cred->lifetime*5*60 < NOW + 15*60);
-#endif /* AFS_LIFETIMES */
+#ifdef HAVE_KRB_LIFE_TO_TIME
+    return (krb_life_to_time(cred->issue_date, cred->lifetime) < NOW);
+#else /* HAVE_KRB_LIFE_TO_TIME */
+    return (cred->issue_date + cred->lifetime*5*60 < NOW);
+#endif /* HAVE_KRB_LIFE_TO_TIME */
 }
 
-int
+static int
 ticket_lookup(realm)
 char *realm;
 {
-  CREDENTIALS cred;
-  KTEXT_ST authent;
-  int retval;
+    CREDENTIALS cred;
+    KTEXT_ST authent;
+    int retval;
 
-  retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm, &cred);
-  if (retval == GC_OK && !ticket_expired(&cred))
-    /* good ticket */
-    return(1);
+    retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm, &cred);
+    if (retval == GC_OK && !ticket_expired(&cred))
+       /* good ticket */
+       return(1);
 
-  if (!strcmp(realm, ZGetRealm())) {
-    get_tgt();
+    return (0);
+}
+
+static Code_t
+ticket_retrieve(realm)
+    Realm *realm;
+{
+    int pid, retval = 0;
+    KTEXT_ST authent;
     
+    get_tgt();
+
+    if (realm->child_pid) 
+       /* Right idea. Basically, we haven't gotten it yet */
+       return KRBET_KDC_AUTH_EXP;
+
     /* For Putrify */
     memset(&authent.dat,0,MAX_KTXT_LEN);
     authent.mbz=0;
 
-    /* this is local, so try to contact the Kerberos server */
-    retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
-                        realm, 0);
-    if (retval != KSUCCESS) {
-      syslog(LOG_ERR, "tkt_lookup: local: %s",
-             krb_err_txt[retval]);
-      return(0);
+    if (realm->have_tkt) {
+       retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
+                           realm->name, 0);
+       if (retval == KSUCCESS) {
+           return retval;
+       }
     } else {
-      return(1);
+       syslog(LOG_ERR, "tkt_rtrv: don't have ticket, but have no child");
     }
-  }
-  
-  return (0);
-}
+    pid = fork();
+    if (pid < 0) {
+       syslog(LOG_ERR, "tkt_rtrv: can't fork");
+       return KRBET_KDC_AUTH_EXP;
+    }
+    else if (pid == 0) {
+#ifdef _POSIX_VERSION
+       struct sigaction action;
+
+       action.sa_flags = 0;
+       sigemptyset(&action.sa_mask);
+       action.sa_handler = 0;
+       sigaction(SIGCHLD, &action, NULL);
+       sigaction(SIGINT, &action, NULL);
+       sigaction(SIGTERM, &action, NULL);
+       sigaction(SIGUSR1, &action, NULL);
+       sigaction(SIGUSR2, &action, NULL);
+       sigaction(SIGFPE, &action, NULL);
+       sigaction(SIGHUP, &action, NULL);
+#ifdef SIGEMT
+       sigaction(SIGEMT, &action, NULL);
+#endif
+#else
+       signal(SIGCHLD, SIG_DFL);
+       signal(SIGINT, SIG_DFL);
+       signal(SIGTERM, SIG_DFL);
+       signal(SIGUSR1, SIG_DFL);
+       signal(SIGUSR2, SIG_DFL);
+       signal(SIGFPE, SIG_DFL);
+       signal(SIGHUP, SIG_DFL);
+#ifdef SIGEMT
+       signal(SIGEMT, SIG_DFL);
+#endif
+#endif
 
-static Code_t
-ticket_retrieve(realm)
-    Realm *realm;
-{
-  int pid, retval;
-  KTEXT_ST authent;
-  
-  get_tgt();
-
-  /* For Putrify */
-  memset(&authent.dat,0,MAX_KTXT_LEN);
-  authent.mbz=0;
-
-  /* Don't lose by trying too often. */
-  if (NOW - realm->tkt_try > 5 * 60) {
-    retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
-                       realm->name, 0);
-    realm->tkt_try = NOW;
-    if (retval != KSUCCESS) {
-      syslog(LOG_WARNING, "tkt_rtrv: %s: %s", realm,
-            krb_err_txt[retval]);
-      return (retval+krb_err_base);
+       while (1) {
+           retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
+                               realm->name, 0);
+           if (retval == KSUCCESS)
+               exit(0);
+      
+           /* Sleep a little while before retrying */
+           sleep(30);
+       }
+    } else {
+       realm->child_pid = pid;
+       realm->have_tkt = 0;
+       
+       syslog(LOG_WARNING, "tkt_rtrv: %s: %s", realm->name,
+              krb_err_txt[retval]);
+       return (retval+krb_err_base);
     }
-    return (0);
-  } else {
-    return (1);
-  }
 }
 #endif /* HAVE_KRB4 */
 
index 928fdfd1ed019f63e984de3bea37d4e516b8d155..ec207d533e6b59da851b035ec793f3de6963f53a 100644 (file)
@@ -3,7 +3,8 @@
  *
  *     Created by:     John T. Kohl
  *
- *     $Id: server.c,v 1.65 1999/01/22 23:19:47 ghudson Exp $
+ *     $Source: /afs/dev.mit.edu/source/repository/athena/lib/zephyr/server/server.c,v $
+ *     $Author: zacheiss $
  *
  *     Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology.
  *     For copying and distribution information, see the file
@@ -16,7 +17,7 @@
 
 #ifndef lint
 #ifndef SABER
-static const char rcsid_server_c[] = "$Id: server.c,v 1.65 1999/01/22 23:19:47 ghudson Exp $";
+static const char rcsid_server_c[] = "$Id: server.c,v 1.66 2001/02/27 04:51:41 zacheiss Exp $";
 #endif
 #endif
 
@@ -419,6 +420,13 @@ srv_states[] = {
     "SERV_DEAD",
     "SERV_STARTING"
 };
+static char *
+rlm_states[] = {
+    "REALM_UP",
+    "REALM_TARDY",
+    "REALM_DEAD",
+    "REALM_STARTING"
+};
 
 /* 
  * A server timout has expired.  If enough hello's have been unanswered,
@@ -639,6 +647,8 @@ server_kill_clt(client)
 
     pnotice = &notice;
 
+    memset (&notice, 0, sizeof(notice));
     pnotice->z_kind = ACKED;
 
     pnotice->z_port = srv_addr.sin_port;
@@ -872,10 +882,9 @@ send_stats(who)
     char **responses;
     int num_resp;
     char *vers, *pkts, *upt;
+    Realm *realm;
 
-#if defined(OLD_COMPAT) || defined(NEW_COMPAT)
     int extrafields = 0;
-#endif /* OLD_ or NEW_COMPAT */
 #define        NUM_FIXED 3                     /* 3 fixed fields, plus server info */
                                        /* well, not really...but for
                                           backward compatibility, we gotta
@@ -901,12 +910,9 @@ send_stats(who)
     if (new_compat_count_subscr)
        extrafields++;
 #endif /* NEW_COMPAT */
-#if defined(OLD_COMPAT) || defined(NEW_COMPAT)
+    extrafields += nrealms;
     responses = (char **) malloc((NUM_FIXED + nservers + extrafields) *
                                 sizeof(char *));
-#else
-    responses = (char **) malloc((NUM_FIXED + nservers) * sizeof(char *));
-#endif /* OLD_ or NEW_COMPAT */
     responses[0] = vers;
     responses[1] = pkts;
     responses[2] = upt;
@@ -944,6 +950,12 @@ send_stats(who)
        responses[num_resp++] = strsave(buf);
     }
 #endif /* NEW_COMPAT */
+    for (realm = otherrealms, i = 0; i < nrealms ; i++, realm++) {
+      sprintf(buf, "%s(%s)/%s", realm->name, 
+             inet_ntoa((realm->addrs[realm->idx]).sin_addr),
+             rlm_states[(int) realm->state]);
+      responses[num_resp++] = strsave(buf);
+    }
 
     send_msg_list(who, ADMIN_STATUS, responses, num_resp, 0);
 
@@ -1251,6 +1263,8 @@ send_msg(who, opcode, auth)
 
     pnotice = &notice;
 
+    memset (&notice, 0, sizeof(notice));
+
     pnotice->z_kind = ACKED;
 
     pnotice->z_port = srv_addr.sin_port;
@@ -1307,6 +1321,8 @@ send_msg_list(who, opcode, lyst, num, auth)
     Code_t retval;
     Unacked *nacked;
 
+    memset (&notice, 0, sizeof(notice));
+
     notice.z_kind = UNSAFE;
     notice.z_port = srv_addr.sin_port;
     notice.z_class = ZEPHYR_ADMIN_CLASS;
index e937f67d229ba947ce102a0f971b6eb516a11a74..00e6ab00bcbfbaf4a2ac7cf0f901f64841b3d67f 100644 (file)
@@ -3,7 +3,8 @@
  *
  *     Created by:     John T. Kohl
  *
- *     $Id: subscr.c,v 1.56 1999/01/22 23:19:48 ghudson Exp $
+ *     $Source: /afs/dev.mit.edu/source/repository/athena/lib/zephyr/server/subscr.c,v $
+ *     $Author: zacheiss $
  *
  *     Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
  *     For copying and distribution information, see the file
@@ -15,7 +16,7 @@
 
 #ifndef lint
 #ifndef SABER
-static const char rcsid_subscr_c[] = "$Id: subscr.c,v 1.56 1999/01/22 23:19:48 ghudson Exp $";
+static const char rcsid_subscr_c[] = "$Id: subscr.c,v 1.58 2001/03/01 00:47:05 zacheiss Exp $";
 #endif
 #endif
 
@@ -85,20 +86,19 @@ extern int new_compat_count_subscr; /* counter of old use */
 
 extern char *re_comp(), *re_conv();
 static Code_t add_subscriptions __P((Client *who, Destlist *subs_queue,
-                                  ZNotice_t *notice));
+                                  ZNotice_t *notice, Server *server));
 static Destlist *extract_subscriptions __P((ZNotice_t *notice));
 static void free_subscriptions __P((Destlist *subs));
+static void free_subscription __P((Destlist *sub));
 static char **subscr_marshal_subs __P((ZNotice_t *notice, int auth,
                                     struct sockaddr_in *who,
                                     int *found));
 static Destlist *subscr_copy_def_subs __P((char *person));
-static Code_t subscr_subscribe_realms __P((struct sockaddr_in *who,
-                                          Destlist *newsubs,
-                                          ZNotice_t *notice));
 static Code_t subscr_realm_sendit __P((Client *who, Destlist *subs,
                                       ZNotice_t *notice, Realm *realm));
 static void subscr_unsub_realms __P((Destlist *newsubs));
-static void subscr_unsub_sendit __P((Destlist *subs, Realm *realm));
+static void subscr_unsub_sendit __P((Client *who, Destlist *subs, 
+                                    Realm *realm));
 static int cl_match  __P((Destlist*, Client *));
 
 static int defaults_read = 0;          /* set to 1 if the default subs
@@ -118,21 +118,23 @@ String *empty;
  */
 
 Code_t
-subscr_subscribe(who, notice)
+subscr_subscribe(who, notice, server)
     Client *who;
     ZNotice_t *notice;
+    Server *server;
 {
     Destlist *subs;
 
     subs = extract_subscriptions(notice);
-    return add_subscriptions(who, subs, notice);
+    return add_subscriptions(who, subs, notice, server);
 }
 
 static Code_t
-add_subscriptions(who, subs, notice)
+add_subscriptions(who, subs, notice, server)
     Client *who;
     Destlist *subs;
     ZNotice_t *notice;
+    Server *server;
 {
     Destlist *next;
     Code_t retval;
@@ -152,18 +154,25 @@ add_subscriptions(who, subs, notice)
        zdbug ((LOG_DEBUG, "subscr: %s/%s/%s", subs->dest.classname->string,
                subs->dest.inst->string, subs->dest.recip->string));
 #endif
+       /* check the recipient for a realm which isn't ours */
+       realm = NULL;
+       if (subs->dest.recip->string[0] == '@' &&
+           strcmp((subs->dest.recip->string + 1), ZGetRealm()) != 0)
+           realm = realm_get_realm_by_name(subs->dest.recip->string + 1);
        if (!bdumping) {
            if (subs->dest.recip != empty && subs->dest.recip != sender
                && subs->dest.recip->string[0] != '@') {
                syslog(LOG_WARNING, "subscr unauth %s recipient %s",
                       sender->string, subs->dest.recip->string);
-               continue;
+               free_subscription(subs); /* free this one - denied */
+               continue; /* the for loop */
            }
            acl = class_get_acl(subs->dest.classname);
-           if (acl) {
+           if (acl && !realm) {
                if (!access_check(sender->string, acl, SUBSCRIBE)) {
                    syslog(LOG_WARNING, "subscr unauth %s class %s",
                           sender->string, subs->dest.classname->string);
+                   free_subscription(subs); /* free this one - denied */
                    continue; /* the for loop */
                }
                if (wildcard_instance == subs->dest.inst) {
@@ -171,36 +180,39 @@ add_subscriptions(who, subs, notice)
                        syslog(LOG_WARNING,
                               "subscr unauth %s class %s wild inst",
                               sender->string, subs->dest.classname->string);
-                       continue;
+                       free_subscription(subs); /* free this one - denied */
+                       continue; /* the for loop */
                    }
                }
            }
        }
-       /* check the recipient for a realm which isn't ours */
-       realm = NULL;
-       if (subs->dest.recip->string[0] == '@' &&
-           strcmp((subs->dest.recip->string + 1), ZGetRealm()) != 0)
-           realm = realm_get_realm_by_name(subs->dest.recip->string + 1);
-       if (realm) {
+       if (realm && !bdumping && server && server == me_server) {
            retval = subscr_realm_sendit(who, subs, notice, realm);
            if (retval != ZERR_NONE) {
-               free(subs);
+               free_subscriptions(subs);
+               free_string(sender);
                return(retval);
-           }
-       }
-       retval = triplet_register(who, &subs->dest, realm);
-       if (retval != ZERR_NONE) {
-           free(subs);
-           if (retval == ZSRV_CLASSXISTS) {
-               continue;
            } else {
-               free_subscriptions(next);
-               return retval;
+             free_subscription(subs); /* free this one, will get from ADD */
            }
+       } else {
+         retval = triplet_register(who, &subs->dest, NULL);
+         if (retval != ZERR_NONE) {
+             if (retval == ZSRV_CLASSXISTS) {
+                 free_subscription(subs); /* free this one */
+             } else {
+                 free_subscriptions(subs);
+                 free_string(sender);
+                 return retval;
+             }
+         } else {
+             /* If realm, let the REALM_ADD_SUBSCRIBE do insertion */
+             LIST_INSERT(&who->subs, subs);
+         }
        }
-       LIST_INSERT(&who->subs, subs);
     }
 
+    free_string(sender);
     return ZERR_NONE;
 }
 
@@ -215,7 +227,7 @@ subscr_def_subs(who)
     Destlist *subs;
 
     subs = subscr_copy_def_subs(who->principal->string);
-    return add_subscriptions(who, subs, &default_notice);
+    return add_subscriptions(who, subs, &default_notice, NULL);
 }
 
 void
@@ -343,20 +355,17 @@ subscr_cancel(sin, notice)
            client_next = client_subs->next;
            if (ZDest_eq(&client_subs->dest, &subs->dest)) {
                LIST_DELETE(client_subs);
-               triplet_deregister(who, &client_subs->dest, NULL);
+               retval = triplet_deregister(who, &client_subs->dest, NULL);
                if (retval == ZSRV_EMPTYCLASS &&
                    client_subs->dest.recip->string[0] == '@') {
                    realm =
                        realm_get_realm_by_name(client_subs->dest.recip->string
                                                + 1);
                    if (realm)
-                       subscr_unsub_sendit(client_subs, realm);
+                       subscr_unsub_sendit(who, client_subs, realm);
                    realm = NULL;
                }
-               free_string(client_subs->dest.classname);
-               free_string(client_subs->dest.inst);
-               free_string(client_subs->dest.recip);
-               free(client_subs);
+               free_subscription(client_subs);
                found = 1;
                break;
            }
@@ -406,10 +415,7 @@ subscr_realm_cancel(sin, notice, realm)
             if (ZDest_eq(&client_subs->dest, &subs->dest)) {
                 LIST_DELETE(client_subs);
                 retval = triplet_deregister(realm->client, &client_subs->dest, realm);
-                free_string(client_subs->dest.classname);
-                free_string(client_subs->dest.inst);
-                free_string(client_subs->dest.recip);
-                free(client_subs);
+               free_subscription(client_subs);
                 found = 1;
                 break;
             }
@@ -460,13 +466,10 @@ subscr_cancel_client(client)
            subs->dest.recip->string[0] == '@') {
            realm = realm_get_realm_by_name(subs->dest.recip->string + 1);
            if (realm)
-               subscr_unsub_sendit(subs, realm);
+               subscr_unsub_sendit(client, subs, realm);
            realm = NULL;
        }
-       free_string(subs->dest.classname);
-       free_string(subs->dest.inst);
-       free_string(subs->dest.recip);
-       free(subs);
+       free_subscription(subs);
     }
 
     client->subs = NULL;
@@ -918,6 +921,19 @@ subscr_send_subs(client)
  * free the memory allocated for the list of subscriptions.
  */
 
+/*
+ * free the memory allocated for one subscription.
+ */
+
+static void
+free_subscription(Destlist *sub)
+{
+    free_string(sub->dest.classname);
+    free_string(sub->dest.inst);
+    free_string(sub->dest.recip);
+    free(sub);
+}
+
 static void
 free_subscriptions(subs)
     Destlist *subs;
@@ -926,10 +942,7 @@ free_subscriptions(subs)
 
     for (; subs; subs = next) {
        next = subs->next;
-       free_string(subs->dest.classname);
-       free_string(subs->dest.inst);
-       free_string(subs->dest.recip);
-       free(subs);
+       free_subscription (subs);
     }
 }
 
@@ -1031,9 +1044,6 @@ subscr_realm_sendit(who, subs, notice, realm)
     ZNotice_t *notice;
     Realm *realm;
 {
-#if 0
-  Destlist *subs2;
-#endif
   ZNotice_t snotice;
   char *pack;
   int packlen;
@@ -1048,28 +1058,14 @@ subscr_realm_sendit(who, subs, notice, realm)
 #endif
 
 
-#ifdef notdef
-  for (subs2 = subs; subs2; subs2 = subs2->next, found++);
-  /* found is now the number of subscriptions */
-  
-  /* coalesce the subscription information into a list of char *'s */
-  /* one extra for client information */
-  if ((text = (char **) malloc((found * NUM_FIELDS + 2)
-                                * sizeof(char *))) == (char **) 0) 
-    {
-      syslog(LOG_ERR, "subscr_rlm_sendit malloc");
-      return(ENOMEM);
-    }
-#endif /* notdef */
-
   if ((text=(char **)malloc((NUM_FIELDS + 2)*sizeof(char *))) == (char **)0) {
       syslog(LOG_ERR, "subscr_rlm_sendit malloc");
       return(ENOMEM);
   }
   /* convert the address to a string of the form x.x.x.x/port */
-  strcpy(addr, inet_ntoa(notice->z_sender_addr));
+  strcpy(addr, inet_ntoa(who->addr.sin_addr));
   if ((retval = ZMakeAscii(port, sizeof(port), (unsigned char *) 
-                           &notice->z_port, sizeof(u_short))) != ZERR_NONE) 
+                           &who->addr.sin_port, sizeof(u_short))) != ZERR_NONE) 
     {
       syslog(LOG_ERR, "subscr_rlm_sendit make ascii: %s",
              error_message(retval));
@@ -1078,19 +1074,15 @@ subscr_realm_sendit(who, subs, notice, realm)
   text[0] = addr;
   text[1] = port;
 
-#ifdef notdef
-  for (i = 0, subs2 = subs; subs2, i < found ; i++, subs2 = subs2->next) {
-    text[i*NUM_FIELDS + 2] = subs2->dest.classname->string;
-    text[i*NUM_FIELDS + 3] = subs2->dest.inst->string;
-    text[i*NUM_FIELDS + 4] = subs2->dest.recip->string;
-  }
-#endif /* notdef */
-
   text[2] = subs->dest.classname->string;
   text[3] = subs->dest.inst->string;
   text[4] = subs->dest.recip->string;
   
+  zdbug((LOG_DEBUG, "subscr_realm_sendit %s/%s (%s) %s,%s,%s\n",
+         text[0], text[1], who->principal->string, text[2], text[3], text[4]));
+  
   /* format snotice */
+  memset (&snotice, 0, sizeof(snotice));
   snotice.z_class_inst = ZEPHYR_CTL_REALM;
   snotice.z_opcode = REALM_REQ_SUBSCRIBE;
   snotice.z_port = srv_addr.sin_port;
@@ -1101,17 +1093,12 @@ subscr_realm_sendit(who, subs, notice, realm)
   snotice.z_kind = ACKED;
   snotice.z_num_other_fields = 0;
   snotice.z_default_format = "";
-  snotice.z_sender = notice->z_sender;
+  snotice.z_sender = who->principal->string;
   snotice.z_recipient = notice->z_recipient;
   snotice.z_default_format = notice->z_default_format;
   
-#ifdef notdef
-  if ((retval = ZFormatNoticeList(&snotice, text, found * NUM_FIELDS + 2,
-                                  &pack, &packlen, ZNOAUTH)) != ZERR_NONE) 
-#else
   if ((retval = ZFormatNoticeList(&snotice, text, NUM_FIELDS + 2,
                                   &pack, &packlen, ZNOAUTH)) != ZERR_NONE) 
-#endif
     {
       syslog(LOG_WARNING, "subscr_rlm_sendit format: %s",
              error_message(retval));
@@ -1136,6 +1123,7 @@ subscr_realm_sendit(who, subs, notice, realm)
   return(ZERR_NONE);
 }
 
+/* Called from subscr_realm and subscr_foreign_user */
 static Code_t
 subscr_add_raw(client, realm, newsubs)
     Client *client;
@@ -1160,12 +1148,33 @@ subscr_add_raw(client, realm, newsubs)
 #endif
     retval = triplet_register(client, &subs->dest, realm);
     if (retval != ZERR_NONE) {
-      free(subs);
-      if (retval == ZSRV_CLASSXISTS) {
-        continue;
-      } else {
-        free_subscriptions(subs2);
-        return retval;
+       free_subscription(subs);
+       if (retval == ZSRV_CLASSXISTS) {
+           continue;
+       } else {
+           free_subscriptions(subs2);
+           return retval;
+       }
+    } else {
+      if (!realm) {
+       Realm *remrealm = 
+         realm_get_realm_by_name(subs->dest.recip->string + 1);
+       if (remrealm) {
+         Destlist *sub = (Destlist *) malloc(sizeof(Destlist));
+         if (!sub) {
+            syslog(LOG_WARNING, "subscr_add_raw: no mem");
+         } else {
+           sub->dest.classname = make_string(subs->dest.classname->string, 0);
+           sub->dest.inst = make_string(subs->dest.inst->string, 0);
+           sub->dest.recip = make_string(subs->dest.recip->string, 0);
+#if 1
+           zdbug ((LOG_DEBUG, "subscr: add %s/%s/%s in %s",
+                   sub->dest.classname->string, sub->dest.inst->string, 
+                   sub->dest.recip->string, remrealm->name));
+#endif
+           LIST_INSERT(&remrealm->remsubs, sub);
+         }
+       }
       }
     }
     LIST_INSERT(head, subs);
@@ -1173,6 +1182,7 @@ subscr_add_raw(client, realm, newsubs)
   return ZERR_NONE;
 }
 
+/* Called from bdump_recv_loop to decapsulate realm subs */
 Code_t
 subscr_realm(realm, notice)
     Realm *realm;
@@ -1192,21 +1202,41 @@ subscr_realm(realm, notice)
 
 /* Like realm_sendit, this only takes one item from subs */
 static void
-subscr_unsub_sendit(subs, realm)
+subscr_unsub_sendit(who, subs, realm)
+    Client *who;
     Destlist *subs;
     Realm *realm;
 {
   ZNotice_t unotice;
   Code_t retval;
-#ifdef notdef
-  char *list[7 * NUM_FIELDS];
-#else /* notdef */
-  char *list[NUM_FIELDS];
-#endif /* notdef */
+  char **list;
   char *pack;
   int packlen;
   int found = 0;
-  Destlist *subs2;
+  Destlist *subsp, *subsn;
+
+  for (subsp = realm->remsubs; subsp; subsp = subsn) {
+    subsn = subsp->next;
+    if (ZDest_eq(&subs->dest, &subsp->dest)) {
+#if 1
+      zdbug ((LOG_DEBUG, "subscr: del %s/%s/%s in %s",
+             subsp->dest.classname->string, subsp->dest.inst->string, 
+             subsp->dest.recip->string, realm->name));
+#endif
+      LIST_DELETE(subsp);
+      free_subscription(subsp);
+      break;
+    }
+  }
+
+  if ((list=(char **)malloc((NUM_FIELDS)*sizeof(char *))) == (char **)0) {
+      syslog(LOG_ERR, "subscr_unsub_sendit malloc");
+      return;
+  }
+
+  list[0] = subs->dest.classname->string;
+  list[1] = subs->dest.inst->string;
+  list[2] = "";
 
   unotice.z_class = ZEPHYR_CTL_CLASS;
   unotice.z_class_inst = ZEPHYR_CTL_REALM;
@@ -1219,52 +1249,13 @@ subscr_unsub_sendit(subs, realm)
   unotice.z_num_other_fields = 0;
   unotice.z_default_format = "";
 
-#ifdef notdef
-  found = 0;
-  for (subs2 = subs; subs2; subs2 = subs2->next) {
-    list[found * NUM_FIELDS] = subs2->dest.classname->string;
-    list[found * NUM_FIELDS + 1] = subs2->dest.inst->string;
-    list[found * NUM_FIELDS + 2] = "";
-          
-    found++;
-    
-    if (found >= 7) {
-      if ((retval = ZFormatNoticeList(&unotice, list, found * NUM_FIELDS, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) {
-        syslog(LOG_WARNING, "subscr_unsub_sendit format: %s",
-               error_message(retval));
-        return;
-      }
-      if ((retval = ZParseNotice(pack, packlen, &unotice)) != ZERR_NONE) {
-        syslog(LOG_WARNING, "subscr_unsub_sendit parse: %s",
-               error_message(retval));
-        free(pack);
-        return;
-      }
-      free(pack);
-      realm_handoff(&unotice, 1, (struct sockaddr_in *) 0, realm, 0);
-      found = 0;
-    }
-  }
-  
-  if (found == 0)
-    return;
-
-  if ((retval = ZFormatNoticeList(&unotice, list, found * NUM_FIELDS, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) {
-    syslog(LOG_WARNING, "subscr_unsub_sendit format: %s",
-           error_message(retval));
-    return;
-  }
-#else /* notdef */
-  list[0] = subs->dest.classname->string;
-  list[1] = subs->dest.inst->string;
-  list[2] = "";
-
   if ((retval = ZFormatNoticeList(&unotice, list, NUM_FIELDS, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) {
     syslog(LOG_WARNING, "subscr_unsub_sendit format: %s",
            error_message(retval));
+    free(list);
     return;
   }
-#endif /* notdef */
+  free(list);
 
   if ((retval = ZParseNotice(pack, packlen, &unotice)) != ZERR_NONE) {
     syslog(LOG_WARNING, "subscr_unsub_sendit parse: %s",
@@ -1272,10 +1263,11 @@ subscr_unsub_sendit(subs, realm)
     free(pack);
     return;
   }
+  realm_handoff(&unotice, 1, who ? &(who->addr) : NULL, realm, 0);
   free(pack);
-  realm_handoff(&unotice, 1, (struct sockaddr_in *) 0, realm, 0);
 }
 
+/* Called from bump_send_loop by way of realm_send_realms */
 Code_t
 subscr_send_realm_subs(realm)
     Realm *realm;
@@ -1343,117 +1335,222 @@ subscr_send_realm_subs(realm)
   return ZERR_NONE;
 }
 
-static Code_t
-subscr_check_foreign_subs(notice, who, realm, newsubs)
-    ZNotice_t *notice;
-    struct sockaddr_in *who;
+Code_t
+subscr_realm_subs(realm)
     Realm *realm;
-    Destlist *newsubs;
 {
-  Destlist *subs, *subs2, *next;
-  Acl *acl;
-  char **text;
-  int found = 0;
+  int i = 0;
+  Destlist *subs, *next;
+  char buf[512];
+  char *text[2 + NUM_FIELDS];
+  unsigned short num = 0;
+  Code_t retval;
   ZNotice_t snotice;
-  char *pack, *cp;
+  char *pack;
   int packlen;
-  Code_t retval;
-  String *sender;
-
-  for (subs = newsubs; subs; subs = subs->next)
-    found++;
-
-  if (found == 0)
-    return(ZERR_NONE);
-  
-  sender = make_string(notice->z_sender, 0);
-
-  if ((text = (char **)malloc((found * NUM_FIELDS + 2) * sizeof(char *))) == (char **) 0) {
-    syslog(LOG_ERR, "subscr_ck_forn_subs no mem(text)");
-    return(ENOMEM);
-  }
-
-  /* grab the client information from the incoming message */
-  cp = notice->z_message;
-  text[0] = cp;
-
-  I_ADVANCE(2);
-  text[1] = cp;
-
-  I_ADVANCE(3);
+  Client **clientp;
+  char port[16];
 
-  found = 0;
-  for (subs = newsubs; subs; subs = next) {
-    next=subs->next;
-    acl = class_get_acl(subs->dest.classname);
-    if (acl) {
-      if (!access_check(sender->string, acl, SUBSCRIBE)) {
-        syslog(LOG_WARNING, "subscr unauth %s class %s",
-               sender->string, subs->dest.classname->string);
-        continue; /* the for loop */
-      }
-      if (wildcard_instance == subs->dest.inst) {
-        if (!access_check(sender->string, acl, INSTWILD)) {
-          syslog(LOG_WARNING,
-                 "subscr unauth %s class %s wild inst",
-                 sender->string, subs->dest.classname->string);
-          continue;
-        }
-      }
-    }
+#if 0
+  zdbug((LOG_DEBUG, "realm_subs"));
+#endif
 
-    /* okay to subscribe.  save for return trip */
-    text[found*NUM_FIELDS + 2] = subs->dest.classname->string;
-    text[found*NUM_FIELDS + 3] = subs->dest.inst->string;
-    text[found*NUM_FIELDS + 4] = "";
-    found++;
+  if (!realm->remsubs)
+    return ZERR_NONE;
 
-    retval = triplet_register(realm->client, &subs->dest, realm);
+  for (subs=realm->remsubs; subs; subs = next) {
+    next = subs->next;
 #ifdef DEBUG
-    zdbug ((LOG_DEBUG, "ck_frn_subs: %s/%s/%s", subs->dest.classname->string,
+    zdbug ((LOG_DEBUG, "realm_subs: %s/%s/%s", subs->dest.classname->string,
             subs->dest.inst->string, subs->dest.recip->string));
 #endif
 
-    if (retval != ZERR_NONE) {
-      if (retval == ZSRV_CLASSXISTS) {
-        continue;
-      } else {
-        free_subscriptions(subs->next);
-        free(text);
-        return retval;
+    num = 0;
+    if ((retval = ZMakeAscii(port, sizeof(port), (unsigned char *) 
+                            &num, sizeof(u_short))) != ZERR_NONE) 
+      {
+       syslog(LOG_ERR, "subscr_rlm_sendit make ascii: %s",
+              error_message(retval));
+       return(ZERR_NONE);
       }
-    }
-    LIST_INSERT(&realm->subs, subs);
-  }
-  /* don't send confirmation if we're not the initial server contacted */
-  if (!(server_which_server(who) || found == 0)) {
-    snotice = *notice;
-    snotice.z_opcode = REALM_ADD_SUBSCRIBE;
+
+    text[0] = "0.0.0.0";
+    text[1] = port;
+    text[2] = subs->dest.classname->string;
+    text[3] = subs->dest.inst->string;
+    text[4] = subs->dest.recip->string;
+
+    /* format snotice */
     snotice.z_class_inst = ZEPHYR_CTL_REALM;
-    snotice.z_port = srv_addr.sin_port;
-    if ((retval = ZFormatNoticeList(&snotice, text, found * NUM_FIELDS + 2, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) {
-      syslog(LOG_WARNING, "subscr_ck_forn_subs format: %s",
-             error_message(retval));
-      free(text);
-      return(ZERR_NONE);      
-    }
+    snotice.z_opcode = REALM_REQ_SUBSCRIBE;
+    snotice.z_port = 0;
+    snotice.z_class = ZEPHYR_CTL_CLASS;
+
+    snotice.z_recipient = "";
+    snotice.z_kind = ACKED;
+    snotice.z_num_other_fields = 0;
+    snotice.z_default_format = "";
+    /* Evil. In the event this is ACL'd, pick a user who is subscribed and
+       resubmit them as the sender. */
+    clientp = triplet_lookup(&subs->dest);
+    if (!clientp)
+      snotice.z_sender = "";
+    else
+      snotice.z_sender = (*clientp)->principal->string;
+    snotice.z_default_format = "";
+
+    if ((retval = ZFormatNoticeList(&snotice, text, NUM_FIELDS + 2,
+                                   &pack, &packlen, ZNOAUTH)) != ZERR_NONE) 
+      {
+       syslog(LOG_WARNING, "subscr_rlm_subs format: %s",
+              error_message(retval));
+       return(ZERR_NONE);
+      }
+  
     if ((retval = ZParseNotice(pack, packlen, &snotice)) != ZERR_NONE) {
-      syslog(LOG_WARNING, "subscr_ck_forn_subs parse: %s",
-             error_message(retval));
-      free(text);
+      syslog(LOG_WARNING, "subscr_rlm_subs parse: %s",
+            error_message(retval));
       free(pack);
       return(ZERR_NONE);
     }
-    realm_handoff(&snotice, 1, who, realm, 0);
+    realm_handoff(&snotice, 1, NULL, realm, 0);
     free(pack);
   }
-  free(text);
+
   return ZERR_NONE;
 }
 
-Code_t subscr_foreign_user(notice, who, realm)
+/* Called from subscr_foreign_user for REALM_REQ_SUBSCRIBE */
+static Code_t
+subscr_check_foreign_subs(notice, who, server, realm, newsubs)
+    ZNotice_t *notice;
+    struct sockaddr_in *who;
+    Server *server;
+    Realm *realm;
+    Destlist *newsubs;
+{
+    Destlist *subs, *subs2, *next;
+    Acl *acl;
+    char **text;
+    int found = 0;
+    ZNotice_t snotice;
+    char *pack, *cp;
+    int packlen;
+    Code_t retval;
+    String *sender;
+
+    for (subs = newsubs; subs; subs = subs->next)
+       found++;
+
+    if (found == 0)
+       return(ZERR_NONE);
+  
+    sender = make_string(notice->z_sender, 0);
+    
+    if ((text = (char **)malloc((found * NUM_FIELDS + 2) * sizeof(char *))) 
+       == (char **) 0) {
+       syslog(LOG_ERR, "subscr_ck_forn_subs no mem(text)");
+       free_string(sender);
+       return(ENOMEM);
+    }
+
+    /* grab the client information from the incoming message */
+    cp = notice->z_message;
+    text[0] = cp;
+
+    I_ADVANCE(2);
+    text[1] = cp;
+
+    I_ADVANCE(3);
+
+    found = 0;
+    for (subs = newsubs; subs; subs = next) {
+       next=subs->next;
+       acl = class_get_acl(subs->dest.classname);
+       if (acl) {
+           Realm *rlm;
+           rlm = realm_which_realm(who); 
+           if (rlm && server == me_server) { 
+               if (!realm_sender_in_realm(rlm->name, sender->string)) { 
+                   syslog(LOG_WARNING, "subscr auth not verifiable %s (%s) class %s",
+                          sender->string, rlm->name, 
+                          subs->dest.classname->string);
+                   continue; 
+               } 
+           } 
+           if (!access_check(sender->string, acl, SUBSCRIBE)) {
+               syslog(LOG_WARNING, "subscr unauth %s class %s",
+                      sender->string, subs->dest.classname->string);
+               continue; /* the for loop */
+           }
+           if (wildcard_instance == subs->dest.inst) {
+               if (!access_check(sender->string, acl, INSTWILD)) {
+                   syslog(LOG_WARNING,
+                          "subscr unauth %s class %s wild inst",
+                          sender->string, subs->dest.classname->string);
+                   continue;
+               }
+           }
+       }
+
+       /* okay to subscribe.  save for return trip */
+       text[found*NUM_FIELDS + 2] = subs->dest.classname->string;
+       text[found*NUM_FIELDS + 3] = subs->dest.inst->string;
+       text[found*NUM_FIELDS + 4] = "";
+       found++;
+       
+       retval = triplet_register(realm->client, &subs->dest, realm);
+#ifdef DEBUG
+       zdbug ((LOG_DEBUG, "ck_frn_subs: %s/%s/%s", subs->dest.classname->string,
+               subs->dest.inst->string, subs->dest.recip->string));
+#endif
+
+       if (retval != ZERR_NONE) {
+           if (retval == ZSRV_CLASSXISTS) {
+               continue;
+           } else {
+               free_subscriptions(newsubs); /* subs->next XXX */
+               free_string(sender);
+               free(text);
+               return retval;
+           }
+       }
+       LIST_INSERT(&realm->subs, subs);
+    }
+    /* don't send confirmation if we're not the initial server contacted */
+    if (!(server_which_server(who) || found == 0)) {
+       snotice = *notice;
+       snotice.z_opcode = REALM_ADD_SUBSCRIBE;
+       snotice.z_class_inst = ZEPHYR_CTL_REALM;
+       snotice.z_port = srv_addr.sin_port;
+       if ((retval = ZFormatNoticeList(&snotice, text, found * NUM_FIELDS + 2, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) {
+           syslog(LOG_WARNING, "subscr_ck_forn_subs format: %s",
+                  error_message(retval));
+           free_string(sender);
+           free(text);
+           return(ZERR_NONE);      
+       }
+       if ((retval = ZParseNotice(pack, packlen, &snotice)) != ZERR_NONE) {
+           syslog(LOG_WARNING, "subscr_ck_forn_subs parse: %s",
+                  error_message(retval));
+           free_string(sender);
+           free(text);
+           free(pack);
+           return(ZERR_NONE);
+       }
+       realm_handoff(&snotice, 1, who, realm, 0);
+       free(pack);
+    }
+    free_string(sender);
+    free(text);
+    return ZERR_NONE;
+}
+
+/* Called from realm_control_dispatch for REALM_REQ/ADD_SUBSCRIBE */
+Code_t subscr_foreign_user(notice, who, server, realm)
     ZNotice_t *notice;
     struct sockaddr_in *who;
+    Server *server;
     Realm *realm;
 {
   Destlist *newsubs, *temp;
@@ -1462,14 +1559,14 @@ Code_t subscr_foreign_user(notice, who, realm)
   Client *client;
   ZNotice_t snotice;
   struct sockaddr_in newwho;
-  char *cp;
+  char *cp, *tp0, *tp1;
   char rlm_recipient[REALM_SZ + 1];
   
 #if 0
   zdbug((LOG_DEBUG, "subscr_foreign_user"));
 #endif
   
-  cp = notice->z_message;
+  tp0 = cp = notice->z_message;
   
   newwho.sin_addr.s_addr = inet_addr(cp);
   if (newwho.sin_addr.s_addr == -1) {
@@ -1478,6 +1575,7 @@ Code_t subscr_foreign_user(notice, who, realm)
   }
 
   I_ADVANCE(0);
+  tp1 = cp;
   
   snotice = *notice;
   
@@ -1503,6 +1601,13 @@ Code_t subscr_foreign_user(notice, who, realm)
   if (!strcmp(snotice.z_opcode, REALM_ADD_SUBSCRIBE)) {
     /* this was approved by the other realm, add subscriptions */
     
+    if (!strcmp(tp0, "0.0.0.0")) {
+      /* skip bogus ADD reply from subscr_realm_subs */
+      zdbug((LOG_DEBUG, "subscr_foreign_user ADD skipped"));
+      return(ZERR_NONE);
+    }
+
+    zdbug((LOG_DEBUG, "subscr_foreign_user ADD %s/%s", tp0, tp1));
     client = client_find(&newwho.sin_addr, snotice.z_port);
     if (client == (Client *)0) {
       syslog(LOG_WARNING, "no client at %s/%d",
@@ -1522,7 +1627,8 @@ Code_t subscr_foreign_user(notice, who, realm)
     
     status = subscr_add_raw(client, (Realm *)0, newsubs);
   } else if (!strcmp(snotice.z_opcode, REALM_REQ_SUBSCRIBE)) {
-    status = subscr_check_foreign_subs(notice, who, realm, newsubs);
+    zdbug((LOG_DEBUG, "subscr_foreign_user REQ %s/%s", tp0, tp1));
+    status = subscr_check_foreign_subs(notice, who, server, realm, newsubs);
   } else {
     syslog(LOG_ERR, "bogus opcode %s in subscr_forn_user",
            snotice.z_opcode);
index a319b228958ce4f258c087e0f3b9d88d2c7ca849..4b587cfbae9a855b97ca123325f5a8caafb85ef4 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     Created by:     John T. Kohl
  *
- *     $Id: uloc.c,v 1.59 2000/01/22 18:36:02 ghudson Exp $
+ *     $Id: uloc.c,v 1.60 2001/02/27 04:59:03 zacheiss Exp $
  *
  *     Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
  *     For copying and distribution information, see the file
@@ -17,7 +17,7 @@
 #ifndef lint
 #ifndef SABER
 static const char rcsid_uloc_c[] =
-"$Id: uloc.c,v 1.59 2000/01/22 18:36:02 ghudson Exp $";
+"$Id: uloc.c,v 1.60 2001/02/27 04:59:03 zacheiss Exp $";
 #endif /* SABER */
 #endif /* lint */
 
@@ -869,7 +869,7 @@ ulogin_marshal_locs(notice, found, auth)
     char **answer;
     int i = 0;
     String *inst;
-    int local = (auth && sender_in_realm(notice));
+    int local = (auth && realm_sender_in_realm(ZGetRealm(), notice->z_sender));
 
     *found = 0;                        /* # of matches */
 
index 985b06d51e2164ed053160397da79fac1d796f10..0a7cf44f1e2c0f50f6ee4caf21f6c42723d16601 100644 (file)
@@ -5,7 +5,9 @@
  *
  *     Created by:     John T. Kohl
  *
- *     $Id: zserver.h,v 1.51 1999/01/22 23:19:53 ghudson Exp $
+ *     $Source: /afs/dev.mit.edu/source/repository/athena/lib/zephyr/server/zserver.h,v $
+ *     $Author: zacheiss $
+ *     $Zephyr: /mit/zephyr/src/server/RCS/zserver.h,v 1.34 91/03/08 12:53:24 raeburn Exp $
  *
  *     Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
  *     For copying and distribution information, see the file
@@ -67,6 +69,7 @@ typedef struct _Destination Destination;
 typedef struct _Destlist Destlist;
 typedef struct _Realm Realm;
 typedef struct _Realmname Realmname;
+typedef enum _Realm_state Realm_state;
 typedef struct _Client Client;
 typedef struct _Triplet Triplet;
 typedef enum _Server_state Server_state;
@@ -87,14 +90,24 @@ struct _Destlist {
     struct _Destlist   *next, **prev_p;
 };
 
+enum _Realm_state {
+    REALM_UP,                          /* Realm is up */
+    REALM_TARDY,                       /* Realm due for a hello XXX */
+    REALM_DEAD,                                /* Realm is considered dead */
+    REALM_STARTING                     /* Realm is between dead and up */
+};
+
 struct _Realm {
     char name[REALM_SZ];
     int count;
     struct sockaddr_in *addrs;
     int idx;                           /* which server we are connected to */
-    Destlist *subs;
-    Client *client;
-    long tkt_try;
+    Destlist *subs;                     /* what their clients sub to */
+    Destlist *remsubs;                  /* our subs on their end */
+    Client *client;                     
+    int child_pid;
+    int have_tkt;
+    Realm_state state;
 };
 
 struct _Realmname {
@@ -284,8 +297,9 @@ Code_t server_adispatch __P((ZNotice_t *notice, int auth,
                             struct sockaddr_in *who, Server *server));
 
 /* found in subscr.c */
+Code_t subscr_foreign_user __P((ZNotice_t *, struct sockaddr_in *, Server *, Realm *));
 Code_t subscr_cancel __P((struct sockaddr_in *sin, ZNotice_t *notice));
-Code_t subscr_subscribe __P((Client *who, ZNotice_t *notice));
+Code_t subscr_subscribe __P((Client *who, ZNotice_t *notice, Server *server));
 Code_t subscr_send_subs __P((Client *client));
 void subscr_cancel_client __P((Client *client));
 void subscr_sendlist __P((ZNotice_t *notice, int auth,
@@ -305,8 +319,11 @@ Code_t ulocate_dispatch __P((ZNotice_t *notice, int auth,
 Code_t uloc_send_locations __P((void));
 
 /* found in realm.c */
+int realm_sender_in_realm __P((char *realm, char *sender));
+int realm_bound_for_realm __P((char *realm, char *recip));
 Realm *realm_which_realm __P((struct sockaddr_in *who));
 Realm *realm_get_realm_by_name __P((char *name));
+Realm *realm_get_realm_by_pid __P((int));
 void realm_handoff(ZNotice_t *, int, struct sockaddr_in *, Realm *, int);
 char *realm_expand_realm(char *);
 void realm_init __P((void));
@@ -314,6 +331,8 @@ Code_t ZCheckRealmAuthentication __P((ZNotice_t *, struct sockaddr_in *,
                                      char *));
 Code_t realm_control_dispatch __P((ZNotice_t *, int, struct sockaddr_in *,
                                   Server *, Realm *));
+void realm_shutdown __P((void));
+void realm_deathgram __P((Server *));
 
 /* found in version.c */
 char *get_version __P((void));
@@ -368,6 +387,9 @@ extern int nservers;                        /* number of other servers*/
 extern String *empty;
 extern String *wildcard_instance;
 
+extern Realm *otherrealms;
+extern int nrealms;
+
 extern struct in_addr my_addr; /* my inet address */
 
 #define class_is_control(classname) (classname == class_control)
@@ -389,6 +411,7 @@ extern struct in_addr my_addr;      /* my inet address */
 #define ADMIN_NEWREALM "NEXT_REALM"    /* Opcode: this is a new realm */
 #define REALM_REQ_LOCATE "REQ_LOCATE"  /* Opcode: request a location */
 #define REALM_ANS_LOCATE "ANS_LOCATE"  /* Opcode: answer to location */
+#define REALM_BOOT      "SENDSUBS"     /* Opcode: first server in realm */
 
 /* me_server_idx is the index into otherservers of this server descriptor. */
 /* the 'limbo' server is always the first server */
index d957073c8a845f0ea0e264d54d8e159ae16856b2..a53badaa21a52d8e3d6f53b516477772c1f76fa3 100644 (file)
@@ -3,7 +3,7 @@
  *
  *      Created by:     David C. Jedlinsky
  *
- *      $Id: zhm.c,v 1.61 2000/04/05 14:57:36 ghudson Exp $
+ *      $Id: zhm.c,v 1.62 2000/05/19 23:19:21 zacheiss Exp $
  *
  *      Copyright (c) 1987,1991 by the Massachusetts Institute of Technology.
  *      For copying and distribution information, see the file
@@ -12,7 +12,7 @@
 
 #include "zhm.h"
 
-static const char rcsid_hm_c[] = "$Id: zhm.c,v 1.61 2000/04/05 14:57:36 ghudson Exp $";
+static const char rcsid_hm_c[] = "$Id: zhm.c,v 1.62 2000/05/19 23:19:21 zacheiss Exp $";
 
 #ifdef HAVE_HESIOD
 int use_hesiod = 0;
@@ -107,7 +107,8 @@ char *argv[];
            break;
        }
     if (errflg) {
-       fprintf(stderr, "Usage: %s [-d] [-h] [-r] [-n] [server]\n", argv[0]);
+       fprintf(stderr, "Usage: %s [-d] [-h] [-r] [-n] [-f] [server]\n", 
+               argv[0]);       
        exit(2);
     }
 
index a09b581bd31311eca2498d4879c4c6a73088f8e7..6fc72a36826c945453440480951541547e11f73d 100644 (file)
@@ -5,7 +5,7 @@
  *
  *      Created by:     David C. Jedlinsky
  *
- *      $Id: zhm.h,v 1.22 1999/01/22 23:20:03 ghudson Exp $
+ *      $Id: zhm.h,v 1.23 2000/05/08 16:00:06 ghudson Exp $
  *      $Zephyr: /mit/zephyr/src.rw/zhm/RCS/zhm.h,v 1.13 90/10/19 07:11:48 raeburn Exp $
  *
  *      Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology.
@@ -44,7 +44,6 @@
 
 #define ever (;;)
 
-#define SERV_TIMEOUT 5
 #define BOOTING 1
 #define NOTICES 2
 
index 81dea0ef2b31204526a58b13619737b49885fc42..cd460c89ce85d9b361a21217f9e9927c8183d17f 100644 (file)
@@ -3,7 +3,7 @@
  *
  *      Created by:     David C. Jedlinsky
  *
- *      $Id: zhm_server.c,v 1.17 1999/10/14 18:37:35 ghudson Exp $
+ *      $Id: zhm_server.c,v 1.18 2000/05/08 16:00:08 ghudson Exp $
  *
  *      Copyright (c) 1987 by the Massachusetts Institute of Technology.
  *      For copying and distribution information, see the file
 
 #ifndef lint
 #ifndef SABER
-static char rcsid_hm_server_c[] = "$Id: zhm_server.c,v 1.17 1999/10/14 18:37:35 ghudson Exp $";
+static char rcsid_hm_server_c[] = "$Id: zhm_server.c,v 1.18 2000/05/08 16:00:08 ghudson Exp $";
 #endif /* SABER */
 #endif /* lint */
 
 static void boot_timeout __P((void *));
+static int get_serv_timeout __P((void));
 
 static Timer *boot_timer = NULL;
+static int serv_rexmit_times[] = { 5, 10, 20, 40 };
+static int serv_timeouts = 0;
 
 int serv_loop = 0;
 extern u_short cli_port;
@@ -64,7 +67,7 @@ char *op;
          Zperr(ret);
          com_err("hm", ret, "sending startup notice");
      }
-     boot_timer = timer_set_rel(SERV_TIMEOUT, boot_timeout, NULL);
+     boot_timer = timer_set_rel(get_serv_timeout(), boot_timeout, NULL);
 }
 
 /* Argument is whether we are detaching or really going down */
@@ -182,6 +185,7 @@ ZNotice_t *notice;
     } else {
        /* This is our server, handle the notice */
        booting = 0;
+       serv_timeouts = 0;
        if (boot_timer) {
            timer_reset(boot_timer);
            boot_timer = NULL;
@@ -305,6 +309,17 @@ char *sugg_serv;
 static void boot_timeout(arg)
 void *arg;
 {
+    serv_timeouts++;
     new_server(NULL);
 }
 
+static int get_serv_timeout(void)
+{
+    int ind, ntimeouts;
+
+    ind = (numserv == 0) ? serv_timeouts : serv_timeouts / numserv;
+    ntimeouts = sizeof(serv_rexmit_times) / sizeof(*serv_rexmit_times);
+    if (ind >= ntimeouts)
+       ind = ntimeouts - 1;
+    return serv_rexmit_times[ind];
+}
index f0d34f9fe5e1c83dc81c4953b008ec78c27efa3d..e3c5ed81410d6b4da7c1efc389549cfb7afa14c7 100644 (file)
@@ -4,7 +4,7 @@
  *
  *      Created by:     Marc Horowitz <marc@athena.mit.edu>
  *
- *      $Id: main.c,v 1.36 1999/01/22 23:20:22 ghudson Exp $
+ *      $Id: main.c,v 1.38 2000/12/30 12:02:50 ghudson Exp $
  *
  *      Copyright (c) 1989 by the Massachusetts Institute of Technology.
  *      For copying and distribution information, see the file
@@ -17,7 +17,7 @@
 #endif
 
 #if (!defined(lint) && !defined(SABER))
-static const char rcsid_main_c[] = "$Id: main.c,v 1.36 1999/01/22 23:20:22 ghudson Exp $";
+static const char rcsid_main_c[] = "$Id: main.c,v 1.38 2000/12/30 12:02:50 ghudson Exp $";
 #endif
 
 #include <netdb.h>
index 52067a3c94db1f3460557b5a5d92fd833b0b3d00..f988a329641ed77c029a04ac7ae48a63445f53b8 100644 (file)
@@ -4,7 +4,7 @@
  *
  *      Created by:     Marc Horowitz <marc@athena.mit.edu>
  *
- *      $Id: zephyr.c,v 1.10 1999/08/13 00:19:52 danw Exp $
+ *      $Id: zephyr.c,v 1.12 2000/10/13 23:07:31 ghudson Exp $
  *
  *      Copyright (c) 1989 by the Massachusetts Institute of Technology.
  *      For copying and distribution information, see the file
@@ -14,7 +14,7 @@
 #include <sysdep.h>
 
 #if (!defined(lint) && !defined(SABER))
-static const char rcsid_zephyr_c[] = "$Id: zephyr.c,v 1.10 1999/08/13 00:19:52 danw Exp $";
+static const char rcsid_zephyr_c[] = "$Id: zephyr.c,v 1.12 2000/10/13 23:07:31 ghudson Exp $";
 #endif
 
 #include <zephyr/mit-copyright.h>
@@ -165,7 +165,7 @@ void zephyr_init(notice_handler)
            exposure = EXPOSE_NONE;
        }
     } else
-      exposure = EXPOSE_NONE;
+      exposure = EXPOSE_OPSTAFF;
     error_code = ZSetLocation(exposure); /* <<<>>> */
     if (error_code != ZERR_LOGINFAIL)
       TRAP( error_code, "while setting location" );
@@ -218,12 +218,12 @@ void finalize_zephyr() /* <<<>>> */
         */
 #ifdef DEBUG
        if (zwgc_debug) {
-           TRAP( ZCancelSubscriptions(0), "while canceling subscriptions" );
            TRAP( ZUnsetLocation(), "while unsetting location" );
+           TRAP( ZCancelSubscriptions(0), "while canceling subscriptions" );
        } else {
 #endif /* DEBUG */
-           (void) ZCancelSubscriptions(0);
            (void) ZUnsetLocation();
+           (void) ZCancelSubscriptions(0);
 #ifdef DEBUG
        }
 #endif /* DEBUG */
index b5dd5b5069db8cc6d1ffcef4ffa82ca8d3234d32..bc8f121f3fd956510e8c25a673f04e5a0f99237d 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: zwgc.1,v 1.23 1999/01/22 23:20:50 ghudson Exp $
+.\"    $Id: zwgc.1,v 1.24 2000/08/10 15:10:52 ghudson Exp $
 '      # end of TP (cf }N below)
 '      # copied here, since we use @ in some of our tags, and that
 '      # messes up \w and \h
@@ -1001,9 +1001,9 @@ Other control messages may be implemented in the future.
 
 .SH EXAMPLES
 For an example of a description file, see
-.IR /usr/athena/lib/zephyr/zwgc.desc .
+.IR /usr/athena/share/zephyr/zwgc.desc .
 For an example of X resources, see
-.IR /usr/athena/lib/zephyr/zwgc_resources .
+.IR /usr/athena/share/zephyr/zwgc_resources .
 
 .SH BUGS
 The X selection code can highlight the wrong portions of messages
@@ -1022,10 +1022,10 @@ which case you must get new tickets and then run ``zctl load
 $HOME/.zwgc.desc
 Default location of user's description file
 .TQ
-/usr/athena/lib/zephyr/zwgc.desc
+/usr/athena/share/zephyr/zwgc.desc
 System-wide description file
 .TQ
-/usr/athena/lib/zephyr/zwgc_resources
+/usr/athena/share/zephyr/zwgc_resources
 Default X application resources.
 .TQ
 $HOME/.zephyr.vars
index 74a0dc83e86a0a53223cd20ed6effa8d7deaecee..06b4f44763623fa22b948879ce65886b3cd13677 100644 (file)
@@ -3,7 +3,7 @@
 #      For copying and distribution information, see the file
 #      "mit-copyright.h".
 # 
-#      $Id: zwgc.desc,v 1.15 1999/01/22 23:20:51 ghudson Exp $
+#      $Id: zwgc.desc,v 1.16 2000/07/14 14:04:23 ghudson Exp $
 #
 #
 # Default WindowGram description file
@@ -41,109 +41,95 @@ if (upcase($opcode) == "PING") then exit endif
 # 'match "forged" to something other than "UNAUTHENTIC".
 case $auth
 match "yes"
-       set aval = "Authentic"
+  set aval = "Authentic"
 match "no","forged"
-       set aval = "@b(@large(UNAUTHENTIC))"
+  set aval = "@b(@large(UNAUTHENTIC))"
 endcase
 
 case $class
 match "WG_CTL_CLASS"
-       exit
-#  
-# MAIL NOTIFICATION
-#
-# To receive mail notifications, you need to do several things:
-# 1) subscribe to MAIL,POP messages.  You do this by typing:
-#      zctl add mail pop
-# to your prompt.  By doing this, you will get a simple notice every
-# time you are logged in and more mail arrives for you at your post office.
-#
-# 2) If you wish to be notified of the sender, recipient and subject of the
-# new mail, remove the pound-signs from the beginning of the 10 lines below
-# between 'match "MAIL"' and 'exit', inclusive, and type the command
-#      zctl add mail popret
-# to your prompt.
-#
-# Note: The use of the following lines is NOT necessary to receive
-# notifications of new mail.  The only effect of uncommenting these
-# lines is to display on your screen the sender, recipient and subject
-# of the mail (In addition, uncommenting these lines will add extra load
-# to the post office servers, making them run slower.).
-# If you do not wish this information to be displayed where other users
-# might possibly read it, or you wish to avoid loading down the post
-# office servers, you need not uncomment these lines.  Just follow step
-# 1 above. 
-#
-#match "MAIL"
-#      case $instance
-#      match "pop"
-#              exec "zmailnotify"
-#              exit
-#      endcase
-#      print "(Authentication: @bold("+$aval+"))\n"
-#      print substitute($default)
-#      put
-#      exit
+  exit
 match "message"
-       if (downcase($recipient) == downcase($user)) then
-               case $instance
-               match "PERSONAL"
-                       set type = "Personal"
-               match "URGENT"
-                       set type = "Urgent"
-               default
-                       set type = $instance
-               endcase
-       else
-               set type = "Instance "+$instance
-       endif
+  if (downcase($recipient) == downcase($user)) then
+    case $instance
+    match "PERSONAL"
+      set type = "Personal"
+    match "URGENT"
+      set type = "Urgent"
+    default
+      set type = $instance
+    endcase
+  else
+    set type = "Instance "+$instance
+  endif
 
-       fields signature body
-       if ($body == "") then
-               set body = $signature
-               set signature = ""
-       endif
-       if ($signature =~ "^[Ff]rom: .*") then
-               set dummy = lany($signature,"From: ")
-       endif
-       if ($signature =~ "\n$") then
-               set dummy = rany($signature,"\n")
-       endif
-       if ($signature == "") then
-               set ftext = "From: @bold("+protect($sender)+")"
-       else
-               set ftext = "From: @bold(@{"+protect($signature)+"} <"+
-                       protect($sender)+">)"
-       endif
+  fields signature body
+  if ($body == "") then
+    set body = $signature
+    set signature = ""
+  endif
+  if ($signature =~ "^[Ff]rom: .*") then
+    set dummy = lany($signature,"From: ")
+  endif
+  if ($signature =~ "\n$") then
+    set dummy = rany($signature,"\n")
+  endif
+  if ($signature == "") then
+    set ftext = "From: @bold("+protect($sender)+")"
+  else
+    set ftext = "From: @bold(@{"+protect($signature)+"} <"+
+      protect($sender)+">)"
+  endif
 
-       print "@center(@bold("+$aval+") "+$type+" message at "+$time+
-               " on "+$date+"\n"+$ftext+" on "+$fromhost+"\nTo: "+
-               $recipient+")\n\n"
-       print $body
-       put
-       exit
+  print "@center(@bold("+$aval+") "+$type+" message at "+$time+
+    " on "+$date+"\n"+$ftext+" on "+$fromhost+"\nTo: "+
+    $recipient+")\n\n"
+  print $body
+  put
+  exit
 
 match "login"
-       case $opcode
-       match "USER_LOGIN"
-               set log = "logged in"
-       match "USER_LOGOUT"
-               set log = "logged out"
-       default
-               set log = "unknown opcode"
-       endcase
+  case $opcode 
+  match "USER_LOGIN"
+    set log = "logged in"
+  match "USER_LOGOUT"
+    set log = "logged out"
+  default
+    set log = "unknown opcode"
+  endcase
 
-       fields host when tty
-       print "@center(@bold("+$sender+") "+$log+")\n"
-       print "@center(on @bold("+$host+") on "+$tty+")\n"
-       print "@center(at "+$when+")"
-       put
-       exit
+  fields host when tty
+  print "@center(@bold("+$sender+") "+$log+")\n"
+  print "@center(on @bold("+$host+") on "+$tty+")\n"
+  print "@center(at "+$when+")"
+  put
+  exit
 
 default
-       print "(Authentication: @bold("+$aval+") from host: "+$fromhost+")\n"
-       print substitute($default)
-       put
-       exit
+  if (downcase($class) == "filsys" and downcase($opcode) == "shutdown") then
+    set format = "From $sender:\n@bold(Shutdown message from $1 at $time)\n"+
+      "@center(System going down, message is:)\n\n$2\n\n@center(@bold($3))"
+  elseif (downcase($class) == "filsys") then
+    set format = "@bold(Filesystem Operation Message for $instance:)\n"+
+      "From: @bold($sender) at $time $date\n$message"
+  elseif (downcase($class) == "mail" and downcase($instance) == "popret") then
+    set format = "You have new mail:\n\nFrom: $1\nTo: $2\nSubject: $3"
+  elseif (downcase($class) == "mail") then
+    set format = "From Post Office $1:\n$2"
+  elseif (downcase($class) == "syslog") then
+    set format = "From $sender:\nSyslog message from $instance, level "+
+      "$opcode:\n$message"
+  elseif ($number_of_fields == "1") then
+    set format = "Class $class, Instance $instance:\nTo: @bold($recipient) "+
+      "at $time $date\nFrom: @bold($sender)\n\n$message"
+  else
+    set format = "Class $class, Instance $instance:\nTo: @bold($recipient) "+
+      "at $time $date\nFrom: @bold($1) <$sender>\n\n$2"
+  endif
+
+  print "(Authentication: @bold("+$aval+") from host: "+$fromhost+")\n"
+  print substitute($format)
+  put
+  exit
 
 endcase