The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_radutmp.c
Go to the documentation of this file.
1/*
2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: e5186eb149ad8c9b278fdd365f5342ef550ef2b6 $
19 * @file rlm_radutmp.c
20 * @brief Tracks sessions.
21 *
22 * @copyright 2000-2013 The FreeRADIUS server project
23 */
24RCSID("$Id: e5186eb149ad8c9b278fdd365f5342ef550ef2b6 $")
25
26#include <freeradius-devel/server/base.h>
27#include <freeradius-devel/server/radutmp.h>
28#include <freeradius-devel/server/module_rlm.h>
29#include <freeradius-devel/util/debug.h>
30#include <freeradius-devel/radius/radius.h>
31
32#include <fcntl.h>
33
34#include "config.h"
35
36#define LOCK_LEN sizeof(struct radutmp)
37
38static char const porttypes[] = "ASITX";
39
40/*
41 * used for caching radutmp lookups in the accounting component.
42 */
43typedef struct nas_port_s NAS_PORT;
50
54
61
66
67static const conf_parser_t module_config[] = {
68 { FR_CONF_OFFSET("check_with_nas", rlm_radutmp_t, check_nas), .dflt = "yes" },
69 { FR_CONF_OFFSET("permissions", rlm_radutmp_t, permission), .dflt = "0644", .func = cf_parse_permissions },
70 { FR_CONF_OFFSET("caller_id", rlm_radutmp_t, caller_id_ok), .dflt = "no" },
72};
73
83
84static fr_dict_t const *dict_radius;
85
88 { .out = &dict_radius, .proto = "radius" },
89 { NULL }
90};
91
103
106 { .out = &attr_acct_delay_time, .name = "Acct-Delay-Time", .type = FR_TYPE_UINT32, .dict = &dict_radius },
107 { .out = &attr_acct_session_id, .name = "Acct-Session-Id", .type = FR_TYPE_STRING, .dict = &dict_radius },
108 { .out = &attr_acct_session_time, .name = "Acct-Session-Time", .type = FR_TYPE_UINT32, .dict = &dict_radius },
109 { .out = &attr_acct_status_type, .name = "Acct-Status-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
110 { .out = &attr_calling_station_id, .name = "Calling-Station-Id", .type = FR_TYPE_STRING, .dict = &dict_radius },
111 { .out = &attr_framed_ip_address, .name = "Framed-IP-Address", .type = FR_TYPE_IPV4_ADDR, .dict = &dict_radius },
112 { .out = &attr_framed_protocol, .name = "Framed-Protocol", .type = FR_TYPE_UINT32, .dict = &dict_radius },
113 { .out = &attr_login_ip_host, .name = "Login-IP-Host", .type = FR_TYPE_IPV4_ADDR, .dict = &dict_radius },
114 { .out = &attr_nas_ip_address, .name = "NAS-IP-Address", .type = FR_TYPE_IPV4_ADDR, .dict = &dict_radius },
115 { .out = &attr_nas_port, .name = "NAS-Port", .type = FR_TYPE_UINT32, .dict = &dict_radius },
116 { .out = &attr_nas_port_type, .name = "NAS-Port-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
117 { NULL }
118};
119
120/*
121 * Zap all users on a NAS from the radutmp file.
122 */
123static unlang_action_t radutmp_zap(rlm_rcode_t *p_result, request_t *request, char const *filename, uint32_t nasaddr, time_t t)
124{
125 struct radutmp u;
126 int fd;
127
128 if (t == 0) time(&t);
129
130 fd = open(filename, O_RDWR);
131 if (fd < 0) {
132 REDEBUG("Error accessing file %s: %s", filename, fr_syserror(errno));
134 }
135
136 /*
137 * Lock the utmp file, prefer lockf() over flock().
138 */
139 if (rad_lockfd(fd, LOCK_LEN) < 0) {
140 REDEBUG("Failed to acquire lock on file %s: %s", filename, fr_syserror(errno));
141 close(fd);
143 }
144
145 /*
146 * Find the entry for this NAS / portno combination.
147 */
148 while (read(fd, &u, sizeof(u)) == sizeof(u)) {
149 if ((nasaddr != 0 && nasaddr != u.nas_address) || u.type != P_LOGIN) {
150 continue;
151 }
152 /*
153 * Match. Zap it.
154 */
155 if (lseek(fd, -(off_t)sizeof(u), SEEK_CUR) < 0) {
156 REDEBUG("radutmp_zap: negative lseek!");
157 lseek(fd, (off_t)0, SEEK_SET);
158 }
159 u.type = P_IDLE;
160 u.time = t;
161
162 if (write(fd, &u, sizeof(u)) < 0) {
163 REDEBUG("Failed writing: %s", fr_syserror(errno));
164
165 close(fd);
167 }
168 }
169 close(fd); /* and implicitly release the locks */
170
172}
173
174/*
175 * Lookup a NAS_PORT in the nas_port_list
176 */
177static NAS_PORT *nas_port_find(NAS_PORT *nas_port_list, uint32_t nasaddr, uint16_t port)
178{
179 NAS_PORT *cl;
180
181 for(cl = nas_port_list; cl; cl = cl->next) {
182 if (nasaddr == cl->nasaddr &&
183 port == cl->port)
184 break;
185 }
186
187 return cl;
188}
189
190
191/*
192 * Store logins in the RADIUS utmp file.
193 */
194static unlang_action_t CC_HINT(nonnull) mod_accounting(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
195{
196 rlm_radutmp_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_radutmp_t);
197 rlm_radutmp_env_t *env = talloc_get_type_abort(mctx->env_data, rlm_radutmp_env_t);
199 struct radutmp ut, u;
200 fr_pair_t *vp;
201 int status = -1;
202 int protocol = -1;
203 time_t t;
204 int fd = -1;
205 bool port_seen = false;
206 int off;
207 char ip_name[INET_ADDRSTRLEN]; /* 255.255.255.255 */
208 char const *nas;
209 NAS_PORT *cache;
210 int r;
211 fr_client_t *client;
212
213 if (request->dict != dict_radius) RETURN_MODULE_NOOP;
214
215 if (request->packet->socket.inet.src_ipaddr.af != AF_INET) {
216 RDEBUG2("IPv6 not supported!");
218 }
219
220 /*
221 * Which type is this.
222 */
223 if ((vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_acct_status_type)) == NULL) {
224 RDEBUG2("No Accounting-Status-Type record");
226 }
227 status = vp->vp_uint32;
228
229 /*
230 * Look for weird reboot packets.
231 *
232 * ComOS (up to and including 3.5.1b20) does not send
233 * standard FR_STATUS_ACCOUNTING_XXX messages.
234 *
235 * Check for: o no Acct-Session-Time, or time of 0
236 * o Acct-Session-Id of "00000000".
237 *
238 * We could also check for NAS-Port, that attribute
239 * should NOT be present (but we don't right now).
240 */
241 if ((status != FR_STATUS_ACCOUNTING_ON) &&
242 (status != FR_STATUS_ACCOUNTING_OFF)) do {
243 int check1 = 0;
244 int check2 = 0;
245
246 if ((vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_acct_session_time))
247 == NULL || vp->vp_uint32 == 0)
248 check1 = 1;
249 if ((vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_acct_session_id))
250 != NULL && vp->vp_length == 8 &&
251 memcmp(vp->vp_strvalue, "00000000", 8) == 0)
252 check2 = 1;
253 if (check1 == 0 || check2 == 0) {
254 break;
255 }
256 RIDEBUG("Converting reboot records");
257 if (status == FR_STATUS_STOP) status = FR_STATUS_ACCOUNTING_OFF;
258 else if (status == FR_STATUS_START) status = FR_STATUS_ACCOUNTING_ON;
259 } while(0);
260
261 time(&t);
262 memset(&ut, 0, sizeof(ut));
263 ut.porttype = 'A';
264 ut.nas_address = htonl(INADDR_NONE);
265
266 /*
267 * First, find the interesting attributes.
268 */
269 for (vp = fr_pair_list_head(&request->request_pairs);
270 vp;
271 vp = fr_pair_list_next(&request->request_pairs, vp)) {
272 if ((vp->da == attr_login_ip_host) ||
274 ut.framed_address = vp->vp_ipv4addr;
275 } else if (vp->da == attr_framed_protocol) {
276 protocol = vp->vp_uint32;
277 } else if (vp->da == attr_nas_ip_address) {
278 ut.nas_address = vp->vp_ipv4addr;
279 } else if (vp->da == attr_nas_port) {
280 ut.nas_port = vp->vp_uint32;
281 port_seen = true;
282 } else if (vp->da == attr_acct_delay_time) {
283 ut.delay = vp->vp_uint32;
284 } else if (vp->da == attr_acct_session_id) {
285 /*
286 * If length > 8, only store the
287 * last 8 bytes.
288 */
289 off = vp->vp_length - sizeof(ut.session_id);
290 /*
291 * Ascend is br0ken - it adds a \0
292 * to the end of any string.
293 * Compensate.
294 */
295 if ((vp->vp_length > 0) && (vp->vp_strvalue[vp->vp_length - 1] == 0)) off--;
296 if (off < 0) off = 0;
297 memcpy(ut.session_id, vp->vp_strvalue + off, sizeof(ut.session_id));
298 } else if (vp->da == attr_nas_port_type) {
299 if (vp->vp_uint32 <= 4) ut.porttype = porttypes[vp->vp_uint32];
300 } else if (vp->da == attr_calling_station_id) {
301 if (inst->caller_id_ok) strlcpy(ut.caller_id, vp->vp_strvalue, sizeof(ut.caller_id));
302 }
303 }
304
305 /*
306 * If we didn't find out the NAS address, use the
307 * originator's IP address.
308 */
309 if (ut.nas_address == htonl(INADDR_NONE)) {
310 client = client_from_request(request);
311 if (!client) goto no_client;
312
313 ut.nas_address = request->packet->socket.inet.src_ipaddr.addr.v4.s_addr;
314 nas = client->shortname;
315
316 } else if (request->packet->socket.inet.src_ipaddr.addr.v4.s_addr == ut.nas_address) { /* might be a client, might not be. */
317 client = client_from_request(request);
318 if (!client) goto no_client;
319
320 nas = client->shortname;
321 /*
322 * The NAS isn't a client, it's behind
323 * a proxy server. In that case, just
324 * get the IP address.
325 */
326 } else {
327 no_client:
328 nas = inet_ntop(AF_INET, &ut.nas_address, ip_name, sizeof(ip_name));
329 }
330
331 /*
332 * Set the protocol field.
333 */
334 if (protocol == FR_PPP) {
335 ut.proto = 'P';
336 } else if (protocol == FR_SLIP) {
337 ut.proto = 'S';
338 } else {
339 ut.proto = 'T';
340 }
341
342 ut.time = t - ut.delay;
343
344 /*
345 * See if this was a reboot.
346 *
347 * Hmm... we may not want to zap all of the users when the NAS comes up, because of issues with receiving
348 * UDP packets out of order.
349 */
350 if (status == FR_STATUS_ACCOUNTING_ON && (ut.nas_address != htonl(INADDR_NONE))) {
351 RIDEBUG("NAS %s restarted (Accounting-On packet seen)", nas);
352 radutmp_zap(&rcode, request, env->filename.vb_strvalue, ut.nas_address, ut.time);
353
354 goto finish;
355 }
356
357 if (status == FR_STATUS_ACCOUNTING_OFF && (ut.nas_address != htonl(INADDR_NONE))) {
358 RIDEBUG("NAS %s rebooted (Accounting-Off packet seen)", nas);
359 radutmp_zap(&rcode, request, env->filename.vb_strvalue, ut.nas_address, ut.time);
360
361 goto finish;
362 }
363
364 /*
365 * If we don't know this type of entry pretend we succeeded.
366 */
367 if (status != FR_STATUS_START && status != FR_STATUS_STOP && status != FR_STATUS_ALIVE) {
368 REDEBUG("NAS %s port %u unknown packet type %d)", nas, ut.nas_port, status);
369 rcode = RLM_MODULE_NOOP;
370
371 goto finish;
372 }
373
374 /*
375 * Copy the expanded username to the radutmp structure
376 */
377 strlcpy(ut.login, env->username.vb_strvalue, RUT_NAMESIZE);
378
379 /*
380 * Perhaps we don't want to store this record into
381 * radutmp. We skip records:
382 *
383 * - without a NAS-Port (telnet / tcp access)
384 * - with the username "!root" (console admin login)
385 */
386 if (!port_seen) {
387 RWDEBUG2("No NAS-Port seen. Cannot do anything. Checkrad will probably not work!");
388 rcode = RLM_MODULE_NOOP;
389
390 goto finish;
391 }
392
393 if (strncmp(ut.login, "!root", RUT_NAMESIZE) == 0) {
394 RDEBUG2("Not recording administrative user");
395 rcode = RLM_MODULE_NOOP;
396
397 goto finish;
398 }
399
400 /*
401 * Enter into the radutmp file.
402 */
403 fd = open(env->filename.vb_strvalue, O_RDWR|O_CREAT, inst->permission);
404 if (fd < 0) {
405 REDEBUG("Error accessing file %pV: %s", &env->filename, fr_syserror(errno));
406 rcode = RLM_MODULE_FAIL;
407
408 goto finish;
409 }
410
411 /*
412 * Lock the utmp file, prefer lockf() over flock().
413 */
414 if (rad_lockfd(fd, LOCK_LEN) < 0) {
415 REDEBUG("Error acquiring lock on %pV: %s", &env->filename, fr_syserror(errno));
416 rcode = RLM_MODULE_FAIL;
417
418 goto finish;
419 }
420
421 /*
422 * Find the entry for this NAS / portno combination.
423 */
424 if ((cache = nas_port_find(inst->mutable->nas_port_list, ut.nas_address, ut.nas_port)) != NULL) {
425 if (lseek(fd, (off_t)cache->offset, SEEK_SET) < 0) {
426 rcode = RLM_MODULE_FAIL;
427 goto finish;
428 }
429 }
430
431 r = 0;
432 off = 0;
433 while (read(fd, &u, sizeof(u)) == sizeof(u)) {
434 off += sizeof(u);
435 if ((u.nas_address != ut.nas_address) || (u.nas_port != ut.nas_port)) {
436 continue;
437 }
438
439 /*
440 * Don't compare stop records to unused entries.
441 */
442 if (status == FR_STATUS_STOP && u.type == P_IDLE) {
443 continue;
444 }
445
446 if ((status == FR_STATUS_STOP) && strncmp(ut.session_id, u.session_id, sizeof(u.session_id)) != 0) {
447 /*
448 * Don't complain if this is not a
449 * login record (some clients can
450 * send _only_ logout records).
451 */
452 if (u.type == P_LOGIN) {
453 RWDEBUG("Logout entry for NAS %s port %u has wrong ID", nas, u.nas_port);
454 }
455
456 r = -1;
457 break;
458 }
459
460 if ((status == FR_STATUS_START) && strncmp(ut.session_id, u.session_id, sizeof(u.session_id)) == 0 &&
461 u.time >= ut.time) {
462 if (u.type == P_LOGIN) {
463 RIDEBUG("Login entry for NAS %s port %u duplicate", nas, u.nas_port);
464 r = -1;
465 break;
466 }
467
468 RWDEBUG("Login entry for NAS %s port %u wrong order", nas, u.nas_port);
469 r = -1;
470 break;
471 }
472
473 /*
474 * FIXME: the ALIVE record could need some more checking, but anyway I'd
475 * rather rewrite this mess -- miquels.
476 */
477 if ((status == FR_STATUS_ALIVE) && strncmp(ut.session_id, u.session_id, sizeof(u.session_id)) == 0 &&
478 u.type == P_LOGIN) {
479 /*
480 * Keep the original login time.
481 */
482 ut.time = u.time;
483 }
484
485 if (lseek(fd, -(off_t)sizeof(u), SEEK_CUR) < 0) {
486 RWDEBUG("negative lseek!");
487 lseek(fd, (off_t)0, SEEK_SET);
488 off = 0;
489 } else {
490 off -= sizeof(u);
491 }
492
493 r = 1;
494 break;
495 } /* read the file until we find a match */
496
497 /*
498 * Found the entry, do start/update it with
499 * the information from the packet.
500 */
501 if ((r >= 0) && (status == FR_STATUS_START || status == FR_STATUS_ALIVE)) {
502 /*
503 * Remember where the entry was, because it's
504 * easier than searching through the entire file.
505 */
506 if (!cache) {
507 cache = talloc_zero(inst->mutable, NAS_PORT);
508 if (cache) {
509 cache->nasaddr = ut.nas_address;
510 cache->port = ut.nas_port;
511 cache->offset = off;
512 cache->next = inst->mutable->nas_port_list;
513 inst->mutable->nas_port_list = cache;
514 }
515 }
516
517 ut.type = P_LOGIN;
518 if (write(fd, &ut, sizeof(u)) < 0) {
519 REDEBUG("Failed writing: %s", fr_syserror(errno));
520
521 rcode = RLM_MODULE_FAIL;
522 goto finish;
523 }
524 }
525
526 /*
527 * The user has logged off, delete the entry by
528 * re-writing it in place.
529 */
530 if (status == FR_STATUS_STOP) {
531 if (r > 0) {
532 u.type = P_IDLE;
533 u.time = ut.time;
534 u.delay = ut.delay;
535 if (write(fd, &u, sizeof(u)) < 0) {
536 REDEBUG("Failed writing: %s", fr_syserror(errno));
537
538 rcode = RLM_MODULE_FAIL;
539 goto finish;
540 }
541 } else if (r == 0) {
542 RWDEBUG("Logout for NAS %s port %u, but no Login record", nas, ut.nas_port);
543 }
544 }
545
546 finish:
547
548 if (fd > -1) {
549 close(fd); /* and implicitly release the locks */
550 }
551
552 RETURN_MODULE_RCODE(rcode);
553}
554
555static int mod_instantiate(module_inst_ctx_t const *mctx)
556{
557 rlm_radutmp_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_radutmp_t);
558
559 /*
560 * Must be in the NULL ctx so it doesn't
561 * end up in a protected page.
562 */
563 inst->mutable = talloc_zero(NULL, rlm_radutmp_mutable_t);
564
565 return 0;
566}
567
568static int mod_detach(module_detach_ctx_t const *mctx)
569{
570 rlm_radutmp_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_radutmp_t);
571
572 talloc_free(inst->mutable);
573
574 return 0;
575}
576
577/* globally exported name */
580 .common = {
581 .magic = MODULE_MAGIC_INIT,
582 .name = "radutmp",
584 .inst_size = sizeof(rlm_radutmp_t),
587 .detach = mod_detach
588 },
589 .method_group = {
590 .bindings = (module_method_binding_t[]){
591 { .section = SECTION_NAME("accounting", CF_IDENT_ANY), .method = mod_accounting, .method_env = &method_env },
593 }
594 }
595};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
#define RCSID(id)
Definition build.h:483
#define CALL_ENV_TERMINATOR
Definition call_env.h:231
#define FR_CALL_ENV_METHOD_OUT(_inst)
Helper macro for populating the size/type fields of a call_env_method_t from the output structure typ...
Definition call_env.h:235
call_env_parser_t const * env
Parsing rules for call method env.
Definition call_env.h:242
@ CALL_ENV_FLAG_REQUIRED
Associated conf pair or section is required.
Definition call_env.h:75
#define FR_CALL_ENV_OFFSET(_name, _cast_type, _flags, _struct, _field)
Specify a call_env_parser_t which writes out runtime results to the specified field.
Definition call_env.h:335
Per method call config.
Definition call_env.h:175
int cf_parse_permissions(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving permissions to a mode-t.
Definition cf_parse.c:1632
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:596
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:268
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:579
#define CF_IDENT_ANY
Definition cf_util.h:78
#define FR_STATUS_STOP
Definition defs.h:137
#define FR_STATUS_START
Definition defs.h:136
#define FR_PPP
Definition defs.h:131
#define FR_STATUS_ALIVE
Definition defs.h:138
#define FR_STATUS_ACCOUNTING_OFF
Definition defs.h:140
#define FR_SLIP
Definition defs.h:132
#define FR_STATUS_ACCOUNTING_ON
Definition defs.h:139
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:268
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:281
Specifies an attribute which must be present for the module to function.
Definition dict.h:267
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:280
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
char const * shortname
Client nickname.
Definition client.h:88
Describes a host allowed to send packets to the server.
Definition client.h:80
#define RWDEBUG(fmt,...)
Definition log.h:361
#define RWDEBUG2(fmt,...)
Definition log.h:362
talloc_free(reap)
unsigned short uint16_t
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
unsigned int uint32_t
unsigned int mode_t
long long int off_t
int rad_lockfd(int fd, int lock_len)
Definition misc.c:119
char const * inet_ntop(int af, void const *src, char *dst, size_t cnt)
Definition missing.c:443
void * env_data
Per call environment data.
Definition module_ctx.h:44
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
module_instance_t * mi
Module instance to detach.
Definition module_ctx.h:57
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for module calls.
Definition module_ctx.h:41
Temporary structure to hold arguments for detach calls.
Definition module_ctx.h:56
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:693
static const conf_parser_t config[]
Definition base.c:183
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG2(fmt,...)
Definition radclient.h:54
#define RIDEBUG(fmt,...)
Definition radsniff.h:65
unsigned int framed_address
Definition radutmp.h:60
char porttype
Definition radutmp.h:65
time_t time
Definition radutmp.h:62
char login[32]
Definition radutmp.h:54
int type
Definition radutmp.h:64
#define P_IDLE
Definition radutmp.h:50
unsigned int nas_address
Definition radutmp.h:59
char session_id[8]
Definition radutmp.h:57
time_t delay
Definition radutmp.h:63
char caller_id[16]
Definition radutmp.h:67
#define RUT_NAMESIZE
Definition radutmp.h:74
#define P_LOGIN
Definition radutmp.h:51
unsigned int nas_port
Definition radutmp.h:56
int proto
Definition radutmp.h:61
#define RETURN_MODULE_NOOP
Definition rcode.h:62
#define RETURN_MODULE_RCODE(_rcode)
Definition rcode.h:64
#define RETURN_MODULE_OK
Definition rcode.h:57
#define RETURN_MODULE_FAIL
Definition rcode.h:56
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:43
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:42
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition rcode.h:48
static fr_dict_attr_t const * attr_login_ip_host
Definition rlm_radutmp.c:99
static int mod_detach(module_detach_ctx_t const *mctx)
fr_dict_attr_autoload_t rlm_radutmp_dict_attr[]
module_rlm_t rlm_radutmp
static fr_dict_attr_t const * attr_acct_session_time
Definition rlm_radutmp.c:94
fr_value_box_t username
Definition rlm_radutmp.c:64
static const call_env_method_t method_env
Definition rlm_radutmp.c:74
static fr_dict_attr_t const * attr_nas_port_type
static fr_dict_attr_t const * attr_calling_station_id
Definition rlm_radutmp.c:96
static fr_dict_t const * dict_radius
Definition rlm_radutmp.c:84
mode_t permission
Definition rlm_radutmp.c:58
static fr_dict_attr_t const * attr_nas_ip_address
uint16_t port
Definition rlm_radutmp.c:46
off_t offset
Definition rlm_radutmp.c:47
static unlang_action_t radutmp_zap(rlm_rcode_t *p_result, request_t *request, char const *filename, uint32_t nasaddr, time_t t)
#define LOCK_LEN
Definition rlm_radutmp.c:36
static fr_dict_attr_t const * attr_framed_ip_address
Definition rlm_radutmp.c:97
static unlang_action_t mod_accounting(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
uint32_t nasaddr
Definition rlm_radutmp.c:45
fr_value_box_t filename
Definition rlm_radutmp.c:63
static fr_dict_attr_t const * attr_framed_protocol
Definition rlm_radutmp.c:98
static fr_dict_attr_t const * attr_nas_port
fr_dict_autoload_t rlm_radutmp_dict[]
Definition rlm_radutmp.c:87
static fr_dict_attr_t const * attr_acct_status_type
Definition rlm_radutmp.c:95
NAS_PORT * nas_port_list
Definition rlm_radutmp.c:52
static fr_dict_attr_t const * attr_acct_delay_time
Definition rlm_radutmp.c:92
static const conf_parser_t module_config[]
Definition rlm_radutmp.c:67
NAS_PORT * next
Definition rlm_radutmp.c:48
static int mod_instantiate(module_inst_ctx_t const *mctx)
static char const porttypes[]
Definition rlm_radutmp.c:38
static fr_dict_attr_t const * attr_acct_session_id
Definition rlm_radutmp.c:93
static NAS_PORT * nas_port_find(NAS_PORT *nas_port_list, uint32_t nasaddr, uint16_t port)
static int instantiate(module_inst_ctx_t const *mctx)
Definition rlm_rest.c:1310
username
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition section.h:40
@ MODULE_TYPE_THREAD_UNSAFE
Module is not threadsafe.
Definition module.h:48
module_flags_t flags
Flags that control how a module starts up and how a module is called.
Definition module.h:227
void * data
Module's instance data.
Definition module.h:271
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition module.h:151
Named methods exported by a module.
Definition module.h:173
fr_client_t * client_from_request(request_t *request)
Search up a list of requests trying to locate one which has a client.
Definition client.c:1112
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition strlcpy.c:34
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
@ T_DOUBLE_QUOTED_STRING
Definition token.h:121
close(uq->fd)
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
Definition pair_inline.c:70
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition pair_inline.c:43
int nonnull(2, 5))