#define MODULE_LOG_PREFIX "config" #include "globals.h" #include "module-anticasc.h" #include "oscam-array.h" #include "oscam-client.h" #include "oscam-conf.h" #include "oscam-conf-chk.h" #include "oscam-conf-mk.h" #include "oscam-config.h" #include "oscam-garbage.h" #include "oscam-lock.h" #include "oscam-string.h" #ifdef CS_CACHEEX_AIO #include "module-cacheex.h" #endif #define cs_user "oscam.user" static void account_tosleep_fn(const char *token, char *value, void *setting, FILE *f) { int32_t *tosleep = setting; if(value) { *tosleep = strToIntVal(value, cfg.tosleep); return; } if(*tosleep != cfg.tosleep || cfg.http_full_cfg) { fprintf_conf(f, token, "%d\n", *tosleep); } } static void account_c35_suppresscmd08_fn(const char *token, char *value, void *setting, FILE *f) { int8_t *c35_suppresscmd08 = setting; if(value) { *c35_suppresscmd08 = (int8_t)strToIntVal(value, cfg.c35_suppresscmd08); return; } if(*c35_suppresscmd08 != cfg.c35_suppresscmd08 || cfg.http_full_cfg) { fprintf_conf(f, token, "%d\n", *c35_suppresscmd08); } } /*static void account_umaxidle_fn(const char *token, char *value, void *setting, FILE *f) { int32_t *umaxidle = setting; if(value) { *umaxidle = (int32_t)strToIntVal(value, cfg.umaxidle); return; } if(*umaxidle != cfg.umaxidle || cfg.http_full_cfg) { fprintf_conf(f, token, "%u\n", *umaxidle); } } */ static void account_ncd_keepalive_fn(const char *token, char *value, void *setting, FILE *f) { int8_t *ncd_keepalive = setting; int8_t def_value = 0; #ifdef MODULE_NEWCAMD def_value = cfg.ncd_keepalive; #endif if(value) { *ncd_keepalive = (int8_t)strToIntVal(value, def_value); return; } if(*ncd_keepalive != def_value || cfg.http_full_cfg) { fprintf_conf(f, token, "%d\n", *ncd_keepalive); } } static void account_allowedprotocols_fn(const char *token, char *value, void *setting, FILE *f) { struct s_auth *account = setting; if(value) { account->allowedprotocols = 0; if(cs_strlen(value) > 3) { char *ptr, *saveptr1 = NULL; for(ptr = strtok_r(value, ",", &saveptr1); ptr; ptr = strtok_r(NULL, ",", &saveptr1)) { if(streq(ptr, "camd33")) { account->allowedprotocols |= LIS_CAMD33TCP; } else if(streq(ptr, "camd35")) { account->allowedprotocols |= LIS_CAMD35UDP; } else if(streq(ptr, "cs357x")) { account->allowedprotocols |= LIS_CAMD35UDP; } else if(streq(ptr, "cs378x")) { account->allowedprotocols |= LIS_CAMD35TCP; } else if(streq(ptr, "newcamd")) { account->allowedprotocols |= LIS_NEWCAMD; } else if(streq(ptr, "cccam")) { account->allowedprotocols |= LIS_CCCAM; } else if(streq(ptr, "csp")) { account->allowedprotocols |= LIS_CSPUDP; } else if(streq(ptr, "gbox")) { account->allowedprotocols |= LIS_GBOX; } else if(streq(ptr, "radegast")) { account->allowedprotocols |= LIS_RADEGAST; } else if(streq(ptr, "scam")) { account->allowedprotocols |= LIS_SCAM; } // these have no listener ports so it doesn't make sense else if(streq(ptr, "dvbapi")) { account->allowedprotocols |= LIS_DVBAPI; } else if(streq(ptr, "constcw")) { account->allowedprotocols |= LIS_CONSTCW; } else if(streq(ptr, "serial")) { account->allowedprotocols |= LIS_SERIAL; } } } return; } if(account->allowedprotocols || cfg.http_full_cfg) { value = mk_t_allowedprotocols(account); fprintf_conf(f, token, "%s\n", value); free_mk_t(value); } } static void account_au_fn(const char *token, char *value, void *setting, FILE *f) { struct s_auth *account = setting; if(value) { // set default values for usage during runtime from Webif account->autoau = 0; if(!account->aureader_list) { account->aureader_list = ll_create("aureader_list"); } if(streq(value, "1")) { account->autoau = 1; } ll_clear(account->aureader_list); LL_ITER itr = ll_iter_create(configured_readers); struct s_reader *rdr; char *pch, *saveptr1 = NULL; for(pch = strtok_r(value, ",", &saveptr1); pch != NULL; pch = strtok_r(NULL, ",", &saveptr1)) { ll_iter_reset(&itr); while((rdr = ll_iter_next(&itr))) { if(streq(rdr->label, pch) || account->autoau) { ll_append(account->aureader_list, rdr); } } } return; } if(account->autoau == 1) { fprintf_conf(f, token, "%d\n", account->autoau); } else if(account->aureader_list) { value = mk_t_aureader(account); if(cs_strlen(value) > 0) { fprintf_conf(f, token, "%s\n", value); } free_mk_t(value); } else if(cfg.http_full_cfg) { fprintf_conf(f, token, "%s\n", ""); } } static void account_expdate_fn(const char *token, char *value, void *setting, FILE *f) { struct s_auth *account = setting; if(value) { if(!value[0]) { account->expirationdate = (time_t)0; return; } int i; struct tm cstime; char *ptr1, *saveptr1 = NULL; memset(&cstime, 0, sizeof(cstime)); for(i = 0, ptr1 = strtok_r(value, "-/", &saveptr1); i < 3 && ptr1; ptr1 = strtok_r(NULL, "-/", &saveptr1), i++) { switch(i) { case 0: cstime.tm_year = atoi(ptr1) - 1900; break; case 1: cstime.tm_mon = atoi(ptr1) - 1; break; case 2: cstime.tm_mday = atoi(ptr1); break; } } cstime.tm_hour = 23; cstime.tm_min = 59; cstime.tm_sec = 59; cstime.tm_isdst = -1; account->expirationdate = mktime(&cstime); return; } if(account->expirationdate || cfg.http_full_cfg) { char buf[16]; struct tm timeinfo; localtime_r(&account->expirationdate, &timeinfo); strftime(buf, 16, "%Y-%m-%d", &timeinfo); fprintf_conf(f, token, "%s\n", streq(buf, "1970-01-01") ? "" : buf); } } static void account_allowedtimeframe_fn(const char *token, char *value, void *setting, FILE *f) { struct s_auth *account = setting; int32_t i, j, t, startt, endt; char *dest; uint8_t day_idx; int32_t allowed[4]; uint32_t tempo = 0; char *ptr1, *ptr2, *ptr3, *saveptr1 = NULL, *saveptr2 = NULL; if(value) { //First empty allowedtimeframe array very important otherwise new config won't be properly set for(i = 0; i < SIZE_SHORTDAY; i++) { for(j = 0; j < 24; j++) { account->allowedtimeframe[i][j][0] = 0; account->allowedtimeframe[i][j][1] = 0; } } account->allowedtimeframe_set=0; strtoupper(value); for(i = 0, ptr1 = strtok_r(value, ";", &saveptr1); (ptr1); ptr1 = strtok_r(NULL, ";", &saveptr1), i++) { if((ptr2 = strchr(trim(ptr1), '@'))) { *ptr2++ = '\0'; // clean up @ symbol // ptr1 is the day dest = strstr(weekdstr,ptr1); day_idx = (dest - weekdstr) / 3; for(j = 0, ptr3 = strtok_r(ptr2, ",", &saveptr2); (ptr3); ptr3 = strtok_r(NULL, ",", &saveptr2), j++) { if((sscanf(ptr3, "%2d:%2d-%2d:%2d", &allowed[0], &allowed[1], &allowed[2], &allowed[3]) == 4) && (day_idx < SIZE_SHORTDAY)) { startt = allowed[0] * 60 + allowed[1]; endt = allowed[2] * 60 + allowed[3]; if(startt == endt) { endt++; } // end time cannot be the same as the star time if((startt < 0) || (startt > 1439)) { startt = 0; } // could not start later than 23H59, avoid overflow if((endt < 0) || (endt > 1440)) { endt = 1440; } // could not be higher than 24H00, avoid overflow account->allowedtimeframe_set = 1; if(startt > endt) { for(t = startt; t < 1440; t++) { tempo = (1 << (t % 30)); account->allowedtimeframe[day_idx][t / 60][(t / 30) % 2] = account->allowedtimeframe[day_idx][t / 60][(t / 30) % 2] | tempo; } startt = 0; } for(t = startt; t < endt; t++) { tempo = (1 << (t % 30)); account->allowedtimeframe[day_idx][t / 60][((t / 30) % 2)] = account->allowedtimeframe[day_idx][t / 60][(t / 30) % 2] | tempo; } } else { fprintf(stderr, "WARNING: Value '%s' is not valid for allowedtimeframe (DAY@HH:MM-HH:MM)\n", value); } } } else // No day specified so whole week (ALL) { if(sscanf(ptr1, "%2d:%2d-%2d:%2d", &allowed[0], &allowed[1], &allowed[2], &allowed[3]) == 4) { startt = allowed[0] * 60 + allowed[1]; endt = allowed[2] * 60 + allowed[3]; if(startt == endt) { endt++; } // end time cannot be the same as the star time if((startt <0) || (startt > 1439)) { startt = 0; } // could not start later than 23H59, avoid overflow if((endt <0) || (endt > 1440)) { endt = 1440; } // could not be higher than 24H00, avoid overflow account->allowedtimeframe_set = 1; dest = strstr(weekdstr,"ALL"); day_idx = (dest - weekdstr) / 3; if(startt > endt) { for(t = startt; t < 1440; t++) { tempo = (1 << (t % 30)); account->allowedtimeframe[day_idx][t / 60][(t / 30) % 2] = account->allowedtimeframe[7][t / 60][(t / 30) % 2] | tempo; } startt=0; } for(t = startt; t < endt; t++) { tempo = (1 << (t % 30)); account->allowedtimeframe[day_idx][t / 60][(t / 30) % 2] = account->allowedtimeframe[7][t / 60][(t / 30) % 2] | tempo; } } else { fprintf(stderr, "WARNING: Value '%s' is not valid for allowedtimeframe (hh:mm-hh:mm)\n", value); } } } return; } if(account->allowedtimeframe_set) { value = mk_t_allowedtimeframe(account); fprintf_conf(f, token, "%s\n", value); free_mk_t(value); } else if(cfg.http_full_cfg) { fprintf_conf(f, token, "%s\n", ""); } } static void account_tuntab_fn(const char *token, char *value, void *setting, FILE *f) { TUNTAB *ttab = setting; if(value) { if(cs_strlen(value) == 0) { tuntab_clear(ttab); } else { chk_tuntab(value, ttab); } return; } if((ttab->ttdata && ttab->ttdata[0].bt_caidfrom) || cfg.http_full_cfg) { value = mk_t_tuntab(ttab); fprintf_conf(f, token, "%s\n", value); free_mk_t(value); } } void group_fn(const char *token, char *value, void *setting, FILE *f) { uint64_t *grp = setting; if(value) { char *ptr1, *saveptr1 = NULL; *grp = 0; for(ptr1 = strtok_r(value, ",", &saveptr1); ptr1; ptr1 = strtok_r(NULL, ",", &saveptr1)) { int32_t g; g = atoi(ptr1); if(g > 0 && g < 65) { *grp |= (((uint64_t)1) << (g - 1)); } } return; } if(*grp || cfg.http_full_cfg) { value = mk_t_group(*grp); fprintf_conf(f, token, "%s\n", value); free_mk_t(value); } } void services_fn(const char *token, char *value, void *setting, FILE *f) { SIDTABS *sidtabs = setting; if(value) { strtolower(value); chk_services(value, sidtabs); return; } value = mk_t_service(sidtabs); if(cs_strlen(value) > 0 || cfg.http_full_cfg) { fprintf_conf(f, token, "%s\n", value); } free_mk_t(value); } void class_fn(const char *token, char *value, void *setting, FILE *f) { CLASSTAB *cltab = setting; if(value) { strtolower(value); chk_cltab(value, cltab); return; } value = mk_t_cltab(cltab); if(cs_strlen(value) > 0 || cfg.http_full_cfg) { fprintf_conf(f, token, "%s\n", value); free_mk_t(value); } } #if defined(CS_ANTICASC) || defined(CS_CACHEEX_AIO) static void account_fixups_fn(void *var) { struct s_auth *account = var; #endif #if defined(CS_ANTICASC) if(account->ac_users < -1) { account->ac_users = DEFAULT_AC_USERS; } if(account->ac_penalty < -1) { account->ac_penalty = DEFAULT_AC_PENALTY; } if(account->acosc_max_ecms_per_minute < -1) { account->acosc_max_ecms_per_minute = -1; } if(account->acosc_max_active_sids < -1) { account->acosc_max_active_sids = -1; } if(account->acosc_zap_limit < -1) { account->acosc_zap_limit = -1; } if(account->acosc_penalty < -1) { account->acosc_penalty = -1; } if(account->acosc_penalty_duration < -1) { account->acosc_penalty_duration = -1; } if(account->acosc_delay < -1) { account->acosc_delay = -1; } if((account->acosc_penalty == 4) || ((cfg.acosc_penalty == 4) && (account->acosc_penalty == -1))) { account->acosc_max_active_sids = -1; // use global value account->acosc_zap_limit = -1; // use global value account->acosc_penalty_duration = -1; // use global value if((account->acosc_max_ecms_per_minute != -1) && (account->acosc_max_ecms_per_minute != 0)) { if(account->acosc_max_ecms_per_minute < 6) { account->acosc_max_ecms_per_minute = 6; } if(account->acosc_max_ecms_per_minute > 20) { account->acosc_max_ecms_per_minute = 20; } account->acosc_penalty_duration = (60 / account->acosc_max_ecms_per_minute); } } #endif #if defined(CS_CACHEEX_AIO) // lgo-ctab -> lgo-ftab port caidtab2ftab_add(&account->cacheex.localgenerated_only_in_caidtab, &account->cacheex.lg_only_in_tab); caidtab_clear(&account->cacheex.localgenerated_only_in_caidtab); caidtab2ftab_add(&account->cacheex.localgenerated_only_caidtab, &account->cacheex.lg_only_tab); caidtab_clear(&account->cacheex.localgenerated_only_caidtab); #endif #if defined(CS_ANTICASC) || defined(CS_CACHEEX_AIO) } #endif #define OFS(X) offsetof(struct s_auth, X) #define SIZEOF(X) sizeof(((struct s_auth *)0)->X) static const struct config_list account_opts[] = { #if defined(CS_ANTICASC) || defined(CS_CACHEEX_AIO) DEF_OPT_FIXUP_FUNC(account_fixups_fn), #endif DEF_OPT_INT8("disabled" , OFS(disabled), 0), DEF_OPT_SSTR("user" , OFS(usr), "", SIZEOF(usr)), DEF_OPT_STR("pwd" , OFS(pwd), NULL), #ifdef WEBIF DEF_OPT_STR("description" , OFS(description), NULL), #endif DEF_OPT_STR("hostname" , OFS(dyndns), NULL), DEF_OPT_FUNC("caid" , OFS(ctab), check_caidtab_fn), DEF_OPT_INT8("uniq" , OFS(uniq), 0), DEF_OPT_UINT8("sleepsend" , OFS(c35_sleepsend), 0), DEF_OPT_INT32("failban" , OFS(failban), 0), DEF_OPT_INT8("monlevel" , OFS(monlvl), 0), DEF_OPT_FUNC("sleep" , OFS(tosleep), account_tosleep_fn), DEF_OPT_FUNC("suppresscmd08" , OFS(c35_suppresscmd08), account_c35_suppresscmd08_fn), DEF_OPT_INT32("umaxidle" , OFS(umaxidle), -1), DEF_OPT_FUNC("keepalive" , OFS(ncd_keepalive), account_ncd_keepalive_fn), DEF_OPT_FUNC("au" , 0, account_au_fn), DEF_OPT_UINT8("emmreassembly" , OFS(emm_reassembly), 2), DEF_OPT_FUNC("expdate" , 0, account_expdate_fn), DEF_OPT_FUNC("allowedprotocols" , 0, account_allowedprotocols_fn), DEF_OPT_FUNC("allowedtimeframe" , 0, account_allowedtimeframe_fn), DEF_OPT_FUNC("betatunnel" , OFS(ttab), account_tuntab_fn), DEF_OPT_FUNC("group" , OFS(grp), group_fn), DEF_OPT_FUNC("services" , OFS(sidtabs), services_fn), DEF_OPT_INT8("preferlocalcards" , OFS(preferlocalcards), -1), DEF_OPT_FUNC_X("ident" , OFS(ftab), ftab_fn, FTAB_ACCOUNT | FTAB_PROVID), DEF_OPT_FUNC_X("chid" , OFS(fchid), ftab_fn, FTAB_ACCOUNT | FTAB_CHID), DEF_OPT_FUNC("class" , OFS(cltab), class_fn), DEF_OPT_UINT32("max_connections" , OFS(max_connections), 1), #ifdef CS_CACHEEX DEF_OPT_INT8("cacheex" , OFS(cacheex.mode), 0), DEF_OPT_INT8("cacheex_maxhop" , OFS(cacheex.maxhop), 0), #ifdef CS_CACHEEX_AIO DEF_OPT_INT8("cacheex_maxhop_lg" , OFS(cacheex.maxhop_lg), 0), #endif DEF_OPT_FUNC("cacheex_maxhop_percaid" , OFS(cacheex.maxhop_percaid), caidvaluetab_fn), #ifdef CS_CACHEEX_AIO DEF_OPT_FUNC("cacheex_maxhop_lg_percaid" , OFS(cacheex.maxhop_lg_percaid),caidvaluetab_fn), #endif DEF_OPT_FUNC("cacheex_ecm_filter" , OFS(cacheex.filter_caidtab), cacheex_hitvaluetab_fn), DEF_OPT_UINT8("cacheex_drop_csp" , OFS(cacheex.drop_csp), 0), DEF_OPT_UINT8("cacheex_allow_request" , OFS(cacheex.allow_request), 0), DEF_OPT_UINT8("no_wait_time" , OFS(no_wait_time), 0), DEF_OPT_UINT8("cacheex_allow_filter" , OFS(cacheex.allow_filter), 1), #ifdef CS_CACHEEX_AIO DEF_OPT_UINT8("cacheex_allow_maxhop" , OFS(cacheex.allow_maxhop), 0), #endif DEF_OPT_UINT8("cacheex_block_fakecws" , OFS(cacheex.block_fakecws), 0), DEF_OPT_UINT8("disablecrccacheex" , OFS(disablecrccacheex), 0), DEF_OPT_FUNC_X("disablecrccacheex_only_for", OFS(disablecrccacheex_only_for), ftab_fn, FTAB_ACCOUNT | FTAB_IGNCRCCEX4USERONLYFOR), #ifdef CS_CACHEEX_AIO DEF_OPT_UINT8("cacheex_cw_check_for_push" , OFS(cacheex.cw_check_for_push), 0), DEF_OPT_UINT8("cacheex_lg_only_remote_settings", OFS(cacheex.lg_only_remote_settings), 1), DEF_OPT_UINT8("cacheex_localgenerated_only", OFS(cacheex.localgenerated_only), 0), DEF_OPT_FUNC("cacheex_localgenerated_only_caid", OFS(cacheex.localgenerated_only_caidtab), check_caidtab_fn), DEF_OPT_FUNC_X("cacheex_lg_only_tab" , OFS(cacheex.lg_only_tab), ftab_fn, 0), DEF_OPT_UINT8("cacheex_lg_only_in_aio_only", OFS(cacheex.lg_only_in_aio_only), 0), DEF_OPT_UINT8("cacheex_localgenerated_only_in", OFS(cacheex.localgenerated_only_in), 0), DEF_OPT_FUNC("cacheex_localgenerated_only_in_caid", OFS(cacheex.localgenerated_only_in_caidtab), check_caidtab_fn), DEF_OPT_FUNC_X("cacheex_lg_only_in_tab" , OFS(cacheex.lg_only_in_tab), ftab_fn, 0), DEF_OPT_FUNC("cacheex_nopushafter" , OFS(cacheex.cacheex_nopushafter_tab), caidvaluetab_fn), #endif #endif #ifdef MODULE_CCCAM DEF_OPT_INT32("cccmaxhops" , OFS(cccmaxhops), DEFAULT_CC_MAXHOPS), DEF_OPT_INT8("cccreshare" , OFS(cccreshare), DEFAULT_CC_RESHARE), DEF_OPT_INT8("cccignorereshare" , OFS(cccignorereshare), DEFAULT_CC_IGNRSHR), DEF_OPT_INT8("cccstealth" , OFS(cccstealth), DEFAULT_CC_STEALTH), #endif #ifdef CS_ANTICASC DEF_OPT_INT32("fakedelay" , OFS(ac_fakedelay), -1), DEF_OPT_INT32("numusers" , OFS(ac_users), DEFAULT_AC_USERS), DEF_OPT_INT8("penalty" , OFS(ac_penalty), DEFAULT_AC_PENALTY), DEF_OPT_INT8("acosc_max_ecms_per_minute" , OFS(acosc_max_ecms_per_minute), -1 ), DEF_OPT_INT8("acosc_max_active_sids" , OFS(acosc_max_active_sids), -1 ), DEF_OPT_INT8("acosc_zap_limit" , OFS(acosc_zap_limit), -1 ), DEF_OPT_INT8("acosc_penalty" , OFS(acosc_penalty), -1 ), DEF_OPT_INT32("acosc_penalty_duration" , OFS(acosc_penalty_duration), -1 ), DEF_OPT_INT32("acosc_delay" , OFS(acosc_delay), -1 ), #endif #ifdef WITH_LB DEF_OPT_INT32("lb_nbest_readers" , OFS(lb_nbest_readers), -1), DEF_OPT_INT32("lb_nfb_readers" , OFS(lb_nfb_readers), -1), DEF_OPT_FUNC("lb_nbest_percaid" , OFS(lb_nbest_readers_tab), caidvaluetab_fn), #endif #ifdef CW_CYCLE_CHECK DEF_OPT_INT8("cwc_disable" , OFS(cwc_disable), 0), #endif DEF_LAST_OPT }; void chk_account(const char *token, char *value, struct s_auth *account) { if(config_list_parse(account_opts, token, value, account)) { return; } else if(token[0] != '#') { fprintf(stderr, "Warning: keyword '%s' in account section not recognized\n", token); } } void account_set_defaults(struct s_auth *account) { config_list_set_defaults(account_opts, account); } struct s_auth *init_userdb(void) { FILE *fp = open_config_file(cs_user); if(!fp) { return NULL; } struct s_auth *authptr = NULL; int32_t tag = 0, nr = 0, expired = 0, disabled = 0; char *token; struct s_auth *account = NULL; struct s_auth *probe = NULL; if(!cs_malloc(&token, MAXLINESIZE)) { return NULL; } while(fgets(token, MAXLINESIZE, fp)) { int32_t l; void *ptr; if((l = cs_strlen(trim(token))) < 3) { continue; } if(token[0] == '[' && token[l - 1] == ']') { token[l - 1] = 0; tag = streq("account", strtolower(token + 1)); if(!cs_malloc(&ptr, sizeof(struct s_auth))) { break; } if(account) { account->next = ptr; } else { authptr = ptr; } account = ptr; account_set_defaults(account); nr++; continue; } if(!tag) { continue; } char *value = strchr(token, '='); if(!value) { continue; } *value++ = '\0'; // check for duplicate useraccounts and make the name unique if(streq(trim(strtolower(token)), "user")) { for(probe = authptr; probe; probe = probe->next) { if(!strcmp(probe->usr, trim(value))) { fprintf(stderr, "Warning: duplicate account '%s'\n", value); if (!cs_strncat(value, "_x", sizeof(probe->usr))) { cs_log("WARNING, bug here!"); } } } } chk_account(trim(strtolower(token)), trim(value), account); } NULLFREE(token); fclose(fp); for(account = authptr; account; account = account->next) { if(account->expirationdate && account->expirationdate < time(NULL)) { ++expired; } if(account->disabled) { ++disabled; } } cs_log("userdb reloaded: %d accounts loaded, %d expired, %d disabled", nr, expired, disabled); return authptr; } int32_t init_free_userdb(struct s_auth *ptr) { int32_t nro; for(nro = 0; ptr; nro++) { struct s_auth *ptr_next; ptr_next = ptr->next; ll_destroy(&ptr->aureader_list); ptr->next = NULL; config_list_gc_values(account_opts, ptr); ftab_clear(&ptr->ftab); ftab_clear(&ptr->fchid); tuntab_clear(&ptr->ttab); caidtab_clear(&ptr->ctab); NULLFREE(ptr->cltab.aclass); NULLFREE(ptr->cltab.bclass); #ifdef CS_CACHEEX cecspvaluetab_clear(&ptr->cacheex.filter_caidtab); ftab_clear(&ptr->disablecrccacheex_only_for); #ifdef CS_CACHEEX_AIO caidtab_clear(&ptr->cacheex.localgenerated_only_caidtab); caidtab_clear(&ptr->cacheex.localgenerated_only_in_caidtab); ftab_clear(&ptr->cacheex.lg_only_tab); ftab_clear(&ptr->cacheex.lg_only_in_tab); caidvaluetab_clear(&ptr->cacheex.cacheex_nopushafter_tab); #endif #endif #ifdef WITH_LB caidvaluetab_clear(&ptr->lb_nbest_readers_tab); #endif add_garbage(ptr); ptr = ptr_next; } cs_log("userdb %d accounts freed", nro); return nro; } int32_t write_userdb(void) { struct s_auth *account; FILE *f = create_config_file(cs_user); if(!f) { return 1; } for(account = cfg.account; account; account = account->next) { fprintf(f, "[account]\n"); config_list_apply_fixups(account_opts, account); config_list_save(f, account_opts, account, cfg.http_full_cfg); fprintf(f, "\n"); } return flush_config_file(f, cs_user); } void cs_accounts_chk(void) { struct s_auth *account1, *account2; struct s_auth *new_accounts = init_userdb(); cs_writelock(__func__, &config_lock); struct s_auth *old_accounts = cfg.account; for(account1 = cfg.account; account1; account1 = account1->next) { for(account2 = new_accounts; account2; account2 = account2->next) { if(!strcmp(account1->usr, account2->usr)) { account2->cwfound = account1->cwfound; account2->cwcache = account1->cwcache; account2->cwnot = account1->cwnot; account2->cwtun = account1->cwtun; account2->cwignored = account1->cwignored; account2->cwtout = account1->cwtout; account2->emmok = account1->emmok; account2->emmnok = account1->emmnok; account2->firstlogin = account1->firstlogin; ac_copy_vars(account1, account2); } } } cs_reinit_clients(new_accounts); cfg.account = new_accounts; init_free_userdb(old_accounts); ac_clear(); cs_writeunlock(__func__, &config_lock); }