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

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

readers: Free configured readers on exit.

Make valgrind a little bit happier.

File size: 30.7 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 free_readerdb(void) {
992 int count = 0;
993 struct s_reader *rdr;
994 LL_ITER itr = ll_iter_create(configured_readers);
995 while((rdr = ll_iter_next(&itr))) {
996 free_reader(rdr);
997 count++;
998 }
999 cs_log("readerdb %d readers freed", count);
1000 ll_destroy(configured_readers);
1001 return count;
1002}
1003
1004int32_t write_server(void)
1005{
1006 FILE *f = create_config_file(cs_srvr);
1007 if (!f)
1008 return 1;
1009 struct s_reader *rdr;
1010 LL_ITER itr = ll_iter_create(configured_readers);
1011 while((rdr = ll_iter_next(&itr))) {
1012 if (rdr->label[0]) {
1013 fprintf(f,"[reader]\n");
1014 config_list_apply_fixups(reader_opts, rdr);
1015 config_list_save_ex(f, reader_opts, rdr, cfg.http_full_cfg, reader_check_setting);
1016 fprintf(f, "\n");
1017 }
1018 }
1019 return flush_config_file(f, cs_srvr);
1020}
Note: See TracBrowser for help on using the repository browser.