summaryrefslogtreecommitdiffstats
path: root/crypto/heimdal/lib/kadm5/ipropd_master.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/heimdal/lib/kadm5/ipropd_master.c')
-rw-r--r--crypto/heimdal/lib/kadm5/ipropd_master.c209
1 files changed, 170 insertions, 39 deletions
diff --git a/crypto/heimdal/lib/kadm5/ipropd_master.c b/crypto/heimdal/lib/kadm5/ipropd_master.c
index 9c87d6e..626e853 100644
--- a/crypto/heimdal/lib/kadm5/ipropd_master.c
+++ b/crypto/heimdal/lib/kadm5/ipropd_master.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -32,8 +32,9 @@
*/
#include "iprop.h"
+#include <rtbl.h>
-RCSID("$Id: ipropd_master.c,v 1.24 2001/09/03 05:54:18 assar Exp $");
+RCSID("$Id: ipropd_master.c,v 1.28 2002/08/16 18:27:53 joda Exp $");
static krb5_log_facility *log_facility;
@@ -83,6 +84,9 @@ struct slave {
char *name;
krb5_auth_context ac;
u_int32_t version;
+ time_t seen;
+ unsigned long flags;
+#define SLAVE_F_DEAD 0x1
struct slave *next;
};
@@ -111,6 +115,39 @@ check_acl (krb5_context context, const char *name)
}
static void
+slave_seen(slave *s)
+{
+ s->seen = time(NULL);
+}
+
+static void
+slave_dead(slave *s)
+{
+ s->flags |= SLAVE_F_DEAD;
+ slave_seen(s);
+}
+
+static void
+remove_slave (krb5_context context, slave *s, slave **root)
+{
+ slave **p;
+
+ if (s->fd >= 0)
+ close (s->fd);
+ if (s->name)
+ free (s->name);
+ if (s->ac)
+ krb5_auth_con_free (context, s->ac);
+
+ for (p = root; *p; p = &(*p)->next)
+ if (*p == s) {
+ *p = s->next;
+ break;
+ }
+ free (s);
+}
+
+static void
add_slave (krb5_context context, krb5_keytab keytab, slave **root, int fd)
{
krb5_principal server;
@@ -159,38 +196,36 @@ add_slave (krb5_context context, krb5_keytab keytab, slave **root, int fd)
goto error;
}
krb5_free_ticket (context, ticket);
+ ticket = NULL;
+
+ {
+ slave *l = *root;
+
+ while (l) {
+ if (strcmp(l->name, s->name) == 0)
+ break;
+ l = l->next;
+ }
+ if (l) {
+ if (l->flags & SLAVE_F_DEAD) {
+ remove_slave(context, l, root);
+ } else {
+ krb5_warnx (context, "second connection from %s", s->name);
+ goto error;
+ }
+ }
+ }
+
krb5_warnx (context, "connection from %s", s->name);
s->version = 0;
+ s->flags = 0;
+ slave_seen(s);
s->next = *root;
*root = s;
return;
error:
- if (s->name)
- free (s->name);
- if (s->ac)
- krb5_auth_con_free(context, s->ac);
- if (ticket)
- krb5_free_ticket (context, ticket);
- close (s->fd);
- free(s);
-}
-
-static void
-remove_slave (krb5_context context, slave *s, slave **root)
-{
- slave **p;
-
- close (s->fd);
- free (s->name);
- krb5_auth_con_free (context, s->ac);
-
- for (p = root; *p; p = &(*p)->next)
- if (*p == s) {
- *p = s->next;
- break;
- }
- free (s);
+ remove_slave(context, s, root);
}
struct prop_context {
@@ -244,21 +279,33 @@ send_complete (krb5_context context, slave *s,
ret = krb5_write_priv_message(context, s->ac, &s->fd, &data);
- if (ret)
- krb5_err (context, 1, ret, "krb5_write_priv_message");
+ if (ret) {
+ krb5_warn (context, ret, "krb5_write_priv_message");
+ slave_dead(s);
+ return ret;
+ }
ret = hdb_foreach (context, db, 0, prop_one, s);
- if (ret)
- krb5_err (context, 1, ret, "hdb_foreach");
+ if (ret) {
+ krb5_warn (context, ret, "hdb_foreach");
+ slave_dead(s);
+ return ret;
+ }
_krb5_put_int (buf, NOW_YOU_HAVE, 4);
_krb5_put_int (buf + 4, current_version, 4);
data.length = 8;
+ s->version = current_version;
+
ret = krb5_write_priv_message(context, s->ac, &s->fd, &data);
+ if (ret) {
+ slave_dead(s);
+ krb5_warn (context, ret, "krb5_write_priv_message");
+ return ret;
+ }
- if (ret)
- krb5_err (context, 1, ret, "krb5_write_priv_message");
+ slave_seen(s);
return 0;
}
@@ -279,12 +326,15 @@ send_diffs (krb5_context context, slave *s, int log_fd,
if (s->version == current_version)
return 0;
+ if (s->flags & SLAVE_F_DEAD)
+ return 0;
+
sp = kadm5_log_goto_end (log_fd);
- right = sp->seek(sp, 0, SEEK_CUR);
+ right = krb5_storage_seek(sp, 0, SEEK_CUR);
for (;;) {
if (kadm5_log_previous (sp, &ver, &timestamp, &op, &len))
abort ();
- left = sp->seek(sp, -16, SEEK_CUR);
+ left = krb5_storage_seek(sp, -16, SEEK_CUR);
if (ver == s->version)
return 0;
if (ver == s->version + 1)
@@ -293,17 +343,21 @@ send_diffs (krb5_context context, slave *s, int log_fd,
return send_complete (context, s, database, current_version);
}
krb5_data_alloc (&data, right - left + 4);
- sp->fetch (sp, (char *)data.data + 4, data.length - 4);
+ krb5_storage_read (sp, (char *)data.data + 4, data.length - 4);
krb5_storage_free(sp);
_krb5_put_int(data.data, FOR_YOU, 4);
ret = krb5_write_priv_message(context, s->ac, &s->fd, &data);
+ krb5_data_free(&data);
if (ret) {
krb5_warn (context, ret, "krb5_write_priv_message");
+ slave_dead(s);
return 1;
}
+ slave_seen(s);
+
return 0;
}
@@ -337,9 +391,86 @@ process_msg (krb5_context context, slave *s, int log_fd,
}
krb5_data_free (&out);
+
+ slave_seen(s);
+
return ret;
}
+#define SLAVE_NAME "Name"
+#define SLAVE_ADDRESS "Address"
+#define SLAVE_VERSION "Version"
+#define SLAVE_STATUS "Status"
+#define SLAVE_SEEN "Last Seen"
+
+static void
+write_stats(krb5_context context, slave *slaves, u_int32_t current_version)
+{
+ char str[30];
+ rtbl_t tbl;
+ time_t t = time(NULL);
+ FILE *fp;
+
+ fp = fopen(KADM5_SLAVE_STATS, "w");
+ if (fp == NULL)
+ return;
+
+ strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S",
+ localtime(&t));
+ fprintf(fp, "Status for slaves, last updated: %s\n\n", str);
+
+ fprintf(fp, "Master version: %lu\n\n", (unsigned long)current_version);
+
+ tbl = rtbl_create();
+ if (tbl == NULL) {
+ fclose(fp);
+ return;
+ }
+
+ rtbl_add_column(tbl, SLAVE_NAME, 0);
+ rtbl_add_column(tbl, SLAVE_ADDRESS, 0);
+ rtbl_add_column(tbl, SLAVE_VERSION, RTBL_ALIGN_RIGHT);
+ rtbl_add_column(tbl, SLAVE_STATUS, 0);
+ rtbl_add_column(tbl, SLAVE_SEEN, 0);
+
+ rtbl_set_prefix(tbl, " ");
+ rtbl_set_column_prefix(tbl, SLAVE_NAME, "");
+
+ while (slaves) {
+ krb5_address addr;
+ krb5_error_code ret;
+ rtbl_add_column_entry(tbl, SLAVE_NAME, slaves->name);
+ ret = krb5_sockaddr2address (context,
+ (struct sockaddr*)&slaves->addr, &addr);
+ if(ret == 0) {
+ krb5_print_address(&addr, str, sizeof(str), NULL);
+ krb5_free_address(context, &addr);
+ rtbl_add_column_entry(tbl, SLAVE_ADDRESS, str);
+ } else
+ rtbl_add_column_entry(tbl, SLAVE_ADDRESS, "<unknown>");
+
+ snprintf(str, sizeof(str), "%u", (unsigned)slaves->version);
+ rtbl_add_column_entry(tbl, SLAVE_VERSION, str);
+
+ if (slaves->flags & SLAVE_F_DEAD)
+ rtbl_add_column_entry(tbl, SLAVE_STATUS, "Down");
+ else
+ rtbl_add_column_entry(tbl, SLAVE_STATUS, "Up");
+
+ strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S",
+ localtime(&slaves->seen));
+ rtbl_add_column_entry(tbl, SLAVE_SEEN, str);
+
+ slaves = slaves->next;
+ }
+
+ rtbl_format(tbl, fp);
+ rtbl_destroy(tbl);
+
+ fclose(fp);
+}
+
+
static char *realm;
static int version_flag;
static int help_flag;
@@ -473,18 +604,18 @@ main(int argc, char **argv)
send_diffs (context, p, log_fd, database, current_version);
}
- for(p = slaves; p != NULL; p = p->next)
+ for(p = slaves; ret && p != NULL; p = p->next)
if (FD_ISSET(p->fd, &readset)) {
--ret;
if(process_msg (context, p, log_fd, database, current_version))
- remove_slave (context, p, &slaves);
+ slave_dead(p);
}
if (ret && FD_ISSET(listen_fd, &readset)) {
add_slave (context, keytab, &slaves, listen_fd);
--ret;
}
-
+ write_stats(context, slaves, current_version);
}
return 0;
OpenPOWER on IntegriCloud