[PATCH 4/7] RADIUS DAS: Separate request processing from the UDP socket handler

Seb Adamski seb at bionic.network
Sun Oct 18 23:38:11 PDT 2026


Move the processing of a received Disconnect-Request or CoA-Request out
of radius_das_receive() into a new function, radius_das_process(). It
takes the parsed request and the shared secret to use and returns the
response, or NULL when the request is dropped. It contains the
authenticator and Message-Authenticator validation, the Event-Timestamp
check, the dispatch to the Disconnect-Request and CoA-Request handlers,
and the completion of the response.

The UDP socket handler keeps recvfrom(), the client address filter, the
parsing and the message dump, and sendto(), and passes the shared
secret of the DAS listener. The shared secret is a parameter so that the
function can be used for requests that arrive over another transport
with a different shared secret.

This is a refactor with no change in behavior; the log messages are
unchanged.

Signed-off-by: Seb Adamski <seb at bionic.network>
---
 src/radius/radius_das.c | 143 ++++++++++++++++++++++------------------
 src/radius/radius_das.h |  23 +++++++
 2 files changed, 102 insertions(+), 64 deletions(-)

diff --git a/src/radius/radius_das.c b/src/radius/radius_das.c
index 02e9e9f6f..5210bf27b 100644
--- a/src/radius/radius_das.c
+++ b/src/radius/radius_das.c
@@ -390,64 +390,24 @@ fail:
 }
 
 
-static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
+struct radius_msg * radius_das_process(struct radius_das_data *das,
+				       struct radius_msg *msg,
+				       const u8 *shared_secret,
+				       size_t shared_secret_len,
+				       const char *abuf, int from_port)
 {
-	struct radius_das_data *das = eloop_ctx;
-	u8 buf[1500];
-	union {
-		struct sockaddr_storage ss;
-		struct sockaddr_in sin;
-#ifdef CONFIG_IPV6
-		struct sockaddr_in6 sin6;
-#endif /* CONFIG_IPV6 */
-	} from;
-	char abuf[50];
-	int from_port = 0;
-	socklen_t fromlen;
-	int len;
-	struct radius_msg *msg, *reply = NULL;
+	struct radius_msg *reply = NULL;
 	struct radius_hdr *hdr;
-	struct wpabuf *rbuf;
 	u32 val;
 	int res;
 	struct os_time now;
 
-	fromlen = sizeof(from);
-	len = recvfrom(sock, buf, sizeof(buf), 0,
-		       (struct sockaddr *) &from.ss, &fromlen);
-	if (len < 0) {
-		wpa_printf(MSG_ERROR, "DAS: recvfrom: %s", strerror(errno));
-		return;
-	}
-
-	os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
-	from_port = ntohs(from.sin.sin_port);
-
-	wpa_printf(MSG_DEBUG, "DAS: Received %d bytes from %s:%d",
-		   len, abuf, from_port);
-	if (das->client_addr.u.v4.s_addr &&
-	    das->client_addr.u.v4.s_addr != from.sin.sin_addr.s_addr) {
-		wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client");
-		return;
-	}
-
-	msg = radius_msg_parse(buf, len);
-	if (msg == NULL) {
-		wpa_printf(MSG_DEBUG, "DAS: Parsing incoming RADIUS packet "
-			   "from %s:%d failed", abuf, from_port);
-		return;
-	}
-
-	if (wpa_debug_level <= MSG_MSGDUMP)
-		radius_msg_dump(msg);
-
-	if (radius_msg_verify_das_req(msg, das->shared_secret,
-				       das->shared_secret_len,
-				       das->require_message_authenticator)) {
+	if (radius_msg_verify_das_req(msg, shared_secret, shared_secret_len,
+				      das->require_message_authenticator)) {
 		wpa_printf(MSG_DEBUG,
 			   "DAS: Invalid authenticator or Message-Authenticator in packet from %s:%d - drop",
 			   abuf, from_port);
-		goto fail;
+		return NULL;
 	}
 
 	os_get_time(&now);
@@ -462,12 +422,12 @@ static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
 				   "packet from %s:%d - drop",
 				   timestamp, (unsigned int) now.sec,
 				   abuf, from_port);
-			goto fail;
+			return NULL;
 		}
 	} else if (das->require_event_timestamp) {
 		wpa_printf(MSG_DEBUG, "DAS: Missing Event-Timestamp in packet "
 			   "from %s:%d - drop", abuf, from_port);
-		goto fail;
+		return NULL;
 	}
 
 	hdr = radius_msg_get_hdr(msg);
@@ -494,7 +454,8 @@ static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
 					 RADIUS_ATTR_PROXY_STATE) < 0) {
 			wpa_printf(MSG_INFO,
 				   "DAS: Failed to copy Proxy-State attributes - drop");
-			goto fail;
+			radius_msg_free(reply);
+			return NULL;
 		}
 
 		if (!radius_msg_add_attr_int32(reply,
@@ -504,28 +465,82 @@ static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
 				   "Event-Timestamp attribute");
 		}
 
