1*f1b790a5Sclaudio /* $OpenBSD: relayctl.c,v 1.63 2024/11/21 13:38:15 claudio Exp $ */ 2feb9ff76Sreyk 3feb9ff76Sreyk /* 4583626ebSreyk * Copyright (c) 2007 - 2013 Reyk Floeter <reyk@openbsd.org> 536f5dc5eSpyr * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> 6feb9ff76Sreyk * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 7feb9ff76Sreyk * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 8feb9ff76Sreyk * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> 9feb9ff76Sreyk * 10feb9ff76Sreyk * Permission to use, copy, modify, and distribute this software for any 11feb9ff76Sreyk * purpose with or without fee is hereby granted, provided that the above 12feb9ff76Sreyk * copyright notice and this permission notice appear in all copies. 13feb9ff76Sreyk * 14feb9ff76Sreyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 15feb9ff76Sreyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 16feb9ff76Sreyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 17feb9ff76Sreyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18feb9ff76Sreyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 19feb9ff76Sreyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 20feb9ff76Sreyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21feb9ff76Sreyk */ 22feb9ff76Sreyk 23feb9ff76Sreyk #include <sys/types.h> 24feb9ff76Sreyk #include <sys/socket.h> 25f04ff968Sreyk #include <sys/time.h> 26feb9ff76Sreyk #include <sys/queue.h> 27feb9ff76Sreyk #include <sys/un.h> 2853967d9eSreyk 2953967d9eSreyk #include <arpa/inet.h> 30feb9ff76Sreyk 31f04ff968Sreyk #include <stdio.h> 32f04ff968Sreyk #include <stdlib.h> 33feb9ff76Sreyk #include <err.h> 3453b804d7Sreyk #include <errno.h> 35b2cd1366Sguenther #include <limits.h> 36feb9ff76Sreyk #include <string.h> 37feb9ff76Sreyk #include <unistd.h> 38f04ff968Sreyk #include <time.h> 39f04ff968Sreyk #include <imsg.h> 40e8fb3979Spyr 41748ceb64Sreyk #include "relayd.h" 42feb9ff76Sreyk #include "parser.h" 43feb9ff76Sreyk 44feb9ff76Sreyk __dead void usage(void); 452edd718bSreyk int show_summary_msg(struct imsg *, int); 46fa0d8478Sreyk int show_session_msg(struct imsg *); 47feb9ff76Sreyk int show_command_output(struct imsg *); 489591a9f7Spyr char *print_rdr_status(int); 49feb9ff76Sreyk char *print_host_status(int, int); 50feb9ff76Sreyk char *print_table_status(int, int); 512edd718bSreyk char *print_relay_status(int); 528e01c6e3Sreyk void print_statistics(struct ctl_stats[PROC_MAX_INSTANCES + 1]); 53feb9ff76Sreyk 54ee20bc67Sreyk struct imsgname { 55ee20bc67Sreyk int type; 56ee20bc67Sreyk char *name; 57ee20bc67Sreyk void (*func)(struct imsg *); 58ee20bc67Sreyk }; 59ee20bc67Sreyk 60ee20bc67Sreyk struct imsgname *monitor_lookup(u_int8_t); 61ee20bc67Sreyk void monitor_host_status(struct imsg *); 62ee20bc67Sreyk void monitor_id(struct imsg *); 63ee20bc67Sreyk int monitor(struct imsg *); 64ee20bc67Sreyk 65ee20bc67Sreyk struct imsgname imsgs[] = { 66ee20bc67Sreyk { IMSG_HOST_STATUS, "host_status", monitor_host_status }, 679591a9f7Spyr { IMSG_CTL_RDR_DISABLE, "ctl_rdr_disable", monitor_id }, 689591a9f7Spyr { IMSG_CTL_RDR_ENABLE, "ctl_rdr_enable", monitor_id }, 69ee20bc67Sreyk { IMSG_CTL_TABLE_DISABLE, "ctl_table_disable", monitor_id }, 70ee20bc67Sreyk { IMSG_CTL_TABLE_ENABLE, "ctl_table_enable", monitor_id }, 71ee20bc67Sreyk { IMSG_CTL_HOST_DISABLE, "ctl_host_disable", monitor_id }, 72ee20bc67Sreyk { IMSG_CTL_HOST_ENABLE, "ctl_host_enable", monitor_id }, 739ea8c990Spyr { IMSG_CTL_TABLE_CHANGED, "ctl_table_changed", monitor_id }, 749ea8c990Spyr { IMSG_CTL_PULL_RULESET, "ctl_pull_ruleset", monitor_id }, 759ea8c990Spyr { IMSG_CTL_PUSH_RULESET, "ctl_push_ruleset", monitor_id }, 76ee20bc67Sreyk { IMSG_SYNC, "sync", NULL }, 77ee20bc67Sreyk { 0, NULL, NULL } 78ee20bc67Sreyk }; 79ee20bc67Sreyk struct imsgname imsgunknown = { 80ee20bc67Sreyk -1, "<unknown>", NULL 81ee20bc67Sreyk }; 82ee20bc67Sreyk 83feb9ff76Sreyk struct imsgbuf *ibuf; 8498ad2da2Sclaudio int error = 0; 85feb9ff76Sreyk 86feb9ff76Sreyk __dead void 87feb9ff76Sreyk usage(void) 88feb9ff76Sreyk { 89feb9ff76Sreyk extern char *__progname; 90feb9ff76Sreyk 91ec4c1254Sbenno fprintf(stderr, "usage: %s [-s socket] command [argument ...]\n", 92ec4c1254Sbenno __progname); 93feb9ff76Sreyk exit(1); 94feb9ff76Sreyk } 95feb9ff76Sreyk 96feb9ff76Sreyk int 97feb9ff76Sreyk main(int argc, char *argv[]) 98feb9ff76Sreyk { 99feb9ff76Sreyk struct sockaddr_un sun; 100feb9ff76Sreyk struct parse_result *res; 101feb9ff76Sreyk struct imsg imsg; 102feb9ff76Sreyk int ctl_sock; 103feb9ff76Sreyk int done = 0; 104f579a0f7Sjsg int n, verbose = 0; 105ec4c1254Sbenno int ch; 106ec4c1254Sbenno const char *sockname; 107ec4c1254Sbenno 108ec4c1254Sbenno sockname = RELAYD_SOCKET; 109ec4c1254Sbenno while ((ch = getopt(argc, argv, "s:")) != -1) { 110ec4c1254Sbenno switch (ch) { 111ec4c1254Sbenno case 's': 112ec4c1254Sbenno sockname = optarg; 113ec4c1254Sbenno break; 114ec4c1254Sbenno default: 115ec4c1254Sbenno usage(); 116ec4c1254Sbenno /* NOTREACHED */ 117ec4c1254Sbenno } 118ec4c1254Sbenno } 119ec4c1254Sbenno argc -= optind; 120ec4c1254Sbenno argv += optind; 121feb9ff76Sreyk 122feb9ff76Sreyk /* parse options */ 123ec4c1254Sbenno if ((res = parse(argc, argv)) == NULL) 124feb9ff76Sreyk exit(1); 125feb9ff76Sreyk 126748ceb64Sreyk /* connect to relayd control socket */ 127feb9ff76Sreyk if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 128feb9ff76Sreyk err(1, "socket"); 129feb9ff76Sreyk 130feb9ff76Sreyk bzero(&sun, sizeof(sun)); 131feb9ff76Sreyk sun.sun_family = AF_UNIX; 132ec4c1254Sbenno if (strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path)) >= 133ec4c1254Sbenno sizeof(sun.sun_path)) 134ec4c1254Sbenno errx(1, "socket `%s' too long", sockname); 13553b804d7Sreyk reconnect: 13653b804d7Sreyk if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) { 13753b804d7Sreyk /* Keep retrying if running in monitor mode */ 13853b804d7Sreyk if (res->action == MONITOR && 13953b804d7Sreyk (errno == ENOENT || errno == ECONNREFUSED)) { 14053b804d7Sreyk usleep(100); 14153b804d7Sreyk goto reconnect; 14253b804d7Sreyk } 143ec4c1254Sbenno err(1, "connect: %s", sockname); 14453b804d7Sreyk } 145feb9ff76Sreyk 146c754e3edSbenno if (pledge("stdio", NULL) == -1) 1474581b8e5Ssemarie err(1, "pledge"); 148c754e3edSbenno 149feb9ff76Sreyk if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) 150feb9ff76Sreyk err(1, NULL); 151*f1b790a5Sclaudio if (imsgbuf_init(ibuf, ctl_sock) == -1) 152*f1b790a5Sclaudio err(1, NULL); 153feb9ff76Sreyk done = 0; 154feb9ff76Sreyk 155feb9ff76Sreyk /* process user request */ 156feb9ff76Sreyk switch (res->action) { 157feb9ff76Sreyk case NONE: 158feb9ff76Sreyk usage(); 159feb9ff76Sreyk /* not reached */ 160feb9ff76Sreyk case SHOW_SUM: 1612edd718bSreyk case SHOW_HOSTS: 162dec6607bSreyk case SHOW_RDRS: 1632edd718bSreyk case SHOW_RELAYS: 164417c432fSreyk case SHOW_ROUTERS: 16530e88fcdSpyr imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0); 166c84cf264Sreyk printf("%-4s\t%-8s\t%-24s\t%-7s\tStatus\n", 167c84cf264Sreyk "Id", "Type", "Name", "Avlblty"); 168feb9ff76Sreyk break; 169fa0d8478Sreyk case SHOW_SESSIONS: 170fa0d8478Sreyk imsg_compose(ibuf, IMSG_CTL_SESSION, 0, 0, -1, NULL, 0); 171fa0d8478Sreyk break; 1729591a9f7Spyr case RDR_ENABLE: 1739591a9f7Spyr imsg_compose(ibuf, IMSG_CTL_RDR_ENABLE, 0, 0, -1, 174feb9ff76Sreyk &res->id, sizeof(res->id)); 175feb9ff76Sreyk break; 1769591a9f7Spyr case RDR_DISABLE: 1779591a9f7Spyr imsg_compose(ibuf, IMSG_CTL_RDR_DISABLE, 0, 0, -1, 178feb9ff76Sreyk &res->id, sizeof(res->id)); 179feb9ff76Sreyk break; 180feb9ff76Sreyk case TABLE_ENABLE: 18130e88fcdSpyr imsg_compose(ibuf, IMSG_CTL_TABLE_ENABLE, 0, 0, -1, 182feb9ff76Sreyk &res->id, sizeof(res->id)); 183feb9ff76Sreyk break; 184feb9ff76Sreyk case TABLE_DISABLE: 18530e88fcdSpyr imsg_compose(ibuf, IMSG_CTL_TABLE_DISABLE, 0, 0, -1, 186feb9ff76Sreyk &res->id, sizeof(res->id)); 187feb9ff76Sreyk break; 188feb9ff76Sreyk case HOST_ENABLE: 18930e88fcdSpyr imsg_compose(ibuf, IMSG_CTL_HOST_ENABLE, 0, 0, -1, 190feb9ff76Sreyk &res->id, sizeof(res->id)); 191feb9ff76Sreyk break; 192feb9ff76Sreyk case HOST_DISABLE: 19330e88fcdSpyr imsg_compose(ibuf, IMSG_CTL_HOST_DISABLE, 0, 0, -1, 194feb9ff76Sreyk &res->id, sizeof(res->id)); 195feb9ff76Sreyk break; 196feb9ff76Sreyk case SHUTDOWN: 19730e88fcdSpyr imsg_compose(ibuf, IMSG_CTL_SHUTDOWN, 0, 0, -1, NULL, 0); 198feb9ff76Sreyk break; 199cd65ce7bSpyr case POLL: 200cd65ce7bSpyr imsg_compose(ibuf, IMSG_CTL_POLL, 0, 0, -1, NULL, 0); 201cd65ce7bSpyr break; 202a2195becSreyk case LOAD: 203a2195becSreyk imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, 204a2195becSreyk res->path, strlen(res->path)); 205a2195becSreyk done = 1; 206a2195becSreyk break; 207feb9ff76Sreyk case RELOAD: 20830e88fcdSpyr imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0); 209a2195becSreyk done = 1; 210feb9ff76Sreyk break; 2111569a65fSpyr case MONITOR: 21230e88fcdSpyr imsg_compose(ibuf, IMSG_CTL_NOTIFY, 0, 0, -1, NULL, 0); 2131569a65fSpyr break; 214f579a0f7Sjsg case LOG_VERBOSE: 215f579a0f7Sjsg verbose = 2; 216f579a0f7Sjsg /* FALLTHROUGH */ 217f579a0f7Sjsg case LOG_BRIEF: 2180325c666Sreyk imsg_compose(ibuf, IMSG_CTL_VERBOSE, 0, 0, -1, 219f579a0f7Sjsg &verbose, sizeof(verbose)); 220f579a0f7Sjsg printf("logging request sent.\n"); 221f579a0f7Sjsg done = 1; 222f579a0f7Sjsg break; 223feb9ff76Sreyk } 224feb9ff76Sreyk 225dd7efffeSclaudio if (imsgbuf_flush(ibuf) == -1) 226feb9ff76Sreyk err(1, "write error"); 227feb9ff76Sreyk 228feb9ff76Sreyk while (!done) { 229668e5ba9Sclaudio if ((n = imsgbuf_read(ibuf)) == -1) 230ef2e27a1Sclaudio err(1, "read error"); 231feb9ff76Sreyk if (n == 0) 232feb9ff76Sreyk errx(1, "pipe closed"); 233feb9ff76Sreyk 234feb9ff76Sreyk while (!done) { 235feb9ff76Sreyk if ((n = imsg_get(ibuf, &imsg)) == -1) 236feb9ff76Sreyk errx(1, "imsg_get error"); 237feb9ff76Sreyk if (n == 0) 238feb9ff76Sreyk break; 239feb9ff76Sreyk switch (res->action) { 240feb9ff76Sreyk case SHOW_SUM: 2412edd718bSreyk case SHOW_HOSTS: 242dec6607bSreyk case SHOW_RDRS: 2432edd718bSreyk case SHOW_RELAYS: 244417c432fSreyk case SHOW_ROUTERS: 24572f1a274Sreyk done = show_summary_msg(&imsg, res->action); 246feb9ff76Sreyk break; 247fa0d8478Sreyk case SHOW_SESSIONS: 248fa0d8478Sreyk done = show_session_msg(&imsg); 249fa0d8478Sreyk break; 2509591a9f7Spyr case RDR_DISABLE: 2519591a9f7Spyr case RDR_ENABLE: 252feb9ff76Sreyk case TABLE_DISABLE: 253feb9ff76Sreyk case TABLE_ENABLE: 254feb9ff76Sreyk case HOST_DISABLE: 255feb9ff76Sreyk case HOST_ENABLE: 256cd65ce7bSpyr case POLL: 257feb9ff76Sreyk case SHUTDOWN: 258c8bdf044Spyr done = show_command_output(&imsg); 259c8bdf044Spyr break; 260feb9ff76Sreyk case NONE: 261f579a0f7Sjsg case LOG_VERBOSE: 262f579a0f7Sjsg case LOG_BRIEF: 263a2195becSreyk case RELOAD: 264a2195becSreyk case LOAD: 265feb9ff76Sreyk break; 2661569a65fSpyr case MONITOR: 2671569a65fSpyr done = monitor(&imsg); 2681569a65fSpyr break; 269feb9ff76Sreyk } 270feb9ff76Sreyk imsg_free(&imsg); 271feb9ff76Sreyk } 272feb9ff76Sreyk } 273feb9ff76Sreyk close(ctl_sock); 274feb9ff76Sreyk free(ibuf); 275feb9ff76Sreyk 27698ad2da2Sclaudio return (error ? 1 : 0); 277feb9ff76Sreyk } 278feb9ff76Sreyk 279ee20bc67Sreyk struct imsgname * 280ee20bc67Sreyk monitor_lookup(u_int8_t type) 281ee20bc67Sreyk { 282ee20bc67Sreyk int i; 283ee20bc67Sreyk 284ee20bc67Sreyk for (i = 0; imsgs[i].name != NULL; i++) 285ee20bc67Sreyk if (imsgs[i].type == type) 286ee20bc67Sreyk return (&imsgs[i]); 287ee20bc67Sreyk return (&imsgunknown); 288ee20bc67Sreyk } 289ee20bc67Sreyk 290ee20bc67Sreyk void 291ee20bc67Sreyk monitor_host_status(struct imsg *imsg) 292ee20bc67Sreyk { 293ee20bc67Sreyk struct ctl_status cs; 294ee20bc67Sreyk 295ee20bc67Sreyk memcpy(&cs, imsg->data, sizeof(cs)); 296ee20bc67Sreyk printf("\tid: %u\n", cs.id); 297ee20bc67Sreyk printf("\tstate: "); 298ee20bc67Sreyk switch (cs.up) { 299ee20bc67Sreyk case HOST_UP: 300ee20bc67Sreyk printf("up\n"); 301ee20bc67Sreyk break; 302ee20bc67Sreyk case HOST_DOWN: 303ee20bc67Sreyk printf("down\n"); 304ee20bc67Sreyk break; 305ee20bc67Sreyk default: 306ee20bc67Sreyk printf("unknown\n"); 307ee20bc67Sreyk break; 308ee20bc67Sreyk } 309ee20bc67Sreyk } 310ee20bc67Sreyk 311ee20bc67Sreyk void 312ee20bc67Sreyk monitor_id(struct imsg *imsg) 313ee20bc67Sreyk { 314ee20bc67Sreyk struct ctl_id id; 315ee20bc67Sreyk 316ee20bc67Sreyk memcpy(&id, imsg->data, sizeof(id)); 317ee20bc67Sreyk printf("\tid: %u\n", id.id); 318e9955165Sreyk if (strlen(id.name)) 319e9955165Sreyk printf("\tname: %s\n", id.name); 320ee20bc67Sreyk } 321ee20bc67Sreyk 322feb9ff76Sreyk int 3231569a65fSpyr monitor(struct imsg *imsg) 3241569a65fSpyr { 3251569a65fSpyr time_t now; 326ee20bc67Sreyk int done = 0; 327ee20bc67Sreyk struct imsgname *imn; 3281569a65fSpyr 3291569a65fSpyr now = time(NULL); 330ee20bc67Sreyk 331ee20bc67Sreyk imn = monitor_lookup(imsg->hdr.type); 332ee20bc67Sreyk printf("%s: imsg type %u len %u peerid %u pid %d\n", imn->name, 333ee20bc67Sreyk imsg->hdr.type, imsg->hdr.len, imsg->hdr.peerid, imsg->hdr.pid); 3342954f9abSguenther printf("\ttimestamp: %lld, %s", (long long)now, ctime(&now)); 335ee20bc67Sreyk if (imn->type == -1) 3361569a65fSpyr done = 1; 337ee20bc67Sreyk if (imn->func != NULL) 338ee20bc67Sreyk (*imn->func)(imsg); 339ee20bc67Sreyk 3401569a65fSpyr return (done); 3411569a65fSpyr } 3421569a65fSpyr 3431569a65fSpyr int 3442edd718bSreyk show_summary_msg(struct imsg *imsg, int type) 345feb9ff76Sreyk { 3469591a9f7Spyr struct rdr *rdr; 347feb9ff76Sreyk struct table *table; 348feb9ff76Sreyk struct host *host; 3492edd718bSreyk struct relay *rlay; 350417c432fSreyk struct router *rt; 351417c432fSreyk struct netroute *nr; 3528e01c6e3Sreyk struct ctl_stats stats[PROC_MAX_INSTANCES]; 353b9fc9a72Sderaadt char name[HOST_NAME_MAX+1]; 354feb9ff76Sreyk 355feb9ff76Sreyk switch (imsg->hdr.type) { 3569591a9f7Spyr case IMSG_CTL_RDR: 357417c432fSreyk if (!(type == SHOW_SUM || type == SHOW_RDRS)) 3582edd718bSreyk break; 3599591a9f7Spyr rdr = imsg->data; 360c84cf264Sreyk printf("%-4u\t%-8s\t%-24s\t%-7s\t%s\n", 3619591a9f7Spyr rdr->conf.id, "redirect", rdr->conf.name, "", 3629591a9f7Spyr print_rdr_status(rdr->conf.flags)); 363feb9ff76Sreyk break; 364feb9ff76Sreyk case IMSG_CTL_TABLE: 365417c432fSreyk if (!(type == SHOW_SUM || type == SHOW_HOSTS)) 3662edd718bSreyk break; 367feb9ff76Sreyk table = imsg->data; 368c84cf264Sreyk printf("%-4u\t%-8s\t%-24s\t%-7s\t%s\n", 369c84cf264Sreyk table->conf.id, "table", table->conf.name, "", 370ec60fe22Spyr print_table_status(table->up, table->conf.flags)); 371feb9ff76Sreyk break; 372feb9ff76Sreyk case IMSG_CTL_HOST: 373417c432fSreyk if (!(type == SHOW_SUM || type == SHOW_HOSTS)) 3742edd718bSreyk break; 375feb9ff76Sreyk host = imsg->data; 3764d6382cdSreyk if (host->conf.parentid) 3774d6382cdSreyk snprintf(name, sizeof(name), "%s parent %u", 3784d6382cdSreyk host->conf.name, host->conf.parentid); 3794d6382cdSreyk else 3804d6382cdSreyk strlcpy(name, host->conf.name, sizeof(name)); 381c84cf264Sreyk printf("%-4u\t%-8s\t%-24s\t%-7s\t%s\n", 3824d6382cdSreyk host->conf.id, "host", name, 3832edd718bSreyk print_availability(host->check_cnt, host->up_cnt), 384feb9ff76Sreyk print_host_status(host->up, host->flags)); 3852edd718bSreyk if (type == SHOW_HOSTS && host->check_cnt) { 386c84cf264Sreyk printf("\t%8s\ttotal: %lu/%lu checks", 3872edd718bSreyk "", host->up_cnt, host->check_cnt); 3882edd718bSreyk if (host->retry_cnt) 3892edd718bSreyk printf(", %d retries", host->retry_cnt); 390c0dc99f6Sreyk if (host->he && host->up == HOST_DOWN) 391c0dc99f6Sreyk printf(", error: %s", host_error(host->he)); 3922edd718bSreyk printf("\n"); 3932edd718bSreyk } 3942edd718bSreyk break; 3952edd718bSreyk case IMSG_CTL_RELAY: 396417c432fSreyk if (!(type == SHOW_SUM || type == SHOW_RELAYS)) 3972edd718bSreyk break; 3982edd718bSreyk rlay = imsg->data; 399c84cf264Sreyk printf("%-4u\t%-8s\t%-24s\t%-7s\t%s\n", 4004a5b9b3eSreyk rlay->rl_conf.id, "relay", rlay->rl_conf.name, "", 4014a5b9b3eSreyk print_relay_status(rlay->rl_conf.flags)); 4022edd718bSreyk break; 403dec6607bSreyk case IMSG_CTL_RDR_STATS: 404dec6607bSreyk if (type != SHOW_RDRS) 405dec6607bSreyk break; 406dec6607bSreyk bcopy(imsg->data, &stats[0], sizeof(stats[0])); 407dec6607bSreyk stats[1].id = EMPTY_ID; 408dec6607bSreyk print_statistics(stats); 409dec6607bSreyk break; 410dec6607bSreyk case IMSG_CTL_RELAY_STATS: 4112edd718bSreyk if (type != SHOW_RELAYS) 4122edd718bSreyk break; 4132edd718bSreyk bcopy(imsg->data, &stats, sizeof(stats)); 414dec6607bSreyk print_statistics(stats); 415feb9ff76Sreyk break; 416417c432fSreyk case IMSG_CTL_ROUTER: 417417c432fSreyk if (!(type == SHOW_SUM || type == SHOW_ROUTERS)) 418417c432fSreyk break; 419417c432fSreyk rt = imsg->data; 420417c432fSreyk printf("%-4u\t%-8s\t%-24s\t%-7s\t%s\n", 421417c432fSreyk rt->rt_conf.id, "router", rt->rt_conf.name, "", 422417c432fSreyk print_relay_status(rt->rt_conf.flags)); 423417c432fSreyk if (type != SHOW_ROUTERS) 424417c432fSreyk break; 425417c432fSreyk if (rt->rt_conf.rtable) 426417c432fSreyk printf("\t%8s\trtable: %d\n", "", rt->rt_conf.rtable); 427417c432fSreyk if (strlen(rt->rt_conf.label)) 428417c432fSreyk printf("\t%8s\trtlabel: %s\n", "", rt->rt_conf.label); 429417c432fSreyk break; 430417c432fSreyk case IMSG_CTL_NETROUTE: 431417c432fSreyk if (type != SHOW_ROUTERS) 432417c432fSreyk break; 433417c432fSreyk nr = imsg->data; 434417c432fSreyk (void)print_host(&nr->nr_conf.ss, name, sizeof(name)); 435417c432fSreyk printf("\t%8s\troute: %s/%d\n", 436417c432fSreyk "", name, nr->nr_conf.prefixlen); 437417c432fSreyk break; 438feb9ff76Sreyk case IMSG_CTL_END: 439feb9ff76Sreyk return (1); 440feb9ff76Sreyk default: 441feb9ff76Sreyk errx(1, "wrong message in summary: %u", imsg->hdr.type); 442feb9ff76Sreyk break; 443feb9ff76Sreyk } 444feb9ff76Sreyk return (0); 445feb9ff76Sreyk } 446feb9ff76Sreyk 447feb9ff76Sreyk int 448fa0d8478Sreyk show_session_msg(struct imsg *imsg) 449fa0d8478Sreyk { 450f4a6e73bSreyk struct rsession *con; 451fa0d8478Sreyk char a[128], b[128]; 452fa0d8478Sreyk struct timeval tv_now; 453fa0d8478Sreyk 454fa0d8478Sreyk switch (imsg->hdr.type) { 455fa0d8478Sreyk case IMSG_CTL_SESSION: 456fa0d8478Sreyk con = imsg->data; 457fa0d8478Sreyk 458f8eb77d7Sthib (void)print_host(&con->se_in.ss, a, sizeof(a)); 459f8eb77d7Sthib (void)print_host(&con->se_out.ss, b, sizeof(b)); 460fa0d8478Sreyk printf("session %u:%u %s:%u -> %s:%u\t%s\n", 461f8eb77d7Sthib imsg->hdr.peerid, con->se_id, 462f8eb77d7Sthib a, ntohs(con->se_in.port), b, ntohs(con->se_out.port), 463f8eb77d7Sthib con->se_done ? "DONE" : "RUNNING"); 464fa0d8478Sreyk 465fd1841a3Sreyk getmonotime(&tv_now); 466f8eb77d7Sthib print_time(&tv_now, &con->se_tv_start, a, sizeof(a)); 467f8eb77d7Sthib print_time(&tv_now, &con->se_tv_last, b, sizeof(b)); 46886b74329Sreyk printf("\tage %s, idle %s, relay %u, pid %u", 46986b74329Sreyk a, b, con->se_relayid, con->se_pid); 470cb8b0e56Sreyk /* XXX grab tagname instead of tag id */ 471cb8b0e56Sreyk if (con->se_tag) 472cb8b0e56Sreyk printf(", tag (id) %u", con->se_tag); 473aadc8ea4Sreyk printf("\n"); 474fa0d8478Sreyk break; 475fa0d8478Sreyk case IMSG_CTL_END: 476fa0d8478Sreyk return (1); 477fa0d8478Sreyk default: 478fa0d8478Sreyk errx(1, "wrong message in session: %u", imsg->hdr.type); 479fa0d8478Sreyk break; 480fa0d8478Sreyk } 481fa0d8478Sreyk return (0); 482fa0d8478Sreyk } 483fa0d8478Sreyk 484fa0d8478Sreyk int 485feb9ff76Sreyk show_command_output(struct imsg *imsg) 486feb9ff76Sreyk { 487feb9ff76Sreyk switch (imsg->hdr.type) { 488feb9ff76Sreyk case IMSG_CTL_OK: 489feb9ff76Sreyk printf("command succeeded\n"); 490feb9ff76Sreyk break; 491feb9ff76Sreyk case IMSG_CTL_FAIL: 492feb9ff76Sreyk printf("command failed\n"); 49398ad2da2Sclaudio error++; 494feb9ff76Sreyk break; 495feb9ff76Sreyk default: 496feb9ff76Sreyk errx(1, "wrong message in summary: %u", imsg->hdr.type); 497feb9ff76Sreyk } 498feb9ff76Sreyk return (1); 499feb9ff76Sreyk } 500feb9ff76Sreyk 501feb9ff76Sreyk char * 5029591a9f7Spyr print_rdr_status(int flags) 503feb9ff76Sreyk { 504feb9ff76Sreyk if (flags & F_DISABLE) { 505feb9ff76Sreyk return ("disabled"); 506feb9ff76Sreyk } else if (flags & F_DOWN) { 507feb9ff76Sreyk return ("down"); 508feb9ff76Sreyk } else if (flags & F_BACKUP) { 509feb9ff76Sreyk return ("active (using backup table)"); 510feb9ff76Sreyk } else 511feb9ff76Sreyk return ("active"); 512feb9ff76Sreyk } 513feb9ff76Sreyk 514feb9ff76Sreyk char * 515feb9ff76Sreyk print_table_status(int up, int fl) 516feb9ff76Sreyk { 517feb9ff76Sreyk static char buf[1024]; 518feb9ff76Sreyk 519feb9ff76Sreyk bzero(buf, sizeof(buf)); 520feb9ff76Sreyk 521feb9ff76Sreyk if (fl & F_DISABLE) { 522feb9ff76Sreyk snprintf(buf, sizeof(buf) - 1, "disabled"); 523feb9ff76Sreyk } else if (!up) { 524feb9ff76Sreyk snprintf(buf, sizeof(buf) - 1, "empty"); 525feb9ff76Sreyk } else 526c0dc99f6Sreyk snprintf(buf, sizeof(buf) - 1, "active (%d hosts)", up); 527feb9ff76Sreyk return (buf); 528feb9ff76Sreyk } 529feb9ff76Sreyk 530feb9ff76Sreyk char * 531feb9ff76Sreyk print_host_status(int status, int fl) 532feb9ff76Sreyk { 533feb9ff76Sreyk if (fl & F_DISABLE) 534feb9ff76Sreyk return ("disabled"); 535feb9ff76Sreyk 536feb9ff76Sreyk switch (status) { 537feb9ff76Sreyk case HOST_DOWN: 538feb9ff76Sreyk return ("down"); 539feb9ff76Sreyk case HOST_UNKNOWN: 540feb9ff76Sreyk return ("unknown"); 541feb9ff76Sreyk case HOST_UP: 542feb9ff76Sreyk return ("up"); 543feb9ff76Sreyk default: 544feb9ff76Sreyk errx(1, "invalid status: %d", status); 545feb9ff76Sreyk } 546feb9ff76Sreyk } 5472edd718bSreyk 5482edd718bSreyk char * 5492edd718bSreyk print_relay_status(int flags) 5502edd718bSreyk { 5512edd718bSreyk if (flags & F_DISABLE) { 5522edd718bSreyk return ("disabled"); 5532edd718bSreyk } else 5542edd718bSreyk return ("active"); 5552edd718bSreyk } 5562edd718bSreyk 557dec6607bSreyk void 5588e01c6e3Sreyk print_statistics(struct ctl_stats stats[PROC_MAX_INSTANCES + 1]) 559dec6607bSreyk { 560dec6607bSreyk struct ctl_stats crs; 561dec6607bSreyk int i; 562dec6607bSreyk 563dec6607bSreyk bzero(&crs, sizeof(crs)); 564dec6607bSreyk crs.interval = stats[0].interval; 565dec6607bSreyk for (i = 0; stats[i].id != EMPTY_ID; i++) { 566dec6607bSreyk crs.cnt += stats[i].cnt; 567dec6607bSreyk crs.last += stats[i].last; 568dec6607bSreyk crs.avg += stats[i].avg; 569dec6607bSreyk crs.last_hour += stats[i].last_hour; 570dec6607bSreyk crs.avg_hour += stats[i].avg_hour; 571dec6607bSreyk crs.last_day += stats[i].last_day; 572dec6607bSreyk crs.avg_day += stats[i].avg_day; 573dec6607bSreyk } 574dec6607bSreyk if (crs.cnt == 0) 575dec6607bSreyk return; 576dec6607bSreyk printf("\t%8s\ttotal: %llu sessions\n" 577b02f4fdbSbenno "\t%8s\tlast: %u/%llus %u/h %u/d sessions\n" 578b02f4fdbSbenno "\t%8s\taverage: %u/%llus %u/h %u/d sessions\n", 579dec6607bSreyk "", crs.cnt, 580dec6607bSreyk "", crs.last, crs.interval, 581dec6607bSreyk crs.last_hour, crs.last_day, 582dec6607bSreyk "", crs.avg, crs.interval, 583dec6607bSreyk crs.avg_hour, crs.avg_day); 584dec6607bSreyk } 585