Bug Summary

File:src/usr.sbin/radiusd/radiusd_radius/../radiusd_radius.c
Warning:line 507, 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.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name radiusd_radius.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/lib/clang/13.0.0 -D USE_LIBEVENT -I /usr/src/usr.sbin/radiusd/radiusd_radius/.. -internal-isystem /usr/local/lib/clang/13.0.0/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 -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/radiusd/radiusd_radius/../radiusd_radius.c
1/* $OpenBSD: radiusd_radius.c,v 1.17 2019/06/28 13:32:49 deraadt 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 exit(EXIT_SUCCESS0);
142}
143
144static void
145module_radius_init(struct module_radius *module)
146{
147 memset(module, 0, sizeof(struct module_radius));
148 TAILQ_INIT(&module->req)do { (&module->req)->tqh_first = ((void *)0); (&
module->req)->tqh_last = &(&module->req)->
tqh_first; } while (0)
;
149}
150
151static void
152module_radius_config_set(void *ctx, const char *paramname, int paramvalc,
153 char * const * paramvalv)
154{
155 const char *errmsg = NULL((void *)0);
156 struct addrinfo *res;
157 struct module_radius *module = ctx;
158
159 if (strcmp(paramname, "server") == 0) {
160 SYNTAX_ASSERT(paramvalc == 1,do { if (!(paramvalc == 1)) { errmsg = ("`server' must have just one argument"
); goto syntax_error; } } while (0 )
161 "`server' must have just one argument")do { if (!(paramvalc == 1)) { errmsg = ("`server' must have just one argument"
); goto syntax_error; } } while (0 )
;
162 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 )
163 "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 )
;
164
165 if (addrport_parse(paramvalv[0], IPPROTO_UDP17, &res) != 0)
166 SYNTAX_ASSERT(0, "could not parse address and port")do { if (!(0)) { errmsg = ("could not parse address and port"
); goto syntax_error; } } while (0 )
;
167 memcpy(&module->server[module->nserver].addr, res->ai_addr,
168 res->ai_addrlen);
169
170 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))
171 == 0)
172 module->server[module->nserver].addr.sin4.sin_port
173 = htons(RADIUS_DEFAULT_PORT)(__uint16_t)(__builtin_constant_p(1812) ? (__uint16_t)(((__uint16_t
)(1812) & 0xffU) << 8 | ((__uint16_t)(1812) & 0xff00U
) >> 8) : __swap16md(1812))
;
174
175 module->server[module->nserver].sock = -1;
176 module->nserver++;
177 freeaddrinfo(res);
178 } else if (strcmp(paramname, "request-timeout") == 0) {
179 SYNTAX_ASSERT(paramvalc == 1,do { if (!(paramvalc == 1)) { errmsg = ("`request-timeout' must have just one argument"
); goto syntax_error; } } while (0 )
180 "`request-timeout' must have just one argument")do { if (!(paramvalc == 1)) { errmsg = ("`request-timeout' must have just one argument"
); goto syntax_error; } } while (0 )
;
181 module->req_timeout = (int)strtonum(paramvalv[0], 0,
182 UINT16_MAX0xffff, &errmsg);
183 if (module->req_timeout == 0 && errmsg != NULL((void *)0)) {
184 module_send_message(module->base, IMSG_NG,
185 "`request-timeout must be 0-%d", UINT16_MAX0xffff);
186 return;
187 }
188 } else if (strcmp(paramname, "max-tries") == 0) {
189 SYNTAX_ASSERT(paramvalc == 1,do { if (!(paramvalc == 1)) { errmsg = ("`max-tries' must have just one argument"
); goto syntax_error; } } while (0 )
190 "`max-tries' must have just one argument")do { if (!(paramvalc == 1)) { errmsg = ("`max-tries' must have just one argument"
); goto syntax_error; } } while (0 )
;
191 module->max_tries = (int)strtonum(paramvalv[0], 0,
192 UINT16_MAX0xffff, &errmsg);
193 if (module->max_tries == 0 && errmsg != NULL((void *)0)) {
194 module_send_message(module->base, IMSG_NG,
195 "`max-tries must be 0-%d", UINT16_MAX0xffff);
196 return;
197 }
198
199 } else if (strcmp(paramname, "max-failovers") == 0) {
200 SYNTAX_ASSERT(paramvalc == 1,do { if (!(paramvalc == 1)) { errmsg = ("`max-failovers' must have just one argument"
); goto syntax_error; } } while (0 )
201 "`max-failovers' must have just one argument")do { if (!(paramvalc == 1)) { errmsg = ("`max-failovers' must have just one argument"
); goto syntax_error; } } while (0 )
;
202 module->max_failovers = (int)strtonum(paramvalv[0], 0,
203 UINT16_MAX0xffff, &errmsg);
204 if (module->max_failovers == 0 && errmsg != NULL((void *)0)) {
205 module_send_message(module->base, IMSG_NG,
206 "`max-failovers' must be 0-%d", UINT16_MAX0xffff);
207 return;
208 }
209 } else if (strcmp(paramname, "secret") == 0) {
210 SYNTAX_ASSERT(paramvalc == 1,do { if (!(paramvalc == 1)) { errmsg = ("`secret' must have just one argument"
); goto syntax_error; } } while (0 )
211 "`secret' must have just one argument")do { if (!(paramvalc == 1)) { errmsg = ("`secret' must have just one argument"
); goto syntax_error; } } while (0 )
;
212 if (strlcpy(module->secret, paramvalv[0],
213 sizeof(module->secret)) >= sizeof(module->secret)) {
214 module_send_message(module->base, IMSG_NG,
215 "`secret' length must be 0-%lu",
216 (u_long) sizeof(module->secret) - 1);
217 return;
218 }
219 } else if (strcmp(paramname, "_debug") == 0)
220 log_init(1);
221 else if (strncmp(paramname, "_", 1) == 0)
222 /* ignore all internal messages */
223 module_send_message(module->base, IMSG_OK, NULL((void *)0));
224 else {
225 module_send_message(module->base, IMSG_NG,
226 "Unknown config parameter name `%s'", paramname);
227 return;
228 }
229 module_send_message(module->base, IMSG_OK, NULL((void *)0));
230
231 return;
232syntax_error:
233 module_send_message(module->base, IMSG_NG, "%s", errmsg);
234}
235
236static void
237module_radius_start(void *ctx)
238{
239 u_int i;
240 struct module_radius *module = ctx;
241
242 if (module->nserver <= 0) {
243 module_send_message(module->base, IMSG_NG,
244 "needs one `server' at least");
245 return;
246 }
247
248 if (module->secret[0] == '\0') {
249 module_send_message(module->base, IMSG_NG,
250 "`secret' configuration is required");
251 return;
252 }
253
254 for (i = 0; i < module->nserver; i++) {
255 module->server[i].module = module;
256 if (radius_server_start(&module->server[i]) != 0) {
257 module_send_message(module->base, IMSG_NG,
258 "module `radius' failed to start one of "
259 "the servers");
260 return;
261 }
262 }
263 module_send_message(module->base, IMSG_OK, NULL((void *)0));
264
265 module_notify_secret(module->base, module->secret);
266}
267
268static void
269module_radius_stop(void *ctx)
270{
271 u_int i;
272 struct module_radius_req *req, *treq;
273 struct module_radius *module = ctx;
274
275 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))
276 module_radius_req_on_failure(req);
277
278 for (i = 0; i < module->nserver; i++)
279 radius_server_stop(&module->server[i]);
280}
281
282static void
283module_radius_access_request(void *ctx, u_int q_id, const u_char *pkt,
284 size_t pktlen)
285{
286 struct module_radius *module = ctx;
287 struct module_radius_req *req;
288 u_char attrbuf[256];
289 ssize_t attrlen;
290
291 req = calloc(1, sizeof(struct module_radius_req));
292 if (req == NULL((void *)0)) {
293 module_radius_log(module, LOG_WARNING4,
294 "%s: Out of memory: %m", __func__);
295 goto on_fail;
296 }
297
298 req->ntry = 0;
299 req->module = module;
300 req->q_id = q_id;
301 if ((req->q_pkt = radius_convert_packet(pkt, pktlen)) == NULL((void *)0)) {
302 module_radius_log(module, LOG_WARNING4,
303 "%s: radius_convert_packet() failed: %m", __func__);
304 goto on_fail;
305 }
306 evtimer_set(&req->ev, module_radius_req_on_timeout, req)event_set(&req->ev, -1, 0, module_radius_req_on_timeout
, req)
;
307 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)
;
308
309 /*
310 * radiusd decrypt User-Password attribute. crypt it again with our
311 * secret.
312 */
313 attrlen = sizeof(attrbuf);
314 if (radius_get_raw_attr(req->q_pkt, RADIUS_TYPE_USER_PASSWORD2,
315 attrbuf, &attrlen) == 0) {
316 attrbuf[attrlen] = '\0';
317 radius_del_attr_all(req->q_pkt, RADIUS_TYPE_USER_PASSWORD2);
318 radius_put_user_password_attr(req->q_pkt, attrbuf,
319 module->secret);
320 }
321
322 /* select current server */
323 module_radius_req_select_server(req);
324
325 module_radius_req_send(req);
326
327 return;
328
329on_fail:
330 free(req);
331 module_accsreq_aborted(module->base, q_id);
332}
333
334/*
335 * radius_server
336 */
337static int
338radius_server_start(struct radius_server *server)
339{
340 socklen_t locallen;
341 char buf0[NI_MAXHOST256 + NI_MAXSERV32 + 32];
342 char buf1[NI_MAXHOST256 + NI_MAXSERV32 + 32];
343
344 if ((server->sock = socket(AF_INET2, SOCK_DGRAM2 | SOCK_NONBLOCK0x4000, 0))
345 == -1) {
346 module_radius_log(server->module, LOG_WARNING4,
347 "%s: socket() failed", __func__);
348 goto on_error;
349 }
350 if (connect(server->sock, (struct sockaddr *)&server->addr,
351 server->addr.sin4.sin_len) != 0) {
352 module_radius_log(server->module, LOG_WARNING4,
353 "%s: connect to %s failed", __func__,
354 addrport_tostring((struct sockaddr *)&server->addr,
355 server->addr.sin4.sin_len, buf1, sizeof(buf1)));
356 goto on_error;
357 }
358 locallen = sizeof(server->local);
359 if (getsockname(server->sock, (struct sockaddr *)&server->local,
360 &locallen) != 0) {
361 module_radius_log(server->module, LOG_WARNING4,
362 "%s: getsockanme() failed", __func__);
363 goto on_error;
364 }
365 module_radius_log(server->module, LOG_INFO6,
366 "Use %s to send requests for %s",
367 addrport_tostring((struct sockaddr *)&server->local,
368 locallen, buf0, sizeof(buf0)),
369 addrport_tostring((struct sockaddr *)&server->addr,
370 server->addr.sin4.sin_len, buf1, sizeof(buf1)));
371
372 event_set(&server->ev, server->sock, EV_READ0x02 | EV_PERSIST0x10,
373 radius_server_on_event, server);
374 if (event_add(&server->ev, NULL((void *)0))) {
375 module_radius_log(server->module, LOG_WARNING4,
376 "%s: event_add() failed", __func__);
377 goto on_error;
378 }
379
380 return (0);
381on_error:
382 if (server->sock >= 0)
383 close(server->sock);
384 server->sock = -1;
385 return (-1);
386}
387
388static void
389radius_server_stop(struct radius_server *server)
390{
391 event_del(&server->ev);
392 if (server->sock >= 0)
393 close(server->sock);
394 server->sock = -1;
395}
396
397static void
398radius_server_on_event(int fd, short evmask, void *ctx)
399{
400 int sz, res_id;
401 u_char pkt[65535];
402 char buf[NI_MAXHOST256 + NI_MAXSERV32 + 32];
403 struct radius_server *server = ctx;
404 RADIUS_PACKET *radpkt = NULL((void *)0);
405 struct module_radius_req *req;
406 struct sockaddr *peer;
407
408 peer = (struct sockaddr *)&server->addr;
409 if ((sz = recv(server->sock, pkt, sizeof(pkt), 0)) == -1) {
410 if (errno(*__errno()) == EAGAIN35)
411 return;
412 module_radius_log(server->module, LOG_WARNING4,
413 "server=%s recv() failed: %m",
414 addrport_tostring(peer, peer->sa_len, buf, sizeof(buf)));
415 return;
416 }
417 if ((radpkt = radius_convert_packet(pkt, sz)) == NULL((void *)0)) {
418 module_radius_log(server->module, LOG_WARNING4,
419 "server=%s could not convert the received message to a "
420 "RADIUS packet object: %m",
421 addrport_tostring(peer, peer->sa_len, buf, sizeof(buf)));
422 return;
423 }
424 res_id = radius_get_id(radpkt);
425 TAILQ_FOREACH(req, &server->module->req, next)for((req) = ((&server->module->req)->tqh_first);
(req) != ((void *)0); (req) = ((req)->next.tqe_next))
{
426 if (req->server == server && req->req_id == res_id)
427 break;
428 }
429 if (req == NULL((void *)0)) {
430 module_radius_log(server->module, LOG_WARNING4,
431 "server=%s Received radius message has unknown id=%d",
432 addrport_tostring(peer, peer->sa_len, buf, sizeof(buf)),
433 res_id);
434 goto out;
435 }
436 radius_set_request_packet(radpkt, req->q_pkt);
437
438 if (radius_check_response_authenticator(radpkt,
439 server->module->secret) != 0) {
440 module_radius_log(server->module, LOG_WARNING4,
441 "server=%s Received radius message(id=%d) has bad "
442 "authenticator",
443 addrport_tostring(peer, peer->sa_len, buf,
444 sizeof(buf)), res_id);
445 goto out;
446 }
447 if (radius_has_attr(radpkt,
448 RADIUS_TYPE_MESSAGE_AUTHENTICATOR80) &&
449 radius_check_message_authenticator(radpkt,
450 server->module->secret) != 0) {
451 module_radius_log(server->module, LOG_WARNING4,
452 "server=%s Received radius message(id=%d) has bad "
453 "message authenticator",
454 addrport_tostring(peer, peer->sa_len, buf,
455 sizeof(buf)), res_id);
456 goto out;
457 }
458
459 module_radius_log(server->module, LOG_INFO6,
460 "q=%u received a response from server %s", req->q_id,
461 addrport_tostring(peer, peer->sa_len, buf, sizeof(buf)));
462
463 module_radius_req_on_success(req, radius_get_data(radpkt),
464 radius_get_length(radpkt));
465out:
466 if (radpkt != NULL((void *)0))
467 radius_delete_packet(radpkt);
468}
469
470static void
471radius_server_on_fail(struct radius_server *server, const char *failmsg)
472{
473 char buf0[NI_MAXHOST256 + NI_MAXSERV32 + 32];
474 char buf1[NI_MAXHOST256 + NI_MAXSERV32 + 32];
475 struct sockaddr *caddr, *naddr;
476
477 caddr = (struct sockaddr *)&server->addr;
478 if (server->module->nserver <= 1) {
479 module_radius_log(server->module, LOG_WARNING4,
480 "Server %s failed: %s",
481 addrport_tostring(caddr, caddr->sa_len, buf0, sizeof(buf0)),
482 failmsg);
483 return;
484 }
485 server->module->curr_server++;
486 server->module->curr_server %= server->module->nserver;
487 naddr = (struct sockaddr *)
488 &server->module->server[server->module->curr_server].addr;
489
490 module_radius_log(server->module, LOG_WARNING4,
491 "Server %s failed: %s Fail over to %s",
492 addrport_tostring(caddr, caddr->sa_len, buf0, sizeof(buf0)),
493 failmsg,
494 addrport_tostring(naddr, naddr->sa_len, buf1, sizeof(buf1)));
495}
496
497/* module_radius_req */
498
499static void
500module_radius_req_send(struct module_radius_req *req)
501{
502 int sz;
503 struct sockaddr *peer;
504 char msg[BUFSIZ1024];
505
506 peer = (struct sockaddr *)&req->server->addr;
507 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'
508 radius_get_length(req->q_pkt), 0)) < 0) {
509 module_radius_log(req->module, LOG_WARNING4,
510 "Sending RADIUS query q=%u to %s failed: %m",
511 req->q_id,
512 addrport_tostring(peer, peer->sa_len, msg, sizeof(msg)));
513 /* retry anyway */
514 }
515 module_radius_log(req->module, LOG_INFO6,
516 "Send RADIUS query q=%u id=%d to %s successfully",
517 req->q_id, req->req_id,
518 addrport_tostring(peer, peer->sa_len, msg, sizeof(msg)));
519 if (module_radius_req_reset_event(req) != -1)
520 req->ntry++;
521}
522
523static int
524module_radius_req_reset_event(struct module_radius_req *req)
525{
526 struct timeval tv;
527 static int timeouts[] = { 2, 4, 8 };
528
529 tv.tv_usec = 0;
530 if (req->module->req_timeout != 0)
531 tv.tv_sec = req->module->req_timeout;
532 else {
533 if (req->ntry < nitems(timeouts)(sizeof((timeouts)) / sizeof((timeouts)[0])))
534 tv.tv_sec = timeouts[req->ntry];
535 else
536 tv.tv_sec = timeouts[nitems(timeouts)(sizeof((timeouts)) / sizeof((timeouts)[0])) - 1];
537 }
538 if (evtimer_add(&req->ev, &tv)event_add(&req->ev, &tv) != 0) {
539 module_radius_log(req->module, LOG_WARNING4,
540 "Cannot proccess the request for q=%u: "
541 "evtimer_add() failed: %m", req->q_id);
542 module_radius_req_on_failure(req);
543 return (-1);
544 }
545 return (0);
546}
547
548static void
549module_radius_req_on_timeout(int fd, short evmask, void *ctx)
550{
551 struct module_radius_req *req = ctx;
552 char msg[BUFSIZ1024];
553
554
555 if (req->module->max_tries <= req->ntry) {
556 snprintf(msg, sizeof(msg), "q=%u didn't response RADIUS query "
557 "%d time%s", req->q_id, req->ntry,
558 (req->ntry > 0)? "s" : "");
559 radius_server_on_fail(req->server, msg);
560 if (++req->nfailover >= req->module->max_failovers) {
561 module_radius_log(req->module,
562 LOG_WARNING4, "RADIUS query q=%u time out",
563 req->q_id);
564 module_radius_req_on_failure(req);
565 return;
566 }
567 /* select the next server */
568 module_radius_req_select_server(req);
569 }
570 module_radius_req_send(req);
571}
572
573static void
574module_radius_req_on_success(struct module_radius_req *req,
575 const u_char *pkt, size_t pktlen)
576{
577 module_accsreq_answer(req->module->base, req->q_id, pkt, pktlen);
578 module_radius_req_free(req);
579}
580
581static void
582module_radius_req_on_failure(struct module_radius_req *req)
583{
584 module_accsreq_aborted(req->module->base, req->q_id);
585 module_radius_req_free(req);
586}
587
588
589static void
590module_radius_req_free(struct module_radius_req *req)
591{
592 evtimer_del(&req->ev)event_del(&req->ev);
593 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)
;
594 if (req->q_pkt != NULL((void *)0))
595 radius_delete_packet(req->q_pkt);
596 free(req);
597}
598
599static void
600module_radius_req_select_server(struct module_radius_req *req)
601{
602 req->server = &req->module->server[req->module->curr_server];
603 req->ntry = 0;
604 req->req_id = req->server->req_id_seq++;
605 radius_set_id(req->q_pkt, req->req_id);
606 module_radius_req_reset_msgauth(req);
607}
608
609static void
610module_radius_req_reset_msgauth(struct module_radius_req *req)
611{
612 if (radius_has_attr(req->q_pkt, RADIUS_TYPE_MESSAGE_AUTHENTICATOR80))
613 radius_del_attr_all(req->q_pkt,
614 RADIUS_TYPE_MESSAGE_AUTHENTICATOR80);
615 radius_put_message_authenticator(req->q_pkt,
616 req->module->secret);
617}
618
619static void
620module_radius_log(struct module_radius *module, int pri, const char *fmt, ...)
621{
622 char fmt0[BUFSIZ1024];
623 va_list va;
624
625 snprintf(fmt0, sizeof(fmt0), "radius: %s", fmt);
626 va_start(va, fmt)__builtin_va_start(va, fmt);
627 vlog(pri, fmt0, va);
628 va_end(va)__builtin_va_end(va);
629}