summaryrefslogtreecommitdiff
path: root/server/realm.c
diff options
context:
space:
mode:
authorGravatar Garry Zacheiss <zacheiss@mit.edu>2001-02-26 23:51:07 +0000
committerGravatar Garry Zacheiss <zacheiss@mit.edu>2001-02-26 23:51:07 +0000
commit36e4a4c6c86a75051f0602987810c68265fb79a4 (patch)
treef0ec140cc77bd19bacfd92debe2f3eb766638381 /server/realm.c
parentefc5e21f47f24b78fb31285fe9a75eecb1f6b354 (diff)
Changes from CMU:
* Replace entire file, resyncing interrealm code between us and CMU.
Diffstat (limited to 'server/realm.c')
-rw-r--r--server/realm.c1983
1 files changed, 1190 insertions, 793 deletions
diff --git a/server/realm.c b/server/realm.c
index a77df82..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,164 +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]);
+
+ for (nrealms = 0; *rlmnames[nrealms].name; nrealms++);
+
+ otherrealms = (Realm *)malloc(nrealms * sizeof(Realm));
+ if (!otherrealms) {
+ syslog(LOG_CRIT, "malloc failed in realm_init");
+ abort();
}
- /* If we found no servers, die here so we don't divide by zero later */
- if (found != 0)
- rlm->count = found;
- else {
- syslog(LOG_CRIT, "Found no servers for realm %s", rlm->name);
- 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 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));
+#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;
+
+ 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);
+}
- rlm->addrs = (struct sockaddr_in *)malloc(found * sizeof (struct sockaddr_in));
- if (!rlm->addrs) {
- syslog(LOG_CRIT, "malloc failed in get_realm_addrs");
- abort();
+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);
}
- 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];
+}
+
+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++;
}
- client = (Client *) malloc(sizeof(Client));
- if (!client) {
- syslog(LOG_CRIT, "malloc failed in get_realm_addrs");
- abort();
+
+ 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);
+ }
}
- memset(&client->addr, 0, sizeof(struct sockaddr_in));
-#ifdef HAVE_KRB4
- 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;
-
- rlm->client = client;
- rlm->idx = random() % rlm->count;
- rlm->subs = NULL;
- rlm->tkt_try = 0;
- free(rlmnames[ii].servers);
- free(addresses);
- }
- free(rlmnames);
}
static Code_t
@@ -484,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);
}
@@ -518,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
@@ -571,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 */
}
@@ -600,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)
@@ -745,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 */