From c0127aec83708e9113ef41857d1e5b1ece5773d7 Mon Sep 17 00:00:00 2001 From: yasuoka Date: Mon, 22 Jul 2024 09:39:23 +0000 Subject: [PATCH] Modify ipcp module to return a result for IMSG_RADIUSD_MODULE_IPCP_DISCONNECT and radiusctl to handle the result. --- usr.sbin/radiusctl/radiusctl.c | 11 ++++++-- usr.sbin/radiusd/radiusd_ipcp.c | 48 +++++++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/usr.sbin/radiusctl/radiusctl.c b/usr.sbin/radiusctl/radiusctl.c index 9caaabe181a..d3bc45eb866 100644 --- a/usr.sbin/radiusctl/radiusctl.c +++ b/usr.sbin/radiusctl/radiusctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: radiusctl.c,v 1.10 2024/07/14 11:12:32 yasuoka Exp $ */ +/* $OpenBSD: radiusctl.c,v 1.11 2024/07/22 09:39:23 yasuoka Exp $ */ /* * Copyright (c) 2015 YASUOKA Masahiko * @@ -180,7 +180,6 @@ main(int argc, char *argv[]) iov[niov++].iov_len = sizeof(res->session_seq); imsg_composev(&ibuf, IMSG_RADIUSD_MODULE_IPCP_DISCONNECT, 0, 0, -1, iov, niov); - done = 1; break; } while (ibuf.w.queued) { @@ -200,6 +199,7 @@ main(int argc, char *argv[]) case IPCP_SHOW: case IPCP_DUMP: case IPCP_MONITOR: + case IPCP_DISCONNECT: done = ipcp_handle_imsg(res, &imsg, cnt++); break; default: @@ -625,6 +625,13 @@ ipcp_handle_imsg(struct parse_result *res, struct imsg *imsg, int cnt) datalen = imsg->hdr.len - IMSG_HEADER_SIZE; switch (imsg->hdr.type) { + case IMSG_OK: + if (datalen > 0 && *((char *)imsg->data + datalen - 1) == '\0') + fprintf(stderr, "OK: %s\n", (char *)imsg->data); + else + fprintf(stderr, "OK\n"); + done = 1; + break; case IMSG_NG: if (datalen > 0 && *((char *)imsg->data + datalen - 1) == '\0') fprintf(stderr, "error: %s\n", (char *)imsg->data); diff --git a/usr.sbin/radiusd/radiusd_ipcp.c b/usr.sbin/radiusd/radiusd_ipcp.c index d007067ecf0..4f34d2972fd 100644 --- a/usr.sbin/radiusd/radiusd_ipcp.c +++ b/usr.sbin/radiusd/radiusd_ipcp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: radiusd_ipcp.c,v 1.5 2024/07/17 11:31:46 yasuoka Exp $ */ +/* $OpenBSD: radiusd_ipcp.c,v 1.6 2024/07/22 09:39:23 yasuoka Exp $ */ /* * Copyright (c) 2024 Internet Initiative Japan Inc. @@ -68,6 +68,11 @@ struct user { char name[0]; }; +struct radiusctl_client { + int peerid; + TAILQ_ENTRY(radiusctl_client) entry; +}; + struct module_ipcp_dae; struct assigned_ipv4 { @@ -98,6 +103,7 @@ struct assigned_ipv4 { TAILQ_ENTRY(assigned_ipv4) dae_next; int dae_ntry; struct event dae_evtimer; + TAILQ_HEAD(, radiusctl_client) dae_clients; }; struct module_ipcp_ctrlconn { @@ -517,6 +523,7 @@ ipcp_config_set(void *ctx, const char *name, int argc, char * const * argv) *dae0 = dae; TAILQ_INIT(&dae0->reqs); TAILQ_INSERT_TAIL(&module->daes, dae0, next); + dae0->ipcp = module; } else if (strcmp(name, "_debug") == 0) log_init(1); else if (strncmp(name, "_", 1) == 0) @@ -544,6 +551,8 @@ ipcp_dispatch_control(void *ctx, struct imsg *imsg) size_t dumpsiz; u_int datalen; unsigned seq; + struct radiusctl_client *client; + const char *cause; datalen = imsg->hdr.len - IMSG_HEADER_SIZE; switch (imsg->hdr.type) { @@ -616,9 +625,13 @@ ipcp_dispatch_control(void *ctx, struct imsg *imsg) if (assign->seq == seq) break; } - if (assign == NULL) + if (assign == NULL) { + cause = "session not found"; log_warnx("Disconnect seq=%u requested, but the " "session is not found", seq); + module_imsg_compose(self->base, IMSG_NG, + imsg->hdr.peerid, 0, -1, cause, strlen(cause) + 1); + } else { if (assign->dae == NULL) log_warnx("Disconnect seq=%u requested, but " @@ -626,9 +639,18 @@ ipcp_dispatch_control(void *ctx, struct imsg *imsg) else { log_info("Disconnect seq=%u requested", assign->seq); + if ((client = calloc(1, sizeof(struct + radiusctl_client))) == NULL) { + log_warn("%s: calloc: %m", + __func__); + goto fail; + } + client->peerid = imsg->hdr.peerid; if (assign->dae_ntry == 0) ipcp_dae_send_disconnect_request( assign); + TAILQ_INSERT_TAIL(&assign->dae_clients, + client, entry); } } break; @@ -1189,6 +1211,7 @@ ipcp_ipv4_assign(struct module_ipcp *self, struct user *user, ip->authtime = self->uptime; RB_INSERT(assigned_ipv4_tree, &self->ipv4s, ip); TAILQ_INSERT_TAIL(&user->ipv4s, ip, next); + TAILQ_INIT(&ip->dae_clients); self->nsessions++; ip->seq = self->seq++; @@ -1562,12 +1585,14 @@ void ipcp_dae_on_event(int fd, short ev, void *ctx) { struct module_ipcp_dae *dae = ctx; + struct module_ipcp *self = dae->ipcp; RADIUS_PACKET *radres = NULL; int code; uint32_t u32; struct assigned_ipv4 *assign; char buf[80], causestr[80]; const char *cause = ""; + struct radiusctl_client *client; if ((ev & EV_READ) == 0) return; @@ -1627,6 +1652,19 @@ ipcp_dae_on_event(int fd, short ev, void *ctx) &dae->nas_addr, buf, sizeof(buf))); break; } + + TAILQ_FOREACH(client, &assign->dae_clients, entry) { + if (*cause != '\0') + module_imsg_compose(self->base, + (code == RADIUS_CODE_DISCONNECT_ACK) + ? IMSG_OK : IMSG_NG, client->peerid, 0, -1, + cause + 1, strlen(cause + 1) + 1); + else + module_imsg_compose(self->base, + (code == RADIUS_CODE_DISCONNECT_ACK) + ? IMSG_OK : IMSG_NG, client->peerid, 0, -1, + NULL, 0); + } ipcp_dae_reset_request(assign); out: if (radres != NULL) @@ -1636,6 +1674,8 @@ ipcp_dae_on_event(int fd, short ev, void *ctx) void ipcp_dae_reset_request(struct assigned_ipv4 *assign) { + struct radiusctl_client *client, *clientt; + if (assign->dae != NULL) { if (assign->dae_ntry > 0) TAILQ_REMOVE(&assign->dae->reqs, assign, dae_next); @@ -1645,6 +1685,10 @@ ipcp_dae_reset_request(struct assigned_ipv4 *assign) assign->dae_reqpkt = NULL; if (evtimer_pending(&assign->dae_evtimer, NULL)) evtimer_del(&assign->dae_evtimer); + TAILQ_FOREACH_SAFE(client, &assign->dae_clients, entry, clientt) { + TAILQ_REMOVE(&assign->dae_clients, client, entry); + free(client); + } assign->dae_ntry = 0; } -- 2.20.1