Bug Summary

File:src/usr.sbin/radiusd/radiusd_radius/../radiusd_radius.c
Warning:line 508, column 7
Although the value stored to 'sz' is used in the enclosing expression, the value is never actually read from 'sz'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name radiusd_radius.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/radiusd/radiusd_radius/obj -resource-dir /usr/local/llvm16/lib/clang/16 -D USE_LIBEVENT -I /usr/src/usr.sbin/radiusd/radiusd_radius/.. -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/usr/src/usr.sbin/radiusd/radiusd_radius/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/radiusd/radiusd_radius/../radiusd_radius.c
1/* $OpenBSD: radiusd_radius.c,v 1.19 2023/09/04 10:49:20 yasuoka Exp $ */
2
3/*
4 * Copyright (c) 2013 Internet Initiative Japan Inc.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20#include <sys/queue.h>
21#include <sys/socket.h>
22#include <netinet/in.h>
23
24#include <err.h>
25#include <errno(*__errno()).h>
26#include <event.h>
27#include <fcntl.h>
28#include <stdbool.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <syslog.h>
33#include <unistd.h>
34
35#include <radius.h>
36
37#include "radiusd.h"
38#include "radiusd_module.h"
39#include "util.h"
40#include "log.h"
41
42struct radius_server {
43 struct module_radius *module;
44 int sock;
45 union {
46 struct sockaddr_in6 sin6;
47 struct sockaddr_in sin4;
48 } addr;
49 union {
50 struct sockaddr_in6 sin6;
51 struct sockaddr_in sin4;
52 } local;
53 struct event ev;
54 u_char req_id_seq;
55};
56
57struct module_radius {
58 struct module_base *base;
59 struct radius_server server[4];
60 char secret[RADIUSD_SECRET_MAX128];
61 u_int nserver;
62 u_int curr_server;
63 u_int req_timeout;
64 u_int max_tries;
65 u_int max_failovers;
66 u_int nfailover;
67 TAILQ_HEAD(,module_radius_req)struct { struct module_radius_req *tqh_first; struct module_radius_req
**tqh_last; }
req;
68};
69
70struct module_radius_req {
71 struct module_radius *module;
72 struct radius_server *server;
73 u_int q_id;
74 RADIUS_PACKET *q_pkt;
75 u_int ntry;
76 u_int nfailover;
77 u_char req_id;
78 struct event ev;
79 TAILQ_ENTRY(module_radius_req)struct { struct module_radius_req *tqe_next; struct module_radius_req
**tqe_prev; }
next;
80};
81
82static void module_radius_init(struct module_radius *);
83static void module_radius_config_set(void *, const char *, int,
84 char * const *);
85static void module_radius_start(void *);
86static void module_radius_stop(void *);
87static void module_radius_access_request(void *, u_int, const u_char *,
88 size_t);
89static int radius_server_start(struct radius_server *);
90static void radius_server_stop(struct radius_server *);
91static void radius_server_on_event(int, short, void *);
92static void radius_server_on_fail(struct radius_server *, const char *);
93static void module_radius_req_send(struct module_radius_req *);
94static int module_radius_req_reset_event(struct module_radius_req *);
95static void module_radius_req_on_timeout(int, short, void *);
96static void module_radius_req_on_success(struct module_radius_req *,
97 const u_char *, size_t);
98static void module_radius_req_on_failure(struct module_radius_req *);
99
100static void module_radius_req_free(struct module_radius_req *);
101static void module_radius_req_select_server(struct module_radius_req *);
102
103static void module_radius_req_reset_msgauth(struct module_radius_req *);
104static void module_radius_log(struct module_radius *, int, const char *, ...);
105
106static struct module_handlers module_radius_handlers = {
107 .config_set = module_radius_config_set,
108 .start = module_radius_start,
109 .stop = module_radius_stop,
110 .access_request = module_radius_access_request
111};
112
113#ifndef nitems
114#define nitems(_x)(sizeof((_x)) / sizeof((_x)[0])) (sizeof((_x)) / sizeof((_x)[0]))
115#endif
116
117int
118main(int argc, char *argv[])
119{
120 static struct module_radius module_radius;
121
122 module_radius_init(&module_radius);
123 openlog(NULL((void *)0), LOG_PID0x01, LOG_DAEMON(3<<3));
124
125 if ((module_radius.base = module_create(
126 STDIN_FILENO0, &module_radius, &module_radius_handlers)) == NULL((void *)0))
127 err(1, "Could not create a module instance");
128 module_drop_privilege(module_radius.base);
129 setproctitle("[main]");
130
131 module_load(module_radius.base);
132 log_init(0);
133 event_init();
134
135 if (pledge("stdio inet", NULL((void *)0)) == -1)
136 err(EXIT_FAILURE1, "pledge");
137
138 module_start(module_radius.base);
139 event_loop(0);
140
141 module_destroy(module_radius.base);
142
143 exit(EXIT_SUCCESS0);
144}
145
146static void
147module_radius_init(struct module_radius *module)
148{
149 memset(module, 0, sizeof(struct module_radius));
150 TAILQ_INIT(&module->req)do { (&module->req)->tqh_first = ((void *)0); (&
module->req)->tqh_last = &(&module->req)->
tqh_first; } while (0)
;
151}
152
153static void
154module_radius_config_set(void *ctx, const char *paramname, int paramvalc,
155 char * const * paramvalv)
156{
157 const char *errmsg = NULL((void *)0);
158 struct addrinfo *res;
159 struct module_radius *module = ctx;
160
161 if (strcmp(paramname, "server") == 0) {
162 SYNTAX_ASSERT(paramvalc == 1,do { if (!(paramvalc == 1)) { errmsg = ("`server' must have just one argument"
); goto syntax_error; } } while (0 )
163 "`server' must have just one argument")do { if (!(paramvalc == 1)) { errmsg = ("`server' must have just one argument"
); goto syntax_error; } } while (0 )
;
164 SYNTAX_ASSERT(module->nserver < (int)nitems(module->server),do { if (!(module->nserver < (int)(sizeof((module->server
)) / sizeof((module->server)[0])))) { errmsg = ("number of server reached limit"
); goto syntax_error; } } while (0 )
165 "number of server reached limit")do { if (!(module->nserver < (int)(sizeof((module->server
)) / sizeof((module->server)[0])))) { errmsg = ("number of server reached limit"
); goto syntax_error; } } while (0 )
;
166
167 if (addrport_parse(paramvalv[0], IPPROTO_UDP17, &res) != 0)
168 SYNTAX_ASSERT(0, "could not parse address and port")do { if (!(0)) { errmsg = ("could not parse address and port"
); goto syntax_error; } } while (0 )
;
169 memcpy(&module->server[module->nserver].addr, res->ai_addr,
170 res->ai_addrlen);
171
172 if (ntohs(module->server[module->nserver].addr.sin4.sin_port)(__uint16_t)(__builtin_constant_p(module->server[module->
nserver].addr.sin4.sin_port) ? (__uint16_t)(((__uint16_t)(module
->server[module->nserver].addr.sin4.sin_port) & 0xffU
) << 8 | ((__uint16_t)(module->server[module->nserver
].addr.sin4.sin_port) & 0xff00U) >> 8) : __swap16md
(module->server[module->nserver].addr.sin4.sin_port))
173 == 0)
174 module->server[module->nserver].addr.sin4.sin_port
175 = htons(RADIUS_DEFAULT_PORT)(__uint16_t)(__builtin_constant_p(1812) ? (__uint16_t)(((__uint16_t
)(1812) & 0xffU) << 8 | ((__uint16_t)(1812) & 0xff00U
) >> 8) : __swap16md(1812))
;
176
177 module->server[module->nserver].sock = -1;
178 module->nserver++;
179 freeaddrinfo(res);
180 } else if (strcmp(paramname, "request-timeout") == 0) {
181 SYNTAX_ASSERT(paramvalc == 1,do { if (!(paramvalc == 1)) { errmsg = ("`request-timeout' must have just one argument"
); goto syntax_error; } } while (0 )
182 "`request-timeout' must have just one argument")do { if (!(paramvalc == 1)) { errmsg = ("`request-timeout' must have just one argument"
); goto syntax_error; } } while (0 )
;
183 module->req_timeout = (int)strtonum(paramvalv[0], 0,
184 UINT16_MAX0xffff, &errmsg);
185 if (module->req_timeout == 0 && errmsg != NULL((void *)0)) {
186 module_send_message(module->base, IMSG_NG,
187 "`request-timeout must be 0-%d", UINT16_MAX0xffff);
188 return;
189 }
190 } else if (strcmp(paramname, "max-tries") == 0) {
191 SYNTAX_ASSERT(paramvalc == 1,do { if (!(paramvalc == 1)) { errmsg = ("`max-tries' must have just one argument"
); goto syntax_error; } } while (0 )
192 "`max-tries' must have just one argument")do { if (!(paramvalc == 1)) { errmsg = ("`max-tries' must have just one argument"
); goto syntax_error; } } while (0 )
;
193 module->max_tries = (int)strtonum(paramvalv[0], 0,
194 UINT16_MAX0xffff, &errmsg);
195 if (module->max_tries == 0 && errmsg != NULL((void *)0)) {
196 module_send_message(module->base, IMSG_NG,
197 "`max-tries must be 0-%d", UINT16_MAX0xffff);
198 return;
199 }
200
201 } else if (strcmp(paramname, "max-failovers") == 0) {
202 SYNTAX_ASSERT(paramvalc == 1,do { if (!(paramvalc == 1)) { errmsg = ("`max-failovers' must have just one argument"
); goto syntax_error; } } while (0 )
203 "`max-failovers' must have just one argument")do { if (!(paramvalc == 1)) { errmsg = ("`max-failovers' must have just one argument"
); goto syntax_error; } } while (0 )
;
204 module->max_failovers = (int)strtonum(paramvalv[0], 0,
205 UINT16_MAX0xffff, &errmsg);
206 if (module->max_failovers == 0 && errmsg != NULL((void *)0)) {
207 module_send_message(module->base, IMSG_NG,
208 "`max-failovers' must be 0-%d", UINT16_MAX0xffff);
209 return;
210 }
211 } else if (strcmp(paramname, "secret") == 0) {
212 SYNTAX_ASSERT(paramvalc == 1,do { if (!(paramvalc == 1)) { errmsg = ("`secret' must have just one argument"
); goto syntax_error; } } while (0 )
213 "`secret' must have just one argument")do { if (!(paramvalc == 1)) { errmsg = ("`secret' must have just one argument"
); goto syntax_error; } } while (0 )
;
214 if (strlcpy(module->secret, paramvalv[0],
215 sizeof(module->secret)) >= sizeof(module->secret)) {
216 module_send_message(module->base, IMSG_NG,
217 "`secret' length must be 0-%lu",
218 (u_long) sizeof(module->secret) - 1);
219 return;
220 }
221 } else if (strcmp(paramname, "_debug") == 0)
222 log_init(1);
223 else if (strncmp(paramname, "_", 1) == 0)
224 /* nothing */; /* ignore all internal messages */
225 else {
226 module_send_message(module->base, IMSG_NG,
227 "Unknown config parameter name `%s'", paramname);
228 return;
229 }
230 module_send_message(module->base, IMSG_OK, NULL((void *)0));
231
232 return;
233syntax_error:
234 module_send_message(module->base, IMSG_NG, "%s", errmsg);
235}
236
237static void
238module_radius_start(void *ctx)
239{
240 u_int i;
241 struct module_radius *module = ctx;
242
243 if (module->nserver <= 0) {
244 module_send_message(module->base, IMSG_NG,
245 "needs one `server' at least");
246 return;
247 }
248
249 if (module->secret[0] == '\0') {
250 module_send_message(module->base, IMSG_NG,
251 "`secret' configuration is required");
252 return;
253 }
254
255 for (i = 0; i < module->nserver; i++) {
256 module->server[i].module = module;
257 if (radius_server_start(&module->server[i]) != 0) {
258 module_send_message(module->base, IMSG_NG,
259 "module `radius' failed to start one of "
260 "the servers");
261 return;
262 }
263 }
264 module_send_message(module->base, IMSG_OK, NULL((void *)0));
265
266 module_notify_secret(module->base, module->secret);
267}
268
269static void
270module_radius_stop(void *ctx)
271{
272 u_int i;
273 struct module_radius_req *req, *treq;
274 struct module_radius *module = ctx;
275
276 TAILQ_FOREACH_SAFE(req, &module->req, next, treq)for ((req) = ((&module->req)->tqh_first); (req) != (
(void *)0) && ((treq) = ((req)->next.tqe_next), 1)
; (req) = (treq))
277 module_radius_req_on_failure(req);
278
279 for (i = 0; i < module->nserver; i++)
280 radius_server_stop(&module->server[i]);
281}
282
283static void
284module_radius_access_request(void *ctx, u_int q_id, const u_char *pkt,
285 size_t pktlen)
286{
287 struct module_radius *module = ctx;
288 struct module_radius_req *req;
289 u_char attrbuf[256];
290 ssize_t attrlen;
291
292 req = calloc(1, sizeof(struct module_radius_req));
293 if (req == NULL((void *)0)) {
294 module_radius_log(module, LOG_WARNING4,
295 "%s: Out of memory: %m", __func__);
296 goto on_fail;
297 }
298
299 req->ntry = 0;
300 req->module = module;
301 req->q_id = q_id;
302 if ((req->q_pkt = radius_convert_packet(pkt, pktlen)) == NULL((void *)0)) {
303 module_radius_log(module, LOG_WARNING4,
304 "%s: radius_convert_packet() failed: %m", __func__);
305 goto on_fail;
306 }
307 evtimer_set(&req->ev, module_radius_req_on_timeout, req)event_set(&req->ev, -1, 0, module_radius_req_on_timeout
, req)
;
308 TAILQ_INSERT_TAIL(&req->module->req, req, next)do { (req)->next.tqe_next = ((void *)0); (req)->next.tqe_prev
= (&req->module->req)->tqh_last; *(&req->
module->req)->tqh_last = (req); (&req->module->
req)->tqh_last = &(req)->next.tqe_next; } while (0)
;
309
310 /*
311 * radiusd decrypt User-Password attribute. crypt it again with our
312 * secret.
313 */
314 attrlen = sizeof(attrbuf);
315 if (radius_get_raw_attr(req->q_pkt, RADIUS_TYPE_USER_PASSWORD2,
316 attrbuf, &attrlen) == 0) {
317 attrbuf[attrlen] = '\0';
318 radius_del_attr_all(req->q_pkt, RADIUS_TYPE_USER_PASSWORD2);
319 radius_put_user_password_attr(req->q_pkt, attrbuf,
320 module->secret);
321 }
322
323 /* select current server */
324 module_radius_req_select_server(req);
325
326 module_radius_req_send(req);
327
328 return;
329
330on_fail:
331 free(req);
332 module_accsreq_aborted(module->base, q_id);
333}
334
335/*
336 * radius_server
337 */
338static int
339radius_server_start(struct radius_server *server)
340{
341 socklen_t locallen;
342 char buf0[NI_MAXHOST256 + NI_MAXSERV32 + 32];
343 char buf1[NI_MAXHOST256 + NI_MAXSERV32 + 32];
344
345 if ((server->sock = socket(AF_INET2, SOCK_DGRAM2 | SOCK_NONBLOCK0x4000, 0))
346 == -1) {
347 module_radius_log(server->module, LOG_WARNING4,
348 "%s: socket() failed", __func__);
349 goto on_error;
350 }
351 if (connect(server->sock, (struct sockaddr *)&server->addr,
352 server->addr.sin4.sin_len) != 0) {
353 module_radius_log(server->module, LOG_WARNING4,
354 "%s: connect to %s failed", __func__,
355 addrport_tostring((struct sockaddr *)&server->addr,
356 server->addr.sin4.sin_len, buf1, sizeof(buf1)));
357 goto on_error;
358 }
359 locallen = sizeof(server->local);
360 if (getsockname(server->sock, (struct sockaddr *)&server->local,
361 &locallen) != 0) {
362 module_radius_log(server->module, LOG_WARNING4,
363 "%s: getsockanme() failed", __func__);
364 goto on_error;
365 }
366 module_radius_log(server->module, LOG_INFO6,
367 "Use %s to send requests for %s",
368 addrport_tostring((struct sockaddr *)&server->local,
369 locallen, buf0, sizeof(buf0)),
370 addrport_tostring((struct sockaddr *)&server->addr,
371 server->addr.sin4.sin_len, buf1, sizeof(buf1)));
372
373 event_set(&server->ev, server->sock, EV_READ0x02 | EV_PERSIST0x10,
374 radius_server_on_event, server);
375 if (event_add(&server->ev, NULL((void *)0))) {
376 module_radius_log(server->module, LOG_WARNING4,
377 "%s: event_add() failed", __func__);
378 goto on_error;
379 }
380
381 return (0);
382on_error:
383 if (server->sock >= 0)
384 close(server->sock);
385 server->sock = -1;
386 return (-1);
387}
388
389static void
390radius_server_stop(struct radius_server *server)
391{
392 event_del(&server->ev);
393 if (server->sock >= 0)
394 close(server->sock);
395 server->sock = -1;
396}
397
398static void
399radius_server_on_event(int fd, short evmask, void *ctx)
400{
401 int sz, res_id;
402 u_char pkt[65535];
403 char buf[NI_MAXHOST256 + NI_MAXSERV32 + 32];
404 struct radius_server *server = ctx;
405 RADIUS_PACKET *radpkt = NULL((void *)0);
406 struct module_radius_req *req;
407 struct sockaddr *peer;
408
409 peer = (struct sockaddr *)&server->addr;
410 if ((sz = recv(server->sock, pkt, sizeof(pkt), 0)) == -1) {
411 if (errno(*__errno()) == EAGAIN35)
412 return;
413 module_radius_log(server->module, LOG_WARNING4,
414 "server=%s recv() failed: %m",
415 addrport_tostring(peer, peer->sa_len, buf, sizeof(buf)));
416 return;
417 }
418 if ((radpkt = radius_convert_packet(pkt, sz)) == NULL((void *)0)) {
419 module_radius_log(server->module, LOG_WARNING4,
420 "server=%s could not convert the received message to a "
421 "RADIUS packet object: %m",
422 addrport_tostring(peer, peer->sa_len, buf, sizeof(buf)));
423 return;
424 }
425 res_id = radius_get_id(radpkt);
426 TAILQ_FOREACH(req, &server->module->req, next)for((req) = ((&server->module->req)->tqh_first);
(req) != ((void *)0); (req) = ((req)->next.tqe_next))
{
427 if (req->server == server && req->req_id == res_id)
428 break;
429 }
430 if (req == NULL((void *)0)) {
431 module_radius_log(server->module, LOG_WARNING4,
432 "server=%s Received radius message has unknown id=%d",
433 addrport_tostring(peer, peer->sa_len, buf, sizeof(buf)),
434 res_id);
435 goto out;
436 }
437 radius_set_request_packet(radpkt, req->q_pkt);
438
439 if (radius_check_response_authenticator(radpkt,
440 server->module->secret) != 0) {
441 module_radius_log(server->module, LOG_WARNING4,
442 "server=%s Received radius message(id=%d) has bad "
443 "authenticator",
444 addrport_tostring(peer, peer->sa_len, buf,
445 sizeof(buf)), res_id);
446 goto out;
447 }
448 if (radius_has_attr(radpkt,
449 RADIUS_TYPE_MESSAGE_AUTHENTICATOR80) &&
450 radius_check_message_authenticator(radpkt,
451 server->module->secret) != 0) {
452 module_radius_log(server->module, LOG_WARNING4,
453 "server=%s Received radius message(id=%d) has bad "
454 "message authenticator",
455 addrport_tostring(peer, peer->sa_len, buf,
456 sizeof(buf)), res_id);
457 goto out;
458 }
459
460 module_radius_log(server->module, LOG_INFO6,
461 "q=%u received a response from server %s", req->q_id,
462 addrport_tostring(peer, peer->sa_len, buf, sizeof(buf)));
463
464 module_radius_req_on_success(req, radius_get_data(radpkt),
465 radius_get_length(radpkt));
466out:
467 if (radpkt != NULL((void *)0))
468 radius_delete_packet(radpkt);
469}
470
471static void
472radius_server_on_fail(struct radius_server *server, const char *failmsg)
473{
474 char buf0[NI_MAXHOST256 + NI_MAXSERV32 + 32];
475 char buf1[NI_MAXHOST256 + NI_MAXSERV32 + 32];
476 struct sockaddr *caddr, *naddr;
477
478 caddr = (struct sockaddr *)&server->addr;
479 if (server->module->nserver <= 1) {
480 module_radius_log(server->module, LOG_WARNING4,
481 "Server %s failed: %s",
482 addrport_tostring(caddr, caddr->sa_len, buf0, sizeof(buf0)),
483 failmsg);
484 return;
485 }
486 server->module->curr_server++;
487 server->module->curr_server %= server->module->nserver;
488 naddr = (struct sockaddr *)
489 &server->module->server[server->module->curr_server].addr;
490
491 module_radius_log(server->module, LOG_WARNING4,
492 "Server %s failed: %s Fail over to %s",
493 addrport_tostring(caddr, caddr->sa_len, buf0, sizeof(buf0)),
494 failmsg,
495 addrport_tostring(naddr, naddr->sa_len, buf1, sizeof(buf1)));
496}
497
498/* module_radius_req */
499
500static void
501module_radius_req_send(struct module_radius_req *req)
502{
503 int sz;
504 struct sockaddr *peer;
505 char msg[BUFSIZ1024];
506
507 peer = (struct sockaddr *)&req->server->addr;
508 if ((sz = send(req->server->sock, radius_get_data(req->q_pkt),
Although the value stored to 'sz' is used in the enclosing expression, the value is never actually read from 'sz'
509 radius_get_length(req->q_pkt), 0)) < 0) {
510 module_radius_log(req->module, LOG_WARNING4,
511 "Sending RADIUS query q=%u to %s failed: %m",
512 req->q_id,
513 addrport_tostring(peer, peer->sa_len, msg, sizeof(msg)));
514 /* retry anyway */
515 }
516 module_radius_log(req->module, LOG_INFO6,
517 "Send RADIUS query q=%u id=%d to %s successfully",
518 req->q_id, req->req_id,
519 addrport_tostring(peer, peer->sa_len, msg, sizeof(msg)));
520 if (module_radius_req_reset_event(req) != -1)
521 req->ntry++;
522}
523
524static int
525module_radius_req_reset_event(struct module_radius_req *req)
526{
527 struct timeval tv;
528 static int timeouts[] = { 2, 4, 8 };
529
530 tv.tv_usec = 0;
531 if (req->module->req_timeout != 0)
532 tv.tv_sec = req->module->req_timeout;
533 else {
534 if (req->ntry < nitems(timeouts)(sizeof((timeouts)) / sizeof((timeouts)[0])))
535 tv.tv_sec = timeouts[req->ntry];
536 else
537 tv.tv_sec = timeouts[nitems(timeouts)(sizeof((timeouts)) / sizeof((timeouts)[0])) - 1];
538 }
539 if (evtimer_add(&req->ev, &tv)event_add(&req->ev, &tv) != 0) {
540 module_radius_log(req->module, LOG_WARNING4,
541 "Cannot process the request for q=%u: "
542 "evtimer_add() failed: %m", req->q_id);
543 module_radius_req_on_failure(req);
544 return (-1);
545 }
546 return (0);
547}
548
549static void
550module_radius_req_on_timeout(int fd, short evmask, void *ctx)
551{
552 struct module_radius_req *req = ctx;
553 char msg[BUFSIZ1024];
554
555
556 if (req->module->max_tries <= req->ntry) {
557 snprintf(msg, sizeof(msg), "q=%u didn't response RADIUS query "
558 "%d time%s", req->q_id, req->ntry,
559 (req->ntry > 0)? "s" : "");
560 radius_server_on_fail(req->server, msg);
561 if (++req->nfailover >= req->module->max_failovers) {
562 module_radius_log(req->module,
563 LOG_WARNING4, "RADIUS query q=%u time out",
564 req->q_id);
565 module_radius_req_on_failure(req);
566 return;
567 }
568 /* select the next server */
569 module_radius_req_select_server(req);
570 }
571 module_radius_req_send(req);
572}
573
574static void
575module_radius_req_on_success(struct module_radius_req *req,
576 const u_char *pkt, size_t pktlen)
577{
578 module_accsreq_answer(req->module->base, req->q_id, pkt, pktlen);
579 module_radius_req_free(req);
580}
581
582static void
583module_radius_req_on_failure(struct module_radius_req *req)
584{
585 module_accsreq_aborted(req->module->base, req->q_id);
586 module_radius_req_free(req);
587}
588
589
590static void
591module_radius_req_free(struct module_radius_req *req)
592{
593 evtimer_del(&req->ev)event_del(&req->ev);
594 TAILQ_REMOVE(&req->module->req, req, next)do { if (((req)->next.tqe_next) != ((void *)0)) (req)->
next.tqe_next->next.tqe_prev = (req)->next.tqe_prev; else
(&req->module->req)->tqh_last = (req)->next.
tqe_prev; *(req)->next.tqe_prev = (req)->next.tqe_next;
; ; } while (0)
;
595 if (req->q_pkt != NULL((void *)0))
596 radius_delete_packet(req->q_pkt);
597 free(req);
598}
599
600static void
601module_radius_req_select_server(struct module_radius_req *req)
602{
603 req->server = &req->module->server[req->module->curr_server];
604 req->ntry = 0;
605 req->req_id = req->server->req_id_seq++;
606 radius_set_id(req->q_pkt, req->req_id);
607 module_radius_req_reset_msgauth(req);
608}
609
610static void
611module_radius_req_reset_msgauth(struct module_radius_req *req)
612{
613 if (radius_has_attr(req->q_pkt, RADIUS_TYPE_MESSAGE_AUTHENTICATOR80))
614 radius_del_attr_all(req->q_pkt,
615 RADIUS_TYPE_MESSAGE_AUTHENTICATOR80);
616 radius_put_message_authenticator(req->q_pkt,
617 req->module->secret);
618}
619
620static void
621module_radius_log(struct module_radius *module, int pri, const char *fmt, ...)
622{
623 char fmt0[BUFSIZ1024];
624 va_list va;
625
626 snprintf(fmt0, sizeof(fmt0), "radius: %s", fmt);
627 va_start(va, fmt)__builtin_va_start((va), fmt);
628 vlog(pri, fmt0, va);
629 va_end(va)__builtin_va_end((va));
630}