The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: 77dec2ca063072afc583583d141a570f6c296659 $
19  * @file rlm_radutmp.c
20  * @brief Tracks sessions.
21  *
22  * @copyright 2000-2013 The FreeRADIUS server project
23  */
24 RCSID("$Id: 77dec2ca063072afc583583d141a570f6c296659 $")
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 
38 static char const porttypes[] = "ASITX";
39 
40 /*
41  * used for caching radutmp lookups in the accounting component.
42  */
43 typedef struct nas_port_s NAS_PORT;
44 struct nas_port_s {
49 };
50 
51 typedef struct {
53  bool check_nas;
57 
58 typedef struct {
62 
63 static const conf_parser_t module_config[] = {
64  { FR_CONF_OFFSET("check_with_nas", rlm_radutmp_t, check_nas), .dflt = "yes" },
65  { FR_CONF_OFFSET("permissions", rlm_radutmp_t, permission), .dflt = "0644" },
66  { FR_CONF_OFFSET("caller_id", rlm_radutmp_t, caller_id_ok), .dflt = "no" },
68 };
69 
70 static fr_dict_t const *dict_radius;
71 
74  { .out = &dict_radius, .proto = "radius" },
75  { NULL }
76 };
77 
89 
92  { .out = &attr_acct_delay_time, .name = "Acct-Delay-Time", .type = FR_TYPE_UINT32, .dict = &dict_radius },
93  { .out = &attr_acct_session_id, .name = "Acct-Session-Id", .type = FR_TYPE_STRING, .dict = &dict_radius },
94  { .out = &attr_acct_session_time, .name = "Acct-Session-Time", .type = FR_TYPE_UINT32, .dict = &dict_radius },
95  { .out = &attr_acct_status_type, .name = "Acct-Status-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
96  { .out = &attr_calling_station_id, .name = "Calling-Station-Id", .type = FR_TYPE_STRING, .dict = &dict_radius },
97  { .out = &attr_framed_ip_address, .name = "Framed-IP-Address", .type = FR_TYPE_IPV4_ADDR, .dict = &dict_radius },
98  { .out = &attr_framed_protocol, .name = "Framed-Protocol", .type = FR_TYPE_UINT32, .dict = &dict_radius },
99  { .out = &attr_login_ip_host, .name = "Login-IP-Host", .type = FR_TYPE_IPV4_ADDR, .dict = &dict_radius },
100  { .out = &attr_nas_ip_address, .name = "NAS-IP-Address", .type = FR_TYPE_IPV4_ADDR, .dict = &dict_radius },
101  { .out = &attr_nas_port, .name = "NAS-Port", .type = FR_TYPE_UINT32, .dict = &dict_radius },
102  { .out = &attr_nas_port_type, .name = "NAS-Port-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
103  { NULL }
104 };
105 
106 /*
107  * Zap all users on a NAS from the radutmp file.
108  */
109 static unlang_action_t radutmp_zap(rlm_rcode_t *p_result, request_t *request, char const *filename, uint32_t nasaddr, time_t t)
110 {
111  struct radutmp u;
112  int fd;
113 
114  if (t == 0) time(&t);
115 
116  fd = open(filename, O_RDWR);
117  if (fd < 0) {
118  REDEBUG("Error accessing file %s: %s", filename, fr_syserror(errno));
120  }
121 
122  /*
123  * Lock the utmp file, prefer lockf() over flock().
124  */
125  if (rad_lockfd(fd, LOCK_LEN) < 0) {
126  REDEBUG("Failed to acquire lock on file %s: %s", filename, fr_syserror(errno));
127  close(fd);
129  }
130 
131  /*
132  * Find the entry for this NAS / portno combination.
133  */
134  while (read(fd, &u, sizeof(u)) == sizeof(u)) {
135  if ((nasaddr != 0 && nasaddr != u.nas_address) || u.type != P_LOGIN) {
136  continue;
137  }
138  /*
139  * Match. Zap it.
140  */
141  if (lseek(fd, -(off_t)sizeof(u), SEEK_CUR) < 0) {
142  REDEBUG("radutmp_zap: negative lseek!");
143  lseek(fd, (off_t)0, SEEK_SET);
144  }
145  u.type = P_IDLE;
146  u.time = t;
147 
148  if (write(fd, &u, sizeof(u)) < 0) {
149  REDEBUG("Failed writing: %s", fr_syserror(errno));
150 
151  close(fd);
153  }
154  }
155  close(fd); /* and implicitly release the locks */
156 
158 }
159 
160 /*
161  * Lookup a NAS_PORT in the nas_port_list
162  */
163 static NAS_PORT *nas_port_find(NAS_PORT *nas_port_list, uint32_t nasaddr, uint16_t port)
164 {
165  NAS_PORT *cl;
166 
167  for(cl = nas_port_list; cl; cl = cl->next) {
168  if (nasaddr == cl->nasaddr &&
169  port == cl->port)
170  break;
171  }
172 
173  return cl;
174 }
175 
176 
177 /*
178  * Store logins in the RADIUS utmp file.
179  */
180 static unlang_action_t CC_HINT(nonnull) mod_accounting(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
181 {
182  rlm_radutmp_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_radutmp_t);
183  rlm_radutmp_env_t *env = talloc_get_type_abort(mctx->env_data, rlm_radutmp_env_t);
184  rlm_rcode_t rcode = RLM_MODULE_OK;
185  struct radutmp ut, u;
186  fr_pair_t *vp;
187  int status = -1;
188  int protocol = -1;
189  time_t t;
190  int fd = -1;
191  bool port_seen = false;
192  int off;
193  char ip_name[INET_ADDRSTRLEN]; /* 255.255.255.255 */
194  char const *nas;
195  NAS_PORT *cache;
196  int r;
197  fr_client_t *client;
198 
199  if (request->dict != dict_radius) RETURN_MODULE_NOOP;
200 
201  if (request->packet->socket.inet.src_ipaddr.af != AF_INET) {
202  RDEBUG2("IPv6 not supported!");
204  }
205 
206  /*
207  * Which type is this.
208  */
209  if ((vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_acct_status_type)) == NULL) {
210  RDEBUG2("No Accounting-Status-Type record");
212  }
213  status = vp->vp_uint32;
214 
215  /*
216  * Look for weird reboot packets.
217  *
218  * ComOS (up to and including 3.5.1b20) does not send
219  * standard FR_STATUS_ACCOUNTING_XXX messages.
220  *
221  * Check for: o no Acct-Session-Time, or time of 0
222  * o Acct-Session-Id of "00000000".
223  *
224  * We could also check for NAS-Port, that attribute
225  * should NOT be present (but we don't right now).
226  */
227  if ((status != FR_STATUS_ACCOUNTING_ON) &&
228  (status != FR_STATUS_ACCOUNTING_OFF)) do {
229  int check1 = 0;
230  int check2 = 0;
231 
232  if ((vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_acct_session_time))
233  == NULL || vp->vp_uint32 == 0)
234  check1 = 1;
235  if ((vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_acct_session_id))
236  != NULL && vp->vp_length == 8 &&
237  memcmp(vp->vp_strvalue, "00000000", 8) == 0)
238  check2 = 1;
239  if (check1 == 0 || check2 == 0) {
240  break;
241  }
242  RIDEBUG("Converting reboot records");
243  if (status == FR_STATUS_STOP) status = FR_STATUS_ACCOUNTING_OFF;
244  else if (status == FR_STATUS_START) status = FR_STATUS_ACCOUNTING_ON;
245  } while(0);
246 
247  time(&t);
248  memset(&ut, 0, sizeof(ut));
249  ut.porttype = 'A';
250  ut.nas_address = htonl(INADDR_NONE);
251 
252  /*
253  * First, find the interesting attributes.
254  */
255  for (vp = fr_pair_list_head(&request->request_pairs);
256  vp;
257  vp = fr_pair_list_next(&request->request_pairs, vp)) {
258  if ((vp->da == attr_login_ip_host) ||
259  (vp->da == attr_framed_ip_address)) {
260  ut.framed_address = vp->vp_ipv4addr;
261  } else if (vp->da == attr_framed_protocol) {
262  protocol = vp->vp_uint32;
263  } else if (vp->da == attr_nas_ip_address) {
264  ut.nas_address = vp->vp_ipv4addr;
265  } else if (vp->da == attr_nas_port) {
266  ut.nas_port = vp->vp_uint32;
267  port_seen = true;
268  } else if (vp->da == attr_acct_delay_time) {
269  ut.delay = vp->vp_uint32;
270  } else if (vp->da == attr_acct_session_id) {
271  /*
272  * If length > 8, only store the
273  * last 8 bytes.
274  */
275  off = vp->vp_length - sizeof(ut.session_id);
276  /*
277  * Ascend is br0ken - it adds a \0
278  * to the end of any string.
279  * Compensate.
280  */
281  if ((vp->vp_length > 0) && (vp->vp_strvalue[vp->vp_length - 1] == 0)) off--;
282  if (off < 0) off = 0;
283  memcpy(ut.session_id, vp->vp_strvalue + off, sizeof(ut.session_id));
284  } else if (vp->da == attr_nas_port_type) {
285  if (vp->vp_uint32 <= 4) ut.porttype = porttypes[vp->vp_uint32];
286  } else if (vp->da == attr_calling_station_id) {
287  if (inst->caller_id_ok) strlcpy(ut.caller_id, vp->vp_strvalue, sizeof(ut.caller_id));
288  }
289  }
290 
291  /*
292  * If we didn't find out the NAS address, use the
293  * originator's IP address.
294  */
295  if (ut.nas_address == htonl(INADDR_NONE)) {
296  client = client_from_request(request);
297  if (!client) goto no_client;
298 
299  ut.nas_address = request->packet->socket.inet.src_ipaddr.addr.v4.s_addr;
300  nas = client->shortname;
301 
302  } else if (request->packet->socket.inet.src_ipaddr.addr.v4.s_addr == ut.nas_address) { /* might be a client, might not be. */
303  client = client_from_request(request);
304  if (!client) goto no_client;
305 
306  nas = client->shortname;
307  /*
308  * The NAS isn't a client, it's behind
309  * a proxy server. In that case, just
310  * get the IP address.
311  */
312  } else {
313  no_client:
314  nas = inet_ntop(AF_INET, &ut.nas_address, ip_name, sizeof(ip_name));
315  }
316 
317  /*
318  * Set the protocol field.
319  */
320  if (protocol == FR_PPP) {
321  ut.proto = 'P';
322  } else if (protocol == FR_SLIP) {
323  ut.proto = 'S';
324  } else {
325  ut.proto = 'T';
326  }
327 
328  ut.time = t - ut.delay;
329 
330  /*
331  * See if this was a reboot.
332  *
333  * Hmm... we may not want to zap all of the users when the NAS comes up, because of issues with receiving
334  * UDP packets out of order.
335  */
336  if (status == FR_STATUS_ACCOUNTING_ON && (ut.nas_address != htonl(INADDR_NONE))) {
337  RIDEBUG("NAS %s restarted (Accounting-On packet seen)", nas);
338  radutmp_zap(&rcode, request, env->filename.vb_strvalue, ut.nas_address, ut.time);
339 
340  goto finish;
341  }
342 
343  if (status == FR_STATUS_ACCOUNTING_OFF && (ut.nas_address != htonl(INADDR_NONE))) {
344  RIDEBUG("NAS %s rebooted (Accounting-Off packet seen)", nas);
345  radutmp_zap(&rcode, request, env->filename.vb_strvalue, ut.nas_address, ut.time);
346 
347  goto finish;
348  }
349 
350  /*
351  * If we don't know this type of entry pretend we succeeded.
352  */
353  if (status != FR_STATUS_START && status != FR_STATUS_STOP && status != FR_STATUS_ALIVE) {
354  REDEBUG("NAS %s port %u unknown packet type %d)", nas, ut.nas_port, status);
355  rcode = RLM_MODULE_NOOP;
356 
357  goto finish;
358  }
359 
360  /*
361  * Copy the expanded username to the radutmp structure
362  */
363  strlcpy(ut.login, env->username.vb_strvalue, RUT_NAMESIZE);
364 
365  /*
366  * Perhaps we don't want to store this record into
367  * radutmp. We skip records:
368  *
369  * - without a NAS-Port (telnet / tcp access)
370  * - with the username "!root" (console admin login)
371  */
372  if (!port_seen) {
373  RWDEBUG2("No NAS-Port seen. Cannot do anything. Checkrad will probably not work!");
374  rcode = RLM_MODULE_NOOP;
375 
376  goto finish;
377  }
378 
379  if (strncmp(ut.login, "!root", RUT_NAMESIZE) == 0) {
380  RDEBUG2("Not recording administrative user");
381  rcode = RLM_MODULE_NOOP;
382 
383  goto finish;
384  }
385 
386  /*
387  * Enter into the radutmp file.
388  */
389  fd = open(env->filename.vb_strvalue, O_RDWR|O_CREAT, inst->permission);
390  if (fd < 0) {
391  REDEBUG("Error accessing file %pV: %s", &env->filename, fr_syserror(errno));
392  rcode = RLM_MODULE_FAIL;
393 
394  goto finish;
395  }
396 
397  /*
398  * Lock the utmp file, prefer lockf() over flock().
399  */
400  if (rad_lockfd(fd, LOCK_LEN) < 0) {
401  REDEBUG("Error acquiring lock on %pV: %s", &env->filename, fr_syserror(errno));
402  rcode = RLM_MODULE_FAIL;
403 
404  goto finish;
405  }
406 
407  /*
408  * Find the entry for this NAS / portno combination.
409  */
410  if ((cache = nas_port_find(inst->nas_port_list, ut.nas_address, ut.nas_port)) != NULL) {
411  if (lseek(fd, (off_t)cache->offset, SEEK_SET) < 0) {
412  rcode = RLM_MODULE_FAIL;
413  goto finish;
414  }
415  }
416 
417  r = 0;
418  off = 0;
419  while (read(fd, &u, sizeof(u)) == sizeof(u)) {
420  off += sizeof(u);
421  if ((u.nas_address != ut.nas_address) || (u.nas_port != ut.nas_port)) {
422  continue;
423  }
424 
425  /*
426  * Don't compare stop records to unused entries.
427  */
428  if (status == FR_STATUS_STOP && u.type == P_IDLE) {
429  continue;
430  }
431 
432  if ((status == FR_STATUS_STOP) && strncmp(ut.session_id, u.session_id, sizeof(u.session_id)) != 0) {
433  /*
434  * Don't complain if this is not a
435  * login record (some clients can
436  * send _only_ logout records).
437  */
438  if (u.type == P_LOGIN) {
439  RWDEBUG("Logout entry for NAS %s port %u has wrong ID", nas, u.nas_port);
440  }
441 
442  r = -1;
443  break;
444  }
445 
446  if ((status == FR_STATUS_START) && strncmp(ut.session_id, u.session_id, sizeof(u.session_id)) == 0 &&
447  u.time >= ut.time) {
448  if (u.type == P_LOGIN) {
449  RIDEBUG("Login entry for NAS %s port %u duplicate", nas, u.nas_port);
450  r = -1;
451  break;
452  }
453 
454  RWDEBUG("Login entry for NAS %s port %u wrong order", nas, u.nas_port);
455  r = -1;
456  break;
457  }
458 
459  /*
460  * FIXME: the ALIVE record could need some more checking, but anyway I'd
461  * rather rewrite this mess -- miquels.
462  */
463  if ((status == FR_STATUS_ALIVE) && strncmp(ut.session_id, u.session_id, sizeof(u.session_id)) == 0 &&
464  u.type == P_LOGIN) {
465  /*
466  * Keep the original login time.
467  */
468  ut.time = u.time;
469  }
470 
471  if (lseek(fd, -(off_t)sizeof(u), SEEK_CUR) < 0) {
472  RWDEBUG("negative lseek!");
473  lseek(fd, (off_t)0, SEEK_SET);
474  off = 0;
475  } else {
476  off -= sizeof(u);
477  }
478 
479  r = 1;
480  break;
481  } /* read the file until we find a match */
482 
483  /*
484  * Found the entry, do start/update it with
485  * the information from the packet.
486  */
487  if ((r >= 0) && (status == FR_STATUS_START || status == FR_STATUS_ALIVE)) {
488  /*
489  * Remember where the entry was, because it's
490  * easier than searching through the entire file.
491  */
492  if (!cache) {
493  cache = talloc_zero(inst, NAS_PORT);
494  if (cache) {
495  cache->nasaddr = ut.nas_address;
496  cache->port = ut.nas_port;
497  cache->offset = off;
498  cache->next = inst->nas_port_list;
499  inst->nas_port_list = cache;
500  }
501  }
502 
503  ut.type = P_LOGIN;
504  if (write(fd, &ut, sizeof(u)) < 0) {
505  REDEBUG("Failed writing: %s", fr_syserror(errno));
506 
507  rcode = RLM_MODULE_FAIL;
508  goto finish;
509  }
510  }
511 
512  /*
513  * The user has logged off, delete the entry by
514  * re-writing it in place.
515  */
516  if (status == FR_STATUS_STOP) {
517  if (r > 0) {
518  u.type = P_IDLE;
519  u.time = ut.time;
520  u.delay = ut.delay;
521  if (write(fd, &u, sizeof(u)) < 0) {
522  REDEBUG("Failed writing: %s", fr_syserror(errno));
523 
524  rcode = RLM_MODULE_FAIL;
525  goto finish;
526  }
527  } else if (r == 0) {
528  RWDEBUG("Logout for NAS %s port %u, but no Login record", nas, ut.nas_port);
529  }
530  }
531 
532  finish:
533 
534  if (fd > -1) {
535  close(fd); /* and implicitly release the locks */
536  }
537 
538  RETURN_MODULE_RCODE(rcode);
539 }
540 
543  .env = (call_env_parser_t[]) {
546  .pair.dflt = "%{User-Name}", .pair.dflt_quote = T_DOUBLE_QUOTED_STRING },
548  }
549 };
550 
551 /* globally exported name */
554  .common = {
555  .magic = MODULE_MAGIC_INIT,
556  .name = "radutmp",
557  .flags = MODULE_TYPE_THREAD_UNSAFE,
558  .inst_size = sizeof(rlm_radutmp_t),
560  },
561  .method_names = (module_method_name_t[]){
562  { .name1 = "accounting", .name2 = CF_IDENT_ANY, .method = mod_accounting,
563  .method_env = &method_env },
565  }
566 };
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:444
#define CALL_ENV_TERMINATOR
Definition: call_env.h:212
#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:216
@ CALL_ENV_FLAG_REQUIRED
Associated conf pair or section is required.
Definition: call_env.h:73
#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:316
Per method call config.
Definition: call_env.h:171
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:626
#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
char const * name1
Name of the CONF_ITEM to parse.
Definition: cf_parse.h:564
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
#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:250
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:263
Specifies an attribute which must be present for the module to function.
Definition: dict.h:249
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:262
void *_CONST data
Module instance's parsed configuration.
Definition: dl_module.h:165
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:65
char const * shortname
Client nickname.
Definition: client.h:85
Describes a host allowed to send packets to the server.
Definition: client.h:77
#define RWDEBUG(fmt,...)
Definition: log.h:361
#define RWDEBUG2(fmt,...)
Definition: log.h:362
unsigned short uint16_t
Definition: merged_model.c:31
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
Definition: merged_model.c:86
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
unsigned int uint32_t
Definition: merged_model.c:33
long long int off_t
Definition: merged_model.c:22
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
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:42
Temporary structure to hold arguments for module calls.
Definition: module_ctx.h:41
Specifies a module method identifier.
Definition: module_method.c:36
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:37
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:688
static const conf_parser_t config[]
Definition: base.c:188
#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
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:85
fr_dict_attr_autoload_t rlm_radutmp_dict_attr[]
Definition: rlm_radutmp.c:91
module_rlm_t rlm_radutmp
Definition: rlm_radutmp.c:553
static fr_dict_attr_t const * attr_acct_session_time
Definition: rlm_radutmp.c:80
fr_value_box_t username
Definition: rlm_radutmp.c:60
static const call_env_method_t method_env
Definition: rlm_radutmp.c:541
static fr_dict_attr_t const * attr_nas_port_type
Definition: rlm_radutmp.c:88
static fr_dict_attr_t const * attr_calling_station_id
Definition: rlm_radutmp.c:82
static fr_dict_t const * dict_radius
Definition: rlm_radutmp.c:70
static NAS_PORT * nas_port_find(NAS_PORT *nas_port_list, uint32_t nasaddr, uint16_t port)
Definition: rlm_radutmp.c:163
static fr_dict_attr_t const * attr_nas_ip_address
Definition: rlm_radutmp.c:86
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)
Definition: rlm_radutmp.c:109
#define LOCK_LEN
Definition: rlm_radutmp.c:36
static fr_dict_attr_t const * attr_framed_ip_address
Definition: rlm_radutmp.c:83
static unlang_action_t mod_accounting(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition: rlm_radutmp.c:180
NAS_PORT * nas_port_list
Definition: rlm_radutmp.c:52
uint32_t nasaddr
Definition: rlm_radutmp.c:45
fr_value_box_t filename
Definition: rlm_radutmp.c:59
static fr_dict_attr_t const * attr_framed_protocol
Definition: rlm_radutmp.c:84
static fr_dict_attr_t const * attr_nas_port
Definition: rlm_radutmp.c:87
fr_dict_autoload_t rlm_radutmp_dict[]
Definition: rlm_radutmp.c:73
bool caller_id_ok
Definition: rlm_radutmp.c:55
static fr_dict_attr_t const * attr_acct_status_type
Definition: rlm_radutmp.c:81
uint32_t permission
Definition: rlm_radutmp.c:54
static fr_dict_attr_t const * attr_acct_delay_time
Definition: rlm_radutmp.c:78
static const conf_parser_t module_config[]
Definition: rlm_radutmp.c:63
NAS_PORT * next
Definition: rlm_radutmp.c:48
static char const porttypes[]
Definition: rlm_radutmp.c:38
static fr_dict_attr_t const * attr_acct_session_id
Definition: rlm_radutmp.c:79
username
Definition: rlm_securid.c:420
@ MODULE_TYPE_THREAD_UNSAFE
Module is not threadsafe.
Definition: module.h:50
#define MODULE_NAME_TERMINATOR
Definition: module.h:135
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:1092
RETURN_MODULE_FAIL
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_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition: pair_inline.c:43
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
int nonnull(2, 5))