1 --- a/src/radius/radius_das.h
2 +++ b/src/radius/radius_das.h
3 @@ -44,6 +44,7 @@ struct radius_das_attrs {
4 struct radius_das_conf {
6 const u8 *shared_secret;
7 + const u8 *nas_identifier;
8 size_t shared_secret_len;
9 const struct hostapd_ip_addr *client_addr;
10 unsigned int time_window;
11 --- a/src/ap/hostapd.c
12 +++ b/src/ap/hostapd.c
13 @@ -1367,6 +1367,7 @@ static int hostapd_setup_bss(struct host
14 struct radius_das_conf das_conf;
15 os_memset(&das_conf, 0, sizeof(das_conf));
16 das_conf.port = conf->radius_das_port;
17 + das_conf.nas_identifier = conf->nas_identifier;
18 das_conf.shared_secret = conf->radius_das_shared_secret;
19 das_conf.shared_secret_len =
20 conf->radius_das_shared_secret_len;
21 --- a/src/radius/radius_das.c
22 +++ b/src/radius/radius_das.c
24 #include "utils/common.h"
25 #include "utils/eloop.h"
26 #include "utils/ip_addr.h"
27 +#include "utils/list.h"
29 #include "radius_das.h"
32 -struct radius_das_data {
33 +static struct dl_list das_ports = DL_LIST_HEAD_INIT(das_ports);
35 +struct radius_das_port {
36 + struct dl_list list;
37 + struct dl_list das_data;
43 +struct radius_das_data {
44 + struct dl_list list;
45 + struct radius_das_port *port;
48 size_t shared_secret_len;
49 struct hostapd_ip_addr client_addr;
50 unsigned int time_window;
51 @@ -378,56 +391,17 @@ fail:
55 -static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
57 +radius_das_receive_msg(struct radius_das_data *das, struct radius_msg *msg,
58 + struct sockaddr *from, socklen_t fromlen,
59 + char *abuf, int from_port)
61 - struct radius_das_data *das = eloop_ctx;
64 - struct sockaddr_storage ss;
65 - struct sockaddr_in sin;
67 - struct sockaddr_in6 sin6;
68 -#endif /* CONFIG_IPV6 */
74 - struct radius_msg *msg, *reply = NULL;
75 + struct radius_msg *reply = NULL;
76 struct radius_hdr *hdr;
83 - fromlen = sizeof(from);
84 - len = recvfrom(sock, buf, sizeof(buf), 0,
85 - (struct sockaddr *) &from.ss, &fromlen);
87 - wpa_printf(MSG_ERROR, "DAS: recvfrom: %s", strerror(errno));
91 - os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
92 - from_port = ntohs(from.sin.sin_port);
94 - wpa_printf(MSG_DEBUG, "DAS: Received %d bytes from %s:%d",
95 - len, abuf, from_port);
96 - if (das->client_addr.u.v4.s_addr &&
97 - das->client_addr.u.v4.s_addr != from.sin.sin_addr.s_addr) {
98 - wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client");
102 - msg = radius_msg_parse(buf, len);
104 - wpa_printf(MSG_DEBUG, "DAS: Parsing incoming RADIUS packet "
105 - "from %s:%d failed", abuf, from_port);
109 - if (wpa_debug_level <= MSG_MSGDUMP)
110 - radius_msg_dump(msg);
112 if (radius_msg_verify_das_req(msg, das->shared_secret,
113 das->shared_secret_len,
114 @@ -494,9 +468,8 @@ static void radius_das_receive(int sock,
115 radius_msg_dump(reply);
117 rbuf = radius_msg_get_buf(reply);
118 - res = sendto(das->sock, wpabuf_head(rbuf),
119 - wpabuf_len(rbuf), 0,
120 - (struct sockaddr *) &from.ss, fromlen);
121 + res = sendto(das->port->sock, wpabuf_head(rbuf),
122 + wpabuf_len(rbuf), 0, from, fromlen);
124 wpa_printf(MSG_ERROR, "DAS: sendto(to %s:%d): %s",
125 abuf, from_port, strerror(errno));
126 @@ -508,6 +481,72 @@ fail:
127 radius_msg_free(reply);
130 +static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
132 + struct radius_das_port *p = eloop_ctx;
133 + struct radius_das_data *das;
136 + struct sockaddr_storage ss;
137 + struct sockaddr_in sin;
139 + struct sockaddr_in6 sin6;
140 +#endif /* CONFIG_IPV6 */
142 + struct radius_msg *msg;
143 + size_t nasid_len = 0;
144 + u8 *nasid_buf = NULL;
151 + fromlen = sizeof(from);
152 + len = recvfrom(sock, buf, sizeof(buf), 0,
153 + (struct sockaddr *) &from.ss, &fromlen);
155 + wpa_printf(MSG_ERROR, "DAS: recvfrom: %s", strerror(errno));
159 + os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
160 + from_port = ntohs(from.sin.sin_port);
162 + msg = radius_msg_parse(buf, len);
164 + wpa_printf(MSG_DEBUG, "DAS: Parsing incoming RADIUS packet "
165 + "from %s:%d failed", abuf, from_port);
169 + wpa_printf(MSG_DEBUG, "DAS: Received %d bytes from %s:%d",
170 + len, abuf, from_port);
172 + if (wpa_debug_level <= MSG_MSGDUMP)
173 + radius_msg_dump(msg);
175 + radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
176 + &nasid_buf, &nasid_len, NULL);
177 + dl_list_for_each(das, &p->das_data, struct radius_das_data, list) {
178 + if (das->client_addr.u.v4.s_addr &&
179 + das->client_addr.u.v4.s_addr != from.sin.sin_addr.s_addr)
182 + if (das->nas_identifier && nasid_buf &&
183 + (nasid_len != os_strlen(das->nas_identifier) ||
184 + os_memcmp(das->nas_identifier, nasid_buf, nasid_len) != 0))
188 + radius_das_receive_msg(das, msg, (struct sockaddr *)&from.ss,
189 + fromlen, abuf, from_port);
193 + wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client");
197 static int radius_das_open_socket(int port)
199 @@ -533,6 +572,49 @@ static int radius_das_open_socket(int po
203 +static struct radius_das_port *
204 +radius_das_open_port(int port)
206 + struct radius_das_port *p;
208 + dl_list_for_each(p, &das_ports, struct radius_das_port, list) {
209 + if (p->port == port)
213 + p = os_zalloc(sizeof(*p));
217 + dl_list_init(&p->das_data);
219 + p->sock = radius_das_open_socket(port);
223 + if (eloop_register_read_sock(p->sock, radius_das_receive, p, NULL))
226 + dl_list_add(&das_ports, &p->list);
238 +static void radius_das_close_port(struct radius_das_port *p)
240 + dl_list_del(&p->list);
241 + eloop_unregister_read_sock(p->sock);
246 struct radius_das_data *
247 radius_das_init(struct radius_das_conf *conf)
249 @@ -553,6 +635,8 @@ radius_das_init(struct radius_das_conf *
250 das->ctx = conf->ctx;
251 das->disconnect = conf->disconnect;
252 das->coa = conf->coa;
253 + if (conf->nas_identifier)
254 + das->nas_identifier = os_strdup(conf->nas_identifier);
256 os_memcpy(&das->client_addr, conf->client_addr,
257 sizeof(das->client_addr));
258 @@ -565,19 +649,15 @@ radius_das_init(struct radius_das_conf *
260 das->shared_secret_len = conf->shared_secret_len;
262 - das->sock = radius_das_open_socket(conf->port);
263 - if (das->sock < 0) {
264 + das->port = radius_das_open_port(conf->port);
266 wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS "
268 radius_das_deinit(das);
272 - if (eloop_register_read_sock(das->sock, radius_das_receive, das, NULL))
274 - radius_das_deinit(das);
277 + dl_list_add(&das->port->das_data, &das->list);
281 @@ -588,11 +668,14 @@ void radius_das_deinit(struct radius_das
285 - if (das->sock >= 0) {
286 - eloop_unregister_read_sock(das->sock);
289 + dl_list_del(&das->list);
291 + if (dl_list_empty(&das->port->das_data))
292 + radius_das_close_port(das->port);
295 + os_free(das->nas_identifier);
296 os_free(das->shared_secret);