summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Karl Ramm <kcr@mit.edu>2001-06-20 06:48:38 +0000
committerGravatar Karl Ramm <kcr@mit.edu>2001-06-20 06:48:38 +0000
commit5c7254c327f37f65b5835017e8d3a83cfee3817d (patch)
tree2bd1618239b4d2123481f6dd26f0b1c0da3ff191
parentd6f33c71a13c998b61ca3cd6d07e47d1a151ada9 (diff)
This commit was generated by cvs2svn to compensate for changes in r81,
which included commits to RCS files with non-trunk default branches.
-rw-r--r--clients/zaway/zaway.110
-rw-r--r--clients/zaway/zaway.c5
-rw-r--r--clients/zctl/zctl.113
-rw-r--r--clients/znol/znol.c5
-rw-r--r--server/bdump.c57
-rw-r--r--server/class.c4
-rw-r--r--server/dispatch.c248
-rw-r--r--server/kstuff.c29
-rw-r--r--server/main.c47
-rw-r--r--server/realm.c1980
-rw-r--r--server/server.c30
-rw-r--r--server/subscr.c560
-rw-r--r--server/uloc.c2
-rw-r--r--server/zserver.h33
-rw-r--r--zhm/zhm.h1
-rw-r--r--zhm/zhm_server.c17
-rw-r--r--zwgc/zephyr.c6
-rw-r--r--zwgc/zwgc.18
-rw-r--r--zwgc/zwgc.desc168
19 files changed, 2007 insertions, 1216 deletions
diff --git a/clients/zaway/zaway.1 b/clients/zaway/zaway.1
index 0f46f96..85d0bce 100644
--- a/clients/zaway/zaway.1
+++ b/clients/zaway/zaway.1
@@ -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
diff --git a/clients/zaway/zaway.c b/clients/zaway/zaway.c
index 8186f61..332598f 100644
--- a/clients/zaway/zaway.c
+++ b/clients/zaway/zaway.c
@@ -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;
}
diff --git a/clients/zctl/zctl.1 b/clients/zctl/zctl.1
index 0817363..73d4fd5 100644
--- a/clients/zctl/zctl.1
+++ b/clients/zctl/zctl.1
@@ -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 \ ... ]
diff --git a/clients/znol/znol.c b/clients/znol/znol.c
index 804f63f..53fd47c 100644
--- a/clients/znol/znol.c
+++ b/clients/znol/znol.c
@@ -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)?
diff --git a/server/bdump.c b/server/bdump.c
index 2de58e4..80f7e72 100644
--- a/server/bdump.c
+++ b/server/bdump.c
@@ -3,7 +3,9 @@
*
* Created by: John T. Kohl
*
+ * $Source$
* $Id$
+ * $Author$
*
* Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
@@ -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;
diff --git a/server/class.c b/server/class.c
index 63a4a2f..6ccacae 100644
--- a/server/class.c
+++ b/server/class.c
@@ -3,7 +3,8 @@
*
* Created by: John T. Kohl
*
- * $Id$
+ * $Source$
+ * $Author$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
@@ -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;
}
diff --git a/server/dispatch.c b/server/dispatch.c
index 12f9c04..493fcd4 100644
--- a/server/dispatch.c
+++ b/server/dispatch.c
@@ -3,7 +3,8 @@
*
* Created by: John T. Kohl
*
- * $Id$
+ * $Source$
+ * $Author$
*
* Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
@@ -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;
diff --git a/server/kstuff.c b/server/kstuff.c
index 04396fa..ca9f055 100644
--- a/server/kstuff.c
+++ b/server/kstuff.c
@@ -8,7 +8,8 @@
* "mit-copyright.h".
*/
/*
- * $Id$
+ * $Source$
+ * $Header$
*/
#include "zserver.h"
@@ -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
diff --git a/server/main.c b/server/main.c
index bd3e138..37b8efb 100644
--- a/server/main.c
+++ b/server/main.c
@@ -3,7 +3,8 @@
*
* Created by: John T. Kohl
*
- * $Id$
+ * $Source$
+ * $Author$
*
* Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
@@ -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
diff --git a/server/realm.c b/server/realm.c
index 1ad55fc..37b0df9 100644
--- a/server/realm.c
+++ b/server/realm.c
@@ -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 */
diff --git a/server/server.c b/server/server.c
index e9c5894..377d397 100644
--- a/server/server.c
+++ b/server/server.c
@@ -3,7 +3,8 @@
*
* Created by: John T. Kohl
*
- * $Id$
+ * $Source$
+ * $Author$
*
* Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
@@ -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;
diff --git a/server/subscr.c b/server/subscr.c
index abf28ca..eb3ba27 100644
--- a/server/subscr.c
+++ b/server/subscr.c
@@ -3,7 +3,8 @@
*
* Created by: John T. Kohl
*
- * $Id$
+ * $Source$
+ * $Author$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
@@ -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);
diff --git a/server/uloc.c b/server/uloc.c
index 4ab909a..0d7ea8e 100644
--- a/server/uloc.c
+++ b/server/uloc.c
@@ -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 */
diff --git a/server/zserver.h b/server/zserver.h
index c0b889a..dc84cf5 100644
--- a/server/zserver.h
+++ b/server/zserver.h
@@ -5,7 +5,9 @@
*
* Created by: John T. Kohl
*
- * $Id$
+ * $Source$
+ * $Author$
+ * $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 */
diff --git a/zhm/zhm.h b/zhm/zhm.h
index 733d9cc..3d6f153 100644
--- a/zhm/zhm.h
+++ b/zhm/zhm.h
@@ -44,7 +44,6 @@
#define ever (;;)
-#define SERV_TIMEOUT 5
#define BOOTING 1
#define NOTICES 2
diff --git a/zhm/zhm_server.c b/zhm/zhm_server.c
index 4630955..50fa04f 100644
--- a/zhm/zhm_server.c
+++ b/zhm/zhm_server.c
@@ -19,8 +19,11 @@ static char rcsid_hm_server_c[] = "$Id$";
#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];
+}
diff --git a/zwgc/zephyr.c b/zwgc/zephyr.c
index c5a3855..c3276e5 100644
--- a/zwgc/zephyr.c
+++ b/zwgc/zephyr.c
@@ -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 */
diff --git a/zwgc/zwgc.1 b/zwgc/zwgc.1
index f646bec..879b240 100644
--- a/zwgc/zwgc.1
+++ b/zwgc/zwgc.1
@@ -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
diff --git a/zwgc/zwgc.desc b/zwgc/zwgc.desc
index 71dfc1e..90a5666 100644
--- a/zwgc/zwgc.desc
+++ b/zwgc/zwgc.desc
@@ -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