From b41cc0c801858fe3ff012a866515bd2e80dfe6af Mon Sep 17 00:00:00 2001 From: tobhe Date: Mon, 19 Sep 2022 20:54:02 +0000 Subject: [PATCH] Add iked connection statistics for successful and failed connections, common error types and other events that help analyze errors in larger setups. The counters can be printed with 'ikectl show stats'. ok bluhm@ patrick@ from and ok markus@ --- sbin/iked/config.c | 9 +++++- sbin/iked/control.c | 4 ++- sbin/iked/iked.h | 39 ++++++++++++++++++++++++- sbin/iked/ikev2.c | 54 ++++++++++++++++++++++++++++------ sbin/iked/ikev2_msg.c | 14 +++++++-- sbin/iked/ikev2_pld.c | 16 ++++++++++- sbin/iked/policy.c | 24 +++++++++++++++- sbin/iked/types.h | 5 ++-- usr.sbin/ikectl/ikectl.c | 62 +++++++++++++++++++++++++++++++++++++++- usr.sbin/ikectl/parser.c | 3 +- usr.sbin/ikectl/parser.h | 5 ++-- 11 files changed, 214 insertions(+), 21 deletions(-) diff --git a/sbin/iked/config.c b/sbin/iked/config.c index 25caf3d3e15..dd1c865a77b 100644 --- a/sbin/iked/config.c +++ b/sbin/iked/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.86 2022/07/08 19:51:11 tobhe Exp $ */ +/* $OpenBSD: config.c,v 1.87 2022/09/19 20:54:02 tobhe Exp $ */ /* * Copyright (c) 2019 Tobias Heider @@ -60,6 +60,7 @@ config_new_sa(struct iked *env, int initiator) gettimeofday(&sa->sa_timecreated, NULL); memcpy(&sa->sa_timeused, &sa->sa_timecreated, sizeof(sa->sa_timeused)); + ikestat_inc(env, ikes_sa_created); return (sa); } @@ -181,6 +182,11 @@ config_free_sa(struct iked *env, struct iked_sa *sa) free(sa->sa_cp_dns); free(sa->sa_tag); + + if (sa->sa_state == IKEV2_STATE_ESTABLISHED) + ikestat_dec(env, ikes_sa_established_current); + ikestat_inc(env, ikes_sa_removed); + free(sa); } @@ -333,6 +339,7 @@ config_free_childsas(struct iked *env, struct iked_childsas *head, childsa_free(ipcomp); } childsa_free(csa); + ikestat_inc(env, ikes_csa_removed); } } diff --git a/sbin/iked/control.c b/sbin/iked/control.c index 828d68e7a71..f88b9bf806c 100644 --- a/sbin/iked/control.c +++ b/sbin/iked/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.32 2021/11/21 22:44:08 tobhe Exp $ */ +/* $OpenBSD: control.c,v 1.33 2022/09/19 20:54:02 tobhe Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter @@ -311,6 +311,7 @@ control_dispatch_imsg(int fd, short event, void *arg) proc_forward_imsg(&env->sc_ps, &imsg, PROC_IKEV2, -1); break; case IMSG_CTL_SHOW_SA: + case IMSG_CTL_SHOW_STATS: proc_forward_imsg(&env->sc_ps, &imsg, PROC_IKEV2, -1); c->flags |= CTL_CONN_NOTIFY; break; @@ -346,6 +347,7 @@ control_dispatch_ikev2(int fd, struct privsep_proc *p, struct imsg *imsg) { switch (imsg->hdr.type) { case IMSG_CTL_SHOW_SA: + case IMSG_CTL_SHOW_STATS: control_imsg_forward(imsg); return (0); default: diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h index 9873bc36f71..e6805b86c91 100644 --- a/sbin/iked/iked.h +++ b/sbin/iked/iked.h @@ -1,4 +1,4 @@ -/* $OpenBSD: iked.h,v 1.206 2022/07/22 15:53:33 tobhe Exp $ */ +/* $OpenBSD: iked.h,v 1.207 2022/09/19 20:54:02 tobhe Exp $ */ /* * Copyright (c) 2019 Tobias Heider @@ -540,6 +540,41 @@ RB_HEAD(iked_dstid_sas, iked_sa); RB_HEAD(iked_addrpool, iked_sa); RB_HEAD(iked_addrpool6, iked_sa); +/* stats */ + +struct iked_stats { + uint64_t ikes_sa_created; + uint64_t ikes_sa_established_total; + uint64_t ikes_sa_established_current; /* gauge */ + uint64_t ikes_sa_established_failures; + uint64_t ikes_sa_proposals_negotiate_failures; + uint64_t ikes_sa_rekeyed; + uint64_t ikes_sa_removed; + uint64_t ikes_csa_created; + uint64_t ikes_csa_removed; + uint64_t ikes_msg_sent; + uint64_t ikes_msg_send_failures; + uint64_t ikes_msg_rcvd; + uint64_t ikes_msg_rcvd_busy; + uint64_t ikes_msg_rcvd_dropped; + uint64_t ikes_retransmit_request; + uint64_t ikes_retransmit_response; + uint64_t ikes_retransmit_limit; + uint64_t ikes_frag_sent; + uint64_t ikes_frag_send_failures; + uint64_t ikes_frag_rcvd; + uint64_t ikes_frag_rcvd_drop; + uint64_t ikes_frag_reass_ok; + uint64_t ikes_frag_reass_drop; + uint64_t ikes_update_addresses_sent; + uint64_t ikes_dpd_sent; + uint64_t ikes_keepalive_sent; +}; + +#define ikestat_add(env, c, n) do { env->sc_stats.c += (n); } while(0) +#define ikestat_inc(env, c) ikestat_add(env, c, 1) +#define ikestat_dec(env, c) ikestat_add(env, c, -1) + struct iked_certreq { struct ibuf *cr_data; uint8_t cr_type; @@ -765,6 +800,8 @@ struct iked { struct iked_flows sc_activeflows; struct iked_users sc_users; + struct iked_stats sc_stats; + void *sc_priv; /* per-process */ int sc_pfkey; /* ike process */ diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c index 6f07d4f35a0..3f718b7a186 100644 --- a/sbin/iked/ikev2.c +++ b/sbin/iked/ikev2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2.c,v 1.351 2022/09/14 13:07:49 tobhe Exp $ */ +/* $OpenBSD: ikev2.c,v 1.352 2022/09/19 20:54:02 tobhe Exp $ */ /* * Copyright (c) 2019 Tobias Heider @@ -187,6 +187,7 @@ int ikev2_resp_informational(struct iked *, struct iked_sa *, void ikev2_ctl_reset_id(struct iked *, struct imsg *, unsigned int); void ikev2_ctl_show_sa(struct iked *); +void ikev2_ctl_show_stats(struct iked *); static struct privsep_proc procs[] = { { "parent", PROC_PARENT, ikev2_dispatch_parent }, @@ -519,6 +520,9 @@ ikev2_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg) case IMSG_CTL_SHOW_SA: ikev2_ctl_show_sa(env); break; + case IMSG_CTL_SHOW_STATS: + ikev2_ctl_show_stats(env); + break; default: return (-1); } @@ -579,6 +583,13 @@ ikev2_ctl_show_sa(struct iked *env) ikev2_info(env, 0); } +void +ikev2_ctl_show_stats(struct iked *env) +{ + proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_STATS, + &env->sc_stats, sizeof(env->sc_stats)); +} + struct iked_sa * ikev2_getimsgdata(struct iked *env, struct imsg *imsg, struct iked_sahdr *sh, uint8_t *type, uint8_t **buf, size_t *size) @@ -642,6 +653,8 @@ ikev2_recv(struct iked *env, struct iked_message *msg) (betoh32(hdr->ike_length) - msg->msg_offset)) return; + ikestat_inc(env, ikes_msg_rcvd); + initiator = (hdr->ike_flags & IKEV2_FLAG_INITIATOR) ? 0 : 1; msg->msg_response = (hdr->ike_flags & IKEV2_FLAG_RESPONSE) ? 1 : 0; msg->msg_exchange = hdr->ike_exchange; @@ -649,8 +662,10 @@ ikev2_recv(struct iked *env, struct iked_message *msg) betoh64(hdr->ike_ispi), betoh64(hdr->ike_rspi), initiator); msg->msg_msgid = betoh32(hdr->ike_msgid); - if (policy_lookup(env, msg, NULL, NULL, 0) != 0) + if (policy_lookup(env, msg, NULL, NULL, 0) != 0) { + ikestat_inc(env, ikes_msg_rcvd_dropped); return; + } logit(hdr->ike_exchange == IKEV2_EXCHANGE_INFORMATIONAL ? LOG_DEBUG : LOG_INFO, @@ -679,20 +694,28 @@ ikev2_recv(struct iked *env, struct iked_message *msg) if (hdr->ike_exchange != IKEV2_EXCHANGE_IKE_SA_INIT && hdr->ike_nextpayload != IKEV2_PAYLOAD_SK && - hdr->ike_nextpayload != IKEV2_PAYLOAD_SKF) + hdr->ike_nextpayload != IKEV2_PAYLOAD_SKF) { + ikestat_inc(env, ikes_msg_rcvd_dropped); return; + } if (msg->msg_response) { - if (msg->msg_msgid > sa->sa_reqid) + if (msg->msg_msgid > sa->sa_reqid) { + ikestat_inc(env, ikes_msg_rcvd_dropped); return; + } mr = ikev2_msg_lookup(env, &sa->sa_requests, msg, hdr->ike_exchange); if (hdr->ike_exchange != IKEV2_EXCHANGE_INFORMATIONAL && - mr == NULL && sa->sa_fragments.frag_count == 0) + mr == NULL && sa->sa_fragments.frag_count == 0) { + ikestat_inc(env, ikes_msg_rcvd_dropped); return; + } if (flag) { - if ((sa->sa_stateflags & flag) == 0) + if ((sa->sa_stateflags & flag) == 0) { + ikestat_inc(env, ikes_msg_rcvd_dropped); return; + } /* * We have initiated this exchange, even if * we are not the initiator of the IKE SA. @@ -723,8 +746,10 @@ ikev2_recv(struct iked *env, struct iked_message *msg) msg->msg_sa = sa = NULL; goto done; } - if (msg->msg_msgid < sa->sa_msgid) + if (msg->msg_msgid < sa->sa_msgid) { + ikestat_inc(env, ikes_msg_rcvd_dropped); return; + } if (flag) initiator = 0; /* @@ -745,6 +770,7 @@ ikev2_recv(struct iked *env, struct iked_message *msg) * Response is being worked on, most likely we're * waiting for the CA process to get back to us */ + ikestat_inc(env, ikes_msg_rcvd_busy); return; } sa->sa_msgid_current = msg->msg_msgid; @@ -753,8 +779,10 @@ ikev2_recv(struct iked *env, struct iked_message *msg) if (sa_address(sa, &sa->sa_peer, (struct sockaddr *)&msg->msg_peer) == -1 || sa_address(sa, &sa->sa_local, (struct sockaddr *)&msg->msg_local) - == -1) + == -1) { + ikestat_inc(env, ikes_msg_rcvd_dropped); return; + } sa->sa_fd = msg->msg_fd; @@ -1033,6 +1061,7 @@ ikev2_ike_auth_recv(struct iked *env, struct iked_sa *sa, 0, -1) != 0) { log_info("%s: no proposal chosen", __func__); msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN; + ikestat_inc(env, ikes_sa_proposals_negotiate_failures); return (-1); } else sa_stateflags(sa, IKED_REQ_SA); @@ -4378,6 +4407,7 @@ ikev2_init_create_child_sa(struct iked *env, struct iked_message *msg) if (proposals_negotiate(&sa->sa_proposals, &sa->sa_proposals, &msg->msg_proposals, 1, -1) != 0) { log_info("%s: no proposal chosen", SPI_SA(sa, __func__)); + ikestat_inc(env, ikes_sa_proposals_negotiate_failures); return (-1); } @@ -4710,6 +4740,8 @@ ikev2_ikesa_enable(struct iked *env, struct iked_sa *sa, struct iked_sa *nsa) sa_state(env, nsa, IKEV2_STATE_ESTABLISHED); ikev2_enable_timer(env, nsa); + ikestat_inc(env, ikes_sa_rekeyed); + nsa->sa_stateflags = nsa->sa_statevalid; /* XXX */ /* unregister DPD keep alive timer & rekey first */ @@ -4887,6 +4919,7 @@ ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg) 1, msg->msg_dhgroup) != 0) { log_info("%s: no proposal chosen", __func__); msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN; + ikestat_inc(env, ikes_sa_proposals_negotiate_failures); goto fail; } @@ -5176,6 +5209,7 @@ ikev2_ike_sa_alive(struct iked *env, void *arg) ikev2_send_ike_e(env, sa, NULL, IKEV2_PAYLOAD_NONE, IKEV2_EXCHANGE_INFORMATIONAL, 0); sa->sa_stateflags |= IKED_REQ_INF; + ikestat_inc(env, ikes_dpd_sent); } /* re-register */ @@ -5199,6 +5233,7 @@ ikev2_ike_sa_keepalive(struct iked *env, void *arg) log_debug("%s: peer %s local %s", __func__, print_host((struct sockaddr *)&sa->sa_peer.addr, NULL, 0), print_host((struct sockaddr *)&sa->sa_local.addr, NULL, 0)); + ikestat_inc(env, ikes_keepalive_sent); timer_add(env, &sa->sa_keepalive, IKED_IKE_SA_KEEPALIVE_TIMEOUT); } @@ -5399,6 +5434,7 @@ ikev2_sa_negotiate_common(struct iked *env, struct iked_sa *sa, struct iked_mess if (proposals_negotiate(&sa->sa_proposals, &msg->msg_policy->pol_proposals, &msg->msg_proposals, 0, -1) != 0) { log_info("%s: proposals_negotiate", __func__); + ikestat_inc(env, ikes_sa_proposals_negotiate_failures); return (-1); } if (sa_stateok(sa, IKEV2_STATE_SA_INIT)) @@ -6361,6 +6397,7 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa, TAILQ_INSERT_TAIL(&sa->sa_childsas, csa, csa_entry); TAILQ_INSERT_TAIL(&sa->sa_childsas, csb, csa_entry); + ikestat_add(env, ikes_csa_created, 2); csa->csa_peersa = csb; csb->csa_peersa = csa; @@ -6609,6 +6646,7 @@ ikev2_childsa_delete(struct iked *env, struct iked_sa *sa, uint8_t saproto, childsa_free(ipcomp); } TAILQ_REMOVE(&sa->sa_childsas, csa, csa_entry); + ikestat_inc(env, ikes_csa_removed); childsa_free(csa); } diff --git a/sbin/iked/ikev2_msg.c b/sbin/iked/ikev2_msg.c index feab4aa7730..c36ba5a24f5 100644 --- a/sbin/iked/ikev2_msg.c +++ b/sbin/iked/ikev2_msg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2_msg.c,v 1.85 2022/03/14 12:58:55 tobhe Exp $ */ +/* $OpenBSD: ikev2_msg.c,v 1.86 2022/09/19 20:54:02 tobhe Exp $ */ /* * Copyright (c) 2019 Tobias Heider @@ -307,7 +307,9 @@ ikev2_msg_send(struct iked *env, struct iked_message *msg) timer_add(env, &sa->sa_timer, IKED_IKE_SA_DELETE_TIMEOUT); } - } + ikestat_inc(env, ikes_msg_send_failures); + } else + ikestat_inc(env, ikes_msg_sent); if (sa == NULL) return (0); @@ -892,6 +894,8 @@ ikev2_send_encrypted_fragments(struct iked *env, struct iked_sa *sa, if (ikev2_msg_send(env, &resp) == -1) goto done; + ikestat_inc(env, ikes_frag_sent); + offset += MINIMUM(left, max_len); left -= MINIMUM(left, max_len); frag_num++; @@ -908,6 +912,7 @@ ikev2_send_encrypted_fragments(struct iked *env, struct iked_sa *sa, done: ikev2_msg_cleanup(env, &resp); ibuf_release(e); + ikestat_inc(env, ikes_frag_send_failures); return ret; } @@ -1268,6 +1273,7 @@ ikev2_msg_retransmit_response(struct iked *env, struct iked_sa *sa, (struct sockaddr *)&m->msg_peer, m->msg_peerlen, (struct sockaddr *)&m->msg_local, m->msg_locallen) == -1) { log_warn("%s: sendtofrom", __func__); + ikestat_inc(env, ikes_msg_send_failures); return (-1); } log_info("%sretransmit %s res %u local %s peer %s", @@ -1279,6 +1285,7 @@ ikev2_msg_retransmit_response(struct iked *env, struct iked_sa *sa, } timer_add(env, &mr->mrt_timer, IKED_RESPONSE_TIMEOUT); + ikestat_inc(env, ikes_retransmit_response); return (0); } @@ -1309,6 +1316,7 @@ ikev2_msg_retransmit_timeout(struct iked *env, void *arg) log_warn("%s: sendtofrom", __func__); ikev2_ike_sa_setreason(sa, "retransmit failed"); sa_free(env, sa); + ikestat_inc(env, ikes_msg_send_failures); return; } log_info("%sretransmit %d %s req %u peer %s " @@ -1321,10 +1329,12 @@ ikev2_msg_retransmit_timeout(struct iked *env, void *arg) /* Exponential timeout */ timer_add(env, &mr->mrt_timer, IKED_RETRANSMIT_TIMEOUT * (2 << (mr->mrt_tries++))); + ikestat_inc(env, ikes_retransmit_request); } else { log_debug("%s: retransmit limit reached for req %u", __func__, msg->msg_msgid); ikev2_ike_sa_setreason(sa, "retransmit limit reached"); + ikestat_inc(env, ikes_retransmit_limit); sa_free(env, sa); } } diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c index d2ec6bd6423..af4f255a328 100644 --- a/sbin/iked/ikev2_pld.c +++ b/sbin/iked/ikev2_pld.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2_pld.c,v 1.124 2022/07/04 09:23:15 tobhe Exp $ */ +/* $OpenBSD: ikev2_pld.c,v 1.125 2022/09/19 20:54:02 tobhe Exp $ */ /* * Copyright (c) 2019 Tobias Heider @@ -1605,6 +1605,7 @@ ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld, size_t frag_num, frag_total; size_t len; int ret = -1; + int processed = 0; ssize_t elen; buf = msgbuf + offset; @@ -1616,6 +1617,8 @@ ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld, buf = msgbuf + offset; len = left - sizeof(frag); + ikestat_inc(env, ikes_frag_rcvd); + /* Limit number of total fragments to avoid DOS */ if (frag_total > IKED_FRAG_TOTAL_MAX ) { log_debug("%s: Total Fragments too big %zu", @@ -1701,10 +1704,15 @@ ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld, } else { ret = 0; } + processed = 1; + done: + if (!processed) + ikestat_inc(env, ikes_frag_rcvd_drop); ibuf_release(e); return (ret); dropall: + ikestat_add(env, ikes_frag_rcvd_drop, sa_frag->frag_count + 1); config_free_fragments(sa_frag); ibuf_release(e); return -1; @@ -1722,6 +1730,7 @@ ikev2_frags_reassemble(struct iked *env, struct ikev2_payload *pld, size_t i; struct iked_message emsg; int ret = -1; + int processed = 0; /* Reassemble fragments to single buffer */ if ((e = ibuf_new(NULL, sa_frag->frag_total_size)) == NULL) { @@ -1765,7 +1774,12 @@ ikev2_frags_reassemble(struct iked *env, struct ikev2_payload *pld, ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e), sa_frag->frag_nextpayload); + processed = 1; done: + if (processed) + ikestat_add(env, ikes_frag_reass_ok, sa_frag->frag_total); + else + ikestat_add(env, ikes_frag_reass_drop, sa_frag->frag_total); config_free_fragments(sa_frag); ibuf_release(e); diff --git a/sbin/iked/policy.c b/sbin/iked/policy.c index ad2b1dc2ccc..a4cdc277355 100644 --- a/sbin/iked/policy.c +++ b/sbin/iked/policy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: policy.c,v 1.90 2022/09/14 13:07:50 tobhe Exp $ */ +/* $OpenBSD: policy.c,v 1.91 2022/09/19 20:54:02 tobhe Exp $ */ /* * Copyright (c) 2020-2021 Tobias Heider @@ -414,6 +414,28 @@ sa_state(struct iked *env, struct iked_sa *sa, int state) } } + if (ostate != sa->sa_state) { + switch (sa->sa_state) { + case IKEV2_STATE_ESTABLISHED: + ikestat_inc(env, ikes_sa_established_total); + ikestat_inc(env, ikes_sa_established_current); + break; + case IKEV2_STATE_CLOSED: + case IKEV2_STATE_CLOSING: + switch (ostate) { + case IKEV2_STATE_ESTABLISHED: + ikestat_dec(env, ikes_sa_established_current); + break; + case IKEV2_STATE_CLOSED: + case IKEV2_STATE_CLOSING: + break; + default: + ikestat_inc(env, ikes_sa_established_failures); + break; + } + break; + } + } } void diff --git a/sbin/iked/types.h b/sbin/iked/types.h index 14f5ca57b27..d4fc55cba76 100644 --- a/sbin/iked/types.h +++ b/sbin/iked/types.h @@ -1,4 +1,4 @@ -/* $OpenBSD: types.h,v 1.50 2022/07/22 15:53:33 tobhe Exp $ */ +/* $OpenBSD: types.h,v 1.51 2022/09/19 20:54:02 tobhe Exp $ */ /* * Copyright (c) 2019 Tobias Heider @@ -130,7 +130,8 @@ enum imsg_type { IMSG_AUTH, IMSG_PRIVKEY, IMSG_PUBKEY, - IMSG_CTL_SHOW_CERTSTORE + IMSG_CTL_SHOW_CERTSTORE, + IMSG_CTL_SHOW_STATS }; enum privsep_procid { diff --git a/usr.sbin/ikectl/ikectl.c b/usr.sbin/ikectl/ikectl.c index 6ba3b25ebe3..cc10c628b50 100644 --- a/usr.sbin/ikectl/ikectl.c +++ b/usr.sbin/ikectl/ikectl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikectl.c,v 1.27 2021/11/21 22:44:08 tobhe Exp $ */ +/* $OpenBSD: ikectl.c,v 1.28 2022/09/19 20:54:02 tobhe Exp $ */ /* * Copyright (c) 2007-2013 Reyk Floeter @@ -49,6 +49,7 @@ void monitor_id(struct imsg *); int monitor(struct imsg *); int show_string(struct imsg *); +int show_stats(struct imsg *, int); int ca_opt(struct parse_result *); @@ -303,6 +304,10 @@ main(int argc, char *argv[]) imsg_compose(ibuf, IMSG_CTL_SHOW_SA, 0, 0, -1, NULL, 0); done = 0; break; + case SHOW_STATS: + imsg_compose(ibuf, IMSG_CTL_SHOW_STATS, 0, 0, -1, NULL, 0); + done = 0; + break; case SHOW_CERTSTORE: imsg_compose(ibuf, IMSG_CTL_SHOW_CERTSTORE, 0, 0, -1, NULL, 0); done = 0; @@ -354,6 +359,9 @@ main(int argc, char *argv[]) case MONITOR: done = monitor(&imsg); break; + case SHOW_STATS: + done = show_stats(&imsg, quiet); + break; case SHOW_SA: case SHOW_CERTSTORE: done = show_string(&imsg); @@ -421,3 +429,55 @@ show_string(struct imsg *imsg) return (done); } + +static char * +plural(u_int64_t n) +{ + return (n != 1 ? "s" : ""); +} + +/* + * Dump IKE statistics structure. + */ +int +show_stats(struct imsg *imsg, int quiet) +{ + struct iked_stats *stat; + int done = 1; + + if (IMSG_DATA_SIZE(imsg) != sizeof(*stat)) + return (done); + stat = imsg->data; + printf("ike:\n"); +#define p(f, m) if (stat->f || !quiet) \ + printf(m, stat->f, plural(stat->f)) + + p(ikes_sa_created, "\t%llu IKE SA%s created\n"); + p(ikes_sa_established_total, "\t%llu IKE SA%s established\n"); + p(ikes_sa_established_current, "\t%llu IKE SA%s currently established\n"); + p(ikes_sa_established_failures, "\t%llu IKE SA%s failed to establish\n"); + p(ikes_sa_proposals_negotiate_failures, "\t%llu failed proposal negotiation%s\n"); + p(ikes_sa_rekeyed, "\t%llu IKE SA%s rekeyed\n"); + p(ikes_sa_removed, "\t%llu IKE SA%s removed\n"); + p(ikes_csa_created, "\t%llu Child SA%s created\n"); + p(ikes_csa_removed, "\t%llu Child SA%s removed\n"); + p(ikes_msg_sent, "\t%llu message%s sent\n"); + p(ikes_msg_send_failures, "\t%llu message%s could not be sent\n"); + p(ikes_msg_rcvd, "\t%llu message%s received\n"); + p(ikes_msg_rcvd_dropped, "\t%llu message%s dropped\n"); + p(ikes_msg_rcvd_busy, "\t%llu request%s dropped, response being worked on\n"); + p(ikes_retransmit_response, "\t%llu response%s retransmitted\n"); + p(ikes_retransmit_request, "\t%llu request%s retransmitted\n"); + p(ikes_retransmit_limit, "\t%llu request%s timed out\n"); + p(ikes_frag_sent, "\t%llu fragment%s sent\n"); + p(ikes_frag_send_failures, "\t%llu fragment%s could not be sent\n"); + p(ikes_frag_rcvd, "\t%llu fragment%s received\n"); + p(ikes_frag_rcvd_drop, "\t%llu fragment%s dropped\n"); + p(ikes_frag_reass_ok, "\t%llu fragment%s reassembled\n"); + p(ikes_frag_reass_drop, "\t%llu fragment%s could not be reassembled\n"); + p(ikes_update_addresses_sent, "\t%llu update addresses request%s sent\n"); + p(ikes_dpd_sent, "\t%llu dpd request%s sent\n"); + p(ikes_keepalive_sent, "\t%llu keepalive message%s sent\n"); +#undef p + return (done); +} diff --git a/usr.sbin/ikectl/parser.c b/usr.sbin/ikectl/parser.c index 008f986ba6f..008bff43483 100644 --- a/usr.sbin/ikectl/parser.c +++ b/usr.sbin/ikectl/parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.c,v 1.20 2021/11/21 22:44:08 tobhe Exp $ */ +/* $OpenBSD: parser.c,v 1.21 2022/09/19 20:54:02 tobhe Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter @@ -215,6 +215,7 @@ static const struct token t_show[] = { { KEYWORD, "ca", SHOW_CA, t_show_ca }, { KEYWORD, "sa", SHOW_SA, NULL }, { KEYWORD, "certstore", SHOW_CERTSTORE,NULL }, + { KEYWORD, "stats", SHOW_STATS, NULL }, { ENDTOKEN, "", NONE, NULL } }; diff --git a/usr.sbin/ikectl/parser.h b/usr.sbin/ikectl/parser.h index cd20e793fef..2e06e357a95 100644 --- a/usr.sbin/ikectl/parser.h +++ b/usr.sbin/ikectl/parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.h,v 1.17 2021/11/21 22:44:08 tobhe Exp $ */ +/* $OpenBSD: parser.h,v 1.18 2022/09/19 20:54:02 tobhe Exp $ */ /* * Copyright (c) 2007-2013 Reyk Floeter @@ -57,7 +57,8 @@ enum actions { SHOW_CA_CERTIFICATES, SHOW_SA, RESET_ID, - SHOW_CERTSTORE + SHOW_CERTSTORE, + SHOW_STATS }; struct parse_result { -- 2.20.1