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

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

Add emmreassembly reader setting.

Unfortunately r8441 causes too many errors for clients that do not
try to be smart (like dvbapi, see ticket #3204) so this commit reverts
r8441.

I can't see how to make non assembled and assembled emms to work both,
so I'm forced to introduce reader setting that turns off emm reassembly.

For the documentation:

emmreassembly = [0|1], Default: 1 (EMM reassembly is enabled).

emmreassembly = 0 (disable) should be set for viaccess and cryptoworks
readers if the client that you are using to send EMMs is reassembling
them instead of just sending them to OSCam for processing.

Two such clients are mgcamd and ACamd (over newcamd).

File size: 30.8 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_UINT8("emmreassembly" , OFS(emm_reassembly), 1 ),
790 DEF_OPT_INT8("deprecated" , OFS(deprecated), 0 ),
791 DEF_OPT_INT8("audisabled" , OFS(audisabled), 0 ),
792 DEF_OPT_FUNC("auprovid" , 0, auprovid_fn ),
793 DEF_OPT_INT8("ndsversion" , OFS(ndsversion), 0 ),
794 DEF_OPT_FUNC("ratelimitecm" , 0, ratelimitecm_fn ),
795 DEF_OPT_FUNC("ratelimitseconds" , 0, ratelimitseconds_fn ),
796 DEF_OPT_INT8("ecmunique" , OFS(ecmunique), 0 ),
797 DEF_OPT_INT8("srvidholdseconds" , OFS(srvidholdseconds), 0 ),
798 DEF_OPT_FUNC("cooldown" , 0, cooldown_fn ),
799 DEF_OPT_FUNC("cooldowndelay" , 0, cooldowndelay_fn ),
800 DEF_OPT_FUNC("cooldowntime" , 0, cooldowntime_fn ),
801 DEF_LAST_OPT
802};
803
804static inline bool in_list(const char *token, const char *list[]) {
805 int i;
806 for(i = 0; list[i]; i++) {
807 if (streq(token, list[i]))
808 return true;
809 }
810 return false;
811}
812
813static bool reader_check_setting(const struct config_list *UNUSED(clist), void *config_data, const char *setting)
814{
815 struct s_reader *reader = config_data;
816 // These are written only when the reader is physical reader
817 static const char *hw_only_settings[] = {
818 "readnano", "resetcycle", "smargopatch", "sc8in1_dtrrts_patch", "boxid",
819 "fix9993", "rsakey", "ins7e", "ins7e11", "force_irdeto", "boxkey",
820 "atr", "detect", "nagra_read", "mhz", "cardmhz", "emmreassembly",
821#ifdef WITH_AZBOX
822 "mode",
823#endif
824 "deprecated", "ndsversion", "ratelimitecm", "ratelimitseconds",
825 "cooldown", "ecmunique", "srvidholdseconds",
826 0
827 };
828 // These are written only when the reader is network reader
829 static const char *network_only_settings[] = {
830 "user", "inactivitytimeout", "reconnecttimeout",
831 0
832 };
833 if (is_network_reader(reader)) {
834 if (in_list(setting, hw_only_settings))
835 return false;
836 } else {
837 if (in_list(setting, network_only_settings))
838 return false;
839 }
840
841 // These are not written in the config file
842 static const char *deprecated_settings[] = {
843 "cooldowndelay", "cooldowntime", "mg-encrypted",
844 0
845 };
846 if (in_list(setting, deprecated_settings))
847 return false;
848
849 // Special settings for NEWCAMD
850 static const char *newcamd_settings[] = {
851 "disableserverfilter", "connectoninit",
852 0
853 };
854 if (reader->typ != R_NEWCAMD && in_list(setting, newcamd_settings))
855 return false;
856
857#ifdef MODULE_CCCAM
858 // These are written only when the reader is CCCAM
859 static const char *cccam_settings[] = {
860 "cccversion", "cccmaxhops", "cccmindown", "cccwantemu", "ccckeepalive",
861 "cccreshare", "cccreconnect",
862 0
863 };
864 // Special settings for CCCAM
865 if (reader->typ != R_CCCAM) {
866 if (in_list(setting, cccam_settings))
867 return false;
868 } else if (streq(setting, "ccchop")) {
869 return false;
870 }
871#endif
872
873#ifdef MODULE_PANDORA
874 // Special settings for PANDORA
875 if (reader->typ != R_PANDORA && streq(setting, "pand_send_ecm"))
876 return false;
877#endif
878
879 return true; // Write the setting
880}
881
882
883void chk_reader(char *token, char *value, struct s_reader *rdr)
884{
885 if (config_list_parse(reader_opts, token, value, rdr))
886 return;
887 else if (token[0] != '#')
888 fprintf(stderr, "Warning: keyword '%s' in reader section not recognized\n", token);
889}
890
891void reader_set_defaults(struct s_reader *rdr) {
892 config_list_set_defaults(reader_opts, rdr);
893}
894
895int32_t init_readerdb(void)
896{
897 configured_readers = ll_create("configured_readers");
898
899 FILE *fp = open_config_file(cs_srvr);
900 if (!fp)
901 return 1;
902
903 int32_t tag = 0;
904 char *value, *token;
905
906 if (!cs_malloc(&token, MAXLINESIZE))
907 return 1;
908
909 struct s_reader *rdr;
910 if (!cs_malloc(&rdr, sizeof(struct s_reader))) {
911 free(token);
912 return 1;
913 }
914
915 ll_append(configured_readers, rdr);
916 while (fgets(token, MAXLINESIZE, fp)) {
917 int32_t l;
918 if ((l = strlen(trim(token))) < 3)
919 continue;
920 if ((token[0] == '[') && (token[l-1] == ']')) {
921 token[l-1] = 0;
922 tag = (!strcmp("reader", strtolower(token+1)));
923 if (rdr->label[0] && rdr->typ) {
924 struct s_reader *newreader;
925 if (cs_malloc(&newreader, sizeof(struct s_reader))) {
926 ll_append(configured_readers, newreader);
927 rdr = newreader;
928 }
929 }
930 reader_set_defaults(rdr);
931 continue;
932 }
933
934 if (!tag)
935 continue;
936 if (!(value=strchr(token, '=')))
937 continue;
938 *value++ ='\0';
939 chk_reader(trim(strtolower(token)), trim(value), rdr);
940 }
941 free(token);
942 LL_ITER itr = ll_iter_create(configured_readers);
943 while((rdr = ll_iter_next(&itr))) { //build active readers list
944 module_reader_set(rdr);
945 }
946 fclose(fp);
947 return(0);
948}
949
950void free_reader(struct s_reader *rdr)
951{
952 NULLFREE(rdr->emmfile);
953
954 struct s_ecmWhitelist *tmp;
955 struct s_ecmWhitelistIdent *tmpIdent;
956 struct s_ecmWhitelistLen *tmpLen;
957 for(tmp = rdr->ecmWhitelist; tmp; tmp=tmp->next){
958 for(tmpIdent = tmp->idents; tmpIdent; tmpIdent=tmpIdent->next){
959 for(tmpLen = tmpIdent->lengths; tmpLen; tmpLen=tmpLen->next){
960 add_garbage(tmpLen);
961 }
962 add_garbage(tmpIdent);
963 }
964 add_garbage(tmp);
965 }
966 rdr->ecmWhitelist = NULL;
967
968 struct s_ecmHeaderwhitelist *tmp1;
969 for(tmp1 = rdr->ecmHeaderwhitelist; tmp1; tmp1=tmp1->next){
970 add_garbage(tmp1);
971 }
972 rdr->ecmHeaderwhitelist = NULL;
973
974 clear_ftab(&rdr->ftab);
975
976#ifdef WITH_LB
977 if (rdr->lb_stat) {
978 cs_lock_destroy(&rdr->lb_stat_lock);
979 ll_destroy_data(rdr->lb_stat);
980 rdr->lb_stat = NULL;
981 }
982
983#endif
984 cs_clear_entitlement(rdr);
985 if (rdr->ll_entitlements) {
986 ll_destroy(rdr->ll_entitlements);
987 rdr->ll_entitlements = NULL;
988 }
989 add_garbage(rdr);
990}
991
992int32_t free_readerdb(void) {
993 int count = 0;
994 struct s_reader *rdr;
995 LL_ITER itr = ll_iter_create(configured_readers);
996 while((rdr = ll_iter_next(&itr))) {
997 free_reader(rdr);
998 count++;
999 }
1000 cs_log("readerdb %d readers freed", count);
1001 ll_destroy(configured_readers);
1002 return count;
1003}
1004
1005int32_t write_server(void)
1006{
1007 FILE *f = create_config_file(cs_srvr);
1008 if (!f)
1009 return 1;
1010 struct s_reader *rdr;
1011 LL_ITER itr = ll_iter_create(configured_readers);
1012 while((rdr = ll_iter_next(&itr))) {
1013 if (rdr->label[0]) {
1014 fprintf(f,"[reader]\n");
1015 config_list_apply_fixups(reader_opts, rdr);
1016 config_list_save_ex(f, reader_opts, rdr, cfg.http_full_cfg, reader_check_setting);
1017 fprintf(f, "\n");
1018 }
1019 }
1020 return flush_config_file(f, cs_srvr);
1021}
Note: See TracBrowser for help on using the repository browser.