-		if (radius_msg_finish_das_resp(reply, das->shared_secret,
-					       das->shared_secret_len, hdr) <
-		    0) {
+		if (radius_msg_finish_das_resp(reply, shared_secret,
+					       shared_secret_len, hdr) < 0) {
 			wpa_printf(MSG_DEBUG, "DAS: Failed to add "
 				   "Message-Authenticator attribute");
 		}
 
 		if (wpa_debug_level <= MSG_MSGDUMP)
 			radius_msg_dump(reply);
+	}
 
-		rbuf = radius_msg_get_buf(reply);
-		res = sendto(das->sock, wpabuf_head(rbuf),
-			     wpabuf_len(rbuf), 0,
-			     (struct sockaddr *) &from.ss, fromlen);
-		if (res < 0) {
-			wpa_printf(MSG_ERROR, "DAS: sendto(to %s:%d): %s",
-				   abuf, from_port, strerror(errno));
-		}
+	return reply;
+}
+
+
+static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
+{
+	struct radius_das_data *das = eloop_ctx;
+	u8 buf[1500];
+	union {
+		struct sockaddr_storage ss;
+		struct sockaddr_in sin;
+#ifdef CONFIG_IPV6
+		struct sockaddr_in6 sin6;
+#endif /* CONFIG_IPV6 */
+	} from;
+	char abuf[50];
+	int from_port = 0;
+	socklen_t fromlen;
+	int len;
+	struct radius_msg *msg, *reply;
+	struct wpabuf *rbuf;
+	int res;
+
+	fromlen = sizeof(from);
+	len = recvfrom(sock, buf, sizeof(buf), 0,
+		       (struct sockaddr *) &from.ss, &fromlen);
+	if (len < 0) {
+		wpa_printf(MSG_ERROR, "DAS: recvfrom: %s", strerror(errno));
+		return;
 	}
 
-fail:
+	os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
+	from_port = ntohs(from.sin.sin_port);
+
+	wpa_printf(MSG_DEBUG, "DAS: Received %d bytes from %s:%d",
+		   len, abuf, from_port);
+	if (das->client_addr.u.v4.s_addr &&
+	    das->client_addr.u.v4.s_addr != from.sin.sin_addr.s_addr) {
+		wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client");
+		return;
+	}
+
+	msg = radius_msg_parse(buf, len);
+	if (msg == NULL) {
+		wpa_printf(MSG_DEBUG, "DAS: Parsing incoming RADIUS packet "
+			   "from %s:%d failed", abuf, from_port);
+		return;
+	}
+
+	if (wpa_debug_level <= MSG_MSGDUMP)
+		radius_msg_dump(msg);
+
+	reply = radius_das_process(das, msg, das->shared_secret,
+				   das->shared_secret_len, abuf, from_port);
 	radius_msg_free(msg);
+	if (!reply)
+		return;
+
+	rbuf = radius_msg_get_buf(reply);
+	res = sendto(das->sock, wpabuf_head(rbuf), wpabuf_len(rbuf), 0,
+		     (struct sockaddr *) &from.ss, fromlen);
+	if (res < 0) {
+		wpa_printf(MSG_ERROR, "DAS: sendto(to %s:%d): %s",
+			   abuf, from_port, strerror(errno));
+	}
+
 	radius_msg_free(reply);
 }
 
diff --git a/src/radius/radius_das.h b/src/radius/radius_das.h
index 233d662f6..e7a611586 100644
--- a/src/radius/radius_das.h
+++ b/src/radius/radius_das.h
@@ -10,6 +10,7 @@
 #define RADIUS_DAS_H
 
 struct radius_das_data;
+struct radius_msg;
 
 enum radius_das_res {
 	RADIUS_DAS_SUCCESS,
@@ -60,4 +61,26 @@ radius_das_init(struct radius_das_conf *conf);
 
 void radius_das_deinit(struct radius_das_data *data);
 
+/**
+ * radius_das_process - Process a received Disconnect-Request or CoA-Request
+ * @das: DAS context from radius_das_init()
+ * @msg: The received request
+ * @shared_secret: Shared secret with the sender of the request
+ * @shared_secret_len: Length of shared_secret in octets
+ * @abuf: Address of the sender as text for log messages
+ * @from_port: Port of the sender for log messages
+ * Returns: The response to send (to be freed with radius_msg_free()) or %NULL
+ *	if the request is dropped
+ *
+ * The request is validated with the shared secret (Request Authenticator,
+ * Message-Authenticator, and Event-Timestamp) and passed to the disconnect or
+ * CoA callback. The response is authenticated with the same shared secret.
+ * The caller owns msg.
+ */
+struct radius_msg * radius_das_process(struct radius_das_data *das,
+				       struct radius_msg *msg,
+				       const u8 *shared_secret,
+				       size_t shared_secret_len,
+				       const char *abuf, int from_port);
+
 #endif /* RADIUS_DAS_H */
-- 
2.54.0 (Apple Git-157)





More information about the Hostap mailing list