X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/blobdiff_plain/de014da64011b21929158b746803d69cbfb05ee6..060ca767db058036f7ade27219de9ebaf1d4737b:/admin.c diff --git a/admin.c b/admin.c index 92ea0a64..987de7ab 100644 --- a/admin.c +++ b/admin.c @@ -77,6 +77,8 @@ static void a_destroy(admin */*a*/); static void a_lock(admin */*a*/); static void a_unlock(admin */*a*/); +#define BOOL(x) ((x) ? "t" : "nil") + /*----- Output functions --------------------------------------------------*/ /* --- @trywrite@ --- * @@ -512,6 +514,9 @@ static long a_parsetime(const char *p) /*----- Backgrounded operations -------------------------------------------*/ +#define BGTAG(bg) \ + (((admin_bgop *)(bg))->tag ? ((admin_bgop *)(bg))->tag : "") + /* --- @a_bgrelease@ --- * * * Arguments: @admin_bgop *bg@ = backgrounded operation @@ -526,19 +531,15 @@ static void a_bgrelease(admin_bgop *bg) { admin *a = bg->a; - if (bg->tag) - xfree(bg->tag); - else - selbuf_enable(&a->b); - if (bg->next) - bg->next->prev = bg->prev; - if (bg->prev) - bg->prev->next = bg->next; - else - a->bg = bg->next; + T( trace(T_ADMIN, "admin: release bgop %s", BGTAG(bg)); ) + if (bg->tag) xfree(bg->tag); + else selbuf_enable(&a->b); + if (bg->next) bg->next->prev = bg->prev; + if (bg->prev) bg->prev->next = bg->next; + else a->bg = bg->next; xfree(bg); - if (a->f & AF_CLOSE) - a_destroy(a); + if (a->f & AF_CLOSE) a_destroy(a); + a_unlock(a); } /* --- @a_bgok@, @a_bginfo@, @a_bgfail@ --- * @@ -596,7 +597,10 @@ static void a_bgadd(admin *a, admin_bgop *bg, const char *tag, bg->cancel = cancel; bg->next = a->bg; bg->prev = 0; + if (a->bg) a->bg->prev = bg; a->bg = bg; + a_lock(a); + T( trace(T_ADMIN, "admin: add bgop %s", BGTAG(bg)); ) if (tag) a_write(a, "DETACH", tag, 0); } @@ -613,6 +617,7 @@ static void a_bgadd(admin *a, admin_bgop *bg, const char *tag, static void a_addfree(admin_addop *add) { + T( trace(T_ADMIN, "admin: free add op %s", BGTAG(add)); ) if (add->peer.name) xfree(add->peer.name); if (add->paddr) xfree(add->paddr); } @@ -630,6 +635,7 @@ static void a_addcancel(admin_bgop *bg) { admin_addop *add = (admin_addop *)bg; + T( trace(T_ADMIN, "admin: cancel add op %s", BGTAG(add)); ) sel_rmtimer(&add->t); bres_abort(&add->r); a_addfree(add); @@ -668,8 +674,7 @@ static void a_addresolve(struct hostent *h, void *v) { admin_addop *add = v; - a_lock(add->bg.a); - T( trace(T_ADMIN, "admin: %u resolved", add->bg.a->seq); ) + T( trace(T_ADMIN, "admin: add op %s resolved", BGTAG(add)); ) TIMER; if (!h) a_bgfail(&add->bg, "resolve-error %s", add->paddr); @@ -680,7 +685,6 @@ static void a_addresolve(struct hostent *h, void *v) sel_rmtimer(&add->t); a_addfree(add); a_bgrelease(&add->bg); - a_unlock(add->bg.a); } /* --- @a_addtimer@ --- * @@ -697,13 +701,11 @@ static void a_addtimer(struct timeval *tv, void *v) { admin_addop *add = v; - a_lock(add->bg.a); - T( trace(T_ADMIN, "admin: %u resolver timeout", add->bg.a->seq); ) + T( trace(T_ADMIN, "admin: add op %s timeout", BGTAG(add)); ) a_bgfail(&add->bg, "resolver-timeout %s\n", add->paddr); bres_abort(&add->r); a_addfree(add); a_bgrelease(&add->bg); - a_unlock(add->bg.a); } /* --- @acmd_add@ --- * @@ -810,10 +812,13 @@ static void acmd_add(admin *a, unsigned ac, char *av[]) */ a_bgadd(a, &add->bg, tag, a_addcancel); + T( trace(T_ADMIN, "admin: %u, add op %s resolving hostname `%s'", + a->seq, BGTAG(add), add->paddr); ) /* --- If the name is numeric, do it the easy way --- */ if (inet_aton(av[i], &add->peer.sa.sin.sin_addr)) { + T( trace(T_ADMIN, "admin: add op %s done the easy way", BGTAG(add)); ) a_doadd(add); a_addfree(add); a_bgrelease(&add->bg); @@ -826,8 +831,6 @@ static void acmd_add(admin *a, unsigned ac, char *av[]) tv.tv_sec += T_RESOLVE; sel_addtimer(&sel, &add->t, &tv, a_addtimer, add); bres_byname(&add->r, add->paddr, a_addresolve, add); - T( trace(T_ADMIN, "admin: %u resolving hostname `%s'", - a->seq, add->paddr); ) return; bad_syntax: @@ -854,6 +857,7 @@ fail: static void a_pingcancel(admin_bgop *bg) { admin_pingop *pg = (admin_pingop *)bg; + T( trace(T_ADMIN, "admin: cancel ping op %s", BGTAG(pg)); ) p_pingdone(&pg->ping, PING_NONOTIFY); } @@ -873,7 +877,6 @@ static void a_pong(int rc, void *v) struct timeval tv; double millis; - a_lock(pg->bg.a); switch (rc) { case PING_OK: gettimeofday(&tv, 0); @@ -893,8 +896,8 @@ static void a_pong(int rc, void *v) default: abort(); } + T( trace(T_ADMIN, "admin: ponged ping op %s", BGTAG(pg)); ) a_bgrelease(&pg->bg); - a_unlock(pg->bg.a); } /* --- @acmd_ping@, @acmd_eping@ --- * @@ -946,6 +949,8 @@ static void a_ping(admin *a, unsigned ac, char *av[], pg = xmalloc(sizeof(*pg)); gettimeofday(&pg->pingtime, 0); a_bgadd(a, &pg->bg, tag, a_pingcancel); + T( trace(T_ADMIN, "admin: ping op %s: %s to %s", + BGTAG(pg), cmd, p_name(p)); ) if (p_pingsend(p, &pg->ping, msg, t, a_pong, pg)) { a_bgfail(&pg->bg, "ping-send-failed"); a_bgrelease(&pg->bg); @@ -987,10 +992,9 @@ static int traceish(admin *a, unsigned ac, char *av[], if (!ac || strcmp(av[0], "?") == 0) { const trace_opt *t; - a_info(a, "Current %s status:", what); for (t = tt; t->ch; t++) { - a_info(a, "%c %c %s", - t->ch, (*ff & t->f) == t->f ? '*' : ' ', t->help); + a_info(a, "%c%c %s", + t->ch, (*ff & t->f) == t->f ? '+' : ' ', t->help); } } else { unsigned sense = 1; @@ -1136,32 +1140,57 @@ static void acmd_addr(admin *a, unsigned ac, char *av[]) } } +static void acmd_peerinfo(admin *a, unsigned ac, char *av[]) +{ + peer *p; + const peerspec *ps; + + if ((p = p_find(av[0])) == 0) { + a_fail(a, "unknown-peer %s", av[0]); + return; + } + + ps = p_spec(p); + a_info(a, "tunnel=%s", ps->tops->name); + a_info(a, "keepalive=%lu", ps->t_ka); + a_ok(a); +} + +static void acmd_servinfo(admin *a, unsigned ac, char *av[]) +{ + a_info(a, "implementation=edgeware-tripe"); + a_info(a, "version=%s", VERSION); + a_info(a, "daemon=%s", BOOL(flags & F_DAEMON)); + a_ok(a); +} + static void acmd_stats(admin *a, unsigned ac, char *av[]) { peer *p; stats *st; - if ((p = p_find(av[0])) == 0) + if ((p = p_find(av[0])) == 0) { a_fail(a, "unknown-peer %s", av[0]); - else { - st = p_stats(p); - a_info(a, "start-time=%s", timestr(st->t_start)); - a_info(a, "last-packet-time=%s", timestr(st->t_last)); - a_info(a, "last-keyexch-time=%s", timestr(st->t_kx)); - a_info(a, "packets-in=%lu bytes-in=%lu", st->n_in, st->sz_in); - a_info(a, "packets-out=%lu bytes-out=%lu", - st->n_out, st->sz_out); - a_info(a, "keyexch-packets-in=%lu keyexch-bytes-in=%lu", - st->n_kxin, st->sz_kxin); - a_info(a, "keyexch-packets-out=%lu keyexch-bytes-out=%lu", - st->n_kxout, st->sz_kxout); - a_info(a, "ip-packets-in=%lu ip-bytes-in=%lu", - st->n_ipin, st->sz_ipin); - a_info(a, "ip-packets-out=%lu ip-bytes-out=%lu", - st->n_ipout, st->sz_ipout); - a_info(a, "rejected-packets=%lu", st->n_reject); - a_ok(a); + return; } + + st = p_stats(p); + a_info(a, "start-time=%s", timestr(st->t_start)); + a_info(a, "last-packet-time=%s", timestr(st->t_last)); + a_info(a, "last-keyexch-time=%s", timestr(st->t_kx)); + a_info(a, "packets-in=%lu bytes-in=%lu", st->n_in, st->sz_in); + a_info(a, "packets-out=%lu bytes-out=%lu", + st->n_out, st->sz_out); + a_info(a, "keyexch-packets-in=%lu keyexch-bytes-in=%lu", + st->n_kxin, st->sz_kxin); + a_info(a, "keyexch-packets-out=%lu keyexch-bytes-out=%lu", + st->n_kxout, st->sz_kxout); + a_info(a, "ip-packets-in=%lu ip-bytes-in=%lu", + st->n_ipin, st->sz_ipin); + a_info(a, "ip-packets-out=%lu ip-bytes-out=%lu", + st->n_ipout, st->sz_ipout); + a_info(a, "rejected-packets=%lu", st->n_reject); + a_ok(a); } static void acmd_kill(admin *a, unsigned ac, char *av[]) @@ -1234,10 +1263,12 @@ static const acmd acmdtab[] = { { "kill", "kill PEER", 1, 1, acmd_kill }, { "list", "list", 0, 0, acmd_list }, { "notify", "notify MESSAGE ...", 1, 0xffff, acmd_notify }, + { "peerinfo", "peerinfo PEER", 1, 1, acmd_peerinfo }, { "ping", "ping [OPTIONS] PEER", 1, 0xffff, acmd_ping }, { "port", "port", 0, 0, acmd_port }, { "quit", "quit", 0, 0, acmd_quit }, { "reload", "reload", 0, 0, acmd_reload }, + { "servinfo", "servinfo", 0, 0, acmd_servinfo }, { "stats", "stats PEER", 1, 1, acmd_stats }, #ifndef NTRACE { "trace", "trace [OPTIONS]", 0, 1, acmd_trace }, @@ -1269,32 +1300,20 @@ static void acmd_help(admin *a, unsigned ac, char *av[]) * immediately. */ -static void a_lock(admin *a) { assert(!(a->f & AF_LOCK)); a->f |= AF_LOCK; } +static void a_lock(admin *a) { a->ref++; } -/* --- @a_unlock@ --- * +/* --- @a_dodestroy@ --- * * * Arguments: @admin *a@ = pointer to an admin block * * Returns: --- * - * Use: Unlocks an admin block, allowing its destruction. This is - * also the second half of @a_destroy@. + * Use: Actually does the legwork of destroying an admin block. */ -static void a_unlock(admin *a) +static void a_dodestroy(admin *a) { admin_bgop *bg, *bbg; - - assert(a->f & AF_LOCK); - - /* --- If we're not dead, that's fine --- */ - - if (!(a->f & AF_DEAD)) { - a->f &= ~AF_LOCK; - return; - } - - /* --- If we are, then destroy the rest of the block --- */ T( trace(T_ADMIN, "admin: completing destruction of connection %u", a->seq); ) @@ -1320,6 +1339,23 @@ static void a_unlock(admin *a) DESTROY(a); } +/* --- @a_unlock@ --- * + * + * Arguments: @admin *a@ = pointer to an admin block + * + * Returns: --- + * + * Use: Unlocks an admin block, allowing its destruction. This is + * also the second half of @a_destroy@. + */ + +static void a_unlock(admin *a) +{ + assert(a->ref); + if (!--a->ref && (a->f & AF_DEAD)) + a_dodestroy(a); +} + /* --- @a_destroy@ --- * * * Arguments: @admin *a@ = pointer to an admin block @@ -1361,12 +1397,10 @@ static void a_destroy(admin *a) /* --- If the block is locked, that's all we can manage --- */ - if (a->f & AF_LOCK) { - T( trace(T_ADMIN, "admin: deferring destruction..."); ) - return; - } - a->f |= AF_LOCK; - a_unlock(a); + if (!a->ref) + a_dodestroy(a); + T( else + trace(T_ADMIN, "admin: deferring destruction..."); ) } /* --- @a_line@ --- *