source: trunk/oscam-config-reader.c@ 8449

Last change on this file since 8449 was 8449, checked in by gf, 9 years ago

readers: Do not leak entitlements on card change and reader freeing.

Reader entitlements are leaken when card is changed. Probably nobody
noticed because changing cards is not an event that happen often.

File size: 30.4 KB
Line 
1#include "globals.h"
2#include "module-gbox.h"
3#include "oscam-aes.h"
4#include "oscam-conf.h"
5#include "oscam-conf-chk.h"
6#include "oscam-conf-mk.h"
7#include "oscam-config.h"
8#include "oscam-garbage.h"
9#include "oscam-lock.h"
10#include "oscam-reader.h"
11#include "oscam-string.h"
12
13#define cs_srvr "oscam.server"
14
15extern struct s_cardreader cardreaders[CS_MAX_MOD];
16extern char *RDR_CD_TXT[];
17
18static void reader_label_fn(const char *token, char *value, void *setting, FILE *f) {
19 struct s_reader *rdr = setting;
20 if (value) {
21 int i, found = 0;
22 if (!strlen(value))
23 return;
24 for (i = 0; i < (int)strlen(value); i++) {
25 if (value[i] == ' ') {
26 value[i] = '_';
27 found++;
28 }
29 }
30 if (found)
31 fprintf(stderr, "Configuration reader: corrected label to %s\n", value);
32 cs_strncpy(rdr->label, value, sizeof(rdr->label));
33 return;
34 }
35 fprintf_conf(f, token, "%s\n", rdr->label);
36}
37
38static void ecmwhitelist_fn(const char *token, char *value, void *setting, FILE *f) {
39 struct s_reader *rdr = setting;
40 if (value) {
41 char *ptr, *ptr2, *ptr3, *saveptr1 = NULL;
42 struct s_ecmWhitelist *tmp, *last;
43 struct s_ecmWhitelistIdent *tmpIdent, *lastIdent;
44 struct s_ecmWhitelistLen *tmpLen, *lastLen;
45 for(tmp = rdr->ecmWhitelist; tmp; tmp=tmp->next){
46 for(tmpIdent = tmp->idents; tmpIdent; tmpIdent=tmpIdent->next){
47 for(tmpLen = tmpIdent->lengths; tmpLen; tmpLen=tmpLen->next){
48 add_garbage(tmpLen);
49 }
50 add_garbage(tmpIdent);
51 }
52 add_garbage(tmp);
53 }
54 rdr->ecmWhitelist = NULL;
55 if(strlen(value) > 0){
56 saveptr1 = NULL;
57 char *saveptr2 = NULL;
58 for (ptr = strtok_r(value, ";", &saveptr1); ptr; ptr = strtok_r(NULL, ";", &saveptr1)) {
59 int16_t caid = 0, len;
60 uint32_t ident = 0;
61 ptr2=strchr(ptr,':');
62 if(ptr2 != NULL){
63 ptr2[0] = '\0';
64 ++ptr2;
65 ptr3=strchr(ptr,'@');
66 if(ptr3 != NULL){
67 ptr3[0] = '\0';
68 ++ptr3;
69 ident = (uint32_t)a2i(ptr3, 6);
70 }
71 caid = (int16_t)dyn_word_atob(ptr);
72 } else ptr2 = ptr;
73 for (ptr2 = strtok_r(ptr2, ",", &saveptr2); ptr2; ptr2 = strtok_r(NULL, ",", &saveptr2)) {
74 len = (int16_t)dyn_word_atob(ptr2);
75 last = NULL, tmpIdent = NULL, lastIdent = NULL, tmpLen = NULL, lastLen = NULL;
76 for(tmp = rdr->ecmWhitelist; tmp; tmp=tmp->next){
77 last = tmp;
78 if(tmp->caid == caid){
79 for(tmpIdent = tmp->idents; tmpIdent; tmpIdent=tmpIdent->next){
80 lastIdent = tmpIdent;
81 if(tmpIdent->ident == ident){
82 for(tmpLen = tmpIdent->lengths; tmpLen; tmpLen=tmpLen->next){
83 lastLen = tmpLen;
84 if(tmpLen->len == len) break;
85 }
86 break;
87 }
88 }
89 }
90 }
91 if(tmp == NULL){
92 if (cs_malloc(&tmp, sizeof(struct s_ecmWhitelist))) {
93 tmp->caid = caid;
94 tmp->idents = NULL;
95 tmp->next = NULL;
96 if(last == NULL){
97 rdr->ecmWhitelist = tmp;
98 } else {
99 last->next = tmp;
100 }
101 }
102 }
103 if(tmp != NULL && tmpIdent == NULL){
104 if (cs_malloc(&tmpIdent, sizeof(struct s_ecmWhitelistIdent))) {
105 tmpIdent->ident = ident;
106 tmpIdent->lengths = NULL;
107 tmpIdent->next = NULL;
108 if(lastIdent == NULL){
109 tmp->idents = tmpIdent;
110 } else {
111 lastIdent->next = tmpIdent;
112 }
113 }
114 }
115 if(tmp != NULL && tmpIdent != NULL && tmpLen == NULL){
116 if (cs_malloc(&tmpLen, sizeof(struct s_ecmWhitelistLen))) {
117 tmpLen->len = len;
118 tmpLen->next = NULL;
119 if(lastLen == NULL){
120 tmpIdent->lengths = tmpLen;
121 } else {
122 lastLen->next = tmpLen;
123 }
124 }
125 }
126 }
127 }
128 }
129 return;
130 }
131
132 value = mk_t_ecmwhitelist(rdr->ecmWhitelist);
133 if (strlen(value) > 0 || cfg.http_full_cfg)
134 fprintf_conf(f, token, "%s\n", value);
135 free_mk_t(value);
136}
137
138static void ecmheaderwhitelist_fn(const char *token, char *value, void *setting, FILE *f) {
139 struct s_reader *rdr = setting;
140 if (value) {
141 char *ptr, *ptr2, *ptr3;
142 struct s_ecmHeaderwhitelist *tmp, *last = NULL;
143
144 if (strlen(value) == 0) {
145 for (tmp = rdr->ecmHeaderwhitelist; tmp; tmp=tmp->next)
146 add_garbage(tmp);
147 rdr->ecmHeaderwhitelist = NULL;
148 } else {
149 char *ptr4, *ptr5, *ptr6, *saveptr = NULL, *saveptr4 = NULL, *saveptr5 = NULL, *saveptr6 = NULL;
150 uint16_t caid = 0;
151 uint32_t provid = 0;
152 int16_t len = 0;
153 for (ptr = strtok_r(value, ";", &saveptr); ptr; ptr = strtok_r(NULL, ";", &saveptr)) {
154 caid = 0;
155 provid = 0;
156 ptr2 = strchr(ptr, '@');
157 ptr3 = strchr(ptr, ':');
158 if (ptr2 == NULL && ptr3 == NULL) { //no Caid no Provid
159 for (ptr4 = strtok_r(ptr, ",", &saveptr4); ptr4; ptr4 = strtok_r(NULL, ",", &saveptr4)) {
160 if (cs_malloc(&tmp, sizeof(struct s_ecmHeaderwhitelist))) {
161 ptr4 = trim(ptr4);
162 len = strlen(ptr4);
163 key_atob_l(ptr4, tmp->header, len);
164 tmp->len = len;
165 tmp->caid = 0;
166 tmp->provid = 0;
167 tmp->next = NULL;
168 if (last == NULL) {
169 rdr->ecmHeaderwhitelist = tmp;
170 } else {
171 last->next = tmp;
172 }
173 last = tmp;
174 }
175 }
176 }
177
178 if (ptr3 != NULL && ptr2 == NULL) { // only with Caid
179 ptr3[0] = '\0';
180 ++ptr3;
181 caid = (int16_t)dyn_word_atob(ptr);
182 for (ptr5 = strtok_r(ptr3, ",", &saveptr5); ptr5; ptr5 = strtok_r(NULL, ",", &saveptr5)) {
183 if (cs_malloc(&tmp, sizeof(struct s_ecmHeaderwhitelist))) {
184 tmp->caid = caid;
185 tmp->provid = 0;
186 ptr5 = trim(ptr5);
187 len = strlen(ptr5);
188 key_atob_l(ptr5, tmp->header, len);
189 tmp->len = len;
190 tmp->next = NULL;
191 if (last == NULL) {
192 rdr->ecmHeaderwhitelist = tmp;
193 } else {
194 last->next = tmp;
195 }
196 last = tmp;
197 }
198 }
199 }
200
201 if (ptr3 != NULL && ptr2 != NULL) { // with Caid & Provid
202 ptr2[0] = '\0';
203 ++ptr2; // -> provid
204 ptr3[0] = '\0';
205 ++ptr3; // -> headers
206 caid = (int16_t)dyn_word_atob(ptr);
207 provid = (uint32_t)a2i(ptr2, 6);
208 for (ptr6 = strtok_r(ptr3, ",", &saveptr6); ptr6; ptr6 = strtok_r(NULL, ",", &saveptr6)) {
209 if (cs_malloc(&tmp, sizeof(struct s_ecmHeaderwhitelist))) {
210 tmp->caid = caid;
211 tmp->provid = provid;
212 ptr6 = trim(ptr6);
213 len = strlen(ptr6);
214 key_atob_l(ptr6, tmp->header, len);
215 tmp->len = len;
216 tmp->next = NULL;
217 if (last == NULL) {
218 rdr->ecmHeaderwhitelist = tmp;
219 } else {
220 last->next = tmp;
221 }
222 last = tmp;
223 }
224 }
225 }
226 }
227 }
228/* if (rdr->ecmHeaderwhitelist != NULL) { // debug
229 cs_log("**********Begin ECM Header List for Reader: %s **************", rdr->label);
230
231 struct s_ecmHeaderwhitelist *tmp;
232 for(tmp = rdr->ecmHeaderwhitelist; tmp; tmp=tmp->next){
233 cs_log("Caid: %i Provid: %i Header: %02X Len: %i", tmp->caid, tmp->provid, tmp->header[0], tmp->len);
234 }
235 cs_log("***********End ECM Header List for Reader: %s ***************", rdr->label);
236 } */
237 return;
238 }
239
240 value = mk_t_ecmheaderwhitelist(rdr->ecmHeaderwhitelist);
241 if (strlen(value) > 0 || cfg.http_full_cfg)
242 fprintf_conf(f, token, "%s\n", value);
243 free_mk_t(value);
244}
245
246static void protocol_fn(const char *token, char *value, void *setting, FILE *f) {
247 struct s_reader *rdr = setting;
248 if (value) {
249 if (strlen(value) == 0)
250 return;
251 struct protocol_map {
252 char *name;
253 int typ;
254 } protocols[] = {
255 { "serial", R_SERIAL },
256 { "camd35", R_CAMD35 },
257 { "cs378x", R_CS378X },
258 { "cs357x", R_CAMD35 },
259 { "camd33", R_CAMD33 },
260 { "gbox", R_GBOX },
261 { "cccam", R_CCCAM },
262 { "cccam ext", R_CCCAM },
263 { "constcw", R_CONSTCW },
264 { "radegast", R_RADEGAST },
265 { "ghttp", R_GHTTP },
266 { "newcamd", R_NEWCAMD },
267 { "newcamd525", R_NEWCAMD },
268 { "newcamd524", R_NEWCAMD },
269 { NULL , 0 }
270 }, *p;
271 int i;
272 // Parse card readers
273 for (i = 0; i < CS_MAX_MOD; i++) {
274 if (streq(value, cardreaders[i].desc)) {
275 rdr->crdr = cardreaders[i];
276 rdr->typ = cardreaders[i].typ;
277 return;
278 }
279 }
280 // Parse protocols
281 for(i = 0, p = &protocols[0]; p->name; p = &protocols[++i]) {
282 if (streq(p->name, value)) {
283 rdr->typ = p->typ;
284 break;
285 }
286 }
287 if (rdr->typ == R_NEWCAMD)
288 rdr->ncd_proto = streq(value, "newcamd524") ? NCD_524 : NCD_525;
289 if (!rdr->typ)
290 fprintf(stderr, "ERROR: '%s' is unsupported reader protocol!\n", value);
291 return;
292 }
293 fprintf_conf(f, token, "%s\n", reader_get_type_desc(rdr, 0));
294}
295
296static void device_fn(const char *token, char *value, void *setting, FILE *f) {
297 struct s_reader *rdr = setting;
298 int32_t isphysical = !is_network_reader(rdr);
299 if (value) {
300 int32_t i;
301 char *ptr, *saveptr1 = NULL;
302 for (i = 0, ptr = strtok_r(value, ",", &saveptr1); (i < 3) && (ptr); ptr = strtok_r(NULL, ",", &saveptr1), i++) {
303 trim(ptr);
304 switch(i) {
305 case 0:
306 cs_strncpy(rdr->device, ptr, sizeof(rdr->device));
307 break;
308 case 1:
309 rdr->r_port = atoi(ptr);
310 break;
311 case 2:
312 rdr->l_port = atoi(ptr);
313 break;
314 }
315 }
316 return;
317 }
318 fprintf_conf(f, token, "%s", rdr->device); // it should not have \n at the end
319 if ((rdr->r_port || cfg.http_full_cfg) && !isphysical)
320 fprintf(f, ",%d", rdr->r_port);
321 if ((rdr->l_port || cfg.http_full_cfg) && !isphysical && strncmp(reader_get_type_desc(rdr, 0), "cccam", 5))
322 fprintf(f, ",%d", rdr->l_port);
323 fprintf(f, "\n");
324}
325
326static void reader_services_fn(const char *token, char *value, void *setting, FILE *f) {
327 services_fn(token, value, setting, f);
328 if (value) {
329 struct s_reader *rdr = container_of(setting, struct s_reader, sidtabs);
330 rdr->changes_since_shareupdate = 1;
331 }
332}
333
334static void reader_caid_fn(const char *token, char *value, void *setting, FILE *f) {
335 check_caidtab_fn(token, value, setting, f);
336 if (value) {
337 struct s_reader *rdr = container_of(setting, struct s_reader, ctab);
338 rdr->changes_since_shareupdate = 1;
339 }
340}
341
342static void boxid_fn(const char *token, char *value, void *setting, FILE *f) {
343 struct s_reader *rdr = setting;
344 if (value) {
345 rdr->boxid = strlen(value) ? a2i(value, 4) : 0;
346 return;
347 }
348 if (rdr->boxid)
349 fprintf_conf(f, token, "%08X\n", rdr->boxid);
350 else if (cfg.http_full_cfg)
351 fprintf_conf(f, token, "\n");
352}
353
354static void rsakey_fn(const char *token, char *value, void *setting, FILE *f) {
355 struct s_reader *rdr = setting;
356 if (value) {
357 int32_t len = strlen(value);
358 if(len != 128 && len != 240) {
359 memset(rdr->rsa_mod, 0, 120);
360 } else {
361 if (key_atob_l(value, rdr->rsa_mod, len)) {
362 fprintf(stderr, "reader rsakey parse error, %s=%s\n", token, value);
363 memset(rdr->rsa_mod, 0, sizeof(rdr->rsa_mod));
364 }
365 }
366 return;
367 }
368 int32_t len = check_filled(rdr->rsa_mod, 120);
369 if (len > 0) {
370 if(len > 64) len = 120;
371 else len = 64;
372 char tmp[len*2+1];
373 fprintf_conf(f, "rsakey", "%s\n", cs_hexdump(0, rdr->rsa_mod, len, tmp, sizeof(tmp)));
374 } else if(cfg.http_full_cfg)
375 fprintf_conf(f, "rsakey", "\n");
376}
377
378static void flags_fn(const char *token, char *value, void *setting, long flag, FILE *f) {
379 uint32_t *var = setting;
380 if (value) {
381 int i = atoi(value);
382 if (!i && (*var & flag))
383 *var -= flag;
384 if (i)
385 *var |= flag;
386 return;
387 }
388 if ((*var & flag) || cfg.http_full_cfg)
389 fprintf_conf(f, token, "%d\n", (*var & flag) ? 1 : 0);
390}
391
392static void ins7E_fn(const char *token, char *value, void *setting, long var_size, FILE *f) {
393 uint8_t *var = setting;
394 var_size -= 1; // var_size contains sizeof(var) which is [X + 1]
395 if (value) {
396 int32_t len = strlen(value);
397 if (len != var_size * 2 || key_atob_l(value, var, len)) {
398 if (len > 0)
399 fprintf(stderr, "reader %s parse error, %s=%s\n", token, token, value);
400 memset(var, 0, var_size + 1);
401 } else {
402 var[var_size] = 1; // found and correct
403 }
404 return;
405 }
406 if (var[var_size]) {
407 char tmp[var_size * 2 + 1];
408 fprintf_conf(f, token, "%s\n", cs_hexdump(0, var, var_size, tmp, sizeof(tmp)));
409 } else if (cfg.http_full_cfg)
410 fprintf_conf(f, token, "\n");
411}
412
413static void atr_fn(const char *token, char *value, void *setting, FILE *f) {
414 struct s_reader *rdr = setting;
415 if (value) {
416 memset(rdr->atr, 0, sizeof(rdr->atr));
417 rdr->atrlen = strlen(value);
418 if (rdr->atrlen) {
419 if (rdr->atrlen > (int32_t)sizeof(rdr->atr) * 2)
420 rdr->atrlen = (int32_t)sizeof(rdr->atr) * 2;
421 key_atob_l(value, rdr->atr, rdr->atrlen);
422 }
423 return;
424 }
425 if (rdr->atr[0] || cfg.http_full_cfg) {
426 int j;
427 fprintf_conf(f, token, "%s", ""); // it should not have \n at the end
428 if (rdr->atr[0]) {
429 for (j = 0; j < rdr->atrlen / 2; j++) {
430 fprintf(f, "%02X", rdr->atr[j]);
431 }
432 }
433 fprintf(f, "\n");
434 }
435}
436
437static void detect_fn(const char *token, char *value, void *setting, FILE *f) {
438 struct s_reader *rdr = setting;
439 if (value) {
440 int i;
441 for (i = 0; RDR_CD_TXT[i]; i++) {
442 if (!strcmp(value, RDR_CD_TXT[i])) {
443 rdr->detect = i;
444 } else {
445 if (value[0] == '!' && streq(value + 1, RDR_CD_TXT[i]))
446 rdr->detect = i | 0x80;
447 }
448 }
449 return;
450 }
451 fprintf_conf(f, token, "%s%s\n", rdr->detect & 0x80 ? "!" : "", RDR_CD_TXT[rdr->detect & 0x7f]);
452}
453
454void ftab_fn(const char *token, char *value, void *setting, long ftab_type, FILE *f) {
455 const char *zType = NULL, *zName = NULL, *zFiltNamef = NULL;
456 struct s_reader *rdr = NULL;
457 FTAB *ftab = setting;
458
459 if (ftab_type & FTAB_ACCOUNT) {
460 struct s_auth *account = NULL;
461 zType = "account";
462 if (ftab_type & FTAB_PROVID) account = container_of(setting, struct s_auth, ftab);
463 if (ftab_type & FTAB_CHID) account = container_of(setting, struct s_auth, fchid);
464 if (account) zName = account->usr;
465 }
466 if (ftab_type & FTAB_READER) {
467 zType = "reader";
468 if (ftab_type & FTAB_PROVID) rdr = container_of(setting, struct s_reader, ftab);
469 if (ftab_type & FTAB_CHID) rdr = container_of(setting, struct s_reader, fchid);
470 if (rdr) zName = rdr->label;
471 }
472 if (ftab_type & FTAB_PROVID) zFiltNamef = "provid";
473 if (ftab_type & FTAB_CHID) zFiltNamef = "chid";
474
475 if (value) {
476 if (strlen(value)) {
477 strtolower(value);
478 chk_ftab(value, ftab, zType, zName, zFiltNamef);
479 } else {
480 clear_ftab(ftab);
481 }
482 if (rdr)
483 rdr->changes_since_shareupdate = 1;
484 return;
485 }
486 value = mk_t_ftab(ftab);
487 if (strlen(value) > 0 || cfg.http_full_cfg)
488 fprintf_conf(f, token, "%s\n", value);
489 free_mk_t(value);
490}
491
492static void aeskeys_fn(const char *token, char *value, void *setting, FILE *f) {
493 struct s_reader *rdr = setting;
494 if (value) {
495 parse_aes_keys(rdr,value);
496 return;
497 }
498 value = mk_t_aeskeys(rdr);
499 if (strlen(value) > 0 || cfg.http_full_cfg)
500 fprintf_conf(f, token, "%s\n", value);
501 free_mk_t(value);
502}
503
504static void emmcache_fn(const char *token, char *value, void *setting, FILE *f) {
505 struct s_reader *rdr = setting;
506 if (value) {
507 rdr->cachemm = 0;
508 rdr->rewritemm = 0;
509 rdr->logemm = 0;
510 if (strlen(value)) {
511 int i;
512 char *ptr, *saveptr1 = NULL;
513 for (i = 0, ptr = strtok_r(value, ",", &saveptr1); (i < 3) && (ptr); ptr = strtok_r(NULL, ",", &saveptr1), i++) {
514 switch(i) {
515 case 0: rdr->cachemm = atoi(ptr); break;
516 case 1: rdr->rewritemm = atoi(ptr); break;
517 case 2: rdr->logemm = atoi(ptr); break;
518 }
519 }
520 if (rdr->rewritemm <= 0) {
521 fprintf(stderr, "Setting reader \"emmcache\" to %i,%d,%i instead of %i,%i,%i.",
522 rdr->cachemm, 1, rdr->logemm,
523 rdr->cachemm, rdr->rewritemm, rdr->logemm);
524 fprintf(stderr, "Zero or negative number of rewrites is silly\n");
525 rdr->rewritemm = 1;
526 }
527 }
528 return;
529 }
530 if (rdr->cachemm || cfg.http_full_cfg)
531 fprintf_conf(f, token, "%d,%d,%d\n", rdr->cachemm, rdr->rewritemm, rdr->logemm);
532}
533
534static void blockemm_bylen_fn(const char *token, char *value, void *setting, FILE *f) {
535 struct s_reader *rdr = setting;
536 if (value) {
537 int32_t i;
538 char *ptr, *saveptr1 = NULL;
539 for (i = 0; i < CS_MAXEMMBLOCKBYLEN; i++)
540 rdr->blockemmbylen[i] = 0;
541 for (i = 0, ptr = strtok_r(value, ",", &saveptr1); (i < CS_MAXEMMBLOCKBYLEN) && (ptr); ptr = strtok_r(NULL, ",", &saveptr1), i++)
542 rdr->blockemmbylen[i] = atoi(ptr);
543 return;
544 }
545 value = mk_t_emmbylen(rdr);
546 if (strlen(value) > 0 || cfg.http_full_cfg)
547 fprintf_conf(f, token, "%s\n", value);
548 free_mk_t(value);
549}
550
551static void nano_fn(const char *token, char *value, void *setting, FILE *f) {
552 uint16_t *nano = setting;
553 if (value) {
554 *nano = 0;
555 if (strlen(value) > 0) {
556 if (streq(value, "all")) {
557 *nano = 0xFFFF;
558 } else {
559 int32_t i;
560 char *ptr, *saveptr1 = NULL;
561 for (ptr = strtok_r(value, ",", &saveptr1); ptr; ptr = strtok_r(NULL, ",", &saveptr1)) {
562 i = (byte_atob(ptr) % 0x80);
563 if (i >= 0 && i <= 16)
564 *nano |= (1 << i);
565 }
566 }
567 }
568 return;
569 }
570 value = mk_t_nano(*nano);
571 if (strlen(value) > 0 || cfg.http_full_cfg)
572 fprintf_conf(f, token, "%s\n", value);
573 free_mk_t(value);
574}
575
576static void auprovid_fn(const char *token, char *value, void *setting, FILE *f) {
577 struct s_reader *rdr = setting;
578 if (value) {
579 rdr->auprovid = 0;
580 if (strlen(value))
581 rdr->auprovid = a2i(value, 3);
582 return;
583 }
584 if (rdr->auprovid)
585 fprintf_conf(f, token, "%06X\n", rdr->auprovid);
586 else if (cfg.http_full_cfg)
587 fprintf_conf(f, token, "\n");
588}
589
590static void ratelimitecm_fn(const char *token, char *value, void *setting, FILE *f) {
591 struct s_reader *rdr = setting;
592 if (value) {
593 rdr->ratelimitecm = 0;
594 if (strlen(value)) {
595 int i;
596 rdr->ratelimitecm = atoi(value);
597 for (i = 0; i < MAXECMRATELIMIT; i++) { // reset all slots
598 rdr->rlecmh[i].srvid = -1;
599 rdr->rlecmh[i].last = -1;
600 }
601 }
602 return;
603 }
604 if (rdr->ratelimitecm || cfg.http_full_cfg)
605 fprintf_conf(f, token, "%d\n", rdr->ratelimitecm);
606}
607
608static void ratelimitseconds_fn(const char *token, char *value, void *setting, FILE *f) {
609 struct s_reader *rdr = setting;
610 if (value) {
611 if (strlen(value) == 0) {
612 if (rdr->ratelimitecm > 0) {
613 rdr->ratelimitseconds = 10;
614 } else {
615 rdr->ratelimitecm = 0; // in case someone set a negative value
616 rdr->ratelimitseconds = 0;
617 }
618 } else {
619 rdr->ratelimitseconds = atoi(value);
620 }
621 return;
622 }
623 if (rdr->ratelimitecm || cfg.http_full_cfg)
624 fprintf_conf(f, token, "%d\n", rdr->ratelimitseconds);
625}
626
627static void cooldown_fn(const char *token, char *value, void *setting, FILE *f) {
628 struct s_reader *rdr = setting;
629 if (value) {
630 if(strlen(value) == 0) {
631 rdr->cooldown[0] = 0;
632 rdr->cooldown[1] = 0;
633 } else {
634 int32_t i;
635 char *ptr, *saveptr1 = NULL;
636 for (i = 0, ptr = strtok_r(value, ",", &saveptr1); (i < 2) && (ptr); ptr = strtok_r(NULL, ",", &saveptr1), i++) {
637 rdr->cooldown[i] = atoi(ptr);
638 }
639 if (rdr->cooldown[0] <= 0 || rdr->cooldown[1] <= 0) {
640 fprintf(stderr, "cooldown must have 2 positive values (x,y) set values %d,%d ! cooldown deactivated\n",
641 rdr->cooldown[0], rdr->cooldown[1]);
642 rdr->cooldown[0] = 0;
643 rdr->cooldown[1] = 0;
644 }
645 }
646 return;
647 }
648 if (rdr->cooldown[0] || cfg.http_full_cfg) {
649 fprintf_conf(f, token, "%d,%d\n", rdr->cooldown[0], rdr->cooldown[1]);
650 }
651}
652
653static void cooldowndelay_fn(const char *UNUSED(token), char *value, void *setting, FILE *UNUSED(f)) {
654 struct s_reader *rdr = setting;
655 if (value) {
656 rdr->cooldown[0] = strlen(value) ? atoi(value) : 0;
657 }
658 // This option is *not* written in the config file.
659 // It is only set by WebIf as convenience
660}
661
662static void cooldowntime_fn(const char *UNUSED(token), char *value, void *setting, FILE *UNUSED(f)) {
663 struct s_reader *rdr = setting;
664 if (value) {
665 if (strlen(value) == 0) {
666 rdr->cooldown[0] = 0; // no cooling down time means no cooling set
667 rdr->cooldown[1] = 0;
668 } else {
669 rdr->cooldown[1] = atoi(value);
670 }
671 return;
672 }
673 // This option is *not* written in the config file.
674 // It is only set by WebIf as convenience
675}
676
677#ifdef WITH_LB
678static void reader_fixups_fn(void *var) {
679 struct s_reader *rdr = var;
680 if (rdr->lb_weight > 1000)
681 rdr->lb_weight = 1000;
682 else if (rdr->lb_weight <= 0)
683 rdr->lb_weight = 100;
684}
685#endif
686
687#define OFS(X) offsetof(struct s_reader, X)
688#define SIZEOF(X) sizeof(((struct s_reader *)0)->X)
689
690static const struct config_list reader_opts[] = {
691#ifdef WITH_LB
692 DEF_OPT_FIXUP_FUNC(reader_fixups_fn),
693#endif
694 DEF_OPT_FUNC("label" , 0, reader_label_fn ),
695#ifdef WEBIF
696 DEF_OPT_STR("description" , OFS(description), NULL ),
697#endif
698 DEF_OPT_INT8("enable" , OFS(enable), 1 ),
699 DEF_OPT_FUNC("protocol" , 0, protocol_fn ),
700 DEF_OPT_FUNC("device" , 0, device_fn ),
701 DEF_OPT_HEX("key" , OFS(ncd_key), SIZEOF(ncd_key) ),
702 DEF_OPT_SSTR("user" , OFS(r_usr), "", SIZEOF(r_usr) ),
703 DEF_OPT_SSTR("password" , OFS(r_pwd), "", SIZEOF(r_pwd) ),
704 DEF_OPT_SSTR("pincode" , OFS(pincode), "none", SIZEOF(pincode) ),
705#ifdef MODULE_GBOX
706 DEF_OPT_FUNC("mg-encrypted" , 0, mgencrypted_fn ),
707 DEF_OPT_INT8("gbox_max_distance" , OFS(gbox_maxdist), DEFAULT_GBOX_MAX_DIST ),
708 DEF_OPT_INT8("gbox_max_ecm_send" , OFS(gbox_maxecmsend), DEFAULT_GBOX_MAX_ECM_SEND ),
709 DEF_OPT_INT8("gbox_reshare" , OFS(gbox_reshare), 0 ),
710 DEF_OPT_FUNC("gbox_group" , OFS(gbox_grp), group_fn ),
711 DEF_OPT_SSTR("gbox_my_password" , OFS(gbox_my_password), "", SIZEOF(gbox_my_password) ),
712#endif
713 DEF_OPT_STR("readnano" , OFS(emmfile), NULL ),
714 DEF_OPT_FUNC("services" , OFS(sidtabs), reader_services_fn ),
715 DEF_OPT_INT32("inactivitytimeout" , OFS(tcp_ito), DEFAULT_INACTIVITYTIMEOUT ),
716 DEF_OPT_INT32("reconnecttimeout" , OFS(tcp_rto), DEFAULT_TCP_RECONNECT_TIMEOUT ),
717 DEF_OPT_INT32("resetcycle" , OFS(resetcycle), 0 ),
718 DEF_OPT_INT8("disableserverfilter" , OFS(ncd_disable_server_filt), 0 ),
719 DEF_OPT_INT8("connectoninit" , OFS(ncd_connect_on_init), 0 ),
720 DEF_OPT_INT8("smargopatch" , OFS(smargopatch), 0 ),
721 DEF_OPT_UINT8("sc8in1_dtrrts_patch" , OFS(sc8in1_dtrrts_patch), 0 ),
722 DEF_OPT_INT8("fallback" , OFS(fallback), 0 ),
723#ifdef CS_CACHEEX
724 DEF_OPT_INT8("cacheex" , OFS(cacheex.mode), 0 ),
725 DEF_OPT_INT8("cacheex_maxhop" , OFS(cacheex.maxhop), 0 ),
726 DEF_OPT_FUNC("cacheex_ecm_filter" , OFS(cacheex.filter_caidtab), cacheex_hitvaluetab_fn ),
727 DEF_OPT_UINT8("cacheex_allow_request" , OFS(cacheex.allow_request), 1 ),
728 DEF_OPT_UINT8("cacheex_drop_csp" , OFS(cacheex.drop_csp), 0 ),
729#endif
730#ifdef WITH_COOLAPI
731 DEF_OPT_INT32("cool_timeout_init" , OFS(cool_timeout_init), 0 ), //0 = use value from atr
732 DEF_OPT_INT32("cool_timeout_after_init" , OFS(cool_timeout_after_init), 0 ), //0 = use value from atr
733#endif
734 DEF_OPT_FUNC("caid" , OFS(ctab), reader_caid_fn ),
735 DEF_OPT_FUNC("atr" , 0, atr_fn ),
736 DEF_OPT_FUNC("boxid" , 0, boxid_fn ),
737 DEF_OPT_HEX("boxkey" , OFS(boxkey), SIZEOF(boxkey) ),
738 DEF_OPT_FUNC("rsakey" , 0, rsakey_fn ),
739 DEF_OPT_FUNC_X("ins7e" , OFS(ins7E), ins7E_fn, SIZEOF(ins7E) ),
740 DEF_OPT_FUNC_X("ins7e11" , OFS(ins7E11), ins7E_fn, SIZEOF(ins7E11) ),
741 DEF_OPT_INT8("fix9993" , OFS(fix_9993), 0 ),
742 DEF_OPT_INT8("force_irdeto" , OFS(force_irdeto), 0 ),
743 DEF_OPT_UINT32("ecmnotfoundlimit" , OFS(ecmnotfoundlimit), 0 ),
744 DEF_OPT_FUNC("ecmwhitelist" , 0, ecmwhitelist_fn ),
745 DEF_OPT_FUNC("ecmheaderwhitelist" , 0, ecmheaderwhitelist_fn ),
746 DEF_OPT_FUNC("detect" , 0, detect_fn ),
747 DEF_OPT_INT8("nagra_read" , OFS(nagra_read), 0 ),
748 DEF_OPT_INT32("mhz" , OFS(mhz), 357 ),
749 DEF_OPT_INT32("cardmhz" , OFS(cardmhz), 357 ),
750#ifdef WITH_AZBOX
751 DEF_OPT_INT32("mode" , OFS(azbox_mode), -1 ),
752#endif
753 DEF_OPT_FUNC_X("ident" , OFS(ftab), ftab_fn, FTAB_READER | FTAB_PROVID ),
754 DEF_OPT_FUNC_X("chid" , OFS(fchid), ftab_fn, FTAB_READER | FTAB_CHID ),
755 DEF_OPT_FUNC("class" , OFS(cltab), class_fn ),
756 DEF_OPT_FUNC("aeskeys" , 0, aeskeys_fn ),
757 DEF_OPT_FUNC("group" , OFS(grp), group_fn ),
758 DEF_OPT_FUNC("emmcache" , 0, emmcache_fn ),
759 DEF_OPT_FUNC_X("blockemm-unknown" , OFS(blockemm), flags_fn, EMM_UNKNOWN ),
760 DEF_OPT_FUNC_X("blockemm-u" , OFS(blockemm), flags_fn, EMM_UNIQUE ),
761 DEF_OPT_FUNC_X("blockemm-s" , OFS(blockemm), flags_fn, EMM_SHARED ),
762 DEF_OPT_FUNC_X("blockemm-g" , OFS(blockemm), flags_fn, EMM_GLOBAL ),
763 DEF_OPT_FUNC_X("saveemm-unknown" , OFS(saveemm), flags_fn, EMM_UNKNOWN ),
764 DEF_OPT_FUNC_X("saveemm-u" , OFS(saveemm), flags_fn, EMM_UNIQUE ),
765 DEF_OPT_FUNC_X("saveemm-s" , OFS(saveemm), flags_fn, EMM_SHARED ),
766 DEF_OPT_FUNC_X("saveemm-g" , OFS(saveemm), flags_fn, EMM_GLOBAL ),
767 DEF_OPT_FUNC("blockemm-bylen" , 0, blockemm_bylen_fn ),
768#ifdef WITH_LB
769 DEF_OPT_INT32("lb_weight" , OFS(lb_weight), 100 ),
770#endif
771 DEF_OPT_FUNC("savenano" , OFS(s_nano), nano_fn ),
772 DEF_OPT_FUNC("blocknano" , OFS(b_nano), nano_fn ),
773 DEF_OPT_INT8("dropbadcws" , OFS(dropbadcws), 0 ),
774 DEF_OPT_INT8("disablecrccws" , OFS(disablecrccws), 0 ),
775 DEF_OPT_INT32("use_gpio" , OFS(use_gpio), 0 ),
776#ifdef MODULE_PANDORA
777 DEF_OPT_UINT8("pand_send_ecm" , OFS(pand_send_ecm), 0 ),
778#endif
779#ifdef MODULE_CCCAM
780 DEF_OPT_SSTR("cccversion" , OFS(cc_version), "", SIZEOF(cc_version) ),
781 DEF_OPT_INT8("cccmaxhops" , OFS(cc_maxhops), DEFAULT_CC_MAXHOPS ),
782 DEF_OPT_INT8("cccmindown" , OFS(cc_mindown), 0 ),
783 DEF_OPT_INT8("cccwantemu" , OFS(cc_want_emu), 0 ),
784 DEF_OPT_INT8("ccckeepalive" , OFS(cc_keepalive), DEFAULT_CC_KEEPALIVE ),
785 DEF_OPT_INT8("cccreshare" , OFS(cc_reshare), DEFAULT_CC_RESHARE ),
786 DEF_OPT_INT32("cccreconnect" , OFS(cc_reconnect), DEFAULT_CC_RECONNECT ),
787 DEF_OPT_INT8("ccchop" , OFS(cc_hop), 0 ),
788#endif
789 DEF_OPT_INT8("deprecated" , OFS(deprecated), 0 ),
790 DEF_OPT_INT8("audisabled" , OFS(audisabled), 0 ),
791 DEF_OPT_FUNC("auprovid" , 0, auprovid_fn ),
792 DEF_OPT_INT8("ndsversion" , OFS(ndsversion), 0 ),
793 DEF_OPT_FUNC("ratelimitecm" , 0, ratelimitecm_fn ),
794 DEF_OPT_FUNC("ratelimitseconds" , 0, ratelimitseconds_fn ),
795 DEF_OPT_INT8("ecmunique" , OFS(ecmunique), 0 ),
796 DEF_OPT_INT8("srvidholdseconds" , OFS(srvidholdseconds), 0 ),
797 DEF_OPT_FUNC("cooldown" , 0, cooldown_fn ),
798 DEF_OPT_FUNC("cooldowndelay" , 0, cooldowndelay_fn ),
799 DEF_OPT_FUNC("cooldowntime" , 0, cooldowntime_fn ),
800 DEF_LAST_OPT
801};
802
803static inline bool in_list(const char *token, const char *list[]) {
804 int i;
805 for(i = 0; list[i]; i++) {
806 if (streq(token, list[i]))
807 return true;
808 }
809 return false;
810}
811
812static bool reader_check_setting(const struct config_list *UNUSED(clist), void *config_data, const char *setting)
813{
814 struct s_reader *reader = config_data;
815 // These are written only when the reader is physical reader
816 static const char *hw_only_settings[] = {
817 "readnano", "resetcycle", "smargopatch", "sc8in1_dtrrts_patch", "boxid",
818 "fix9993", "rsakey", "ins7e", "ins7e11", "force_irdeto", "boxkey",
819 "atr", "detect", "nagra_read", "mhz", "cardmhz",
820#ifdef WITH_AZBOX
821 "mode",
822#endif
823 "deprecated", "ndsversion", "ratelimitecm", "ratelimitseconds",
824 "cooldown", "ecmunique", "srvidholdseconds",
825 0
826 };
827 // These are written only when the reader is network reader
828 static const char *network_only_settings[] = {
829 "user", "inactivitytimeout", "reconnecttimeout",
830 0
831 };
832 if (is_network_reader(reader)) {
833 if (in_list(setting, hw_only_settings))
834 return false;
835 } else {
836 if (in_list(setting, network_only_settings))
837 return false;
838 }
839
840 // These are not written in the config file
841 static const char *deprecated_settings[] = {
842 "cooldowndelay", "cooldowntime", "mg-encrypted",
843 0
844 };
845 if (in_list(setting, deprecated_settings))
846 return false;
847
848 // Special settings for NEWCAMD
849 static const char *newcamd_settings[] = {
850 "disableserverfilter", "connectoninit",
851 0
852 };
853 if (reader->typ != R_NEWCAMD && in_list(setting, newcamd_settings))
854 return false;
855
856#ifdef MODULE_CCCAM
857 // These are written only when the reader is CCCAM
858 static const char *cccam_settings[] = {
859 "cccversion", "cccmaxhops", "cccmindown", "cccwantemu", "ccckeepalive",
860 "cccreshare", "cccreconnect",
861 0
862 };
863 // Special settings for CCCAM
864 if (reader->typ != R_CCCAM) {
865 if (in_list(setting, cccam_settings))
866 return false;
867 } else if (streq(setting, "ccchop")) {
868 return false;
869 }
870#endif
871
872#ifdef MODULE_PANDORA
873 // Special settings for PANDORA
874 if (reader->typ != R_PANDORA && streq(setting, "pand_send_ecm"))
875 return false;
876#endif
877
878 return true; // Write the setting
879}
880
881
882void chk_reader(char *token, char *value, struct s_reader *rdr)
883{
884 if (config_list_parse(reader_opts, token, value, rdr))
885 return;
886 else if (token[0] != '#')
887 fprintf(stderr, "Warning: keyword '%s' in reader section not recognized\n", token);
888}
889
890void reader_set_defaults(struct s_reader *rdr) {
891 config_list_set_defaults(reader_opts, rdr);
892}
893
894int32_t init_readerdb(void)
895{
896 configured_readers = ll_create("configured_readers");
897
898 FILE *fp = open_config_file(cs_srvr);
899 if (!fp)
900 return 1;
901
902 int32_t tag = 0;
903 char *value, *token;
904
905 if (!cs_malloc(&token, MAXLINESIZE))
906 return 1;
907
908 struct s_reader *rdr;
909 if (!cs_malloc(&rdr, sizeof(struct s_reader))) {
910 free(token);
911 return 1;
912 }
913
914 ll_append(configured_readers, rdr);
915 while (fgets(token, MAXLINESIZE, fp)) {
916 int32_t l;
917 if ((l = strlen(trim(token))) < 3)
918 continue;
919 if ((token[0] == '[') && (token[l-1] == ']')) {
920 token[l-1] = 0;
921 tag = (!strcmp("reader", strtolower(token+1)));
922 if (rdr->label[0] && rdr->typ) {
923 struct s_reader *newreader;
924 if (cs_malloc(&newreader, sizeof(struct s_reader))) {
925 ll_append(configured_readers, newreader);
926 rdr = newreader;
927 }
928 }
929 reader_set_defaults(rdr);
930 continue;
931 }
932
933 if (!tag)
934 continue;
935 if (!(value=strchr(token, '=')))
936 continue;
937 *value++ ='\0';
938 chk_reader(trim(strtolower(token)), trim(value), rdr);
939 }
940 free(token);
941 LL_ITER itr = ll_iter_create(configured_readers);
942 while((rdr = ll_iter_next(&itr))) { //build active readers list
943 module_reader_set(rdr);
944 }
945 fclose(fp);
946 return(0);
947}
948
949void free_reader(struct s_reader *rdr)
950{
951 NULLFREE(rdr->emmfile);
952
953 struct s_ecmWhitelist *tmp;
954 struct s_ecmWhitelistIdent *tmpIdent;
955 struct s_ecmWhitelistLen *tmpLen;
956 for(tmp = rdr->ecmWhitelist; tmp; tmp=tmp->next){
957 for(tmpIdent = tmp->idents; tmpIdent; tmpIdent=tmpIdent->next){
958 for(tmpLen = tmpIdent->lengths; tmpLen; tmpLen=tmpLen->next){
959 add_garbage(tmpLen);
960 }
961 add_garbage(tmpIdent);
962 }
963 add_garbage(tmp);
964 }
965 rdr->ecmWhitelist = NULL;
966
967 struct s_ecmHeaderwhitelist *tmp1;
968 for(tmp1 = rdr->ecmHeaderwhitelist; tmp1; tmp1=tmp1->next){
969 add_garbage(tmp1);
970 }
971 rdr->ecmHeaderwhitelist = NULL;
972
973 clear_ftab(&rdr->ftab);
974
975#ifdef WITH_LB
976 if (rdr->lb_stat) {
977 cs_lock_destroy(&rdr->lb_stat_lock);
978 ll_destroy_data(rdr->lb_stat);
979 rdr->lb_stat = NULL;
980 }
981
982#endif
983 cs_clear_entitlement(rdr);
984 if (rdr->ll_entitlements) {
985 ll_destroy(rdr->ll_entitlements);
986 rdr->ll_entitlements = NULL;
987 }
988 add_garbage(rdr);
989}
990
991int32_t write_server(void)
992{
993 FILE *f = create_config_file(cs_srvr);
994 if (!f)
995 return 1;
996 struct s_reader *rdr;
997 LL_ITER itr = ll_iter_create(configured_readers);
998 while((rdr = ll_iter_next(&itr))) {
999 if (rdr->label[0]) {
1000 fprintf(f,"[reader]\n");
1001 config_list_apply_fixups(reader_opts, rdr);
1002 config_list_save_ex(f, reader_opts, rdr, cfg.http_full_cfg, reader_check_setting);
1003 fprintf(f, "\n");
1004 }
1005 }
1006 return flush_config_file(f, cs_srvr);
1007}
Note: See TracBrowser for help on using the repository browser.