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: 0b05b0049344d6f9bf4ae6138b25cf3a227c90df $
19  * @file rlm_radutmp.c
20  * @brief Tracks sessions.
21  *
22  * @copyright 2000-2013 The FreeRADIUS server project
23  */
24 RCSID("$Id: 0b05b0049344d6f9bf4ae6138b25cf3a227c90df $")
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 {
54 
55 typedef struct {
57  bool check_nas;
61 
62 typedef struct {
66 
67 static 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" },
70  { FR_CONF_OFFSET("caller_id", rlm_radutmp_t, caller_id_ok), .dflt = "no" },
72 };
73 
74 static const call_env_method_t method_env = {
76  .env = (call_env_parser_t[]) {
79  .pair.dflt = "%{User-Name}", .pair.dflt_quote = T_DOUBLE_QUOTED_STRING },
81  }
82 };
83 
84 static 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  */
123 static 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  */
177 static 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  */
194 static 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);
198  rlm_rcode_t rcode = RLM_MODULE_OK;
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) ||
273  (vp->da == attr_framed_ip_address)) {
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 
555 static 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 
568 static 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",
583  .flags = MODULE_TYPE_THREAD_UNSAFE,
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:481
#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_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
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:627
#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:564
#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:267
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:280
Specifies an attribute which must be present for the module to function.
Definition: dict.h:266
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:279
#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
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
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
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)
Definition: rlm_radutmp.c:568
fr_dict_attr_autoload_t rlm_radutmp_dict_attr[]
Definition: rlm_radutmp.c:105
module_rlm_t rlm_radutmp
Definition: rlm_radutmp.c:579
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
Definition: rlm_radutmp.c:102
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
static NAS_PORT * nas_port_find(NAS_PORT *nas_port_list, uint32_t nasaddr, uint16_t port)
Definition: rlm_radutmp.c:177
static fr_dict_attr_t const * attr_nas_ip_address
Definition: rlm_radutmp.c:100
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:123
#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)
Definition: rlm_radutmp.c:194
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
Definition: rlm_radutmp.c:101
fr_dict_autoload_t rlm_radutmp_dict[]
Definition: rlm_radutmp.c:87
bool caller_id_ok
Definition: rlm_radutmp.c:59
static fr_dict_attr_t const * attr_acct_status_type
Definition: rlm_radutmp.c:95
uint32_t permission
Definition: rlm_radutmp.c:58
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)
Definition: rlm_radutmp.c:555
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 int instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_rest.c:1302
username
Definition: rlm_securid.c:420
#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
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
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))