source: trunk/oscam-ecm.c@ 8456

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

Slim down struct s_port.

struct s_port contains filter array and couple of other fields that are
used only for newcamd and nothing else. They waste more than 2k in common
case.

To stop losing this much space, create private structure only for
newcamd fields and allocate it dynamically. This lowers struct s_port
size a lot and of course struct s_ptab even more because it contains
array of struct s_ports's.

New structure sizes (32-bit):

                  before  after
  struct s_port     2144     12
  struct s_ptab    68612    388
  struct s_config 141260   4812

Size report (32-bit):

    text     data      bss      dec    hex filename
  998222     1944   602344  1602510 1873ce before/oscam-1.20-unstable_svn8453-i486-slackware-linux
  998174     1944    61800  1061918 10341e  after/oscam-1.20-unstable_svn8453-i486-slackware-linux

bloat-o-meter report (32-bit):

  add/remove: 0/1 grow/shrink: 13/16 up/down: 7897/-548383 (-540486)
  function                                     old     new   delta
  modules                                     1840    9520   +7680
  ...
  cfg                                       141260    4812 -136448
  static.ptab                               411672       - -411672
File size: 44.2 KB
Line 
1#include "globals.h"
2#include "cscrypt/md5.h"
3#include "module-anticasc.h"
4#include "module-cacheex.h"
5#include "module-led.h"
6#include "module-stat.h"
7#include "module-webif.h"
8#include "module-ird-guess.h"
9#include "module-cw-cycle-check.h"
10#include "oscam-chk.h"
11#include "oscam-client.h"
12#include "oscam-config.h"
13#include "oscam-ecm.h"
14#include "oscam-garbage.h"
15#include "oscam-failban.h"
16#include "oscam-net.h"
17#include "oscam-time.h"
18#include "oscam-lock.h"
19#include "oscam-string.h"
20#include "oscam-work.h"
21#include "reader-common.h"
22
23extern CS_MUTEX_LOCK ecmcache_lock;
24extern struct ecm_request_t *ecmcwcache;
25extern struct s_client *timecheck_client;
26extern uint16_t len4caid[256];
27extern uint32_t ecmcwcache_size;
28
29/**
30 * get ecm from ecmcache
31 **/
32struct ecm_request_t *check_cwcache(ECM_REQUEST *er, struct s_client *cl)
33{
34 time_t now = time(NULL);
35 //time_t timeout = now-(time_t)(cfg.ctimeout/1000)-CS_CACHE_TIMEOUT;
36 time_t timeout = now-cfg.max_cache_time;
37 struct ecm_request_t *ecm;
38 uint64_t grp = cl?cl->grp:0;
39#ifdef CS_CACHEEX
40 // precalculate for better performance
41 uint8_t ecmd5chk = checkECMD5(er);
42 bool hasMatchAlias = cacheex_is_match_alias(cl, er);
43#endif
44 cs_readlock(&ecmcache_lock);
45 for (ecm = ecmcwcache; ecm; ecm = ecm->next) {
46 if (ecm->tps.time < timeout) {
47 ecm = NULL;
48 break;
49 }
50 if (ecm->ecmcacheptr)
51 continue;
52
53 if ((grp && ecm->grp && !(grp & ecm->grp)))
54 continue;
55
56#ifdef CS_CACHEEX
57 if (!hasMatchAlias || !cacheex_match_alias(cl, er, ecm)) {
58 //CWs from csp/cacheex have no ecms, csp ecmd5 is invalid, cacheex has ecmd5
59 if (ecmd5chk && checkECMD5(ecm)) {
60 if (memcmp(ecm->ecmd5, er->ecmd5, CS_ECMSTORESIZE))
61 continue; // no match
62 } else if (ecm->csp_hash != er->csp_hash) //fallback for csp only
63 continue; // no match
64 }
65#else
66 if (memcmp(ecm->ecmd5, er->ecmd5, CS_ECMSTORESIZE))
67 continue; // no match
68#endif
69
70 if (er->caid != ecm->caid && ecm->rc >= E_NOTFOUND && !is_betatunnel_caid(er->caid))
71 continue; //CW for the cached ECM wasn't found but now the client asks on a different caid so give it another try
72
73 if (ecm->rc != E_99) {
74 cs_readunlock(&ecmcache_lock);
75 return ecm;
76 }
77 }
78 cs_readunlock(&ecmcache_lock);
79 return NULL; // nothing found so return null
80}
81
82void convert_to_beta(struct s_client *cl, ECM_REQUEST *er, uint16_t caidto)
83{
84 static uint8_t headerN3[10] = {0xc7, 0x00, 0x00, 0x00, 0x01, 0x10, 0x10, 0x00, 0x87, 0x12};
85 static uint8_t headerN2[10] = {0xc9, 0x00, 0x00, 0x00, 0x01, 0x10, 0x10, 0x00, 0x48, 0x12};
86
87 er->ocaid = er->caid;
88 er->caid = caidto;
89 er->prid = 0;
90 er->ecmlen = er->ecm[2] + 3;
91
92 memmove(er->ecm + 13, er->ecm + 3, er->ecmlen - 3);
93
94 if (er->ecmlen > 0x88) {
95 memcpy(er->ecm + 3, headerN3, 10);
96 if (er->ecm[0] == 0x81)
97 er->ecm[12] += 1;
98 er->ecm[1]=0x70;
99 } else {
100 memcpy(er->ecm + 3, headerN2, 10);
101 }
102
103 er->ecmlen += 10;
104 er->ecm[2] = er->ecmlen - 3;
105 er->btun = 1;
106
107 cl->cwtun++;
108 cl->account->cwtun++;
109 first_client->cwtun++;
110
111 cs_debug_mask(D_TRACE, "ECM converted ocaid from 0x%04X to BetaCrypt caid 0x%04X for service id 0x%04X",
112 er->ocaid, caidto, er->srvid);
113}
114
115void convert_to_nagra(struct s_client *cl, ECM_REQUEST *er, uint16_t caidto)
116{
117 cs_debug_mask(D_TRACE, "convert_to_nagra");
118 er->ocaid = er->caid;
119 er->caid = caidto;
120 er->prid = 0;
121 er->ecmlen = er->ecm[2] + 3;
122
123 //not sure
124 if (er->ecmlen < 0x52)
125 er->ecm[1] = 0x30;
126
127 memmove(er->ecm + 3, er->ecm + 13, er->ecmlen - 3);
128
129 er->ecmlen -= 10;
130 er->ecm[2] = er->ecmlen - 3;
131 er->btun = 1;
132
133 cl->cwtun++;
134 cl->account->cwtun++;
135 first_client->cwtun++;
136
137 cs_debug_mask(D_TRACE, "ECM converted ocaid from: 0x%04X to Nagra: 0x04%X for service id:0x04%X",
138 er->ocaid, caidto, er->srvid);
139}
140
141void cs_betatunnel(ECM_REQUEST *er)
142{
143 int32_t n;
144 struct s_client *cl = cur_client();
145 uint32_t mask_all = 0xFFFF;
146
147 TUNTAB *ttab;
148 ttab = &cl->ttab;
149
150 if (er->caid>>8 == 0x18)
151 cs_ddump_mask(D_TRACE, er->ecm, 13, "betatunnel? ecmlen=%d", er->ecmlen);
152
153 for (n = 0; n<ttab->n; n++) {
154 if ((er->caid==ttab->bt_caidfrom[n]) && ((er->srvid==ttab->bt_srvid[n]) || (ttab->bt_srvid[n])==mask_all)) {
155 if ((er->caid == 0x1702 || er->caid == 0x1722) && er->ocaid == 0x0000) {
156 convert_to_nagra(cl, er, ttab->bt_caidto[n]);
157 } else if (er->ocaid == 0x0000) {
158 convert_to_beta(cl, er, ttab->bt_caidto[n]);
159 }
160 return;
161 }
162 }
163}
164
165static void remove_ecm_from_reader(ECM_REQUEST *ecm)
166{
167 int32_t i;
168 struct s_ecm_answer *ea = ecm->matching_rdr;
169 while (ea) {
170 if ((ea->status & REQUEST_SENT) && !(ea->status & REQUEST_ANSWERED)) {
171 //we found a outstanding reader, clean it:
172 struct s_reader *rdr = ea->reader;
173 if (rdr) {
174 struct s_client *cl = rdr->client;
175 if (cl) {
176 ECM_REQUEST *ecmtask = cl->ecmtask;
177 if (ecmtask) {
178 for (i = 0; i < cfg.max_pending; ++i) {
179 if (ecmtask[i].parent == ecm) {
180 ecmtask[i].parent = NULL;
181 ecmtask[i].client = NULL;
182 cacheex_set_csp_lastnode(&ecmtask[i]);
183 }
184 }
185 }
186 }
187 }
188 }
189 ea = ea->next;
190 }
191}
192
193void free_ecm(ECM_REQUEST *ecm)
194{
195 struct s_ecm_answer *ea, *nxt;
196 cacheex_free_csp_lastnodes(ecm);
197 //remove this ecm from reader queue to avoid segfault on very late answers (when ecm is already disposed)
198 //first check for outstanding answers:
199 remove_ecm_from_reader(ecm);
200 //free matching_rdr list:
201 ea = ecm->matching_rdr;
202 ecm->matching_rdr = NULL;
203 while (ea) {
204 nxt = ea->next;
205 add_garbage(ea);
206 ea = nxt;
207 }
208 if (ecm->src_data)
209 add_garbage(ecm->src_data);
210 add_garbage(ecm);
211}
212
213ECM_REQUEST *get_ecmtask(void)
214{
215 ECM_REQUEST *er = NULL;
216 struct s_client *cl = cur_client();
217 if (!cl)
218 return NULL;
219 if (!cs_malloc(&er, sizeof(ECM_REQUEST)))
220 return NULL;
221 cs_ftime(&er->tps);
222#ifdef CS_CACHEEX
223 er->cacheex_wait.time = er->tps.time;
224 er->cacheex_wait.millitm = er->tps.millitm;
225 er->cacheex_wait_time = 0;
226#endif
227 er->rc = E_UNHANDLED;
228 er->client = cl;
229 er->grp = cl->grp;
230 //cs_log("client %s ECMTASK %d module %s", username(cl), n, get_module(cl)->desc);
231 return er;
232}
233
234void cleanup_ecmtasks(struct s_client *cl)
235{
236 ECM_REQUEST *ecm;
237 struct s_ecm_answer *ea_list, *ea_prev;
238
239 if (cl->ecmtask) {
240 int32_t i;
241 for (i = 0; i < cfg.max_pending; i++) {
242 ecm = &cl->ecmtask[i];
243 ecm->matching_rdr = NULL;
244 ecm->client = NULL;
245 }
246 add_garbage(cl->ecmtask);
247 cl->ecmtask = NULL;
248 }
249
250 if (cl->cascadeusers) {
251 ll_destroy_data(cl->cascadeusers);
252 cl->cascadeusers = NULL;
253 }
254
255 //remove this clients ecm from queue. because of cache, just null the client:
256 cs_readlock(&ecmcache_lock);
257 for (ecm = ecmcwcache; ecm; ecm = ecm->next) {
258 if (ecm->client == cl) {
259 ecm->client = NULL;
260 cacheex_set_cacheex_src(ecm, cl);
261 //if cl is a reader, remove from matching_rdr:
262 for (ea_list = ecm->matching_rdr, ea_prev = NULL; ea_list; ea_prev = ea_list, ea_list = ea_list->next) {
263 if (ea_list->reader->client == cl) {
264 if (ea_prev)
265 ea_prev->next = ea_list->next;
266 else
267 ecm->matching_rdr = ea_list->next;
268 add_garbage(ea_list);
269 }
270 }
271 //if cl is a client, remove ecm from reader queue:
272 remove_ecm_from_reader(ecm);
273 }
274 }
275 cs_readunlock(&ecmcache_lock);
276
277 //remove client from rdr ecm-queue:
278 cs_readlock(&readerlist_lock);
279 struct s_reader *rdr = first_active_reader;
280 while (rdr) {
281 if (rdr->client && rdr->client->ecmtask) {
282 int i;
283 for (i = 0; i < cfg.max_pending; i++) {
284 ecm = &rdr->client->ecmtask[i];
285 if (ecm->client == cl) {
286 ecm->client = NULL;
287 ecm->parent = NULL;
288 }
289 }
290 }
291 rdr = rdr->next;
292 }
293 cs_readunlock(&readerlist_lock);
294}
295
296/**
297 * removes a reader from ecm cache queue - data
298 **/
299void remove_reader_from_ecm(struct s_reader *rdr)
300{
301 ECM_REQUEST *ecm;
302 struct s_ecm_answer *ea_list, *ea_prev;
303
304 cs_readlock(&ecmcache_lock);
305 for (ecm = ecmcwcache; ecm; ecm = ecm->next) {
306 for (ea_list = ecm->matching_rdr, ea_prev = NULL; ea_list; ea_prev = ea_list, ea_list = ea_list->next) {
307 if (ea_list->reader == rdr) {
308 if (ea_prev)
309 ea_prev->next = ea_list->next;
310 else
311 ecm->matching_rdr = ea_list->next;
312 add_garbage(ea_list);
313 }
314 }
315 }
316 cs_readunlock(&ecmcache_lock);
317}
318
319
320/**
321 * Check for NULL CWs
322 * Return them as "NOT FOUND"
323 **/
324void checkCW(ECM_REQUEST *er)
325{
326 int8_t i;
327 for (i = 0; i < 16; i++) {
328 if (er->cw[i])
329 return;
330 }
331 er->rc = E_NOTFOUND;
332}
333
334static void add_cascade_data(struct s_client *client, ECM_REQUEST *er)
335{
336 if (!client->cascadeusers)
337 client->cascadeusers = ll_create("cascade_data");
338 LLIST *l = client->cascadeusers;
339 LL_ITER it = ll_iter_create(l);
340 time_t now = time(NULL);
341 struct s_cascadeuser *cu;
342 int8_t found = 0;
343 while ((cu = ll_iter_next(&it))) {
344 if (er->caid==cu->caid && er->prid==cu->prid && er->srvid==cu->srvid) { //found it
345 if (cu->time < now)
346 cu->cwrate = now-cu->time;
347 cu->time = now;
348 found = 1;
349 }
350 else if (cu->time+60 < now) // old
351 ll_iter_remove_data(&it);
352 }
353 if (!found) { //add it if not found
354 if (!cs_malloc(&cu, sizeof(struct s_cascadeuser)))
355 return;
356 cu->caid = er->caid;
357 cu->prid = er->prid;
358 cu->srvid = er->srvid;
359 cu->time = now;
360 ll_append(l, cu);
361 }
362}
363
364static int32_t is_double_check_caid(ECM_REQUEST *er)
365{
366 if (!cfg.double_check_caid.caid[0]) //no caids defined: Check all
367 return 1;
368 int32_t i;
369 for (i = 0; i < CS_MAXCAIDTAB; i++) {
370 uint16_t tcaid = cfg.double_check_caid.caid[i];
371 if (!tcaid)
372 break;
373 if (tcaid == er->caid || (tcaid < 0x0100 && (er->caid >> 8) == tcaid)) {
374 return 1;
375 }
376 }
377 return 0;
378}
379
380static int32_t send_dcw(struct s_client * client, ECM_REQUEST *er)
381{
382 if (!client || client->kill || client->typ != 'c')
383 return 0;
384
385 static const char stageTxt[]={'0','C','L','P','F','X'};
386 static const char *stxt[]={"found", "cache1", "cache2", "cache3",
387 "not found", "timeout", "sleeping",
388 "fake", "invalid", "corrupt", "no card", "expdate", "disabled", "stopped"};
389 static const char *stxtEx[16]={"", "group", "caid", "ident", "class", "chid", "queue", "peer", "sid", "", "", "", "", "", "", ""};
390 static const char *stxtWh[16]={"", "user ", "reader ", "server ", "lserver ", "", "", "", "", "", "", "", "" ,"" ,"", ""};
391 char sby[100]="", sreason[32]="", schaninfo[32]="";
392 char erEx[32]="";
393 char uname[38]="";
394 char channame[32];
395 struct timeb tpe;
396
397 snprintf(uname,sizeof(uname)-1, "%s", username(client));
398
399 if (er->rc < E_NOTFOUND)
400 checkCW(er);
401
402#ifdef WITH_DEBUG
403 if (cs_dblevel & D_CLIENTECM) {
404 char buf[ECM_FMT_LEN];
405 char ecmd5[17*3];
406 char cwstr[17*3];
407 format_ecm(er, buf, ECM_FMT_LEN);
408 cs_hexdump(0, er->ecmd5, 16, ecmd5, sizeof(ecmd5));
409 cs_hexdump(0, er->cw, 16, cwstr, sizeof(cwstr));
410#ifdef CS_CACHEEX
411 char csphash[5*3];
412 cs_hexdump(0, (void*)&er->csp_hash, 4, csphash, sizeof(csphash));
413 cs_debug_mask(D_CLIENTECM, "Client %s csphash %s cw %s rc %d %s", username(client), csphash, cwstr, er->rc, buf);
414#else
415 cs_debug_mask(D_CLIENTECM, "Client %s cw %s rc %d %s", username(client), cwstr, er->rc, buf);
416#endif
417 }
418#endif
419
420 struct s_reader *er_reader = er->selected_reader; //responding reader
421
422 if (er_reader) {
423 // add marker to reader if ECM_REQUEST was betatunneled
424 if (er->ocaid)
425 snprintf(sby, sizeof(sby)-1, " by %s(btun %04X)", er_reader->label, er->ocaid);
426 else
427 snprintf(sby, sizeof(sby)-1, " by %s", er_reader->label);
428 } else if (er->rc == E_TIMEOUT) {
429 struct s_ecm_answer *ea_list;
430 int32_t ofs = 0;
431 for (ea_list = er->matching_rdr; ea_list; ea_list = ea_list->next) {
432 if (ea_list->reader && ofs < (int32_t)sizeof(sby) && (ea_list->status & (REQUEST_SENT|REQUEST_ANSWERED)) == REQUEST_SENT) { //Request send, but no answer!
433 ofs += snprintf(sby+ofs, sizeof(sby)-ofs-1, "%s%s", ofs?",":" by ", ea_list->reader->label);
434 }
435 }
436 if (er->ocaid && ofs < (int32_t)sizeof(sby))
437 ofs += snprintf(sby+ofs, sizeof(sby)-ofs-1, "(btun %04X)", er->ocaid);
438 }
439
440 if (er->rc < E_NOTFOUND)
441 er->rcEx = 0;
442
443 if (er->rcEx)
444 snprintf(erEx, sizeof(erEx)-1, "rejected %s%s", stxtWh[er->rcEx>>4], stxtEx[er->rcEx & 0xf]);
445
446 if (cfg.appendchaninfo)
447 snprintf(schaninfo, sizeof(schaninfo)-1, " - %s", get_servicename(client, er->srvid, er->caid, channame));
448
449 if (er->msglog[0])
450 snprintf(sreason, sizeof(sreason)-1, " (%s)", er->msglog);
451
452 cs_ftime(&tpe);
453
454#ifdef CS_CACHEEX
455 if (er->rc == E_FOUND && er->cacheex_wait_time)
456 snprintf(sreason, sizeof(sreason)-1, " (real %d ms)", comp_timeb(&tpe, &er->cacheex_wait));
457#endif
458
459 client->cwlastresptime = 1000 * (tpe.time-er->tps.time) + tpe.millitm-er->tps.millitm;
460
461 time_t now = time(NULL);
462 webif_client_add_lastresponsetime(client, client->cwlastresptime, now, er->rc); // add to ringbuffer
463
464 if (er_reader) {
465 struct s_client *er_cl = er_reader->client;
466 if (er_cl) {
467 er_cl->cwlastresptime = client->cwlastresptime;
468 webif_client_add_lastresponsetime(er_cl, client->cwlastresptime, now, er->rc);
469 er_cl->last_srvidptr = client->last_srvidptr;
470 }
471 }
472
473 webif_client_init_lastreader(client, er, er_reader, stxt);
474
475 client->last = now;
476
477 //cs_debug_mask(D_TRACE, "CHECK rc=%d er->cacheex_src=%s", er->rc, username(er->cacheex_src));
478 switch(er->rc) {
479 case E_FOUND: {
480 client->cwfound++;
481 client->account->cwfound++;
482 first_client->cwfound++;
483 break;
484 }
485 case E_CACHE1:
486 case E_CACHE2:
487 case E_CACHEEX: {
488 client->cwcache++;
489 client->account->cwcache++;
490 first_client->cwcache++;
491#ifdef CS_CACHEEX
492 if (er->cacheex_src) {
493 er->cacheex_src->cwcacheexhit++;
494 if (er->cacheex_src->account)
495 er->cacheex_src->account->cwcacheexhit++;
496 first_client->cwcacheexhit++;
497 }
498#endif
499 break;
500 }
501 case E_NOTFOUND:
502 case E_CORRUPT:
503 case E_NOCARD: {
504 if (er->rcEx) {
505 client->cwignored++;
506 client->account->cwignored++;
507 first_client->cwignored++;
508 } else {
509 client->cwnot++;
510 client->account->cwnot++;
511 first_client->cwnot++;
512 }
513 break;
514 }
515 case E_TIMEOUT: {
516 client->cwtout++;
517 client->account->cwtout++;
518 first_client->cwtout++;
519 break;
520 }
521 default: {
522 client->cwignored++;
523 client->account->cwignored++;
524 first_client->cwignored++;
525 } }
526
527 ac_chk(client, er, 1);
528
529 int32_t is_fake = 0;
530 if (er->rc == E_FAKE) {
531 is_fake = 1;
532 er->rc = E_FOUND;
533 }
534
535 if (cfg.double_check && er->rc == E_FOUND && er->selected_reader && is_double_check_caid(er)) {
536 if (er->checked == 0) {//First CW, save it and wait for next one
537 er->checked = 1;
538 er->origin_reader = er->selected_reader;
539 memcpy(er->cw_checked, er->cw, sizeof(er->cw));
540 cs_log("DOUBLE CHECK FIRST CW by %s idx %d cpti %d", er->origin_reader->label, er->idx, er->msgid);
541 } else if (er->origin_reader != er->selected_reader) { //Second (or third and so on) cw. We have to compare
542 if (memcmp(er->cw_checked, er->cw, sizeof(er->cw)) == 0) {
543 er->checked++;
544 cs_log("DOUBLE CHECKED! %d. CW by %s idx %d cpti %d", er->checked, er->selected_reader->label, er->idx, er->msgid);
545 } else {
546 cs_log("DOUBLE CHECKED NONMATCHING! %d. CW by %s idx %d cpti %d", er->checked, er->selected_reader->label, er->idx, er->msgid);
547 }
548 }
549 if (er->checked < 2) { //less as two same cw? mark as pending!
550 er->rc = E_UNHANDLED;
551 return 0;
552 }
553 }
554
555 get_module(client)->send_dcw(client, er);
556
557 add_cascade_data(client, er);
558
559 if (is_fake)
560 er->rc = E_FAKE;
561
562 if (!(er->rc == E_SLEEPING && client->cwlastresptime == 0)) {
563 char buf[ECM_FMT_LEN];
564 format_ecm(er, buf, ECM_FMT_LEN);
565 if (er->reader_avail == 1) {
566 cs_log("%s (%s): %s (%d ms)%s %s%s",
567 uname, buf,
568 er->rcEx?erEx:stxt[er->rc], client->cwlastresptime, sby, schaninfo, sreason);
569 } else {
570 cs_log("%s (%s): %s (%d ms)%s (%c/%d/%d/%d)%s%s",
571 uname, buf,
572 er->rcEx ? erEx : stxt[er->rc],
573 client->cwlastresptime, sby,
574 stageTxt[er->stage], er->reader_requested, er->reader_count, er->reader_avail,
575 schaninfo, sreason);
576 }
577 }
578
579 cs_ddump_mask (D_ATR, er->cw, 16, "cw:");
580 led_status_cw_not_found(er);
581
582 return 0;
583}
584
585/*
586 * write_ecm_request():
587 */
588static int32_t write_ecm_request(struct s_reader *rdr, ECM_REQUEST *er)
589{
590 add_job(rdr->client, ACTION_READER_ECM_REQUEST, (void*)er, 0);
591 return 1;
592}
593
594
595/**
596 * distributes found ecm-request to all clients with rc=99
597 **/
598static void distribute_ecm(ECM_REQUEST *er, int32_t rc)
599{
600 struct ecm_request_t *ecm;
601 cs_readlock(&ecmcache_lock);
602 for (ecm = ecmcwcache; ecm; ecm = ecm->next) {
603 if (ecm != er && ecm->rc >= E_99 && ecm->ecmcacheptr == er) {
604 cacheex_init_cacheex_src(ecm, er);
605 write_ecm_answer(er->selected_reader, ecm, rc, 0, er->cw, NULL);
606 }
607 }
608 cs_readunlock(&ecmcache_lock);
609}
610
611/**
612 * sends the ecm request to the readers
613 * ECM_REQUEST er : the ecm
614 * er->stage: 0 = no reader asked yet
615 * 2 = ask only local reader (skipped without preferlocalcards)
616 * 3 = ask any non fallback reader
617 * 4 = ask fallback reader
618 **/
619void request_cw_from_readers(ECM_REQUEST *er)
620{
621 struct s_ecm_answer *ea;
622 int8_t sent = 0;
623
624 if (er->stage >= 4) return;
625
626 while (1) {
627 er->stage++;
628
629#ifndef CS_CACHEEX
630 if (er->stage == 1)
631 er->stage++;
632#endif
633 if (er->stage == 2 && !cfg.preferlocalcards)
634 er->stage++;
635
636 for (ea = er->matching_rdr; ea; ea = ea->next) {
637 switch(er->stage) {
638#ifdef CS_CACHEEX
639 case 1: {
640 // Cache-Exchange
641 if ((ea->status & REQUEST_SENT) ||
642 (ea->status & (READER_CACHEEX|READER_ACTIVE)) != (READER_CACHEEX|READER_ACTIVE))
643 continue;
644 break;
645 }
646#endif
647 case 2: {
648 // only local reader
649 if ((ea->status & REQUEST_SENT) ||
650 (ea->status & (READER_ACTIVE|READER_FALLBACK|READER_LOCAL)) != (READER_ACTIVE|READER_LOCAL))
651 continue;
652 break;
653 }
654 case 3: {
655 // any non fallback reader not asked yet
656 if ((ea->status & REQUEST_SENT) ||
657 (ea->status & (READER_ACTIVE|READER_FALLBACK)) != READER_ACTIVE)
658 continue;
659 break;
660 }
661 default: {
662 // only fallbacks
663 if ((ea->status & (READER_ACTIVE|READER_FALLBACK)) != (READER_ACTIVE|READER_FALLBACK))
664 continue;
665 if (ea->status & REQUEST_SENT) {
666 if (ea->reader && ea->reader->client && ea->reader->client->is_udp) //Always resend on udp
667 break;
668 if (er->reader_count > 1) //do not resend to the same reader(s) if we have more than one reader
669 continue;
670 }
671 break;
672 } }
673
674 struct s_reader *rdr = ea->reader;
675 char ecmd5[17*3];
676 cs_hexdump(0, er->ecmd5, 16, ecmd5, sizeof(ecmd5));
677 cs_debug_mask(D_TRACE | D_CSPCWC, "request_cw stage=%d to reader %s ecm hash=%s", er->stage, rdr?rdr->label:"", ecmd5);
678
679 ea->status |= REQUEST_SENT;
680 er->reader_requested++;
681 write_ecm_request(ea->reader, er);
682
683 //set sent=1 only if reader is active/connected. If not, switch to next stage!
684 if (!sent && rdr) {
685 struct s_client *rcl = rdr->client;
686 if (rcl) {
687 if (rcl->typ=='r' && rdr->card_status==CARD_INSERTED)
688 sent = 1;
689 else if (rcl->typ=='p' && (rdr->card_status==CARD_INSERTED ||rdr->tcp_connected))
690 sent = 1;
691 }
692 }
693 }
694 if (sent || er->stage >= 4)
695 break;
696 }
697}
698
699void chk_dcw(struct s_client *cl, struct s_ecm_answer *ea)
700{
701 if (!ea || !ea->er)
702 return;
703
704 ECM_REQUEST *ert = ea->er;
705 struct s_ecm_answer *ea_list;
706 struct s_reader *eardr = ea->reader;
707 if (!ert)
708 return;
709
710 if (eardr) {
711 char ecmd5[17*3];
712 cs_hexdump(0, ert->ecmd5, 16, ecmd5, sizeof(ecmd5));
713 rdr_debug_mask(eardr, D_TRACE, "ecm answer for ecm hash %s rc=%d", ecmd5, ea->rc);
714 //rdr_ddump_mask(eardr, D_TRACE, ea->cw, sizeof(ea->cw), "received cw caid=%04X srvid=%04X hash=%08X",
715 // ert->caid, ert->srvid, ert->csp_hash);
716 //rdr_ddump_mask(eardr, D_TRACE, ert->ecm, ert->ecmlen, "received cw for ecm caid=%04X srvid=%04X hash=%08X",
717 // ert->caid, ert->srvid, ert->csp_hash);
718 }
719
720 ea->status |= REQUEST_ANSWERED;
721
722 if (eardr) {
723 //Update reader stats:
724 if (ea->rc == E_FOUND) {
725 eardr->ecmsok++;
726#ifdef CS_CACHEEX
727 struct s_client *eacl = eardr->client;
728 if (cacheex_reader(eardr) && !ert->cacheex_done && eacl) {
729 eacl->cwcacheexgot++;
730 cacheex_add_stats(eacl, ea->er->caid, ea->er->srvid, ea->er->prid, 1);
731 first_client->cwcacheexgot++;
732 }
733#endif
734 } else if (ea->rc == E_NOTFOUND) {
735 eardr->ecmsnok++;
736 if (eardr->ecmnotfoundlimit && eardr->ecmsnok >= eardr->ecmnotfoundlimit) {
737 rdr_log(eardr,"ECM not found limit reached %u. Restarting the reader.",
738 eardr->ecmsnok);
739 eardr->ecmsnok = 0; // Reset the variable
740 eardr->ecmshealthnok = 0; // Reset the variable
741 add_job(eardr->client, ACTION_READER_RESTART, NULL, 0);
742 }
743 }
744
745 //Reader ECMs Health Try (by Pickser)
746 if (eardr->ecmsok != 0 || eardr->ecmsnok != 0) {
747 eardr->ecmshealthok = ((double) eardr->ecmsok / (eardr->ecmsok + eardr->ecmsnok)) * 100;
748 eardr->ecmshealthnok = ((double) eardr->ecmsnok / (eardr->ecmsok + eardr->ecmsnok)) * 100;
749 }
750
751 //Reader Dynamic Loadbalancer Try (by Pickser)
752 /*
753 * todo: config-option!
754 *
755#ifdef WITH_LB
756 if (eardr->ecmshealthok >= 75) {
757 eardr->lb_weight = 100;
758 } else if (eardr->ecmshealthok >= 50) {
759 eardr->lb_weight = 75;
760 } else if (eardr->ecmshealthok >= 25) {
761 eardr->lb_weight = 50;
762 } else {
763 eardr->lb_weight = 25;
764 }
765#endif
766 */
767 }
768
769 if (ert->rc < E_99) {
770 send_reader_stat(eardr, ert, ea, ea->rc);
771#ifdef CS_CACHEEX
772 if (ea && ert->rc < E_NOTFOUND && ea->rc < E_NOTFOUND && memcmp(ea->cw, ert->cw, sizeof(ert->cw)) != 0) {
773 char cw1[16*3+2], cw2[16*3+2];
774 cs_hexdump(0, ea->cw, 16, cw1, sizeof(cw1));
775 cs_hexdump(0, ert->cw, 16, cw2, sizeof(cw2));
776
777 char ip1[20]="", ip2[20]="";
778 if (ea->reader) cs_strncpy(ip1, cs_inet_ntoa(ea->reader->client->ip), sizeof(ip1));
779 if (ert->cacheex_src) cs_strncpy(ip2, cs_inet_ntoa(ert->cacheex_src->ip), sizeof(ip2));
780 else if (ert->selected_reader) cs_strncpy(ip2, cs_inet_ntoa(ert->selected_reader->client->ip), sizeof(ip2));
781
782 ECM_REQUEST *er = ert;
783 debug_ecm(D_TRACE, "WARNING2: Different CWs %s from %s(%s)<>%s(%s): %s<>%s", buf,
784 username(ea->reader ? ea->reader->client : cl), ip1,
785 er->cacheex_src ? username(er->cacheex_src) : (ea->reader ? ea->reader->label : "unknown/csp"), ip2,
786 cw1, cw2);
787 }
788#endif
789 if (ea && ea->rc < ert->rc) { //answer too late, only cache update:
790 memcpy(ert->cw, ea->cw, sizeof(ea->cw));
791 ert->rc = ea->rc;
792 }
793
794 return; // already done
795 }
796
797 int32_t reader_left = 0, local_left = 0;
798#ifdef CS_CACHEEX
799 int8_t cacheex_left = 0;
800#endif
801
802 switch (ea->rc) {
803 case E_FOUND:
804 case E_CACHE2:
805 case E_CACHE1:
806 case E_CACHEEX:
807 memcpy(ert->cw, ea->cw, 16);
808 ert->rcEx = 0;
809 ert->rc = ea->rc;
810 ert->selected_reader = eardr;
811 break;
812 case E_TIMEOUT:
813 ert->rc = E_TIMEOUT;
814 ert->rcEx = 0;
815 break;
816 case E_NOTFOUND: {
817 ert->rcEx = ea->rcEx;
818 cs_strncpy(ert->msglog, ea->msglog, sizeof(ert->msglog));
819 ert->selected_reader = eardr;
820 if (!ert->ecmcacheptr) {
821#ifdef CS_CACHEEX
822 uint8_t has_cacheex = 0;
823#endif
824 for (ea_list = ert->matching_rdr; ea_list; ea_list = ea_list->next) {
825#ifdef CS_CACHEEX
826 if (((ea_list->status & READER_CACHEEX)) == READER_CACHEEX)
827 has_cacheex = 1;
828 if (((ea_list->status & (REQUEST_SENT|REQUEST_ANSWERED|READER_CACHEEX|READER_ACTIVE)) == (REQUEST_SENT|READER_CACHEEX|READER_ACTIVE)))
829 cacheex_left++;
830#endif
831 if (((ea_list->status & (REQUEST_SENT|REQUEST_ANSWERED|READER_LOCAL|READER_ACTIVE)) == (REQUEST_SENT|READER_LOCAL|READER_ACTIVE)))
832 local_left++;
833 if (((ea_list->status & (REQUEST_ANSWERED|READER_ACTIVE)) == (READER_ACTIVE)))
834 reader_left++;
835 }
836#ifdef CS_CACHEEX
837 if (has_cacheex && !cacheex_left && !ert->cacheex_done) {
838 ert->cacheex_done = 1;
839 request_cw_from_readers(ert);
840 } else
841#endif
842 if (cfg.preferlocalcards && !local_left && !ert->locals_done) {
843 ert->locals_done = 1;
844 request_cw_from_readers(ert);
845 }
846 }
847 break;
848 }
849 default:
850 cs_log("unexpected ecm answer rc=%d.", ea->rc);
851 return;
852 break;
853 }
854
855 if (ea->rc == E_NOTFOUND && !reader_left) {
856 // no more matching reader
857 ert->rc = E_NOTFOUND; //so we set the return code
858 }
859
860 send_reader_stat(eardr, ert, ea, ea->rc);
861
862#ifdef CS_CACHEEX
863 if (ea->rc < E_NOTFOUND && !ert->ecmcacheptr)
864 cacheex_cache_push(ert);
865#endif
866
867 if (ert->rc < E_99) {
868 if (cl) send_dcw(cl, ert);
869 if (!ert->ecmcacheptr && ert->rc != E_UNHANDLED)
870 distribute_ecm(ert, (ert->rc == E_FOUND)?E_CACHE2:ert->rc);
871 }
872
873 return;
874}
875
876uint32_t chk_provid(uint8_t *ecm, uint16_t caid)
877{
878 int32_t i, len, descriptor_length = 0;
879 uint32_t provid = 0;
880
881 switch(caid >> 8) {
882 case 0x01:
883 // seca
884 provid = b2i(2, ecm+3);
885 break;
886 case 0x05:
887 // viaccess
888 i = (ecm[4] == 0xD2) ? ecm[5]+2 : 0; // skip d2 nano
889 if ((ecm[5+i] == 3) && ((ecm[4+i] == 0x90) || (ecm[4+i] == 0x40)))
890 provid = (b2i(3, ecm+6+i) & 0xFFFFF0);
891
892 i = (ecm[6] == 0xD2) ? ecm[7]+2 : 0; // skip d2 nano long ecm
893 if ((ecm[7+i] == 7) && ((ecm[6+i] == 0x90) || (ecm[6+i] == 0x40)))
894 provid = (b2i(3, ecm+8+i) & 0xFFFFF0);
895
896 break;
897 case 0x0D:
898 // cryptoworks
899 len = (((ecm[1] & 0xf) << 8) | ecm[2])+3;
900 for (i = 8; i < len; i += descriptor_length + 2) {
901 descriptor_length = ecm[i+1];
902 if (ecm[i] == 0x83) {
903 provid = (uint32_t)ecm[i+2] & 0xFE;
904 break;
905 }
906 }
907 break;
908#ifdef WITH_LB
909 default:
910 for (i = 0; i < CS_MAXCAIDTAB; i++) {
911 uint16_t tcaid = cfg.lb_noproviderforcaid.caid[i];
912 if (!tcaid) break;
913 if (tcaid == caid) {
914 provid = 0;
915 break;
916 }
917 if (tcaid < 0x0100 && (caid >> 8) == tcaid) {
918 provid = 0;
919 break;
920 }
921 }
922#endif
923 }
924 return provid;
925}
926
927void update_chid(ECM_REQUEST *er)
928{
929 if ((er->caid >> 8) == 0x06 && !er->chid && er->ecmlen > 7)
930 er->chid = (er->ecm[6] << 8) | er->ecm[7];
931}
932
933int32_t write_ecm_answer(struct s_reader * reader, ECM_REQUEST *er, int8_t rc, uint8_t rcEx, uint8_t *cw, char *msglog)
934{
935 int32_t i;
936 uint8_t c;
937 struct s_ecm_answer *ea = NULL, *ea_list, *ea_org = NULL;
938 struct timeb now;
939
940 //if (!er->parent && !er->client) //distribute also if no client is set!
941 // return 0;
942
943 cs_ftime(&now);
944
945 if (er->parent) {
946 // parent is only set on reader->client->ecmtask[], but we want client->ecmtask[]
947 // this means: reader has a ecm copy from client, so point to client
948 er->rc = rc;
949 er->idx = 0;
950 er = er->parent; //Now er is "original" ecm, before it was the reader-copy
951 er->grp |= reader->grp; // extend grp by grp of answering reader so clients in other group use cache
952
953 if (er->rc < E_99) {
954 send_reader_stat(reader, er, NULL, rc);
955 return 0; //Already done
956 }
957 }
958
959#ifdef CW_CYCLE_CHECK
960 if (!checkcwcycle(er, reader, cw, rc )) {
961 rc = E_NOTFOUND;
962 rcEx = E2_WRONG_CHKSUM;
963 }
964#endif
965
966 for (ea_list = er->matching_rdr; reader && ea_list && !ea_org; ea_list = ea_list->next) {
967 if (ea_list->reader == reader)
968 ea_org = ea_list;
969 }
970
971 if (!ea_org) {
972 if (!cs_malloc(&ea, sizeof(struct s_ecm_answer))) // Freed by ACTION_CLIENT_ECM_ANSWER
973 return 0;
974 } else {
975 ea = ea_org;
976 }
977
978 if (cw)
979 memcpy(ea->cw, cw, 16);
980
981 if (msglog)
982 memcpy(ea->msglog, msglog, MSGLOGSIZE);
983
984 ea->rc = rc;
985 ea->rcEx = rcEx;
986 ea->reader = reader;
987 ea->status |= REQUEST_ANSWERED;
988 ea->er = er;
989
990 if (reader && rc < E_NOTFOUND) {
991 if (reader->disablecrccws == 0) {
992 for (i = 0; i < 16; i += 4) {
993 c = ((ea->cw[i]+ea->cw[i+1]+ea->cw[i+2]) & 0xff);
994 if (ea->cw[i+3]!=c) {
995 if (reader->dropbadcws) {
996 ea->rc = E_NOTFOUND;
997 ea->rcEx = E2_WRONG_CHKSUM;
998 break;
999 } else {
1000 cs_debug_mask(D_TRACE, "notice: changed dcw checksum byte cw[%i] from %02x to %02x", i+3, ea->cw[i+3],c);
1001 ea->cw[i+3] = c;
1002 }
1003 }
1004 }
1005 } else {
1006 cs_debug_mask(D_TRACE, "notice: CW checksum check disabled");
1007 }
1008 }
1009
1010 if (reader && ea->rc==E_FOUND) {
1011 /* CWL logging only if cwlogdir is set in config */
1012 if (cfg.cwlogdir != NULL)
1013 logCWtoFile(er, ea->cw);
1014 }
1015
1016 int32_t res = 0;
1017 struct s_client *cl = er->client;
1018 if (cl && !cl->kill) {
1019 if (ea_org) { //duplicate for queue
1020 if (!cs_malloc(&ea, sizeof(struct s_ecm_answer)))
1021 return 0;
1022 memcpy(ea, ea_org, sizeof(struct s_ecm_answer));
1023 }
1024 add_job(cl, ACTION_CLIENT_ECM_ANSWER, ea, sizeof(struct s_ecm_answer));
1025 res = 1;
1026 } else { //client has disconnected. Distribute ecms to other waiting clients
1027 if (!er->ecmcacheptr)
1028 chk_dcw(NULL, ea);
1029 if (!ea_org)
1030 free(ea);
1031 }
1032
1033 if (reader && rc == E_FOUND && reader->resetcycle > 0) {
1034 reader->resetcounter++;
1035 if (reader->resetcounter > reader->resetcycle) {
1036 reader->resetcounter = 0;
1037 rdr_log(reader, "Resetting reader, resetcyle of %d ecms reached", reader->resetcycle);
1038 reader->card_status = CARD_NEED_INIT;
1039 cardreader_reset(cl);
1040 }
1041 }
1042
1043 return res;
1044}
1045
1046static void guess_cardsystem(ECM_REQUEST *er)
1047{
1048 uint16_t last_hope = 0;
1049
1050 // viaccess - check by provid-search
1051 if ((er->prid = chk_provid(er->ecm, 0x500)))
1052 er->caid = 0x500;
1053
1054 // nagra
1055 // is ecm[1] always 0x30 ?
1056 // is ecm[3] always 0x07 ?
1057 if ((er->ecm[6]==1) && (er->ecm[4]==er->ecm[2]-2))
1058 er->caid = 0x1801;
1059
1060 // seca2 - very poor
1061 if ((er->ecm[8]==0x10) && ((er->ecm[9]&0xF1)==1))
1062 last_hope = 0x100;
1063
1064 // is cryptoworks, but which caid ?
1065 if ((er->ecm[3]==0x81) && (er->ecm[4]==0xFF) &&
1066 (!er->ecm[5]) && (!er->ecm[6]) && (er->ecm[7]==er->ecm[2]-5))
1067 {
1068 last_hope = 0xd00;
1069 }
1070
1071 if (!er->caid && er->ecm[2] == 0x31 && er->ecm[0x0b] == 0x28)
1072 guess_irdeto(er);
1073
1074 if (!er->caid) // guess by len ..
1075 er->caid = len4caid[er->ecm[2] + 3];
1076
1077 if (!er->caid)
1078 er->caid = last_hope;
1079}
1080
1081void get_cw(struct s_client * client, ECM_REQUEST *er)
1082{
1083 int32_t i, j, m;
1084 time_t now = time((time_t*)0);
1085 uint32_t line = 0;
1086
1087 er->client = client;
1088 if (now - client->lastecm > cfg.hideclient_to) client->lastswitch = 0; // user was on freetv or didn't request for some time so we reset lastswitch to get correct stats/webif display
1089 client->lastecm = now;
1090
1091 if (client == first_client || !client ->account || client->account == first_client->account) {
1092 //DVBApi+serial is allowed to request anonymous accounts:
1093 int16_t listenertype = get_module(client)->listenertype;
1094 if (listenertype != LIS_DVBAPI && listenertype != LIS_SERIAL) {
1095 er->rc = E_INVALID;
1096 er->rcEx = E2_GLOBAL;
1097 snprintf(er->msglog, sizeof(er->msglog), "invalid user account %s", username(client));
1098 }
1099 }
1100
1101 if (er->ecmlen > MAX_ECM_SIZE) {
1102 er->rc = E_INVALID;
1103 er->rcEx = E2_GLOBAL;
1104 snprintf(er->msglog, sizeof(er->msglog), "ECM size %d > Max Ecm size %d, ignored! client %s", er->ecmlen, MAX_ECM_SIZE, username(client));
1105 }
1106
1107 if (!client->grp) {
1108 er->rc = E_INVALID;
1109 er->rcEx = E2_GROUP;
1110 snprintf(er->msglog, sizeof(er->msglog), "invalid user group %s", username(client));
1111 }
1112
1113
1114 if (!er->caid)
1115 guess_cardsystem(er);
1116
1117 /* Quickfix Area */
1118 update_chid(er);
1119
1120 // quickfix for 0100:000065
1121 if (er->caid == 0x100 && er->prid == 0x00006a) { // cds nl add fix so mismatch between ecm and secatype reader wont set channel on sid blacklist
1122 er->chid = b2i(2, er->ecm+7); // not quite right but good enough to function, its also registered this way in module-stat
1123 }
1124
1125 if (er->caid == 0x100 && er->prid == 0x65 && er->srvid == 0)
1126 er->srvid = 0x0642;
1127
1128 // Quickfixes for Opticum/Globo HD9500
1129 // Quickfix for 0500:030300
1130 if (er->caid == 0x500 && er->prid == 0x030300)
1131 er->prid = 0x030600;
1132
1133 // Quickfix for 0500:D20200
1134 if (er->caid == 0x500 && er->prid == 0xD20200)
1135 er->prid = 0x030600;
1136
1137 //betacrypt ecm with nagra header
1138 if ((er->caid == 0x1702 || er->caid == 0x1722) && (er->ecmlen == 0x89 || er->ecmlen == 0x4A) && er->ecm[3] == 0x07 && (er->ecm[4] == 0x84 || er->ecm[4] == 0x45))
1139 {
1140 //cs_debug_mask(D_TRACE, "Quickfix remap beta->nagra: 0x%X, 0x%X, 0x%X, 0x%X", er->caid, er->ecmlen, er->ecm[3], er->ecm[4]);
1141 if (er->caid == 0x1702) {
1142 er->caid = 0x1833;
1143 } else {
1144 check_lb_auto_betatunnel_mode(er);
1145 }
1146 cs_debug_mask(D_TRACE, "Quickfix remap beta->nagra: 0x%X, 0x%X, 0x%X, 0x%X", er->caid, er->ecmlen, er->ecm[3], er->ecm[4]);
1147 }
1148
1149 //nagra ecm with betacrypt header 1801, 1833, 1834, 1835
1150 if ((er->caid == 0x1801 || er->caid == 0x1833 || er->caid == 0x1834 || er->caid == 0x1835) && (er->ecmlen == 0x93 || er->ecmlen == 0x54) && er->ecm[13] == 0x07 && (er->ecm[14] == 0x84 || er->ecm[14] == 0x45))
1151 {
1152 //cs_debug_mask(D_TRACE, "Quickfix remap nagra->beta: 0x%X, 0x%X, 0x%X, 0x%X", er->caid, er->ecmlen, er->ecm[13], er->ecm[44]);
1153 if (er->caid == 0x1833) {
1154 er->caid = 0x1702;
1155 } else {
1156 er->caid = 0x1722;
1157 }
1158 cs_debug_mask(D_TRACE, "Quickfix remap nagra->beta: 0x%X, 0x%X, 0x%X, 0x%X", er->caid, er->ecmlen, er->ecm[13], er->ecm[44]);
1159 }
1160
1161 //Ariva quickfix (invalid nagra provider)
1162 if (((er->caid & 0xFF00) == 0x1800) && er->prid > 0x00FFFF)
1163 er->prid = 0;
1164
1165 //Check for invalid provider, extract provider out of ecm:
1166 uint32_t prid = chk_provid(er->ecm, er->caid);
1167 if (!er->prid) {
1168 er->prid = prid;
1169 } else {
1170 if (prid && prid != er->prid) {
1171 cs_debug_mask(D_TRACE, "provider fixed: %04X:%06X to %04X:%06X",er->caid, er->prid, er->caid, prid);
1172 er->prid = prid;
1173 }
1174 }
1175
1176 // Set providerid for newcamd clients if none is given
1177 if (!er->prid && client->ncd_server) {
1178 int32_t pi = client->port_idx;
1179 if (pi >= 0 && cfg.ncd_ptab.nports && cfg.ncd_ptab.nports >= pi && cfg.ncd_ptab.ports[pi].ncd)
1180 er->prid = cfg.ncd_ptab.ports[pi].ncd->ncd_ftab.filts[0].prids[0];
1181 }
1182
1183 // CAID not supported or found
1184 if (!er->caid) {
1185 er->rc = E_INVALID;
1186 er->rcEx = E2_CAID;
1187 snprintf( er->msglog, MSGLOGSIZE, "CAID not supported or found" );
1188 }
1189
1190 // user expired
1191 if (client->expirationdate && client->expirationdate < client->lastecm)
1192 er->rc = E_EXPDATE;
1193
1194 // out of timeframe
1195 if (client->allowedtimeframe[0] && client->allowedtimeframe[1]) {
1196 struct tm acttm;
1197 localtime_r(&now, &acttm);
1198 int32_t curtime = (acttm.tm_hour * 60) + acttm.tm_min;
1199 int32_t mintime = client->allowedtimeframe[0];
1200 int32_t maxtime = client->allowedtimeframe[1];
1201 if (!((mintime <= maxtime && curtime > mintime && curtime < maxtime) || (mintime > maxtime && (curtime > mintime || curtime < maxtime)))) {
1202 er->rc = E_EXPDATE;
1203 }
1204 cs_debug_mask(D_TRACE, "Check Timeframe - result: %d, start: %d, current: %d, end: %d\n",er->rc, mintime, curtime, maxtime);
1205 }
1206
1207 // user disabled
1208 if (client->disabled != 0) {
1209 if (client->failban & BAN_DISABLED) {
1210 cs_add_violation(client, client->account->usr);
1211 cs_disconnect_client(client);
1212 }
1213 er->rc = E_DISABLED;
1214 }
1215
1216 if (!chk_global_whitelist(er, &line)) {
1217 debug_ecm(D_TRACE, "whitelist filtered: %s (%s) line %d", username(client), buf, line);
1218 er->rc = E_INVALID;
1219 }
1220
1221 // rc<100 -> ecm error
1222 if (er->rc >= E_UNHANDLED) {
1223 m = er->caid;
1224 i = er->srvid;
1225
1226 if (i != client->last_srvid || !client->lastswitch) {
1227 if (cfg.usrfileflag)
1228 cs_statistics(client);
1229 client->lastswitch = now;
1230 }
1231
1232 // user sleeping
1233 if (client->tosleep && (now - client->lastswitch > client->tosleep)) {
1234 if (client->failban & BAN_SLEEPING) {
1235 cs_add_violation(client, client->account->usr);
1236 cs_disconnect_client(client);
1237 }
1238 if (client->c35_sleepsend != 0) {
1239 er->rc = E_STOPPED; // send stop command CMD08 {00 xx}
1240 } else {
1241 er->rc = E_SLEEPING;
1242 }
1243 }
1244
1245 client->last_srvid = i;
1246 client->last_caid = m;
1247
1248 int32_t ecm_len = (((er->ecm[1] & 0x0F) << 8) | er->ecm[2]) + 3;
1249
1250 for (j = 0; (j < 6) && (er->rc >= E_UNHANDLED); j++) {
1251 switch(j) {
1252 case 0:
1253 // fake (uniq)
1254 if (client->dup)
1255 er->rc = E_FAKE;
1256 break;
1257 case 1:
1258 // invalid (caid)
1259 if (!chk_bcaid(er, &client->ctab)) {
1260 er->rc = E_INVALID;
1261 er->rcEx = E2_CAID;
1262 snprintf( er->msglog, MSGLOGSIZE, "invalid caid 0x%04X", er->caid );
1263 }
1264 break;
1265 case 2:
1266 // invalid (srvid)
1267 if (!chk_srvid(client, er)) {
1268 er->rc = E_INVALID;
1269 snprintf( er->msglog, MSGLOGSIZE, "invalid SID" );
1270 }
1271 break;
1272 case 3:
1273 // invalid (ufilters)
1274 if (!chk_ufilters(er))
1275 er->rc = E_INVALID;
1276 break;
1277 case 4:
1278 // invalid (sfilter)
1279 if (!chk_sfilter(er, &get_module(client)->ptab))
1280 er->rc = E_INVALID;
1281 break;
1282 case 5:
1283 // corrupt
1284 if ((i = er->ecmlen - ecm_len)) {
1285 if (i > 0) {
1286 cs_debug_mask(D_TRACE, "warning: ecm size adjusted from %d to %d", er->ecmlen, ecm_len);
1287 er->ecmlen = ecm_len;
1288 }
1289 else
1290 er->rc = E_CORRUPT;
1291 }
1292 break;
1293 }
1294 }
1295 }
1296
1297 //Schlocke: above checks could change er->rc so
1298 if (er->rc >= E_UNHANDLED) {
1299 /*BetaCrypt tunneling
1300 *moved behind the check routines,
1301 *because newcamd ECM will fail
1302 *if ECM is converted before
1303 */
1304 if (client->ttab.n)
1305 cs_betatunnel(er);
1306
1307 // ignore ecm ...
1308 int32_t offset = 3;
1309 // ... and betacrypt header for cache md5 calculation
1310 if ((er->caid >> 8) == 0x17)
1311 offset = 13;
1312 unsigned char md5tmp[MD5_DIGEST_LENGTH];
1313 // store ECM in cache
1314 memcpy(er->ecmd5, MD5(er->ecm + offset, er->ecmlen - offset, md5tmp), CS_ECMSTORESIZE);
1315 cacheex_update_hash(er);
1316 ac_chk(client, er, 0);
1317 }
1318
1319 struct s_ecm_answer *ea, *prv = NULL;
1320 if (er->rc >= E_99 && !cacheex_is_match_alias(client, er)) {
1321 er->reader_avail = 0;
1322 struct s_reader *rdr;
1323
1324 cs_readlock(&readerlist_lock);
1325 cs_readlock(&clientlist_lock);
1326
1327 for (rdr = first_active_reader; rdr; rdr = rdr->next) {
1328 int8_t match = matching_reader(er, rdr, 1); // include ratelimitercheck
1329#ifdef WITH_LB
1330 //if this reader does not match, check betatunnel for it
1331 if (!match && cfg.lb_auto_betatunnel) {
1332 uint16_t caid = get_betatunnel_caid_to(er->caid);
1333 if (caid) {
1334 uint16_t save_caid = er->caid;
1335 er->caid = caid;
1336 match = matching_reader(er, rdr, 1); //matching (including ratelimitercheck)
1337 er->caid = save_caid;
1338 }
1339 }
1340#endif
1341 if (match) {
1342 if (!cs_malloc(&ea, sizeof(struct s_ecm_answer)))
1343 goto OUT;
1344 ea->reader = rdr;
1345 if (prv)
1346 prv->next = ea;
1347 else
1348 er->matching_rdr = ea;
1349 prv = ea;
1350
1351 ea->status = READER_ACTIVE;
1352 if (!is_network_reader(rdr))
1353 ea->status |= READER_LOCAL;
1354 else if (cacheex_reader(rdr))
1355 ea->status |= READER_CACHEEX;
1356 if (rdr->fallback)
1357 ea->status |= READER_FALLBACK;
1358#ifdef WITH_LB
1359 if (cfg.lb_mode || !rdr->fallback)
1360#else
1361 if (!rdr->fallback)
1362#endif
1363 er->reader_avail++;
1364 }
1365 }
1366
1367OUT:
1368 cs_readunlock(&clientlist_lock);
1369 cs_readunlock(&readerlist_lock);
1370
1371 stat_get_best_reader(er);
1372
1373 int32_t fallback_reader_count = 0;
1374 er->reader_count = 0;
1375 for (ea = er->matching_rdr; ea; ea = ea->next) {
1376 if (ea->status & READER_ACTIVE) {
1377 if (!(ea->status & READER_FALLBACK))
1378 er->reader_count++;
1379 else
1380 fallback_reader_count++;
1381 }
1382 }
1383
1384 if ((er->reader_count + fallback_reader_count) == 0) { //no reader -> not found
1385 er->rc = E_NOTFOUND;
1386 if (!er->rcEx)
1387 er->rcEx = E2_GROUP;
1388 snprintf(er->msglog, MSGLOGSIZE, "no matching reader");
1389 }
1390 }
1391
1392 //we have to go through matching_reader() to check services!
1393 struct ecm_request_t *ecm;
1394 if (er->rc == E_UNHANDLED) {
1395 ecm = check_cwcache(er, client);
1396 if (ecm) {
1397 if (ecm->rc < E_99) {
1398 memcpy(er->cw, ecm->cw, 16);
1399 er->selected_reader = ecm->selected_reader;
1400 er->rc = (ecm->rc == E_FOUND) ? E_CACHE1 : ecm->rc;
1401 } else { //E_UNHANDLED
1402 er->ecmcacheptr = ecm;
1403 er->rc = E_99;
1404#ifdef CS_CACHEEX
1405 //to support cache without ecms we store the first client ecm request here
1406 //when we got a cache ecm from cacheex
1407 if (!ecm->ecmlen && er->ecmlen && !ecm->matching_rdr) {
1408 ecm->matching_rdr = er->matching_rdr;
1409 er->matching_rdr = NULL;
1410 ecm->ecmlen = er->ecmlen;
1411 ecm->client = er->client;
1412 er->client = NULL;
1413 memcpy(ecm->ecm, er->ecm, sizeof(ecm->ecm));
1414 memcpy(ecm->ecmd5, er->ecmd5, sizeof(ecm->ecmd5));
1415 }
1416#endif
1417 }
1418#ifdef CS_CACHEEX
1419 er->cacheex_src = ecm->cacheex_src;
1420#endif
1421 } else
1422 er->rc = E_UNHANDLED;
1423 }
1424
1425#ifdef CS_CACHEEX
1426 int8_t cacheex = client->account ? client->account->cacheex.mode : 0;
1427 uint32_t cacheex_wait_time = get_cacheex_wait_time(er,client);
1428 uint8_t cwcycle_act = cwcycle_check_act(er->caid);
1429 if (!cwcycle_act)
1430 cs_debug_mask(D_CACHEEX | D_CSPCWC, "[GET_CW] wait_time %d caid %04X prov %06X srvid %04X rc %d cacheex %d", cacheex_wait_time, er->caid, er->prid, er->srvid, er->rc, cacheex);
1431 if ((cacheex_wait_time && !cwcycle_act) && er->rc == E_UNHANDLED) { //not found in cache, so wait!
1432 add_ms_to_timeb(&er->cacheex_wait, cacheex_wait_time);
1433 er->cacheex_wait_time = cacheex_wait_time;
1434 int32_t max_wait = cacheex_wait_time; // uint32_t can't value <> n/50
1435 while (max_wait > 0 && !client->kill) {
1436 cs_sleepms(50);
1437 max_wait -= 50;
1438 ecm = check_cwcache(er, client);
1439 if (ecm) {
1440 if (ecm->rc < E_99) { //Found cache!
1441 memcpy(er->cw, ecm->cw, 16);
1442 er->selected_reader = ecm->selected_reader;
1443 er->rc = (ecm->rc == E_FOUND)?E_CACHE1:ecm->rc;
1444 } else { //Found request!
1445 er->ecmcacheptr = ecm;
1446 er->rc = E_99;
1447 }
1448 er->cacheex_src = ecm->cacheex_src;
1449 break;
1450 }
1451 }
1452 if (max_wait <= 0 ) {
1453 cs_debug_mask(D_CACHEEX|D_CSPCWC, "[GET_CW] wait_time over");
1454 snprintf(er->msglog, MSGLOGSIZE, "wait_time over");
1455 }
1456 }
1457#endif
1458
1459 if (er->rc >= E_99) {
1460#ifdef CS_CACHEEX
1461 if (cacheex != 1 || er->rc == E_99) { //Cacheex should not add to the ecmcache:
1462#endif
1463 if (er->rc == E_UNHANDLED) {
1464 ecm = check_cwcache(er, client);
1465 if (ecm && ecm != er) {
1466 er->rc = E_99;
1467 er->ecmcacheptr = ecm; //Linking ecm to first request
1468#ifdef CS_CACHEEX
1469 er->cacheex_src = ecm->cacheex_src;
1470#endif
1471 }
1472 }
1473 cs_writelock(&ecmcache_lock);
1474 er->next = ecmcwcache;
1475 ecmcwcache = er;
1476 ecmcwcache_size++;
1477 cs_writeunlock(&ecmcache_lock);
1478#ifdef CS_CACHEEX
1479 }
1480#endif
1481 }
1482
1483 if (er->rc < E_99) {
1484#ifdef CS_CACHEEX
1485 if (cfg.delay && cacheex != 1) //No delay on cacheexchange mode 1 client!
1486 cs_sleepms(cfg.delay);
1487
1488 if (cacheex == 1 && er->rc < E_NOTFOUND) {
1489 cacheex_add_stats(client, er->caid, er->srvid, er->prid, 0);
1490 client->cwcacheexpush++;
1491 if (client->account)
1492 client->account->cwcacheexpush++;
1493 first_client->cwcacheexpush++;
1494 }
1495#else
1496 if (cfg.delay)
1497 cs_sleepms(cfg.delay);
1498#endif
1499 send_dcw(client, er);
1500 free_ecm(er);
1501 return; //ECM found/not found/error/invalid
1502 }
1503
1504 if (er->rc == E_99) {
1505 er->stage = 4;
1506 if (timecheck_client) {
1507 pthread_mutex_lock(&timecheck_client->thread_lock);
1508 if (timecheck_client->thread_active == 2)
1509 pthread_kill(timecheck_client->thread, OSCAM_SIGNAL_WAKEUP);
1510 pthread_mutex_unlock(&timecheck_client->thread_lock);
1511 }
1512 return; //ECM already requested / found in ECM cache
1513 }
1514
1515#ifdef CS_CACHEEX
1516 //er->rc == E_UNHANDLED
1517 //Cache Exchange never request cws from readers!
1518 if (cacheex == 1) {
1519 er->rc = E_NOTFOUND;
1520 er->rcEx = E2_OFFLINE;
1521 send_dcw(client, er);
1522 free_ecm(er);
1523 return;
1524 }
1525#endif
1526
1527 lb_mark_last_reader(er);
1528
1529 er->rcEx = 0;
1530#if defined CS_CACHEEX && defined CW_CYCLE_CHECK
1531 if (cwcycle_act)
1532 cs_debug_mask(D_CACHEEX | D_CSPCWC, "[GET_CW] wait_time (cwc) %d caid %04X prov %06X srvid %04X rc %d cacheex %d %ld", cacheex_wait_time, er->caid, er->prid, er->srvid, er->rc, cacheex, er->tps.time);
1533 if ((cacheex_wait_time && cwcycle_act) && er->rc == E_UNHANDLED) { //wait for cache answer!
1534 add_ms_to_timeb(&er->cacheex_wait, cacheex_wait_time);
1535 er->cacheex_wait_time = cacheex_wait_time;
1536 } else
1537#endif
1538 request_cw_from_readers(er);
1539
1540#ifdef WITH_DEBUG
1541 if (D_CLIENTECM & cs_dblevel) {
1542 char buf[ECM_FMT_LEN];
1543 format_ecm(er, buf, ECM_FMT_LEN);
1544 cs_ddump_mask(D_CLIENTECM, er->ecm, er->ecmlen, "Client %s ECM dump %s", username(client), buf);
1545 }
1546#endif
1547
1548 if (timecheck_client) {
1549 pthread_mutex_lock(&timecheck_client->thread_lock);
1550 if (timecheck_client->thread_active == 2)
1551 pthread_kill(timecheck_client->thread, OSCAM_SIGNAL_WAKEUP);
1552 pthread_mutex_unlock(&timecheck_client->thread_lock);
1553 }
1554}
1555
1556int32_t ecmfmt(uint16_t caid, uint32_t prid, uint16_t chid, uint16_t pid, uint16_t srvid, uint16_t l, char *ecmd5hex, char *csphash, char *cw, char *result, size_t size)
1557{
1558 if (!cfg.ecmfmt)
1559 return snprintf(result, size, "%04X&%06X/%04X/%04X/%02X:%s", caid, prid, chid, srvid, l, ecmd5hex);
1560
1561 uint32_t s = 0, zero = 0, flen = 0, value = 0;
1562 char *c = cfg.ecmfmt, fmt[5] = "%04X";
1563 while (*c) {
1564 switch(*c) {
1565 case '0': zero = 1; value = 0; break;
1566 case 'c': flen = 4; value = caid; break;
1567 case 'p': flen = 6; value = prid; break;
1568 case 'i': flen = 4; value = chid; break;
1569 case 'd': flen = 4; value = pid; break;
1570 case 's': flen = 4; value = srvid; break;
1571 case 'l': flen = 2; value = l; break;
1572 case 'h': flen = CS_ECMSTORESIZE; break;
1573 case 'e': flen = 5; break;
1574 case 'w': flen = 17; break;
1575 case '\\':
1576 c++;
1577 flen = 0;
1578 value = *c;
1579 break;
1580 default: flen = 0; value = *c; break;
1581 }
1582 if (value)
1583 zero = 0;
1584
1585 if (!zero) {
1586 //fmt[0] = '%';
1587 if (flen) { //Build %04X / %06X / %02X
1588 fmt[1] = '0';
1589 fmt[2] = flen+'0';
1590 fmt[3] = 'X';
1591 fmt[4] = 0;
1592 }
1593 else {
1594 fmt[1] = 'c';
1595 fmt[2] = 0;
1596 }
1597 if (flen == CS_ECMSTORESIZE) s += snprintf(result+s, size-s ,"%s", ecmd5hex);
1598 else if (flen == 5) s += snprintf(result+s, size-s ,"%s", csphash);
1599 else if (flen == 17) s += snprintf(result+s, size-s ,"%s", cw);
1600 else s += snprintf(result+s, size-s, fmt, value);
1601 }
1602 c++;
1603 }
1604 return s;
1605}
1606
1607int32_t format_ecm(ECM_REQUEST *ecm, char *result, size_t size)
1608{
1609 char ecmd5hex[17 * 3];
1610 char csphash[5 * 3] = { 0 };
1611 char cwhex[17 * 3];
1612 cs_hexdump(0, ecm->ecmd5, 16, ecmd5hex, sizeof(ecmd5hex));
1613#ifdef CS_CACHEEX
1614 cs_hexdump(0, (void *)&ecm->csp_hash, 4, csphash, sizeof(csphash));
1615#endif
1616 cs_hexdump(0, ecm->cw, 16, cwhex, sizeof(cwhex));
1617 return ecmfmt(ecm->caid, ecm->prid, ecm->chid, ecm->pid, ecm->srvid, ecm->ecmlen, ecmd5hex, csphash, cwhex, result, size);
1618}
Note: See TracBrowser for help on using the repository browser.