+static void peerkeys_maybe_incorporate(struct site *st, const char *file,
+ const char *whatmore,
+ int logcl_enoent)
+{
+ struct peer_keyset *atsuffix=
+ keyset_load(file,&st->scratch,st->log,logcl_enoent,st->defhash);
+ if (!atsuffix) return;
+
+ if (st->peerkeys_current &&
+ serial_cmp(atsuffix->serial,st->peerkeys_current->serial) <= 0) {
+ slog(st,LOG_SIGKEYS,"keys from %s%s are older, discarding",
+ file,whatmore);
+ keyset_dispose(&atsuffix);
+ int r=unlink(file);
+ if (r) slog(st,LOG_ERROR,"failed to remove old key update %s: %s\n",
+ st->peerkeys_tmpl.buffer,strerror(errno));
+ return;
+ } else {
+ slog(st,LOG_SIGKEYS,"keys from %s%s are newer, installing",
+ file,whatmore);
+ keyset_dispose(&st->peerkeys_current);
+ st->peerkeys_current=atsuffix;
+ int r=rename(file,st->peerkeys_path);
+ if (r) slog(st,LOG_ERROR,"failed to install key update %s as %s: %s\n",
+ st->peerkeys_tmpl.buffer,st->peerkeys_path,
+ strerror(errno));
+ }
+}
+
+static void peerkeys_check_for_update(struct site *st)
+{
+ if (!st->peerkeys_path) return;
+
+ pathprefix_template_setsuffix(&st->peerkeys_tmpl,"~proc");
+ peerkeys_maybe_incorporate(st,st->peerkeys_tmpl.buffer,
+ " (found old update)",
+ M_DEBUG);
+
+ pathprefix_template_setsuffix(&st->peerkeys_tmpl,"~update");
+ const char *inputp=st->peerkeys_tmpl.buffer;
+ if (access(inputp,R_OK)) {
+ if (errno!=ENOENT)
+ slog(st,LOG_ERROR,"cannot access peer key update file %s\n",
+ inputp);
+ return;
+ }
+
+ buffer_init(&st->scratch,0);
+ BUF_ADD_BYTES(append,&st->scratch,
+ st->peerkeys_tmpl.buffer,
+ strlen(st->peerkeys_tmpl.buffer)+1);
+ inputp=st->scratch.start;
+
+ pathprefix_template_setsuffix(&st->peerkeys_tmpl,"~proc");
+ const char *oursp=st->peerkeys_tmpl.buffer;
+
+ int r=rename(inputp,oursp);
+ if (r) {
+ slog(st,LOG_ERROR,"failed to claim key update file %s as %s: %s",
+ inputp,oursp,strerror(errno));
+ return;
+ }
+
+ peerkeys_maybe_incorporate(st,oursp," (update)",M_ERR);
+}
+
+
+static bool_t kex_init(struct site *st)