url resolve_tex (url name) { string s= as_string (name); if (is_cached ("font_cache.scm", s)) { url u= url_system (cache_get ("font_cache.scm", s) -> label); if (exists (u)) return u; cache_reset ("font_cache.scm", s); } bench_start ("resolve tex"); url u= url_none (); if (ends (s, "mf" )) { u= resolve_tfm (name); #ifdef OS_WIN32 if (is_none (u)) u= resolve_tfm (replace (s, ".mf", ".tfm")); #endif } if (ends (s, "tfm")) u= resolve_tfm (name); if (ends (s, "pk" )) u= resolve_pk (name); if (ends (s, "pfb")) u= resolve_pfb (name); bench_cumul ("resolve tex"); if (!is_none (u)) cache_set ("font_cache.scm", s, as_string (u)); //cout << "Resolve " << name << " -> " << u << "\n"; return u; }
static int stream_cache_seek (stream_wrapper_t * wrapper, int64_t pos, int whence) { int ret = 0; cache_ctx_t *ctx = (cache_ctx_t *)wrapper->stream_priv; stream_cache_t *cache = ctx->cache; stream_wrapper_t *real_st = ctx->wrapper; stream_ctrl_t *info = &wrapper->info; info->eof_flag = 0; dt_info(TAG,"Enter cache seek \n"); // ret stream size if(whence == AVSEEK_SIZE) { dt_debug(TAG,"REQUEST STREAM SIZE:%lld \n",info->stream_size); return info->stream_size; } int step; int orig; if(whence == SEEK_SET) { step = abs(info->cur_pos - pos); orig = (info->cur_pos > pos)?0:1; } if(whence == SEEK_CUR) { step = abs(pos); orig = (pos < 0)?0:1; } if(cache_seek(cache,step,orig) == 0) // seek in cache { dt_info(TAG,"cache seek success \n"); } else // seek through real stream ops { pause_cache_thread(ctx); ret =real_st->seek(real_st,pos,whence); // fixme: seek maybe failed for online video if(ret != DTERROR_NONE) { dt_error(TAG,"SEEK FAILED \n"); } cache_reset(ctx->cache); resume_cache_thread(ctx); } info->eof_flag = 0; if(whence == SEEK_SET) info->cur_pos = pos; if(whence == SEEK_CUR) info->cur_pos += pos; return ret; }
static void bc_reset_handler(void) { cache_reset(); }
void NDECL(dispatch) { char *cmdsave; cmdsave = mudstate.debug_cmd; mudstate.debug_cmd = (char *)"< dispatch >"; /* this routine can be used to poll from interface.c */ if (!mudstate.alarm_triggered) return; mudstate.alarm_triggered = 0; mudstate.lastnowmsec = mudstate.nowmsec; mudstate.lastnow = mudstate.now; mudstate.nowmsec = time_ng(NULL); mudstate.now = (time_t) floor(mudstate.nowmsec); do_second(); local_second(); /* Free list reconstruction */ if ((mudconf.control_flags & CF_DBCHECK) && (mudstate.check_counter <= mudstate.nowmsec)) { mudstate.check_counter = mudconf.check_interval + mudstate.nowmsec; mudstate.debug_cmd = (char *)"< dbck >"; cache_reset(0); do_dbck (NOTHING, NOTHING, 0); cache_reset(0); pcache_trim(); } /* Database dump routines */ if ((mudconf.control_flags & CF_CHECKPOINT) && (mudstate.dump_counter <= mudstate.nowmsec)) { mudstate.dump_counter = mudconf.dump_interval + mudstate.nowmsec; mudstate.debug_cmd = (char *)"< dump >"; fork_and_dump(0, (char *)NULL); } /* Idle user check */ if ((mudconf.control_flags & CF_IDLECHECK) && (mudstate.idle_counter <= mudstate.nowmsec)) { mudstate.idle_counter = mudconf.idle_interval + mudstate.nowmsec; mudstate.debug_cmd = (char *)"< idlecheck >"; cache_reset(0); check_idle(); } #ifdef HAVE_GETRUSAGE /* Memory use stats */ if (mudstate.mstats_counter <= mudstate.nowmsec) { int curr; mudstate.mstats_counter = 15 + mudstate.nowmsec; curr = mudstate.mstat_curr; if ( (curr >= 0 ) && (mudstate.now > mudstate.mstat_secs[curr]) ) { struct rusage usage; curr = 1-curr; getrusage(RUSAGE_SELF, &usage); mudstate.mstat_ixrss[curr] = usage.ru_ixrss; mudstate.mstat_idrss[curr] = usage.ru_idrss; mudstate.mstat_isrss[curr] = usage.ru_isrss; mudstate.mstat_secs[curr] = mudstate.now; mudstate.mstat_curr = curr; } } #endif #ifdef RWHO_IN_USE if ((mudconf.control_flags & CF_RWHO_XMIT) && (mudstate.rwho_counter <= mudstate.nowmsec)) { mudstate.rwho_counter = mudconf.rwho_interval + mudstate.nowmsec; mudstate.debug_cmd = (char *)"< rwho update >"; rwho_update(); } #endif /* reset alarm */ alarm_msec (next_timer()); mudstate.debug_cmd = cmdsave; }
/** * exit function if a signal is received in daemon mode. * * Argument: signal number * Return: None */ gboolean nuauth_reload(int signum) { struct nuauth_params *newconf = NULL; gboolean restart; int retval; g_message("[+] Reload NuAuth server"); nuauth_install_signals(FALSE); /* Reload the configuration file */ retval = nuauth_parse_configuration(nuauthconf->configfile); if (retval != 0) { log_message(CRITICAL, DEBUG_AREA_MAIN, "Cannot reload configuration (file '%s')", nuauthconf->configfile); return -1; } init_nuauthconf(&newconf); g_message("nuauth module reloading"); /* block threads of pool at start */ block_thread_pools(); /* we have to wait that all threads are blocked */ wait_all_thread_pools(); /* unload modules */ unload_modules(); /* Only duplicate configfile info, if configfile has not been set */ if (! newconf->configfile) { newconf->configfile = g_strdup(nuauthconf->configfile); } /* switch conf before loading modules */ restart = compare_nuauthparams(nuauthconf, newconf); if (restart == FALSE) { apply_new_config(newconf); /* debug is set via command line thus duplicate */ newconf->debug_level = nuauthconf->debug_level; free_nuauth_params(nuauthconf); g_free(nuauthconf); nuauthconf = newconf; } else { free_nuauth_params(newconf); } /* reload modules with new conf */ load_modules(); /* init period */ nuauthconf->periods = init_periods(nuauthconf); /* ask cache to reset */ if (nuauthconf->acl_cache) { cache_reset(nuauthdatas->acl_cache); } release_thread_pools(); nuauth_install_signals(TRUE); force_refresh_crl_file(); g_message("[+] NuAuth server reloaded"); return restart; }
// find valid instructions offsets before ret int _ropit_x86_find_gadgets (uint8_t *bytes, int len, int64_t *rets, int n_rets) { int sz_inst; /* size of instruction */ x86_insn_t insn; /* instruction */ int idx_ret, sz_ret; int valid_gadget; // back track instruction count int n_backtrack_inst, n_backtrack_bytes; // start for rop search uint8_t *start, *gadget_start; // disassemble int len_disasm; int sz_dst; char disassembled[DISASSEMBLED_SIZE_MAX] = {0}; // cache FILE *fp_cache; struct cache_t *caches; int idx_caches, n_caches; struct gadget_t *gadgets; int idx_gadgets, n_gadgets; // cache queue struct gadget_cache_queue_t *cache_queue; // count int count_gadgets; // check params if (!bytes || len <= 0) { debug_printf (MESSAGE_ERROR, stderr, "error: _ropit_x86_find_gadgets(): Bytes null or len <= 0\n"); return NULL; } // search rets if (!rets || n_rets <= 0) { debug_printf (MESSAGE_ERROR, stderr, "error: _ropit_x86_find_gadgets(): No rets\n"); return NULL; } // init gadget_cache fp_cache = fopen("tmp/gadget_cache", "w"); if (!fp_cache) { debug_printf (MESSAGE_ERROR, stderr, "error: _ropit_x86_find_gadgets(): Failed open (w)\n"); return NULL; } // init cache_queue cache_queue = NULL; if (!gadget_cache_queue_init(&cache_queue)) { debug_printf (MESSAGE_ERROR, stderr, "error: _ropit_x86_find_gadgets(): Cache queue allocation failed\n"); return NULL; } gadget_cache_queue_set_file (cache_queue, fp_cache); // init gadgets n_gadgets = 1024; gadgets = calloc(sizeof(struct gadget_t), n_gadgets); if (!gadgets) { debug_printf (MESSAGE_ERROR, stderr, "error: _ropit_x86_find_gadgets(): Failed allocating caches\n"); return NULL; } for (idx_gadgets = 0; idx_gadgets < n_gadgets; idx_gadgets++) gadget_init(&(gadgets[idx_gadgets]), DISASSEMBLED_SIZE_MAX); // init caches n_caches = 1; caches = calloc(sizeof(struct cache_t), n_caches); if (!caches) { debug_printf (MESSAGE_ERROR, stderr, "error: _ropit_x86_find_gadgets(): Failed allocating caches\n"); return NULL; } for (idx_caches = 0; idx_caches < n_caches; idx_caches++) { cache_init(&(caches[idx_caches]), 1024); } // init disasm x86_init(opt_none, NULL, NULL); idx_caches = 0; idx_gadgets = 0; count_gadgets = 0; for (idx_ret = 0; idx_ret < n_rets; idx_ret++) { start = bytes + rets[idx_ret]; n_backtrack_inst = 0; n_backtrack_bytes = 0; while ( bytes <= start && start <= bytes + len ) { /* disassemble address */ sz_inst = x86_disasm(start, len - (start - bytes), 0, 0, &insn); x86_oplist_free(&insn); if (sz_inst <= 0) { // printf("not found inst\n"); n_backtrack_bytes++; } else { // printf("found inst\n"); n_backtrack_bytes = 0; valid_gadget = 0; // gadget_start = start; if (gadget_start == bytes + rets[idx_ret]) valid_gadget = 1; else { n_backtrack_inst = 0; // check gadget validity while (bytes <= gadget_start && gadget_start <= bytes + rets[idx_ret]) { /* disassemble address */ sz_inst = x86_disasm(gadget_start, gadget_start - bytes, 0, 0, &insn); x86_oplist_free(&insn); if (sz_inst <= 0) break; else { n_backtrack_inst++; gadget_start += sz_inst; if (gadget_start == bytes + rets[idx_ret]) { valid_gadget = 1; break; } } } } if (valid_gadget == 1) { // ++count_gadgets; // get ret size sz_ret = x86_disasm(bytes + rets[idx_ret], 10, 0, 0, &insn); x86_oplist_free(&insn); // fill gadget structure gadgets[idx_gadgets].ret_addr = rets[idx_ret]; gadgets[idx_gadgets].ret_bytes = rets[idx_ret] + bytes; gadgets[idx_gadgets].address = start - bytes; gadgets[idx_gadgets].len_bytes = (rets[idx_ret] - (start - bytes)) + sz_ret; if (gadgets[idx_gadgets].sz_bytes < gadgets[idx_gadgets].len_bytes) { gadgets[idx_gadgets].bytes = realloc (gadgets[idx_gadgets].bytes, gadgets[idx_gadgets].len_bytes); gadgets[idx_gadgets].sz_bytes = gadgets[idx_gadgets].len_bytes; } memcpy(gadgets[idx_gadgets].bytes, start, gadgets[idx_gadgets].len_bytes); if (cache_add (&(caches[idx_caches]), &(gadgets[idx_gadgets])) == -ERR_CACHE_FULL) { gadget_cache_queue_add (cache_queue, &(caches[idx_caches])); gadget_cache_queue_fwrite_worker (cache_queue); cache_reset (&(caches[idx_caches])); } idx_gadgets = (idx_gadgets + 1) % n_gadgets; } } --start; // maximum intel instruction size is 15 // maximum instructions in a gadget is hardcoded to 8 here /* TODO : Get more gadgets with n_backtrack_inst instructions * Effectively, we stop at the first gadget which has * n_backtrack_inst instructions while there might be multiple * possibilities. */ if (n_backtrack_bytes >= 15 || n_backtrack_inst == 8) break; } } x86_cleanup(); // write remaining gadgets gadget_cache_queue_add (cache_queue, &(caches[idx_caches])); gadget_cache_queue_fwrite_worker (cache_queue); cache_reset (&(caches[idx_caches])); // clean up for (idx_caches = 0; idx_caches < n_caches; idx_caches++) free(caches[idx_caches].objects); free(caches); for (idx_gadgets = 0; idx_gadgets < n_gadgets; idx_gadgets++) { // gadget_free(&(gadgets[idx_gadgets])); // free (gadgets[idx_gadgets].repr); free (gadgets[idx_gadgets].bytes); } free(gadgets); gadget_cache_queue_destroy (&cache_queue); fclose (fp_cache); return count_gadgets; }
/* * Store logins in the RADIUS utmp file. */ static rlm_rcode_t radutmp_accounting(void *instance, REQUEST *request) { rlm_radutmp_t *inst = instance; struct radutmp utmp, u; VALUE_PAIR *vp; int status = -1; uint32_t nas_address = 0; uint32_t framed_address = 0; int protocol = -1; int fd; int port_seen = 0; char buffer[256]; char filename[1024]; char ip_name[32]; /* 255.255.255.255 */ const char *nas; NAS_PORT *nas_port, myPort; radutmp_cache_t *cache; int read_size; rbnode_t *node; /* * Which type is this. */ if ((vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE, 0, TAG_ANY)) == NULL) { radlog(L_ERR, "rlm_radutmp: No Accounting-Status-Type record."); return RLM_MODULE_NOOP; } status = vp->vp_integer; /* * Look for weird reboot packets. * * ComOS (up to and including 3.5.1b20) does not send * standard PW_STATUS_ACCOUNTING_* messages. * * Check for: o no Acct-Session-Time, or time of 0 * o Acct-Session-Id of "00000000". * * We could also check for NAS-Port, that attribute * should NOT be present (but we don't right now). */ if ((status != PW_STATUS_ACCOUNTING_ON) && (status != PW_STATUS_ACCOUNTING_OFF)) do { int check1 = 0; int check2 = 0; if ((vp = pairfind(request->packet->vps, PW_ACCT_SESSION_TIME, 0, TAG_ANY)) == NULL || vp->vp_date == 0) check1 = 1; if ((vp = pairfind(request->packet->vps, PW_ACCT_SESSION_ID, 0, TAG_ANY)) != NULL && vp->length == 8 && memcmp(vp->vp_strvalue, "00000000", 8) == 0) check2 = 1; if (check1 == 0 || check2 == 0) { #if 0 /* Cisco sometimes sends START records without username. */ radlog(L_ERR, "rlm_radutmp: no username in record"); return RLM_MODULE_FAIL; #else break; #endif } radlog(L_INFO, "rlm_radutmp: converting reboot records."); if (status == PW_STATUS_STOP) status = PW_STATUS_ACCOUNTING_OFF; if (status == PW_STATUS_START) status = PW_STATUS_ACCOUNTING_ON; } while(0); memset(&utmp, 0, sizeof(utmp)); utmp.porttype = 'A'; /* * First, find the interesting attributes. */ for (vp = request->packet->vps; vp; vp = vp->next) { switch (vp->da->attribute) { case PW_LOGIN_IP_HOST: case PW_FRAMED_IP_ADDRESS: framed_address = vp->vp_ipaddr; utmp.framed_address = vp->vp_ipaddr; break; case PW_FRAMED_PROTOCOL: protocol = vp->vp_integer; break; case PW_NAS_IP_ADDRESS: nas_address = vp->vp_ipaddr; utmp.nas_address = vp->vp_ipaddr; break; case PW_NAS_PORT: utmp.nas_port = vp->vp_integer; port_seen = 1; break; case PW_ACCT_DELAY_TIME: utmp.delay = vp->vp_integer; break; case PW_ACCT_SESSION_ID: /* * If it's too big, only use the * last bit. */ if (vp->length > sizeof(utmp.session_id)) { int length = vp->length - sizeof(utmp.session_id); /* * Ascend is br0ken - it * adds a \0 to the end * of any string. * Compensate. */ if (vp->vp_strvalue[vp->length - 1] == 0) { length--; } memcpy(utmp.session_id, vp->vp_strvalue + length, sizeof(utmp.session_id)); } else { memset(utmp.session_id, 0, sizeof(utmp.session_id)); memcpy(utmp.session_id, vp->vp_strvalue, vp->length); } break; case PW_NAS_PORT_TYPE: if (vp->vp_integer <= 4) utmp.porttype = porttypes[vp->vp_integer]; break; case PW_CALLING_STATION_ID: if(inst->callerid_ok) strlcpy(utmp.caller_id, (char *)vp->vp_strvalue, sizeof(utmp.caller_id)); break; } } /* * If we didn't find out the NAS address, use the * originator's IP address. */ if (nas_address == 0) { nas_address = request->packet->src_ipaddr; utmp.nas_address = nas_address; nas = request->client->shortname; } else if (request->packet->src_ipaddr.ipaddr.ip4addr.s_addr == nas_address) { /* might be a client, might not be. */ nas = request->client->shortname; } else { /* * The NAS isn't a client, it's behind * a proxy server. In that case, just * get the IP address. */ nas = ip_ntoa(ip_name, nas_address); } /* * Set the protocol field. */ if (protocol == PW_PPP) utmp.proto = 'P'; else if (protocol == PW_SLIP) utmp.proto = 'S'; else utmp.proto = 'T'; utmp.time = request->timestamp - utmp.delay; /* * Get the utmp filename, via xlat. */ radius_xlat(filename, sizeof(filename), inst->filename, request, NULL); /* * Future: look up filename in filename tree, to get * radutmp_cache_t pointer */ cache = &inst->cache; /* * For now, double-check the filename, to be sure it isn't * changing. */ if (!cache->filename) { cache->filename = strdup(filename); rad_assert(cache->filename != NULL); } else if (strcmp(cache->filename, filename) != 0) { radlog(L_ERR, "rlm_radutmp: We do not support dynamically named files."); return RLM_MODULE_FAIL; } /* * If the lookup failed, create a new one, and add it * to the filename tree, and cache the file, as below. */ /* * For aging, in the future. */ cache->last_used = request->timestamp; /* * If we haven't already read the file, then read the * entire file, in order to cache its entries. */ if (!cache->cached_file) { cache_file(inst, cache); } /* * See if this was a reboot. * * Hmm... we may not want to zap all of the users when * the NAS comes up, because of issues with receiving * UDP packets out of order. */ if (status == PW_STATUS_ACCOUNTING_ON && nas_address) { radlog(L_INFO, "rlm_radutmp: NAS %s restarted (Accounting-On packet seen)", nas); if (!radutmp_zap(inst, cache, nas_address, utmp.time)) { rad_assert(0 == 1); } return RLM_MODULE_OK; } if (status == PW_STATUS_ACCOUNTING_OFF && nas_address) { radlog(L_INFO, "rlm_radutmp: NAS %s rebooted (Accounting-Off packet seen)", nas); if (!radutmp_zap(inst, cache, nas_address, utmp.time)) { rad_assert(0 == 1); } return RLM_MODULE_OK; } /* * If we don't know this type of entry, then pretend we * succeeded. */ if (status != PW_STATUS_START && status != PW_STATUS_STOP && status != PW_STATUS_ALIVE) { radlog(L_ERR, "rlm_radutmp: NAS %s port %u unknown packet type %d, ignoring it.", nas, utmp.nas_port, status); return RLM_MODULE_NOOP; } /* * Perhaps we don't want to store this record into * radutmp. We skip records: * * - without a NAS-Port (telnet / tcp access) * - with the username "!root" (console admin login) */ if (!port_seen) { DEBUG2(" rlm_radutmp: No NAS-Port in the packet. Cannot do anything."); DEBUG2(" rlm_radumtp: WARNING: checkrad will probably not work!"); return RLM_MODULE_NOOP; } /* * Translate the User-Name attribute, or whatever else * they told us to use. */ *buffer = '\0'; radius_xlat(buffer, sizeof(buffer), inst->username, request, NULL); /* * Don't log certain things... */ if (strcmp(buffer, "!root") == 0) { DEBUG2(" rlm_radutmp: Not recording administrative user"); return RLM_MODULE_NOOP; } strlcpy(utmp.login, buffer, RUT_NAMESIZE); /* * First, try to open the file. If it doesn't exist, * nuke the existing caches, and try to create it. * * FIXME: Create any intermediate directories, as * appropriate. See rlm_detail. */ fd = open(cache->filename, O_RDWR, inst->permission); if (fd < 0) { if (errno == ENOENT) { DEBUG2(" rlm_radutmp: File %s doesn't exist, creating it.", cache->filename); if (!cache_reset(inst, cache)) return RLM_MODULE_FAIL; /* * Try to create the file. */ fd = open(cache->filename, O_RDWR | O_CREAT, inst->permission); } } else { /* exists, but may be empty */ struct stat buf; /* * If the file is empty, reset the cache. */ if ((stat(cache->filename, &buf) == 0) && (buf.st_size == 0) && (!cache_reset(inst, cache))) { return RLM_MODULE_FAIL; } DEBUG2(" rlm_radutmp: File %s was truncated. Resetting cache.", cache->filename); } /* * Error from creation, or error other than ENOENT: die. */ if (fd < 0) { radlog(L_ERR, "rlm_radutmp: Error accessing file %s: %s", cache->filename, strerror(errno)); return RLM_MODULE_FAIL; } /* * OK. Now that we've prepared everything we want to do, * let's see if we've cached the entry. */ myPort.nas_address = utmp.nas_address; myPort.nas_port = utmp.nas_port; pthread_mutex_lock(&cache->mutex); node = rbtree_find(cache->nas_ports, &myPort); pthread_mutex_unlock(&cache->mutex); if (node) { nas_port = rbtree_node2data(cache->nas_ports, node); #if 0 /* * stat the file, and get excited if it's been * truncated. * * i.e wipe out the cache, and re-read the file. */ /* * Now find the new entry. */ pthread_mutex_lock(&cache->mutex); node = rbtree_find(cache->nas_ports, &myPort); pthread_mutex_unlock(&cache->mutex); #endif } if (!node) { radutmp_simul_t *user; /* * Not found in the cache, and we're trying to * delete an existing record: ignore it. */ if (status == PW_STATUS_STOP) { DEBUG2(" rlm_radumtp: Logout entry for NAS %s port %u with no Login: ignoring it.", nas, utmp.nas_port); return RLM_MODULE_NOOP; } pthread_mutex_lock(&cache->mutex); /* * It's a START or ALIVE. Try to find a free * offset where we can store the new entry, or * create one, if one doesn't already exist. */ if (!cache->free_offsets) { cache->free_offsets = rad_malloc(sizeof(NAS_PORT)); memset(cache->free_offsets, 0, sizeof(*(cache->free_offsets))); cache->free_offsets->offset = cache->max_offset; cache->max_offset += sizeof(u); } /* * Grab the offset, and put it into the various * caches. */ nas_port = cache->free_offsets; cache->free_offsets = nas_port->next; nas_port->nas_address = nas_address; nas_port->nas_port = utmp.nas_port; if (!rbtree_insert(cache->nas_ports, nas_port)) { rad_assert(0 == 1); } /* * Allocate new entry, and add it * to the tree. */ user = rad_malloc(sizeof(user)); strlcpy(user->login, utmp.login, sizeof(user->login)); user->simul_count = 1; if (!rbtree_insert(inst->user_tree, user)) { rad_assert(0 == 1); } pthread_mutex_unlock(&cache->mutex); } /* * Entry was found, or newly created in the cache. * Seek to the place in the file. */ lseek(fd, nas_port->offset, SEEK_SET); /* * Lock the utmp file, prefer lockf() over flock(). */ rad_lockfd(fd, LOCK_LEN); /* * If it WAS found in the cache, double-check it against * what is in the file. */ if (node) { /* * If we didn't read anything, then this entry * doesn't exist. * * Similarly, if the entry in the file doesn't * match what we recall, then nuke the cache * entry. */ read_size = read(fd, &u, sizeof(u)); if ((read_size < 0) || ((read_size > 0) && (read_size != sizeof(u)))) { /* * Bad read, or bad record. */ radlog(L_ERR, "rlm_radutmp: Badly formed file %s", cache->filename); close(fd); return RLM_MODULE_FAIL; } rad_assert(read_size != 0); /* * We've read a record, go poke at it. */ if (read_size > 0) { /* * If these aren't true, then * * a) we have cached a "logout" entry, * which we don't do. * * b) we have cached the wrong NAS address * * c) we have cached the wrong NAS port. */ rad_assert(u.type == P_LOGIN); rad_assert(u.nas_address == utmp.nas_address); rad_assert(u.nas_port == utmp.nas_port); /* * An update for the same session. */ if (strncmp(utmp.session_id, u.session_id, sizeof(u.session_id)) == 0) { /* * It's a duplicate start, so we * don't bother writing it. */ if (status == PW_STATUS_START) { DEBUG2(" rlm_radutmp: Login entry for NAS %s port %u duplicate, ignoring it.", nas, u.nas_port); close(fd); return RLM_MODULE_OK; /* * ALIVE for this session, keep the * original login time. */ } else if (status == PW_STATUS_ALIVE) { utmp.time = u.time; /* * Stop: delete it from our cache. */ } else if (status == PW_STATUS_STOP) { radutmp_simul_t *user, myUser; pthread_mutex_lock(&cache->mutex); rbtree_deletebydata(cache->nas_ports, nas_port); strlcpy(myUser.login, u.login, sizeof(myUser.login)); user = rbtree_finddata(inst->user_tree, &myUser); rad_assert(user != NULL); rad_assert(user->simul_count > 0); user->simul_count--; if (user->simul_count == 0) { rbtree_deletebydata(inst->user_tree, user); } pthread_mutex_unlock(&cache->mutex); } else { /* * We don't know how to * handle this. */ rad_assert(0 == 1); } } else { /* session ID doesn't match */ /* * STOP for the right NAS & port, * but the Acct-Session-Id is * different. This means that * we missed the original "stop", * and a new "start". */ if (status == PW_STATUS_STOP) { radlog(L_ERR, "rlm_radutmp: Logout entry for NAS %s port %u has old Acct-Session-ID, ignoring it.", nas, u.nas_port); close(fd); return RLM_MODULE_OK; } } /* checked session ID's */ } /* else we haven't read anything from the file. */ } /* else the entry wasn't cached, but could have been inserted */ /* * Hmm... we may have received a start or alive packet * AFTER a stop or nas-down, in that case, we want to * discard the new packet. However, the original code * could over-write an idle record with a new login * record for another NAS && port, so we won't worry * about this case too much. */ /* * Seek to where the entry is, and write it blindly. */ lseek(fd, nas_port->offset, SEEK_SET); /* FIXME: err */ if (status != PW_STATUS_STOP) { utmp.type = P_LOGIN; rad_assert(nas_port != NULL); /* it WAS cached */ } else { /* FIXME: maybe assert that the entry was deleted... */ memcpy(&utmp, &u, sizeof(utmp)); utmp.type = P_IDLE; } write(fd, &utmp, sizeof(utmp)); /* FIXME: err */ close(fd); /* and implicitly release the locks */ return RLM_MODULE_OK; }