/* * Creates a string ready to write as a token into config or WebIf for an iprange. You must free the returned value through free_mk_t(). */ char *mk_t_iprange(struct s_ip *range) { struct s_ip *cip; char *value, *dot = ""; int32_t needed = 1, pos = 0; for(cip = range; cip; cip = cip->next) { needed += 32; } char tmp[needed]; for(cip = range; cip; cip = cip->next) { pos += snprintf(tmp + pos, needed - pos, "%s%s", dot, cs_inet_ntoa(cip->ip[0])); if(!IP_EQUAL(cip->ip[0], cip->ip[1])) { pos += snprintf(tmp + pos, needed - pos, "-%s", cs_inet_ntoa(cip->ip[1])); } dot = ","; } if(pos == 0 || !cs_malloc(&value, pos + 1)) { return ""; } memcpy(value, tmp, pos + 1); return value; }
/* Calculates a new opaque value. Please note that opaque needs to be at least (MD5_DIGEST_LENGTH * 2) + 1 large. */ void calculate_opaque(IN_ADDR_T addr, char *opaque) { char noncetmp[128]; unsigned char md5tmp[MD5_DIGEST_LENGTH]; snprintf(noncetmp, sizeof(noncetmp), "%d:%s:%d", (int32_t)time(NULL), cs_inet_ntoa(addr), (int16_t)rand()); char_to_hex(MD5((unsigned char *)noncetmp, strlen(noncetmp), md5tmp), MD5_DIGEST_LENGTH, (unsigned char *)opaque); }
static void radegast_server_init(struct s_client *cl) { if (!cl->init_done) { if (IP_ISSET(cl->ip)) cs_log("radegast: new connection from %s", cs_inet_ntoa(cl->ip)); radegast_auth_client(cur_client()->ip); cl->init_done=1; } return; }
void cs_disconnect_client(struct s_client * client) { char buf[32] = { 0 }; if (IP_ISSET(client->ip)) snprintf(buf, sizeof(buf), " from %s", cs_inet_ntoa(client->ip)); cs_log("%s disconnected%s", username(client), buf); if (client == cur_client()) cs_exit(0); else kill_thread(client); }
/* Resolves the ip of the hostname of the specified account and saves it in account->dynip. If the hostname is not configured, the ip is set to 0. */ static void cs_user_resolve(struct s_auth *account) { if (account->dyndns) { IN_ADDR_T lastip; IP_ASSIGN(lastip, account->dynip); cs_resolve(account->dyndns, &account->dynip, NULL, NULL); if (!IP_EQUAL(lastip, account->dynip)) { cs_log("%s: resolved ip=%s", account->dyndns, cs_inet_ntoa(account->dynip)); } } else { set_null_ip(&account->dynip); } }
static void serverip_fn(const char *token, char *value, void *setting, FILE *f) { IN_ADDR_T srvip = *(IN_ADDR_T *)setting; if (value) { if (strlen(value) == 0) { set_null_ip((IN_ADDR_T *)setting); } else { cs_inet_addr(value, (IN_ADDR_T *)setting); } return; } if (IP_ISSET(srvip) || cfg.http_full_cfg) fprintf_conf(f, token, "%s\n", cs_inet_ntoa(srvip)); }
void gbox_write_peer_onl(void) { FILE *fhandle = fopen(FILE_GBOX_PEER_ONL, "w"); if(!fhandle) { cs_log("Couldn't open %s: %s\n", FILE_GBOX_PEER_ONL, strerror(errno)); return; } struct s_client *cl; for(cl = first_client; cl; cl = cl->next) { if(cl->gbox && (cl->typ == 'p')) { struct gbox_peer *peer = cl->gbox; if (peer->online) { fprintf(fhandle, "1 %s %s %04X 2.%02X\n",cl->reader->device, cs_inet_ntoa(cl->ip),peer->gbox.id, peer->gbox.minor_version); } else { fprintf(fhandle, "0 %s %s %04X 0.00\n",cl->reader->device, cs_inet_ntoa(cl->ip),peer->gbox.id); } } } fclose(fhandle); return; }
static void gbox_server_init(struct s_client *cl) { if(!cl->init_done) { if(IP_ISSET(cl->ip)) { cs_log("gbox: new connection from %s", cs_inet_ntoa(cl->ip)); } gbox_auth_client(cl); if(cl->gbox) { gbox_local_cards(cl); cl->init_done = 1; } } return; }
int32_t cs_auth_client(struct s_client * client, struct s_auth *account, const char *e_txt) { int32_t rc = 0; unsigned char md5tmp[MD5_DIGEST_LENGTH]; char buf[32]; char *t_crypt = "encrypted"; char *t_plain = "plain"; char *t_grant = " granted"; char *t_reject = " rejected"; char *t_msg[] = { buf, "invalid access", "invalid ip", "unknown reason", "protocol not allowed" }; struct s_module *module = get_module(client); memset(&client->grp, 0xff, sizeof(uint64_t)); //client->grp=0xffffffffffffff; if ((intptr_t)account != 0 && (intptr_t)account != -1 && account->disabled) { cs_add_violation(client, account->usr); cs_log("%s %s-client %s%s (%s%sdisabled account)", client->crypted ? t_crypt : t_plain, module->desc, IP_ISSET(client->ip) ? cs_inet_ntoa(client->ip) : "", IP_ISSET(client->ip) ? t_reject : t_reject+1, e_txt ? e_txt : "", e_txt ? " " : ""); return 1; } // check whether client comes in over allowed protocol if ((intptr_t)account != 0 && (intptr_t)account != -1 && (intptr_t)account->allowedprotocols && (((intptr_t)account->allowedprotocols & module->listenertype) != module->listenertype)) { cs_add_violation(client, account->usr); cs_log("%s %s-client %s%s (%s%sprotocol not allowed)", client->crypted ? t_crypt : t_plain, module->desc, IP_ISSET(client->ip) ? cs_inet_ntoa(client->ip) : "", IP_ISSET(client->ip) ? t_reject : t_reject+1, e_txt ? e_txt : "", e_txt ? " " : ""); return 1; } client->account = first_client->account; switch((intptr_t)account) { case 0: { // reject access rc = 1; cs_add_violation(client, NULL); cs_log("%s %s-client %s%s (%s)", client->crypted ? t_crypt : t_plain, module->desc, IP_ISSET(client->ip) ? cs_inet_ntoa(client->ip) : "", IP_ISSET(client->ip) ? t_reject : t_reject+1, e_txt ? e_txt : t_msg[rc]); break; } default: { // grant/check access if (IP_ISSET(client->ip) && account->dyndns) { if (!IP_EQUAL(client->ip, account->dynip)) cs_user_resolve(account); if (!IP_EQUAL(client->ip, account->dynip)) { cs_add_violation(client, account->usr); rc=2; } } client->monlvl = account->monlvl; client->account = account; if (!rc) { client->dup=0; if (client->typ=='c' || client->typ=='m') client->pcrc = crc32(0L, MD5((uchar *)(ESTR(account->pwd)), strlen(ESTR(account->pwd)), md5tmp), MD5_DIGEST_LENGTH); if (client->typ=='c') { client->last_caid = NO_CAID_VALUE; client->last_srvid = NO_SRVID_VALUE; client->expirationdate = account->expirationdate; client->disabled = account->disabled; client->allowedtimeframe[0] = account->allowedtimeframe[0]; client->allowedtimeframe[1] = account->allowedtimeframe[1]; if (account->firstlogin == 0) account->firstlogin = time((time_t*)0); client->failban = account->failban; client->c35_suppresscmd08 = account->c35_suppresscmd08; client->ncd_keepalive = account->ncd_keepalive; client->grp = account->grp; client->aureader_list = account->aureader_list; client->autoau = account->autoau; client->tosleep = (60*account->tosleep); client->c35_sleepsend = account->c35_sleepsend; memcpy(&client->ctab, &account->ctab, sizeof(client->ctab)); if (account->uniq) cs_fake_client(client, account->usr, account->uniq, client->ip); client->ftab = account->ftab; // IDENT filter client->cltab = account->cltab; // CLASS filter client->fchid = account->fchid; // CHID filter client->sidtabs.ok= account->sidtabs.ok; // services client->sidtabs.no= account->sidtabs.no; // services memcpy(&client->ttab, &account->ttab, sizeof(client->ttab)); ac_init_client(client, account); } } } case -1: { // anonymous grant access if (rc) { t_grant = t_reject; } else { if (client->typ == 'm') { snprintf(t_msg[0], sizeof(buf), "lvl=%d", client->monlvl); } else { int32_t rcount = ll_count(client->aureader_list); snprintf(buf, sizeof(buf), "au="); if (!rcount) snprintf(buf+3, sizeof(buf)-3, "off"); else { if (client->autoau) snprintf(buf+3, sizeof(buf)-3, "auto (%d reader)", rcount); else snprintf(buf+3, sizeof(buf)-3, "on (%d reader)", rcount); } } } cs_log("%s %s-client %s%s (%s, %s)", client->crypted ? t_crypt : t_plain, e_txt ? e_txt : module->desc, IP_ISSET(client->ip) ? cs_inet_ntoa(client->ip) : "", IP_ISSET(client->ip) ? t_grant : t_grant + 1, username(client), t_msg[rc]); break; } } return rc; }
struct s_client *create_client(IN_ADDR_T ip) { struct s_client *cl; if (!cs_malloc(&cl, sizeof(struct s_client))) { cs_log("max connections reached (out of memory) -> reject client %s", IP_ISSET(ip) ? cs_inet_ntoa(ip) : "with null address"); return NULL; } //client part IP_ASSIGN(cl->ip, ip); cl->account = first_client->account; //master part pthread_mutex_init(&cl->thread_lock, NULL); cl->login = cl->last = time(NULL); cl->tid = (uint32_t)(uintptr_t)cl; // Use pointer adress of client as threadid (for monitor and log) //Now add new client to the list: struct s_client *last; cs_writelock(&clientlist_lock); if (sizeof(uintptr_t) > 4) { // 64bit systems can have collisions because of the cast so lets check if there are some int8_t found; do { found = 0; for (last=first_client; last; last=last->next) { if (last->tid == cl->tid) { found = 1; break; } } if (found || cl->tid == 0) { cl->tid = (uint32_t)rand(); } } while (found || cl->tid == 0); } for (last = first_client; last->next != NULL; last = last->next) ; //ends with cl on last client last->next = cl; int32_t bucket = (uintptr_t)cl/16 % CS_CLIENT_HASHBUCKETS; cl->nexthashed = first_client_hashed[bucket]; first_client_hashed[bucket] = cl; cs_writeunlock(&clientlist_lock); return cl; }
static void cs_fake_client(struct s_client *client, char *usr, int32_t uniq, IN_ADDR_T ip) { /* Uniq = 1: only one connection per user * * Uniq = 2: set (new connected) user only to fake if source * ip is different (e.g. for newcamd clients with * different CAID's -> Ports) * * Uniq = 3: only one connection per user, but only the last * login will survive (old mpcs behavior) * * Uniq = 4: set user only to fake if source ip is * different, but only the last login will survive */ struct s_client *cl; struct s_auth *account; cs_writelock(&fakeuser_lock); for (cl = first_client->next; cl; cl = cl->next) { account = cl->account; if (cl != client && cl->typ == 'c' && !cl->dup && account && streq(account->usr, usr) && uniq < 5 && ((uniq % 2) || !IP_EQUAL(cl->ip, ip))) { char buf[20]; if (uniq == 3 || uniq == 4) { cl->dup = 1; cl->aureader_list = NULL; cs_strncpy(buf, cs_inet_ntoa(cl->ip), sizeof(buf)); cs_log("client(%8lX) duplicate user '%s' from %s (prev %s) set to fake (uniq=%d)", (unsigned long)cl->thread, usr, cs_inet_ntoa(ip), buf, uniq); if (cl->failban & BAN_DUPLICATE) { cs_add_violation(cl, usr); } if (cfg.dropdups) { cs_writeunlock(&fakeuser_lock); cs_sleepms(100); // sleep a bit to prevent against saturation from fast reconnecting clients kill_thread(cl); cs_writelock(&fakeuser_lock); } } else { client->dup = 1; client->aureader_list = NULL; cs_strncpy(buf, cs_inet_ntoa(ip), sizeof(buf)); cs_log("client(%8lX) duplicate user '%s' from %s (current %s) set to fake (uniq=%d)", (unsigned long)pthread_self(), usr, cs_inet_ntoa(cl->ip), buf, uniq); if (client->failban & BAN_DUPLICATE) { cs_add_violation_by_ip(ip, get_module(client)->ptab->ports[client->port_idx].s_port, usr); } if (cfg.dropdups) { cs_writeunlock(&fakeuser_lock); // we need to unlock here as cs_disconnect_client kills the current thread! cs_sleepms(100); // sleep a bit to prevent against saturation from fast reconnecting clients cs_disconnect_client(client); cs_writelock(&fakeuser_lock); } break; } } } cs_writeunlock(&fakeuser_lock); }
static int32_t cs_check_v(IN_ADDR_T ip, int32_t port, int32_t add, char *info, int32_t acosc_penalty_duration) { int32_t result = 0; bool acosc_enabled = false; #ifdef CS_ANTICASC if(cfg.acosc_enabled) acosc_enabled = true; #endif if(!(cfg.failbantime || acosc_enabled)) { return 0; } if(!cfg.v_list) { cfg.v_list = ll_create("v_list"); } struct timeb (now); cs_ftime(&now); LL_ITER itr = ll_iter_create(cfg.v_list); V_BAN *v_ban_entry; int32_t ftime = cfg.failbantime * 60 * 1000; //run over all banned entries to do housekeeping: while((v_ban_entry = ll_iter_next(&itr))) { // housekeeping: int32_t gone = comp_timeb(&now, &v_ban_entry->v_time); if(((gone >= ftime) && !v_ban_entry->acosc_entry) || (v_ban_entry->acosc_entry && ((gone/1000) >= v_ban_entry->acosc_penalty_dur))) // entry out of time->remove { NULLFREE(v_ban_entry->info); ll_iter_remove_data(&itr); continue; } if(IP_EQUAL(ip, v_ban_entry->v_ip) && port == v_ban_entry->v_port) { result = 1; if(!info) { info = v_ban_entry->info; } else if(!v_ban_entry->info) { v_ban_entry->info = cs_strdup(info); } if(!add) { if(v_ban_entry->v_count >= cfg.failbancount) { if(!v_ban_entry->acosc_entry) { cs_debug_mask(D_TRACE, "failban: banned ip %s:%d - %d seconds left%s%s", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, (ftime - gone)/1000, info ? ", info: " : "", info ? info : ""); } else { cs_debug_mask(D_TRACE, "failban: banned ip %s:%d - %d seconds left%s%s", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, (v_ban_entry->acosc_penalty_dur - (gone/1000)), info?", info: ":"", info?info:""); } } else { cs_debug_mask(D_TRACE, "failban: ip %s:%d chance %d of %d%s%s", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, v_ban_entry->v_count, cfg.failbancount, info ? ", info: " : "", info ? info : ""); v_ban_entry->v_count++; } } else { cs_debug_mask(D_TRACE, "failban: banned ip %s:%d - already exist in list%s%s", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, info ? ", info: " : "", info ? info : ""); } } } if(add && !result) { if(cs_malloc(&v_ban_entry, sizeof(V_BAN))) { cs_ftime(&v_ban_entry->v_time); v_ban_entry->v_ip = ip; v_ban_entry->v_port = port; v_ban_entry->v_count = 1; v_ban_entry->acosc_entry = false; v_ban_entry->acosc_penalty_dur = 0; if(acosc_penalty_duration > 0) { v_ban_entry->v_count = cfg.failbancount +1; // set it to a higher level v_ban_entry->acosc_entry = true; v_ban_entry->acosc_penalty_dur = acosc_penalty_duration; } if(info) { v_ban_entry->info = cs_strdup(info); } ll_iter_insert(&itr, v_ban_entry); cs_debug_mask(D_TRACE, "failban: ban ip %s:%d with timestamp %ld%s%s", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, v_ban_entry->v_time.time, info ? ", info: " : "", info ? info : ""); } } return result; }
/* Checks if authentication is correct. Returns -1 if not correct, 1 if correct and 2 if nonce isn't valid anymore. Note that authstring will be modified. */ int32_t check_auth(char *authstring, char *method, char *path, IN_ADDR_T addr, char *expectednonce, char *opaque) { int32_t authok = 0, uriok = 0; char authnonce[(MD5_DIGEST_LENGTH * 2) + 1]; memset(authnonce, 0, sizeof(authnonce)); char *authnc = ""; char *authcnonce = ""; char *authresponse = ""; char *uri = ""; char *username = ""; char *expectedPassword = cfg.http_pwd; char *pch = authstring + 22; char *pch2; char *saveptr1 = NULL; memset(opaque, 0, (MD5_DIGEST_LENGTH * 2) + 1); for(pch = strtok_r(pch, ",", &saveptr1); pch; pch = strtok_r(NULL, ",", &saveptr1)) { pch2 = pch; while(pch2[0] == ' ' && pch2[0] != '\0') { ++pch2; } if(strncmp(pch2, "nonce", 5) == 0) { cs_strncpy(authnonce, parse_auth_value(pch2), sizeof(authnonce)); } else if(strncmp(pch2, "nc", 2) == 0) { authnc = parse_auth_value(pch2); } else if(strncmp(pch2, "cnonce", 6) == 0) { authcnonce = parse_auth_value(pch2); } else if(strncmp(pch2, "response", 8) == 0) { authresponse = parse_auth_value(pch2); } else if(strncmp(pch2, "uri", 3) == 0) { uri = parse_auth_value(pch2); } else if(strncmp(pch2, "username", 8) == 0) { username = parse_auth_value(pch2); } else if(strncmp(pch2, "opaque", 6) == 0) { char *tmp = parse_auth_value(pch2); cs_strncpy(opaque, tmp, (MD5_DIGEST_LENGTH * 2) + 1); } } if(strncmp(uri, path, strlen(path)) == 0) { uriok = 1; } else { pch2 = uri; for(pch = uri; pch[0] != '\0'; ++pch) { if(pch[0] == '/') { pch2 = pch; } if(strncmp(pch2, path, strlen(path)) == 0) { uriok = 1; } } } if(uriok == 1 && streq(username, cfg.http_user)) { char A1tmp[3 + strlen(username) + strlen(AUTHREALM) + strlen(expectedPassword)]; char A1[(MD5_DIGEST_LENGTH * 2) + 1], A2[(MD5_DIGEST_LENGTH * 2) + 1], A3[(MD5_DIGEST_LENGTH * 2) + 1]; unsigned char md5tmp[MD5_DIGEST_LENGTH]; snprintf(A1tmp, sizeof(A1tmp), "%s:%s:%s", username, AUTHREALM, expectedPassword); char_to_hex(MD5((unsigned char *)A1tmp, strlen(A1tmp), md5tmp), MD5_DIGEST_LENGTH, (unsigned char *)A1); char A2tmp[2 + strlen(method) + strlen(uri)]; snprintf(A2tmp, sizeof(A2tmp), "%s:%s", method, uri); char_to_hex(MD5((unsigned char *)A2tmp, strlen(A2tmp), md5tmp), MD5_DIGEST_LENGTH, (unsigned char *)A2); char A3tmp[10 + strlen(A1) + strlen(A2) + strlen(authnonce) + strlen(authnc) + strlen(authcnonce)]; snprintf(A3tmp, sizeof(A3tmp), "%s:%s:%s:%s:auth:%s", A1, authnonce, authnc, authcnonce, A2); char_to_hex(MD5((unsigned char *)A3tmp, strlen(A3tmp), md5tmp), MD5_DIGEST_LENGTH, (unsigned char *)A3); if(strcmp(A3, authresponse) == 0) { if(strlen(opaque) != MD5_DIGEST_LENGTH * 2) { calculate_opaque(addr, opaque); } calculate_nonce(authnonce, expectednonce, opaque); if(strcmp(expectednonce, authnonce) == 0) { authok = 1; } else { authok = 2; cs_debug_mask(D_TRACE, "WebIf: Received stale header from %s (nonce=%s, expectednonce=%s, opaque=%s).", cs_inet_ntoa(addr), authnonce, expectednonce, opaque); } } } return authok; }
void add_cache(ECM_REQUEST *er){ if(!er->csp_hash) return; ECMHASH *result = NULL; CW *cw = NULL; #ifdef CS_CACHEEX bool add_new_cw=false; #endif pthread_rwlock_wrlock(&cache_lock); //add csp_hash to cache result = find_hash_table(&ht_cache, &er->csp_hash, sizeof(int32_t), &compare_csp_hash); if(!result){ if(cs_malloc(&result, sizeof(ECMHASH))){ result->csp_hash = er->csp_hash; init_hash_table(&result->ht_cw, &result->ll_cw); cs_ftime(&result->first_recv_time); add_hash_table(&ht_cache, &result->ht_node, &ll_cache, &result->ll_node, result, &result->csp_hash, sizeof(int32_t)); }else{ pthread_rwlock_unlock(&cache_lock); cs_log("ERROR: NO added HASH to cache!!"); return; } } cs_ftime(&result->upd_time); //need to be updated at each cw! We use it for deleting this hash when no more cws arrive inside max_cache_time! //add cw to this csp hash cw = find_hash_table(&result->ht_cw, er->cw, sizeof(er->cw), &compare_cw); if(!cw){ if(count_hash_table(&result->ht_cw)>=10){ //max 10 different cws stored pthread_rwlock_unlock(&cache_lock); return; } while(1){ if(cs_malloc(&cw, sizeof(CW))){ memcpy(cw->cw, er->cw, sizeof(er->cw)); cw->odd_even = get_odd_even(er); cw->cwc_cycletime = er->cwc_cycletime; cw->cwc_next_cw_cycle = er->cwc_next_cw_cycle; cw->count= 0; cw->csp = 0; cw->cacheex = 0; cw->localcards=0; cw->proxy=0; cw->grp = 0; cw->caid = er->caid; cw->prid = er->prid; cw->srvid = er->srvid; cw->selected_reader=er->selected_reader; #ifdef CS_CACHEEX cw->cacheex_src=er->cacheex_src; #endif cw->pushout_client = NULL; while(1){ if (pthread_rwlock_init(&cw->pushout_client_lock, NULL) == 0) break; cs_log("Error creating lock pushout_client_lock!"); cs_sleepms(1); } add_hash_table(&result->ht_cw, &cw->ht_node, &result->ll_cw, &cw->ll_node, cw, cw->cw, sizeof(er->cw)); #ifdef CS_CACHEEX add_new_cw=true; #endif break; } cs_log("ERROR: NO added CW to cache!! Re-trying..."); cs_sleepms(1); } } //update if answered from csp/cacheex/local_proxy if(er->from_cacheex) cw->cacheex = 1; if(er->from_csp) cw->csp = 1; #ifdef CS_CACHEEX if(!er->cacheex_src){ #endif if(is_localreader(er->selected_reader, er)) cw->localcards=1; else cw->proxy = 1; #ifdef CS_CACHEEX } #endif //always update group and counter cw->grp |= er->grp; cw->count++; //sort cw_list by counter (DESC order) if(cw->count>1) sort_list(&result->ll_cw, count_sort); pthread_rwlock_unlock(&cache_lock); #ifdef CS_CACHEEX er->cw_cache=cw; cacheex_cache_push(er); //cacheex debug log lines and cw diff stuff if(check_client(er->cacheex_src)){ if(add_new_cw){ debug_ecm(D_CACHEEX|D_CSP, "got pushed ECM %s from %s", buf, er->from_csp ? "csp" : username(er->cacheex_src)); CW *cw_first = get_first_cw(result, er); if(er && cw_first){ //compare er cw with mostly counted cached cw if(memcmp(er->cw, cw_first->cw, sizeof(er->cw)) != 0) { er->cacheex_src->cwcacheexerrcw++; if (er->cacheex_src->account) er->cacheex_src->account->cwcacheexerrcw++; if (((0x0200| 0x0800) & cs_dblevel)) { //avoid useless operations if debug is not enabled char cw1[16*3+2], cw2[16*3+2]; cs_hexdump(0, er->cw, 16, cw1, sizeof(cw1)); cs_hexdump(0, cw_first->cw, 16, cw2, sizeof(cw2)); char ip1[20]="", ip2[20]=""; if (check_client(er->cacheex_src)) cs_strncpy(ip1, cs_inet_ntoa(er->cacheex_src->ip), sizeof(ip1)); if (check_client(cw_first->cacheex_src)) cs_strncpy(ip2, cs_inet_ntoa(cw_first->cacheex_src->ip), sizeof(ip2)); else if (cw_first->selected_reader && check_client(cw_first->selected_reader->client)) cs_strncpy(ip2, cs_inet_ntoa(cw_first->selected_reader->client->ip), sizeof(ip2)); debug_ecm(D_CACHEEX| D_CSP, "WARNING: Different CWs %s from %s(%s)<>%s(%s): %s<>%s ", buf, er->from_csp ? "csp" : username(er->cacheex_src), ip1, check_client(cw_first->cacheex_src)?username(cw_first->cacheex_src):(cw_first->selected_reader?cw_first->selected_reader->label:"unknown/csp"), ip2, cw1, cw2); } } } }else debug_ecm(D_CACHEEX| D_CSP, "got duplicate pushed ECM %s from %s", buf, er->from_csp ? "csp" : username(er->cacheex_src)); } #endif }
void cs_statistics(struct s_client *client) { if(!cfg.disableuserfile) { struct tm lt; char buf[LOG_BUF_SIZE]; float cwps; time_t walltime = cs_time(); localtime_r(&walltime, <); if(client->cwfound + client->cwnot > 0) { cwps = client->last - client->login; cwps /= client->cwfound + client->cwnot; } else { cwps = 0; } char channame[CS_SERVICENAME_SIZE]; get_servicename(client, client->last_srvid, client->last_provid, client->last_caid, channame, sizeof(channame)); int32_t lsec; if((client->last_caid == NO_CAID_VALUE) && (client->last_srvid == NO_SRVID_VALUE)) { lsec = client->last - client->login; } //client leave calc total duration else { lsec = client->last - client->lastswitch; } int32_t secs = 0, fullmins = 0, mins = 0, fullhours = 0; if((lsec > 0) && (lsec < 1000000)) { secs = lsec % 60; if(lsec > 60) { fullmins = lsec / 60; mins = fullmins % 60; if(fullmins > 60) { fullhours = fullmins / 60; } } } /* statistics entry start with 's' to filter it out on other end of pipe * so we can use the same Pipe as Log */ snprintf(buf, sizeof(buf), "s%02d.%02d.%02d %02d:%02d:%02d %3.1f %s %s %d %d %d %d %d %d %d %ld %ld %02d:%02d:%02d %s %04X@%06X:%04X %s\n", lt.tm_mday, lt.tm_mon + 1, lt.tm_year % 100, lt.tm_hour, lt.tm_min, lt.tm_sec, cwps, client->account->usr, cs_inet_ntoa(client->ip), client->port, client->cwfound, client->cwcache, client->cwnot, client->cwignored, client->cwtout, client->cwtun, client->login, client->last, fullhours, mins, secs, get_module(client)->desc, client->last_caid, client->last_provid, client->last_srvid, channame); cs_write_log_int(buf); } }
static char *monitor_client_info(char id, struct s_client *cl, char *sbuf){ char channame[32]; sbuf[0] = '\0'; if (cl){ char ldate[16], ltime[16], *usr; int32_t lsec, isec, con, cau, lrt =- 1; time_t now; struct tm lt; now=time((time_t*)0); if ((cfg.hideclient_to <= 0) || (now-cl->lastecm < cfg.hideclient_to) || (now-cl->lastemm < cfg.hideclient_to) || (cl->typ != 'c')) { lsec = now - cl->login; isec = now - cl->last; usr = username(cl); if (cl->dup) con = 2; else if ((cl->tosleep) && (now-cl->lastswitch>cl->tosleep)) con = 1; else con = 0; // no AU reader == 0 / AU ok == 1 / Last EMM > aulow == -1 if(cl->typ == 'c' || cl->typ == 'p' || cl->typ == 'r') { if ((cl->typ == 'c' && ll_count(cl->aureader_list) == 0) || ((cl->typ == 'p' || cl->typ == 'r') && cl->reader->audisabled)) cau = 0; else if ((now-cl->lastemm) / 60 > cfg.aulow) cau = (-1); else cau = 1; } else { cau = 0; } if( cl->typ == 'r') { int32_t i; struct s_reader *rdr; for (i=0,rdr=first_active_reader; rdr ; rdr=rdr->next, i++) if (cl->reader == rdr) lrt=i; if( lrt >= 0 ) lrt = 10 + cl->reader->card_status; } else lrt = cl->cwlastresptime; localtime_r(&cl->login, <); snprintf(ldate, sizeof(ldate), "%02d.%02d.%02d", lt.tm_mday, lt.tm_mon+1, lt.tm_year % 100); int32_t cnr=get_threadnum(cl); snprintf(ltime, sizeof(ldate), "%02d:%02d:%02d", lt.tm_hour, lt.tm_min, lt.tm_sec); snprintf(sbuf, 256, "[%c--CCC]%8X|%c|%d|%s|%d|%d|%s|%d|%s|%s|%s|%d|%04X:%04X|%s|%d|%d|%d|%d|%d|%d|%d|%d|%d|%d\n", id, cl->tid, cl->typ, cnr, usr, cau, cl->crypted, cs_inet_ntoa(cl->ip), cl->port, client_get_proto(cl), ldate, ltime, lsec, cl->last_caid, cl->last_srvid, get_servicename(cl, cl->last_srvid, cl->last_caid, channame), isec, con, cl->cwfound, cl->cwnot, cl->cwcache, cl->cwignored, cl->cwtout, cl->emmok, cl->emmnok, lrt); } } return sbuf; }
void cs_statistics(struct s_client * client) { if (!cfg.disableuserfile){ time_t t; struct tm lt; char buf[LOG_BUF_SIZE]; float cwps; time(&t); localtime_r(&t, <); if (client->cwfound+client->cwnot>0) { cwps=client->last-client->login; cwps/=client->cwfound+client->cwnot; } else cwps=0; char channame[32]; if(cfg.mon_appendchaninfo) get_servicename(client, client->last_srvid,client->last_caid, channame); else channame[0] = '\0'; int32_t lsec; if ((client->last_caid == 0xFFFF) && (client->last_srvid == 0xFFFF)) lsec = client->last - client->login; //client leave calc total duration else lsec = client->last - client->lastswitch; int32_t secs = 0, fullmins = 0, mins = 0, fullhours = 0; if((lsec > 0) && (lsec < 1000000)) { secs = lsec % 60; if (lsec > 60) { fullmins = lsec / 60; mins = fullmins % 60; if(fullmins > 60) { fullhours = fullmins / 60; } } } /* statistics entry start with 's' to filter it out on other end of pipe * so we can use the same Pipe as Log */ snprintf(buf, sizeof(buf), "s%02d.%02d.%02d %02d:%02d:%02d %3.1f %s %s %d %d %d %d %d %d %d %ld %ld %02d:%02d:%02d %s %04X:%04X %s\n", lt.tm_mday, lt.tm_mon+1, lt.tm_year%100, lt.tm_hour, lt.tm_min, lt.tm_sec, cwps, client->account->usr, cs_inet_ntoa(client->ip), client->port, client->cwfound, client->cwcache, client->cwnot, client->cwignored, client->cwtout, client->cwtun, client->login, client->last, fullhours, mins, secs, ph[client->ctyp].desc, client->last_caid, client->last_srvid, channame); cs_write_log_int(buf); } }
struct s_client *create_client(IN_ADDR_T ip) { struct s_client *cl; if(!cs_malloc(&cl, sizeof(struct s_client))) { cs_log("max connections reached (out of memory) -> reject client %s", IP_ISSET(ip) ? cs_inet_ntoa(ip) : "with null address"); return NULL; } //client part IP_ASSIGN(cl->ip, ip); cl->account = first_client->account; //master part SAFE_MUTEX_INIT(&cl->thread_lock, NULL); cl->login = cl->last = time(NULL); cl->tid = (uint32_t)rand(); //Now add new client to the list: struct s_client *last; cs_writelock(__func__, &clientlist_lock); for(last = first_client; last && last->next; last = last->next) { ; } //ends with cl on last client if (last) last->next = cl; int32_t bucket = (uintptr_t)cl / 16 % CS_CLIENT_HASHBUCKETS; cl->nexthashed = first_client_hashed[bucket]; first_client_hashed[bucket] = cl; cs_writeunlock(__func__, &clientlist_lock); return cl; }