24 RCSID(
"$Id: 9f45f1083bf9620144c4c7be021e531a395d106c $")
26 #include <freeradius-devel/radiusd.h>
27 #include <freeradius-devel/radutmp.h>
28 #include <freeradius-devel/modules.h>
29 #include <freeradius-devel/rad_assert.h>
35 #define LOCK_LEN sizeof(struct radutmp)
71 #ifdef WITH_ACCOUNTING
82 fd = open(filename, O_RDWR);
100 while (read(fd, &u,
sizeof(u)) ==
sizeof(u)) {
107 if (lseek(fd, -(off_t)
sizeof(u), SEEK_CUR) < 0) {
108 REDEBUG(
"radutmp_zap: negative lseek!");
109 lseek(fd, (off_t)0, SEEK_SET);
114 if (write(fd, &u,
sizeof(u)) < 0) {
133 for(cl = nas_port_list; cl; cl = cl->
next) {
156 bool port_seen =
false;
159 char ip_name[INET_ADDRSTRLEN];
164 char *filename = NULL;
165 char *expanded = NULL;
167 if (request->packet->src_ipaddr.af != AF_INET) {
168 DEBUG(
"rlm_radutmp: IPv6 not supported!");
176 RDEBUG(
"No Accounting-Status-Type record");
179 status = vp->vp_integer;
199 == NULL || vp->vp_date == 0)
202 != NULL && vp->vp_length == 8 &&
203 memcmp(vp->vp_strvalue,
"00000000", 8) == 0)
205 if (check1 == 0 || check2 == 0) {
208 INFO(
"rlm_radutmp: converting reboot records");
216 memset(&ut, 0,
sizeof(ut));
227 case PW_LOGIN_IP_HOST:
228 case PW_FRAMED_IP_ADDRESS:
232 case PW_FRAMED_PROTOCOL:
233 protocol = vp->vp_integer;
236 case PW_NAS_IP_ADDRESS:
245 case PW_ACCT_DELAY_TIME:
246 ut.
delay = vp->vp_integer;
249 case PW_ACCT_SESSION_ID:
260 if (vp->vp_length > 0 &&
261 vp->vp_strvalue[vp->vp_length - 1] == 0)
263 if (off < 0) off = 0;
268 case PW_NAS_PORT_TYPE:
269 if (vp->vp_integer <= 4)
270 ut.
porttype = porttypes[vp->vp_integer];
273 case PW_CALLING_STATION_ID:
284 ut.
nas_address = request->packet->src_ipaddr.ipaddr.ip4addr.s_addr;
285 nas = request->client->shortname;
287 }
else if (request->packet->src_ipaddr.ipaddr.ip4addr.s_addr == ut.
nas_address) {
288 nas = request->client->shortname;
304 }
else if (protocol ==
PW_SLIP) {
327 RIDEBUG(
"NAS %s restarted (Accounting-On packet seen)", nas);
334 RIDEBUG(
"NAS %s rebooted (Accounting-Off packet seen)", nas);
344 REDEBUG(
"NAS %s port %u unknown packet type %d)", nas, ut.
nas_port, status);
359 TALLOC_FREE(expanded);
369 RWDEBUG2(
"No NAS-Port seen. Cannot do anything. Checkrad will probably not work!");
376 RDEBUG2(
"Not recording administrative user");
385 fd = open(filename, O_RDWR|O_CREAT, inst->
permission);
407 if (lseek(fd, (off_t)cache->
offset, SEEK_SET) < 0) {
415 while (read(fd, &u,
sizeof(u)) ==
sizeof(u)) {
435 RWDEBUG(
"Logout entry for NAS %s port %u has wrong ID", nas, u.
nas_port);
445 INFO(
"rlm_radutmp: Login entry for NAS %s port %u duplicate",
451 RWDEBUG(
"Login entry for NAS %s port %u wrong order", nas, u.
nas_port);
468 if (lseek(fd, -(off_t)
sizeof(u), SEEK_CUR) < 0) {
470 lseek(fd, (off_t)0, SEEK_SET);
490 cache = talloc_zero(NULL,
NAS_PORT);
501 if (write(fd, &ut,
sizeof(u)) < 0) {
518 if (write(fd, &u,
sizeof(u)) < 0) {
525 RWDEBUG(
"Logout for NAS %s port %u, but no Login record", nas, ut.
nas_port);
531 talloc_free(filename);
541 #ifdef WITH_SESSION_MGMT
559 char const *call_num = NULL;
562 char *expanded = NULL;
572 fd = open(expanded, O_RDWR);
578 if (errno == ENOENT) {
579 request->simul_count=0;
586 ERROR(
"rlm_radumtp: Error accessing file %s: %s", expanded,
fr_syserror(errno));
593 TALLOC_FREE(expanded);
613 request->simul_count = 0;
618 while (read(fd, &u,
sizeof(u)) ==
sizeof(u)) {
622 ++request->simul_count;
630 if ((request->simul_count < request->simul_max) || !inst->
check_nas) {
635 lseek(fd, (off_t)0, SEEK_SET);
641 ipno = vp->vp_ipaddr;
645 call_num = vp->vp_strvalue;
659 request->simul_count = 0;
660 while (read(fd, &u,
sizeof(u)) ==
sizeof(u)) {
664 char utmp_login[
sizeof(u.login) + 1];
667 u.session_id[
sizeof(u.session_id) - 1] =
'\0';
686 memset(utmp_login, 0,
sizeof(utmp_login));
687 memcpy(utmp_login, u.login,
sizeof(u.login));
703 u.framed_address, u.proto, 0);
705 else if (rcode == 1) {
709 ++request->simul_count;
714 if (strchr(
"SCPA", u.proto) && ipno && u.framed_address == ipno) {
715 request->simul_mpp = 2;
716 }
else if (strchr(
"SCPA", u.proto) && call_num && !strncmp(u.caller_id, call_num,16)) {
717 request->simul_mpp = 2;
720 RWDEBUG(
"Failed to check the terminal server for user '%s'.", utmp_login);
729 talloc_free(expanded);
746 .config = module_config,
748 #ifdef WITH_ACCOUNTING
751 #ifdef WITH_SESSION_MGMT
ssize_t ssize_t ssize_t radius_axlat(char **out, REQUEST *request, char const *fmt, xlat_escape_t escape, void *escape_ctx) CC_HINT(nonnull(1
int session_zap(REQUEST *request, uint32_t nasaddr, uint32_t nas_port, char const *user, char const *sessionid, uint32_t cliaddr, char proto, int session_time)
int rad_lockfd(int fd, int lock_len)
static rlm_rcode_t mod_accounting(void *instance, REQUEST *request)
Write accounting data to Couchbase documents.
The module is OK, continue.
Metadata exported by the module.
#define RLM_TYPE_THREAD_UNSAFE
Module is not threadsafe.
#define CONF_PARSER_TERMINATOR
char const * inet_ntop(int af, void const *src, char *dst, size_t cnt)
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
#define RLM_TYPE_HUP_SAFE
Will be restarted on HUP.
Defines a CONF_PAIR to C data type mapping.
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
static rlm_rcode_t radutmp_zap(REQUEST *request, char const *filename, uint32_t nasaddr, time_t t)
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
unsigned int framed_address
#define PW_TYPE_XLAT
string will be dynamically expanded.
4 methods index for checksimul section.
unsigned int attr
Attribute number.
3 methods index for accounting section.
unsigned int vendor
Vendor that defines this attribute.
Stores an attribute, a value and various bits of other data.
static rlm_rcode_t mod_checksimul(void *instance, REQUEST *request)
Check if a given user is already logged in.
int rad_check_ts(uint32_t nasaddr, uint32_t nas_port, char const *user, char const *sessionid)
enum rlm_rcodes rlm_rcode_t
Return codes indicating the result of the module call.
#define RWDEBUG2(fmt,...)
Module succeeded without doing anything.
uint64_t magic
Used to validate module struct.
Module failed, don't reply.
#define PW_TYPE_FILE_OUTPUT
File matching value must exist, and must be writeable.
#define FR_CONF_OFFSET(_n, _t, _s, _f)
VALUE_PAIR * fr_cursor_next(vp_cursor_t *cursor)
Advanced the cursor to the next VALUE_PAIR.
int strncasecmp(char *s1, char *s2, int n)
#define PW_STATUS_ACCOUNTING_ON
int rad_unlockfd(int fd, int lock_len)
struct rlm_radutmp_t rlm_radutmp_t
#define PW_TYPE_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
VALUE_PAIR * fr_pair_find_by_num(VALUE_PAIR *head, unsigned int vendor, unsigned int attr, int8_t tag)
Find the pair with the matching attribute.
size_t strlcpy(char *dst, char const *src, size_t siz)
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
static NAS_PORT * nas_port_find(NAS_PORT *nas_port_list, uint32_t nasaddr, uint16_t port)
static rlm_rcode_t CC_HINT(nonnull)
String of printable characters.
static const CONF_PARSER module_config[]
#define PW_STATUS_ACCOUNTING_OFF
static char const porttypes[]