1 #define MODULE_LOG_PREFIX "config"
3 //FIXME Not checked on threadsafety yet; after checking please remove this line
7 #include "oscam-conf.h"
8 #include "oscam-conf-chk.h"
9 #include "oscam-config.h"
10 #include "oscam-files.h"
11 #include "oscam-garbage.h"
12 #include "oscam-lock.h"
13 #include "oscam-string.h"
14 #include "oscam-time.h"
16 extern uint16_t len4caid
[256];
18 #define cs_srid "oscam.srvid"
19 #define cs_ratelimit "oscam.ratelimit"
20 #define cs_trid "oscam.tiers"
21 #define cs_l4ca "oscam.guess"
22 #define cs_sidt "oscam.services"
23 #define cs_whitelist "oscam.whitelist"
24 #define cs_provid "oscam.provid"
25 #define cs_fakecws "oscam.fakecws"
26 #define cs_twin "oscam.twin"
28 uint32_t cfg_sidtab_generation
= 1;
30 extern char cs_confdir
[];
32 char *get_config_filename(char *dest
, size_t destlen
, const char *filename
)
34 // cs_confdir is always terminated with /
35 snprintf(dest
, destlen
, "%s%s", cs_confdir
, filename
);
39 int32_t write_services(void)
42 struct s_sidtab
*sidtab
= cfg
.sidtab
;
44 FILE *f
= create_config_file(cs_sidt
);
53 if(*ptr
== ' ') { *ptr
= '_'; }
56 fprintf(f
, "[%s]\n", sidtab
->label
);
57 fprintf_conf(f
, "caid", "%s", ""); // it should not have \n at the end
58 for(i
= 0; i
< sidtab
->num_caid
; i
++)
60 if(i
== 0) { fprintf(f
, "%04X", sidtab
->caid
[i
]); }
61 else { fprintf(f
, ",%04X", sidtab
->caid
[i
]); }
64 fprintf_conf(f
, "provid", "%s", ""); // it should not have \n at the end
65 for(i
= 0; i
< sidtab
->num_provid
; i
++)
67 if(i
== 0) { fprintf(f
, "%06X", sidtab
->provid
[i
]); }
68 else { fprintf(f
, ",%06X", sidtab
->provid
[i
]); }
71 fprintf_conf(f
, "srvid", "%s", ""); // it should not have \n at the end
72 for(i
= 0; i
< sidtab
->num_srvid
; i
++)
74 if(i
== 0) { fprintf(f
, "%04X", sidtab
->srvid
[i
]); }
75 else { fprintf(f
, ",%04X", sidtab
->srvid
[i
]); }
78 sidtab
= sidtab
->next
;
81 return flush_config_file(f
, cs_sidt
);
84 void free_sidtab(struct s_sidtab
*ptr
)
87 add_garbage(ptr
->caid
); //no need to check on NULL first, freeing NULL doesnt do anything
88 add_garbage(ptr
->provid
);
89 add_garbage(ptr
->srvid
);
93 static void chk_entry4sidtab(char *value
, struct s_sidtab
*sidtab
, int32_t what
)
96 char *ptr
, *saveptr1
= NULL
;
97 uint16_t *slist
= (uint16_t *) 0;
98 uint32_t *llist
= (uint32_t *) 0;
100 char buf
[strlen(value
) + 1];
101 cs_strncpy(buf
, value
, sizeof(buf
));
102 b
= (what
== 1) ? sizeof(uint32_t) : sizeof(uint16_t);
103 for(i
= 0, ptr
= strtok_r(value
, ",", &saveptr1
); ptr
; ptr
= strtok_r(NULL
, ",", &saveptr1
))
109 if(b
== sizeof(uint16_t))
111 if(!cs_malloc(&slist
, i
* sizeof(uint16_t))) { return; }
115 if(!cs_malloc(&llist
, i
* sizeof(uint32_t))) { return; }
117 cs_strncpy(value
, buf
, sizeof(buf
));
118 for(i
= 0, ptr
= strtok_r(value
, ",", &saveptr1
); ptr
; ptr
= strtok_r(NULL
, ",", &saveptr1
))
121 if(errno
) { continue; }
122 if(b
== sizeof(uint16_t))
123 { slist
[i
++] = (uint16_t) caid
; }
125 { llist
[i
++] = caid
; }
130 add_garbage(sidtab
->caid
);
131 sidtab
->caid
= slist
;
132 sidtab
->num_caid
= i
;
135 add_garbage(sidtab
->provid
);
136 sidtab
->provid
= llist
;
137 sidtab
->num_provid
= i
;
140 add_garbage(sidtab
->srvid
);
141 sidtab
->srvid
= slist
;
142 sidtab
->num_srvid
= i
;
147 void chk_sidtab(char *token
, char *value
, struct s_sidtab
*sidtab
)
149 if(!strcmp(token
, "caid"))
151 chk_entry4sidtab(value
, sidtab
, 0);
154 if(!strcmp(token
, "provid"))
156 chk_entry4sidtab(value
, sidtab
, 1);
159 if(!strcmp(token
, "ident"))
161 chk_entry4sidtab(value
, sidtab
, 1);
164 if(!strcmp(token
, "srvid"))
166 chk_entry4sidtab(value
, sidtab
, 2);
170 { fprintf(stderr
, "Warning: keyword '%s' in sidtab section not recognized\n", token
); }
173 void init_free_sidtab(void)
175 struct s_sidtab
*nxt
, *ptr
= cfg
.sidtab
;
183 ++cfg_sidtab_generation
;
186 //#define DEBUG_SIDTAB 1
188 static void show_sidtab(struct s_sidtab
*sidtab
)
190 for(; sidtab
; sidtab
= sidtab
->next
)
195 cs_log("label=%s", sidtab
->label
);
196 snprintf(buf
, sizeof(buf
), "caid(%d)=", sidtab
->num_caid
);
197 for(i
= 0; i
< sidtab
->num_caid
; i
++)
198 { snprintf(buf
+ strlen(buf
), 1024 - (buf
- saveptr
), "%04X ", sidtab
->caid
[i
]); }
200 snprintf(buf
, sizeof(buf
), "provider(%d)=", sidtab
->num_provid
);
201 for(i
= 0; i
< sidtab
->num_provid
; i
++)
202 { snprintf(buf
+ strlen(buf
), 1024 - (buf
- saveptr
), "%08X ", sidtab
->provid
[i
]); }
204 snprintf(buf
, sizeof(buf
), "services(%d)=", sidtab
->num_srvid
);
205 for(i
= 0; i
< sidtab
->num_srvid
; i
++)
206 { snprintf(buf
+ strlen(buf
), 1024 - (buf
- saveptr
), "%04X ", sidtab
->srvid
[i
]); }
211 static void show_sidtab(struct s_sidtab
*UNUSED(sidtab
)) { }
214 int32_t init_sidtab(void)
216 FILE *fp
= open_config_file(cs_sidt
);
220 int32_t nr
, nro
, nrr
;
222 if(!cs_malloc(&token
, MAXLINESIZE
))
224 struct s_sidtab
*ptr
;
225 struct s_sidtab
*sidtab
= (struct s_sidtab
*)0;
227 for(nro
= 0, ptr
= cfg
.sidtab
; ptr
; nro
++)
229 struct s_sidtab
*ptr_next
;
230 ptr_next
= ptr
->next
;
236 while(fgets(token
, MAXLINESIZE
, fp
))
239 if((l
= strlen(trim(token
))) < 3) { continue; }
240 if((token
[0] == '[') && (token
[l
- 1] == ']'))
245 fprintf(stderr
, "Warning: Service No.%d - '%s' ignored. Max allowed Services %d\n", nr
, strtolower(token
+ 1), MAX_SIDBITS
);
251 if(!cs_malloc(&ptr
, sizeof(struct s_sidtab
)))
257 { sidtab
->next
= ptr
; }
259 { cfg
.sidtab
= ptr
; }
262 cs_strncpy(sidtab
->label
, strtolower(token
+ 1), sizeof(sidtab
->label
));
266 if(!sidtab
) { continue; }
267 if(!(value
= strchr(token
, '='))) { continue; }
269 chk_sidtab(trim(strtolower(token
)), trim(strtolower(value
)), sidtab
);
274 show_sidtab(cfg
.sidtab
);
275 ++cfg_sidtab_generation
;
276 cs_log("services reloaded: %d services freed, %d services loaded, rejected %d", nro
, nr
, nrr
);
280 int32_t init_provid(void)
282 FILE *fp
= open_config_file(cs_provid
);
287 char *payload
, *saveptr1
= NULL
, *token
;
288 if(!cs_malloc(&token
, MAXLINESIZE
))
290 struct s_provid
*provid_ptr
= NULL
;
291 struct s_provid
*new_cfg_provid
= NULL
, *last_provid
;
294 while(fgets(token
, MAXLINESIZE
, fp
))
297 struct s_provid
*new_provid
= NULL
;
302 if(tmp
[0] == '#') { continue; }
303 if((l
= strlen(tmp
)) < 11) { continue; }
304 if(!(payload
= strchr(token
, '|'))) { continue; }
308 if(!cs_malloc(&new_provid
, sizeof(struct s_provid
)))
315 new_provid
->nprovid
= 0;
316 for(i
= 0, ptr1
= strtok_r(token
, ":@", &saveptr1
); ptr1
; ptr1
= strtok_r(NULL
, ":@", &saveptr1
), i
++)
320 new_provid
->caid
= a2i(ptr1
, 3);
324 new_provid
->nprovid
++;
327 if(!cs_malloc(&new_provid
->provid
, sizeof(uint32_t) * new_provid
->nprovid
))
329 NULLFREE(new_provid
);
335 ptr1
= token
+ strlen(token
) + 1;
336 for(i
= 0; i
< new_provid
->nprovid
; i
++)
338 new_provid
->provid
[i
] = a2i(ptr1
, 3);
340 ptr1
= ptr1
+ strlen(ptr1
) + 1;
343 for(i
= 0, ptr1
= strtok_r(payload
, "|", &saveptr1
); ptr1
; ptr1
= strtok_r(NULL
, "|", &saveptr1
), i
++)
348 cs_strncpy(new_provid
->prov
, trim(ptr1
), sizeof(new_provid
->prov
));
351 cs_strncpy(new_provid
->sat
, trim(ptr1
), sizeof(new_provid
->sat
));
354 cs_strncpy(new_provid
->lang
, trim(ptr1
), sizeof(new_provid
->lang
));
359 if(strlen(new_provid
->prov
) == 0)
361 NULLFREE(new_provid
->provid
);
362 NULLFREE(new_provid
);
370 provid_ptr
->next
= new_provid
;
374 new_cfg_provid
= new_provid
;
376 provid_ptr
= new_provid
;
383 { cs_log("%d provid's loaded", nr
); }
385 if(new_cfg_provid
== NULL
)
387 if(!cs_malloc(&new_cfg_provid
, sizeof(struct s_provid
)))
393 cs_writelock(__func__
, &config_lock
);
395 //this allows reloading of provids, so cleanup of old data is needed:
396 last_provid
= cfg
.provid
; //old data
397 cfg
.provid
= new_cfg_provid
; //assign after loading, so everything is in memory
399 cs_writeunlock(__func__
, &config_lock
);
402 for(cl
= first_client
->next
; cl
; cl
= cl
->next
)
403 { cl
->last_providptr
= NULL
; }
405 struct s_provid
*ptr
, *nptr
;
410 while(ptr
) //cleanup old data:
412 add_garbage(ptr
->provid
);
422 int32_t init_srvid(void)
424 int8_t new_syntax
= 1;
425 FILE *fp
= open_config_file("oscam.srvid2");
428 fp
= open_config_file(cs_srid
);
437 fp
= create_config_file("oscam.srvid2");
440 flush_config_file(fp
, "oscam.srvid2");
446 int32_t nr
= 0, i
, j
;
447 char *payload
, *saveptr1
= NULL
, *saveptr2
= NULL
, *token
;
449 if(!cs_malloc(&token
, MAXLINESIZE
))
451 struct s_srvid
*srvid
= NULL
, *new_cfg_srvid
[16], *last_srvid
[16];
452 // A cache for strings within srvids. A checksum is calculated which is the start point in the array (some kind of primitive hash algo).
453 // From this point, a sequential search is done. This greatly reduces the amount of string comparisons.
454 const char **stringcache
[1024];
455 int32_t allocated
[1024] = { 0 };
456 int32_t used
[1024] = { 0 };
460 memset(last_srvid
, 0, sizeof(last_srvid
));
461 memset(new_cfg_srvid
, 0, sizeof(new_cfg_srvid
));
463 while(fgets(token
, MAXLINESIZE
, fp
))
465 int32_t l
, len
= 0, len2
, srvidtmp
;
468 char *srvidasc
, *prov
;
471 if(tmp
[0] == '#') { continue; }
472 if((l
= strlen(tmp
)) < 6) { continue; }
473 if(!(srvidasc
= strchr(token
, ':'))) { continue; }
474 if(!(payload
= strchr(token
, '|'))) { continue; }
477 if(!cs_malloc(&srvid
, sizeof(struct s_srvid
)))
486 int32_t offset
[4] = { -1, -1, -1, -1 };
487 char *ptr1
= NULL
, *ptr2
= NULL
;
488 const char *searchptr
[4] = { NULL
, NULL
, NULL
, NULL
};
489 const char **ptrs
[4] = { &srvid
->prov
, &srvid
->name
, &srvid
->type
, &srvid
->desc
};
490 uint32_t max_payload_length
= MAXLINESIZE
- (payload
- token
);
494 ptrs
[0] = &srvid
->name
;
495 ptrs
[1] = &srvid
->type
;
496 ptrs
[2] = &srvid
->desc
;
497 ptrs
[3] = &srvid
->prov
;
500 // allow empty strings as "||"
501 if(payload
[0] == '|' && (strlen(payload
)+2 < max_payload_length
))
503 memmove(payload
+1, payload
, strlen(payload
)+1);
507 for(k
=1; ((k
< max_payload_length
) && (payload
[k
] != '\0')); k
++)
509 if(payload
[k
-1] == '|' && payload
[k
] == '|')
511 if(strlen(payload
+k
)+2 < max_payload_length
-k
)
513 memmove(payload
+k
+1, payload
+k
, strlen(payload
+k
)+1);
523 for(i
= 0, ptr1
= strtok_r(payload
, "|", &saveptr1
); ptr1
&& (i
< 4) ; ptr1
= strtok_r(NULL
, "|", &saveptr1
), ++i
)
525 // check if string is in cache
528 for(j
= 0; j
< len2
; ++j
) { pos
+= (uint8_t)ptr1
[j
]; }
530 for(j
= 0; j
< used
[pos
]; ++j
)
532 if(!strcmp(stringcache
[pos
][j
], ptr1
))
534 searchptr
[i
] = stringcache
[pos
][j
];
538 if(searchptr
[i
]) { continue; }
541 cs_strncpy(tmptxt
+ len
, trim(ptr1
), sizeof(tmptxt
) - len
);
542 len
+= strlen(ptr1
) + 1;
546 if(len
> 0 && !cs_malloc(&tmpptr
, len
))
549 srvid
->data
= tmpptr
;
550 if(len
> 0) { memcpy(tmpptr
, tmptxt
, len
); }
552 for(i
= 0; i
< 4; i
++)
556 *ptrs
[i
] = searchptr
[i
];
561 *ptrs
[i
] = tmpptr
+ offset
[i
];
562 // store string in stringcache
566 for(j
= 0; j
< len2
; ++j
) { pos
+= (uint8_t)tmp
[j
]; }
568 if(used
[pos
] >= allocated
[pos
])
570 if(allocated
[pos
] == 0)
572 if(!cs_malloc(&stringcache
[pos
], 16 * sizeof(char *)))
577 if(!cs_realloc(&stringcache
[pos
], (allocated
[pos
] + 16) * sizeof(char *)))
580 allocated
[pos
] += 16;
582 stringcache
[pos
][used
[pos
]] = tmp
;
589 { srvidtmp
= dyn_word_atob(token
) & 0xFFFF; }
591 { srvidtmp
= dyn_word_atob(srvidasc
) & 0xFFFF; }
601 srvid
->srvid
= srvidtmp
;
605 for(i
= 0, ptr1
= strtok_r(new_syntax
? srvidasc
: token
, ",", &saveptr1
); (ptr1
); ptr1
= strtok_r(NULL
, ",", &saveptr1
), i
++)
610 if(!cs_malloc(&srvid
->caid
, sizeof(struct s_srvid_caid
) * srvid
->ncaid
))
617 ptr1
= new_syntax
? srvidasc
: token
;
618 for(i
= 0; i
< srvid
->ncaid
; i
++)
620 prov
= strchr(ptr1
,'@');
622 srvid
->caid
[i
].nprovid
= 0;
628 for(j
= 0, ptr2
= strtok_r(prov
+1, "@", &saveptr2
); (ptr2
); ptr2
= strtok_r(NULL
, "@", &saveptr2
), j
++)
630 srvid
->caid
[i
].nprovid
++;
633 if(!cs_malloc(&srvid
->caid
[i
].provid
, sizeof(uint32_t) * srvid
->caid
[i
].nprovid
))
635 for(j
= 0; j
< i
; j
++)
636 { NULLFREE(srvid
->caid
[j
].provid
); }
637 NULLFREE(srvid
->caid
);
644 for(j
= 0; j
< srvid
->caid
[i
].nprovid
; j
++)
646 srvid
->caid
[i
].provid
[j
] = dyn_word_atob(ptr2
) & 0xFFFFFF;
647 ptr2
= ptr2
+ strlen(ptr2
) + 1;
658 srvid
->caid
[i
].caid
= dyn_word_atob(ptr1
) & 0xFFFF;
662 { ptr1
= ptr1
+ strlen(ptr1
) + 1; }
667 if(new_cfg_srvid
[srvid
->srvid
>> 12])
668 { last_srvid
[srvid
->srvid
>> 12]->next
= srvid
; }
670 { new_cfg_srvid
[srvid
->srvid
>> 12] = srvid
; }
672 last_srvid
[srvid
->srvid
>> 12] = srvid
;
674 for(i
= 0; i
< 1024; ++i
)
676 if(allocated
[i
] > 0) { NULLFREE(stringcache
[i
]); }
681 int64_t load_time
= comp_timeb(&te
, &ts
);
686 cs_log("%d service-id's loaded in %"PRId64
" ms", nr
, load_time
);
689 cs_log("WARNING: You risk high CPU load and high ECM times with more than 2000 service-id's!");
690 cs_log("HINT: --> use optimized lists from http://www.streamboard.tv/wiki/Srvid");
694 cs_writelock(__func__
, &config_lock
);
695 //this allows reloading of srvids, so cleanup of old data is needed:
696 memcpy(last_srvid
, cfg
.srvid
, sizeof(last_srvid
)); //old data
697 memcpy(cfg
.srvid
, new_cfg_srvid
, sizeof(last_srvid
)); //assign after loading, so everything is in memory
699 cs_writeunlock(__func__
, &config_lock
);
702 for(cl
= first_client
->next
; cl
; cl
= cl
->next
)
703 { cl
->last_srvidptr
= NULL
; }
705 struct s_srvid
*ptr
, *nptr
;
707 for(i
= 0; i
< 16; i
++)
710 while(ptr
) //cleanup old data:
712 for(j
= 0; j
< ptr
->ncaid
; j
++)
713 { add_garbage(ptr
->caid
[j
].provid
); }
714 add_garbage(ptr
->caid
);
715 add_garbage(ptr
->data
);
725 int32_t init_fakecws(void)
727 int32_t nr
= 0, i
, j
, idx
;
728 uint32_t alloccount
[0x100], count
[0x100], tmp
, max_compares
= 0, average_compares
= 0;
729 char *token
, cw_string
[64];
730 uint8_t cw
[16], wrong_checksum
, c
, have_fakecw
= 0;
733 memset(alloccount
, 0, sizeof(count
));
734 memset(count
, 0, sizeof(alloccount
));
736 cs_writelock(__func__
, &config_lock
);
737 for(i
=0; i
<0x100; i
++)
739 cfg
.fakecws
[i
].count
= 0;
740 NULLFREE(cfg
.fakecws
[i
].data
);
742 cs_writeunlock(__func__
, &config_lock
);
744 fp
= open_config_file(cs_fakecws
);
748 if(!cs_malloc(&token
, MAXLINESIZE
))
751 while(fgets(token
, MAXLINESIZE
, fp
))
753 if(sscanf(token
, " %62s ", cw_string
) == 1)
755 if(strlen(cw_string
) == 32)
757 if(cs_atob(cw
, cw_string
, 16) == 16)
761 for(i
= 0; i
< 16; i
+= 4)
763 c
= ((cw
[i
] + cw
[i
+ 1] + cw
[i
+ 2]) & 0xff);
772 cs_log("skipping fake cw %s because of wrong checksum!", cw_string
);
776 idx
= ((cw
[0]&0xF)<<4) | (cw
[8]&0xF);
783 cs_log("skipping fake cw %s because it contains invalid characters!", cw_string
);
788 cs_log("skipping fake cw %s because of wrong length (%u != 32)!", cw_string
, (uint32_t)strlen(cw_string
));
800 for(i
=0; i
<0x100; i
++)
802 if(alloccount
[i
] && !cs_malloc(&cfg
.fakecws
[i
].data
, sizeof(struct s_cw
)*alloccount
[i
]))
808 fseek(fp
, 0, SEEK_SET
);
810 while(fgets(token
, MAXLINESIZE
, fp
))
812 if(sscanf(token
, " %62s ", cw_string
) == 1)
814 if(strlen(cw_string
) == 32)
816 if(cs_atob(cw
, cw_string
, 16) == 16)
820 for(i
= 0; i
< 16; i
+= 4)
822 c
= ((cw
[i
] + cw
[i
+ 1] + cw
[i
+ 2]) & 0xff);
831 idx
= ((cw
[0]&0xF)<<4) | (cw
[8]&0xF);
833 if(count
[idx
] < alloccount
[idx
])
835 memcpy(cfg
.fakecws
[idx
].data
[count
[idx
]].cw
, cw
, 16);
849 { cs_log("%d fakecws's loaded", nr
); }
852 cs_writelock(__func__
, &config_lock
);
853 for(i
=0; i
<0x100; i
++)
855 cfg
.fakecws
[i
].count
= count
[i
];
857 cs_writeunlock(__func__
, &config_lock
);
860 for(i
=0; i
<0x100; i
++)
862 if(count
[i
] > max_compares
)
863 { max_compares
= count
[i
]; }
866 for(i
=0; i
<(0x100-1); i
++) {
867 for(j
=i
+1; j
<0x100; j
++) {
868 if(count
[j
] < count
[i
]) {
875 average_compares
= ((count
[0x100/2] + count
[0x100/2 - 1]) / 2);
878 cs_log("max %d fakecw compares required, on average: %d compares", max_compares
, average_compares
);
883 static struct s_rlimit
*ratelimit_read_int(void)
885 FILE *fp
= open_config_file(cs_ratelimit
);
888 char token
[1024], str1
[1024];
889 int32_t i
, ret
, count
= 0;
890 struct s_rlimit
*new_rlimit
= NULL
, *entry
, *last
= NULL
;
893 while(fgets(token
, sizeof(token
), fp
))
896 if(strlen(token
) <= 1) { continue; }
897 if(token
[0] == '#' || token
[0] == '/') { continue; }
898 if(strlen(token
) > 1024) { continue; }
900 for(i
= 0; i
< (int)strlen(token
); i
++)
902 if((token
[i
] == ':' || token
[i
] == ' ') && token
[i
+ 1] == ':')
904 memmove(token
+ i
+ 2, token
+ i
+ 1, strlen(token
) - i
+ 1);
907 if(token
[i
] == '#' || token
[i
] == '/')
914 uint32_t caid
= 0, provid
= 0, srvid
= 0, chid
= 0, ratelimitecm
= 0, ratelimittime
= 0, srvidholdtime
= 0;
915 memset(str1
, 0, sizeof(str1
));
917 ret
= sscanf(token
, "%4x:%6x:%4x:%4x:%d:%d:%d:%1023s", &caid
, &provid
, &srvid
, &chid
, &ratelimitecm
, &ratelimittime
, &srvidholdtime
, str1
);
918 if(ret
< 1) { continue; }
919 strncat(str1
, ",", sizeof(str1
) - strlen(str1
) - 1);
920 if(!cs_malloc(&entry
, sizeof(struct s_rlimit
)))
927 if (ratelimittime
< 60) ratelimittime
*=1000;
928 if (srvidholdtime
< 60) srvidholdtime
*=1000;
929 entry
->rl
.caid
= caid
;
930 entry
->rl
.provid
= provid
;
931 entry
->rl
.srvid
= srvid
;
932 entry
->rl
.chid
= chid
;
933 entry
->rl
.ratelimitecm
= ratelimitecm
;
934 entry
->rl
.ratelimittime
= ratelimittime
;
935 entry
->rl
.srvidholdtime
= srvidholdtime
;
937 cs_log_dbg(D_TRACE
, "ratelimit: %04X@%06X:%04X:%04X:%d:%d:%d", entry
->rl
.caid
, entry
->rl
.provid
, entry
->rl
.srvid
, entry
->rl
.chid
,
938 entry
->rl
.ratelimitecm
, entry
->rl
.ratelimittime
, entry
->rl
.srvidholdtime
);
953 { cs_log("%d entries read from %s", count
, cs_ratelimit
); }
960 void ratelimit_read(void)
963 struct s_rlimit
*entry
, *old_list
;
965 old_list
= cfg
.ratelimit_list
;
966 cfg
.ratelimit_list
= ratelimit_read_int();
970 entry
= old_list
->next
;
976 struct ecmrl
get_ratelimit(ECM_REQUEST
*er
)
980 memset(&tmp
, 0, sizeof(tmp
));
981 if(!cfg
.ratelimit_list
) { return tmp
; }
982 struct s_rlimit
*entry
= cfg
.ratelimit_list
;
985 if(entry
->rl
.caid
== er
->caid
&& entry
->rl
.provid
== er
->prid
&& entry
->rl
.srvid
== er
->srvid
&& (!entry
->rl
.chid
|| entry
->rl
.chid
== er
->chid
))
992 if(entry
) { tmp
= entry
->rl
; }
997 int32_t init_tierid(void)
999 FILE *fp
= open_config_file(cs_trid
);
1004 char *payload
, *saveptr1
= NULL
, *token
;
1005 if(!cs_malloc(&token
, MAXLINESIZE
))
1007 static struct s_tierid
*tierid
= NULL
, *new_cfg_tierid
= NULL
;
1010 while(fgets(token
, MAXLINESIZE
, fp
))
1015 char *tmp
, *tieridasc
;
1018 if(tmp
[0] == '#') { continue; }
1019 if((l
= strlen(tmp
)) < 6) { continue; }
1020 if(!(payload
= strchr(token
, '|'))) { continue; }
1021 if(!(tieridasc
= strchr(token
, ':'))) { continue; }
1024 if(!cs_malloc(&ptr
, sizeof(struct s_tierid
)))
1031 { tierid
->next
= ptr
; }
1033 { new_cfg_tierid
= ptr
; }
1038 char *ptr1
= strtok_r(payload
, "|", &saveptr1
);
1040 { cs_strncpy(tierid
->name
, trim(ptr1
), sizeof(tierid
->name
)); }
1042 *tieridasc
++ = '\0';
1043 tierid
->tierid
= dyn_word_atob(tieridasc
);
1044 //printf("tierid %s - %d\n",tieridasc,tierid->tierid );
1047 for(i
= 0, ptr1
= strtok_r(token
, ",", &saveptr1
); (ptr1
) && (i
< 10) ; ptr1
= strtok_r(NULL
, ",", &saveptr1
), i
++)
1049 tierid
->caid
[i
] = dyn_word_atob(ptr1
);
1050 tierid
->ncaid
= i
+ 1;
1051 // cs_log("ld caid: %04X tierid: %04X name: %s",tierid->caid[i],tierid->tierid,tierid->name);
1058 { cs_log("%d tier-id's loaded", nr
); }
1059 cs_writelock(__func__
, &config_lock
);
1061 tierid
= cfg
.tierid
;
1062 cfg
.tierid
= new_cfg_tierid
;
1063 struct s_tierid
*ptr
;
1070 cs_writeunlock(__func__
, &config_lock
);
1075 int32_t match_whitelist(ECM_REQUEST
*er
, struct s_global_whitelist
*entry
)
1077 return ((!entry
->caid
|| entry
->caid
== er
->caid
)
1078 && (!entry
->provid
|| entry
->provid
== er
->prid
)
1079 && (!entry
->srvid
|| entry
->srvid
== er
->srvid
)
1080 && (!entry
->chid
|| entry
->chid
== er
->chid
)
1081 && (!entry
->pid
|| entry
->pid
== er
->pid
)
1082 && (!entry
->ecmlen
|| entry
->ecmlen
== er
->ecmlen
));
1085 int32_t chk_global_whitelist(ECM_REQUEST
*er
, uint32_t *line
)
1088 if(!cfg
.global_whitelist
)
1091 struct s_global_whitelist
*entry
;
1094 if(cfg
.global_whitelist_use_m
)
1096 entry
= cfg
.global_whitelist
;
1099 if(entry
->type
== 'm')
1101 if(match_whitelist(er
, entry
))
1103 er
->caid
= entry
->mapcaid
;
1104 er
->prid
= entry
->mapprovid
;
1105 cs_log_dbg(D_TRACE
, "whitelist: mapped %04X@%06X to %04X@%06X", er
->caid
, er
->prid
, entry
->mapcaid
, entry
->mapprovid
);
1109 entry
= entry
->next
;
1113 if(cfg
.global_whitelist_use_l
) //Check caid/prov/srvid etc matching, except ecm-len:
1115 entry
= cfg
.global_whitelist
;
1116 int8_t caidprov_matches
= 0;
1119 if(entry
->type
== 'l')
1121 if(match_whitelist(er
, entry
))
1123 *line
= entry
->line
;
1126 if((!entry
->caid
|| entry
->caid
== er
->caid
)
1127 && (!entry
->provid
|| entry
->provid
== er
->prid
)
1128 && (!entry
->srvid
|| entry
->srvid
== er
->srvid
)
1129 && (!entry
->chid
|| entry
->chid
== er
->chid
)
1130 && (!entry
->pid
|| entry
->pid
== er
->pid
))
1132 caidprov_matches
= 1;
1133 *line
= entry
->line
;
1136 entry
= entry
->next
;
1138 if(caidprov_matches
) //...but not ecm-len!
1142 entry
= cfg
.global_whitelist
;
1145 if(match_whitelist(er
, entry
))
1147 *line
= entry
->line
;
1148 if(entry
->type
== 'w')
1150 else if(entry
->type
== 'i')
1153 entry
= entry
->next
;
1160 //w:caid:prov:srvid:pid:chid:ecmlen
1162 //i:caid:prov:srvid:pid:chid:ecmlen
1163 //ECM len check - Entry:
1164 //l:caid:prov:srvid:pid:chid:ecmlen
1167 //m:caid:prov:srvid:pid:chid:ecmlen caidto:provto
1169 static struct s_global_whitelist
*global_whitelist_read_int(void)
1171 FILE *fp
= open_config_file(cs_whitelist
);
1175 char token
[1024], str1
[1024];
1177 int32_t i
, ret
, count
= 0;
1178 struct s_global_whitelist
*new_whitelist
= NULL
, *entry
, *last
= NULL
;
1181 cfg
.global_whitelist_use_l
= 0;
1182 cfg
.global_whitelist_use_m
= 0;
1184 while(fgets(token
, sizeof(token
), fp
))
1187 if(strlen(token
) <= 1) { continue; }
1188 if(token
[0] == '#' || token
[0] == '/') { continue; }
1189 if(strlen(token
) > 1024) { continue; }
1191 for(i
= 0; i
< (int)strlen(token
); i
++)
1193 if((token
[i
] == ':' || token
[i
] == ' ') && token
[i
+ 1] == ':')
1195 memmove(token
+ i
+ 2, token
+ i
+ 1, strlen(token
) - i
+ 1);
1198 if(token
[i
] == '#' || token
[i
] == '/')
1206 uint32_t caid
= 0, provid
= 0, srvid
= 0, pid
= 0, chid
= 0, ecmlen
= 0, mapcaid
= 0, mapprovid
= 0;
1207 memset(str1
, 0, sizeof(str1
));
1209 ret
= sscanf(token
, "%c:%4x:%6x:%4x:%4x:%4x:%1023s", &type
, &caid
, &provid
, &srvid
, &pid
, &chid
, str1
);
1211 type
= tolower(type
);
1217 if(ret
< 1 || (type
!= 'w' && type
!= 'i' && type
!= 'l' && type
!= 'm'))
1222 char *p
= strstr(token
+ 4, " ");
1223 if(!p
|| sscanf(p
+ 1, "%4x:%6x", &mapcaid
, &mapprovid
) < 2)
1225 cs_log_dbg(D_TRACE
, "whitelist: wrong mapping: %s", token
);
1229 cfg
.global_whitelist_use_m
= 1;
1231 strncat(str1
, ",", sizeof(str1
) - strlen(str1
) - 1);
1232 char *p
= str1
, *p2
= str1
;
1239 sscanf(p2
, "%4x", &ecmlen
);
1241 if(!cs_malloc(&entry
, sizeof(struct s_global_whitelist
)))
1244 return new_whitelist
;
1251 entry
->provid
= provid
;
1252 entry
->srvid
= srvid
;
1255 entry
->ecmlen
= ecmlen
;
1256 entry
->mapcaid
= mapcaid
;
1257 entry
->mapprovid
= mapprovid
;
1258 if(entry
->type
== 'l')
1259 { cfg
.global_whitelist_use_l
= 1; }
1263 "whitelist: %c: %04X@%06X:%04X:%04X:%04X:%02X map to %04X@%06X", entry
->type
, entry
->caid
, entry
->provid
, entry
->srvid
, entry
->pid
, entry
->chid
, entry
->ecmlen
, entry
->mapcaid
, entry
->mapprovid
);
1266 "whitelist: %c: %04X@%06X:%04X:%04X:%04X:%02X", entry
->type
, entry
->caid
, entry
->provid
, entry
->srvid
, entry
->pid
, entry
->chid
, entry
->ecmlen
);
1270 new_whitelist
= entry
;
1271 last
= new_whitelist
;
1286 { cs_log("%d entries read from %s", count
, cs_whitelist
); }
1290 return new_whitelist
;
1293 void global_whitelist_read(void)
1296 struct s_global_whitelist
*entry
, *old_list
;
1298 old_list
= cfg
.global_whitelist
;
1299 cfg
.global_whitelist
= global_whitelist_read_int();
1303 entry
= old_list
->next
;
1309 void init_len4caid(void)
1311 FILE *fp
= open_config_file(cs_l4ca
);
1316 char *value
, *token
;
1318 if(!cs_malloc(&token
, MAXLINESIZE
))
1321 memset(len4caid
, 0, sizeof(uint16_t) << 8);
1322 for(nr
= 0; fgets(token
, MAXLINESIZE
, fp
);)
1326 if(!(value
= strchr(token
, ':')))
1329 if((ptr
= strchr(value
, '#')))
1331 if(strlen(trim(token
)) != 2)
1333 if(strlen(trim(value
)) != 4)
1335 if((i
= byte_atob(token
)) < 0)
1337 if((c
= word_atob(value
)) < 0)
1345 { cs_log("%d lengths for caid guessing loaded", nr
); }
1349 #ifdef MODULE_SERIAL
1350 static struct s_twin
*twin_read_int(void)
1352 FILE *fp
= open_config_file(cs_twin
);
1355 char token
[1024], str1
[1024];
1356 int32_t i
, ret
, count
= 0;
1357 struct s_twin
*new_twin
= NULL
, *entry
, *last
= NULL
;
1360 while(fgets(token
, sizeof(token
), fp
))
1363 if(strlen(token
) <= 1) { continue; }
1364 if(token
[0] == '#' || token
[0] == '/') { continue; }
1365 if(strlen(token
) > 1024) { continue; }
1367 for(i
= 0; i
< (int)strlen(token
); i
++)
1369 if((token
[i
] == ':' || token
[i
] == ' ') && token
[i
+ 1] == ':')
1371 memmove(token
+ i
+ 2, token
+ i
+ 1, strlen(token
) - i
+ 1);
1374 if(token
[i
] == '#' || token
[i
] == '/' || token
[i
] == '"')
1381 uint32_t caid
= 0, provid
= 0, srvid
= 0, deg
= 0, freq
= 0;
1382 // char hdeg[4], hfreq[4], hsrvid[4];
1383 memset(str1
, 0, sizeof(str1
));
1385 ret
= sscanf(token
, "%4x:%6x:%d:%d:%d", &caid
, &provid
, °
, &freq
, &srvid
);
1386 if(ret
< 1) { continue; }
1387 // snprintf(hdeg, 4, "%x", deg);
1388 // sscanf(hdeg, "%4x", °);
1389 // snprintf(hfreq, 4, "%x", freq);
1390 // sscanf(hfreq, "%4x", &freq);
1391 // snprintf(hsrvid, 4, "%x", srvid);
1392 // sscanf(hsrvid, "%4x", &srvid);
1393 strncat(str1
, ",", sizeof(str1
) - strlen(str1
) - 1);
1394 if(!cs_malloc(&entry
, sizeof(struct s_twin
)))
1401 entry
->tw
.caid
= caid
;
1402 entry
->tw
.provid
= provid
;
1403 entry
->tw
.srvid
= srvid
;
1404 entry
->tw
.deg
= deg
;
1405 entry
->tw
.freq
= freq
;
1407 cs_debug_mask(D_TRACE
, "channel: %04X:%06X:%d:%d:%d", entry
->tw
.caid
, entry
->tw
.provid
, entry
->tw
.deg
,
1408 entry
->tw
.freq
, entry
->tw
.srvid
);
1423 { cs_log("%d entries read from %s", count
, cs_twin
); }
1430 void twin_read(void)
1433 struct s_twin
*entry
, *old_list
;
1435 old_list
= cfg
.twin_list
;
1436 cfg
.twin_list
= twin_read_int();
1440 entry
= old_list
->next
;
1446 struct ecmtw
get_twin(ECM_REQUEST
*er
)
1449 memset(&tmp
, 0, sizeof(tmp
));
1452 cs_log("twin_list not found!");
1455 struct s_twin
*entry
= cfg
.twin_list
;
1458 if(entry
->tw
.caid
== er
->caid
&& entry
->tw
.provid
== er
->prid
&& entry
->tw
.srvid
== er
->srvid
)
1462 entry
= entry
->next
;
1465 if(entry
) { tmp
= entry
->tw
; }