sync with OpenBSD -current
This commit is contained in:
parent
9f8f4295e0
commit
51a5102224
38 changed files with 2285 additions and 1213 deletions
|
@ -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
|
||||
***********************************************************************/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue