sync with OpenBSD -current

This commit is contained in:
purplerain 2024-09-15 18:29:36 +00:00
parent 9f8f4295e0
commit 51a5102224
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
38 changed files with 2285 additions and 1213 deletions

View file

@ -1,4 +1,4 @@
/* $OpenBSD: radiusd_ipcp.c,v 1.14 2024/08/27 06:06:14 florian Exp $ */
/* $OpenBSD: radiusd_ipcp.c,v 1.17 2024/09/15 05:31:23 yasuoka Exp $ */
/*
* Copyright (c) 2024 Internet Initiative Japan Inc.
@ -122,8 +122,10 @@ struct module_ipcp_dae {
struct sockaddr_in6 sin6;
} nas_addr;
struct event ev_sock;
struct event ev_reqs;
TAILQ_ENTRY(module_ipcp_dae) next;
TAILQ_HEAD(, assigned_ipv4) reqs;
int ninflight;
};
struct module_ipcp {
@ -178,6 +180,8 @@ struct assigned_ipv4
struct in_addr);
static struct assigned_ipv4
*ipcp_ipv4_find(struct module_ipcp *, struct in_addr);
static void ipcp_ipv4_delete(struct module_ipcp *,
struct assigned_ipv4 *, const char *);
static void ipcp_ipv4_release(struct module_ipcp *,
struct assigned_ipv4 *);
static int assigned_ipv4_compar(struct assigned_ipv4 *,
@ -198,6 +202,7 @@ static void ipcp_dae_send_disconnect_request(struct assigned_ipv4 *);
static void ipcp_dae_request_on_timeout(int, short, void *);
static void ipcp_dae_on_event(int, short, void *);
static void ipcp_dae_reset_request(struct assigned_ipv4 *);
static void ipcp_dae_send_pending_requests(int, short, void *);
static struct ipcp_address
*parse_address_range(const char *);
static const char
@ -303,18 +308,20 @@ ipcp_start(void *ctx)
TAILQ_FOREACH(dae, &self->daes, next) {
if ((sock = socket(dae->nas_addr.sin4.sin_family,
SOCK_DGRAM, IPPROTO_UDP)) == -1) {
log_warn("could not start dae: %s", strerror(errno));
log_warn("%s: could not start dae: socket()", __func__);
return;
}
if (connect(sock, (struct sockaddr *)&dae->nas_addr,
dae->nas_addr.sin4.sin_len) == -1) {
log_warn("could not start dae: %s", strerror(errno));
log_warn("%s: could not start dae: connect()",
__func__);
return;
}
dae->sock = sock;
event_set(&dae->ev_sock, sock, EV_READ | EV_PERSIST,
ipcp_dae_on_event, dae);
event_add(&dae->ev_sock, NULL);
evtimer_set(&dae->ev_reqs, ipcp_dae_send_pending_requests, dae);
}
module_send_message(self->base, IMSG_OK, NULL);
@ -334,6 +341,8 @@ ipcp_stop(void *ctx)
close(dae->sock);
dae->sock = -1;
}
if (evtimer_pending(&dae->ev_reqs, NULL))
event_del(&dae->ev_reqs);
}
if (evtimer_pending(&self->ev_timer, NULL))
evtimer_del(&self->ev_timer);
@ -624,10 +633,14 @@ ipcp_dispatch_control(void *ctx, struct imsg *imsg)
freezero(dump ,dumpsiz);
break;
case IMSG_RADIUSD_MODULE_IPCP_DISCONNECT:
case IMSG_RADIUSD_MODULE_IPCP_DELETE:
if (datalen < sizeof(unsigned)) {
log_warn("%s: received "
"IMSG_RADIUSD_MODULE_IPCP_DISCONNECT message size "
"is wrong", __func__);
"%s message size is wrong", __func__,
(imsg->hdr.type ==
IMSG_RADIUSD_MODULE_IPCP_DISCONNECT)
? "IMSG_RADIUSD_MODULE_IPCP_DISCONNECT"
: "IMSG_RADIUSD_MODULE_IPCP_DELETE");
goto fail;
}
seq = *(unsigned *)imsg->data;
@ -640,12 +653,19 @@ ipcp_dispatch_control(void *ctx, struct imsg *imsg)
}
if (assign == NULL) {
cause = "session not found";
log_warnx("Disconnect seq=%u requested, but the "
"session is not found", seq);
log_warnx("%s seq=%u requested, but the "
"session is not found",
(imsg->hdr.type ==
IMSG_RADIUSD_MODULE_IPCP_DISCONNECT)? "Disconnect"
: "Delete", seq);
module_imsg_compose(self->base, IMSG_NG,
imsg->hdr.peerid, 0, -1, cause, strlen(cause) + 1);
}
else {
} else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_IPCP_DELETE) {
log_info("Delete seq=%u by request", assign->seq);
ipcp_ipv4_delete(self, assign, "By control");
module_imsg_compose(self->base, IMSG_OK,
imsg->hdr.peerid, 0, -1, NULL, 0);
} else {
if (assign->dae == NULL)
log_warnx("Disconnect seq=%u requested, but "
"DAE is not configured", assign->seq);
@ -1059,10 +1079,12 @@ ipcp_accounting_request(void *ctx, u_int q_id, const u_char *pkt,
!IN6_ARE_ADDR_EQUAL(&assign->nas_ipv6, &nas_ipv6) ||
strcmp(assign->nas_id, nas_id) != 0)
continue;
log_info("Delete record for %s", inet_ntop(AF_INET,
&assign->ipv4, buf, sizeof(buf)));
ipcp_del_db(self, assign);
ipcp_ipv4_release(self, assign);
log_info("q=%u Delete record for %s", q_id,
inet_ntop(AF_INET, &assign->ipv4, buf,
sizeof(buf)));
ipcp_ipv4_delete(self, assign,
(type == RADIUS_ACCT_STATUS_TYPE_ACCT_ON)
? "Receive Acct-On" : "Receive Acct-Off");
}
return;
}
@ -1144,9 +1166,9 @@ ipcp_accounting_request(void *ctx, u_int q_id, const u_char *pkt,
if (ipcp_notice_startstop(self, assign, 1, NULL) != 0)
goto fail;
log_info("Start seq=%u user=%s duration=%dsec session=%s "
"tunnel=%s from=%s auth=%s ip=%s", assign->seq,
assign->user->name, delay, assign->session_id,
log_info("q=%u Start seq=%u user=%s duration=%dsec "
"session=%s tunnel=%s from=%s auth=%s ip=%s", q_id,
assign->seq, assign->user->name, delay, assign->session_id,
assign->tun_type, print_addr((struct sockaddr *)
&assign->tun_client, buf1, sizeof(buf1)),
assign->auth_method, inet_ntop(AF_INET, &addr4, buf,
@ -1180,10 +1202,10 @@ ipcp_accounting_request(void *ctx, u_int q_id, const u_char *pkt,
strlcpy(stat.cause, radius_terminate_cause_string(uval),
sizeof(stat.cause));
log_info("Stop seq=%u user=%s duration=%lldsec session=%s "
"tunnel=%s from=%s auth=%s ip=%s datain=%"PRIu64"bytes,%"
PRIu32"packets dataout=%"PRIu64"bytes,%"PRIu32"packets "
"cause=\"%s\"",
log_info("q=%u Stop seq=%u user=%s duration=%lldsec "
"session=%s tunnel=%s from=%s auth=%s ip=%s "
"datain=%"PRIu64"bytes,%" PRIu32"packets dataout=%"PRIu64
"bytes,%"PRIu32"packets cause=\"%s\"", q_id,
assign->seq, assign->user->name, dur.tv_sec,
assign->session_id, assign->tun_type, print_addr(
(struct sockaddr *)&assign->tun_client, buf1, sizeof(buf1)),
@ -1254,6 +1276,20 @@ ipcp_ipv4_find(struct module_ipcp *self, struct in_addr ina)
return (ret);
}
void
ipcp_ipv4_delete(struct module_ipcp *self, struct assigned_ipv4 *assign,
const char *cause)
{
static struct radiusd_ipcp_statistics stat = { 0 };
memset(stat.cause, 0, sizeof(stat.cause));
strlcpy(stat.cause, cause, sizeof(stat.cause));
ipcp_del_db(self, assign);
ipcp_notice_startstop(self, assign, 0, &stat);
ipcp_ipv4_release(self, assign);
}
void
ipcp_ipv4_release(struct module_ipcp *self, struct assigned_ipv4 *assign)
{
@ -1567,22 +1603,27 @@ ipcp_dae_send_disconnect_request(struct assigned_ipv4 *assign)
radius_set_accounting_request_authenticator(reqpkt,
assign->dae->secret);
assign->dae_reqpkt = reqpkt;
TAILQ_INSERT_TAIL(&assign->dae->reqs, assign, dae_next);
}
if (assign->dae_ntry == 0) {
if (assign->dae->ninflight >= RADIUSD_IPCP_DAE_MAX_INFLIGHT)
return;
log_info("Sending Disconnect-Request seq=%u to %s",
assign->seq, print_addr((struct sockaddr *)
&assign->dae->nas_addr, buf, sizeof(buf)));
TAILQ_INSERT_TAIL(&assign->dae->reqs, assign, dae_next);
}
if (radius_send(assign->dae->sock, assign->dae_reqpkt, 0) < 0)
log_warn("%s: sendto: %m", __func__);
tv.tv_sec = dae_request_timeouts[assign->dae_ntry++];
tv.tv_sec = dae_request_timeouts[assign->dae_ntry];
tv.tv_usec = 0;
evtimer_set(&assign->dae_evtimer, ipcp_dae_request_on_timeout, assign);
evtimer_add(&assign->dae_evtimer, &tv);
if (assign->dae_ntry == 0)
assign->dae->ninflight++;
assign->dae_ntry++;
}
void
@ -1625,7 +1666,7 @@ ipcp_dae_on_event(int fd, short ev, void *ctx)
if ((radres = radius_recv(dae->sock, 0)) == NULL) {
if (errno == EAGAIN)
return;
log_warn("Failed to receive from %s", print_addr(
log_warn("%s: Failed to receive from %s", __func__, print_addr(
(struct sockaddr *)&dae->nas_addr, buf, sizeof(buf)));
return;
}
@ -1634,16 +1675,16 @@ ipcp_dae_on_event(int fd, short ev, void *ctx)
break;
}
if (assign == NULL) {
log_warnx("Received RADIUS packet from %s has unknown id=%d",
print_addr((struct sockaddr *)&dae->nas_addr, buf,
sizeof(buf)), radius_get_id(radres));
log_warnx("%s: Received RADIUS packet from %s has unknown "
"id=%d", __func__, print_addr((struct sockaddr *)
&dae->nas_addr, buf, sizeof(buf)), radius_get_id(radres));
goto out;
}
radius_set_request_packet(radres, assign->dae_reqpkt);
if ((radius_check_response_authenticator(radres, dae->secret)) != 0) {
log_warnx("Received RADIUS packet for seq=%u from %s has a bad "
"authenticator", assign->seq, print_addr(
log_warnx("%s: Received RADIUS packet for seq=%u from %s has "
"a bad authenticator", __func__, assign->seq, print_addr(
(struct sockaddr *)&dae->nas_addr, buf,
sizeof(buf)));
goto out;
@ -1667,13 +1708,13 @@ ipcp_dae_on_event(int fd, short ev, void *ctx)
&dae->nas_addr, buf, sizeof(buf)), cause);
break;
case RADIUS_CODE_DISCONNECT_NAK:
log_warnx("Received Disconnect-NAK for seq=%u from %s%s",
log_info("Received Disconnect-NAK for seq=%u from %s%s",
assign->seq, print_addr((struct sockaddr *)
&dae->nas_addr, buf, sizeof(buf)), cause);
break;
default:
log_warn("Received unknown code=%d for id=%u from %s",
code, assign->seq, print_addr((struct sockaddr *)
log_warn("%s: Received unknown code=%d for id=%u from %s",
__func__, code, assign->seq, print_addr((struct sockaddr *)
&dae->nas_addr, buf, sizeof(buf)));
break;
}
@ -1700,10 +1741,16 @@ void
ipcp_dae_reset_request(struct assigned_ipv4 *assign)
{
struct radiusctl_client *client, *clientt;
const struct timeval zero = { 0, 0 };
if (assign->dae != NULL) {
if (assign->dae_ntry > 0)
if (assign->dae_reqpkt != NULL)
TAILQ_REMOVE(&assign->dae->reqs, assign, dae_next);
if (assign->dae_ntry > 0) {
assign->dae->ninflight--;
if (!evtimer_pending(&assign->dae->ev_reqs, NULL))
evtimer_add(&assign->dae->ev_reqs, &zero);
}
}
if (assign->dae_reqpkt != NULL)
radius_delete_packet(assign->dae_reqpkt);
@ -1717,6 +1764,23 @@ ipcp_dae_reset_request(struct assigned_ipv4 *assign)
assign->dae_ntry = 0;
}
void
ipcp_dae_send_pending_requests(int fd, short ev, void *ctx)
{
struct module_ipcp_dae *dae = ctx;
struct module_ipcp *self = dae->ipcp;
struct assigned_ipv4 *assign, *assignt;
ipcp_update_time(self);
TAILQ_FOREACH_SAFE(assign, &dae->reqs, dae_next, assignt) {
if (dae->ninflight >= RADIUSD_IPCP_DAE_MAX_INFLIGHT)
break;
if (assign->dae_ntry == 0) /* pending */
ipcp_dae_send_disconnect_request(assign);
}
}
/***********************************************************************
* Miscellaneous functions
***********************************************************************/