diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/main.c | 2 | ||||
-rw-r--r-- | server/realm.c | 190 | ||||
-rw-r--r-- | server/server.c | 1 | ||||
-rw-r--r-- | server/zserver.h | 3 |
4 files changed, 107 insertions, 89 deletions
diff --git a/server/main.c b/server/main.c index 8e326d9..0186b17 100644 --- a/server/main.c +++ b/server/main.c @@ -258,8 +258,6 @@ main(int argc, gettimeofday(&t_local, NULL); uptime = NOW; - realm_wakeup(); - for (;;) { if (doreset) do_reset(); diff --git a/server/realm.c b/server/realm.c index 4f42455..085c0ce 100644 --- a/server/realm.c +++ b/server/realm.c @@ -45,9 +45,6 @@ int n_realm_slots = 0; /* size of malloc'd otherrealms */ * 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, * ZRealm *realm) @@ -61,6 +58,7 @@ int n_realm_slots = 0; /* size of malloc'd otherrealms */ * do a database dump of foreign realm info * */ +static int realm_next_idx_by_idx(ZRealm *realm, int idx); static void realm_sendit(ZNotice_t *notice, struct sockaddr_in *who, int auth, ZRealm *realm, int ack_to_sender); #ifdef HAVE_KRB5 static Code_t realm_sendit_auth(ZNotice_t *notice, struct sockaddr_in *who, int auth, ZRealm *realm, int ack_to_sender); @@ -82,6 +80,66 @@ is_usable(ZRealm_server *srvr) return !srvr->deleted && srvr->got_addr; } +static int +is_sendable(ZRealm_server *srvr) +{ + return !srvr->deleted && srvr->got_addr && !srvr->dontsend; +} + +static void +rlm_wakeup_cb(void *arg) +{ + ZRealm *realm = arg; + 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; + +#ifdef HAVE_KRB5 + if (!ticket_lookup(realm->name)) + if ((retval = ticket_retrieve(realm)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_wakeup failed: %s", + error_message(retval)); + return; + } +#endif + + 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 void rlm_set_server_address(ZRealm_server *srvr, struct hostent *hp) { @@ -90,6 +148,17 @@ rlm_set_server_address(ZRealm_server *srvr, struct hostent *hp) srvr->addr.sin_port = srv_addr.sin_port; srvr->addr.sin_family = AF_INET; srvr->got_addr = 1; + if (is_sendable(srvr) && srvr->realm->state == REALM_NEW) { + srvr->realm->idx = realm_next_idx_by_idx(srvr->realm, srvr->realm->idx); + srvr->realm->state = REALM_TARDY; + /* + * Set a timer to send a wakeup to this realm. We do this rather + * than just sending the notice now because, if we are not using + * C-ARES, then we might be called during server startup before + * the server is prepared to send notices. + */ + timer_set_rel(0, rlm_wakeup_cb, srvr->realm); + } } #ifdef HAVE_ARES @@ -192,9 +261,7 @@ realm_next_idx_by_idx(ZRealm *realm, int idx) /* loop through the servers */ for (b = idx; b < realm->count; b++) { srvr = realm->srvrs[b]; - if (!is_usable(srvr)) - continue; - if (!srvr->dontsend) + if (is_sendable(srvr)) return(b); } @@ -202,9 +269,7 @@ realm_next_idx_by_idx(ZRealm *realm, int idx) if (idx != 0) for (b = 0; b < idx; b++) { srvr = realm->srvrs[b]; - if (!is_usable(srvr)) - continue; - if (!srvr->dontsend) + if (is_sendable(srvr)) return(b); } @@ -599,7 +664,7 @@ realm_init(void) Client *client; ZRealmname *rlmnames; ZRealm *rlm; - int ii, jj, kk, nrlmnames; + int ii, jj, kk, nrlmnames, nsendable; char realm_list_file[128]; char rlmprinc[MAX_PRINCIPAL_SIZE]; @@ -629,6 +694,7 @@ realm_init(void) /* ii: entry in rlmnames */ for (ii = 0; ii < nrlmnames; ii++) { + nsendable = 0; rlm = realm_get_realm_by_name_string(rlmnames[ii].name); if (rlm) { /* jj: server entry in otherrealms */ @@ -642,6 +708,7 @@ realm_init(void) rlm->srvrs[jj]->dontsend = rlmnames[ii].servers[kk].dontsend; rlm->srvrs[jj]->deleted = 0; rlm_lookup_server_address(rlm->srvrs[jj]); + if (is_sendable(rlm->srvrs[jj])) nsendable++; /* mark realm.list server entry used */ rlmnames[ii].servers[kk].deleted = 1; @@ -669,13 +736,19 @@ realm_init(void) abort(); } *(rlm->srvrs[rlm->count]) = rlmnames[ii].servers[kk]; + rlm->srvrs[rlm->count]->realm = rlm; rlm_lookup_server_address(rlm->srvrs[rlm->count]); + if (is_sendable(rlm->srvrs[rlm->count])) nsendable++; rlm->count++; } /* The current server might have been deleted or marked dontsend. Advance to one we can use, if necessary. */ - rlm->idx = (rlm->count) ? - realm_next_idx_by_idx(rlm, rlm->idx) : 0; + if (nsendable) { + rlm->idx = realm_next_idx_by_idx(rlm, rlm->idx); + } else { + rlm->idx = 0; + rlm->state = REALM_NEW; + } free(rlmnames[ii].servers); continue; } @@ -702,6 +775,7 @@ realm_init(void) rlm->namestr = rlmnames[ii].name; rlm->name = rlm->namestr->string; + rlm->state = REALM_NEW; /* convert names to addresses */ rlm->count = rlmnames[ii].nused; @@ -712,7 +786,9 @@ realm_init(void) } for (jj = 0; jj < rlm->count; jj++) { rlm->srvrs[jj] = &rlmnames[ii].servers[jj]; + rlm->srvrs[jj]->realm = rlm; rlm_lookup_server_address(rlm->srvrs[jj]); + if (is_sendable(rlm->srvrs[jj])) nsendable++; } client = (Client *) malloc(sizeof(Client)); @@ -740,13 +816,11 @@ realm_init(void) client->addr.sin_addr.s_addr = 0; rlm->client = client; - rlm->idx = (rlm->count) ? + rlm->idx = (nsendable) ? realm_next_idx_by_idx(rlm, (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); @@ -813,74 +887,6 @@ realm_deathgram(Server *server) } } -void -realm_wakeup(void) -{ - int jj, found = 0; - ZRealm *realm; - - 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 (jj = 0; jj < nrealms; jj++) { - ZNotice_t snotice; - char *pack; - char rlm_recipient[REALM_SZ + 1]; - int packlen, retval; - - realm = otherrealms[jj]; - 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; - -#ifdef HAVE_KRB5 - if (!ticket_lookup(realm->name)) - if ((retval = ticket_retrieve(realm)) != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_wakeup failed: %s", - error_message(retval)); - continue; - } -#endif - - 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 realm_ulocate_dispatch(ZNotice_t *notice, int auth, @@ -961,7 +967,7 @@ realm_control_dispatch(ZNotice_t *notice, } else if (!strcmp(opcode, REALM_BOOT)) { zdbug((LOG_DEBUG, "got a REALM_BOOT from %s", inet_ntoa(server->addr.sin_addr))); - realm->state = REALM_STARTING; + if (realm->state != REALM_UP) realm->state = REALM_STARTING; realm_set_server(who, realm); #ifdef REALM_MGMT /* resend subscriptions but only if this was to us */ @@ -1046,7 +1052,7 @@ realm_set_server(struct sockaddr_in *sin, idx = realm_get_idx_by_addr(realm, sin); /* Not exactly */ - if (!is_usable(realm->srvrs[idx]) || realm->srvrs[idx]->dontsend != 0) + if (!is_sendable(realm->srvrs[idx])) return ZSRV_NORLM; realm->idx = idx; @@ -1101,6 +1107,12 @@ realm_sendit(ZNotice_t *notice, Code_t retval; Unacked *nacked; + if (realm->count == 0 || realm->state == REALM_NEW) { + /* XXX we should have a queue or something */ + syslog(LOG_WARNING, "rlm_sendit no servers for %s", realm->name); + return; + } + notice->z_auth = auth; notice->z_authent_len = 0; notice->z_ascii_authent = ""; @@ -1181,7 +1193,7 @@ rlm_rexmit(void *arg) zdbug((LOG_DEBUG, "rlm_rexmit: sending to %s:%d (%d)", realm->name, realm->idx, nackpacket->rexmits)); - if (realm->count == 0) + if (realm->count == 0 || realm->state == REALM_NEW) return; /* Check to see if we've retransmitted as many times as we can */ @@ -1314,6 +1326,12 @@ realm_sendit_auth(ZNotice_t *notice, char multi[64]; ZNotice_t partnotice, newnotice; + if (realm->count == 0 || realm->state == REALM_NEW) { + /* XXX we should have a queue or something */ + syslog(LOG_WARNING, "rlm_sendit_auth no servers for %s", realm->name); + return ZERR_INTERNAL; + } + offset = 0; buffer = (char *)malloc(sizeof(ZPacket_t)); diff --git a/server/server.c b/server/server.c index 934c700..1603775 100644 --- a/server/server.c +++ b/server/server.c @@ -399,6 +399,7 @@ srv_states[] = { }; static char * rlm_states[] = { + "REALM_NEW", "REALM_UP", "REALM_TARDY", "REALM_DEAD", diff --git a/server/zserver.h b/server/zserver.h index 7862cea..b1b4bc8 100644 --- a/server/zserver.h +++ b/server/zserver.h @@ -68,6 +68,7 @@ typedef struct { #endif enum _ZRealm_state { + REALM_NEW, /* New realm; no servers yet */ REALM_UP, /* ZRealm is up */ REALM_TARDY, /* ZRealm due for a hello XXX */ REALM_DEAD, /* ZRealm is considered dead */ @@ -117,6 +118,7 @@ struct _Destlist { struct _ZRealm_server { String *name; /* server's hostname */ struct sockaddr_in addr; /* server's address */ + ZRealm *realm; /* realm this server belongs to */ Timer *timer; /* timer for name lookup */ unsigned int dontsend :1; /* private server, do not send */ unsigned int got_addr :1; /* IP address is valid */ @@ -406,7 +408,6 @@ void realm_shutdown(void); void realm_deathgram(Server *); Code_t realm_send_realms(void); Code_t realm_dispatch(ZNotice_t *, int, struct sockaddr_in *, Server *); -void realm_wakeup(void); void kill_realm_pids(void); void realm_dump_realms(FILE *); |