2026-02-16 09:02:48 +00:00
|
|
|
#define MODULE_LOG_PREFIX "config"
|
|
|
|
|
|
|
|
|
|
#include "globals.h"
|
|
|
|
|
#include "module-stat.h"
|
|
|
|
|
#include "oscam-aes.h"
|
|
|
|
|
#include "oscam-array.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-reader.h"
|
|
|
|
|
#include "oscam-string.h"
|
|
|
|
|
#ifdef MODULE_GBOX
|
|
|
|
|
#include "module-gbox.h"
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef CS_CACHEEX_AIO
|
|
|
|
|
#include "module-cacheex.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define cs_srvr "oscam.server"
|
|
|
|
|
|
|
|
|
|
extern const struct s_cardreader *cardreaders[];
|
|
|
|
|
extern char *RDR_CD_TXT[];
|
|
|
|
|
|
|
|
|
|
static void reader_label_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
int i, found = 0;
|
|
|
|
|
if(!cs_strlen(value))
|
|
|
|
|
{ return; }
|
|
|
|
|
for(i = 0; i < (int)cs_strlen(value); i++)
|
|
|
|
|
{
|
|
|
|
|
if(value[i] == ' ')
|
|
|
|
|
{
|
|
|
|
|
value[i] = '_';
|
|
|
|
|
found++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(found)
|
|
|
|
|
{ fprintf(stderr, "Configuration reader: corrected label to %s\n", value); }
|
|
|
|
|
cs_strncpy(rdr->label, value, sizeof(rdr->label));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
fprintf_conf(f, token, "%s\n", rdr->label);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ecmwhitelist_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
if(cs_strlen(value))
|
|
|
|
|
chk_ecm_whitelist(value, &rdr->ecm_whitelist);
|
|
|
|
|
else
|
|
|
|
|
ecm_whitelist_clear(&rdr->ecm_whitelist);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
value = mk_t_ecm_whitelist(&rdr->ecm_whitelist);
|
|
|
|
|
if(cs_strlen(value) > 0 || cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "%s\n", value); }
|
|
|
|
|
free_mk_t(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ecmheaderwhitelist_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
if(cs_strlen(value))
|
|
|
|
|
chk_ecm_hdr_whitelist(value, &rdr->ecm_hdr_whitelist);
|
|
|
|
|
else
|
|
|
|
|
ecm_hdr_whitelist_clear(&rdr->ecm_hdr_whitelist);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
value = mk_t_ecm_hdr_whitelist(&rdr->ecm_hdr_whitelist);
|
|
|
|
|
if(cs_strlen(value) > 0 || cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "%s\n", value); }
|
|
|
|
|
free_mk_t(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void protocol_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
if(cs_strlen(value) == 0)
|
|
|
|
|
{ return; }
|
|
|
|
|
struct protocol_map
|
|
|
|
|
{
|
|
|
|
|
char *name;
|
|
|
|
|
int typ;
|
|
|
|
|
} protocols[] =
|
|
|
|
|
{
|
|
|
|
|
{ "serial", R_SERIAL },
|
|
|
|
|
{ "camd35", R_CAMD35 },
|
|
|
|
|
{ "cs378x", R_CS378X },
|
|
|
|
|
{ "cs357x", R_CAMD35 },
|
|
|
|
|
{ "camd33", R_CAMD33 },
|
|
|
|
|
{ "gbox", R_GBOX },
|
|
|
|
|
{ "cccam", R_CCCAM },
|
|
|
|
|
{ "cccam_ext", R_CCCAM },
|
|
|
|
|
{ "cccam_mcs", R_CCCAM },
|
|
|
|
|
{ "constcw", R_CONSTCW },
|
|
|
|
|
{ "radegast", R_RADEGAST },
|
|
|
|
|
{ "scam", R_SCAM },
|
|
|
|
|
{ "ghttp", R_GHTTP },
|
|
|
|
|
{ "newcamd", R_NEWCAMD },
|
|
|
|
|
{ "newcamd525", R_NEWCAMD },
|
|
|
|
|
{ "newcamd524", R_NEWCAMD },
|
|
|
|
|
{ "drecas", R_DRECAS },
|
|
|
|
|
{ "emu", R_EMU },
|
|
|
|
|
{ NULL, 0 }
|
|
|
|
|
}, *p;
|
|
|
|
|
int i;
|
|
|
|
|
// Parse card readers
|
|
|
|
|
for(i = 0; cardreaders[i]; i++)
|
|
|
|
|
{
|
|
|
|
|
if(streq(value, cardreaders[i]->desc))
|
|
|
|
|
{
|
|
|
|
|
rdr->crdr = cardreaders[i];
|
|
|
|
|
rdr->typ = cardreaders[i]->typ;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Parse protocols
|
|
|
|
|
for(i = 0, p = &protocols[0]; p->name; p = &protocols[++i])
|
|
|
|
|
{
|
|
|
|
|
if(streq(p->name, value))
|
|
|
|
|
{
|
|
|
|
|
rdr->typ = p->typ;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(rdr->typ == R_NEWCAMD)
|
|
|
|
|
{ rdr->ncd_proto = streq(value, "newcamd524") ? NCD_524 : NCD_525; }
|
|
|
|
|
if(!rdr->typ)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "ERROR: '%s' is unsupported reader protocol!\n", value);
|
|
|
|
|
rdr->enable = 0;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
fprintf_conf(f, token, "%s\n", reader_get_type_desc(rdr, 0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void device_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
int32_t isphysical = !is_network_reader(rdr);
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
int32_t i;
|
|
|
|
|
char *ptr, *saveptr1 = NULL;
|
|
|
|
|
for(i = 0, ptr = strtok_r(value, ",", &saveptr1); (i < 3) && (ptr); ptr = strtok_r(NULL, ",", &saveptr1), i++)
|
|
|
|
|
{
|
|
|
|
|
trim(ptr);
|
|
|
|
|
switch(i)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
cs_strncpy(rdr->device, ptr, sizeof(rdr->device));
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
rdr->r_port = atoi(ptr);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
rdr->l_port = atoi(ptr);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
fprintf_conf(f, token, "%s", rdr->device); // it should not have \n at the end
|
|
|
|
|
if((rdr->r_port || cfg.http_full_cfg) && !isphysical)
|
|
|
|
|
{ fprintf(f, ",%d", rdr->r_port); }
|
|
|
|
|
if((rdr->l_port || cfg.http_full_cfg) && !isphysical && strncmp(reader_get_type_desc(rdr, 0), "cccam", 5))
|
|
|
|
|
{ fprintf(f, ",%d", rdr->l_port); }
|
|
|
|
|
fprintf(f, "\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void reader_services_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
services_fn(token, value, setting, f);
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = container_of(setting, struct s_reader, sidtabs);
|
|
|
|
|
if(rdr)
|
|
|
|
|
{ rdr->changes_since_shareupdate = 1; }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void reader_lb_services_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
services_fn(token, value, setting, f);
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = container_of(setting, struct s_reader, lb_sidtabs);
|
|
|
|
|
if(rdr)
|
|
|
|
|
{ rdr->changes_since_shareupdate = 1; }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void reader_caid_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
check_caidtab_fn(token, value, setting, f);
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = container_of(setting, struct s_reader, ctab);
|
|
|
|
|
if(rdr)
|
|
|
|
|
{ rdr->changes_since_shareupdate = 1; }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_CARDREADER
|
|
|
|
|
static void boxid_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
rdr->boxid = cs_strlen(value) ? a2i(value, 4) : 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(rdr->boxid)
|
|
|
|
|
{ fprintf_conf(f, token, "%08X\n", rdr->boxid); }
|
|
|
|
|
else if(cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "\n"); }
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef READER_TONGFANG
|
|
|
|
|
static void tongfang3_calibsn_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
rdr->tongfang3_calibsn = strlen(value) ? a2i(value, 4) : 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(rdr->tongfang3_calibsn)
|
|
|
|
|
fprintf_conf(f, token, "%08X\n", rdr->tongfang3_calibsn);
|
|
|
|
|
else if(cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "\n"); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void tongfang_boxid_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
rdr->tongfang_boxid = cs_strlen(value) ? a2i(value, 4) : 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(rdr->tongfang_boxid)
|
|
|
|
|
{ fprintf_conf(f, token, "%08X\n", rdr->tongfang_boxid); }
|
|
|
|
|
else if(cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "\n"); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void stbid_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
int32_t len = cs_strlen(value);
|
|
|
|
|
if(len != 16)
|
|
|
|
|
{
|
|
|
|
|
rdr->stbid_length = 0;
|
|
|
|
|
memset(rdr->stbid, 0, 8);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(key_atob_l(value, rdr->stbid, len))
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "reader stbid parse error, %s=%s\n", token, value);
|
|
|
|
|
rdr->stbid_length = 0;
|
|
|
|
|
memset(rdr->stbid, 0, sizeof(rdr->stbid));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rdr->stbid_length = len/2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
int32_t len = rdr->stbid_length;
|
|
|
|
|
if(len > 0)
|
|
|
|
|
{
|
|
|
|
|
char tmp[len * 2 + 1];
|
|
|
|
|
fprintf_conf(f, "stbid", "%s\n", cs_hexdump(0, rdr->stbid, len, tmp, sizeof(tmp)));
|
|
|
|
|
}
|
|
|
|
|
else if(cfg.http_full_cfg)
|
|
|
|
|
{
|
|
|
|
|
fprintf_conf(f, "stbid", "\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void tongfang3_deskey_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
int32_t len = cs_strlen(value);
|
|
|
|
|
if(len != 16)
|
|
|
|
|
{
|
|
|
|
|
rdr->tongfang3_deskey_length = 0;
|
|
|
|
|
memset(rdr->tongfang3_deskey, 0, 8);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(key_atob_l(value, rdr->tongfang3_deskey, len))
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "reader tongfang3_deskey parse error, %s=%s\n", token, value);
|
|
|
|
|
rdr->tongfang3_deskey_length = 0;
|
|
|
|
|
memset(rdr->tongfang3_deskey, 0, sizeof(rdr->tongfang3_deskey));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rdr->tongfang3_deskey_length = len/2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
int32_t len = rdr->tongfang3_deskey_length;
|
|
|
|
|
if(len > 0)
|
|
|
|
|
{
|
|
|
|
|
char tmp[len * 2 + 1];
|
|
|
|
|
fprintf_conf(f, "tongfang3_deskey", "%s\n", cs_hexdump(0, rdr->tongfang3_deskey, len, tmp, sizeof(tmp)));
|
|
|
|
|
}
|
|
|
|
|
else if(cfg.http_full_cfg)
|
|
|
|
|
{
|
|
|
|
|
fprintf_conf(f, "tongfang3_deskey", "\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_CARDREADER
|
|
|
|
|
static void cwpkkey_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
int32_t len = strlen(value);
|
|
|
|
|
// rdr_log(rdr, "CWPK config key length: %16X", len);
|
|
|
|
|
if(len == 0 || len > 32)
|
|
|
|
|
{
|
|
|
|
|
rdr->cwpk_mod_length = 0;
|
|
|
|
|
memset(rdr->cwpk_mod, 0, sizeof(rdr->cwpk_mod));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(key_atob_l(value, rdr->cwpk_mod, len))
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "reader cwpkkey parse error, %s=%s\n", token, value);
|
|
|
|
|
rdr->cwpk_mod_length = 0;
|
|
|
|
|
memset(rdr->cwpk_mod, 0, sizeof(rdr->cwpk_mod));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rdr->cwpk_mod_length = len/2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
int32_t len = rdr->cwpk_mod_length;
|
|
|
|
|
if(len > 0)
|
|
|
|
|
{
|
|
|
|
|
char tmp[len * 2 + 1];
|
|
|
|
|
fprintf_conf(f, "cwpkkey", "%s\n", cs_hexdump(0, rdr->cwpk_mod, len, tmp, sizeof(tmp)));
|
|
|
|
|
}
|
|
|
|
|
else if(cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, "cwpkkey", "\n"); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void rsakey_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
int32_t len = cs_strlen(value);
|
|
|
|
|
if(len != 128 && len != 240)
|
|
|
|
|
{
|
|
|
|
|
rdr->rsa_mod_length = 0;
|
|
|
|
|
memset(rdr->rsa_mod, 0, 120);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(key_atob_l(value, rdr->rsa_mod, len))
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "reader rsakey parse error, %s=%s\n", token, value);
|
|
|
|
|
rdr->rsa_mod_length = 0;
|
|
|
|
|
memset(rdr->rsa_mod, 0, sizeof(rdr->rsa_mod));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rdr->rsa_mod_length = len/2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
int32_t len = rdr->rsa_mod_length;
|
|
|
|
|
if(len > 0)
|
|
|
|
|
{
|
|
|
|
|
char tmp[len * 2 + 1];
|
|
|
|
|
fprintf_conf(f, "rsakey", "%s\n", cs_hexdump(0, rdr->rsa_mod, len, tmp, sizeof(tmp)));
|
|
|
|
|
}
|
|
|
|
|
else if(cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, "rsakey", "\n"); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void deskey_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
int32_t len = cs_strlen(value);
|
|
|
|
|
if(((len % 16) != 0) || len == 0 || len > 128*2)
|
|
|
|
|
{
|
|
|
|
|
rdr->des_key_length = 0;
|
|
|
|
|
memset(rdr->des_key, 0, sizeof(rdr->des_key));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(key_atob_l(value, rdr->des_key, len))
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "reader 3DES key parse error, %s=%s\n", token, value);
|
|
|
|
|
rdr->des_key_length = 0;
|
|
|
|
|
memset(rdr->des_key, 0, sizeof(rdr->des_key));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rdr->des_key_length = len/2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
int32_t len = rdr->des_key_length;
|
|
|
|
|
if(len > 0)
|
|
|
|
|
{
|
|
|
|
|
char tmp[len * 2 + 1];
|
|
|
|
|
fprintf_conf(f, "deskey", "%s\n", cs_hexdump(0, rdr->des_key, len, tmp, sizeof(tmp)));
|
|
|
|
|
}
|
|
|
|
|
else if(cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, "deskey", "\n"); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void boxkey_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
int32_t len = cs_strlen(value);
|
|
|
|
|
if(((len % 8) != 0) || len == 0 || len > 32)
|
|
|
|
|
{
|
|
|
|
|
rdr->boxkey_length = 0;
|
|
|
|
|
memset(rdr->boxkey, 0, sizeof(rdr->boxkey));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(key_atob_l(value, rdr->boxkey, len))
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "reader boxkey parse error, %s=%s\n", token, value);
|
|
|
|
|
rdr->boxkey_length = 0;
|
|
|
|
|
memset(rdr->boxkey, 0, sizeof(rdr->boxkey));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rdr->boxkey_length = len/2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
int32_t len = rdr->boxkey_length;
|
|
|
|
|
if(len > 0)
|
|
|
|
|
{
|
|
|
|
|
char tmp[len * 2 + 1];
|
|
|
|
|
fprintf_conf(f, "boxkey", "%s\n", cs_hexdump(0, rdr->boxkey, len, tmp, sizeof(tmp)));
|
|
|
|
|
}
|
|
|
|
|
else if(cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, "boxkey", "\n"); }
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(READER_NAGRA) || defined(READER_NAGRA_MERLIN)
|
|
|
|
|
static void param_fn(const char *token, char *value, void *setting, long data, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
uint8_t *var = setting, valid_len = data & 0xFF;
|
|
|
|
|
uint8_t *var_len = (var + (data >> 8));
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
int32_t len = cs_strlen(value);
|
|
|
|
|
if(len != valid_len * 2 || key_atob_l(value, var, len))
|
|
|
|
|
{
|
|
|
|
|
if(len > 0)
|
|
|
|
|
{ fprintf(stderr, "reader %s parse error, %s=%s\n", token, token, value); }
|
|
|
|
|
*var_len = 0;
|
|
|
|
|
memset(var, 0, valid_len);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*var_len = valid_len; // found and correct
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(*var_len)
|
|
|
|
|
{
|
|
|
|
|
char tmp[*var_len * 2 + 1];
|
|
|
|
|
fprintf_conf(f, token, "%s\n", cs_hexdump(0, var, *var_len, tmp, sizeof(tmp)));
|
|
|
|
|
}
|
|
|
|
|
else if(cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "\n"); }
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static void flags_fn(const char *token, char *value, void *setting, long flag, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
uint32_t *var = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
int i = atoi(value);
|
|
|
|
|
if(!i && (*var & flag))
|
|
|
|
|
{ *var -= flag; }
|
|
|
|
|
if(i)
|
|
|
|
|
{ *var |= flag; }
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if((*var & flag) || cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "%d\n", (*var & flag) ? 1 : 0); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef READER_VIDEOGUARD
|
|
|
|
|
static void ins7E_fn(const char *token, char *value, void *setting, long var_size, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
uint8_t *var = setting;
|
|
|
|
|
var_size -= 1; // var_size contains sizeof(var) which is [X + 1]
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
int32_t len = cs_strlen(value);
|
|
|
|
|
if(len != var_size * 2 || key_atob_l(value, var, len))
|
|
|
|
|
{
|
|
|
|
|
if(len > 0)
|
|
|
|
|
{ fprintf(stderr, "reader %s parse error, %s=%s\n", token, token, value); }
|
|
|
|
|
memset(var, 0, var_size + 1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var[var_size] = 1; // found and correct
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(var[var_size])
|
|
|
|
|
{
|
|
|
|
|
char tmp[var_size * 2 + 1];
|
|
|
|
|
fprintf_conf(f, token, "%s\n", cs_hexdump(0, var, var_size, tmp, sizeof(tmp)));
|
|
|
|
|
}
|
|
|
|
|
else if(cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "\n"); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ins42_fn(const char *token, char *value, void *setting, long var_size, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
uint8_t *var = setting;
|
|
|
|
|
var_size -= 1; // var_size contains sizeof(var) which is [X + 1]
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
int32_t len = cs_strlen(value);
|
|
|
|
|
if(len != var_size * 2 || key_atob_l(value, var, len))
|
|
|
|
|
{
|
|
|
|
|
if(len > 0)
|
|
|
|
|
{ fprintf(stderr, "reader %s parse error, %s=%s\n", token, token, value); }
|
|
|
|
|
memset(var, 0, var_size + 1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var[var_size] = 1; // found and correct
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(var[var_size])
|
|
|
|
|
{
|
|
|
|
|
char tmp[var_size * 2 + 1];
|
|
|
|
|
fprintf_conf(f, token, "%s\n", cs_hexdump(0, var, var_size, tmp, sizeof(tmp)));
|
|
|
|
|
}
|
|
|
|
|
else if(cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "\n"); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void des_and_3des_key_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
uint8_t *var = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
int32_t len = cs_strlen(value);
|
|
|
|
|
if(((len != 16) && (len != 32)) || (key_atob_l(value, var, len)))
|
|
|
|
|
{
|
|
|
|
|
if(len > 0)
|
|
|
|
|
{ fprintf(stderr, "reader %s parse error, %s=%s\n", token, token, value); }
|
|
|
|
|
memset(var, 0, 17);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var[16] = len/2;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(var[16])
|
|
|
|
|
{
|
|
|
|
|
char tmp[var[16] * 2 + 1];
|
|
|
|
|
fprintf_conf(f, token, "%s\n", cs_hexdump(0, var, var[16], tmp, sizeof(tmp)));
|
|
|
|
|
}
|
|
|
|
|
else if(cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "\n"); }
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_CARDREADER
|
|
|
|
|
static void atr_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
memset(rdr->atr, 0, sizeof(rdr->atr));
|
|
|
|
|
rdr->atrlen = cs_strlen(value);
|
|
|
|
|
if(rdr->atrlen)
|
|
|
|
|
{
|
|
|
|
|
if(rdr->atrlen > (int32_t)sizeof(rdr->atr) * 2)
|
|
|
|
|
{ rdr->atrlen = (int32_t)sizeof(rdr->atr) * 2; }
|
|
|
|
|
key_atob_l(value, rdr->atr, rdr->atrlen);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(rdr->atr[0] || cfg.http_full_cfg)
|
|
|
|
|
{
|
|
|
|
|
int j;
|
|
|
|
|
fprintf_conf(f, token, "%s", ""); // it should not have \n at the end
|
|
|
|
|
if(rdr->atr[0])
|
|
|
|
|
{
|
|
|
|
|
for(j = 0; j < rdr->atrlen / 2; j++)
|
|
|
|
|
{
|
|
|
|
|
fprintf(f, "%02X", rdr->atr[j]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fprintf(f, "\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void detect_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for(i = 0; RDR_CD_TXT[i]; i++)
|
|
|
|
|
{
|
|
|
|
|
if(!strcmp(value, RDR_CD_TXT[i]))
|
|
|
|
|
{
|
|
|
|
|
rdr->detect = i;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(value[0] == '!' && streq(value + 1, RDR_CD_TXT[i]))
|
|
|
|
|
{ rdr->detect = i | 0x80; }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
fprintf_conf(f, token, "%s%s\n", rdr->detect & 0x80 ? "!" : "", RDR_CD_TXT[rdr->detect & 0x7f]);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void ftab_fn(const char *token, char *value, void *setting, long ftab_type, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
FTAB *ftab = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
if(cs_strlen(value))
|
|
|
|
|
chk_ftab(value, ftab);
|
|
|
|
|
else
|
|
|
|
|
ftab_clear(ftab);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(ftab_type & FTAB_READER)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = NULL;
|
|
|
|
|
if(ftab_type & FTAB_PROVID) { rdr = container_of(setting, struct s_reader, ftab); }
|
|
|
|
|
if(ftab_type & FTAB_CHID) { rdr = container_of(setting, struct s_reader, fchid); }
|
|
|
|
|
if(ftab_type & FTAB_FBPCAID) { rdr = container_of(setting, struct s_reader, fallback_percaid); }
|
|
|
|
|
if(ftab_type & FTAB_LOCALCARDS) { rdr = container_of(setting, struct s_reader, localcards); }
|
|
|
|
|
if(ftab_type & FTAB_IGNCHKSMCAID){ rdr = container_of(setting, struct s_reader, disablecrccws_only_for); }
|
|
|
|
|
#ifdef WITH_EMU
|
|
|
|
|
if(ftab_type & FTAB_EMUAU) { rdr = container_of(setting, struct s_reader, emu_auproviders); }
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef MODULE_GBOX
|
|
|
|
|
if(ftab_type & FTAB_CCCGBXRESHARE){ rdr = container_of(setting, struct s_reader, ccc_gbx_reshare_ident); }
|
|
|
|
|
#endif
|
|
|
|
|
if(rdr)
|
|
|
|
|
{ rdr->changes_since_shareupdate = 1; }
|
|
|
|
|
}
|
|
|
|
|
value = mk_t_ftab(ftab);
|
|
|
|
|
if(cs_strlen(value) > 0 || cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "%s\n", value); }
|
|
|
|
|
free_mk_t(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef READER_VIACCESS
|
|
|
|
|
static void aeskeys_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
parse_aes_keys(rdr, value);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
value = mk_t_aeskeys(rdr);
|
|
|
|
|
if(cs_strlen(value) > 0 || cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "%s\n", value); }
|
|
|
|
|
free_mk_t(value);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static void emmcache_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
rdr->cachemm = 0;
|
|
|
|
|
rdr->rewritemm = 0;
|
|
|
|
|
rdr->logemm = 0;
|
|
|
|
|
rdr->deviceemm = 0;
|
|
|
|
|
if(cs_strlen(value))
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
char *ptr, *saveptr1 = NULL;
|
|
|
|
|
for(i = 0, ptr = strtok_r(value, ",", &saveptr1); (i < 4) && (ptr); ptr = strtok_r(NULL, ",", &saveptr1), i++)
|
|
|
|
|
{
|
|
|
|
|
switch(i)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
rdr->cachemm = atoi(ptr);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
rdr->rewritemm = atoi(ptr);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
rdr->logemm = atoi(ptr);
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
rdr->deviceemm = atoi(ptr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(rdr->rewritemm <= 0)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Setting reader \"emmcache\" to %i,%d,%i,%i instead of %i,%i,%i,%i.",
|
|
|
|
|
rdr->cachemm, 1, rdr->logemm, rdr->deviceemm,
|
|
|
|
|
rdr->cachemm, rdr->rewritemm, rdr->logemm, rdr->deviceemm);
|
|
|
|
|
fprintf(stderr, "Zero or negative number of rewrites is silly\n");
|
|
|
|
|
rdr->rewritemm = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(rdr->cachemm || rdr->logemm || cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "%d,%d,%d,%d\n", rdr->cachemm, rdr->rewritemm, rdr->logemm,rdr->deviceemm); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void blockemm_bylen_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
char *ptr, *saveptr1 = NULL, dash;
|
|
|
|
|
struct s_emmlen_range *blocklen;
|
|
|
|
|
uint32_t num;
|
|
|
|
|
|
|
|
|
|
if(!cs_strlen(value))
|
|
|
|
|
{
|
|
|
|
|
ll_destroy_data(&rdr->blockemmbylen);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!rdr->blockemmbylen)
|
|
|
|
|
{ rdr->blockemmbylen = ll_create("blockemmbylen"); }
|
|
|
|
|
else
|
|
|
|
|
{ ll_clear_data(rdr->blockemmbylen); }
|
|
|
|
|
|
|
|
|
|
for(ptr = strtok_r(value, ",", &saveptr1); ptr;
|
|
|
|
|
ptr = strtok_r(NULL, ",", &saveptr1))
|
|
|
|
|
{
|
|
|
|
|
if(!cs_malloc(&blocklen, sizeof(*blocklen)))
|
|
|
|
|
{ return; }
|
|
|
|
|
num = sscanf(ptr, "%hd%c%hd", &blocklen->min, &dash, &blocklen->max);
|
|
|
|
|
if(num <= 0)
|
|
|
|
|
{
|
|
|
|
|
NULLFREE(blocklen);
|
|
|
|
|
fprintf(stderr, "blockemm-bylen parse error: %s\n", value);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if(num == 1) // single values: x1, x2, x3, ...
|
|
|
|
|
{ blocklen->max = blocklen->min; }
|
|
|
|
|
else if(num == 2) // range values with open end: x1-
|
|
|
|
|
{ blocklen->max = 0; }
|
|
|
|
|
ll_append(rdr->blockemmbylen, blocklen);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
value = mk_t_emmbylen(rdr);
|
|
|
|
|
if(cs_strlen(value) > 0 || cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "%s\n", value); }
|
|
|
|
|
free_mk_t(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void nano_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
uint16_t *nano = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
*nano = 0;
|
|
|
|
|
if(cs_strlen(value) > 0)
|
|
|
|
|
{
|
|
|
|
|
if(streq(value, "all"))
|
|
|
|
|
{
|
|
|
|
|
*nano = 0xFFFF;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int32_t i;
|
|
|
|
|
char *ptr, *saveptr1 = NULL;
|
|
|
|
|
for(ptr = strtok_r(value, ",", &saveptr1); ptr; ptr = strtok_r(NULL, ",", &saveptr1))
|
|
|
|
|
{
|
|
|
|
|
i = (byte_atob(ptr) % 0x80);
|
|
|
|
|
if(i >= 0 && i <= 16)
|
|
|
|
|
{ *nano |= (1 << i); }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
value = mk_t_nano(*nano);
|
|
|
|
|
if(cs_strlen(value) > 0 || cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "%s\n", value); }
|
|
|
|
|
free_mk_t(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void auprovid_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
rdr->auprovid = 0;
|
|
|
|
|
if(cs_strlen(value))
|
|
|
|
|
{ rdr->auprovid = a2i(value, 3); }
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(rdr->auprovid)
|
|
|
|
|
{ fprintf_conf(f, token, "%06X\n", rdr->auprovid); }
|
|
|
|
|
else if(cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "\n"); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ratelimitecm_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
rdr->ratelimitecm = 0;
|
|
|
|
|
if(cs_strlen(value))
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
rdr->ratelimitecm = atoi(value);
|
|
|
|
|
for(i = 0; i < MAXECMRATELIMIT; i++) // reset all slots
|
|
|
|
|
{
|
|
|
|
|
rdr->rlecmh[i].srvid = -1;
|
|
|
|
|
rdr->rlecmh[i].last.time = -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(rdr->ratelimitecm || cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "%d\n", rdr->ratelimitecm); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ecmunique_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
if(cs_strlen(value) == 0)
|
|
|
|
|
{
|
|
|
|
|
rdr->ecmunique = 0; // default
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rdr->ecmunique = atoi(value);
|
|
|
|
|
if(rdr->ecmunique >= 1)
|
|
|
|
|
{ rdr->ecmunique = 1; }
|
|
|
|
|
else
|
|
|
|
|
{ rdr->ecmunique = 0; }
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if((rdr->ratelimitecm && rdr->ecmunique != 0) || cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "%d\n", rdr->ecmunique); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ratelimittime_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
if(cs_strlen(value) == 0)
|
|
|
|
|
{
|
|
|
|
|
if(rdr->ratelimitecm > 0)
|
|
|
|
|
{
|
|
|
|
|
rdr->ratelimittime = 9000; // default 9 seconds
|
|
|
|
|
rdr->srvidholdtime = 2000; // default 2 seconds hold
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rdr->ratelimitecm = 0; // in case someone set a negative value
|
|
|
|
|
rdr->ratelimittime = 0;
|
|
|
|
|
rdr->srvidholdtime = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rdr->ratelimittime = atoi(value);
|
|
|
|
|
if (rdr->ratelimittime < 60) rdr->ratelimittime *= 1000;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(rdr->ratelimitecm || cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "%d\n", rdr->ratelimittime); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void srvidholdtime_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
if(cs_strlen(value) == 0)
|
|
|
|
|
{
|
|
|
|
|
if(rdr->ratelimitecm > 0)
|
|
|
|
|
{
|
|
|
|
|
rdr->srvidholdtime = 2000; // default 2 seconds hold
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rdr->ratelimitecm = 0; // in case someone set a negative value
|
|
|
|
|
rdr->srvidholdtime = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rdr->srvidholdtime = atoi(value);
|
|
|
|
|
if (rdr->srvidholdtime < 60) rdr->srvidholdtime *=1000;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(rdr->ratelimitecm || cfg.http_full_cfg)
|
|
|
|
|
{ fprintf_conf(f, token, "%d\n", rdr->srvidholdtime); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cooldown_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
if(cs_strlen(value) == 0)
|
|
|
|
|
{
|
|
|
|
|
rdr->cooldown[0] = 0;
|
|
|
|
|
rdr->cooldown[1] = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int32_t i;
|
|
|
|
|
char *ptr, *saveptr1 = NULL;
|
|
|
|
|
for(i = 0, ptr = strtok_r(value, ",", &saveptr1); (i < 2) && (ptr); ptr = strtok_r(NULL, ",", &saveptr1), i++)
|
|
|
|
|
{
|
|
|
|
|
rdr->cooldown[i] = atoi(ptr);
|
|
|
|
|
}
|
|
|
|
|
if(rdr->cooldown[0] <= 0 || rdr->cooldown[1] <= 0)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "cooldown must have 2 positive values (x,y) set values %d,%d ! cooldown deactivated\n",
|
|
|
|
|
rdr->cooldown[0], rdr->cooldown[1]);
|
|
|
|
|
rdr->cooldown[0] = 0;
|
|
|
|
|
rdr->cooldown[1] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(rdr->cooldown[0] || cfg.http_full_cfg)
|
|
|
|
|
{
|
|
|
|
|
fprintf_conf(f, token, "%d,%d\n", rdr->cooldown[0], rdr->cooldown[1]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void parallelfactor_fn(const char *token, char *value, void *setting, FILE *f)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
if(cs_strlen(value) == 0)
|
|
|
|
|
{
|
|
|
|
|
rdr->parallelfactor = 1.5; // default
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Parse float manually to avoid locale issues (strtof uses locale decimal separator)
|
|
|
|
|
// Accept both '.' and ',' as decimal separator
|
|
|
|
|
char tmp[32];
|
|
|
|
|
cs_strncpy(tmp, value, sizeof(tmp));
|
|
|
|
|
|
|
|
|
|
// Find decimal separator (either . or ,)
|
|
|
|
|
char *sep = strchr(tmp, '.');
|
|
|
|
|
if(!sep) sep = strchr(tmp, ',');
|
|
|
|
|
|
|
|
|
|
if(sep)
|
|
|
|
|
{
|
|
|
|
|
*sep = '\0'; // Split at separator
|
|
|
|
|
int32_t integer_part = atoi(tmp);
|
|
|
|
|
int32_t decimal_part = atoi(sep + 1);
|
|
|
|
|
// Calculate decimal value (assuming 1 decimal place)
|
|
|
|
|
rdr->parallelfactor = (float)integer_part + (float)decimal_part / 10.0f;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rdr->parallelfactor = (float)atoi(tmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(rdr->parallelfactor < 0)
|
|
|
|
|
rdr->parallelfactor = 1.5; // default on negative
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// Write config: use comma as decimal separator
|
|
|
|
|
if(rdr->parallelfactor != 1.5 || cfg.http_full_cfg)
|
|
|
|
|
{
|
|
|
|
|
char buf[16];
|
|
|
|
|
snprintf(buf, sizeof(buf), "%.1f", rdr->parallelfactor);
|
|
|
|
|
char *dot = strchr(buf, '.');
|
|
|
|
|
if(dot) *dot = ',';
|
|
|
|
|
fprintf_conf(f, token, "%s\n", buf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cooldowndelay_fn(const char *UNUSED(token), char *value, void *setting, FILE *UNUSED(f))
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
rdr->cooldown[0] = cs_strlen(value) ? atoi(value) : 0;
|
|
|
|
|
}
|
|
|
|
|
// This option is *not* written in the config file.
|
|
|
|
|
// It is only set by WebIf as convenience
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cooldowntime_fn(const char *UNUSED(token), char *value, void *setting, FILE *UNUSED(f))
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = setting;
|
|
|
|
|
if(value)
|
|
|
|
|
{
|
|
|
|
|
if(cs_strlen(value) == 0)
|
|
|
|
|
{
|
|
|
|
|
rdr->cooldown[0] = 0; // no cooling down time means no cooling set
|
|
|
|
|
rdr->cooldown[1] = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rdr->cooldown[1] = atoi(value);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// This option is *not* written in the config file.
|
|
|
|
|
// It is only set by WebIf as convenience
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void reader_fixups_fn(void *var)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr = var;
|
|
|
|
|
#ifdef WITH_LB
|
|
|
|
|
if(rdr->lb_weight > 1000)
|
|
|
|
|
{ rdr->lb_weight = 1000; }
|
|
|
|
|
else if(rdr->lb_weight <= 0)
|
|
|
|
|
{ rdr->lb_weight = 100; }
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef CS_CACHEEX_AIO
|
|
|
|
|
caidtab2ftab_add(&rdr->cacheex.localgenerated_only_in_caidtab, &rdr->cacheex.lg_only_in_tab);
|
|
|
|
|
caidtab_clear(&rdr->cacheex.localgenerated_only_in_caidtab);
|
|
|
|
|
caidtab2ftab_add(&rdr->cacheex.localgenerated_only_caidtab, &rdr->cacheex.lg_only_tab);
|
|
|
|
|
caidtab_clear(&rdr->cacheex.localgenerated_only_caidtab);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if(is_cascading_reader(rdr) && (rdr->typ == R_CAMD35 || rdr->typ == R_CS378X))
|
|
|
|
|
{
|
|
|
|
|
#ifdef CS_CACHEEX
|
|
|
|
|
if(rdr && rdr->cacheex.mode>1)
|
|
|
|
|
{ rdr->keepalive = 1; } // with cacheex, it is required!
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
if(rdr->typ == R_CAMD35)
|
|
|
|
|
{ rdr->keepalive = 0; } // with NO-cacheex, and UDP, keepalive is not required!
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allocate/reallocate parallel_slots if maxparallel changed
|
|
|
|
|
// Two separate arrays: active slots (maxparallel) and pending slots (round(maxparallel * parallelfactor))
|
|
|
|
|
if(rdr->maxparallel > 0)
|
|
|
|
|
{
|
|
|
|
|
// Set default parallelfactor if negative (not configured)
|
|
|
|
|
// parallelfactor = 0 is valid (disables pending slots)
|
|
|
|
|
if(rdr->parallelfactor < 0)
|
|
|
|
|
rdr->parallelfactor = 1.5;
|
|
|
|
|
|
|
|
|
|
// Calculate pending slots size: round(maxparallel * parallelfactor) without math.h
|
|
|
|
|
// parallelfactor = 0 means no pending slots (zapping support disabled)
|
|
|
|
|
int32_t pending_size = (int32_t)(rdr->maxparallel * rdr->parallelfactor + 0.5);
|
|
|
|
|
|
|
|
|
|
// Only allocate if not yet allocated (first time setup)
|
|
|
|
|
// Size changes require OSCam restart to take effect
|
|
|
|
|
if(!rdr->parallel_slots)
|
|
|
|
|
{
|
|
|
|
|
if(!cs_malloc(&rdr->parallel_slots, rdr->maxparallel * sizeof(struct s_parallel_slot)))
|
|
|
|
|
{ rdr->maxparallel = 0; } // disable on allocation failure
|
|
|
|
|
else if(pending_size > 0 && !cs_malloc(&rdr->parallel_slots_prov, pending_size * sizeof(struct s_parallel_slot)))
|
|
|
|
|
{
|
|
|
|
|
NULLFREE(rdr->parallel_slots); // free first array on second failure
|
|
|
|
|
rdr->maxparallel = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cs_lock_create(__func__, &rdr->parallel_lock, "parallel_lock", 5000);
|
|
|
|
|
rdr->blocked_services = ll_create("blocked_services");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rdr->parallel_full = 0; // reset full flag
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(rdr->parallel_slots || rdr->parallel_slots_prov)
|
|
|
|
|
{
|
|
|
|
|
// maxparallel was disabled, free the slots
|
|
|
|
|
NULLFREE(rdr->parallel_slots);
|
|
|
|
|
NULLFREE(rdr->parallel_slots_prov);
|
|
|
|
|
ll_destroy_data(&rdr->blocked_services);
|
|
|
|
|
rdr->parallel_full = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define OFS(X) offsetof(struct s_reader, X)
|
|
|
|
|
#define SIZEOF(X) sizeof(((struct s_reader *)0)->X)
|
|
|
|
|
|
|
|
|
|
static const struct config_list reader_opts[] =
|
|
|
|
|
{
|
|
|
|
|
DEF_OPT_FIXUP_FUNC(reader_fixups_fn),
|
|
|
|
|
DEF_OPT_FUNC("label" , 0, reader_label_fn),
|
|
|
|
|
#ifdef WEBIF
|
|
|
|
|
DEF_OPT_STR("description" , OFS(description), NULL),
|
|
|
|
|
#endif
|
|
|
|
|
DEF_OPT_INT8("enable" , OFS(enable), 1),
|
|
|
|
|
DEF_OPT_FUNC("protocol" , 0, protocol_fn),
|
|
|
|
|
DEF_OPT_FUNC("device" , 0, device_fn),
|
|
|
|
|
DEF_OPT_UINT8("ipv4force" , OFS(ipv4force), 0),
|
|
|
|
|
DEF_OPT_HEX("key" , OFS(ncd_key), SIZEOF(ncd_key)),
|
|
|
|
|
DEF_OPT_SSTR("user" , OFS(r_usr), "", SIZEOF(r_usr)),
|
|
|
|
|
DEF_OPT_SSTR("password" , OFS(r_pwd), "", SIZEOF(r_pwd)),
|
|
|
|
|
DEF_OPT_SSTR("pincode" , OFS(pincode), "none", SIZEOF(pincode)),
|
|
|
|
|
#ifdef MODULE_GBOX
|
|
|
|
|
DEF_OPT_UINT8("gbox_max_distance" , OFS(gbox_maxdist), DEFAULT_GBOX_MAX_DIST),
|
|
|
|
|
DEF_OPT_UINT8("gbox_max_ecm_send" , OFS(gbox_maxecmsend), DEFAULT_GBOX_MAX_ECM_SEND),
|
|
|
|
|
DEF_OPT_UINT8("gbox_reshare" , OFS(gbox_reshare), DEFAULT_GBOX_RESHARE),
|
|
|
|
|
DEF_OPT_INT8("cccam_reshare" , OFS(gbox_cccam_reshare), -1),
|
|
|
|
|
DEF_OPT_UINT8("force_remm" , OFS(gbox_force_remm), 0),
|
|
|
|
|
DEF_OPT_FUNC_X("ccc_gbx_reshare_ident" , OFS(ccc_gbx_reshare_ident), ftab_fn, FTAB_READER | FTAB_CCCGBXRESHARE),
|
|
|
|
|
DEF_OPT_UINT8("send_offline_cmd" , OFS(send_offline_cmd), 0),
|
|
|
|
|
#endif
|
|
|
|
|
DEF_OPT_STR("readnano" , OFS(emmfile), NULL),
|
|
|
|
|
DEF_OPT_FUNC("services" , OFS(sidtabs), reader_services_fn),
|
|
|
|
|
DEF_OPT_FUNC("lb_whitelist_services" , OFS(lb_sidtabs), reader_lb_services_fn),
|
|
|
|
|
DEF_OPT_INT32("inactivitytimeout" , OFS(tcp_ito), DEFAULT_INACTIVITYTIMEOUT),
|
|
|
|
|
DEF_OPT_INT32("reconnecttimeout" , OFS(tcp_rto), DEFAULT_TCP_RECONNECT_TIMEOUT),
|
|
|
|
|
DEF_OPT_INT32("reconnectdelay" , OFS(tcp_reconnect_delay), 60000),
|
|
|
|
|
DEF_OPT_INT32("resetcycle" , OFS(resetcycle), 0),
|
|
|
|
|
DEF_OPT_INT8("disableserverfilter" , OFS(ncd_disable_server_filt), 0),
|
|
|
|
|
DEF_OPT_INT8("connectoninit" , OFS(ncd_connect_on_init), 0),
|
|
|
|
|
DEF_OPT_UINT8("keepalive" , OFS(keepalive), 0),
|
|
|
|
|
#ifdef WITH_CARDREADER
|
|
|
|
|
DEF_OPT_INT8("smargopatch" , OFS(smargopatch), 0),
|
|
|
|
|
DEF_OPT_INT8("autospeed" , OFS(autospeed), 1),
|
|
|
|
|
DEF_OPT_UINT8("sc8in1_dtrrts_patch" , OFS(sc8in1_dtrrts_patch), 0),
|
|
|
|
|
#endif
|
|
|
|
|
DEF_OPT_INT8("fallback" , OFS(fallback), 0),
|
|
|
|
|
DEF_OPT_FUNC_X("fallback_percaid" , OFS(fallback_percaid), ftab_fn, FTAB_READER | FTAB_FBPCAID),
|
|
|
|
|
DEF_OPT_FUNC_X("localcards" , OFS(localcards), ftab_fn, FTAB_READER | FTAB_LOCALCARDS),
|
|
|
|
|
DEF_OPT_FUNC_X("disablecrccws_only_for" , OFS(disablecrccws_only_for), ftab_fn, FTAB_READER | FTAB_IGNCHKSMCAID),
|
|
|
|
|
#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),
|
2026-02-17 09:41:05 +00:00
|
|
|
#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),
|
2026-02-16 09:02:48 +00:00
|
|
|
#endif
|
|
|
|
|
DEF_OPT_FUNC("cacheex_ecm_filter" , OFS(cacheex.filter_caidtab), cacheex_hitvaluetab_fn),
|
|
|
|
|
DEF_OPT_UINT8("cacheex_allow_request" , OFS(cacheex.allow_request), 0),
|
|
|
|
|
DEF_OPT_UINT8("cacheex_drop_csp" , OFS(cacheex.drop_csp), 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),
|
|
|
|
|
#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, FTAB_ACCOUNT),
|
|
|
|
|
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, FTAB_ACCOUNT),
|
|
|
|
|
DEF_OPT_FUNC("cacheex_nopushafter" , OFS(cacheex.cacheex_nopushafter_tab), caidvaluetab_fn),
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
DEF_OPT_FUNC("caid" , OFS(ctab), reader_caid_fn),
|
|
|
|
|
#ifdef WITH_CARDREADER
|
|
|
|
|
DEF_OPT_FUNC("atr" , 0, atr_fn),
|
|
|
|
|
DEF_OPT_FUNC("boxid" , 0, boxid_fn),
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef READER_TONGFANG
|
|
|
|
|
DEF_OPT_FUNC("tongfang3_calibsn" , 0, tongfang3_calibsn_fn),
|
|
|
|
|
DEF_OPT_FUNC("tongfang_boxid" , 0, tongfang_boxid_fn),
|
|
|
|
|
DEF_OPT_FUNC("stbid" , 0, stbid_fn),
|
|
|
|
|
DEF_OPT_FUNC("tongfang3_deskey" , 0, tongfang3_deskey_fn),
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef WITH_CARDREADER
|
|
|
|
|
DEF_OPT_FUNC("boxkey" , 0, boxkey_fn),
|
|
|
|
|
DEF_OPT_FUNC("rsakey" , 0, rsakey_fn),
|
|
|
|
|
DEF_OPT_FUNC("cwpkkey" , 0, cwpkkey_fn),
|
|
|
|
|
DEF_OPT_FUNC("deskey" , 0, deskey_fn),
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef READER_NAGRA_MERLIN
|
|
|
|
|
DEF_OPT_FUNC_X("mod1" , OFS(mod1), param_fn, SIZEOF(mod1) ^ (OFS(mod1_length) - OFS(mod1)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("idird" , OFS(idird), param_fn, SIZEOF(idird) ^ (OFS(idird_length) - OFS(idird)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cmd0eprov" , OFS(cmd0eprov), param_fn, SIZEOF(cmd0eprov) ^ (OFS(cmd0eprov_length) - OFS(cmd0eprov)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("mod2" , OFS(mod2), param_fn, SIZEOF(mod2) ^ (OFS(mod2_length) - OFS(mod2)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("key3588" , OFS(key3588), param_fn, SIZEOF(key3588) ^ (OFS(key3588_length) - OFS(key3588)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("key3460" , OFS(key3460), param_fn, SIZEOF(key3460) ^ (OFS(key3460_length) - OFS(key3460)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("key3310" , OFS(key3310), param_fn, SIZEOF(key3310) ^ (OFS(key3310_length) - OFS(key3310)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("data50" , OFS(data50), param_fn, SIZEOF(data50) ^ (OFS(data50_length) - OFS(data50)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("mod50" , OFS(mod50), param_fn, SIZEOF(mod50) ^ (OFS(mod50_length) - OFS(mod50)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("nuid" , OFS(nuid), param_fn, SIZEOF(nuid) ^ (OFS(nuid_length) - OFS(nuid)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("forcepair" , OFS(forcepair), param_fn, SIZEOF(forcepair) ^ (OFS(forcepair_length) - OFS(forcepair)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("otpcsc" , OFS(otpcsc), param_fn, SIZEOF(otpcsc) ^ (OFS(otpcsc_length) - OFS(otpcsc)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("otacsc" , OFS(otacsc), param_fn, SIZEOF(otacsc) ^ (OFS(otacsc_length) - OFS(otacsc)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwpkcaid" , OFS(cwpkcaid), param_fn, SIZEOF(cwpkcaid) ^ (OFS(cwpkcaid_length) - OFS(cwpkcaid)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey0" , OFS(cwekey[0]), param_fn, SIZEOF(cwekey[0]) ^ (OFS(cwekey_length[0]) - OFS(cwekey[0])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey1" , OFS(cwekey[1]), param_fn, SIZEOF(cwekey[1]) ^ (OFS(cwekey_length[1]) - OFS(cwekey[1])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey2" , OFS(cwekey[2]), param_fn, SIZEOF(cwekey[2]) ^ (OFS(cwekey_length[2]) - OFS(cwekey[2])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey3" , OFS(cwekey[3]), param_fn, SIZEOF(cwekey[3]) ^ (OFS(cwekey_length[3]) - OFS(cwekey[3])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey4" , OFS(cwekey[4]), param_fn, SIZEOF(cwekey[4]) ^ (OFS(cwekey_length[4]) - OFS(cwekey[4])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey5" , OFS(cwekey[5]), param_fn, SIZEOF(cwekey[5]) ^ (OFS(cwekey_length[5]) - OFS(cwekey[5])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey6" , OFS(cwekey[6]), param_fn, SIZEOF(cwekey[6]) ^ (OFS(cwekey_length[6]) - OFS(cwekey[6])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey7" , OFS(cwekey[7]), param_fn, SIZEOF(cwekey[7]) ^ (OFS(cwekey_length[7]) - OFS(cwekey[7])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey8" , OFS(cwekey[8]), param_fn, SIZEOF(cwekey[8]) ^ (OFS(cwekey_length[8]) - OFS(cwekey[8])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey9" , OFS(cwekey[9]), param_fn, SIZEOF(cwekey[9]) ^ (OFS(cwekey_length[9]) - OFS(cwekey[9])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey10" , OFS(cwekey[10]), param_fn, SIZEOF(cwekey[10]) ^ (OFS(cwekey_length[10]) - OFS(cwekey[10])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey11" , OFS(cwekey[11]), param_fn, SIZEOF(cwekey[11]) ^ (OFS(cwekey_length[11]) - OFS(cwekey[11])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey12" , OFS(cwekey[12]), param_fn, SIZEOF(cwekey[12]) ^ (OFS(cwekey_length[12]) - OFS(cwekey[12])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey13" , OFS(cwekey[13]), param_fn, SIZEOF(cwekey[13]) ^ (OFS(cwekey_length[13]) - OFS(cwekey[13])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey14" , OFS(cwekey[14]), param_fn, SIZEOF(cwekey[14]) ^ (OFS(cwekey_length[14]) - OFS(cwekey[14])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey15" , OFS(cwekey[15]), param_fn, SIZEOF(cwekey[15]) ^ (OFS(cwekey_length[15]) - OFS(cwekey[15])) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cwekey16" , OFS(cwekey[16]), param_fn, SIZEOF(cwekey[16]) ^ (OFS(cwekey_length[16]) - OFS(cwekey[16])) << 8),
|
|
|
|
|
DEF_OPT_INT8("forcecwswap" , OFS(forcecwswap), 0),
|
|
|
|
|
DEF_OPT_INT8("evensa" , OFS(evensa), 0),
|
|
|
|
|
DEF_OPT_INT8("forceemmg" , OFS(forceemmg), 0),
|
|
|
|
|
DEF_OPT_INT8("cwpkota" , OFS(cwpkota), 0),
|
|
|
|
|
DEF_OPT_INT8("headermode" , OFS(headermode), 1),
|
|
|
|
|
DEF_OPT_INT8("cak7_mode" , OFS(cak7_mode), 0),
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(READER_NAGRA)
|
|
|
|
|
DEF_OPT_FUNC_X("cak63nuid" , OFS(cak63nuid), param_fn, SIZEOF(cak63nuid) ^ (OFS(cak63nuid_length) - OFS(cak63nuid)) << 8),
|
|
|
|
|
DEF_OPT_FUNC_X("cak63cwekey" , OFS(cak63cwekey), param_fn, SIZEOF(cak63cwekey) ^ (OFS(cak63cwekey_length) - OFS(cak63cwekey)) << 8),
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(READER_VIDEOGUARD)
|
|
|
|
|
DEF_OPT_INT8("ndsversion" , OFS(ndsversion), 0),
|
|
|
|
|
DEF_OPT_INT32("card_startdate_basemonth" , OFS(card_startdate_basemonth), 1),
|
|
|
|
|
DEF_OPT_INT32("card_startdate_baseyear" , OFS(card_startdate_baseyear), 1997),
|
|
|
|
|
DEF_OPT_INT32("card_expiredate_basemonth" , OFS(card_expiredate_basemonth), 1),
|
|
|
|
|
DEF_OPT_INT32("card_expiredate_baseyear" , OFS(card_expiredate_baseyear), 1997),
|
|
|
|
|
DEF_OPT_FUNC_X("ins7e" , OFS(ins7E), ins7E_fn, SIZEOF(ins7E)),
|
|
|
|
|
DEF_OPT_FUNC_X("ins42" , OFS(ins42), ins42_fn, SIZEOF(ins42)),
|
|
|
|
|
DEF_OPT_FUNC_X("ins7e11" , OFS(ins7E11), ins7E_fn, SIZEOF(ins7E11)),
|
|
|
|
|
DEF_OPT_FUNC_X("ins2e06" , OFS(ins2e06), ins7E_fn, SIZEOF(ins2e06)),
|
|
|
|
|
DEF_OPT_FUNC("k1_generic" , OFS(k1_generic), des_and_3des_key_fn),
|
|
|
|
|
DEF_OPT_FUNC("k1_unique" , OFS(k1_unique), des_and_3des_key_fn),
|
|
|
|
|
DEF_OPT_INT8("fix07" , OFS(fix_07), 1),
|
|
|
|
|
DEF_OPT_INT8("fix9993" , OFS(fix_9993), 0),
|
|
|
|
|
DEF_OPT_INT8("readtiers" , OFS(readtiers), 1),
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef READER_IRDETO
|
|
|
|
|
DEF_OPT_INT8("force_irdeto" , OFS(force_irdeto), 0),
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef READER_CRYPTOWORKS
|
|
|
|
|
DEF_OPT_INT8("needsglobalfirst" , OFS(needsglobalfirst), 0),
|
|
|
|
|
#endif
|
|
|
|
|
DEF_OPT_UINT32("ecmnotfoundlimit" , OFS(ecmnotfoundlimit), 0),
|
|
|
|
|
DEF_OPT_FUNC("ecmwhitelist" , 0, ecmwhitelist_fn),
|
|
|
|
|
DEF_OPT_FUNC("ecmheaderwhitelist" , 0, ecmheaderwhitelist_fn),
|
|
|
|
|
#ifdef WITH_CARDREADER
|
|
|
|
|
DEF_OPT_FUNC("detect" , 0, detect_fn),
|
|
|
|
|
#ifdef READER_NAGRA
|
|
|
|
|
DEF_OPT_INT8("nagra_read" , OFS(nagra_read), 0),
|
|
|
|
|
DEF_OPT_INT8("detect_seca_nagra_tunneled_card", OFS(detect_seca_nagra_tunneled_card), 1),
|
|
|
|
|
#endif
|
|
|
|
|
DEF_OPT_INT32("mhz" , OFS(mhz), 357),
|
|
|
|
|
DEF_OPT_INT32("cardmhz" , OFS(cardmhz), 357),
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef WITH_AZBOX
|
|
|
|
|
DEF_OPT_INT32("mode" , OFS(azbox_mode), -1),
|
|
|
|
|
#endif
|
|
|
|
|
DEF_OPT_FUNC_X("ident" , OFS(ftab), ftab_fn, FTAB_READER | FTAB_PROVID),
|
|
|
|
|
DEF_OPT_FUNC_X("chid" , OFS(fchid), ftab_fn, FTAB_READER | FTAB_CHID),
|
|
|
|
|
DEF_OPT_FUNC("class" , OFS(cltab), class_fn),
|
|
|
|
|
#ifdef READER_VIACCESS
|
|
|
|
|
DEF_OPT_FUNC("aeskeys" , 0, aeskeys_fn),
|
|
|
|
|
#endif
|
|
|
|
|
DEF_OPT_FUNC("group" , OFS(grp), group_fn),
|
|
|
|
|
DEF_OPT_FUNC("emmcache" , 0, emmcache_fn),
|
|
|
|
|
DEF_OPT_FUNC_X("blockemm-unknown" , OFS(blockemm), flags_fn, EMM_UNKNOWN),
|
|
|
|
|
DEF_OPT_FUNC_X("blockemm-u" , OFS(blockemm), flags_fn, EMM_UNIQUE),
|
|
|
|
|
DEF_OPT_FUNC_X("blockemm-s" , OFS(blockemm), flags_fn, EMM_SHARED),
|
|
|
|
|
DEF_OPT_FUNC_X("blockemm-g" , OFS(blockemm), flags_fn, EMM_GLOBAL),
|
|
|
|
|
DEF_OPT_FUNC_X("saveemm-unknown" , OFS(saveemm), flags_fn, EMM_UNKNOWN),
|
|
|
|
|
DEF_OPT_FUNC_X("saveemm-u" , OFS(saveemm), flags_fn, EMM_UNIQUE),
|
|
|
|
|
DEF_OPT_FUNC_X("saveemm-s" , OFS(saveemm), flags_fn, EMM_SHARED),
|
|
|
|
|
DEF_OPT_FUNC_X("saveemm-g" , OFS(saveemm), flags_fn, EMM_GLOBAL),
|
|
|
|
|
DEF_OPT_FUNC("blockemm-bylen" , 0, blockemm_bylen_fn),
|
|
|
|
|
#ifdef WITH_LB
|
|
|
|
|
DEF_OPT_INT32("lb_weight" , OFS(lb_weight), 100),
|
|
|
|
|
DEF_OPT_INT8("lb_force_fallback" , OFS(lb_force_fallback), 0),
|
|
|
|
|
#endif
|
|
|
|
|
DEF_OPT_FUNC("savenano" , OFS(s_nano), nano_fn),
|
|
|
|
|
DEF_OPT_FUNC("blocknano" , OFS(b_nano), nano_fn),
|
|
|
|
|
DEF_OPT_INT8("dropbadcws" , OFS(dropbadcws), 0),
|
|
|
|
|
DEF_OPT_INT8("disablecrccws" , OFS(disablecrccws), 0),
|
|
|
|
|
#ifdef WITH_CARDREADER
|
|
|
|
|
DEF_OPT_INT32("use_gpio" , OFS(use_gpio), 0),
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef MODULE_PANDORA
|
|
|
|
|
DEF_OPT_UINT8("pand_send_ecm" , OFS(pand_send_ecm), 0),
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef MODULE_CCCAM
|
|
|
|
|
DEF_OPT_SSTR("cccversion" , OFS(cc_version), "", SIZEOF(cc_version)),
|
|
|
|
|
DEF_OPT_INT8("cccmaxhops" , OFS(cc_maxhops), DEFAULT_CC_MAXHOPS),
|
|
|
|
|
DEF_OPT_INT8("cccmindown" , OFS(cc_mindown), 0),
|
|
|
|
|
DEF_OPT_INT8("cccwantemu" , OFS(cc_want_emu), 0),
|
|
|
|
|
DEF_OPT_INT8("ccckeepalive" , OFS(cc_keepalive), DEFAULT_CC_KEEPALIVE),
|
|
|
|
|
DEF_OPT_INT8("cccreshare" , OFS(cc_reshare), DEFAULT_CC_RESHARE),
|
|
|
|
|
DEF_OPT_INT32("cccreconnect" , OFS(cc_reconnect), DEFAULT_CC_RECONNECT),
|
|
|
|
|
DEF_OPT_INT8("ccchop" , OFS(cc_hop), 0),
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef MODULE_GHTTP
|
|
|
|
|
DEF_OPT_UINT8("use_ssl" , OFS(ghttp_use_ssl), 0),
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(READER_DRE) || defined(READER_DRECAS)
|
|
|
|
|
DEF_OPT_HEX("force_ua" , OFS(force_ua), 4),
|
|
|
|
|
DEF_OPT_STR("exec_cmd_file" , OFS(userscript), NULL),
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef READER_DRECAS
|
|
|
|
|
DEF_OPT_STR("stmkeys" , OFS(stmkeys), NULL),
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef WITH_EMU
|
|
|
|
|
DEF_OPT_FUNC_X("emu_auproviders" , OFS(emu_auproviders), ftab_fn, FTAB_READER | FTAB_EMUAU),
|
|
|
|
|
DEF_OPT_INT8("emu_datecodedenabled" , OFS(emu_datecodedenabled), 0),
|
|
|
|
|
#endif
|
|
|
|
|
DEF_OPT_INT8("resetalways" , OFS(resetalways), 0),
|
|
|
|
|
#ifdef WITH_CARDREADER
|
|
|
|
|
DEF_OPT_INT8("deprecated" , OFS(deprecated), 0),
|
|
|
|
|
#endif
|
|
|
|
|
DEF_OPT_INT8("audisabled" , OFS(audisabled), 0),
|
|
|
|
|
DEF_OPT_FUNC("auprovid" , 0, auprovid_fn),
|
|
|
|
|
DEF_OPT_FUNC("ratelimitecm" , 0, ratelimitecm_fn),
|
|
|
|
|
DEF_OPT_FUNC("ecmunique" , 0, ecmunique_fn),
|
|
|
|
|
DEF_OPT_FUNC("ratelimittime" , 0, ratelimittime_fn),
|
|
|
|
|
DEF_OPT_FUNC("srvidholdtime" , 0, srvidholdtime_fn),
|
|
|
|
|
DEF_OPT_FUNC("cooldown" , 0, cooldown_fn),
|
|
|
|
|
DEF_OPT_INT32("maxparallel" , OFS(maxparallel), 0),
|
|
|
|
|
DEF_OPT_FUNC("parallelfactor" , 0, parallelfactor_fn),
|
|
|
|
|
DEF_OPT_INT32("paralleltimeout" , OFS(paralleltimeout), 1000),
|
|
|
|
|
DEF_OPT_FUNC("cooldowndelay" , 0, cooldowndelay_fn),
|
|
|
|
|
DEF_OPT_FUNC("cooldowntime" , 0, cooldowntime_fn),
|
|
|
|
|
#ifdef READER_VIACCESS
|
|
|
|
|
DEF_OPT_UINT8("read_old_classes" , OFS(read_old_classes), 1),
|
|
|
|
|
#endif
|
|
|
|
|
DEF_LAST_OPT
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static inline bool in_list(const char *token, const char *list[])
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for(i = 0; list[i]; i++)
|
|
|
|
|
{
|
|
|
|
|
if(streq(token, list[i]))
|
|
|
|
|
{ return true; }
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool reader_check_setting(const struct config_list *UNUSED(clist), void *config_data, const char *setting)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *reader = config_data;
|
|
|
|
|
// These are written only when the reader is physical reader
|
|
|
|
|
static const char *hw_only_settings[] =
|
|
|
|
|
{
|
|
|
|
|
"readnano", "resetcycle", "smargopatch", "autospeed", "sc8in1_dtrrts_patch", "boxid","fix07",
|
|
|
|
|
"fix9993", "rsakey", "deskey", "card_startdate_basemonth", "card_startdate_baseyear", "card_expiredate_basemonth", "card_expiredate_baseyear", "ins7e", "ins42", "ins7e11", "ins2e06", "k1_generic", "k1_unique", "force_irdeto", "boxkey",
|
|
|
|
|
"atr", "detect", "nagra_read", "mhz", "cardmhz", "readtiers", "read_old_classes", "use_gpio", "needsglobalfirst",
|
|
|
|
|
#ifdef READER_NAGRA_MERLIN
|
|
|
|
|
"mod1", "idird", "cmd0eprov", "mod2", "key3588", "key3460", "key3310", "data50", "mod50", "nuid", "forcepair", "otpcsc", "otacsc", "cwpkcaid", "headermode", "cwekey0", "cwekey1", "cwekey2", "cwekey3", "cwekey4", "cwekey5", "cwekey6", "cwekey7", "cwekey8", "cwekey9", "cwekey10", "cwekey11", "cwekey12", "cwekey13", "cwekey14", "cwekey15", "cwekey16",
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(READER_NAGRA)
|
|
|
|
|
"cak63nuid", "cak63cwekey",
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(READER_DRE) || defined(READER_DRECAS)
|
|
|
|
|
"exec_cmd_file",
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef READER_CONAX
|
|
|
|
|
"cwpkkey",
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(READER_TONGFANG)
|
|
|
|
|
"tongfang3_deskey", "tongfang3_calibsn", "stbid", "tongfang_boxid",
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef WITH_AZBOX
|
|
|
|
|
"mode",
|
|
|
|
|
#endif
|
|
|
|
|
"resetalways", "deprecated", "ndsversion",
|
|
|
|
|
0
|
|
|
|
|
};
|
|
|
|
|
// These are written only when the reader is network reader
|
|
|
|
|
static const char *network_only_settings[] =
|
|
|
|
|
{
|
|
|
|
|
"user", "inactivitytimeout", "reconnecttimeout",
|
|
|
|
|
0
|
|
|
|
|
};
|
|
|
|
|
if(is_network_reader(reader))
|
|
|
|
|
{
|
|
|
|
|
if(in_list(setting, hw_only_settings))
|
|
|
|
|
{ return false; }
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(in_list(setting, network_only_settings))
|
|
|
|
|
{ return false; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// These are not written in the config file
|
|
|
|
|
static const char *deprecated_settings[] =
|
|
|
|
|
{
|
|
|
|
|
"cooldowndelay", "cooldowntime",
|
|
|
|
|
0
|
|
|
|
|
};
|
|
|
|
|
if(in_list(setting, deprecated_settings))
|
|
|
|
|
{ return false; }
|
|
|
|
|
|
|
|
|
|
// Special settings for NEWCAMD
|
|
|
|
|
static const char *newcamd_settings[] =
|
|
|
|
|
{
|
|
|
|
|
"disableserverfilter", "connectoninit",
|
|
|
|
|
0
|
|
|
|
|
};
|
|
|
|
|
if(reader->typ != R_NEWCAMD && in_list(setting, newcamd_settings))
|
|
|
|
|
{ return false; }
|
|
|
|
|
#ifdef MODULE_CCCAM
|
|
|
|
|
// These are written only when the reader is CCCAM
|
|
|
|
|
static const char *cccam_settings[] =
|
|
|
|
|
{
|
|
|
|
|
"cccversion", "cccmaxhops", "cccmindown", "cccwantemu", "ccckeepalive",
|
|
|
|
|
"cccreconnect",
|
|
|
|
|
0
|
|
|
|
|
};
|
|
|
|
|
// Special settings for CCCAM
|
|
|
|
|
if(reader->typ != R_CCCAM)
|
|
|
|
|
{
|
|
|
|
|
if(in_list(setting, cccam_settings))
|
|
|
|
|
{ return false; }
|
|
|
|
|
}
|
|
|
|
|
else if(streq(setting, "ccchop"))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef MODULE_PANDORA
|
|
|
|
|
// Special settings for PANDORA
|
|
|
|
|
if(reader->typ != R_PANDORA && streq(setting, "pand_send_ecm"))
|
|
|
|
|
{ return false; }
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef MODULE_GBOX
|
|
|
|
|
// These are written only when the reader is GBOX
|
|
|
|
|
static const char *gbox_settings[] =
|
|
|
|
|
{
|
|
|
|
|
"gbox_max_distance", "gbox_max_ecm_send", "gbox_reshare", "cccam_reshare", "force_remm","ccc_gbx_reshare_ident","send_offline_cmd",
|
|
|
|
|
0
|
|
|
|
|
};
|
|
|
|
|
if(reader->typ != R_GBOX)
|
|
|
|
|
{
|
|
|
|
|
if(in_list(setting, gbox_settings))
|
|
|
|
|
{ return false; }
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return true; // Write the setting
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void chk_reader(char *token, char *value, struct s_reader *rdr)
|
|
|
|
|
{
|
|
|
|
|
if(config_list_parse(reader_opts, token, value, rdr))
|
|
|
|
|
{ return; }
|
|
|
|
|
else if(token[0] != '#')
|
|
|
|
|
{ fprintf(stderr, "Warning: keyword '%s' in reader section not recognized\n", token); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void reader_set_defaults(struct s_reader *rdr)
|
|
|
|
|
{
|
|
|
|
|
config_list_set_defaults(reader_opts, rdr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t init_readerdb(void)
|
|
|
|
|
{
|
|
|
|
|
configured_readers = ll_create("configured_readers");
|
|
|
|
|
|
|
|
|
|
FILE *fp = open_config_file(cs_srvr);
|
|
|
|
|
if(!fp)
|
|
|
|
|
{ return 1; }
|
|
|
|
|
|
|
|
|
|
int32_t tag = 0;
|
|
|
|
|
char *value, *token;
|
|
|
|
|
|
|
|
|
|
if(!cs_malloc(&token, MAXLINESIZE))
|
|
|
|
|
{ return 1; }
|
|
|
|
|
|
|
|
|
|
struct s_reader *rdr;
|
|
|
|
|
if(!cs_malloc(&rdr, sizeof(struct s_reader)))
|
|
|
|
|
{
|
|
|
|
|
NULLFREE(token);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ll_append(configured_readers, rdr);
|
|
|
|
|
while(fgets(token, MAXLINESIZE, fp))
|
|
|
|
|
{
|
|
|
|
|
int32_t l;
|
|
|
|
|
if((l = cs_strlen(trim(token))) < 3)
|
|
|
|
|
{ continue; }
|
|
|
|
|
if((token[0] == '[') && (token[l - 1] == ']'))
|
|
|
|
|
{
|
|
|
|
|
token[l - 1] = 0;
|
|
|
|
|
tag = (!strcmp("reader", strtolower(token + 1)));
|
|
|
|
|
if(rdr->label[0] && rdr->typ)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *newreader;
|
|
|
|
|
if(cs_malloc(&newreader, sizeof(struct s_reader)))
|
|
|
|
|
{
|
|
|
|
|
ll_append(configured_readers, newreader);
|
|
|
|
|
rdr = newreader;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
reader_set_defaults(rdr);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!tag)
|
|
|
|
|
{ continue; }
|
|
|
|
|
if(!(value = strchr(token, '=')))
|
|
|
|
|
{ continue; }
|
|
|
|
|
*value++ = '\0';
|
|
|
|
|
chk_reader(trim(strtolower(token)), trim(value), rdr);
|
|
|
|
|
}
|
|
|
|
|
NULLFREE(token);
|
|
|
|
|
LL_ITER itr = ll_iter_create(configured_readers);
|
|
|
|
|
while((rdr = ll_iter_next(&itr))) // build active readers list
|
|
|
|
|
{
|
|
|
|
|
reader_fixups_fn(rdr);
|
|
|
|
|
module_reader_set(rdr);
|
|
|
|
|
}
|
|
|
|
|
fclose(fp);
|
|
|
|
|
return (0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void free_reader(struct s_reader *rdr)
|
|
|
|
|
{
|
|
|
|
|
NULLFREE(rdr->emmfile);
|
|
|
|
|
if(rdr->parallel_slots || rdr->parallel_slots_prov)
|
|
|
|
|
{ cs_lock_destroy(__func__, &rdr->parallel_lock); }
|
|
|
|
|
NULLFREE(rdr->parallel_slots);
|
|
|
|
|
NULLFREE(rdr->parallel_slots_prov);
|
|
|
|
|
ll_destroy_data(&rdr->blocked_services);
|
|
|
|
|
|
|
|
|
|
ecm_whitelist_clear(&rdr->ecm_whitelist);
|
|
|
|
|
ecm_hdr_whitelist_clear(&rdr->ecm_hdr_whitelist);
|
|
|
|
|
|
|
|
|
|
ftab_clear(&rdr->fallback_percaid);
|
|
|
|
|
ftab_clear(&rdr->localcards);
|
|
|
|
|
ftab_clear(&rdr->fchid);
|
|
|
|
|
ftab_clear(&rdr->ftab);
|
|
|
|
|
ftab_clear(&rdr->disablecrccws_only_for);
|
|
|
|
|
#ifdef MODULE_GBOX
|
|
|
|
|
ftab_clear(&rdr->ccc_gbx_reshare_ident);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
NULLFREE(rdr->cltab.aclass);
|
|
|
|
|
NULLFREE(rdr->cltab.bclass);
|
|
|
|
|
|
|
|
|
|
caidtab_clear(&rdr->ctab);
|
|
|
|
|
#ifdef CS_CACHEEX
|
|
|
|
|
cecspvaluetab_clear(&rdr->cacheex.filter_caidtab);
|
|
|
|
|
#ifdef CS_CACHEEX_AIO
|
|
|
|
|
caidtab_clear(&rdr->cacheex.localgenerated_only_caidtab);
|
|
|
|
|
caidtab_clear(&rdr->cacheex.localgenerated_only_in_caidtab);
|
|
|
|
|
ftab_clear(&rdr->cacheex.lg_only_tab);
|
|
|
|
|
ftab_clear(&rdr->cacheex.lg_only_in_tab);
|
|
|
|
|
caidvaluetab_clear(&rdr->cacheex.cacheex_nopushafter_tab);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
lb_destroy_stats(rdr);
|
|
|
|
|
|
|
|
|
|
cs_clear_entitlement(rdr);
|
|
|
|
|
ll_destroy(&rdr->ll_entitlements);
|
|
|
|
|
|
|
|
|
|
if(rdr->csystem && rdr->csystem->card_done)
|
|
|
|
|
rdr->csystem->card_done(rdr);
|
|
|
|
|
NULLFREE(rdr->csystem_data);
|
|
|
|
|
|
|
|
|
|
ll_destroy_data(&rdr->blockemmbylen);
|
|
|
|
|
|
|
|
|
|
ll_destroy_data(&rdr->emmstat);
|
|
|
|
|
#ifdef READER_VIACCESS
|
|
|
|
|
aes_clear_entries(&rdr->aes_list);
|
|
|
|
|
#endif
|
|
|
|
|
config_list_gc_values(reader_opts, rdr);
|
|
|
|
|
add_garbage(rdr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t free_readerdb(void)
|
|
|
|
|
{
|
|
|
|
|
int count = 0;
|
|
|
|
|
struct s_reader *rdr;
|
|
|
|
|
LL_ITER itr = ll_iter_create(configured_readers);
|
|
|
|
|
while((rdr = ll_iter_next(&itr)))
|
|
|
|
|
{
|
|
|
|
|
free_reader(rdr);
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
cs_log("readerdb %d readers freed", count);
|
|
|
|
|
ll_destroy(&configured_readers);
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t write_server(void)
|
|
|
|
|
{
|
|
|
|
|
FILE *f = create_config_file(cs_srvr);
|
|
|
|
|
if(!f)
|
|
|
|
|
{ return 1; }
|
|
|
|
|
struct s_reader *rdr;
|
|
|
|
|
LL_ITER itr = ll_iter_create(configured_readers);
|
|
|
|
|
while((rdr = ll_iter_next(&itr)))
|
|
|
|
|
{
|
|
|
|
|
if(rdr->label[0])
|
|
|
|
|
{
|
|
|
|
|
fprintf(f, "[reader]\n");
|
|
|
|
|
config_list_apply_fixups(reader_opts, rdr);
|
|
|
|
|
config_list_save_ex(f, reader_opts, rdr, cfg.http_full_cfg, reader_check_setting);
|
|
|
|
|
fprintf(f, "\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return flush_config_file(f, cs_srvr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void reload_readerdb(void)
|
|
|
|
|
{
|
|
|
|
|
struct s_reader *rdr;
|
|
|
|
|
LL_ITER itr = ll_iter_create(configured_readers);
|
|
|
|
|
while((rdr = ll_iter_next(&itr)))
|
|
|
|
|
{
|
|
|
|
|
// disable the current reader
|
|
|
|
|
rdr->enable = 0;
|
|
|
|
|
restart_cardreader(rdr,1);
|
|
|
|
|
}
|
|
|
|
|
free_readerdb(); // release the old readerdb
|
|
|
|
|
init_readerdb(); // reload the new readerdb
|
|
|
|
|
init_cardreader(); // start the readers
|
|
|
|
|
}
|