/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
#include "feature/control/fmt_serverstatus.h"
#include "app/config/config.h"
#include "feature/dirauth/voteflags.h"// XXXX remove
#include "feature/nodelist/nodelist.h"
#include "feature/relay/router.h"
#include "feature/nodelist/node_st.h"
#include "feature/nodelist/routerinfo_st.h"
/**
* Allocate and return a description of the status of the server desc,
* for use in a v1-style router-status line. The server is listed
* as running iff is_live is true.
*
* This is deprecated: it's only used for controllers that want outputs in
* the old format.
*/
static char *
list_single_server_status(const routerinfo_t *desc, int is_live)
{
char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
char *cp;
const node_t *node;
tor_assert(desc);
cp = buf;
if (!is_live) {
*cp++ = '!';
}
node = node_get_by_id(desc->cache_info.identity_digest);
if (node && node->is_valid) {
strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf));
cp += strlen(cp);
*cp++ = '=';
}
*cp++ = '$';
base16_encode(cp, HEX_DIGEST_LEN+1, desc->cache_info.identity_digest,
DIGEST_LEN);
return tor_strdup(buf);
}
/** Based on the routerinfo_ts in routers, allocate the
* contents of a v1-style router-status line, and store it in
* *router_status_out. Return 0 on success, -1 on failure.
*
* If for_controller is true, include the routers with very old descriptors.
*
* This is deprecated: it's only used for controllers that want outputs in
* the old format.
*/
int
list_server_status_v1(smartlist_t *routers, char **router_status_out,
int for_controller)
{
/* List of entries in a router-status style: An optional !, then an optional
* equals-suffixed nickname, then a dollar-prefixed hexdigest. */
smartlist_t *rs_entries;
time_t now = time(NULL);
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
const or_options_t *options = get_options();
/* We include v2 dir auths here too, because they need to answer
* controllers. Eventually we'll deprecate this whole function;
* see also networkstatus_getinfo_by_purpose(). */
int authdir = authdir_mode_publishes_statuses(options);
tor_assert(router_status_out);
rs_entries = smartlist_new();
SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
tor_assert(node);
if (authdir) {
/* Update router status in routerinfo_t. */
dirserv_set_router_is_running(ri, now);
}
if (for_controller) {
char name_buf[MAX_VERBOSE_NICKNAME_LEN+2];
char *cp = name_buf;
if (!node->is_running)
*cp++ = '!';
router_get_verbose_nickname(cp, ri);
smartlist_add_strdup(rs_entries, name_buf);
} else if (ri->cache_info.published_on >= cutoff) {
smartlist_add(rs_entries, list_single_server_status(ri,
node->is_running));
}
} SMARTLIST_FOREACH_END(ri);
*router_status_out = smartlist_join_strings(rs_entries, " ", 0, NULL);
SMARTLIST_FOREACH(rs_entries, char *, cp, tor_free(cp));
smartlist_free(rs_entries);
return 0;
}